use crate::comm::ExecuteContext;
use crate::errors::Result;
use crate::interceptor::shared::InterceptorBase;
use crate::interceptor::{InterceptorType, OperationType};
use akita_core::AkitaValue;
use std::collections::HashSet;
#[derive(Debug, Clone)]
pub struct TenantConfig {
pub column: String,
pub tenant_id: AkitaValue,
pub ignore_tables: HashSet<String>,
}
impl TenantConfig {
pub fn new(column: &str, tenant_id: AkitaValue) -> Self {
Self {
column: column.to_string(),
tenant_id,
ignore_tables: HashSet::new(),
}
}
pub fn ignore_table(mut self, table: &str) -> Self {
self.ignore_tables.insert(table.to_string());
self
}
}
pub struct TenantLineInterceptor {
config: TenantConfig,
}
impl TenantLineInterceptor {
pub fn new(config: TenantConfig) -> Self {
Self { config }
}
pub fn config(&self) -> &TenantConfig {
&self.config
}
pub(crate) fn should_ignore_table(&self, table: &str) -> bool {
self.config.ignore_tables.contains(table)
}
}
impl InterceptorBase for TenantLineInterceptor {
fn name(&self) -> &'static str {
"tenant_line"
}
fn interceptor_type(&self) -> InterceptorType {
InterceptorType::Tenant
}
fn order(&self) -> i32 {
15 }
fn will_ignore_table(&self, table_name: &str) -> bool {
self.should_ignore_table(table_name)
}
}
#[cfg(any(
feature = "mysql-sync",
feature = "postgres-sync",
feature = "sqlite-sync",
feature = "oracle-sync",
feature = "mssql-sync"
))]
impl crate::interceptor::blocking::AkitaInterceptor for TenantLineInterceptor {
fn before_execute(&self, ctx: &mut ExecuteContext) -> Result<()> {
let table = ctx.table_info().name.clone();
if self.should_ignore_table(&table) {
return Ok(());
}
ctx.set_metadata("tenant_column".to_string(), self.config.column.clone());
ctx.set_metadata("tenant_id".to_string(), self.config.tenant_id.to_string());
ctx.set_metadata("tenant_active".to_string(), "true".to_string());
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tenant_config() {
let config = TenantConfig::new("tenant_id", AkitaValue::Text("tenant_001".to_string()));
assert_eq!(config.column, "tenant_id");
assert_eq!(config.tenant_id, AkitaValue::Text("tenant_001".to_string()));
assert!(config.ignore_tables.is_empty());
}
#[test]
fn test_tenant_config_with_ignore() {
let config = TenantConfig::new("tenant_id", AkitaValue::Text("tenant_001".to_string()))
.ignore_table("sys_config")
.ignore_table("sys_user");
assert!(config.ignore_tables.contains("sys_config"));
assert!(config.ignore_tables.contains("sys_user"));
}
#[test]
fn test_tenant_line_interceptor() {
let config = TenantConfig::new("tenant_id", AkitaValue::Text("tenant_001".to_string()));
let interceptor = TenantLineInterceptor::new(config);
assert_eq!(interceptor.name(), "tenant_line");
assert_eq!(interceptor.interceptor_type(), InterceptorType::Tenant);
assert_eq!(interceptor.order(), 15);
}
#[test]
fn test_should_ignore_table() {
let config = TenantConfig::new("tenant_id", AkitaValue::Text("tenant_001".to_string()))
.ignore_table("sys_config");
let interceptor = TenantLineInterceptor::new(config);
assert!(interceptor.should_ignore_table("sys_config"));
assert!(!interceptor.should_ignore_table("users"));
}
}