feat: impl dao (#1)

Co-authored-by: kould <2435992353@qq.com>
This commit is contained in:
Kould 2023-12-13 12:32:01 +08:00 committed by GitHub
parent 6ad8d5799b
commit c6d0d85ab5
19 changed files with 725 additions and 1 deletions

View File

@ -9,6 +9,11 @@ edition = "2021"
actix-web = "4.3.1"
actix-rt = "2.8.0"
postgres = "0.19.7"
sea-orm = {version = "0.12.9", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"]}
serde = { version = "1", features = ["derive"] }
[[bin]]
name = "doc_gpt"
[workspace]
members = [".", "migration"]

19
migration/Cargo.toml Normal file
View File

@ -0,0 +1,19 @@
[package]
name = "migration"
version = "0.1.0"
edition = "2021"
publish = false
[lib]
name = "migration"
path = "src/lib.rs"
[dependencies]
async-std = { version = "1", features = ["attributes", "tokio1"] }
[dependencies.sea-orm-migration]
version = "0.12.0"
features = [
"runtime-tokio-rustls", # `ASYNC_RUNTIME` feature
"sqlx-postgres", # `DATABASE_DRIVER` feature
]

41
migration/README.md Normal file
View File

@ -0,0 +1,41 @@
# Running Migrator CLI
- Generate a new migration file
```sh
cargo run -- generate MIGRATION_NAME
```
- Apply all pending migrations
```sh
cargo run
```
```sh
cargo run -- up
```
- Apply first 10 pending migrations
```sh
cargo run -- up -n 10
```
- Rollback last applied migrations
```sh
cargo run -- down
```
- Rollback last 10 applied migrations
```sh
cargo run -- down -n 10
```
- Drop all tables from the database, then reapply all migrations
```sh
cargo run -- fresh
```
- Rollback all applied migrations, then reapply all migrations
```sh
cargo run -- refresh
```
- Rollback all applied migrations
```sh
cargo run -- reset
```
- Check the status of all migrations
```sh
cargo run -- status
```

12
migration/src/lib.rs Normal file
View File

@ -0,0 +1,12 @@
pub use sea_orm_migration::prelude::*;
mod m20220101_000001_create_table;
pub struct Migrator;
#[async_trait::async_trait]
impl MigratorTrait for Migrator {
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
vec![Box::new(m20220101_000001_create_table::Migration)]
}
}

View File

@ -0,0 +1,299 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(UserInfo::Table)
.if_not_exists()
.col(
ColumnDef::new(UserInfo::Uid)
.big_integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(UserInfo::Email).string().not_null())
.col(ColumnDef::new(UserInfo::Nickname).string().not_null())
.col(ColumnDef::new(UserInfo::AvatarUrl).string())
.col(ColumnDef::new(UserInfo::ColorSchema).string().default("dark"))
.col(ColumnDef::new(UserInfo::ListStyle).string().default("list"))
.col(ColumnDef::new(UserInfo::Language).string().default("chinese"))
.col(ColumnDef::new(UserInfo::CreatedAt).date().not_null())
.col(ColumnDef::new(UserInfo::UpdatedAt).date().not_null())
.col(ColumnDef::new(UserInfo::IsDeleted).boolean().default(false))
.to_owned(),
)
.await?;
manager
.create_table(
Table::create()
.table(TagInfo::Table)
.if_not_exists()
.col(
ColumnDef::new(TagInfo::Uid)
.big_integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(TagInfo::TagName).string().not_null())
.col(ColumnDef::new(TagInfo::Regx).string())
.col(ColumnDef::new(TagInfo::Color).big_integer().default(1))
.col(ColumnDef::new(TagInfo::Icon).big_integer().default(1))
.col(ColumnDef::new(TagInfo::Dir).string())
.col(ColumnDef::new(TagInfo::CreatedAt).date().not_null())
.col(ColumnDef::new(TagInfo::UpdatedAt).date().not_null())
.col(ColumnDef::new(TagInfo::IsDeleted).boolean().default(false))
.to_owned(),
)
.await?;
manager
.create_table(
Table::create()
.table(Tag2Doc::Table)
.if_not_exists()
.col(ColumnDef::new(Tag2Doc::TagId).big_integer())
.col(ColumnDef::new(Tag2Doc::Did).big_integer().comment("doc id, did in docinfo"))
.index(Index::create().col(Tag2Doc::TagId))
.to_owned(),
)
.await?;
manager
.create_table(
Table::create()
.table(Kb2Doc::Table)
.if_not_exists()
.col(ColumnDef::new(Kb2Doc::KbId).big_integer())
.col(ColumnDef::new(Kb2Doc::Did).big_integer().comment("doc id, did in docinfo"))
.index(Index::create().col(Kb2Doc::KbId))
.to_owned(),
)
.await?;
manager
.create_table(
Table::create()
.table(Dialog2Kb::Table)
.if_not_exists()
.col(ColumnDef::new(Dialog2Kb::DialogId).big_integer())
.col(ColumnDef::new(Dialog2Kb::KbId).big_integer())
.index(Index::create().col(Dialog2Kb::DialogId))
.to_owned(),
)
.await?;
manager
.create_table(
Table::create()
.table(Doc2Doc::Table)
.if_not_exists()
.col(ColumnDef::new(Doc2Doc::ParentId).big_integer().comment("doc id, did in docinfo"))
.col(ColumnDef::new(Doc2Doc::Did).big_integer().comment("doc id, did in docinfo"))
.index(Index::create().col(Doc2Doc::ParentId))
.to_owned(),
)
.await?;
manager
.create_table(
Table::create()
.table(KbInfo::Table)
.if_not_exists()
.col(ColumnDef::new(KbInfo::KbId).big_integer().auto_increment().not_null())
.col(ColumnDef::new(KbInfo::Uid).big_integer().not_null())
.col(ColumnDef::new(KbInfo::KbName).string().not_null())
.col(ColumnDef::new(KbInfo::Icon).big_integer().default(1))
.col(ColumnDef::new(KbInfo::CreatedAt).date().not_null())
.col(ColumnDef::new(KbInfo::UpdatedAt).date().not_null())
.col(ColumnDef::new(KbInfo::IsDeleted).boolean().default(false))
.index(Index::create().col(KbInfo::KbId))
.index(Index::create().col(KbInfo::Uid))
.to_owned(),
)
.await?;
manager
.create_table(
Table::create()
.table(DocInfo::Table)
.if_not_exists()
.col(ColumnDef::new(DocInfo::Did).big_integer().auto_increment().not_null())
.col(ColumnDef::new(DocInfo::Uid).big_integer().not_null())
.col(ColumnDef::new(DocInfo::DocName).string().not_null())
.col(ColumnDef::new(DocInfo::Size).big_integer().not_null())
.col(ColumnDef::new(DocInfo::Type).string().not_null()).comment("doc|folder")
.col(ColumnDef::new(DocInfo::KbProgress).float().default(0))
.col(ColumnDef::new(DocInfo::CreatedAt).date().not_null())
.col(ColumnDef::new(DocInfo::UpdatedAt).date().not_null())
.col(ColumnDef::new(DocInfo::IsDeleted).boolean().default(false))
.index(Index::create().col(DocInfo::Did))
.index(Index::create().col(DocInfo::Uid))
.to_owned(),
)
.await?;
manager
.create_table(
Table::create()
.table(DialogInfo::Table)
.if_not_exists()
.col(ColumnDef::new(DialogInfo::DialogId).big_integer().auto_increment().not_null())
.col(ColumnDef::new(DialogInfo::Uid).big_integer().not_null())
.col(ColumnDef::new(DialogInfo::DialogName).string().not_null())
.col(ColumnDef::new(DialogInfo::History).string().comment("json"))
.col(ColumnDef::new(DialogInfo::CreatedAt).date().not_null())
.col(ColumnDef::new(DialogInfo::UpdatedAt).date().not_null())
.col(ColumnDef::new(DialogInfo::IsDeleted).boolean().default(false))
.index(Index::create().col(DialogInfo::DialogId))
.index(Index::create().col(DialogInfo::Uid))
.to_owned(),
)
.await?;
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(UserInfo::Table).to_owned())
.await?;
manager
.drop_table(Table::drop().table(TagInfo::Table).to_owned())
.await?;
manager
.drop_table(Table::drop().table(Tag2Doc::Table).to_owned())
.await?;
manager
.drop_table(Table::drop().table(Kb2Doc::Table).to_owned())
.await?;
manager
.drop_table(Table::drop().table(Dialog2Kb::Table).to_owned())
.await?;
manager
.drop_table(Table::drop().table(Doc2Doc::Table).to_owned())
.await?;
manager
.drop_table(Table::drop().table(KbInfo::Table).to_owned())
.await?;
manager
.drop_table(Table::drop().table(DocInfo::Table).to_owned())
.await?;
manager
.drop_table(Table::drop().table(DialogInfo::Table).to_owned())
.await?;
Ok(())
}
}
#[derive(DeriveIden)]
enum UserInfo {
Table,
Uid,
Email,
Nickname,
AvatarUrl,
ColorSchema,
ListStyle,
Language,
CreatedAt,
UpdatedAt,
IsDeleted,
}
#[derive(DeriveIden)]
enum TagInfo {
Table,
Uid,
TagName,
Regx,
Color,
Icon,
Dir,
CreatedAt,
UpdatedAt,
IsDeleted,
}
#[derive(DeriveIden)]
enum Tag2Doc {
Table,
TagId,
Did,
}
#[derive(DeriveIden)]
enum Kb2Doc {
Table,
KbId,
Did,
}
#[derive(DeriveIden)]
enum Dialog2Kb {
Table,
DialogId,
KbId,
}
#[derive(DeriveIden)]
enum Doc2Doc {
Table,
ParentId,
Did,
}
#[derive(DeriveIden)]
enum KbInfo {
Table,
KbId,
Uid,
KbName,
Icon,
CreatedAt,
UpdatedAt,
IsDeleted,
}
#[derive(DeriveIden)]
enum DocInfo {
Table,
Did,
Uid,
DocName,
Size,
Type,
KbProgress,
CreatedAt,
UpdatedAt,
IsDeleted,
}
#[derive(DeriveIden)]
enum DialogInfo {
Table,
DialogId,
Uid,
DialogName,
History,
CreatedAt,
UpdatedAt,
IsDeleted,
}

