From acf79a306797b1b12e95415c340792d7c88815ab Mon Sep 17 00:00:00 2001 From: Melody Horn / boringcactus Date: Fri, 18 Jun 2021 13:42:52 -0600 Subject: lay groundwork for make-migrations --- src/cli/make_migrations.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++ src/cli/mod.rs | 3 +++ src/db/models/meta.rs | 3 +++ src/db/models/mod.rs | 1 + tosin-macros/src/lib.rs | 4 ++- 5 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/cli/make_migrations.rs diff --git a/src/cli/make_migrations.rs b/src/cli/make_migrations.rs new file mode 100644 index 0000000..767639f --- /dev/null +++ b/src/cli/make_migrations.rs @@ -0,0 +1,66 @@ +use std::collections::HashMap; + +use structopt::StructOpt; + +use crate::{Settings, UrlMap, db::backend::Connectable}; +use crate::db::migration::{Migration, DatabaseChange, CreateModelOption}; +use crate::db::models::{Field, ModelMeta}; + +#[derive(StructOpt)] +/// Generate migrations +pub struct MakeMigrations { +} + +#[derive(Debug)] +struct AppTablesState { + db: HashMap<&'static str, TableState>, +} + +#[derive(Debug)] +struct TableState { + fields: Vec, +} + +impl From<&[ModelMeta]> for AppTablesState { + fn from(models: &[ModelMeta]) -> Self { + let mut db = HashMap::new(); + for model in models { + db.insert(model.name, TableState { fields: model.fields.into() }); + } + Self { db } + } +} + +impl From<&[Migration]> for AppTablesState { + fn from(migrations: &[Migration]) -> Self { + let mut db = HashMap::new(); + for migration in migrations { + for change in migration.changes { + match change { + DatabaseChange::CreateModel { name, fields, options } => { + if db.contains_key(name) { + if options.contains(&CreateModelOption::IfNotExist) { + continue; + } else { + panic!("double-created table {}", name); + } + } + db.insert(*name, TableState { fields: (*fields).into() }); + } + } + } + } + Self { db } + } +} + +impl MakeMigrations { + pub fn execute(self, _urls: UrlMap, settings: Settings) { + for app in settings.installed_apps { + let expected_table_state = AppTablesState::from(app.models); + let actual_table_state = AppTablesState::from(app.migrations); + dbg!(expected_table_state, actual_table_state); + todo!(); + } + } +} diff --git a/src/cli/mod.rs b/src/cli/mod.rs index a11fd48..851812f 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -2,11 +2,13 @@ use structopt::StructOpt; use crate::{Settings, UrlMap, db::backend::Connectable}; +mod make_migrations; mod migrate; mod run_server; #[derive(StructOpt)] enum Command { + MakeMigrations(make_migrations::MakeMigrations), Migrate(migrate::Migrate), RunServer(run_server::RunServer), } @@ -14,6 +16,7 @@ enum Command { impl Command { fn execute(self, urls: UrlMap, settings: Settings) { match self { + Command::MakeMigrations(command) => command.execute(urls, settings), Command::Migrate(command) => command.execute(urls, settings), Command::RunServer(command) => command.execute(urls, settings), } diff --git a/src/db/models/meta.rs b/src/db/models/meta.rs index 50729a8..16e7290 100644 --- a/src/db/models/meta.rs +++ b/src/db/models/meta.rs @@ -1,3 +1,6 @@ +use super::Field; + pub struct ModelMeta { pub name: &'static str, + pub fields: &'static [Field], } diff --git a/src/db/models/mod.rs b/src/db/models/mod.rs index feadb43..3f39ccd 100644 --- a/src/db/models/mod.rs +++ b/src/db/models/mod.rs @@ -5,6 +5,7 @@ pub use meta::*; pub type Id = usize; +#[derive(Clone, Debug)] pub enum Field { CharField { name: &'static str, diff --git a/tosin-macros/src/lib.rs b/tosin-macros/src/lib.rs index 531a92b..86750e1 100644 --- a/tosin-macros/src/lib.rs +++ b/tosin-macros/src/lib.rs @@ -20,9 +20,11 @@ pub fn model_derive(input: TokenStream) -> TokenStream { fn impl_model(ast: &syn::DeriveInput) -> TokenStream { let name = &ast.ident; let gen = quote! { + use tosin::db::models::ModelMeta; impl #name { - pub const META: tosin::db::models::ModelMeta = tosin::db::models::ModelMeta { + pub const META: ModelMeta = ModelMeta { name: stringify!(#name), + fields: &[], }; } }; -- cgit v1.2.3