first commit
This commit is contained in:
22
backend_rust/migration/Cargo.toml
Normal file
22
backend_rust/migration/Cargo.toml
Normal file
@@ -0,0 +1,22 @@
|
||||
[package]
|
||||
edition = "2024"
|
||||
name = "migration"
|
||||
publish = false
|
||||
version = "0.1.0"
|
||||
|
||||
[lib]
|
||||
name = "migration"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread"] }
|
||||
|
||||
[dependencies.sea-orm-migration]
|
||||
features = [
|
||||
# Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI.
|
||||
# View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime.
|
||||
# e.g.
|
||||
"runtime-tokio-rustls",
|
||||
"sqlx-postgres",
|
||||
]
|
||||
version = "~2.0.0-rc"
|
||||
47
backend_rust/migration/README.md
Normal file
47
backend_rust/migration/README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# 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
|
||||
```
|
||||
|
||||
|
||||
- Generate entity from sea-orm-cli
|
||||
```sh
|
||||
sea-orm-cli generate entity --database-url postgres://dyc:dycdyc89@192.168.150.142/notify --output-dir ./src/entity --entity-format dense
|
||||
```
|
||||
42
backend_rust/migration/src/lib.rs
Normal file
42
backend_rust/migration/src/lib.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
pub use sea_orm_migration::prelude::*;
|
||||
|
||||
mod m20220101_000001_create_user;
|
||||
mod m20220101_000002_create_enums;
|
||||
mod m20220101_000003_create_invite;
|
||||
mod m20220101_000004_create_recurrence_rule;
|
||||
mod m20220101_000005_create_todo;
|
||||
mod m20220101_000006_create_reminder_task;
|
||||
mod m20220101_000007_create_reminder_task_recipient;
|
||||
mod m20220101_000008_create_reminder_offset;
|
||||
mod m20220101_000009_create_notification;
|
||||
mod m20220101_000010_create_delivery_log;
|
||||
mod m20260128_000011_modify_todo;
|
||||
mod m20260129_000012_add_bark_params;
|
||||
mod m20260129_000013_add_notification_offset_id;
|
||||
mod m20260129_000014_convert_timestamps_to_timestamptz;
|
||||
mod m20260129_000015_add_user_invite_id;
|
||||
|
||||
pub struct Migrator;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigratorTrait for Migrator {
|
||||
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
|
||||
vec![
|
||||
Box::new(m20220101_000001_create_user::Migration),
|
||||
Box::new(m20220101_000002_create_enums::Migration),
|
||||
Box::new(m20220101_000003_create_invite::Migration),
|
||||
Box::new(m20220101_000004_create_recurrence_rule::Migration),
|
||||
Box::new(m20220101_000005_create_todo::Migration),
|
||||
Box::new(m20220101_000006_create_reminder_task::Migration),
|
||||
Box::new(m20220101_000007_create_reminder_task_recipient::Migration),
|
||||
Box::new(m20220101_000008_create_reminder_offset::Migration),
|
||||
Box::new(m20220101_000009_create_notification::Migration),
|
||||
Box::new(m20220101_000010_create_delivery_log::Migration),
|
||||
Box::new(m20260128_000011_modify_todo::Migration),
|
||||
Box::new(m20260129_000012_add_bark_params::Migration),
|
||||
Box::new(m20260129_000013_add_notification_offset_id::Migration),
|
||||
Box::new(m20260129_000014_convert_timestamps_to_timestamptz::Migration),
|
||||
Box::new(m20260129_000015_add_user_invite_id::Migration),
|
||||
]
|
||||
}
|
||||
}
|
||||
74
backend_rust/migration/src/m20220101_000001_create_user.rs
Normal file
74
backend_rust/migration/src/m20220101_000001_create_user.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
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(User::Table)
|
||||
.if_not_exists()
|
||||
.col(ColumnDef::new(User::Id).uuid().primary_key().not_null())
|
||||
.col(
|
||||
ColumnDef::new(User::Username)
|
||||
.string()
|
||||
.unique_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(User::PasswordHash).string().not_null())
|
||||
.col(ColumnDef::new(User::Avatar).string().null())
|
||||
.col(
|
||||
ColumnDef::new(User::Timezone)
|
||||
.string()
|
||||
.not_null()
|
||||
.default("Asia/Shanghai"),
|
||||
)
|
||||
.col(ColumnDef::new(User::BarkUrl).string().null())
|
||||
.col(
|
||||
ColumnDef::new(User::InappEnabled)
|
||||
.boolean()
|
||||
.not_null()
|
||||
.default(true),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(User::BarkEnabled)
|
||||
.boolean()
|
||||
.not_null()
|
||||
.default(false),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(User::CreatedAt)
|
||||
.timestamp()
|
||||
.not_null()
|
||||
.extra("DEFAULT NOW()"),
|
||||
)
|
||||
.col(ColumnDef::new(User::UpdatedAt).timestamp().not_null())
|
||||
.to_owned(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_table(Table::drop().table("User").to_owned())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum User {
|
||||
Table,
|
||||
Id,
|
||||
Username,
|
||||
PasswordHash,
|
||||
Avatar,
|
||||
Timezone,
|
||||
BarkUrl,
|
||||
InappEnabled,
|
||||
BarkEnabled,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
}
|
||||
137
backend_rust/migration/src/m20220101_000002_create_enums.rs
Normal file
137
backend_rust/migration/src/m20220101_000002_create_enums.rs
Normal file
@@ -0,0 +1,137 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
use sea_query::extension::postgres::Type;
|
||||
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
// Create RecurrenceType enum
|
||||
manager
|
||||
.create_type(
|
||||
Type::create()
|
||||
.as_enum(RecurrenceType::Type)
|
||||
.values([
|
||||
RecurrenceType::Hourly,
|
||||
RecurrenceType::Daily,
|
||||
RecurrenceType::Weekly,
|
||||
RecurrenceType::Monthly,
|
||||
RecurrenceType::Yearly,
|
||||
])
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Create TargetType enum
|
||||
manager
|
||||
.create_type(
|
||||
Type::create()
|
||||
.as_enum(TargetType::Type)
|
||||
.values([TargetType::Todo, TargetType::ReminderTask])
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Create ChannelType enum
|
||||
manager
|
||||
.create_type(
|
||||
Type::create()
|
||||
.as_enum(ChannelType::Type)
|
||||
.values([ChannelType::Inapp, ChannelType::Bark])
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Create NotificationStatus enum
|
||||
manager
|
||||
.create_type(
|
||||
Type::create()
|
||||
.as_enum(NotificationStatus::Type)
|
||||
.values([
|
||||
NotificationStatus::Pending,
|
||||
NotificationStatus::Queued,
|
||||
NotificationStatus::Sent,
|
||||
NotificationStatus::Failed,
|
||||
])
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_type(Type::drop().name(NotificationStatus::Type).to_owned())
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.drop_type(Type::drop().name(ChannelType::Type).to_owned())
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.drop_type(Type::drop().name(TargetType::Type).to_owned())
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.drop_type(Type::drop().name(RecurrenceType::Type).to_owned())
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// RecurrenceType enum
|
||||
#[derive(DeriveIden)]
|
||||
pub enum RecurrenceType {
|
||||
#[sea_orm(iden = "recurrence_type")]
|
||||
Type,
|
||||
#[sea_orm(iden = "hourly")]
|
||||
Hourly,
|
||||
#[sea_orm(iden = "daily")]
|
||||
Daily,
|
||||
#[sea_orm(iden = "weekly")]
|
||||
Weekly,
|
||||
#[sea_orm(iden = "monthly")]
|
||||
Monthly,
|
||||
#[sea_orm(iden = "yearly")]
|
||||
Yearly,
|
||||
}
|
||||
|
||||
// TargetType enum
|
||||
#[derive(DeriveIden)]
|
||||
pub enum TargetType {
|
||||
#[sea_orm(iden = "target_type")]
|
||||
Type,
|
||||
#[sea_orm(iden = "todo")]
|
||||
Todo,
|
||||
#[sea_orm(iden = "reminder_task")]
|
||||
ReminderTask,
|
||||
}
|
||||
|
||||
// ChannelType enum
|
||||
#[derive(DeriveIden)]
|
||||
pub enum ChannelType {
|
||||
#[sea_orm(iden = "channel_type")]
|
||||
Type,
|
||||
#[sea_orm(iden = "inapp")]
|
||||
Inapp,
|
||||
#[sea_orm(iden = "bark")]
|
||||
Bark,
|
||||
}
|
||||
|
||||
// NotificationStatus enum
|
||||
#[derive(DeriveIden)]
|
||||
pub enum NotificationStatus {
|
||||
#[sea_orm(iden = "notification_status")]
|
||||
Type,
|
||||
#[sea_orm(iden = "pending")]
|
||||
Pending,
|
||||
#[sea_orm(iden = "queued")]
|
||||
Queued,
|
||||
#[sea_orm(iden = "sent")]
|
||||
Sent,
|
||||
#[sea_orm(iden = "failed")]
|
||||
Failed,
|
||||
}
|
||||
102
backend_rust/migration/src/m20220101_000003_create_invite.rs
Normal file
102
backend_rust/migration/src/m20220101_000003_create_invite.rs
Normal file
@@ -0,0 +1,102 @@
|
||||
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(Invite::Table)
|
||||
.if_not_exists()
|
||||
.col(ColumnDef::new(Invite::Id).uuid().primary_key().not_null())
|
||||
.col(
|
||||
ColumnDef::new(Invite::Code)
|
||||
.string()
|
||||
.unique_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(Invite::CreatorId).uuid().not_null())
|
||||
.col(
|
||||
ColumnDef::new(Invite::MaxUses)
|
||||
.integer()
|
||||
.not_null()
|
||||
.default(5),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Invite::UsedCount)
|
||||
.integer()
|
||||
.not_null()
|
||||
.default(0),
|
||||
)
|
||||
.col(ColumnDef::new(Invite::ExpiresAt).timestamp().not_null())
|
||||
.col(ColumnDef::new(Invite::RevokedAt).timestamp().null())
|
||||
.col(
|
||||
ColumnDef::new(Invite::CreatedAt)
|
||||
.timestamp()
|
||||
.not_null()
|
||||
.extra("DEFAULT NOW()"),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_invite_creator")
|
||||
.from(Invite::Table, Invite::CreatorId)
|
||||
.to(User::Table, User::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Create indexes
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("IDX_invite_creator_id")
|
||||
.table(Invite::Table)
|
||||
.col(Invite::CreatorId)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("IDX_invite_expires_at")
|
||||
.table(Invite::Table)
|
||||
.col(Invite::ExpiresAt)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_table(Table::drop().table(Invite::Table).to_owned())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum Invite {
|
||||
Table,
|
||||
Id,
|
||||
Code,
|
||||
CreatorId,
|
||||
MaxUses,
|
||||
UsedCount,
|
||||
ExpiresAt,
|
||||
RevokedAt,
|
||||
CreatedAt,
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum User {
|
||||
Table,
|
||||
Id,
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
use crate::m20220101_000002_create_enums::RecurrenceType;
|
||||
|
||||
#[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(RecurrenceRule::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(RecurrenceRule::Id)
|
||||
.uuid()
|
||||
.primary_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(RecurrenceRule::Type)
|
||||
.custom(RecurrenceType::Type)
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(RecurrenceRule::Interval)
|
||||
.integer()
|
||||
.not_null()
|
||||
.default(1),
|
||||
)
|
||||
.col(ColumnDef::new(RecurrenceRule::ByWeekday).integer().null())
|
||||
.col(ColumnDef::new(RecurrenceRule::ByMonthday).integer().null())
|
||||
.col(
|
||||
ColumnDef::new(RecurrenceRule::Timezone)
|
||||
.string()
|
||||
.not_null()
|
||||
.default("Asia/Shanghai"),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(RecurrenceRule::CreatedAt)
|
||||
.timestamp()
|
||||
.not_null()
|
||||
.extra("DEFAULT NOW()"),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(RecurrenceRule::UpdatedAt)
|
||||
.timestamp()
|
||||
.not_null(),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_table(Table::drop().table(RecurrenceRule::Table).to_owned())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum RecurrenceRule {
|
||||
Table,
|
||||
Id,
|
||||
Type,
|
||||
Interval,
|
||||
ByWeekday,
|
||||
ByMonthday,
|
||||
Timezone,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
}
|
||||
102
backend_rust/migration/src/m20220101_000005_create_todo.rs
Normal file
102
backend_rust/migration/src/m20220101_000005_create_todo.rs
Normal file
@@ -0,0 +1,102 @@
|
||||
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(Todo::Table)
|
||||
.if_not_exists()
|
||||
.col(ColumnDef::new(Todo::Id).uuid().primary_key().not_null())
|
||||
.col(ColumnDef::new(Todo::OwnerId).uuid().not_null())
|
||||
.col(ColumnDef::new(Todo::Title).string().not_null())
|
||||
.col(ColumnDef::new(Todo::Description).string().null())
|
||||
.col(ColumnDef::new(Todo::DueAt).timestamp().not_null())
|
||||
.col(ColumnDef::new(Todo::RecurrenceRuleId).uuid().null())
|
||||
.col(
|
||||
ColumnDef::new(Todo::CreatedAt)
|
||||
.timestamp()
|
||||
.not_null()
|
||||
.extra("DEFAULT NOW()"),
|
||||
)
|
||||
.col(ColumnDef::new(Todo::UpdatedAt).timestamp().not_null())
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_todo_owner")
|
||||
.from(Todo::Table, Todo::OwnerId)
|
||||
.to(User::Table, User::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_todo_recurrence_rule")
|
||||
.from(Todo::Table, Todo::RecurrenceRuleId)
|
||||
.to(RecurrenceRule::Table, RecurrenceRule::Id)
|
||||
.on_delete(ForeignKeyAction::SetNull)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Create indexes
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("IDX_todo_owner_due")
|
||||
.table(Todo::Table)
|
||||
.col(Todo::OwnerId)
|
||||
.col(Todo::DueAt)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("IDX_todo_recurrence_rule_id")
|
||||
.table(Todo::Table)
|
||||
.col(Todo::RecurrenceRuleId)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_table(Table::drop().table(Todo::Table).to_owned())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum Todo {
|
||||
Table,
|
||||
Id,
|
||||
OwnerId,
|
||||
Title,
|
||||
Description,
|
||||
DueAt,
|
||||
RecurrenceRuleId,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum User {
|
||||
Table,
|
||||
Id,
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum RecurrenceRule {
|
||||
Table,
|
||||
Id,
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
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(ReminderTask::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(ReminderTask::Id)
|
||||
.uuid()
|
||||
.primary_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(ReminderTask::CreatorId).uuid().not_null())
|
||||
.col(ColumnDef::new(ReminderTask::Title).string().not_null())
|
||||
.col(ColumnDef::new(ReminderTask::Description).string().null())
|
||||
.col(ColumnDef::new(ReminderTask::DueAt).timestamp().not_null())
|
||||
.col(ColumnDef::new(ReminderTask::RecurrenceRuleId).uuid().null())
|
||||
.col(
|
||||
ColumnDef::new(ReminderTask::CreatedAt)
|
||||
.timestamp()
|
||||
.not_null()
|
||||
.extra("DEFAULT NOW()"),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ReminderTask::UpdatedAt)
|
||||
.timestamp()
|
||||
.not_null(),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_reminder_task_creator")
|
||||
.from(ReminderTask::Table, ReminderTask::CreatorId)
|
||||
.to(User::Table, User::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_reminder_task_recurrence_rule")
|
||||
.from(ReminderTask::Table, ReminderTask::RecurrenceRuleId)
|
||||
.to(RecurrenceRule::Table, RecurrenceRule::Id)
|
||||
.on_delete(ForeignKeyAction::SetNull)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Create indexes
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("IDX_reminder_task_creator_due")
|
||||
.table(ReminderTask::Table)
|
||||
.col(ReminderTask::CreatorId)
|
||||
.col(ReminderTask::DueAt)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("IDX_reminder_task_recurrence_rule_id")
|
||||
.table(ReminderTask::Table)
|
||||
.col(ReminderTask::RecurrenceRuleId)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_table(Table::drop().table(ReminderTask::Table).to_owned())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum ReminderTask {
|
||||
Table,
|
||||
Id,
|
||||
CreatorId,
|
||||
Title,
|
||||
Description,
|
||||
DueAt,
|
||||
RecurrenceRuleId,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum User {
|
||||
Table,
|
||||
Id,
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum RecurrenceRule {
|
||||
Table,
|
||||
Id,
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
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(ReminderTaskRecipient::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(ReminderTaskRecipient::TaskId)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ReminderTaskRecipient::UserId)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.primary_key(
|
||||
Index::create()
|
||||
.col(ReminderTaskRecipient::TaskId)
|
||||
.col(ReminderTaskRecipient::UserId),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_reminder_task_recipient_task")
|
||||
.from(ReminderTaskRecipient::Table, ReminderTaskRecipient::TaskId)
|
||||
.to(ReminderTask::Table, ReminderTask::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_reminder_task_recipient_user")
|
||||
.from(ReminderTaskRecipient::Table, ReminderTaskRecipient::UserId)
|
||||
.to(User::Table, User::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Create index on user_id for reverse lookups
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("IDX_reminder_task_recipient_user_id")
|
||||
.table(ReminderTaskRecipient::Table)
|
||||
.col(ReminderTaskRecipient::UserId)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_table(Table::drop().table(ReminderTaskRecipient::Table).to_owned())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum ReminderTaskRecipient {
|
||||
Table,
|
||||
TaskId,
|
||||
UserId,
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum ReminderTask {
|
||||
Table,
|
||||
Id,
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum User {
|
||||
Table,
|
||||
Id,
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
use crate::m20220101_000002_create_enums::TargetType;
|
||||
|
||||
#[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(ReminderOffset::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(ReminderOffset::Id)
|
||||
.uuid()
|
||||
.primary_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ReminderOffset::TargetType)
|
||||
.custom(TargetType::Type)
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(ReminderOffset::TargetId).uuid().not_null())
|
||||
.col(
|
||||
ColumnDef::new(ReminderOffset::OffsetMinutes)
|
||||
.integer()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ReminderOffset::ChannelInapp)
|
||||
.boolean()
|
||||
.not_null()
|
||||
.default(true),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ReminderOffset::ChannelBark)
|
||||
.boolean()
|
||||
.not_null()
|
||||
.default(false),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(ReminderOffset::CreatedAt)
|
||||
.timestamp()
|
||||
.not_null()
|
||||
.extra("DEFAULT NOW()"),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Create index for polymorphic lookup
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("IDX_reminder_offset_target")
|
||||
.table(ReminderOffset::Table)
|
||||
.col(ReminderOffset::TargetType)
|
||||
.col(ReminderOffset::TargetId)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_table(Table::drop().table(ReminderOffset::Table).to_owned())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum ReminderOffset {
|
||||
Table,
|
||||
Id,
|
||||
TargetType,
|
||||
TargetId,
|
||||
OffsetMinutes,
|
||||
ChannelInapp,
|
||||
ChannelBark,
|
||||
CreatedAt,
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
use crate::m20220101_000002_create_enums::{ChannelType, NotificationStatus, TargetType};
|
||||
|
||||
#[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(Notification::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(Notification::Id)
|
||||
.uuid()
|
||||
.primary_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(Notification::RecipientId).uuid().not_null())
|
||||
.col(
|
||||
ColumnDef::new(Notification::TargetType)
|
||||
.custom(TargetType::Type)
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(Notification::TargetId).uuid().not_null())
|
||||
.col(
|
||||
ColumnDef::new(Notification::TriggerAt)
|
||||
.timestamp()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Notification::Channel)
|
||||
.custom(ChannelType::Type)
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Notification::Status)
|
||||
.custom(NotificationStatus::Type)
|
||||
.not_null()
|
||||
.default("pending"),
|
||||
)
|
||||
.col(ColumnDef::new(Notification::LockedAt).timestamp().null())
|
||||
.col(ColumnDef::new(Notification::SentAt).timestamp().null())
|
||||
.col(ColumnDef::new(Notification::ReadAt).timestamp().null())
|
||||
.col(
|
||||
ColumnDef::new(Notification::CreatedAt)
|
||||
.timestamp()
|
||||
.not_null()
|
||||
.extra("DEFAULT NOW()"),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(Notification::UpdatedAt)
|
||||
.timestamp()
|
||||
.not_null(),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_notification_recipient")
|
||||
.from(Notification::Table, Notification::RecipientId)
|
||||
.to(User::Table, User::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Create unique constraint
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("UQ_notification_recipient_target_trigger_channel")
|
||||
.table(Notification::Table)
|
||||
.col(Notification::RecipientId)
|
||||
.col(Notification::TargetType)
|
||||
.col(Notification::TargetId)
|
||||
.col(Notification::TriggerAt)
|
||||
.col(Notification::Channel)
|
||||
.unique()
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Create indexes
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("IDX_notification_status_trigger")
|
||||
.table(Notification::Table)
|
||||
.col(Notification::Status)
|
||||
.col(Notification::TriggerAt)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("IDX_notification_recipient_read")
|
||||
.table(Notification::Table)
|
||||
.col(Notification::RecipientId)
|
||||
.col(Notification::ReadAt)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_table(Table::drop().table(Notification::Table).to_owned())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum Notification {
|
||||
Table,
|
||||
Id,
|
||||
RecipientId,
|
||||
TargetType,
|
||||
TargetId,
|
||||
TriggerAt,
|
||||
Channel,
|
||||
Status,
|
||||
LockedAt,
|
||||
SentAt,
|
||||
ReadAt,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum User {
|
||||
Table,
|
||||
Id,
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
use crate::m20220101_000002_create_enums::{ChannelType, NotificationStatus};
|
||||
|
||||
#[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(DeliveryLog::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
ColumnDef::new(DeliveryLog::Id)
|
||||
.uuid()
|
||||
.primary_key()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(DeliveryLog::NotificationId)
|
||||
.uuid()
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(DeliveryLog::AttemptNo).integer().not_null())
|
||||
.col(
|
||||
ColumnDef::new(DeliveryLog::Channel)
|
||||
.custom(ChannelType::Type)
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(DeliveryLog::Status)
|
||||
.custom(NotificationStatus::Type)
|
||||
.not_null(),
|
||||
)
|
||||
.col(ColumnDef::new(DeliveryLog::ResponseMeta).json_binary().null())
|
||||
.col(
|
||||
ColumnDef::new(DeliveryLog::CreatedAt)
|
||||
.timestamp()
|
||||
.not_null()
|
||||
.extra("DEFAULT NOW()"),
|
||||
)
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("FK_delivery_log_notification")
|
||||
.from(DeliveryLog::Table, DeliveryLog::NotificationId)
|
||||
.to(Notification::Table, Notification::Id)
|
||||
.on_delete(ForeignKeyAction::Cascade)
|
||||
.on_update(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Create index
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("IDX_delivery_log_notification_id")
|
||||
.table(DeliveryLog::Table)
|
||||
.col(DeliveryLog::NotificationId)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_table(Table::drop().table(DeliveryLog::Table).to_owned())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum DeliveryLog {
|
||||
Table,
|
||||
Id,
|
||||
NotificationId,
|
||||
AttemptNo,
|
||||
Channel,
|
||||
Status,
|
||||
ResponseMeta,
|
||||
CreatedAt,
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum Notification {
|
||||
Table,
|
||||
Id,
|
||||
}
|
||||
38
backend_rust/migration/src/m20260128_000011_modify_todo.rs
Normal file
38
backend_rust/migration/src/m20260128_000011_modify_todo.rs
Normal file
@@ -0,0 +1,38 @@
|
||||
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
|
||||
.alter_table(
|
||||
Table::alter()
|
||||
.table(Todo::Table)
|
||||
.add_column(ColumnDef::new(Todo::CheckInAt).timestamp().null())
|
||||
.add_column(
|
||||
ColumnDef::new(Todo::CheckInCount)
|
||||
.integer()
|
||||
.not_null()
|
||||
.default(0),
|
||||
)
|
||||
.add_column(
|
||||
ColumnDef::new(Todo::IsCheckedIn)
|
||||
.boolean()
|
||||
.not_null()
|
||||
.default(false),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum Todo {
|
||||
Table,
|
||||
CheckInAt,
|
||||
CheckInCount,
|
||||
IsCheckedIn,
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
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
|
||||
.alter_table(
|
||||
Table::alter()
|
||||
.table(ReminderOffset::Table)
|
||||
.add_column(ColumnDef::new(ReminderOffset::BarkTitle).string().null())
|
||||
.add_column(ColumnDef::new(ReminderOffset::BarkSubtitle).string().null())
|
||||
.add_column(ColumnDef::new(ReminderOffset::BarkBodyMarkdown).text().null())
|
||||
.add_column(ColumnDef::new(ReminderOffset::BarkLevel).string().null())
|
||||
.add_column(ColumnDef::new(ReminderOffset::BarkIcon).string().null())
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.alter_table(
|
||||
Table::alter()
|
||||
.table(ReminderOffset::Table)
|
||||
.drop_column(ReminderOffset::BarkTitle)
|
||||
.drop_column(ReminderOffset::BarkSubtitle)
|
||||
.drop_column(ReminderOffset::BarkBodyMarkdown)
|
||||
.drop_column(ReminderOffset::BarkLevel)
|
||||
.drop_column(ReminderOffset::BarkIcon)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum ReminderOffset {
|
||||
Table,
|
||||
BarkTitle,
|
||||
BarkSubtitle,
|
||||
BarkBodyMarkdown,
|
||||
BarkLevel,
|
||||
BarkIcon,
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
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
|
||||
.alter_table(
|
||||
Table::alter()
|
||||
.table(Notification::Table)
|
||||
.add_column(ColumnDef::new(Notification::OffsetId).uuid().null())
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.alter_table(
|
||||
Table::alter()
|
||||
.table(Notification::Table)
|
||||
.drop_column(Notification::OffsetId)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum Notification {
|
||||
Table,
|
||||
OffsetId,
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
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> {
|
||||
let db = manager.get_connection();
|
||||
|
||||
// User table: created_at, updated_at
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE \"user\"
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE USING created_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN updated_at TYPE TIMESTAMP WITH TIME ZONE USING updated_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// Invite table: expires_at, revoked_at, created_at
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE invite
|
||||
ALTER COLUMN expires_at TYPE TIMESTAMP WITH TIME ZONE USING expires_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN revoked_at TYPE TIMESTAMP WITH TIME ZONE USING revoked_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE USING created_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// RecurrenceRule table: created_at, updated_at
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE recurrence_rule
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE USING created_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN updated_at TYPE TIMESTAMP WITH TIME ZONE USING updated_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// Todo table: due_at, created_at, updated_at, check_in_at
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE todo
|
||||
ALTER COLUMN due_at TYPE TIMESTAMP WITH TIME ZONE USING due_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE USING created_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN updated_at TYPE TIMESTAMP WITH TIME ZONE USING updated_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN check_in_at TYPE TIMESTAMP WITH TIME ZONE USING check_in_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// ReminderTask table: due_at, created_at, updated_at
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE reminder_task
|
||||
ALTER COLUMN due_at TYPE TIMESTAMP WITH TIME ZONE USING due_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE USING created_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN updated_at TYPE TIMESTAMP WITH TIME ZONE USING updated_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// ReminderOffset table: created_at
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE reminder_offset
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE USING created_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// Notification table: trigger_at, locked_at, sent_at, read_at, created_at, updated_at
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE notification
|
||||
ALTER COLUMN trigger_at TYPE TIMESTAMP WITH TIME ZONE USING trigger_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN locked_at TYPE TIMESTAMP WITH TIME ZONE USING locked_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN sent_at TYPE TIMESTAMP WITH TIME ZONE USING sent_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN read_at TYPE TIMESTAMP WITH TIME ZONE USING read_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE USING created_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN updated_at TYPE TIMESTAMP WITH TIME ZONE USING updated_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// DeliveryLog table: created_at
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE delivery_log
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE USING created_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
let db = manager.get_connection();
|
||||
|
||||
// Revert User table
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE \"user\"
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN updated_at TYPE TIMESTAMP USING updated_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// Revert Invite table
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE invite
|
||||
ALTER COLUMN expires_at TYPE TIMESTAMP USING expires_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN revoked_at TYPE TIMESTAMP USING revoked_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// Revert RecurrenceRule table
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE recurrence_rule
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN updated_at TYPE TIMESTAMP USING updated_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// Revert Todo table
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE todo
|
||||
ALTER COLUMN due_at TYPE TIMESTAMP USING due_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN updated_at TYPE TIMESTAMP USING updated_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN check_in_at TYPE TIMESTAMP USING check_in_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// Revert ReminderTask table
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE reminder_task
|
||||
ALTER COLUMN due_at TYPE TIMESTAMP USING due_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN updated_at TYPE TIMESTAMP USING updated_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// Revert ReminderOffset table
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE reminder_offset
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// Revert Notification table
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE notification
|
||||
ALTER COLUMN trigger_at TYPE TIMESTAMP USING trigger_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN locked_at TYPE TIMESTAMP USING locked_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN sent_at TYPE TIMESTAMP USING sent_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN read_at TYPE TIMESTAMP USING read_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC',
|
||||
ALTER COLUMN updated_at TYPE TIMESTAMP USING updated_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
// Revert DeliveryLog table
|
||||
db.execute_unprepared(
|
||||
"ALTER TABLE delivery_log
|
||||
ALTER COLUMN created_at TYPE TIMESTAMP USING created_at AT TIME ZONE 'UTC'"
|
||||
).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
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> {
|
||||
// Add invite_id column to user table
|
||||
manager
|
||||
.alter_table(
|
||||
Table::alter()
|
||||
.table(User::Table)
|
||||
.add_column(ColumnDef::new(User::InviteId).uuid().null())
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Add foreign key constraint
|
||||
manager
|
||||
.create_foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("fk_user_invite_id")
|
||||
.from(User::Table, User::InviteId)
|
||||
.to(Invite::Table, Invite::Id)
|
||||
.on_delete(ForeignKeyAction::SetNull)
|
||||
.on_update(ForeignKeyAction::Cascade)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Add index for better query performance
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("idx_user_invite_id")
|
||||
.table(User::Table)
|
||||
.col(User::InviteId)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
// Drop index
|
||||
manager
|
||||
.drop_index(Index::drop().name("idx_user_invite_id").to_owned())
|
||||
.await?;
|
||||
|
||||
// Drop foreign key
|
||||
manager
|
||||
.drop_foreign_key(
|
||||
ForeignKey::drop()
|
||||
.table(User::Table)
|
||||
.name("fk_user_invite_id")
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Drop column
|
||||
manager
|
||||
.alter_table(
|
||||
Table::alter()
|
||||
.table(User::Table)
|
||||
.drop_column(User::InviteId)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum User {
|
||||
Table,
|
||||
InviteId,
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum Invite {
|
||||
Table,
|
||||
Id,
|
||||
}
|
||||
6
backend_rust/migration/src/main.rs
Normal file
6
backend_rust/migration/src/main.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
cli::run_cli(migration::Migrator).await;
|
||||
}
|
||||
Reference in New Issue
Block a user