diff --git a/src/bin/cli/main.rs b/src/bin/cli/main.rs index 2f6ca5b..e5c4456 100644 --- a/src/bin/cli/main.rs +++ b/src/bin/cli/main.rs @@ -30,9 +30,6 @@ enum Commands { Discover { /// Schema to discover, it defaults to `public` in postures. schema: Option, - - #[arg(short = 'o', long)] - output: Option, }, } @@ -51,9 +48,7 @@ async fn main() -> Result<()> { // matches just as you would the top level cmd let result = match &cli.command { Commands::Query { sql } => sql::handle_query(url, sql).await, - Commands::Discover { schema, output } => { - sql::discover_scheme(url, schema.to_owned(), output.to_owned()).await - } + Commands::Discover { schema } => sql::discover_scheme(url, schema.to_owned()).await, }; if let Err(err) = result { diff --git a/src/sql.rs b/src/sql.rs index af8509f..90728a2 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -1,7 +1,3 @@ -use std::fs::File; -use std::io; -use std::path::Path; - use clap::ValueEnum; use sea_schema::postgres::discovery::SchemaDiscovery; use sqlx::PgPool; @@ -9,7 +5,7 @@ use url::Url; use crate::error::{Error, Result}; -use self::schema::{DataModel, Schema}; +use self::schema::SchemaDefinition; mod postgres; mod schema; @@ -47,11 +43,7 @@ pub async fn handle_query(url: String, query: &String) -> Result<()> { return Ok(()); } -pub async fn discover_scheme( - url: String, - schema: Option, - output: Option, -) -> Result<()> { +pub async fn discover_scheme(url: String, schema: Option) -> Result<()> { let (_, db_name) = get_connector(&url).await?; let schema_discovery = match db_name.as_str() { @@ -70,17 +62,9 @@ pub async fn discover_scheme( let schema = schema_discovery.discover().await?; - let mut data_model = DataModel::new(); - data_model - .schemas - .insert(schema.schema.to_owned(), Schema::from(schema)); + let schema_definition = SchemaDefinition::from(schema); - let mut buffer: Box = match output { - Some(path) => Box::new(File::create(Path::new(&path))?), - None => Box::new(io::stdout()), - }; - - data_model.write(&mut buffer)?; + println!("{}", schema_definition); Ok(()) } diff --git a/src/sql/schema.rs b/src/sql/schema.rs index 10fc03c..ffad5b3 100644 --- a/src/sql/schema.rs +++ b/src/sql/schema.rs @@ -2,62 +2,40 @@ use heck::ToTitleCase; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fmt; -use std::io::Write; -use toml_edit::visit_mut::VisitMut; +use toml_edit::visit_mut::{visit_table_like_kv_mut, VisitMut}; +use toml_edit::{DocumentMut, Item, KeyMut, Table as TomlTable, Value}; -use sea_schema::postgres::def as sea_schema_def; - -use crate::error; +use sea_schema::postgres::def::{ColumnInfo, ColumnType, References, Schema, TableDef}; struct InlineTableFix; -// the toml serializer doesn't generate inline tables by default impl VisitMut for InlineTableFix { - fn visit_table_like_kv_mut( - &mut self, - mut key: toml_edit::KeyMut<'_>, - node: &mut toml_edit::Item, - ) { - // add the keys of the tables that needs to be inline here + fn visit_table_like_kv_mut(&mut self, mut key: KeyMut<'_>, node: &mut Item) { if ["reference", "type"].contains(&key.get()) { - if let toml_edit::Item::Table(table) = node { + // Turn the table into an inline table. + if let Item::Table(table) = node { // Turn the table into an inline table. - let table = std::mem::replace(table, toml_edit::Table::new()); + let table = std::mem::replace(table, TomlTable::new()); let inline_table = table.into_inline_table(); key.fmt(); - *node = toml_edit::Item::Value(toml_edit::Value::InlineTable(inline_table)); + *node = Item::Value(Value::InlineTable(inline_table)); } } - toml_edit::visit_mut::visit_table_like_kv_mut(self, key, node); + visit_table_like_kv_mut(self, key, node); } } #[derive(Serialize, Deserialize, Debug)] -pub struct DataModel { - #[serde(flatten)] - pub schemas: HashMap, +pub struct SchemaDefinition { + /// Name of the schema, and table associated + pub tables: HashMap, } -impl DataModel { - pub fn new() -> Self { - Self { - schemas: HashMap::new(), - } - } -} - -impl DataModel { - pub fn write(&self, buffer: &mut T) -> error::Result<()> { - buffer.write_all(self.to_string().as_bytes())?; - Ok(()) - } -} - -impl fmt::Display for DataModel { +impl fmt::Display for SchemaDefinition { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let toml = toml::to_string_pretty(self).map_err(|_| fmt::Error)?; - let mut document: toml_edit::DocumentMut = toml.parse().map_err(|_| fmt::Error)?; + let mut document: DocumentMut = toml.parse().map_err(|_| fmt::Error)?; let mut visitor = InlineTableFix; visitor.visit_document_mut(&mut document); @@ -66,14 +44,8 @@ impl fmt::Display for DataModel { } } -#[derive(Serialize, Deserialize, Debug)] -pub struct Schema { - #[serde(flatten)] - pub tables: HashMap, -} - -impl From for Schema { - fn from(schema: sea_schema_def::Schema) -> Self { +impl From for SchemaDefinition { + fn from(schema: Schema) -> Self { let mut tables: HashMap = HashMap::new(); for table in schema.tables { @@ -86,14 +58,17 @@ impl From for Schema { #[derive(Serialize, Deserialize, Debug)] pub struct Table { + /// real name of the table + name: String, /// Default is capitalized name display_name: Option, columns: Vec, } -impl From for Table { - fn from(table: sea_schema_def::TableDef) -> Self { +impl From for Table { + fn from(table: TableDef) -> Self { Self { + name: table.info.name.to_owned(), display_name: Some(table.info.name.to_owned().to_title_case()), columns: table .columns @@ -121,14 +96,14 @@ impl From for Table { pub struct Column { name: String, #[serde(rename = "type")] - col_type: sea_schema_def::ColumnType, + col_type: ColumnType, default: Option, not_null: bool, reference: Option, } -impl From for Column { - fn from(col: sea_schema_def::ColumnInfo) -> Self { +impl From for Column { + fn from(col: ColumnInfo) -> Self { Self { name: col.name, col_type: col.col_type, @@ -146,8 +121,8 @@ pub struct ColumnReference { label: Option, } -impl From for ColumnReference { - fn from(reference: sea_schema_def::References) -> Self { +impl From for ColumnReference { + fn from(reference: References) -> Self { Self { table: reference.table, identity: reference.foreign_columns[0].to_owned(),