add generator picker
This commit is contained in:
parent
1fa7c7bbc8
commit
dc68f88f9d
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -304,8 +304,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -601,6 +603,7 @@ dependencies = [
|
||||
"base64",
|
||||
"chrono",
|
||||
"fake",
|
||||
"getrandom",
|
||||
"gloo",
|
||||
"js-sys",
|
||||
"lazy-regex",
|
||||
|
@ -16,6 +16,7 @@ gloo = "0.8"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
fake = "2.5"
|
||||
rand = "0.8"
|
||||
getrandom = { version = "0.2.8", features = ["js"] }
|
||||
chrono = "0.4.23"
|
||||
|
||||
[dependencies.zip]
|
||||
|
136
src/app.rs
136
src/app.rs
@ -1,3 +1,4 @@
|
||||
use std::cell::RefCell;
|
||||
use std::io::Cursor;
|
||||
use std::collections::{HashMap, self};
|
||||
use std::rc::Rc;
|
||||
@ -9,24 +10,32 @@ use web_sys::{DragEvent, Event, FileList, HtmlInputElement, MouseEvent};
|
||||
use yew::html::TargetCast;
|
||||
use yew::{html, Callback, Component, Context, Html};
|
||||
|
||||
use crate::generate_sql::{SQLValueGuess, generate_table_guessess};
|
||||
use crate::magicdraw_parser::{parse_project, SQLTableCollection, SQLTable};
|
||||
use crate::components::sql_column_info::SQLTableColumnInfo;
|
||||
|
||||
const COLLECTION_STORE_KEY: &str = "current_collection";
|
||||
const DEFAULT_ROWS_PER_TABLE: u32 = 20;
|
||||
|
||||
pub enum Msg {
|
||||
Noop,
|
||||
Loaded(String, Vec<u8>),
|
||||
UploadProject(File),
|
||||
UpdateCurrentProject(Option<SQLTableCollection>),
|
||||
UpdateGenarator(String, SQLValueGuess),
|
||||
ShowNextTable,
|
||||
ShowPrevTable
|
||||
ShowPrevTable,
|
||||
AllGoodConfirmation,
|
||||
GenerateSQL,
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
active_readers: HashMap<String, FileReader>,
|
||||
current_collection: Option<Vec<Rc<SQLTable>>>,
|
||||
currently_shown_table: usize
|
||||
current_guessess: Vec<Rc<RefCell<HashMap<String, SQLValueGuess>>>>,
|
||||
currently_shown_table: usize,
|
||||
all_good_confirmed: bool,
|
||||
generated_sql: Option<String>
|
||||
}
|
||||
|
||||
impl Component for App {
|
||||
@ -34,15 +43,24 @@ impl Component for App {
|
||||
type Properties = ();
|
||||
|
||||
fn create(_ctx: &Context<Self>) -> Self {
|
||||
let mut current_guessess = vec![];
|
||||
let mut current_collection = None;
|
||||
if let Ok(collection) = LocalStorage::get::<SQLTableCollection>("current_collection") {
|
||||
for table in &collection.tables {
|
||||
let guess = generate_table_guessess(table);
|
||||
current_guessess.push(Rc::new(RefCell::new(guess)));
|
||||
}
|
||||
|
||||
current_collection = Some(collection.tables.into_iter().map(Rc::new).collect());
|
||||
}
|
||||
|
||||
Self {
|
||||
active_readers: HashMap::default(),
|
||||
current_collection,
|
||||
currently_shown_table: 0
|
||||
currently_shown_table: 0,
|
||||
all_good_confirmed: true, // TODO: make this false, by default
|
||||
generated_sql: None,
|
||||
current_guessess
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,6 +102,14 @@ impl Component for App {
|
||||
Msg::UpdateCurrentProject(collection) => {
|
||||
if let Some(collection) = collection {
|
||||
LocalStorage::set(COLLECTION_STORE_KEY, &collection).unwrap();
|
||||
self.currently_shown_table = 0;
|
||||
self.all_good_confirmed = false;
|
||||
self.generated_sql = None;
|
||||
self.current_guessess = vec![];
|
||||
for table in &collection.tables {
|
||||
let guess = generate_table_guessess(table);
|
||||
self.current_guessess.push(Rc::new(RefCell::new(guess)));
|
||||
}
|
||||
self.current_collection = Some(collection.tables.into_iter().map(Rc::new).collect());
|
||||
} else {
|
||||
LocalStorage::delete(COLLECTION_STORE_KEY);
|
||||
@ -106,17 +132,49 @@ impl Component for App {
|
||||
}
|
||||
false
|
||||
},
|
||||
Msg::AllGoodConfirmation => {
|
||||
self.all_good_confirmed = true;
|
||||
true
|
||||
},
|
||||
Msg::UpdateGenarator(column, generator) => {
|
||||
console_dbg!(column, generator);
|
||||
let mut guessess = self.current_guessess[self.currently_shown_table].borrow_mut();
|
||||
let entry = guessess.get_mut(&column).unwrap();
|
||||
*entry = generator;
|
||||
true
|
||||
},
|
||||
Msg::GenerateSQL => {
|
||||
false
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn view(&self, ctx: &Context<Self>) -> Html {
|
||||
html! {
|
||||
<main class="flex-col 4rem center">
|
||||
<p class="text-3xl text-center">{ "🪄 MagicDraw SQL Data Generator" }</p>
|
||||
{ self.show_step1(ctx) }
|
||||
if self.current_collection.is_some() {
|
||||
{ self.show_step2(ctx) }
|
||||
if self.all_good_confirmed {
|
||||
{ self.show_step3(ctx) }
|
||||
if self.generated_sql.is_some() {
|
||||
{ self.show_step4(ctx) }
|
||||
}
|
||||
}
|
||||
}
|
||||
</main>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl App {
|
||||
fn show_step1(&self, ctx: &Context<Self>) -> Html {
|
||||
let prevent_default_cb = Callback::from(|event: DragEvent| {
|
||||
event.prevent_default();
|
||||
});
|
||||
|
||||
html! {
|
||||
<main class="flex-col 4rem center">
|
||||
<p class="text-3xl text-center">{ "🪄 MagicDraw SQL Data Generator" }</p>
|
||||
<div>
|
||||
<p class="text-2xl mt-2rem pb-1rem">
|
||||
<span>{ "1. Upload " }</span>
|
||||
@ -151,45 +209,77 @@ impl Component for App {
|
||||
/>
|
||||
<p class="text-amber300">{ "NOTE: This relies on the fact, that you have a .dll script configured" }</p>
|
||||
</div>
|
||||
if let Some(collection) = &self.current_collection {
|
||||
}
|
||||
}
|
||||
|
||||
fn show_step2(&self, ctx: &Context<Self>) -> Html {
|
||||
let collection = self.current_collection.as_ref().unwrap();
|
||||
|
||||
html! {
|
||||
<div>
|
||||
<p class="text-2xl mt-2rem">{ "2. Make sure everything looks 👌" }</p>
|
||||
<div class="mb-0.5rem gap-3 flex flex-row items-center">
|
||||
<button
|
||||
class="p-0.5rem btn-white"
|
||||
onclick={ctx.link().callback(move |_: MouseEvent| {
|
||||
Msg::ShowPrevTable
|
||||
})}
|
||||
onclick={ctx.link().callback(move |_: MouseEvent| { Msg::ShowPrevTable })}
|
||||
>
|
||||
{ "< Previous" }
|
||||
</button>
|
||||
<div> { self.currently_shown_table + 1 } { " / " } { collection.len() } </div>
|
||||
<button
|
||||
class="p-0.5rem btn-white"
|
||||
onclick={ctx.link().callback(move |_: MouseEvent| {
|
||||
Msg::ShowNextTable
|
||||
})}
|
||||
onclick={ctx.link().callback(move |_: MouseEvent| { Msg::ShowNextTable })}
|
||||
>
|
||||
{ "Next >" }
|
||||
</button>
|
||||
</div>
|
||||
{ Self::show_table(collection[self.currently_shown_table].clone()) }
|
||||
<button class="display-block p-1rem mt-1rem btn-emerald">{ "All good?" }</button>
|
||||
<SQLTableColumnInfo
|
||||
table={collection[self.currently_shown_table].clone()}
|
||||
guessess={self.current_guessess[self.currently_shown_table].clone()}
|
||||
onchange={ctx.link().callback(|(column_name, generator)| {
|
||||
Msg::UpdateGenarator(column_name, generator)
|
||||
})}
|
||||
/>
|
||||
<button
|
||||
class="display-block p-1rem mt-1rem btn-emerald"
|
||||
onclick={ctx.link().callback(move |_: MouseEvent| { Msg::AllGoodConfirmation })}
|
||||
>{ "All good?" }</button>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
fn show_step3(&self, ctx: &Context<Self>) -> Html {
|
||||
html! {
|
||||
<div>
|
||||
<p class="text-2xl mt-2rem">{ "3. Copy & Paste" }</p>
|
||||
<p class="text-2xl mt-2rem">{ "3. Final settings" }</p>
|
||||
<label for="gen-amount-input">
|
||||
{ "Entries per table: " }
|
||||
</label>
|
||||
<input
|
||||
id="gen-amount-input"
|
||||
class="rounded items-center p-0.3rem bg-dark800 text-light100 w-5rem b-0"
|
||||
value={DEFAULT_ROWS_PER_TABLE.to_string()}
|
||||
type="number"
|
||||
/>
|
||||
|
||||
<button
|
||||
class="block mt-1rem p-1rem btn-emerald"
|
||||
>
|
||||
{ "Generate" }
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</main>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl App {
|
||||
|
||||
fn show_table(table: Rc<SQLTable>) -> Html {
|
||||
html!{
|
||||
<SQLTableColumnInfo table={table} />
|
||||
fn show_step4(&self, ctx: &Context<Self>) -> Html {
|
||||
let sql = self.generated_sql.as_ref().unwrap();
|
||||
html! {
|
||||
<div>
|
||||
<p class="text-2xl mt-2rem">{ "4. Copy & Paste" }</p>
|
||||
<code>
|
||||
{ sql }
|
||||
</code>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
|
191
src/components/generator_picker.rs
Normal file
191
src/components/generator_picker.rs
Normal file
@ -0,0 +1,191 @@
|
||||
use std::{collections::HashMap, str::FromStr};
|
||||
|
||||
use gloo::console::console_dbg;
|
||||
use yew::{Html, html, Callback, TargetCast, AttrValue};
|
||||
use web_sys::{Event, HtmlInputElement};
|
||||
|
||||
use crate::{generate_sql::{SQLValueGuess, SQLStringValueGuess, SQLBoolValueGuess, SQLTimeValueGuess, SQLIntValueGuess}, magicdraw_parser::{SQLColumn, SQLCheckConstraint}};
|
||||
|
||||
fn show_dropdown_picker(
|
||||
selected: &str,
|
||||
options: &[AttrValue],
|
||||
onchange: Callback<String>
|
||||
) -> Html {
|
||||
html!{
|
||||
<select onchange={Callback::from(move |e: Event| {
|
||||
let value = e.target_unchecked_into::<HtmlInputElement>().value();
|
||||
onchange.emit(value);
|
||||
})}>
|
||||
{
|
||||
options.iter().map(|value| {
|
||||
html! { <option selected={value.eq(&selected)} value={value.clone()}>{ value }</option> }
|
||||
}).collect::<Html>()
|
||||
}
|
||||
</select>
|
||||
}
|
||||
}
|
||||
|
||||
fn show_enum_dropdown<T: PartialEq + Clone + 'static>(
|
||||
selected: &T,
|
||||
options: HashMap<AttrValue, T>,
|
||||
onchange: Callback<T>
|
||||
) -> Html {
|
||||
let keys = options.keys().map(AttrValue::clone).collect::<Vec<_>>();
|
||||
let guess_str = options.iter().find(|(_, v)| v.eq(&selected)).unwrap().0.clone();
|
||||
|
||||
show_dropdown_picker(&guess_str, &keys, onchange.reform(move |value_str: String| {
|
||||
options.get(value_str.as_str()).unwrap().clone()
|
||||
}))
|
||||
}
|
||||
|
||||
fn show_range_picker<T: FromStr + ToString + Clone + 'static>(
|
||||
min: T,
|
||||
max: T,
|
||||
default_min: T,
|
||||
default_max: T,
|
||||
onchange: Callback<(T, T)>,
|
||||
) -> Html {
|
||||
|
||||
let onchange_min = {
|
||||
let onchange = onchange.clone();
|
||||
let default_min = default_min.clone();
|
||||
let max = max.clone();
|
||||
Callback::from(move |e: Event| {
|
||||
let value = e.target_unchecked_into::<HtmlInputElement>().value();
|
||||
let min_value = value.parse().unwrap_or(default_min.clone());
|
||||
onchange.emit((min_value, max.clone()))
|
||||
})
|
||||
};
|
||||
|
||||
let onchange_max = {
|
||||
let onchange = onchange.clone();
|
||||
let default_max = default_max.clone();
|
||||
let min = min.clone();
|
||||
Callback::from(move |e: Event| {
|
||||
let value = e.target_unchecked_into::<HtmlInputElement>().value();
|
||||
let max_value = value.parse().unwrap_or(default_max.clone());
|
||||
onchange.emit((min.clone(), max_value))
|
||||
})
|
||||
};
|
||||
|
||||
html! {
|
||||
<div class="flex flex-row">
|
||||
<input
|
||||
value={min.to_string()}
|
||||
class="w-5rem"
|
||||
type="number"
|
||||
placeholder={default_min.to_string()}
|
||||
onchange={onchange_min}
|
||||
/>
|
||||
<div class="ml-1 mr-1">{ ".." }</div>
|
||||
<input
|
||||
value={max.to_string()}
|
||||
class="w-5rem"
|
||||
type="number"
|
||||
placeholder={default_max.to_string()}
|
||||
onchange={onchange_max}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generator_picker(
|
||||
column: &SQLColumn,
|
||||
value: &SQLValueGuess,
|
||||
onchange: Callback<SQLValueGuess>
|
||||
) -> Html {
|
||||
// TODO: Refacotr 'time', 'datetime', and 'date'. They are very similar
|
||||
match value {
|
||||
SQLValueGuess::Int(guess) => {
|
||||
if column.primary_key {
|
||||
return html!("Auto increment")
|
||||
}
|
||||
|
||||
let mut min = 0;
|
||||
let mut max = 0;
|
||||
if let SQLIntValueGuess::Range(range_min, range_max) = guess {
|
||||
min = *range_min;
|
||||
max = *range_max;
|
||||
}
|
||||
|
||||
// TODO: Disallow entering floating point numbers
|
||||
show_range_picker(min, max, 0, 100, onchange.reform(|(min, max)| {
|
||||
SQLValueGuess::Int(SQLIntValueGuess::Range(min, max))
|
||||
}))
|
||||
},
|
||||
SQLValueGuess::Float(min, max) => {
|
||||
show_range_picker(*min, *max, 0.0, 100.0, onchange.reform(|(min, max)| {
|
||||
SQLValueGuess::Float(min, max)
|
||||
}))
|
||||
},
|
||||
SQLValueGuess::Date(guess) => {
|
||||
let options = HashMap::from([
|
||||
("Now".into() , SQLTimeValueGuess::Now),
|
||||
("Future".into(), SQLTimeValueGuess::Future),
|
||||
("Past".into() , SQLTimeValueGuess::Past),
|
||||
]);
|
||||
|
||||
show_enum_dropdown(guess, options, onchange.reform(|enum_value| {
|
||||
SQLValueGuess::Date(enum_value)
|
||||
}))
|
||||
},
|
||||
SQLValueGuess::Time(guess) => {
|
||||
let options = HashMap::from([
|
||||
("Now".into() , SQLTimeValueGuess::Now),
|
||||
("Future".into(), SQLTimeValueGuess::Future),
|
||||
("Past".into() , SQLTimeValueGuess::Past),
|
||||
]);
|
||||
|
||||
show_enum_dropdown(guess, options, onchange.reform(|enum_value| {
|
||||
SQLValueGuess::Time(enum_value)
|
||||
}))
|
||||
},
|
||||
SQLValueGuess::Datetime(guess) => {
|
||||
let options = HashMap::from([
|
||||
("Now".into() , SQLTimeValueGuess::Now),
|
||||
("Future".into(), SQLTimeValueGuess::Future),
|
||||
("Past".into() , SQLTimeValueGuess::Past),
|
||||
]);
|
||||
|
||||
show_enum_dropdown(guess, options, onchange.reform(|enum_value| {
|
||||
SQLValueGuess::Datetime(enum_value)
|
||||
}))
|
||||
}
|
||||
SQLValueGuess::Bool(guess) => {
|
||||
let options = HashMap::from([
|
||||
("Random".into(), SQLBoolValueGuess::Random),
|
||||
("True".into() , SQLBoolValueGuess::True),
|
||||
("False".into() , SQLBoolValueGuess::False),
|
||||
]);
|
||||
|
||||
show_enum_dropdown(guess, options, onchange.reform(|enum_value| {
|
||||
SQLValueGuess::Bool(enum_value)
|
||||
}))
|
||||
},
|
||||
SQLValueGuess::String(max_size, guess) => {
|
||||
if let Some(constraint) = &column.check_constraint {
|
||||
if let SQLCheckConstraint::OneOf(_) = constraint {
|
||||
return html!("Random Enum");
|
||||
}
|
||||
}
|
||||
|
||||
let options = HashMap::from([
|
||||
("Lorem Ipsum".into() , SQLStringValueGuess::LoremIpsum),
|
||||
("First Name".into() , SQLStringValueGuess::FirstName),
|
||||
("Last Name".into() , SQLStringValueGuess::LastName),
|
||||
("Full Name".into() , SQLStringValueGuess::FullName),
|
||||
("Empty".into() , SQLStringValueGuess::Empty),
|
||||
("Phone number".into() , SQLStringValueGuess::PhoneNumber),
|
||||
("City name".into() , SQLStringValueGuess::CityName),
|
||||
("Address".into() , SQLStringValueGuess::Address),
|
||||
("Email".into() , SQLStringValueGuess::Email),
|
||||
("URL".into() , SQLStringValueGuess::URL),
|
||||
]);
|
||||
|
||||
let max_size = *max_size;
|
||||
show_enum_dropdown(guess, options, onchange.reform(move |enum_value| {
|
||||
SQLValueGuess::String(max_size, enum_value)
|
||||
}))
|
||||
},
|
||||
}
|
||||
}
|
@ -1 +1,2 @@
|
||||
pub mod sql_column_info;
|
||||
pub mod generator_picker;
|
||||
|
@ -1,12 +1,14 @@
|
||||
use std::rc::Rc;
|
||||
use std::{rc::Rc, collections::HashMap, cell::RefCell};
|
||||
|
||||
use yew::{Properties, html, function_component, Html};
|
||||
use yew::{Properties, html, function_component, Html, Callback};
|
||||
|
||||
use crate::magicdraw_parser::SQLTable;
|
||||
use crate::{magicdraw_parser::SQLTable, generate_sql::SQLValueGuess, components::generator_picker::generator_picker};
|
||||
|
||||
#[derive(Properties, PartialEq)]
|
||||
pub struct SQLTableColumnInfoProps {
|
||||
pub table: Rc<SQLTable>
|
||||
pub table: Rc<SQLTable>,
|
||||
pub guessess: Rc<RefCell<HashMap<String, SQLValueGuess>>>,
|
||||
pub onchange: Callback<(String, SQLValueGuess)>
|
||||
}
|
||||
|
||||
const CHECK_MARK: &str = "✔️";
|
||||
@ -22,6 +24,9 @@ pub fn SQLTableColumnInfo(props: &SQLTableColumnInfoProps) -> Html {
|
||||
|
||||
let rows = table.columns.iter()
|
||||
.map(|col| {
|
||||
let guessess = &props.guessess.borrow();
|
||||
let generator = guessess.get(&col.name);
|
||||
|
||||
let foreign_key;
|
||||
if let Some((table_name, prop_name)) = &col.foreign_key {
|
||||
foreign_key = format!("{} {}", table_name, prop_name);
|
||||
@ -29,10 +34,19 @@ pub fn SQLTableColumnInfo(props: &SQLTableColumnInfoProps) -> Html {
|
||||
foreign_key = CROSS_MARK.into();
|
||||
}
|
||||
|
||||
let name = col.name.clone();
|
||||
let onchange = props.onchange.reform(move |value: SQLValueGuess| (name.clone(), value));
|
||||
html! {
|
||||
<tr>
|
||||
<td> { &col.name } </td>
|
||||
<td> { &col.sql_type } </td>
|
||||
<td> {
|
||||
if let Some(generator) = generator {
|
||||
generator_picker(col, generator, onchange)
|
||||
} else {
|
||||
html!(CROSS_MARK)
|
||||
}
|
||||
} </td>
|
||||
<td> { bool_to_mark(col.primary_key) } </td>
|
||||
<td> { bool_to_mark(col.nullable) } </td>
|
||||
<td> { foreign_key } </td>
|
||||
@ -47,12 +61,11 @@ pub fn SQLTableColumnInfo(props: &SQLTableColumnInfoProps) -> Html {
|
||||
border="solid dark100 0.2rem collapse"
|
||||
>
|
||||
<p class="text-center"> { &table.name } </p>
|
||||
<table
|
||||
border="solid dark100 t-0.2rem collapse"
|
||||
>
|
||||
<table border="solid dark100 t-0.2rem collapse">
|
||||
<tr>
|
||||
<th> { "Column" } </th>
|
||||
<th> { "Type" } </th>
|
||||
<th> { "Generator" } </th>
|
||||
<th> { "Primary?" } </th>
|
||||
<th> { "Nullable?" } </th>
|
||||
<th> { "Foreign key?" } </th>
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::{rc::Rc, collections::HashSet};
|
||||
use std::{rc::Rc, collections::{HashSet, HashMap}};
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use rand::{seq::SliceRandom, Rng, rngs::ThreadRng};
|
||||
@ -9,20 +9,20 @@ use crate::magicdraw_parser::{SQLTable, SQLColumn, SQLType, SQLCheckConstraint};
|
||||
|
||||
const INDENT: &str = " ";
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum SQLIntValueGuess {
|
||||
Range(i32, i32),
|
||||
AutoIncrement
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum SQLTimeValueGuess {
|
||||
Now,
|
||||
Future,
|
||||
Past
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum SQLStringValueGuess {
|
||||
LoremIpsum,
|
||||
FirstName,
|
||||
@ -37,14 +37,14 @@ pub enum SQLStringValueGuess {
|
||||
RandomEnum(Vec<String>),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum SQLBoolValueGuess {
|
||||
True,
|
||||
False,
|
||||
Random,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum SQLValueGuess {
|
||||
Int(SQLIntValueGuess),
|
||||
Date(SQLTimeValueGuess),
|
||||
@ -58,7 +58,7 @@ pub enum SQLValueGuess {
|
||||
// TODO: Check primary key constraint
|
||||
pub fn generate_fake_entries(
|
||||
tables: &[Rc<SQLTable>],
|
||||
value_guessess: &Vec<Vec<SQLValueGuess>>,
|
||||
value_guessess: &Vec<HashMap<&str, SQLValueGuess>>,
|
||||
rows_per_table: u32
|
||||
) -> Result<String> {
|
||||
let mut lines = vec![];
|
||||
@ -96,9 +96,9 @@ pub fn generate_fake_entries(
|
||||
for (table_idx, table) in tables.iter().enumerate() {
|
||||
let entries = &mut all_entries[table_idx];
|
||||
|
||||
for (column_idx, column) in table.columns.iter().enumerate() {
|
||||
for column in &table.columns {
|
||||
let mut auto_increment_counter = 0;
|
||||
let value_guess = &value_guessess[table_idx][column_idx];
|
||||
let value_guess = value_guessess[table_idx].get(column.name.as_str()).expect("Failed to get column guess");
|
||||
for entry_idx in 0..(rows_per_table as usize) {
|
||||
if let Some(_) = &column.foreign_key {
|
||||
entries_with_foreign_keys.insert((table_idx, entry_idx));
|
||||
@ -358,8 +358,9 @@ pub fn generate_guess(column: &SQLColumn) -> SQLValueGuess {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_table_guessess(table: &SQLTable) -> Vec<SQLValueGuess> {
|
||||
pub fn generate_table_guessess(table: &SQLTable) -> HashMap<String, SQLValueGuess> {
|
||||
table.columns.iter()
|
||||
.map(|column| generate_guess(column))
|
||||
.filter(|column| column.foreign_key.is_none())
|
||||
.map(|column| (column.name.clone(), generate_guess(column)))
|
||||
.collect()
|
||||
}
|
||||
|
12
styles.css
12
styles.css
@ -7,3 +7,15 @@
|
||||
button {
|
||||
border: 0
|
||||
}
|
||||
|
||||
/* Chrome, Safari, Edge, Opera */
|
||||
input::-webkit-outer-spin-button,
|
||||
input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
input[type=number] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user