use charybdis_parser::schema::{IndexName, SchemaObject};
use crate::model::runner::INDEX_SUFFIX;
use crate::model::ModelType;
type FieldName = String;
type FieldType = String;
type OldFieldType = FieldType;
type NewFieldType = FieldType;
pub struct ModelData<'a> {
pub(crate) migration_object_name: &'a String,
pub(crate) migration_object_type: ModelType,
pub(crate) current_code_schema: &'a SchemaObject,
pub(crate) current_db_schema: &'a SchemaObject,
pub(crate) new_fields: Vec<(FieldName, FieldType)>,
pub(crate) removed_fields: Vec<FieldName>,
pub(crate) new_global_secondary_indexes: Vec<FieldName>,
pub(crate) new_local_secondary_indexes: Vec<FieldName>,
pub(crate) removed_global_secondary_indexes: Vec<IndexName>,
pub(crate) removed_local_secondary_indexes: Vec<IndexName>,
pub(crate) changed_field_types: Vec<(FieldName, OldFieldType, NewFieldType)>,
}
impl<'a> ModelData<'a> {
pub(crate) fn new(
migration_object_name: &'a String,
migration_object_type: ModelType,
current_code_schema: &'a SchemaObject,
current_db_schema: &'a SchemaObject,
) -> Self {
let mut data = Self {
migration_object_name,
migration_object_type,
current_code_schema,
current_db_schema,
new_fields: vec![],
removed_fields: vec![],
new_global_secondary_indexes: vec![],
new_local_secondary_indexes: vec![],
removed_global_secondary_indexes: vec![],
removed_local_secondary_indexes: vec![],
changed_field_types: vec![],
};
data.fetch_new_fields();
data.fetch_removed_fields();
data.fetch_new_global_secondary_indexes();
data.fetch_removed_global_secondary_indexes();
data.fetch_new_local_secondary_indexes();
data.fetch_removed_local_secondary_indexes();
data.fetch_changed_field_types();
data
}
pub(crate) fn construct_index_name(&self, column_name: &String) -> String {
format!("{}_{}_{}", self.migration_object_name, column_name, INDEX_SUFFIX)
}
pub(crate) fn is_first_migration(&self) -> bool {
self.current_db_schema.fields.is_empty()
}
pub(crate) fn has_new_global_secondary_indexes(&self) -> bool {
!self.new_global_secondary_indexes.is_empty()
}
pub(crate) fn has_removed_global_secondary_indexes(&self) -> bool {
!self.removed_global_secondary_indexes.is_empty()
}
pub(crate) fn has_new_local_secondary_indexes(&self) -> bool {
!self.new_local_secondary_indexes.is_empty()
}
pub(crate) fn has_removed_local_secondary_indexes(&self) -> bool {
!self.removed_local_secondary_indexes.is_empty()
}
pub(crate) fn has_new_fields(&self) -> bool {
!self.new_fields.is_empty()
}
pub(crate) fn has_removed_fields(&self) -> bool {
!self.removed_fields.is_empty()
}
pub(crate) fn has_changed_type_fields(&self) -> bool {
!self.changed_field_types.is_empty()
}
pub(crate) fn partition_key_changed(&self) -> bool {
let mut code_partition_keys = self.current_code_schema.partition_keys.clone();
let mut db_partition_keys = self.current_db_schema.partition_keys.clone();
code_partition_keys.sort();
db_partition_keys.sort();
code_partition_keys != db_partition_keys
}
pub(crate) fn clustering_key_changed(&self) -> bool {
let mut code_clustering_keys = self.current_code_schema.clustering_keys.clone();
let mut db_clustering_keys = self.current_db_schema.clustering_keys.clone();
code_clustering_keys.sort();
db_clustering_keys.sort();
code_clustering_keys != db_clustering_keys
}
fn fetch_new_fields(&mut self) {
for (field_name, field_type, _) in self.current_code_schema.fields.iter() {
if !self.current_db_schema.contains_field(field_name) {
self.new_fields.push((field_name.clone(), field_type.clone()));
}
}
}
fn fetch_removed_fields(&mut self) {
for (field_name, _, _) in self.current_db_schema.fields.iter() {
if !self.current_code_schema.contains_field(field_name) {
self.removed_fields.push(field_name.clone());
}
}
}
fn fetch_new_global_secondary_indexes(&mut self) {
let _ = &self
.current_code_schema
.global_secondary_indexes
.iter()
.for_each(|(_index_name, index_target)| {
if !self
.current_db_schema
.global_secondary_indexes
.iter()
.any(|(_, target)| target == index_target)
{
self.new_global_secondary_indexes.push(index_target.clone());
}
});
}
fn fetch_removed_global_secondary_indexes(&mut self) {
let _ = &self
.current_db_schema
.global_secondary_indexes
.iter()
.for_each(|(index_name, index_target)| {
if !self
.current_code_schema
.global_secondary_indexes
.iter()
.any(|(_index_name, target)| target == index_target)
{
self.removed_global_secondary_indexes.push(index_name.clone());
}
});
}
fn fetch_new_local_secondary_indexes(&mut self) {
let _ = &self
.current_code_schema
.local_secondary_indexes
.iter()
.for_each(|(_index_name, index_target)| {
if !self
.current_db_schema
.local_secondary_indexes
.iter()
.any(|(_, target)| target == index_target)
{
self.new_local_secondary_indexes.push(index_target.clone());
}
});
}
fn fetch_removed_local_secondary_indexes(&mut self) {
let _ = &self
.current_db_schema
.local_secondary_indexes
.iter()
.for_each(|(index_name, index_target)| {
if !self
.current_code_schema
.local_secondary_indexes
.iter()
.any(|(_index_name, target)| target == index_target)
{
self.removed_local_secondary_indexes.push(index_name.clone());
}
});
}
fn fetch_changed_field_types(&mut self) {
for (field_name, field_type, _) in self.current_code_schema.fields.iter() {
if let Some(db_field_type) = self.current_db_schema.types_by_name.get(field_name) {
let code_field_type = field_type.to_lowercase().replace(' ', "");
let db_field_type = db_field_type.to_lowercase().replace(' ', "");
if code_field_type != db_field_type {
self.changed_field_types
.push((field_name.clone(), db_field_type.clone(), code_field_type.clone()));
}
}
}
}
}