6
migration/src/main.rs Normal file
View File

@ -0,0 +1,6 @@
use sea_orm_migration::prelude::*;
#[async_std::main]
async fn main() {
cli::run_cli(migration::Migrator).await;
}

0
src/api/mod.rs Normal file
View File

34
src/entity/dialog_2_kb.rs Normal file
View File

@ -0,0 +1,34 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)]
#[sea_orm(table_name = "dialog_2_kb")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub dialog_id: i64,
#[sea_orm(primary_key, auto_increment = false)]
pub kb_id: i64,
}
#[derive(Debug, Clone, Copy, EnumIter)]
pub enum Relation {
DialogInfo,
KbInfo,
}
impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
match self {
Self::DialogInfo => Entity::belongs_to(super::dialog_info::Entity)
.from(Column::DialogId)
.to(super::dialog_info::Column::DialogId)
.into(),
Self::KbInfo => Entity::belongs_to(super::kb_info::Entity)
.from(Column::KbId)
.to(super::kb_info::Column::KbId)
.into(),
}
}
}
impl ActiveModelBehavior for ActiveModel {}

33
src/entity/dialog_info.rs Normal file
View File

@ -0,0 +1,33 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)]
#[sea_orm(table_name = "dialog_info")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub dialog_id: i64,
#[sea_orm(primary_key, auto_increment = false)]
pub uid: i64,
pub dialog_name: String,
pub history: String,
pub created_at: DateTimeWithTimeZone,
pub updated_at: DateTimeWithTimeZone,
#[sea_orm(soft_delete_column)]
pub is_deleted: bool,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl Related<super::kb_info::Entity> for Entity {
fn to() -> RelationDef {
super::dialog_2_kb::Relation::KbInfo.def()
}
fn via() -> Option<RelationDef> {
Some(super::dialog_2_kb::Relation::DialogInfo.def().rev())
}
}
impl ActiveModelBehavior for ActiveModel {}

