use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::Duration;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectionConfig {
pub connection_string: String,
pub max_connections: Option<u32>,
pub connection_timeout: Option<Duration>,
pub query_timeout: Option<Duration>,
pub ssl_mode: Option<String>,
pub credentials: Option<Credentials>,
}
impl ConnectionConfig {
pub fn new(connection_string: String) -> Self {
Self {
connection_string,
max_connections: None,
connection_timeout: None,
query_timeout: None,
ssl_mode: None,
credentials: None,
}
}
pub fn with_max_connections(mut self, max_connections: u32) -> Self {
self.max_connections = Some(max_connections);
self
}
pub fn with_connection_timeout(mut self, timeout: Duration) -> Self {
self.connection_timeout = Some(timeout);
self
}
pub fn with_query_timeout(mut self, timeout: Duration) -> Self {
self.query_timeout = Some(timeout);
self
}
pub fn with_ssl_mode(mut self, ssl_mode: String) -> Self {
self.ssl_mode = Some(ssl_mode);
self
}
pub fn with_credentials(mut self, credentials: Credentials) -> Self {
self.credentials = Some(credentials);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Credentials {
pub username: String,
pub password: String,
pub database: Option<String>,
pub additional_params: HashMap<String, String>,
}
impl Credentials {
pub fn new(username: String, password: String) -> Self {
Self {
username,
password,
database: None,
additional_params: HashMap::new(),
}
}
pub fn with_database(mut self, database: String) -> Self {
self.database = Some(database);
self
}
pub fn add_param(&mut self, key: String, value: String) {
self.additional_params.insert(key, value);
}
pub fn get_param(&self, key: &str) -> Option<&String> {
self.additional_params.get(key)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Schema {
pub tables: Vec<TableInfo>,
pub views: Vec<ViewInfo>,
pub version: Option<String>,
}
impl Schema {
pub fn new() -> Self {
Self {
tables: Vec::new(),
views: Vec::new(),
version: None,
}
}
pub fn add_table(&mut self, table: TableInfo) {
self.tables.push(table);
}
pub fn add_view(&mut self, view: ViewInfo) {
self.views.push(view);
}
pub fn set_version(&mut self, version: String) {
self.version = Some(version);
}
pub fn find_table(&self, name: &str) -> Option<&TableInfo> {
self.tables.iter().find(|t| t.name == name)
}
pub fn find_view(&self, name: &str) -> Option<&ViewInfo> {
self.views.iter().find(|v| v.name == name)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TableInfo {
pub name: String,
pub schema: Option<String>,
pub columns: Vec<ColumnInfo>,
pub primary_keys: Vec<String>,
pub indexes: Vec<IndexInfo>,
}
impl TableInfo {
pub fn new(name: String) -> Self {
Self {
name,
schema: None,
columns: Vec::new(),
primary_keys: Vec::new(),
indexes: Vec::new(),
}
}
pub fn with_schema(mut self, schema: String) -> Self {
self.schema = Some(schema);
self
}
pub fn add_column(&mut self, column: ColumnInfo) {
self.columns.push(column);
}
pub fn add_primary_key(&mut self, column_name: String) {
if !self.primary_keys.contains(&column_name) {
self.primary_keys.push(column_name);
}
}
pub fn add_index(&mut self, index: IndexInfo) {
self.indexes.push(index);
}
pub fn find_column(&self, name: &str) -> Option<&ColumnInfo> {
self.columns.iter().find(|c| c.name == name)
}
pub fn is_primary_key(&self, column_name: &str) -> bool {
self.primary_keys.contains(&column_name.to_string())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ColumnInfo {
pub name: String,
pub data_type: String,
pub is_nullable: bool,
pub default_value: Option<String>,
pub max_length: Option<i32>,
}
impl ColumnInfo {
pub fn new(name: String, data_type: String) -> Self {
Self {
name,
data_type,
is_nullable: true,
default_value: None,
max_length: None,
}
}
pub fn with_nullable(mut self, nullable: bool) -> Self {
self.is_nullable = nullable;
self
}
pub fn with_default_value(mut self, default_value: String) -> Self {
self.default_value = Some(default_value);
self
}
pub fn with_max_length(mut self, max_length: i32) -> Self {
self.max_length = Some(max_length);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ViewInfo {
pub name: String,
pub schema: Option<String>,
pub definition: String,
}
impl ViewInfo {
pub fn new(name: String, definition: String) -> Self {
Self {
name,
schema: None,
definition,
}
}
pub fn with_schema(mut self, schema: String) -> Self {
self.schema = Some(schema);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IndexInfo {
pub name: String,
pub columns: Vec<String>,
pub is_unique: bool,
pub is_primary: bool,
pub is_clustered: bool,
}
impl IndexInfo {
pub fn new(name: String, columns: Vec<String>) -> Self {
Self {
name,
columns,
is_unique: false,
is_primary: false,
is_clustered: false,
}
}
pub fn with_unique(mut self, unique: bool) -> Self {
self.is_unique = unique;
self
}
pub fn with_primary(mut self, primary: bool) -> Self {
self.is_primary = primary;
self
}
pub fn with_clustered(mut self, clustered: bool) -> Self {
self.is_clustered = clustered;
self
}
pub fn add_column(&mut self, column: String) {
if !self.columns.contains(&column) {
self.columns.push(column);
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QueryResult {
pub columns: Vec<String>,
pub data_types: Vec<String>,
pub row_count: usize,
pub execution_time: Duration,
}
impl QueryResult {
pub fn new(
columns: Vec<String>,
data_types: Vec<String>,
row_count: usize,
execution_time: Duration,
) -> Self {
Self {
columns,
data_types,
row_count,
execution_time,
}
}
pub fn column_count(&self) -> usize {
self.columns.len()
}
pub fn is_empty(&self) -> bool {
self.row_count == 0
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataSourceStats {
pub total_connections: u32,
pub active_connections: u32,
pub total_queries: u64,
pub failed_queries: u64,
pub average_query_time: Duration,
pub last_activity: Option<std::time::SystemTime>,
}
impl DataSourceStats {
pub fn new() -> Self {
Self {
total_connections: 0,
active_connections: 0,
total_queries: 0,
failed_queries: 0,
average_query_time: Duration::from_millis(0),
last_activity: None,
}
}
pub fn success_rate(&self) -> f64 {
if self.total_queries == 0 {
1.0
} else {
(self.total_queries - self.failed_queries) as f64 / self.total_queries as f64
}
}
pub fn failure_rate(&self) -> f64 {
1.0 - self.success_rate()
}
pub fn update_activity(&mut self) {
self.last_activity = Some(std::time::SystemTime::now());
}
}