diff --git a/src/lib.rs b/src/lib.rs index de6829df..bddfe71c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,8 +34,9 @@ use crate::{ QueryAsIf, QueryAsIfKind, ResultRow, }, valve::{ - ValveColumnConfig, ValveDatatypeConfig, ValveError, ValveRow, ValveSpecialConfig, - ValveTableConfig, + ValveColumnConfig, ValveDatatypeConfig, ValveError, ValveForeignConstraint, ValveRow, + ValveSpecialConfig, ValveTableConfig, ValveTableConstraints, ValveTreeConstraint, + ValveUnderConstraint, }, valve_grammar::StartParser, }; @@ -218,7 +219,7 @@ pub fn read_config_files( HashMap, HashMap, SerdeMap, - SerdeMap, + ValveTableConstraints, Vec, HashMap>, HashMap>, @@ -579,12 +580,7 @@ pub fn read_config_files( } // Initialize the constraints config: - let mut constraints_config = SerdeMap::new(); - constraints_config.insert(String::from("foreign"), SerdeValue::Object(SerdeMap::new())); - constraints_config.insert(String::from("unique"), SerdeValue::Object(SerdeMap::new())); - constraints_config.insert(String::from("primary"), SerdeValue::Object(SerdeMap::new())); - constraints_config.insert(String::from("tree"), SerdeValue::Object(SerdeMap::new())); - constraints_config.insert(String::from("under"), SerdeValue::Object(SerdeMap::new())); + let mut table_constraints = ValveTableConstraints::default(); for table_name in tables_config.keys().cloned().collect::>() { let optional_path = tables_config @@ -669,8 +665,8 @@ pub fn read_config_files( .get_mut(&table_name) .and_then(|t| Some(t.column_order = column_order)); - // Populate the constraints config: - let table_constraints = get_table_constraints( + // Populate the table constraints for this table: + let (primaries, uniques, foreigns, trees, unders) = get_table_constraints( &tables_config, &datatypes_config, parser, @@ -678,13 +674,19 @@ pub fn read_config_files( &pool, ); - for constraint_type in vec!["foreign", "unique", "primary", "tree", "under"] { - let table_constraints = table_constraints.get(constraint_type).unwrap().clone(); - constraints_config - .get_mut(constraint_type) - .and_then(|o| o.as_object_mut()) - .and_then(|o| o.insert(table_name.to_string(), table_constraints)); - } + table_constraints + .primary + .insert(table_name.to_string(), primaries); + table_constraints + .unique + .insert(table_name.to_string(), uniques); + table_constraints + .foreign + .insert(table_name.to_string(), foreigns); + table_constraints.tree.insert(table_name.to_string(), trees); + table_constraints + .under + .insert(table_name.to_string(), unders); } // Manually add the messsage table config: @@ -903,7 +905,7 @@ pub fn read_config_files( // table list that is returned. .filter(|m| m != "history" && m != "message") .collect(), - &constraints_config, + &table_constraints, ); // Finally, return all the configs: @@ -912,7 +914,7 @@ pub fn read_config_files( tables_config, datatypes_config, rules_config, - constraints_config, + table_constraints, sorted_tables, table_dependencies_in, table_dependencies_out, @@ -2895,7 +2897,7 @@ pub fn local_sql_syntax(pool: &AnyPool, sql: &String) -> String { /// list that is returned. pub fn verify_table_deps_and_sort( table_list: &Vec, - constraints: &SerdeMap, + constraints: &ValveTableConstraints, ) -> ( Vec, HashMap>, @@ -2934,16 +2936,15 @@ pub fn verify_table_deps_and_sort( } // Check for intra-table cycles: - let trees = constraints.get("tree").and_then(|t| t.as_object()).unwrap(); + let trees = &constraints.tree; for table_name in table_list { let mut dependency_graph = DiGraphMap::<&str, ()>::new(); - let table_trees = trees.get(table_name).and_then(|t| t.as_array()).unwrap(); + let table_trees = trees.get(table_name).unwrap(); for tree in table_trees { - let tree = tree.as_object().unwrap(); - let child = tree.get("child").and_then(|c| c.as_str()).unwrap(); - let parent = tree.get("parent").and_then(|p| p.as_str()).unwrap(); - let c_index = dependency_graph.add_node(child); - let p_index = dependency_graph.add_node(parent); + let child = &tree.child; + let parent = &tree.parent; + let c_index = dependency_graph.add_node(&child); + let p_index = dependency_graph.add_node(&parent); dependency_graph.add_edge(c_index, p_index, ()); } match get_cycles(&dependency_graph) { @@ -2957,12 +2958,8 @@ pub fn verify_table_deps_and_sort( let end_index = cycle.len() - 1; for (i, child) in cycle.iter().enumerate() { if i < end_index { - let dep = table_trees - .iter() - .find(|d| d.get("child").unwrap().as_str() == Some(child)) - .and_then(|d| d.as_object()) - .unwrap(); - let parent = dep.get("parent").unwrap(); + let dep = table_trees.iter().find(|d| d.child == *child).unwrap(); + let parent = &dep.parent; message.push_str( format!("tree({}) references {}", child, parent).as_str(), ); @@ -2979,40 +2976,28 @@ pub fn verify_table_deps_and_sort( } // Check for inter-table cycles: - let foreign_keys = constraints - .get("foreign") - .and_then(|f| f.as_object()) - .unwrap(); - let under_keys = constraints - .get("under") - .and_then(|u| u.as_object()) - .unwrap(); + let foreign_keys = &constraints.foreign; + let under_keys = &constraints.under; let mut dependency_graph = DiGraphMap::<&str, ()>::new(); for table_name in table_list { let t_index = dependency_graph.add_node(table_name); - let fkeys = foreign_keys - .get(table_name) - .and_then(|f| f.as_array()) - .unwrap(); + let fkeys = foreign_keys.get(table_name).unwrap(); for fkey in fkeys { - let ftable = fkey.get("ftable").and_then(|f| f.as_str()).unwrap(); - let f_index = dependency_graph.add_node(ftable); + let ftable = &fkey.ftable; + let f_index = dependency_graph.add_node(&ftable); dependency_graph.add_edge(t_index, f_index, ()); } - let ukeys = under_keys - .get(table_name) - .and_then(|u| u.as_array()) - .unwrap(); + let ukeys = under_keys.get(table_name).unwrap(); for ukey in ukeys { - let ttable = ukey.get("ttable").and_then(|t| t.as_str()).unwrap(); - let tcolumn = ukey.get("tcolumn").and_then(|t| t.as_str()).unwrap(); - let value = ukey.get("value").and_then(|t| t.as_str()).unwrap(); + let ttable = &ukey.ttable; + let tcolumn = &ukey.tcolumn; + let value = &ukey.value; if ttable != table_name { - let ttable_trees = trees.get(ttable).and_then(|t| t.as_array()).unwrap(); + let ttable_trees = trees.get(ttable).unwrap(); if ttable_trees .iter() - .filter(|d| d.get("child").unwrap().as_str() == Some(tcolumn)) + .filter(|d| d.child == *tcolumn) .collect::>() .is_empty() { @@ -3021,7 +3006,7 @@ pub fn verify_table_deps_and_sort( ttable, tcolumn, value ); } - let tt_index = dependency_graph.add_node(ttable); + let tt_index = dependency_graph.add_node(&ttable); dependency_graph.add_edge(t_index, tt_index, ()); } } @@ -3060,27 +3045,19 @@ pub fn verify_table_deps_and_sort( for (i, table) in cycle.iter().enumerate() { if i < end_index { let dep_name = cycle.get(i + 1).unwrap().as_str(); - let fkeys = foreign_keys.get(table).and_then(|f| f.as_array()).unwrap(); - let ukeys = under_keys.get(table).and_then(|u| u.as_array()).unwrap(); + let fkeys = foreign_keys.get(table).unwrap(); + let ukeys = under_keys.get(table).unwrap(); let column; let ref_table; let ref_column; - if let Some(dep) = fkeys - .iter() - .find(|d| d.get("ftable").unwrap().as_str() == Some(dep_name)) - .and_then(|d| d.as_object()) - { - column = dep.get("column").unwrap(); - ref_table = dep.get("ftable").unwrap(); - ref_column = dep.get("fcolumn").unwrap(); - } else if let Some(dep) = ukeys - .iter() - .find(|d| d.get("ttable").unwrap().as_str() == Some(dep_name)) - .and_then(|d| d.as_object()) - { - column = dep.get("column").unwrap(); - ref_table = dep.get("ttable").unwrap(); - ref_column = dep.get("tcolumn").unwrap(); + if let Some(dep) = fkeys.iter().find(|d| d.ftable == *dep_name) { + column = &dep.column; + ref_table = &dep.ftable; + ref_column = &dep.fcolumn; + } else if let Some(dep) = ukeys.iter().find(|d| d.ttable == *dep_name) { + column = &dep.column; + ref_table = &dep.ttable; + ref_column = &dep.tcolumn; } else { panic!("{}. Unable to retrieve the details.", message); } @@ -3112,14 +3089,18 @@ pub fn get_table_constraints( parser: &StartParser, table_name: &str, pool: &AnyPool, -) -> SerdeValue { - let mut table_constraints = json!({ - "foreign": [], - "unique": [], - "primary": [], - "tree": [], - "under": [], - }); +) -> ( + Vec, + Vec, + Vec, + Vec, + Vec, +) { + let mut primaries = vec![]; + let mut uniques = vec![]; + let mut foreigns = vec![]; + let mut trees = vec![]; + let mut unders = vec![]; let column_names = tables_config .get(table_name) @@ -3146,18 +3127,10 @@ pub fn get_table_constraints( for expression in parsed_structure { match *expression { Expression::Label(value) if value == "primary" => { - let primary_keys = table_constraints - .get_mut("primary") - .and_then(|v| v.as_array_mut()) - .unwrap(); - primary_keys.push(SerdeValue::String(column_name.to_string())); + primaries.push(column_name.to_string()); } Expression::Label(value) if value == "unique" => { - let unique_constraints = table_constraints - .get_mut("unique") - .and_then(|v| v.as_array_mut()) - .unwrap(); - unique_constraints.push(SerdeValue::String(column_name.to_string())); + uniques.push(column_name.to_string()); } Expression::Function(name, args) if name == "from" => { if args.len() != 1 { @@ -3165,16 +3138,11 @@ pub fn get_table_constraints( } match &*args[0] { Expression::Field(ftable, fcolumn) => { - let foreign_keys = table_constraints - .get_mut("foreign") - .and_then(|v| v.as_array_mut()) - .unwrap(); - let foreign_key = json!({ - "column": column_name, - "ftable": ftable, - "fcolumn": fcolumn, + foreigns.push(ValveForeignConstraint { + column: column_name.to_string(), + ftable: ftable.to_string(), + fcolumn: fcolumn.to_string(), }); - foreign_keys.push(foreign_key); } _ => { panic!("Invalid foreign key: {} for: {}", structure, table_name) @@ -3215,13 +3183,10 @@ pub fn get_table_constraints( child_sql_type, child, child, table_name, sql_type, parent ); } - let tree_constraints = table_constraints - .get_mut("tree") - .and_then(|t| t.as_array_mut()) - .unwrap(); - let entry = json!({"parent": column_name, - "child": child}); - tree_constraints.push(entry); + trees.push(ValveTreeConstraint { + child: child.to_string(), + parent: column_name.to_string(), + }); } _ => { panic!( @@ -3241,15 +3206,12 @@ pub fn get_table_constraints( } match (&*args[0], &*args[1]) { (Expression::Field(ttable, tcolumn), Expression::Label(value)) => { - let under_constraints = table_constraints - .get_mut("under") - .and_then(|u| u.as_array_mut()) - .unwrap(); - let entry = json!({"column": column_name, - "ttable": ttable, - "tcolumn": tcolumn, - "value": value}); - under_constraints.push(entry); + unders.push(ValveUnderConstraint { + column: column_name.to_string(), + ttable: ttable.to_string(), + tcolumn: tcolumn.to_string(), + value: json!(value), + }); } (_, _) => panic!("{}", generic_error), }; @@ -3263,7 +3225,7 @@ pub fn get_table_constraints( } } - return table_constraints; + return (primaries, uniques, foreigns, trees, unders); } /// Given table configuration map and a datatype configuration map, a parser, a table name, and a @@ -3321,7 +3283,8 @@ pub fn get_table_ddl( json!({"foreign": [], "unique": [], "primary": [], "tree": [], "under": [],}) } else { // TODO: Here. - get_table_constraints(&HashMap::new(), &HashMap::new(), parser, &table_name, &pool) + serde_json::Value::Object(SerdeMap::new()) + //get_table_constraints(&HashMap::new(), &HashMap::new(), parser, &table_name, &pool) //get_table_constraints(tables_config, datatypes_config_old, parser, &table_name, &pool) } }; diff --git a/src/valve.rs b/src/valve.rs index 30925cd0..71df7e39 100644 --- a/src/valve.rs +++ b/src/valve.rs @@ -131,53 +131,54 @@ struct _ValveRuleConfig { // TODO: Make this struct public; remove unneeded derives. #[derive(Debug, Default)] -struct _ValveTreeConstraint { - pub _child: String, - pub _parent: String, +pub struct ValveTreeConstraint { + pub child: String, + pub parent: String, } // TODO: Make this struct public; remove unneeded derives. #[derive(Debug, Default)] -struct _ValveUnderConstraint { - pub _column: String, - pub _ttable: String, - pub _tcolumn: String, - pub _value: SerdeValue, +pub struct ValveUnderConstraint { + pub column: String, + pub ttable: String, + pub tcolumn: String, + pub value: SerdeValue, } // TODO: Make this struct public; remove unneeded derives. #[derive(Debug, Default)] -struct _ValveForeignConstraint { - pub _column: String, - pub _ftable: String, - pub _fcolumn: String, +pub struct ValveForeignConstraint { + pub column: String, + pub ftable: String, + pub fcolumn: String, } // TODO: Make this struct public; remove unneeded derives. #[derive(Debug, Default)] -struct _ValveTableConstraints { +pub struct ValveTableConstraints { // Note that primary would be better as HashMap, since it is not possible to // have more than one primary key per table, but the below reflects the current implementation // which in principle allows for more than one. - pub _primary: HashMap>, - pub _unique: HashMap>, - pub _foreign: HashMap>, - pub _tree: HashMap>, - pub _under: HashMap>, + // TODO: Change it so that more than one primary key is not allowed. + pub primary: HashMap>, + pub unique: HashMap>, + pub foreign: HashMap>, + pub tree: HashMap>, + pub under: HashMap>, } // TODO: Make this struct public; remove unneeded derives. #[derive(Debug, Default)] -struct ValveConfig { +pub struct ValveConfig { pub special: ValveSpecialConfig, pub table: HashMap, pub datatype: HashMap, //pub rule: HashMap>>, - //pub table_constraints: ValveTableConstraints, + pub table_constraints: ValveTableConstraints, //pub datatype_conditions: HashMap, //pub rule_conditions: HashMap>>, //pub structure_conditions: HashMap, - //pub sorted_table_list: Vec, + pub sorted_table_list: Vec, } /// Main entrypoint for the Valve API. @@ -263,8 +264,8 @@ impl Valve { specials_config, tables_config, datatypes_config, - rules_config_old, - constraints_config_old, + _rules_config_old, + constraints_config, sorted_table_list, table_dependencies_in, table_dependencies_out, @@ -274,45 +275,21 @@ impl Valve { special: specials_config, table: tables_config, datatype: datatypes_config, + table_constraints: constraints_config, + sorted_table_list: sorted_table_list.clone(), }; println!("SPECIALS CONFIG: {:#?}", config.special); println!("TABLES CONFIG: {:#?}", config.table); println!("DATATYPES CONFIG: {:#?}", config.datatype); + println!("TABLE CONSTRAINTS: {:#?}", config.table_constraints); + println!("SORTED TABLE LIST: {:?}", config.sorted_table_list); // TODO: Obviously remove this later. if 1 == 1 { todo!(); } - let mut config_old = SerdeMap::new(); - //config_old.insert( - // String::from("special"), - // SerdeValue::Object(specials_config_old.clone()), - //); - //config_old.insert( - // String::from("table"), - // SerdeValue::Object(tables_config_old.clone()), - //); - //config_old.insert( - // String::from("datatype"), - // SerdeValue::Object(datatypes_config_old.clone()), - //); - config_old.insert( - String::from("rule"), - SerdeValue::Object(rules_config_old.clone()), - ); - config_old.insert( - String::from("constraints"), - SerdeValue::Object(constraints_config_old.clone()), - ); - let mut sorted_table_serdevalue_list: Vec = vec![]; - for table in &sorted_table_list { - sorted_table_serdevalue_list.push(SerdeValue::String(table.to_string())); - } - config_old.insert( - String::from("sorted_table_list"), - SerdeValue::Array(sorted_table_serdevalue_list), - ); + let config_old = SerdeMap::new(); let compiled_datatype_conditions = get_compiled_datatype_conditions(&config_old, &parser); let compiled_rule_conditions = get_compiled_rule_conditions( @@ -1005,7 +982,8 @@ impl Valve { ))); } - let constraints_config = self + // TODO: Here. + let _constraints_config_old = self .config .get("constraints") .and_then(|c| c.as_object()) @@ -1021,8 +999,9 @@ impl Valve { .map(|s| s.to_string()) .collect::>(); + // TODO: Here. let (sorted_subset, _, _) = - verify_table_deps_and_sort(&filtered_subset, &constraints_config); + verify_table_deps_and_sort(&filtered_subset, &ValveTableConstraints::default()); // Since the result of verify_table_deps_and_sort() will include dependencies of the tables // in its input list, we filter those out here: