diff --git a/sr_download/src/db_part.rs b/sr_download/src/db_part.rs index e43ac7d..8c78cc1 100644 --- a/sr_download/src/db_part.rs +++ b/sr_download/src/db_part.rs @@ -9,7 +9,7 @@ use crate::model; use crate::model::sea_orm_active_enums::SaveType; use migration::{SaveId, FULL_DATA_VIEW, TEXT_DATA_MAX_LEN}; -pub mod definitions; +pub mod defines; pub mod search; pub mod updates; pub mod utils; diff --git a/sr_download/src/db_part/definitions.rs b/sr_download/src/db_part/defines.rs similarity index 57% rename from sr_download/src/db_part/definitions.rs rename to sr_download/src/db_part/defines.rs index a5db527..e499a86 100644 --- a/sr_download/src/db_part/definitions.rs +++ b/sr_download/src/db_part/defines.rs @@ -1,8 +1,10 @@ -use sea_orm::sea_query::{ColumnDef, ForeignKey, ForeignKeyAction, Table}; use sea_orm::{ConnectionTrait, DatabaseBackend, DatabaseConnection, Statement}; use crate::config::ConfigFile; +pub mod main_data_table; +pub mod full_data_view; + pub mod db_names { /// 主数据表 pub const MAIN_DATA_TABLE: &str = "main_data"; @@ -16,52 +18,44 @@ pub mod db_names { pub const SEA_ORM_TABLE: &str = "seaql_migrations"; } -pub async fn check_table_exists( - db: &DatabaseConnection, - table_name: &str, - schema: &str, -) -> Option { + +pub const CURRENT_DB_VERSION: i32 = 1; + +pub const TEXT_DATA_MAX_LEN: usize = 1024; +pub type SaveId = u32; + +pub async fn check_table_exists(db: &DatabaseConnection, table_name: &str, schema: &str) -> bool { let sql = format!( "SELECT EXISTS (SELECT FROM pg_tables WHERE tablename = '{}' AND schemaname = '{}');", table_name, schema ); - let exists = db + if let Ok(Some(exists)) = db .query_one(Statement::from_string(DatabaseBackend::Postgres, sql)) - .await.ok()?; - exists?.try_get("", "exists").ok() + .await + { + if let Ok(exists) = exists.try_get("", "exists") { + return exists; + } + } + false } -pub async fn check_main_data_exists( - db: &DatabaseConnection, - conf: &ConfigFile, -) -> Option { +pub async fn check_main_data_exists(db: &DatabaseConnection, conf: &ConfigFile) -> bool { check_table_exists(db, db_names::MAIN_DATA_TABLE, &conf.db.schema).await } -pub async fn check_long_data_exists( - db: &DatabaseConnection, - conf: &ConfigFile, -) -> Option { +pub async fn check_long_data_exists(db: &DatabaseConnection, conf: &ConfigFile) -> bool { check_table_exists(db, db_names::LONG_DATA_TABLE, &conf.db.schema).await } -pub async fn check_full_data_exists( - db: &DatabaseConnection, - conf: &ConfigFile, -) -> Option { +pub async fn check_full_data_exists(db: &DatabaseConnection, conf: &ConfigFile) -> bool { check_table_exists(db, db_names::FULL_DATA_TABLE, &conf.db.schema).await } -pub async fn check_db_version_exists( - db: &DatabaseConnection, - conf: &ConfigFile, -) -> Option { +pub async fn check_db_version_exists(db: &DatabaseConnection, conf: &ConfigFile) -> bool { check_table_exists(db, db_names::DB_VERSION_TABLE, &conf.db.schema).await } -pub async fn check_sea_orm_exists( - db: &DatabaseConnection, - conf: &ConfigFile, -) -> Option { +pub async fn check_sea_orm_exists(db: &DatabaseConnection, conf: &ConfigFile) -> bool { check_table_exists(db, db_names::SEA_ORM_TABLE, &conf.db.schema).await } diff --git a/sr_download/src/db_part/defines/full_data_view.rs b/sr_download/src/db_part/defines/full_data_view.rs new file mode 100644 index 0000000..5db7b8f --- /dev/null +++ b/sr_download/src/db_part/defines/full_data_view.rs @@ -0,0 +1,42 @@ +use sea_orm::DeriveIden; + +pub const FULL_DATA_SQL: &str = r" +CREATE OR REPLACE VIEW full_data as +SELECT + md.save_id, + md.save_type, + md.blake_hash, + md.xml_tested, + md.len, + CASE + WHEN md.len > 1024 THEN + ld.text + ELSE md.short_data + END AS data +FROM main_data md +LEFT JOIN long_data ld ON md.save_id = ld.save_id +"; + +#[derive(DeriveIden)] +pub enum FullData { + /// 表 (实际上是个视图) + Table, + /// 这个存档的 Id + SaveId, + /// 存档类型 + /// - ship: 船 + /// - save: 存档 + /// - unknown: 未知 (没下载呢) + /// - none: 没有存档 (这个 Id 为 空) + SaveType, + /// blake3 hash + /// len = 64 + /// 64 位的 blake3 hash + BlakeHash, + /// 存档的长度 (用来过滤太长的存档) + Len, + /// 完整的数据 + Data, + /// 数据是不是合法的 XML 数据 + XmlTested, +} diff --git a/sr_download/src/db_part/defines/main_data_table.rs b/sr_download/src/db_part/defines/main_data_table.rs new file mode 100644 index 0000000..bae9dd1 --- /dev/null +++ b/sr_download/src/db_part/defines/main_data_table.rs @@ -0,0 +1,76 @@ +use sea_orm::sea_query::{ColumnDef, Table}; +use sea_orm::{DatabaseBackend, DeriveIden, EnumIter, Iterable, Statement}; + +use super::TEXT_DATA_MAX_LEN; + +pub async fn main_table() -> Statement { + let mut table = Table::create(); + table + .table(MainData::Table) + .if_not_exists() + .col( + ColumnDef::new(MainData::SaveId) + .integer() + .not_null() + .primary_key(), + ) + .col( + ColumnDef::new(MainData::SaveType) + .enumeration(SaveTypeEnum, SaveTypeVariants::iter()) + .not_null(), + ) + // blake hash: + // ad4a4c99162bac6766fa9a658651688c6db4955922f8e5447cb14ad1c1b05825 + // len = 64 + .col(ColumnDef::new(MainData::BlakeHash).char_len(64).not_null()) + .col(ColumnDef::new(MainData::Len).big_integer().not_null()) + .col(ColumnDef::new(MainData::ShortData).string_len(TEXT_DATA_MAX_LEN as u32)) + .col(ColumnDef::new(MainData::XmlTested).boolean().null()); + DatabaseBackend::Postgres.build(&table) +} + +#[derive(DeriveIden)] +#[sea_orm(iden = "save_type")] +pub struct SaveTypeEnum; + +#[derive(DeriveIden, EnumIter)] +pub enum SaveTypeVariants { + #[sea_orm(iden = "ship")] + /// 飞船 + Ship, + #[sea_orm(iden = "save")] + /// 存档 + Save, + #[sea_orm(iden = "unknown")] + /// 未知 (预计用作下载中的占位符) + Unknown, + #[sea_orm(iden = "none")] + /// 没有存档 (这个 Id 为 空) + None, +} + +#[derive(DeriveIden)] +pub enum MainData { + /// 表 + Table, + /// 这个存档的 Id + SaveId, + /// 存档类型 + /// - ship: 船 + /// - save: 存档 + /// - unknown: 未知 (没下载呢) + /// - none: 没有存档 (这个 Id 为 空) + SaveType, + /// blake3 hash + /// len = 64 + /// 64 位的 blake3 hash + BlakeHash, + /// 存档的长度 (用来过滤太长的存档) + /// 长度 > 1024 的存档会存在隔壁表 + Len, + /// 如果长度 < 1024 + /// 那就直接存在这 + ShortData, + /// 数据是不是合法的 XML 数据 + XmlTested, +}