34
src/entity/doc_2_doc.rs Normal file
View File

@ -0,0 +1,34 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)]
#[sea_orm(table_name = "doc_2_doc")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub parent_id: i64,
#[sea_orm(primary_key, auto_increment = false)]
pub did: i64,
}
#[derive(Debug, Clone, Copy, EnumIter)]
pub enum Relation {
Parent,
Child
}
impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
match self {
Self::Parent => Entity::belongs_to(super::doc_info::Entity)
.from(Column::ParentId)
.to(super::doc_info::Column::Did)
.into(),
Self::Child => Entity::belongs_to(super::doc_info::Entity)
.from(Column::Did)
.to(super::doc_info::Column::Did)
.into(),
}
}
}
impl ActiveModelBehavior for ActiveModel {}

56
src/entity/doc_info.rs Normal file
View File

@ -0,0 +1,56 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize)]
#[sea_orm(table_name = "doc_info")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub did: i64,
#[sea_orm(primary_key, auto_increment = false)]
pub uid: i64,
pub doc_name: String,
pub size: i64,
#[sea_orm(column_name = "type")]
pub r#type: String,
pub kb_progress: f64,
pub created_at: DateTimeWithTimeZone,
pub updated_at: DateTimeWithTimeZone,
#[sea_orm(soft_delete_column)]
pub is_deleted: bool,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl Related<super::tag_info::Entity> for Entity {
fn to() -> RelationDef {
super::tag_2_doc::Relation::Tag.def()
}
fn via() -> Option<RelationDef> {
Some(super::tag_2_doc::Relation::DocInfo.def().rev())
}
}
impl Related<super::kb_info::Entity> for Entity {
fn to() -> RelationDef {
super::kb_2_doc::Relation::KbInfo.def()
}
fn via() -> Option<RelationDef> {
Some(super::kb_2_doc::Relation::DocInfo.def().rev())
}
}
impl Related<Entity> for Entity {
fn to() -> RelationDef {
super::doc_2_doc::Relation::Parent.def()
}
fn via() -> Option<RelationDef> {
Some(super::doc_2_doc::Relation::Child.def().rev())
}
}
impl ActiveModelBehavior for ActiveModel {}

