metric_engine/engine/alter/
extract_new_columns.rs1use std::collections::{HashMap, HashSet};
16
17use api::v1::SemanticType;
18use common_query::native_histogram::is_native_histogram_value_type;
19use snafu::ensure;
20use store_api::metadata::ColumnMetadata;
21use store_api::region_request::{AlterKind, RegionAlterRequest};
22use store_api::storage::RegionId;
23
24use crate::error::{AddingFieldColumnSnafu, Result};
25
26pub fn extract_new_columns<'a>(
32 requests: &'a [(RegionId, RegionAlterRequest)],
33 physical_columns: &HashMap<String, ColumnMetadata>,
34 new_column_names: &mut HashSet<&'a str>,
35 new_columns: &mut Vec<ColumnMetadata>,
36) -> Result<()> {
37 for (_, request) in requests {
38 let AlterKind::AddColumns { columns } = &request.kind else {
39 unreachable!()
40 };
41 for col in columns {
42 let column_name = col.column_metadata.column_schema.name.as_str();
43 if !physical_columns.contains_key(column_name)
44 && !new_column_names.contains(column_name)
45 {
46 ensure!(
47 col.column_metadata.semantic_type != SemanticType::Field
48 || is_native_histogram_value_type(
49 &col.column_metadata.column_schema.data_type
50 ),
51 AddingFieldColumnSnafu {
52 name: column_name.to_string(),
53 }
54 );
55 new_column_names.insert(column_name);
56 new_columns.push(col.column_metadata.clone());
58 }
59 }
60 }
61
62 Ok(())
63}
64
65#[cfg(test)]
66mod tests {
67 use std::collections::{HashMap, HashSet};
68
69 use api::v1::SemanticType;
70 use datatypes::prelude::ConcreteDataType;
71 use datatypes::schema::ColumnSchema;
72 use store_api::metadata::ColumnMetadata;
73 use store_api::region_request::{AddColumn, AlterKind, RegionAlterRequest};
74 use store_api::storage::RegionId;
75
76 use super::*;
77 use crate::error::Error;
78
79 #[test]
80 fn test_extract_new_columns_with_field_type() {
81 let requests = vec![(
82 RegionId::new(1, 1),
83 RegionAlterRequest {
84 kind: AlterKind::AddColumns {
85 columns: vec![AddColumn {
86 column_metadata: ColumnMetadata {
87 column_schema: ColumnSchema::new(
88 "new_column".to_string(),
89 ConcreteDataType::string_datatype(),
90 false,
91 ),
92 semantic_type: SemanticType::Field,
93 column_id: 0,
94 },
95 location: None,
96 }],
97 },
98 },
99 )];
100
101 let physical_columns = HashMap::new();
102 let mut new_column_names = HashSet::new();
103 let mut new_columns = Vec::new();
104
105 let err = extract_new_columns(
106 &requests,
107 &physical_columns,
108 &mut new_column_names,
109 &mut new_columns,
110 )
111 .unwrap_err();
112
113 assert!(matches!(err, Error::AddingFieldColumn { .. }));
114 }
115}