chore: restore examples after thread safety feature
This commit is contained in:
@@ -1,160 +1,161 @@
|
||||
fn main() {}
|
||||
// use heave::*;
|
||||
//
|
||||
// // Define a struct named `Component` to represent an electronic component.
|
||||
// #[derive(Debug, Clone, PartialEq)]
|
||||
// struct Component {
|
||||
// pub id: String,
|
||||
// pub part_number: String,
|
||||
// pub kind: String,
|
||||
// pub value: u64,
|
||||
// pub package: String,
|
||||
// pub in_stock: bool,
|
||||
// }
|
||||
// // Implement the `EAV` trait for the `Component` struct.
|
||||
// impl EAV for Component {
|
||||
// // `class` is a function that returns the class name of the entity.
|
||||
// fn class() -> &'static str {
|
||||
// "component"
|
||||
// }
|
||||
// }
|
||||
// // Implement the `From<Component>` trait for the `Entity` struct.
|
||||
// impl From<Component> for Entity {
|
||||
// // `from` is a function that converts a `Component` into an `Entity`.
|
||||
// fn from(value: Component) -> Entity {
|
||||
// Entity::new::<Component>()
|
||||
// .with_id(&value.id)
|
||||
// .with_attribute("part_number", value.part_number)
|
||||
// .with_attribute("kind", value.kind)
|
||||
// .with_attribute("value", value.value)
|
||||
// .with_attribute("package", value.package)
|
||||
// .with_attribute("in_stock", value.in_stock)
|
||||
// }
|
||||
// }
|
||||
// // Implement the `From<Entity>` trait for the `Component` struct.
|
||||
// impl From<Entity> for Component {
|
||||
// // `from` is a function that converts an `Entity` into a `Component`.
|
||||
// fn from(value: Entity) -> Self {
|
||||
// Self {
|
||||
// id: value.id.clone(),
|
||||
// part_number: value
|
||||
// .unwrap("part_number")
|
||||
// .expect("part_number is always present"),
|
||||
// kind: value.unwrap("kind").expect("kind is always present"),
|
||||
// value: value.unwrap("value").expect("value is always present"),
|
||||
// package: value.unwrap("package").expect("package is always present"),
|
||||
// in_stock: value
|
||||
// .unwrap("in_stock")
|
||||
// .expect("in_stock is always present"),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn main() {
|
||||
// // Define the path for the SQLite database file.
|
||||
// let db_path = "./using_filters.sqlite3";
|
||||
// // Create a new `Catalog` instance with the specified database path.
|
||||
// let mut catalog = Catalog::new(db_path);
|
||||
// // Initialize the catalog, which sets up the database.
|
||||
// catalog.init().unwrap();
|
||||
// // Create some component instances.
|
||||
// let components_to_add = vec![
|
||||
// // This one should be found
|
||||
// Component {
|
||||
// id: "R1".to_string(),
|
||||
// part_number: "R-10K-0805".to_string(),
|
||||
// kind: "resistor".to_string(),
|
||||
// value: 10000,
|
||||
// package: "smd-0805".to_string(),
|
||||
// in_stock: true,
|
||||
// },
|
||||
// // This one should be found
|
||||
// Component {
|
||||
// id: "R2".to_string(),
|
||||
// part_number: "R-4K7-0805".to_string(),
|
||||
// kind: "resistor".to_string(),
|
||||
// value: 4700,
|
||||
// package: "smd-0805".to_string(),
|
||||
// in_stock: true,
|
||||
// },
|
||||
// // This one should NOT be found (wrong kind)
|
||||
// Component {
|
||||
// id: "C1".to_string(),
|
||||
// part_number: "C-100n-0603".to_string(),
|
||||
// kind: "capacitor".to_string(),
|
||||
// value: 100,
|
||||
// package: "smd-0603".to_string(),
|
||||
// in_stock: true,
|
||||
// },
|
||||
// // This one should NOT be found (value too low)
|
||||
// Component {
|
||||
// id: "R3".to_string(),
|
||||
// part_number: "R-100-0805".to_string(),
|
||||
// kind: "resistor".to_string(),
|
||||
// value: 100,
|
||||
// package: "smd-0805".to_string(),
|
||||
// in_stock: true,
|
||||
// },
|
||||
// // This one should NOT be found (not in stock)
|
||||
// Component {
|
||||
// id: "R4".to_string(),
|
||||
// part_number: "R-22K-TH".to_string(),
|
||||
// kind: "resistor".to_string(),
|
||||
// value: 22000,
|
||||
// package: "through-hole".to_string(),
|
||||
// in_stock: false,
|
||||
// },
|
||||
// // This one should NOT be found (wrong kind, even if other fields match)
|
||||
// Component {
|
||||
// id: "L1".to_string(),
|
||||
// part_number: "L-10mH-TH".to_string(),
|
||||
// kind: "inductor".to_string(),
|
||||
// value: 10000,
|
||||
// package: "through-hole".to_string(),
|
||||
// in_stock: true,
|
||||
// },
|
||||
// ];
|
||||
// // Insert the components into the catalog.
|
||||
// catalog.insert_many(components_to_add.clone()).unwrap();
|
||||
// // Persist the changes to the database.
|
||||
// catalog.persist().unwrap();
|
||||
// // Create a new catalog to ensure we are loading from the database.
|
||||
// let mut new_catalog = Catalog::new(db_path);
|
||||
// // Create a composite filter.
|
||||
// // We are looking for resistors with a value greater than 1000 that are in stock.
|
||||
// let filter = Filter::new()
|
||||
// .with_text("kind", Comparison::IsExactly, "resistor")
|
||||
// .with_unsigned_int("value", Comparison::Greater, 1000)
|
||||
// .with_bool("in_stock", true);
|
||||
// // Load entities from the database using the filter.
|
||||
// new_catalog.load_by_filter(&filter).unwrap();
|
||||
// // Get the list of loaded components.
|
||||
// let loaded_components: Vec<Component> = new_catalog
|
||||
// .list_by_class::<Component>()
|
||||
// .map(|c| c.unwrap())
|
||||
// .collect();
|
||||
// // Print the loaded components
|
||||
// println!(
|
||||
// "Found {} components matching the filter:",
|
||||
// loaded_components.len()
|
||||
// );
|
||||
// for component in &loaded_components {
|
||||
// println!(
|
||||
// "- ID: {}, Part Number: {}, Kind: {}, Value: {}, Package: {}, In Stock: {}",
|
||||
// component.id,
|
||||
// component.part_number,
|
||||
// component.kind,
|
||||
// component.value,
|
||||
// component.package,
|
||||
// component.in_stock
|
||||
// );
|
||||
// }
|
||||
// // Verify that we have loaded the correct number of components.
|
||||
// assert_eq!(loaded_components.len(), 2);
|
||||
// // Verify that the correct components were loaded.
|
||||
// let ids: Vec<String> = loaded_components.iter().map(|c| c.id.clone()).collect();
|
||||
// assert!(ids.contains(&"R1".to_string()));
|
||||
// assert!(ids.contains(&"R2".to_string()));
|
||||
// // Clean up the database file.
|
||||
// std::fs::remove_file(db_path).unwrap();
|
||||
// }
|
||||
use heave::*;
|
||||
|
||||
// Define a struct named `Component` to represent an electronic component.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
struct Component {
|
||||
pub id: String,
|
||||
pub part_number: String,
|
||||
pub kind: String,
|
||||
pub value: u64,
|
||||
pub package: String,
|
||||
pub in_stock: bool,
|
||||
}
|
||||
// Implement the `EAV` trait for the `Component` struct.
|
||||
impl EAV for Component {
|
||||
// `class` is a function that returns the class name of the entity.
|
||||
fn class() -> &'static str {
|
||||
"component"
|
||||
}
|
||||
}
|
||||
// Implement the `From<Component>` trait for the `Entity` struct.
|
||||
impl From<Component> for Entity {
|
||||
// `from` is a function that converts a `Component` into an `Entity`.
|
||||
fn from(value: Component) -> Entity {
|
||||
Entity::new::<Component>()
|
||||
.with_id(&value.id)
|
||||
.with_attribute("part_number", value.part_number)
|
||||
.with_attribute("kind", value.kind)
|
||||
.with_attribute("value", value.value)
|
||||
.with_attribute("package", value.package)
|
||||
.with_attribute("in_stock", value.in_stock)
|
||||
}
|
||||
}
|
||||
// Implement the `From<Entity>` trait for the `Component` struct.
|
||||
impl From<Entity> for Component {
|
||||
// `from` is a function that converts an `Entity` into a `Component`.
|
||||
fn from(value: Entity) -> Self {
|
||||
Self {
|
||||
id: value.id.clone(),
|
||||
part_number: value
|
||||
.unwrap("part_number")
|
||||
.expect("part_number is always present"),
|
||||
kind: value.unwrap("kind").expect("kind is always present"),
|
||||
value: value.unwrap("value").expect("value is always present"),
|
||||
package: value.unwrap("package").expect("package is always present"),
|
||||
in_stock: value
|
||||
.unwrap("in_stock")
|
||||
.expect("in_stock is always present"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Define the path for the SQLite database file.
|
||||
let db_path = "./using_filters.sqlite3";
|
||||
// Create a new `Catalog` instance with the specified database path.
|
||||
let mut catalog = Catalog::new(db_path);
|
||||
// Initialize the catalog, which sets up the database.
|
||||
catalog.init().unwrap();
|
||||
// Create some component instances.
|
||||
let components_to_add = vec![
|
||||
// This one should be found
|
||||
Component {
|
||||
id: "R1".to_string(),
|
||||
part_number: "R-10K-0805".to_string(),
|
||||
kind: "resistor".to_string(),
|
||||
value: 10000,
|
||||
package: "smd-0805".to_string(),
|
||||
in_stock: true,
|
||||
},
|
||||
// This one should be found
|
||||
Component {
|
||||
id: "R2".to_string(),
|
||||
part_number: "R-4K7-0805".to_string(),
|
||||
kind: "resistor".to_string(),
|
||||
value: 4700,
|
||||
package: "smd-0805".to_string(),
|
||||
in_stock: true,
|
||||
},
|
||||
// This one should NOT be found (wrong kind)
|
||||
Component {
|
||||
id: "C1".to_string(),
|
||||
part_number: "C-100n-0603".to_string(),
|
||||
kind: "capacitor".to_string(),
|
||||
value: 100,
|
||||
package: "smd-0603".to_string(),
|
||||
in_stock: true,
|
||||
},
|
||||
// This one should NOT be found (value too low)
|
||||
Component {
|
||||
id: "R3".to_string(),
|
||||
part_number: "R-100-0805".to_string(),
|
||||
kind: "resistor".to_string(),
|
||||
value: 100,
|
||||
package: "smd-0805".to_string(),
|
||||
in_stock: true,
|
||||
},
|
||||
// This one should NOT be found (not in stock)
|
||||
Component {
|
||||
id: "R4".to_string(),
|
||||
part_number: "R-22K-TH".to_string(),
|
||||
kind: "resistor".to_string(),
|
||||
value: 22000,
|
||||
package: "through-hole".to_string(),
|
||||
in_stock: false,
|
||||
},
|
||||
// This one should NOT be found (wrong kind, even if other fields match)
|
||||
Component {
|
||||
id: "L1".to_string(),
|
||||
part_number: "L-10mH-TH".to_string(),
|
||||
kind: "inductor".to_string(),
|
||||
value: 10000,
|
||||
package: "through-hole".to_string(),
|
||||
in_stock: true,
|
||||
},
|
||||
];
|
||||
// Insert the components into the catalog.
|
||||
catalog.insert_many(components_to_add.clone()).unwrap();
|
||||
// Persist the changes to the database.
|
||||
catalog.persist().unwrap();
|
||||
// Create a new catalog to ensure we are loading from the database.
|
||||
let mut new_catalog = Catalog::new(db_path);
|
||||
// Create a composite filter.
|
||||
// We are looking for resistors with a value greater than 1000 that are in stock.
|
||||
let filter = Filter::new()
|
||||
.with_text("kind", Comparison::IsExactly, "resistor")
|
||||
.with_unsigned_int("value", Comparison::Greater, 1000)
|
||||
.with_bool("in_stock", true);
|
||||
// Load entities from the database using the filter.
|
||||
new_catalog.load_by_filter(&filter).unwrap();
|
||||
// Get the list of loaded components.
|
||||
let loaded_components: Vec<Component> = new_catalog
|
||||
.list_by_class::<Component>()
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|c| c.unwrap())
|
||||
.collect();
|
||||
// Print the loaded components
|
||||
println!(
|
||||
"Found {} components matching the filter:",
|
||||
loaded_components.len()
|
||||
);
|
||||
for component in &loaded_components {
|
||||
println!(
|
||||
"- ID: {}, Part Number: {}, Kind: {}, Value: {}, Package: {}, In Stock: {}",
|
||||
component.id,
|
||||
component.part_number,
|
||||
component.kind,
|
||||
component.value,
|
||||
component.package,
|
||||
component.in_stock
|
||||
);
|
||||
}
|
||||
// Verify that we have loaded the correct number of components.
|
||||
assert_eq!(loaded_components.len(), 2);
|
||||
// Verify that the correct components were loaded.
|
||||
let ids: Vec<String> = loaded_components.iter().map(|c| c.id.clone()).collect();
|
||||
assert!(ids.contains(&"R1".to_string()));
|
||||
assert!(ids.contains(&"R2".to_string()));
|
||||
// Clean up the database file.
|
||||
std::fs::remove_file(db_path).unwrap();
|
||||
}
|
||||
|
||||
@@ -1,228 +1,236 @@
|
||||
fn main() {}
|
||||
// use heave::*;
|
||||
// use std::path::Path;
|
||||
//
|
||||
// struct Laptop {
|
||||
// pub id: String,
|
||||
// pub model: String,
|
||||
// pub price: u64,
|
||||
// }
|
||||
// struct Display {
|
||||
// pub id: String,
|
||||
// pub model: String,
|
||||
// pub resolution: f64,
|
||||
// pub price: u64,
|
||||
// }
|
||||
// struct Mouse {
|
||||
// pub id: String,
|
||||
// pub model: String,
|
||||
// pub wireless: bool,
|
||||
// pub price: u64,
|
||||
// }
|
||||
// enum Product {
|
||||
// None,
|
||||
// Laptop(Laptop),
|
||||
// Display(Display),
|
||||
// Mouse(Mouse),
|
||||
// }
|
||||
// impl EAV for Product {
|
||||
// fn class() -> &'static str {
|
||||
// "product"
|
||||
// }
|
||||
// }
|
||||
// impl From<Entity> for Product {
|
||||
// fn from(value: Entity) -> Self {
|
||||
// if let Some(ref subclass) = value.subclass {
|
||||
// match subclass.as_ref() {
|
||||
// "laptop" => Product::Laptop(Laptop {
|
||||
// id: value.id.clone(),
|
||||
// model: value.unwrap("model").expect("model is mandatory"),
|
||||
// price: value.unwrap("price").expect("price is mandatory"),
|
||||
// }),
|
||||
// "display" => Product::Display(Display {
|
||||
// id: value.id.clone(),
|
||||
// model: value.unwrap("model").expect("model is mandatory"),
|
||||
// price: value.unwrap("price").expect("price is mandatory"),
|
||||
// resolution: value.unwrap("resolution").expect("resolution is mandatory"),
|
||||
// }),
|
||||
// "mouse" => Product::Mouse(Mouse {
|
||||
// id: value.id.clone(),
|
||||
// model: value.unwrap("model").expect("model is mandatory"),
|
||||
// price: value.unwrap("price").expect("price is mandatory"),
|
||||
// wireless: value.unwrap("wireless").expect("wireless is mandatory"),
|
||||
// }),
|
||||
// _ => unreachable!(),
|
||||
// }
|
||||
// } else {
|
||||
// Product::None
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// impl From<Product> for Entity {
|
||||
// fn from(value: Product) -> Self {
|
||||
// match value {
|
||||
// Product::Laptop(value) => Entity::new::<Product>()
|
||||
// .with_id(&value.id)
|
||||
// .with_subclass("laptop")
|
||||
// .with_attribute("model", value.model)
|
||||
// .with_attribute("price", value.price),
|
||||
// Product::Display(value) => Entity::new::<Product>()
|
||||
// .with_id(&value.id)
|
||||
// .with_subclass("display")
|
||||
// .with_attribute("model", value.model)
|
||||
// .with_attribute("resolution", value.resolution)
|
||||
// .with_attribute("price", value.price),
|
||||
// Product::Mouse(value) => Entity::new::<Product>()
|
||||
// .with_id(&value.id)
|
||||
// .with_subclass("mouse")
|
||||
// .with_attribute("model", value.model)
|
||||
// .with_attribute("wireless", value.wireless)
|
||||
// .with_attribute("price", value.price),
|
||||
// _ => unreachable!(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// fn main() -> Result<(), FailedTo> {
|
||||
// let db_path = "working_with_many_types.db";
|
||||
//
|
||||
// // Clean up previous runs if file exists
|
||||
// if Path::new(db_path).exists() {
|
||||
// std::fs::remove_file(db_path).unwrap();
|
||||
// }
|
||||
//
|
||||
// // 1. Initialize and Persist Data
|
||||
// println!("== 1. Storing different product types ==");
|
||||
// let mut catalog = Catalog::new(db_path);
|
||||
// catalog.init()?;
|
||||
//
|
||||
// let products_to_add = vec![
|
||||
// Product::Laptop(Laptop {
|
||||
// id: "laptop_01".to_string(),
|
||||
// model: "Titan".to_string(),
|
||||
// price: 1500,
|
||||
// }),
|
||||
// Product::Display(Display {
|
||||
// id: "display_01".to_string(),
|
||||
// model: "CrystalClear".to_string(),
|
||||
// resolution: 4.0, // 4K
|
||||
// price: 600,
|
||||
// }),
|
||||
// Product::Mouse(Mouse {
|
||||
// id: "mouse_01".to_string(),
|
||||
// model: "SwiftClick".to_string(),
|
||||
// wireless: true,
|
||||
// price: 80,
|
||||
// }),
|
||||
// Product::Laptop(Laptop {
|
||||
// id: "laptop_02".to_string(),
|
||||
// model: "Nomad".to_string(),
|
||||
// price: 950,
|
||||
// }),
|
||||
// ];
|
||||
//
|
||||
// catalog.insert_many(products_to_add)?;
|
||||
// catalog.persist()?;
|
||||
// println!("✅ 4 products saved to the database.\n");
|
||||
//
|
||||
// // 2. Load data using filters
|
||||
// println!("== 2. Loading products using class and subclass filters ==");
|
||||
//
|
||||
// // Load only laptops
|
||||
// let mut laptop_catalog = Catalog::new(db_path);
|
||||
// let laptop_filter = Filter::new()
|
||||
// .with_class(Product::class())
|
||||
// .with_subclass("laptop");
|
||||
//
|
||||
// laptop_catalog.load_by_filter(&laptop_filter)?;
|
||||
//
|
||||
// let laptops: Vec<Product> = laptop_catalog.list_by_class().map(|p| p.unwrap()).collect();
|
||||
//
|
||||
// println!("✅ Loaded {} laptop(s) using filter.", laptops.len());
|
||||
// assert_eq!(laptops.len(), 2);
|
||||
// for p in laptops {
|
||||
// if let Product::Laptop(laptop) = p {
|
||||
// println!(
|
||||
// " - Laptop: {} ({}) - ${}",
|
||||
// laptop.id, laptop.model, laptop.price
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// println!();
|
||||
//
|
||||
// println!("== 3. Loading products using attribute filters ==");
|
||||
// // Load expensive products (price > 1000)
|
||||
// let mut expensive_catalog = Catalog::new(db_path);
|
||||
// let expensive_filter = Filter::new()
|
||||
// .with_class(Product::class())
|
||||
// .with_unsigned_int("price", Comparison::Greater, 1000);
|
||||
//
|
||||
// expensive_catalog.load_by_filter(&expensive_filter)?;
|
||||
//
|
||||
// let expensive_products: Vec<Product> = expensive_catalog
|
||||
// .list_by_class()
|
||||
// .map(|p| p.unwrap())
|
||||
// .collect();
|
||||
//
|
||||
// println!(
|
||||
// "✅ Loaded {} product(s) with price > $1000.",
|
||||
// expensive_products.len()
|
||||
// );
|
||||
// assert_eq!(expensive_products.len(), 1);
|
||||
//
|
||||
// for p in expensive_products {
|
||||
// match p {
|
||||
// Product::Laptop(laptop) => {
|
||||
// println!(
|
||||
// " - Found Laptop: {} ({}) - ${}",
|
||||
// laptop.id, laptop.model, laptop.price
|
||||
// );
|
||||
// assert_eq!(laptop.id, "laptop_01");
|
||||
// }
|
||||
// _ => panic!("Expected a laptop!"),
|
||||
// }
|
||||
// }
|
||||
// println!();
|
||||
//
|
||||
// println!("== 4. Loading all product types ==");
|
||||
// let mut all_products_catalog = Catalog::new(db_path);
|
||||
// let all_products_filter = Filter::new().with_class(Product::class());
|
||||
// all_products_catalog.load_by_filter(&all_products_filter)?;
|
||||
//
|
||||
// let all_products: Vec<Product> = all_products_catalog
|
||||
// .list_by_class()
|
||||
// .map(|p| p.unwrap())
|
||||
// .collect();
|
||||
//
|
||||
// println!("✅ Loaded {} total products.", all_products.len());
|
||||
// assert_eq!(all_products.len(), 4);
|
||||
//
|
||||
// for p in all_products {
|
||||
// match p {
|
||||
// Product::Laptop(laptop) => {
|
||||
// println!(
|
||||
// " - Found Laptop: {} ({}) - ${}",
|
||||
// laptop.id, laptop.model, laptop.price
|
||||
// );
|
||||
// }
|
||||
// Product::Display(display) => {
|
||||
// println!(
|
||||
// " - Found Display: {} ({}) - ${}",
|
||||
// display.id, display.model, display.price
|
||||
// );
|
||||
// }
|
||||
// Product::Mouse(mouse) => {
|
||||
// println!(
|
||||
// " - Found Mouse: {} ({}) - ${}",
|
||||
// mouse.id, mouse.model, mouse.price
|
||||
// );
|
||||
// }
|
||||
// Product::None => panic!("Product::None should not be loaded"),
|
||||
// }
|
||||
// }
|
||||
// println!();
|
||||
//
|
||||
// // Clean up the created database file
|
||||
// std::fs::remove_file(db_path).unwrap();
|
||||
//
|
||||
// Ok(())
|
||||
// }
|
||||
use heave::*;
|
||||
use std::path::Path;
|
||||
|
||||
struct Laptop {
|
||||
pub id: String,
|
||||
pub model: String,
|
||||
pub price: u64,
|
||||
}
|
||||
struct Display {
|
||||
pub id: String,
|
||||
pub model: String,
|
||||
pub resolution: f64,
|
||||
pub price: u64,
|
||||
}
|
||||
struct Mouse {
|
||||
pub id: String,
|
||||
pub model: String,
|
||||
pub wireless: bool,
|
||||
pub price: u64,
|
||||
}
|
||||
enum Product {
|
||||
None,
|
||||
Laptop(Laptop),
|
||||
Display(Display),
|
||||
Mouse(Mouse),
|
||||
}
|
||||
impl EAV for Product {
|
||||
fn class() -> &'static str {
|
||||
"product"
|
||||
}
|
||||
}
|
||||
impl From<Entity> for Product {
|
||||
fn from(value: Entity) -> Self {
|
||||
if let Some(ref subclass) = value.subclass {
|
||||
match subclass.as_ref() {
|
||||
"laptop" => Product::Laptop(Laptop {
|
||||
id: value.id.clone(),
|
||||
model: value.unwrap("model").expect("model is mandatory"),
|
||||
price: value.unwrap("price").expect("price is mandatory"),
|
||||
}),
|
||||
"display" => Product::Display(Display {
|
||||
id: value.id.clone(),
|
||||
model: value.unwrap("model").expect("model is mandatory"),
|
||||
price: value.unwrap("price").expect("price is mandatory"),
|
||||
resolution: value.unwrap("resolution").expect("resolution is mandatory"),
|
||||
}),
|
||||
"mouse" => Product::Mouse(Mouse {
|
||||
id: value.id.clone(),
|
||||
model: value.unwrap("model").expect("model is mandatory"),
|
||||
price: value.unwrap("price").expect("price is mandatory"),
|
||||
wireless: value.unwrap("wireless").expect("wireless is mandatory"),
|
||||
}),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
Product::None
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<Product> for Entity {
|
||||
fn from(value: Product) -> Self {
|
||||
match value {
|
||||
Product::Laptop(value) => Entity::new::<Product>()
|
||||
.with_id(&value.id)
|
||||
.with_subclass("laptop")
|
||||
.with_attribute("model", value.model)
|
||||
.with_attribute("price", value.price),
|
||||
Product::Display(value) => Entity::new::<Product>()
|
||||
.with_id(&value.id)
|
||||
.with_subclass("display")
|
||||
.with_attribute("model", value.model)
|
||||
.with_attribute("resolution", value.resolution)
|
||||
.with_attribute("price", value.price),
|
||||
Product::Mouse(value) => Entity::new::<Product>()
|
||||
.with_id(&value.id)
|
||||
.with_subclass("mouse")
|
||||
.with_attribute("model", value.model)
|
||||
.with_attribute("wireless", value.wireless)
|
||||
.with_attribute("price", value.price),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
fn main() -> Result<(), FailedTo> {
|
||||
let db_path = "working_with_many_types.db";
|
||||
|
||||
// Clean up previous runs if file exists
|
||||
if Path::new(db_path).exists() {
|
||||
std::fs::remove_file(db_path).unwrap();
|
||||
}
|
||||
|
||||
// 1. Initialize and Persist Data
|
||||
println!("== 1. Storing different product types ==");
|
||||
let mut catalog = Catalog::new(db_path);
|
||||
catalog.init()?;
|
||||
|
||||
let products_to_add = vec![
|
||||
Product::Laptop(Laptop {
|
||||
id: "laptop_01".to_string(),
|
||||
model: "Titan".to_string(),
|
||||
price: 1500,
|
||||
}),
|
||||
Product::Display(Display {
|
||||
id: "display_01".to_string(),
|
||||
model: "CrystalClear".to_string(),
|
||||
resolution: 4.0, // 4K
|
||||
price: 600,
|
||||
}),
|
||||
Product::Mouse(Mouse {
|
||||
id: "mouse_01".to_string(),
|
||||
model: "SwiftClick".to_string(),
|
||||
wireless: true,
|
||||
price: 80,
|
||||
}),
|
||||
Product::Laptop(Laptop {
|
||||
id: "laptop_02".to_string(),
|
||||
model: "Nomad".to_string(),
|
||||
price: 950,
|
||||
}),
|
||||
];
|
||||
|
||||
catalog.insert_many(products_to_add)?;
|
||||
catalog.persist()?;
|
||||
println!("✅ 4 products saved to the database.\n");
|
||||
|
||||
// 2. Load data using filters
|
||||
println!("== 2. Loading products using class and subclass filters ==");
|
||||
|
||||
// Load only laptops
|
||||
let mut laptop_catalog = Catalog::new(db_path);
|
||||
let laptop_filter = Filter::new()
|
||||
.with_class(Product::class())
|
||||
.with_subclass("laptop");
|
||||
|
||||
laptop_catalog.load_by_filter(&laptop_filter)?;
|
||||
|
||||
let laptops: Vec<Product> = laptop_catalog
|
||||
.list_by_class()
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|p| p.unwrap())
|
||||
.collect();
|
||||
|
||||
println!("✅ Loaded {} laptop(s) using filter.", laptops.len());
|
||||
assert_eq!(laptops.len(), 2);
|
||||
for p in laptops {
|
||||
if let Product::Laptop(laptop) = p {
|
||||
println!(
|
||||
" - Laptop: {} ({}) - ${}",
|
||||
laptop.id, laptop.model, laptop.price
|
||||
);
|
||||
}
|
||||
}
|
||||
println!();
|
||||
|
||||
println!("== 3. Loading products using attribute filters ==");
|
||||
// Load expensive products (price > 1000)
|
||||
let mut expensive_catalog = Catalog::new(db_path);
|
||||
let expensive_filter = Filter::new()
|
||||
.with_class(Product::class())
|
||||
.with_unsigned_int("price", Comparison::Greater, 1000);
|
||||
|
||||
expensive_catalog.load_by_filter(&expensive_filter)?;
|
||||
|
||||
let expensive_products: Vec<Product> = expensive_catalog
|
||||
.list_by_class()
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|p| p.unwrap())
|
||||
.collect();
|
||||
|
||||
println!(
|
||||
"✅ Loaded {} product(s) with price > $1000.",
|
||||
expensive_products.len()
|
||||
);
|
||||
assert_eq!(expensive_products.len(), 1);
|
||||
|
||||
for p in expensive_products {
|
||||
match p {
|
||||
Product::Laptop(laptop) => {
|
||||
println!(
|
||||
" - Found Laptop: {} ({}) - ${}",
|
||||
laptop.id, laptop.model, laptop.price
|
||||
);
|
||||
assert_eq!(laptop.id, "laptop_01");
|
||||
}
|
||||
_ => panic!("Expected a laptop!"),
|
||||
}
|
||||
}
|
||||
println!();
|
||||
|
||||
println!("== 4. Loading all product types ==");
|
||||
let mut all_products_catalog = Catalog::new(db_path);
|
||||
let all_products_filter = Filter::new().with_class(Product::class());
|
||||
all_products_catalog.load_by_filter(&all_products_filter)?;
|
||||
|
||||
let all_products: Vec<Product> = all_products_catalog
|
||||
.list_by_class()
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|p| p.unwrap())
|
||||
.collect();
|
||||
|
||||
println!("✅ Loaded {} total products.", all_products.len());
|
||||
assert_eq!(all_products.len(), 4);
|
||||
|
||||
for p in all_products {
|
||||
match p {
|
||||
Product::Laptop(laptop) => {
|
||||
println!(
|
||||
" - Found Laptop: {} ({}) - ${}",
|
||||
laptop.id, laptop.model, laptop.price
|
||||
);
|
||||
}
|
||||
Product::Display(display) => {
|
||||
println!(
|
||||
" - Found Display: {} ({}) - ${}",
|
||||
display.id, display.model, display.price
|
||||
);
|
||||
}
|
||||
Product::Mouse(mouse) => {
|
||||
println!(
|
||||
" - Found Mouse: {} ({}) - ${}",
|
||||
mouse.id, mouse.model, mouse.price
|
||||
);
|
||||
}
|
||||
Product::None => panic!("Product::None should not be loaded"),
|
||||
}
|
||||
}
|
||||
println!();
|
||||
|
||||
// Clean up the created database file
|
||||
std::fs::remove_file(db_path).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user