34
src/entity/kb_2_doc.rs Normal file
View File

@ -0,0 +1,34 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)]
#[sea_orm(table_name = "kb_2_doc")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub kb_id: i64,
#[sea_orm(primary_key, auto_increment = false)]
pub uid: i64,
}
#[derive(Debug, Clone, Copy, EnumIter)]
pub enum Relation {
DocInfo,
KbInfo,
}
impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
match self {
Self::DocInfo => Entity::belongs_to(super::doc_info::Entity)
.from(Column::Uid)
.to(super::doc_info::Column::Uid)
.into(),
Self::KbInfo => Entity::belongs_to(super::kb_info::Entity)
.from(Column::KbId)
.to(super::kb_info::Column::KbId)
.into(),
}
}
}
impl ActiveModelBehavior for ActiveModel {}

43
src/entity/kb_info.rs Normal file
View File

@ -0,0 +1,43 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)]
#[sea_orm(table_name = "kb_info")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub kb_id: i64,
#[sea_orm(primary_key, auto_increment = false)]
pub uid: i64,
pub kn_name: String,
pub icon: i64,
pub created_at: DateTimeWithTimeZone,
pub updated_at: DateTimeWithTimeZone,
#[sea_orm(soft_delete_column)]
pub is_deleted: bool,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl Related<super::doc_info::Entity> for Entity {
fn to() -> RelationDef {
super::kb_2_doc::Relation::DocInfo.def()
}
fn via() -> Option<RelationDef> {
Some(super::kb_2_doc::Relation::KbInfo.def().rev())
}
}
impl Related<super::dialog_info::Entity> for Entity {
fn to() -> RelationDef {
super::dialog_2_kb::Relation::DialogInfo.def()
}
fn via() -> Option<RelationDef> {
Some(super::dialog_2_kb::Relation::KbInfo.def().rev())
}
}
impl ActiveModelBehavior for ActiveModel {}

