use crate::error::{QuickDbError, QuickDbResult};
use crate::model::FieldDefinition;
use crate::pool::DatabaseConnection;
use crate::types::*;
use async_trait::async_trait;
use std::collections::HashMap;
mod cached;
#[cfg(feature = "mongodb-support")]
mod mongodb;
#[cfg(feature = "mysql-support")]
mod mysql;
#[cfg(feature = "postgres-support")]
mod postgres;
mod postgres_utils;
#[cfg(feature = "sqlite-support")]
mod sqlite;
mod utils;
pub use cached::CachedDatabaseAdapter;
#[cfg(feature = "mongodb-support")]
pub use mongodb::MongoAdapter;
#[cfg(feature = "mysql-support")]
pub use mysql::MysqlAdapter;
#[cfg(feature = "postgres-support")]
pub use postgres::PostgresAdapter;
pub use postgres_utils::{build_json_query_condition, convert_to_jsonb_value};
#[cfg(feature = "sqlite-support")]
pub use sqlite::SqliteAdapter;
pub use utils::get_field_type;
#[async_trait]
pub trait DatabaseAdapter: Send + Sync {
async fn create(
&self,
connection: &DatabaseConnection,
table: &str,
data: &HashMap<String, DataValue>,
id_strategy: &IdStrategy,
alias: &str,
) -> QuickDbResult<DataValue>;
async fn find_by_id(
&self,
connection: &DatabaseConnection,
table: &str,
id: &DataValue,
alias: &str,
) -> QuickDbResult<Option<DataValue>>;
async fn find(
&self,
connection: &DatabaseConnection,
table: &str,
conditions: &[QueryConditionWithConfig],
options: &QueryOptions,
alias: &str,
) -> QuickDbResult<Vec<DataValue>> {
self.find_with_cache_control(connection, table, conditions, options, alias, false).await
}
async fn find_with_cache_control(
&self,
connection: &DatabaseConnection,
table: &str,
conditions: &[QueryConditionWithConfig],
options: &QueryOptions,
alias: &str,
bypass_cache: bool,
) -> QuickDbResult<Vec<DataValue>>;
async fn find_with_groups(
&self,
connection: &DatabaseConnection,
table: &str,
condition_groups: &[QueryConditionGroup],
options: &QueryOptions,
alias: &str,
) -> QuickDbResult<Vec<DataValue>> {
self.find_with_groups_with_cache_control(connection, table, condition_groups, options, alias, false).await
}
async fn find_with_groups_with_cache_control(
&self,
connection: &DatabaseConnection,
table: &str,
condition_groups: &[QueryConditionGroup],
options: &QueryOptions,
alias: &str,
bypass_cache: bool,
) -> QuickDbResult<Vec<DataValue>> {
let condition_groups_with_config: Vec<QueryConditionGroupWithConfig> = condition_groups
.iter()
.map(|g| g.clone().into())
.collect();
self.find_with_groups_with_cache_control_and_config(connection, table, &condition_groups_with_config, options, alias, bypass_cache).await
}
async fn find_with_groups_with_config(
&self,
connection: &DatabaseConnection,
table: &str,
condition_groups: &[QueryConditionGroupWithConfig],
options: &QueryOptions,
alias: &str,
) -> QuickDbResult<Vec<DataValue>> {
self.find_with_groups_with_cache_control_and_config(connection, table, condition_groups, options, alias, false).await
}
async fn find_with_groups_with_cache_control_and_config(
&self,
connection: &DatabaseConnection,
table: &str,
condition_groups: &[QueryConditionGroupWithConfig],
options: &QueryOptions,
alias: &str,
bypass_cache: bool,
) -> QuickDbResult<Vec<DataValue>>;
async fn update(
&self,
connection: &DatabaseConnection,
table: &str,
conditions: &[QueryConditionWithConfig],
data: &HashMap<String, DataValue>,
alias: &str,
) -> QuickDbResult<u64>;
async fn update_with_operations(
&self,
connection: &DatabaseConnection,
table: &str,
conditions: &[QueryConditionWithConfig],
operations: &[crate::types::UpdateOperation],
alias: &str,
) -> QuickDbResult<u64>;
async fn update_by_id(
&self,
connection: &DatabaseConnection,
table: &str,
id: &DataValue,
data: &HashMap<String, DataValue>,
alias: &str,
) -> QuickDbResult<bool>;
async fn delete(
&self,
connection: &DatabaseConnection,
table: &str,
conditions: &[QueryConditionWithConfig],
alias: &str,
) -> QuickDbResult<u64>;
async fn delete_by_id(
&self,
connection: &DatabaseConnection,
table: &str,
id: &DataValue,
alias: &str,
) -> QuickDbResult<bool>;
async fn count(
&self,
connection: &DatabaseConnection,
table: &str,
conditions: &[QueryConditionWithConfig],
alias: &str,
) -> QuickDbResult<u64>;
async fn count_with_groups(
&self,
connection: &DatabaseConnection,
table: &str,
condition_groups: &[QueryConditionGroupWithConfig],
alias: &str,
) -> QuickDbResult<u64>;
async fn create_table(
&self,
connection: &DatabaseConnection,
table: &str,
fields: &HashMap<String, FieldDefinition>,
id_strategy: &IdStrategy,
alias: &str,
) -> QuickDbResult<()>;
async fn create_index(
&self,
connection: &DatabaseConnection,
table: &str,
index_name: &str,
fields: &[String],
unique: bool,
) -> QuickDbResult<()>;
async fn table_exists(
&self,
connection: &DatabaseConnection,
table: &str,
) -> QuickDbResult<bool>;
async fn drop_table(&self, connection: &DatabaseConnection, table: &str) -> QuickDbResult<()>;
async fn get_server_version(&self, connection: &DatabaseConnection) -> QuickDbResult<String>;
async fn create_stored_procedure(
&self,
connection: &DatabaseConnection,
config: &crate::stored_procedure::StoredProcedureConfig,
) -> QuickDbResult<crate::stored_procedure::StoredProcedureCreateResult>;
async fn execute_stored_procedure(
&self,
connection: &DatabaseConnection,
procedure_name: &str,
database: &str,
params: Option<std::collections::HashMap<String, crate::types::DataValue>>,
) -> QuickDbResult<crate::stored_procedure::StoredProcedureQueryResult>;
}
pub fn create_adapter(db_type: &DatabaseType) -> QuickDbResult<Box<dyn DatabaseAdapter>> {
match db_type {
#[cfg(feature = "sqlite-support")]
DatabaseType::SQLite => Ok(Box::new(SqliteAdapter::new())),
#[cfg(feature = "mysql-support")]
DatabaseType::MySQL => Ok(Box::new(MysqlAdapter::new())),
#[cfg(feature = "postgres-support")]
DatabaseType::PostgreSQL => Ok(Box::new(PostgresAdapter::new())),
#[cfg(feature = "mongodb-support")]
DatabaseType::MongoDB => Ok(Box::new(MongoAdapter::new())),
#[allow(unreachable_patterns)]
_ => Err(QuickDbError::UnsupportedDatabase {
db_type: format!("{:?} (可能需要启用相应的feature)", db_type),
}),
}
}
pub fn create_adapter_with_cache(
db_type: &DatabaseType,
cache_manager: std::sync::Arc<crate::cache::CacheManager>,
) -> QuickDbResult<Box<dyn DatabaseAdapter>> {
let base_adapter = create_adapter(db_type)?;
Ok(Box::new(CachedDatabaseAdapter::new(
base_adapter,
cache_manager,
)))
}