use crate::metadata::{NavigationKind, NavigationMeta};
use crate::relations::DeleteBehavior;
use std::any::{Any, TypeId};
pub struct DrainedChild {
pub parent_type_id: TypeId,
pub parent_entry_idx: usize,
pub child: Box<dyn Any + Send + Sync>,
pub child_type_id: TypeId,
pub fk_target_type_id: TypeId,
pub through_table: Option<String>,
pub through_parent_fk_col: Option<String>,
pub through_child_fk_col: Option<String>,
}
pub struct FixupLink {
pub parent_type_id: TypeId,
pub parent_entry_idx: usize,
pub child_type_id: TypeId,
pub child_entry_indices: Vec<usize>,
pub fk_target_type_id: TypeId,
pub through_table: Option<String>,
pub through_parent_fk_col: Option<String>,
pub through_child_fk_col: Option<String>,
}
pub fn m2m_insert_sql(table: &str, parent_col: &str, child_col: &str, row_count: usize) -> String {
let placeholders: Vec<String> = (0..row_count).map(|_| "(?, ?)".to_string()).collect();
format!(
"INSERT INTO {} ({}, {}) VALUES {}",
table,
parent_col,
child_col,
placeholders.join(", ")
)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CascadeDeleteAction {
Delete,
SetNull,
}
pub struct CascadeDeleteDirective {
pub table: String,
pub fk_column: String,
pub principal_pk: i64,
pub action: CascadeDeleteAction,
}
pub fn resolve_delete_behavior(nav: &NavigationMeta) -> DeleteBehavior {
if let Some(b) = nav.delete_behavior {
return b;
}
if nav.kind == NavigationKind::ManyToMany {
return DeleteBehavior::Cascade;
}
if let Some(meta_fn) = nav.related_entity_meta {
let child_meta = meta_fn();
if let Some(fk_prop) = child_meta.properties.iter().find(|p| p.is_foreign_key) {
let is_nullable = fk_prop.type_name.contains("Option");
return if is_nullable {
DeleteBehavior::Restrict
} else {
DeleteBehavior::Cascade
};
}
}
DeleteBehavior::Cascade
}