9
src/entity/mod.rs Normal file
View File

@ -0,0 +1,9 @@
mod user_info;
mod tag_info;
mod tag_2_doc;
mod kb_2_doc;
mod dialog_2_kb;
mod doc_2_doc;
mod kb_info;
mod doc_info;
mod dialog_info;

34
src/entity/tag_2_doc.rs Normal file
View File

@ -0,0 +1,34 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)]
#[sea_orm(table_name = "tag_2_doc")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub tag_id: i64,
#[sea_orm(primary_key, auto_increment = false)]
pub uid: i64,
}
#[derive(Debug, Clone, Copy, EnumIter)]
pub enum Relation {
DocInfo,
Tag,
}
impl RelationTrait for Relation {
fn def(&self) -> sea_orm::RelationDef {
match self {
Self::DocInfo => Entity::belongs_to(super::doc_info::Entity)
.from(Column::Uid)
.to(super::doc_info::Column::Uid)
.into(),
Self::Tag => Entity::belongs_to(super::tag_info::Entity)
.from(Column::TagId)
.to(super::tag_info::Column::Uid)
.into(),
}
}
}
impl ActiveModelBehavior for ActiveModel {}

35
src/entity/tag_info.rs Normal file
View File

@ -0,0 +1,35 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)]
#[sea_orm(table_name = "tag_info")]
pub struct Model {
#[sea_orm(primary_key)]
#[serde(skip_deserializing)]
pub uid: i64,
pub tag_name: String,
pub regx: String,
pub color: i64,
pub icon: i64,
pub dir: String,
pub created_at: DateTimeWithTimeZone,
pub updated_at: DateTimeWithTimeZone,
#[sea_orm(soft_delete_column)]
pub is_deleted: bool,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl Related<super::doc_info::Entity> for Entity {
fn to() -> RelationDef {
super::tag_2_doc::Relation::DocInfo.def()
}
fn via() -> Option<RelationDef> {
Some(super::tag_2_doc::Relation::Tag.def().rev())
}
}
impl ActiveModelBehavior for ActiveModel {}

26
src/entity/user_info.rs Normal file
View File

@ -0,0 +1,26 @@
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Deserialize, Serialize)]
#[sea_orm(table_name = "user_info")]
pub struct Model {
#[sea_orm(primary_key)]
#[serde(skip_deserializing)]
pub uid: i64,
pub email: String,
pub nickname: String,
pub avatar_url: String,
pub color_schema: String,
pub list_style: String,
pub language: String,
pub created_at: DateTimeWithTimeZone,
pub updated_at: DateTimeWithTimeZone,
#[sea_orm(soft_delete_column)]
pub is_deleted: bool,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}

View File

@ -1,3 +1,7 @@
mod api;
mod entity;
mod service;
use actix_web::{get, web, App, HttpServer, Responder};
#[get("/")]

0
src/service/mod.rs Normal file
View File