use std::sync::atomic::{AtomicBool, Ordering};
static GLOBAL_OPERATION_LOCK: AtomicBool = AtomicBool::new(false);
pub mod adapter;
pub mod config;
pub mod error;
pub mod manager;
pub mod model;
pub mod odm;
pub mod pool;
pub mod serializer;
pub mod types;
pub mod utils;
pub mod i18n;
pub mod security;
pub mod table;
pub mod cache;
pub mod id_generator;
pub mod join_macro;
pub mod stored_procedure;
pub use error::{QuickDbError, QuickDbResult};
pub use manager::{
add_database, drop_table, get_aliases, health_check, register_model, set_default_alias,
table_exists,
};
pub use pool::DatabaseConnection;
pub use types::*;
pub use manager::{clear_all_caches, clear_cache, get_cache_manager, get_cache_stats};
pub use model::{
FieldDefinition, FieldType, IndexDefinition, Model, ModelManager, ModelMeta, ModelOperations,
array_field, boolean_field, datetime_field, datetime_with_tz_field, dict_field, float_field,
integer_field, json_field, list_field, reference_field, string_field, uuid_field,
};
pub use odm::{AsyncOdmManager, OdmOperations, get_odm_manager, get_odm_manager_mut};
pub use adapter::{DatabaseAdapter, create_adapter};
pub use config::{
AppConfig, AppConfigBuilder, DatabaseConfigBuilder, Environment, GlobalConfig,
GlobalConfigBuilder, LogLevel, LoggingConfig, LoggingConfigBuilder, PoolConfigBuilder,
mongodb_config, mysql_config, postgres_config, sqlite_config,
};
pub use model::conversion::database_aware::convert_datetime_with_tz_aware;
pub use model::conversion::datetime_conversion::convert_string_to_datetime_with_tz;
pub use serializer::{DataSerializer, OutputFormat, SerializationResult, SerializerConfig};
pub use table::{ColumnDefinition, ColumnType, IndexType, TableManager, TableSchema};
pub use cache::{CacheManager, CacheStats};
pub use id_generator::{IdGenerator, MongoAutoIncrementGenerator};
pub use stored_procedure::*;
pub(crate) use odm::{
count, create, delete, delete_by_id, find, find_by_id, find_with_groups, update, update_by_id,
};
pub(crate) use odm::{create_stored_procedure, execute_stored_procedure};
pub use odm::get_server_version;
use rat_logger::info;
#[cfg(debug_assertions)]
#[macro_export]
macro_rules! debug_log {
($($arg:tt)*) => {
rat_logger::debug!($($arg)*);
};
}
#[cfg(not(debug_assertions))]
#[macro_export]
macro_rules! debug_log {
($($arg:tt)*) => {
};
}
pub fn init() {
i18n::ErrorMessageI18n::init();
}
pub fn generate_object_id() -> String {
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};
static COUNTER: AtomicU64 = AtomicU64::new(0);
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
let counter = COUNTER.fetch_add(1, Ordering::SeqCst);
let machine_id = std::process::id() % 0xFFFFFF;
format!(
"{:08x}{:06x}{:04x}{:06x}",
timestamp,
machine_id,
(machine_id >> 8) & 0xFFFF,
counter % 0xFFFFFF
)
}
fn apply_timezone_offset_to_datetime(
utc_dt: chrono::DateTime<chrono::FixedOffset>,
timezone_offset: &str,
) -> QuickDbResult<chrono::DateTime<chrono::FixedOffset>> {
let offset_seconds = crate::utils::timezone::parse_timezone_offset_to_seconds(timezone_offset)?;
if offset_seconds < -86399 || offset_seconds > 86399 {
return Err(QuickDbError::ValidationError {
field: "timezone_offset".to_string(),
message: format!(
"时区偏移超出有效范围: {}, 允许范围: -23:59 到 +23:59",
timezone_offset
),
});
}
let utc_chrono = utc_dt.with_timezone(&chrono::Utc);
let local_dt = utc_chrono.with_timezone(&chrono::FixedOffset::east(offset_seconds));
Ok(local_dt)
}
pub fn process_data_fields_from_metadata(
mut data_map: std::collections::HashMap<String, DataValue>,
fields: &std::collections::HashMap<String, crate::model::FieldDefinition>,
) -> std::collections::HashMap<String, DataValue> {
for (field_name, field_def) in fields {
if let Some(current_value) = data_map.get::<str>(field_name) {
let converted_value = match current_value {
DataValue::String(json_str)
if json_str.starts_with('[') || json_str.starts_with('{') =>
{
match serde_json::from_str::<serde_json::Value>(json_str.as_str()) {
Ok(json_value) => {
let converted =
crate::types::data_value::json_value_to_data_value(json_value);
debug_log!(
"字段 {} JSON转换成功: {:?} -> {:?}",
field_name,
json_str,
converted
);
Some(converted)
}
Err(e) => {
debug_log!(
"字段 {} JSON解析失败,保持原字符串: {} (错误: {})",
field_name,
json_str,
e
);
None }
}
}
DataValue::Int(int_val)
if matches!(field_def.field_type, crate::model::FieldType::Boolean) =>
{
if *int_val == 0 || *int_val == 1 {
debug_log!(
"字段 {} 整数转布尔: {} -> {}",
field_name,
int_val,
*int_val == 1
);
Some(DataValue::Bool(*int_val == 1))
} else {
debug_log!(
"字段 {} 整数值超出布尔范围: {},保持原值",
field_name,
int_val
);
None
}
}
DataValue::DateTime(dt)
if matches!(
field_def.field_type,
crate::model::FieldType::DateTimeWithTz { .. }
) =>
{
if let crate::model::FieldType::DateTimeWithTz { timezone_offset } =
&field_def.field_type
{
debug_log!(
"字段 {} DateTimeWithTz时区转换: {} -> 时区 {}",
field_name,
dt,
timezone_offset
);
match apply_timezone_offset_to_datetime(*dt, timezone_offset) {
Ok(local_dt) => {
debug_log!(
"字段 {} 时区转换成功: {} -> {}",
field_name,
dt,
local_dt
);
Some(DataValue::DateTime(local_dt))
}
Err(e) => {
debug_log!(
"字段 {} 时区转换失败: {} (错误: {})",
field_name,
dt,
e
);
None }
}
} else {
None
}
}
_ => None, };
if let Some(converted) = converted_value {
data_map.insert(field_name.clone(), converted);
}
}
}
data_map
}
#[deprecated(since = "0.2.0", note = "请使用init(),日志系统由调用者自行初始化")]
pub fn init_with_log_level(_level: rat_logger::LevelFilter) {
init();
}
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const NAME: &str = env!("CARGO_PKG_NAME");
pub fn get_info() -> String {
format!("{} v{}", NAME, VERSION)
}
#[doc(hidden)]
pub(crate) fn lock_global_operations() {
GLOBAL_OPERATION_LOCK.store(true, Ordering::SeqCst);
}
#[doc(hidden)]
pub(crate) fn is_global_operations_locked() -> bool {
GLOBAL_OPERATION_LOCK.load(Ordering::SeqCst)
}
#[doc(hidden)]
pub(crate) fn can_add_database() -> bool {
!is_global_operations_locked()
}