Oyelowo / surreal-orm

Powerful & expressive ORM/query-builder/static checker for raw queries/Fully Automated migration tooling , designed to offer an intuitive API, strict type-checking, novel features, & full specification support. It provides a fresh perspective in data management. Currently supports SurrealDB engine. RDMSs(PG, MYSQL etc) and others coming soon
85 stars 2 forks source link

42 implement fully automated db schema migration #44

Closed Oyelowo closed 10 months ago

Oyelowo commented 10 months ago

Overview

This pull request adds support for database migration workflow, focusing on the user experience with new CLI commands for generating and managing migrations. The updates aim to provide a more intuitive and efficient process for handling database changes, ensuring that developers can easily create, apply, roll back, and list migrations with minimal friction.

Features

Example:

use surreal_orm::migrator::{self, embed_migrations, MigrationConfig};

// Embed migrations as constants
const MIGRATIONS_ONE_WAY: migrator::EmbeddedMigrationsOneWay =
    embed_migrations!("migrations-oneway", one_way, strict);

const MIGRATIONS_TWO_WAY: migrator::EmbeddedMigrationsTwoWay =
    embed_migrations!("migrations-twoway, two_way, strict");

Usage Examples

Gather Resources from the code base:

#[derive(Debug, Clone)]
pub struct Resources;

impl DbResources for Resources {
    create_table_resources!(Student, Planet);
}

#[derive(Node, Serialize, Deserialize, Debug, Clone, Default)]
#[serde(rename_all = "camelCase")]
#[surreal_orm(table_name = "planet", schemafull)]
pub struct Planet {
    pub id: SurrealSimpleId<Self>,
    pub population: u64,
    pub created_at: chrono::DateTime<Utc>,
    pub updated_at: chrono::DateTime<Utc>,
    pub labels: Vec<String>,
}

impl TableResources for Planet {}

#[derive(Node, Serialize, Deserialize, Debug, Clone, Default)]
#[serde(rename_all = "camelCase")]
#[surreal_orm(table_name = "student", schemafull)]
pub struct Student {
    pub id: SurrealSimpleId<Self>,
// Uncomment the below line to perform a rename before running the cli
//    #[surreal_orm(old_name = "school")]
    pub university: String,
    pub age: u8,
    pub updated_at: chrono::DateTime<Utc>,
    pub created_at: chrono::DateTime<Utc>,
}

impl TableResources for Student {}

Set up CLI Binary:

use surreal_models::migrations::Resources;
use surreal_orm::migrator::cli;
use surrealdb::engine::any::{connect, Any};

#[tokio::main]
async fn main() {
   // Option 1: Db connection is setup for you depending on CLI arguments
    cli::migration_cli(Resources, None).await;

// Option 2:
// Create your own db connection
//    let db = setup_db().await;
//  cli::migration_cli(Resources, Some(db)).await;
}

Generate a New Migration:

cargo run -- generate --name [migration_name]
cargo run -- generate --name "create user"

This command will create new migration files in the specified directory.

Apply Migrations to the Database:

cargo run -- run  --db [database] --ns [namespace] --path [db_path]
cargo run -- run  --db test --ns test --path http://localhost:8000

This will apply all pending migrations in the specified directory to the database.

Roll Back Applied Migrations:

cargo run -- rollback --db [database] --ns [namespace] --path [db_path]
cargo run -- rollback --db test --ns test --path http://localhost:8000
cargo run -- rollback --db test --ns test --path http://localhost:8000 --latest
cargo run -- rollback --db test --ns test --path http://localhost:8000 --by_count 2
cargo run -- rollback --db test --ns test --path http://localhost:8000 --till <id>

This command will roll back migrations that have been applied, in reverse order.

List Migrations:

cargo run -- list --db test --ns test

Conclusion

The enhancements to the database migration workflow represent a significant improvement in the developer experience.