6 releases
0.3.1 | Mar 1, 2024 |
---|---|
0.3.0 | Mar 1, 2024 |
0.2.3 | Feb 29, 2024 |
#1593 in Database interfaces
33KB
629 lines
Basic Database Interface. Currently works with mySQL only. Uses the mysql crate and provides a wrapper around it to make interacting with a mysql database easier.
use std::error::Error;
use datalocker::common::enums::ClauseType;
use datalocker::common::traits::BuildsClauses;
use datalocker::common::traits::QueryData;
use datalocker::common::traits::FromLockerRow;
use datalocker::lockers::builders::clause::{SelectBuilder, ClauseBuilder};
use datalocker::lockers::mysql_locker::MysqlConnection;
use datalocker::mysql;
use datalocker::query_primary_key;
//It is useful to create structs representing your data
pub struct TestDataStruct {
id: Option<u32>,
name: String,
address: String,
age: u8
}
impl Default for TestDataStruct {
fn default() -> TestDataStruct {
TestDataStruct {
id: None,
name: String::from(""),
address: String::from(""),
age: 0
}
}
}
impl ToString for TestDataStruct {
fn to_string(&self) -> String {
match self.id {
Some(id) => format!("{} {} {} {}", id, self.name, self.address, self.age),
None => format!("{} {} {}", self.name, self.address, self.age)
}
}
}
//You can implement the QueryData trait so that they can be automatically inserted using the insert function
impl QueryData for TestDataStruct {
fn to_query_string(&self) -> String {
format!("'{}', '{}', {}", self.name, self.address, self.age)
}
fn to_column_array(&self) -> &[&str] {
&["Name", "Address", "Age"]
}
fn to_column_string(&self) -> String {
self.to_column_array().join(", ")
}
}
//You can implement the FromLockerRow trait to automatically create structs from query results
impl FromLockerRow for TestDataStruct {
fn from_row(row: mysql::Row) -> Self {
let (id, name, address, age) = mysql::from_row::<(u32, String, String, u8)>(row);
Self {
id: Some(id),
name,
address,
age
}
}
}
fn main() {
//Create a new connection
let mut conn: MysqlConnection = MysqlConnection::new(
"root".to_string(),
"rootroot".to_string(),
"localhost".to_string(),
3306,
"rust_example".to_string()
);
let r2: Result<(), Box<dyn Error>> = conn.connect();
//println!(r2.to_string());
//Drop a table
let rdrop: Result<(), Box<dyn Error>> = conn.drop_table("testTable");
//Create a table.
//query_primary_key is a macro that returns a standard primary key field
//IE int not null PRIMARY KEY AUTO_INCREMENT
let r3 = conn.create("testTable",
&[
("id", query_primary_key!()),
("Name", "varchar(255)"),
("Address", "varchar(255)"),
("Age", "tinyint UNSIGNED")
]);
//This is the data to be inserted
let data = [
TestDataStruct{ name: String::from("Michael"), address: String::from("158 Crystal Avenue"), age: 25, ..Default::default() },
TestDataStruct{ name: String::from("John"), address: String::from("742 St. Lawrence Avenue"), age: 28, ..Default::default() },
TestDataStruct{ name: String::from("William"), address: String::from("415 Atkins Street"), age: 55, ..Default::default() }
];
//insert can be used on structs with the QueryData trait
let r4 = conn.insert("testTable", &data);
//a raw select query function. Simply builds a query from the different parts
//accepts table name, columns to select, a where clause, an order by and a limit
let r5 = conn.select_raw("testTable", "*", None, None, None);
//unwrap the results to get a vector of rows
let rows: Vec<mysql::Row> = r5.unwrap();
for row in rows {
//grab the data fields from the row using the mysql crate from_row function
let (id, name, address, age) = mysql::from_row::<(u32, String, String, u8)>(row);
println!("{} {} {} {}", id, name, address, age);
}
//Use SelectBuilder to create more complex select queries that would be unwieldy using the select_row function
//uses factory style to build the query
let selector = SelectBuilder::new("testTable", &["*".to_string()])
.add_where("Name = 'Michael'")
.or()
.add_where("Age = 28");
//select function simply accepts a SelectBuilder object
let r6 = conn.select(&selector);
let rows2: Vec<mysql::Row> = r6.unwrap();
for row in rows2 {
let (id, name, address, age) = mysql::from_row::<(u32, String, String, u8)>(row);
println!("{} {} {} {}", id, name, address, age);
}
//SelectBuilders can accept other select builders are sub queries
let subselcetor = SelectBuilder::new("testTable", &["id".to_string()])
.add_where("id = 3")
.or()
.add_where("id = 2");
let selector2 = SelectBuilder::new("testTable", &["Name, Address".to_string()])
.add_where_subquery("id in", subselcetor)
.set_order_by("Name", None)
.set_limit(1, None);
//selector2 would create the query:
//SELECT Name, Address FROM testTable WHERE id in (SELECT id FROM testTable WHERE id = 3 OR id = 2) ORDER BY Name ASC LIMIT 1
let r7 = conn.select(&selector2);
let rows3: Vec<mysql::Row> = r7.unwrap();
for row in rows3 {
let (name, address) = mysql::from_row::<(String, String)>(row);
println!("{} {}", name, address);
}
//ClauseBuilder is similar to SelectBuilder, but more general
//we can use this to create where clauses for deletes (and updates)
//in the same way as above
let deletor = ClauseBuilder::new("testTable", ClauseType::Delete)
.add_where("id = 1");
//simply pass the clausebuilder into the delete function
let r9 = conn.delete(&deletor);
//or use the delete_raw function directly
let r10 = conn.delete_raw("testTable", Some("id=2"));
let r8 = conn.select_raw("testTable", "*", None, None, None);
let rows4: Vec<mysql::Row> = r8.unwrap();
for row in rows4 {
//when using a struct that implements the FromLockerRow trait
//new instances can be created using the from_row static method
let tds = TestDataStruct::from_row(row);
println!("{}", tds.to_string());
}
//use the update raw function to perform updates
//pass in the table name, a where clause option, and an
//array of update tuples with the field name and new value
let r11 = conn.update_raw("testTable", Some("id = 3"), &[
("Name", "'George'"),
("Address", "'815 Atkins Street'")
]);
//can also use the ClauseBuilder clause when using more complex where clauses
//make sure toset the correct ClauseType
let claus = ClauseBuilder::new("testTable", ClauseType::Update)
.add_where("Name = 'Connor'")
.or()
.add_where("Name = 'Franz'");
let r12 = conn.update(&claus, &[("age", "11")]);
//lets select everything again and confirm our results work
let r8 = conn.select_raw("testTable", "*", None, None, None);
let rows4: Vec<mysql::Row> = r8.unwrap();
for row in rows4 {
let tds = TestDataStruct::from_row(row);
println!("{}", tds.to_string());
}
}
Dependencies
~14–28MB
~436K SLoC