Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ jobs:
- run: curl --fail -X POST http://localhost:8080/png --data-binary @result.puml -o test.png

- run: ./target/release/sqlant $TEST_DATABASE_URL --legend -e --inline-puml-lib > result.puml
- run: curl --fail -X POST http://localhost:8080/png --data-binary @result.puml -o test.png

- run: ./target/release/sqlant $TEST_DATABASE_URL --conceptual > result.puml
- run: curl --fail -X POST http://localhost:8080/png --data-binary @result.puml -o test.png

# Mermaid
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub struct GeneratorConfigOptions {
pub draw_enums: bool,
pub draw_legend: bool,
pub inline_puml_lib: bool,
pub conceptual_diagram: bool,
}

pub trait ViewGenerator {
Expand Down
8 changes: 8 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ async fn main() {
.action(ArgAction::Set)
.default_value("plantuml"),
)
.arg(
Arg::new("conceptual")
.long("conceptual")
.help("Create conceptual ER diagram")
.action(ArgAction::SetTrue)
.default_value("false"),
)
.get_matches();

let mut s = lookup_parser(
Expand All @@ -79,6 +86,7 @@ async fn main() {
draw_enums: args.get_flag("enums"),
draw_legend: args.get_flag("legend"),
inline_puml_lib: args.get_flag("inline-puml-lib"),
conceptual_diagram: args.get_flag("conceptual"),
},
)
.unwrap();
Expand Down
39 changes: 29 additions & 10 deletions src/plantuml_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ pub struct PlantUmlDefaultGenerator<'a> {

static PUML_TEMPLATE: &str = "@startuml\n\n\
hide circle\n\
hide empty members\n\
skinparam linetype ortho\n\n\
{puml_lib}\n\n\
{{ for ent in entities}}{ent}\n{{ endfor }}\n\
{{ for view in views}}{view}\n{{ endfor }}\n\
{{ for fk in foreign_keys}}{fk}\n{{ endfor }}\n\
{{ for e in enums}}{e}\n{{ endfor }}{legend}\n@enduml";

static ENTITY_TEMPLATE: &str = "table({name}) \\{\n{pks} ---\n{fks}{nns}{others}}\n";
static ENTITY_TEMPLATE: &str =
"table({name}) \\{\n{pks} {{ if pks }} ---\n{{ endif }}{fks}{nns}{others}}\n";

static VIEW_TEMPLATE: &str =
"view({name}{{ if materialized}}, $materialized=true{{ endif }}) \\{\n{columns}}\n";
Expand Down Expand Up @@ -154,7 +156,7 @@ impl<'a> PlantUmlDefaultGenerator<'a> {
others,
}
}
fn entity_render(&self, tbl: &Table) -> Result<String, crate::SqlantError> {
fn entity_render(&self, tbl: &Table, conceptual: bool) -> Result<String, crate::SqlantError> {
let sorted_columns = Self::sort_columns(&tbl.columns);

let columns_render = |columns: Vec<Arc<TableColumn>>| -> Result<String, _> {
Expand All @@ -178,19 +180,28 @@ impl<'a> PlantUmlDefaultGenerator<'a> {
},
)?)
};

let columns_render_if_not_conceptual =
|columns: Vec<Arc<TableColumn>>| -> Result<String, _> {
if !conceptual {
return columns_render(columns);
}
Ok(String::default())
};

Ok(self.str_templates.render(
"ent",
&SEntity {
pks: columns_render(sorted_columns.pks)?,
fks: columns_render(sorted_columns.fks)?,
nns: columns_render(sorted_columns.nns)?,
others: columns_render(sorted_columns.others)?,
pks: columns_render_if_not_conceptual(sorted_columns.pks)?,
fks: columns_render_if_not_conceptual(sorted_columns.fks)?,
nns: columns_render_if_not_conceptual(sorted_columns.nns)?,
others: columns_render_if_not_conceptual(sorted_columns.others)?,
name: tbl.name.clone(),
},
)?)
}

fn view_render(&self, view: &View) -> Result<String, crate::SqlantError> {
fn view_render(&self, view: &View, conceptual: bool) -> Result<String, crate::SqlantError> {
let columns_render = |columns: Vec<Arc<TableColumn>>| -> Result<String, _> {
Ok::<std::string::String, crate::SqlantError>(columns.iter().try_fold(
String::new(),
Expand All @@ -212,10 +223,18 @@ impl<'a> PlantUmlDefaultGenerator<'a> {
},
)?)
};
let columns_render_if_not_conceptual =
|columns: Vec<Arc<TableColumn>>| -> Result<String, _> {
if !conceptual {
return columns_render(columns);
}
Ok(String::default())
};

Ok(self.str_templates.render(
"view",
&SView {
columns: columns_render(view.columns.clone())?,
columns: columns_render_if_not_conceptual(view.columns.clone())?,
name: view.name.clone(),
materialized: view.materialized,
},
Expand All @@ -232,12 +251,12 @@ impl ViewGenerator for PlantUmlDefaultGenerator<'_> {
let entities: Vec<String> = sql_erd
.tables
.iter()
.map(|tbl| self.entity_render(tbl))
.map(|tbl| self.entity_render(tbl, opts.conceptual_diagram))
.collect::<Result<Vec<String>, crate::SqlantError>>()?;
let views: Vec<String> = sql_erd
.views
.iter()
.map(|view| self.view_render(view))
.map(|view| self.view_render(view, opts.conceptual_diagram))
.collect::<Result<Vec<String>, crate::SqlantError>>()?;

let foreign_keys: Vec<String> = sql_erd
Expand Down