use crate::capitalizing::table_name_to_struct_name;
use crate::env_property_reader::keyspace;
use crate::query_metadata::query_columns;
use crate::runtime::query_collect_to_vec;
use std::collections::HashSet;
#[derive(scylla::FromRow)]
pub struct MaterializedViewFromDb {
pub table_name: String,
pub base_table_name: String,
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct MaterializedView {
pub struct_name: String,
pub base_table_name: String,
pub base_struct_name: String,
pub same_columns: bool,
}
pub fn query_for_materialized_view() -> String {
format!(
"select view_name as table_name, base_table_name from system_schema.views where keyspace_name = '{}'",
keyspace()
)
}
pub fn query_materialized_views() -> Vec<MaterializedViewFromDb> {
query_collect_to_vec(query_for_materialized_view(), [])
}
pub fn query_materialized_view(table_name: &str) -> Option<MaterializedView> {
let query = format!(
"{} and view_name = '{}'",
query_for_materialized_view(),
table_name
);
let mut rows: Vec<MaterializedViewFromDb> = query_collect_to_vec(query, []);
if rows.is_empty() {
return None;
}
assert_eq!(1, rows.len());
let mv = rows.remove(0);
let query_column_names = |table_name| {
query_columns(table_name)
.into_iter()
.map(|r| r.column_name)
.collect::<HashSet<_>>()
};
let columns_base = query_column_names(&mv.base_table_name);
let columns_own = query_column_names(table_name);
let base_table_name = mv.base_table_name;
let base_struct_name = table_name_to_struct_name(&base_table_name);
Some(MaterializedView {
base_table_name,
struct_name: table_name_to_struct_name(&mv.table_name),
same_columns: columns_base.eq(&columns_own),
base_struct_name,
})
}
#[cfg(test)]
mod test {
use super::*;
use crate::runtime::{query, TEST_TABLE};
#[test]
fn materialized_view() {
dotenv::dotenv().unwrap();
let test_table_mv = format!("{}_mv", TEST_TABLE);
let test_table_mv_struct_name = table_name_to_struct_name(&test_table_mv);
let drop_mv = || {
query(
format!("drop materialized view if exists {}", test_table_mv),
[],
);
};
drop_mv();
let assert = |val| {
assert_eq!(val, query_materialized_view(&test_table_mv));
drop_mv();
};
assert(None);
let add_materialized_view = |select| {
query(format!("
create materialized view {} as
select {}
from {}
where b is not null and c is not null and a is not null and d is not null
primary key ((b), c, d, a)", &test_table_mv, select, TEST_TABLE), []);
};
let mv_inf = |same_columns| MaterializedView {
base_table_name: TEST_TABLE.to_string(),
struct_name: test_table_mv_struct_name.clone(),
same_columns,
base_struct_name: "TestTable".to_string(),
};
add_materialized_view("*");
assert(Some(mv_inf(true)));
add_materialized_view("a, b, c, d");
assert(Some(mv_inf(false)));
add_materialized_view("a, b, c, d, e");
assert(Some(mv_inf(true)));
add_materialized_view("a, b, c, e, d");
assert(Some(mv_inf(true)));
}
}