use std::fs::remove_file;
use dml_tools::Loader;
use dml_tools::Processor;
use dml_tools::type_writers::*;
use dml_tools::sql::*;
use serde::{Deserialize, Serialize};
use dml_tools::util::*;
use dml_tools::macros::*;
mod common;
use common::print_if_different;
macro_rules! des_ser_base {
() => { "local-proc-objs" };
}
const DES_SER_FILE: &str = concat!(des_ser_base!(), ".yaml");
const DES_SER_FILE_COMP: &str = concat!(des_ser_base!(), "_comp.yaml");
const NUM_STATEMENTS: usize = 18;
#[derive(Serialize, Deserialize, Debug)]
pub struct MyRoles {
pub rw: String,
pub ro: String,
pub upd: String,
}
impl Default for MyRoles {
fn default() -> Self {
MyRoles {
rw: "rw_user".into(),
ro: "ro_user".into(),
upd: "upd_user".into(),
}
}
}
type BxTypeWriter = Box<dyn TypeWriter>;
fn generate_from_code(type_writer:Option<BxTypeWriter>) -> Vec<String> {
let mut proc = Processor::new(type_writer);
assert_eq!(proc.objects().len(), 0);
let roles = MyRoles::default();
let my_schema = String::from("my_schema");
let schema = Schema::new(&my_schema, &roles.rw);
proc.add(&schema);
let oschema = ObjectPath::new_table_only(&schema.name);
add_grant!(proc, GrantType::All, &roles.rw, &oschema);
add_grant!(proc, GrantType::Usage, &roles.upd, &oschema);
add_grant!(proc, GrantType::Usage, &roles.ro, &oschema);
let u_fields = vec![
Field::new("workspace", &FieldAttributes::new_uk(FieldType::Txt)),
Field::new("is_archived", &FieldAttributes::new(FieldType::Bool)),
Field::new("creation_date", &FieldAttributes::new_nn(FieldType::Txt)),
Field::new("user_id", &FieldAttributes::new_nn(FieldType::Txt)),
Field::new("user_name", &FieldAttributes::new_uk(FieldType::Txt)),
Field::new("full_name", &FieldAttributes::new(FieldType::Txt)),
Field::new("role", &FieldAttributes::new_nn(FieldType::Txt)),
Field::new("is_locked", &FieldAttributes::new_nn(FieldType::Bool)),
Field::new("email", &FieldAttributes::new(FieldType::Txt)),
Field::new("phone_number", &FieldAttributes::new(FieldType::Txt)),
Field::new("supervisor_id", &FieldAttributes::new(FieldType::Txt)),
Field::new("is_locked_by_supervisor", &FieldAttributes::new_nn_def(FieldType::Bool, "false")),
Field::new("is_locked_by_headquarters", &FieldAttributes::new_nn_def(FieldType::Bool, "false")),
];
let t_users = Table::new(&ObjectPath::new_table(&my_schema, "users"), u_fields, None);
proc.add(&t_users);
grant_perms!(&mut proc, &roles, &t_users.path);
let c_fields = vec![
Field::new("id", &FieldAttributes::new_nn(FieldType::AutoInc)),
Field::new("pk", &FieldAttributes::new(FieldType::Txt)),
Field::new("responsible", &FieldAttributes::new_nn(FieldType::Txt)),
Field::new("responsible_id", &FieldAttributes::new_nn(FieldType::Txt)),
Field::new("workspace", &FieldAttributes::new_pk(FieldType::Txt)),
Field::new("survey_id", &FieldAttributes::new_pk(FieldType::Int)),
Field::new("questionnaire_id", &FieldAttributes::new_nn(FieldType::Txt)),
Field::new("date_created", &FieldAttributes::new_nn(FieldType::Txt)),
Field::new("date_updated", &FieldAttributes::new_nn(FieldType::Txt)),
Field::new("otro", &FieldAttributes::new_meta(FieldType::Int, "4")),
];
let t_cache = Table::new(&ObjectPath::new_table(&my_schema, "cache"), c_fields, None);
proc.add(&t_cache);
grant_perms!(&mut proc, &roles, &t_cache.path);
let o_seq = ObjectPath::new_sequence(&my_schema, "asignaciones_cache_id_seq");
grant_perms!(&mut proc, &roles, &o_seq);
proc.serialize_to_yaml_file(DES_SER_FILE).expect("to write proc to file");
proc.sql_statements()
}
fn check_processor_from_code(type_writer:BxTypeWriter) {
let id = type_writer.as_ref().id().to_owned();
let sqlfile = format!("tests/fixtures/proc_{}.sql", id);
let pstr = read_file_into_string(&sqlfile);
let sqls = generate_from_code(Some(type_writer));
let re_mnl = regex::Regex::new(r"\n+").unwrap();
let rsqls = sqls.join("\n");
let sqlsj = re_mnl.replace_all(&rsqls, "\n");
print_if_different(&sqlsj, &pstr);
assert_eq!(sqlsj, pstr);
let psqls:Vec<&str> = pstr.split(";").filter(|s| ! s.is_empty()).collect();
if id == "pgsql" {
for (i, sql) in sqls.iter().enumerate() {
assert_eq!(sql, format!("{};", psqls[i].trim()).as_str())
}
}
}
#[test]
fn test_processor_from_code_mysql() {
check_processor_from_code(Box::new(Mysql{}))
}
#[test]
fn test_processor_from_code_sqlite() {
check_processor_from_code(Box::new(Sqlite{}))
}
#[test]
fn test_processor_from_code_pgsql() {
check_processor_from_code(Box::new(Postgresql{}))
}
#[test]
fn test_processor_from_file() {
_ = generate_from_code(None);
let loader = Loader::new_from_file(DES_SER_FILE).unwrap();
let proc = Processor::new_with_objects(loader.objects(), None);
assert_eq!(proc.objects().len(), NUM_STATEMENTS);
proc.serialize_to_yaml_file(DES_SER_FILE_COMP).expect("to write comp file");
assert_eq!(read_file_into_string(DES_SER_FILE), read_file_into_string(DES_SER_FILE_COMP));
remove_file(DES_SER_FILE).unwrap();
remove_file(DES_SER_FILE_COMP).unwrap();
}
const SQLI_YAML : &str = "tests/fixtures/sqlite-init.yaml";
const SQLI_SQL : &str = "tests/fixtures/sqlite-init.sql";
#[test]
fn test_processor_sqlite_from_yaml() {
let loader = Loader::new_from_file(SQLI_YAML).unwrap();
let tr: BxTypeWriter = Box::new(Sqlite{});
let proc = Processor::new_with_objects(loader.objects(),Some(tr));
let expected = read_file_into_string(SQLI_SQL);
let generated = proc.join_sql_statements();
print_if_different(&expected, &generated);
assert_eq!(generated, expected)
}