Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schema Manager #12

Closed
tyt2y3 opened this issue Aug 14, 2021 · 4 comments · Fixed by #26
Closed

Schema Manager #12

tyt2y3 opened this issue Aug 14, 2021 · 4 comments · Fixed by #26
Assignees

Comments

@tyt2y3
Copy link
Member

tyt2y3 commented Aug 14, 2021

To support SeaORM, we want to develop SeaSchema into a fully-featured schema manager.

Functionalities:

  • A cli client (to be wrapped by sea-orm-cli as a sub command)
  • Migration manager
  • Migration codegen
  • Schema manager

Migration Manager

The migration manager would work like sqlx-cli migration, keeping track of executed migrations.
Our private table would be named seaql_migrations.

The migration 'script' would look like:

use sea_schema::*;

#[derive(Migrator)]
pub struct M20210101020202CreateGlyphTable;

#[derive(Iden)]
pub enum Glyph {
    Table,
    Id,
    Image,
    Aspect,
}

#[async_trait]
impl MigratorTrait for M20210101020202CreateGlyphTable {
    async fn up(mg: &SchemaManager) -> Result<(), DbErr> {
        mg.create_table(
            // TableCreateStatement
            Table::create()
                .table(Glyph::Table)
                .col(
                    ColumnDef::new(Glyph::Id)
                        .integer_len(11)
                        .not_null()
                        .auto_increment()
                        .primary_key()
                )
                .col(ColumnDef::new(Glyph::Aspect).double().not_null())
                .col(ColumnDef::new(Glyph::Image).text())
        ).await?;

        Ok(())
    }

    async fn down(mg: &SchemaManager) -> Result<(), DbErr> {
        mg.drop_table(Glyph::Table).await?;

        Ok(())
    }
}

Migration Codegen

The migration should scaffold a rust project with the following structure:

\migration
    Cargo.toml
    \src
        m20210101020202_create_glyph_table.rs
        lib.rs
        main.rs

The project would serve two functions: as an executable to be executed:

cd migration
cargo run -- run

On the other hand, it can also be used as a library, to be required by the web server when deployed:

use migration::Migrator;

async fn main() {
    Migrator::run().await;
    WebServer::start().await;
}

Schema Manager

The SchemaManager will provide 3 categories of APIs:

  1. Definition: create_table, create_index, create_foreign_key etc
  2. Mutation: add_column, rename_column etc
  3. Inspection: has_table, has_column etc
@JonasCir
Copy link

Hi, thank you for creating all these great libs, I'm really happy to see progress on this! 🚀

Not certain if this was brought up before, but I think it could be beneficial to support:

  1. SchemaManager.migrateFromRawSql(sql:&str)
  2. SchemaManager.migrateFromFile(path: &impl AsRef<Path>)

A disadvantage I see is that adding these functions breaks the strict structure the current implementation enforces. On the other hand, it might help people to experiment with this tool stack as their current migrations might be plain SQL. Not supporting this would require them to rewrite everything in plain Rust just to test a few things.

Personally, I also prefer writing my migrations in plain SQL, so that's also a reason why I raised this :D

@billy1624
Copy link
Member

Hey @JonasCir, nice observations! This is actually supported, you can define migration with raw SQL in string literal or from SQL file using include_str! macro.

pub async fn exec_stmt<S>(&self, stmt: S) -> Result<(), DbErr>
where
S: StatementBuilder,
{
let builder = self.conn.get_database_backend();
self.conn.execute(builder.build(&stmt)).await.map(|_| ())
}

@JonasCir
Copy link

Hi thanks for the prompt answer, happy to see it being supported then 👍
Maybe it is worth to state this somewhere in the docs or on the website b/c I'm pretty certain a lot of people will search for this.

@tasn
Copy link

tasn commented Jan 31, 2022

This looks like a related effort that can be reused: https://github.com/rust-db/refinery

@tyt2y3 tyt2y3 closed this as completed in #26 Feb 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants