mirror of
https://github.com/actix/examples
synced 2024-11-27 16:02:57 +01:00
This commit is contained in:
parent
7736cbb7f7
commit
8e736d9ea4
13
databases/mysql/Cargo.toml
Normal file
13
databases/mysql/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "mysql"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
actix-web = "4.3.1"
|
||||
serde = { version = "1.0.136", features = ["derive"] }
|
||||
mysql = "24.0.0"
|
||||
dotenv = "0.15.0"
|
||||
chrono = "0.4.26"
|
80
databases/mysql/README.md
Normal file
80
databases/mysql/README.md
Normal file
@ -0,0 +1,80 @@
|
||||
# mysql
|
||||
|
||||
This RESTful Actix Web API examples illustrates how to connect to MySQL database using Mysql client library implemented in rust i.e MySql database driver
|
||||
|
||||
Below APIs are supported:
|
||||
- Add Bank
|
||||
- Add Branch
|
||||
- Add Teller
|
||||
- Add Customer
|
||||
- Get Bank
|
||||
- Get Branch
|
||||
- Get Teller
|
||||
- Get Customer
|
||||
|
||||
The RESTful Actix Web API has below listed dependencies:
|
||||
- [Actix Web](https://github.com/actix/actix-web) web framework for Rust
|
||||
- [Serde](https://github.com/serde-rs/serde) for serializing and deserializing Rust data structures
|
||||
- [MySQL](https://github.com/mysql/mysql-server) MySQL database server
|
||||
- [mysql](https://github.com/blackbeam/rust-mysql-simple) MySql database driver
|
||||
|
||||
## Instructions
|
||||
|
||||
### NOTE:
|
||||
|
||||
You may need to ensure that you are running the commands with the correct MySQL user/password.
|
||||
|
||||
1. Access MySQL Server
|
||||
|
||||
Log in to the MySQL Server using a user account that has the CREATE DATABASE privilege.
|
||||
|
||||
2. Create database
|
||||
|
||||
```sql
|
||||
CREATE DATABASE my_bank;
|
||||
```
|
||||
|
||||
3. Create tables in the database
|
||||
|
||||
Directory "mysql\sql" contains below listed ".sql" files:
|
||||
- bankdetails.sql
|
||||
- branch_details.sql
|
||||
- teller_details.sql
|
||||
- customer_details.sql
|
||||
|
||||
Copy the contents of each of the ".sql" and execute them separately on MySQL Server. This will create four tables in the database.
|
||||
|
||||
4. Create `.env` file:
|
||||
|
||||
```ini
|
||||
SERVER_ADDR=127.0.0.1:8080
|
||||
MYSQL_USER=XXX
|
||||
MYSQL_PASSWORD=XXX
|
||||
MYSQL_HOST=127.0.0.1
|
||||
MYSQL_PORT=3306
|
||||
MYSQL_DBNAME=my_bank
|
||||
```
|
||||
|
||||
Update "MYSQL_USER" and "MYSQL_PASSWORD" values with the correct MySQL user/password.
|
||||
If your password contains dollar sign "$", then remember to escape it eg "123$abc" will need to be changed to "123\\$abc"
|
||||
|
||||
5. Run the server:
|
||||
|
||||
```shell
|
||||
cargo run
|
||||
```
|
||||
|
||||
6. Using a different terminal send an HTTP GET/POST requests to the running server:
|
||||
|
||||
Directory "mysql\apis" contains below listed api's files:
|
||||
- addbank.txt
|
||||
- addbranch.txt
|
||||
- addteller.txt
|
||||
- addcustomer.txt
|
||||
- getbank.txt
|
||||
- getbranch.txt
|
||||
- getteller.txt
|
||||
- getcustomer.txt
|
||||
|
||||
Copy the curl request on each of the ".txt" and execute them on separate terminals. Each ".txt" contains curl request and expected json reponse data.
|
||||
|
17
databases/mysql/apis/addbank.txt
Normal file
17
databases/mysql/apis/addbank.txt
Normal file
@ -0,0 +1,17 @@
|
||||
1.
|
||||
Linux
|
||||
|
||||
curl -d '{"bank_name":"Bank ABC","country":"Kenya"}' -H 'Content-Type: application/json' http://127.0.0.1:8080/addbank
|
||||
|
||||
2.
|
||||
Windows
|
||||
|
||||
curl -H "Content-type:application/json" --data-binary "{\"bank_name\":\"Bank ABC\",\"country\":\"Kenya\"}" http://127.0.0.1:8080/addbank
|
||||
|
||||
3.
|
||||
Json response
|
||||
|
||||
{
|
||||
"status_code": 0,
|
||||
"status_description": "Successful"
|
||||
}
|
18
databases/mysql/apis/addbranch.txt
Normal file
18
databases/mysql/apis/addbranch.txt
Normal file
@ -0,0 +1,18 @@
|
||||
1.
|
||||
Linux
|
||||
|
||||
curl -d '{"branch_name":"HQ branch", "location":"Central Business District"}' -H 'Content-Type: application/json' http://127.0.0.1:8080/addbranch
|
||||
|
||||
2.
|
||||
Windows
|
||||
|
||||
curl -H "Content-type:application/json" --data-binary "{\"branch_name\":\"HQ branch\", \"location\":\"Central Business District\"}" http://127.0.0.1:8080/addbranch
|
||||
|
||||
|
||||
3.
|
||||
Json response
|
||||
|
||||
{
|
||||
"status_code": 0,
|
||||
"status_description": "Successful"
|
||||
}
|
18
databases/mysql/apis/addcustomer.txt
Normal file
18
databases/mysql/apis/addcustomer.txt
Normal file
@ -0,0 +1,18 @@
|
||||
1.
|
||||
Linux
|
||||
|
||||
curl -d '{"customer_name":"Peter Paul", "branch_name":"Central Business District"}' -H 'Content-Type: application/json' http://127.0.0.1:8080/addcustomer
|
||||
|
||||
2.
|
||||
Windows
|
||||
|
||||
curl -H "Content-type:application/json" --data-binary "{\"customer_name\":\"Peter Paul\", \"branch_name\":\"Central Business District\"}" http://127.0.0.1:8080/addcustomer
|
||||
|
||||
|
||||
3.
|
||||
Json response
|
||||
|
||||
{
|
||||
"status_code": 0,
|
||||
"status_description": "Successful"
|
||||
}
|
18
databases/mysql/apis/addteller.txt
Normal file
18
databases/mysql/apis/addteller.txt
Normal file
@ -0,0 +1,18 @@
|
||||
1.
|
||||
Linux
|
||||
|
||||
curl -d '{"teller_name":"John Doe", "branch_name":"Central Business District"}' -H 'Content-Type: application/json' http://127.0.0.1:8080/addteller
|
||||
|
||||
2.
|
||||
Windows
|
||||
|
||||
curl -H "Content-type:application/json" --data-binary "{\"teller_name\":\"John Doe\", \"branch_name\":\"Central Business District\"}" http://127.0.0.1:8080/addteller
|
||||
|
||||
|
||||
3.
|
||||
Json response
|
||||
|
||||
{
|
||||
"status_code": 0,
|
||||
"status_description": "Successful"
|
||||
}
|
23
databases/mysql/apis/getbank.txt
Normal file
23
databases/mysql/apis/getbank.txt
Normal file
@ -0,0 +1,23 @@
|
||||
1.
|
||||
Linux
|
||||
|
||||
curl 'http://localhost:8080/getbank'
|
||||
|
||||
2.
|
||||
Windows
|
||||
|
||||
curl http://localhost:8080/getbank
|
||||
|
||||
3.
|
||||
Json response
|
||||
|
||||
{
|
||||
"status_code": 0,
|
||||
"status_description": "Successful",
|
||||
"bank_data": [
|
||||
{
|
||||
"bank_name": "bank abc",
|
||||
"country": "kenya"
|
||||
}
|
||||
]
|
||||
}
|
23
databases/mysql/apis/getbranch.txt
Normal file
23
databases/mysql/apis/getbranch.txt
Normal file
@ -0,0 +1,23 @@
|
||||
1.
|
||||
Linux
|
||||
|
||||
curl 'http://localhost:8080/getbranch'
|
||||
|
||||
2.
|
||||
Windows
|
||||
|
||||
curl http://localhost:8080/getbranch
|
||||
|
||||
3.
|
||||
Json response
|
||||
|
||||
{
|
||||
"status_code": 0,
|
||||
"status_description": "Successful",
|
||||
"branch_data": [
|
||||
{
|
||||
"branch_name": "hq branch",
|
||||
"location": "central business district"
|
||||
}
|
||||
]
|
||||
}
|
23
databases/mysql/apis/getcustomer.txt
Normal file
23
databases/mysql/apis/getcustomer.txt
Normal file
@ -0,0 +1,23 @@
|
||||
1.
|
||||
Linux
|
||||
|
||||
curl 'http://localhost:8080/getcustomer'
|
||||
|
||||
2.
|
||||
Windows
|
||||
|
||||
curl http://localhost:8080/getcustomer
|
||||
|
||||
3.
|
||||
Json response
|
||||
|
||||
{
|
||||
"status_code": 0,
|
||||
"status_description": "Successful",
|
||||
"customer_data": [
|
||||
{
|
||||
"customer_name": "peter paul",
|
||||
"branch_name": "central business district"
|
||||
}
|
||||
]
|
||||
}
|
23
databases/mysql/apis/getteller.txt
Normal file
23
databases/mysql/apis/getteller.txt
Normal file
@ -0,0 +1,23 @@
|
||||
1.
|
||||
Linux
|
||||
|
||||
curl 'http://localhost:8080/getteller'
|
||||
|
||||
2.
|
||||
Windows
|
||||
|
||||
curl http://localhost:8080/getteller
|
||||
|
||||
3.
|
||||
Json response
|
||||
|
||||
{
|
||||
"status_code": 0,
|
||||
"status_description": "Successful",
|
||||
"teller_data": [
|
||||
{
|
||||
"teller_name": "john doe",
|
||||
"branch_name": "central business district"
|
||||
}
|
||||
]
|
||||
}
|
7
databases/mysql/sql/bankdetails.sql
Normal file
7
databases/mysql/sql/bankdetails.sql
Normal file
@ -0,0 +1,7 @@
|
||||
CREATE TABLE `bank_details` (
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`bank_name` varchar(30) DEFAULT '',
|
||||
`country` varchar(30) DEFAULT '',
|
||||
`date_added` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
|
7
databases/mysql/sql/branch_details.sql
Normal file
7
databases/mysql/sql/branch_details.sql
Normal file
@ -0,0 +1,7 @@
|
||||
CREATE TABLE `branch_details` (
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`branch_name` varchar(30) DEFAULT '',
|
||||
`location` varchar(30) DEFAULT '',
|
||||
`date_added` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
|
7
databases/mysql/sql/customer_details.sql
Normal file
7
databases/mysql/sql/customer_details.sql
Normal file
@ -0,0 +1,7 @@
|
||||
CREATE TABLE `customer_details` (
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`customer_name` varchar(100) DEFAULT '',
|
||||
`branch_name` varchar(30) DEFAULT '',
|
||||
`date_added` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
|
7
databases/mysql/sql/teller_details.sql
Normal file
7
databases/mysql/sql/teller_details.sql
Normal file
@ -0,0 +1,7 @@
|
||||
CREATE TABLE `teller_details` (
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`teller_name` varchar(100) DEFAULT '',
|
||||
`branch_name` varchar(30) DEFAULT '',
|
||||
`date_added` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
|
418
databases/mysql/src/db_layer.rs
Normal file
418
databases/mysql/src/db_layer.rs
Normal file
@ -0,0 +1,418 @@
|
||||
use crate::BankDetails;
|
||||
use crate::BankResponseData;
|
||||
use crate::BranchDetails;
|
||||
use crate::BranchResponseData;
|
||||
use crate::CustomerDetails;
|
||||
use crate::CustomerResponseData;
|
||||
use crate::ResponseStatus;
|
||||
use crate::TellerDetails;
|
||||
use crate::TellerResponseData;
|
||||
use actix_web::web;
|
||||
use mysql::prelude::*;
|
||||
use mysql::*;
|
||||
|
||||
const ERROR_MESSAGE: &str = "Error occured during processing, please try again.";
|
||||
|
||||
pub fn create_bank(data: &web::Data<Pool>, bank_name: String, _country: String) -> ResponseStatus {
|
||||
let my_status_code: u8 = 1;
|
||||
let my_status_description: String = ERROR_MESSAGE.to_string();
|
||||
|
||||
let mut response_status = ResponseStatus {
|
||||
status_code: my_status_code,
|
||||
status_description: my_status_description,
|
||||
};
|
||||
|
||||
if bank_name.replace(" ", "").trim().len() == 0 {
|
||||
response_status.status_description = String::from("Bank name is empty!");
|
||||
return response_status;
|
||||
}
|
||||
|
||||
if _country.replace(" ", "").trim().len() == 0 {
|
||||
response_status.status_description = String::from("Country is empty!");
|
||||
return response_status;
|
||||
}
|
||||
|
||||
match data.get_conn().and_then(|mut conn| {
|
||||
insert_bank_data(&mut conn, bank_name.to_lowercase(), _country.to_lowercase())
|
||||
}) {
|
||||
Ok(x) => {
|
||||
if x > 0 {
|
||||
response_status.status_code = 0;
|
||||
response_status.status_description = String::from("Successful");
|
||||
}
|
||||
}
|
||||
Err(e) => println!("Failed to open DB connection. create_bank {:?}", e),
|
||||
}
|
||||
|
||||
response_status
|
||||
}
|
||||
|
||||
pub fn create_branch(
|
||||
data: &web::Data<Pool>,
|
||||
branch_name: String,
|
||||
_location: String,
|
||||
) -> ResponseStatus {
|
||||
let my_status_code: u8 = 1;
|
||||
let my_status_description: String = ERROR_MESSAGE.to_string();
|
||||
|
||||
let mut response_status = ResponseStatus {
|
||||
status_code: my_status_code,
|
||||
status_description: my_status_description,
|
||||
};
|
||||
|
||||
if branch_name.replace(" ", "").trim().len() == 0 {
|
||||
response_status.status_description = String::from("Branch name is empty!");
|
||||
return response_status;
|
||||
}
|
||||
|
||||
if _location.replace(" ", "").trim().len() == 0 {
|
||||
response_status.status_description = String::from("Location is empty!");
|
||||
return response_status;
|
||||
}
|
||||
|
||||
match data.get_conn().and_then(|mut conn| {
|
||||
insert_branch_data(
|
||||
&mut conn,
|
||||
branch_name.to_lowercase(),
|
||||
_location.to_lowercase(),
|
||||
)
|
||||
}) {
|
||||
Ok(x) => {
|
||||
if x > 0 {
|
||||
response_status.status_code = 0;
|
||||
response_status.status_description = String::from("Successful");
|
||||
}
|
||||
}
|
||||
Err(e) => println!("Failed to open DB connection. create_branch {:?}", e),
|
||||
}
|
||||
|
||||
response_status
|
||||
}
|
||||
|
||||
pub fn create_teller(
|
||||
data: &web::Data<Pool>,
|
||||
teller_name: String,
|
||||
branch_name: String,
|
||||
) -> ResponseStatus {
|
||||
let my_status_code: u8 = 1;
|
||||
let my_status_description: String = ERROR_MESSAGE.to_string();
|
||||
|
||||
let mut response_status = ResponseStatus {
|
||||
status_code: my_status_code,
|
||||
status_description: my_status_description,
|
||||
};
|
||||
|
||||
if teller_name.replace(" ", "").trim().len() == 0 {
|
||||
response_status.status_description = String::from("Teller name is empty!");
|
||||
return response_status;
|
||||
}
|
||||
|
||||
if branch_name.replace(" ", "").trim().len() == 0 {
|
||||
response_status.status_description = String::from("Branch name is empty!");
|
||||
return response_status;
|
||||
}
|
||||
|
||||
match data.get_conn().and_then(|mut conn| {
|
||||
insert_teller_data(
|
||||
&mut conn,
|
||||
teller_name.to_lowercase(),
|
||||
branch_name.to_lowercase(),
|
||||
)
|
||||
}) {
|
||||
Ok(x) => {
|
||||
if x > 0 {
|
||||
response_status.status_code = 0;
|
||||
response_status.status_description = String::from("Successful");
|
||||
}
|
||||
}
|
||||
Err(e) => println!("Failed to open DB connection. create_teller {:?}", e),
|
||||
}
|
||||
|
||||
response_status
|
||||
}
|
||||
|
||||
pub fn create_customer(
|
||||
data: &web::Data<Pool>,
|
||||
customer_name: String,
|
||||
branch_name: String,
|
||||
) -> ResponseStatus {
|
||||
let my_status_code: u8 = 1;
|
||||
let my_status_description: String = ERROR_MESSAGE.to_string();
|
||||
|
||||
let mut response_status = ResponseStatus {
|
||||
status_code: my_status_code,
|
||||
status_description: my_status_description,
|
||||
};
|
||||
|
||||
if customer_name.replace(" ", "").trim().len() == 0 {
|
||||
response_status.status_description = String::from("Customer name is empty!");
|
||||
return response_status;
|
||||
}
|
||||
|
||||
if branch_name.replace(" ", "").trim().len() == 0 {
|
||||
response_status.status_description = String::from("Branch name is empty!");
|
||||
return response_status;
|
||||
}
|
||||
|
||||
match data.get_conn().and_then(|mut conn| {
|
||||
insert_customer_data(
|
||||
&mut conn,
|
||||
customer_name.to_lowercase(),
|
||||
branch_name.to_lowercase(),
|
||||
)
|
||||
}) {
|
||||
Ok(x) => {
|
||||
if x > 0 {
|
||||
response_status.status_code = 0;
|
||||
response_status.status_description = String::from("Successful");
|
||||
}
|
||||
}
|
||||
Err(e) => println!("Failed to open DB connection. create_customer {:?}", e),
|
||||
}
|
||||
|
||||
response_status
|
||||
}
|
||||
|
||||
pub fn get_bank_data(data: &web::Data<Pool>) -> BankResponseData {
|
||||
let mut vec_bank_data = Vec::new();
|
||||
let mut my_status_code: u8 = 1;
|
||||
let mut my_status_description: String = String::from("Record not found");
|
||||
|
||||
match data
|
||||
.get_conn()
|
||||
.and_then(|mut conn| select_bank_details(&mut conn))
|
||||
{
|
||||
Ok(s) => {
|
||||
vec_bank_data = s;
|
||||
}
|
||||
Err(e) => println!("Failed to open DB connection. {:?}", e),
|
||||
}
|
||||
|
||||
if vec_bank_data.len() > 0 {
|
||||
my_status_code = 0;
|
||||
my_status_description = String::from("Successful");
|
||||
}
|
||||
|
||||
//Assign values to struct variable
|
||||
let output_data = BankResponseData {
|
||||
status_code: my_status_code,
|
||||
status_description: my_status_description,
|
||||
bank_data: vec_bank_data,
|
||||
};
|
||||
|
||||
output_data
|
||||
}
|
||||
|
||||
pub fn get_branch_data(data: &web::Data<Pool>) -> BranchResponseData {
|
||||
let mut vec_branch_data = Vec::new();
|
||||
let mut my_status_code: u8 = 1;
|
||||
let mut my_status_description: String = String::from("Record not found");
|
||||
|
||||
match data
|
||||
.get_conn()
|
||||
.and_then(|mut conn| select_branch_details(&mut conn))
|
||||
{
|
||||
Ok(s) => {
|
||||
vec_branch_data = s;
|
||||
}
|
||||
Err(e) => println!("Failed to open DB connection. {:?}", e),
|
||||
}
|
||||
|
||||
if vec_branch_data.len() > 0 {
|
||||
my_status_code = 0;
|
||||
my_status_description = String::from("Successful");
|
||||
}
|
||||
|
||||
//Assign values to struct variable
|
||||
let output_data = BranchResponseData {
|
||||
status_code: my_status_code,
|
||||
status_description: my_status_description,
|
||||
branch_data: vec_branch_data,
|
||||
};
|
||||
|
||||
output_data
|
||||
}
|
||||
|
||||
pub fn get_teller_data(data: &web::Data<Pool>) -> TellerResponseData {
|
||||
let mut vec_teller_data = Vec::new();
|
||||
let mut my_status_code: u8 = 1;
|
||||
let mut my_status_description: String = String::from("Record not found");
|
||||
|
||||
match data
|
||||
.get_conn()
|
||||
.and_then(|mut conn| select_teller_details(&mut conn))
|
||||
{
|
||||
Ok(s) => {
|
||||
vec_teller_data = s;
|
||||
}
|
||||
Err(e) => println!("Failed to open DB connection. {:?}", e),
|
||||
}
|
||||
|
||||
if vec_teller_data.len() > 0 {
|
||||
my_status_code = 0;
|
||||
my_status_description = String::from("Successful");
|
||||
}
|
||||
|
||||
//Assign values to struct variable
|
||||
let output_data = TellerResponseData {
|
||||
status_code: my_status_code,
|
||||
status_description: my_status_description,
|
||||
teller_data: vec_teller_data,
|
||||
};
|
||||
|
||||
output_data
|
||||
}
|
||||
|
||||
pub fn get_customer_data(data: &web::Data<Pool>) -> CustomerResponseData {
|
||||
let mut vec_customer_data = Vec::new();
|
||||
let mut my_status_code: u8 = 1;
|
||||
let mut my_status_description: String = String::from("Record not found");
|
||||
|
||||
match data
|
||||
.get_conn()
|
||||
.and_then(|mut conn| select_customer_details(&mut conn))
|
||||
{
|
||||
Ok(s) => {
|
||||
vec_customer_data = s;
|
||||
}
|
||||
Err(e) => println!("Failed to open DB connection. {:?}", e),
|
||||
}
|
||||
|
||||
if vec_customer_data.len() > 0 {
|
||||
my_status_code = 0;
|
||||
my_status_description = String::from("Successful");
|
||||
}
|
||||
|
||||
//Assign values to struct variable
|
||||
let output_data = CustomerResponseData {
|
||||
status_code: my_status_code,
|
||||
status_description: my_status_description,
|
||||
customer_data: vec_customer_data,
|
||||
};
|
||||
|
||||
output_data
|
||||
}
|
||||
|
||||
fn insert_bank_data(
|
||||
conn: &mut PooledConn,
|
||||
my_bank_name: String,
|
||||
my_country: String,
|
||||
) -> std::result::Result<u64, mysql::error::Error> {
|
||||
// Insert data into the database table bank_details
|
||||
conn.exec_drop(
|
||||
"insert into bank_details (bank_name, country) values (:bank_name, :country);",
|
||||
params! {
|
||||
"bank_name" => my_bank_name,
|
||||
"country" => my_country,
|
||||
},
|
||||
)
|
||||
.and_then(|_| Ok(conn.last_insert_id()))
|
||||
}
|
||||
|
||||
fn insert_branch_data(
|
||||
conn: &mut PooledConn,
|
||||
my_branch_name: String,
|
||||
my_location: String,
|
||||
) -> std::result::Result<u64, mysql::error::Error> {
|
||||
// Insert data into the database table branch_details
|
||||
conn.exec_drop(
|
||||
"insert into branch_details (branch_name, location) values (:branch_name, :location);",
|
||||
params! {
|
||||
"branch_name" => my_branch_name,
|
||||
"location" => my_location,
|
||||
},
|
||||
)
|
||||
.and_then(|_| Ok(conn.last_insert_id()))
|
||||
}
|
||||
|
||||
fn insert_teller_data(
|
||||
conn: &mut PooledConn,
|
||||
my_teller_name: String,
|
||||
my_branch_name: String,
|
||||
) -> std::result::Result<u64, mysql::error::Error> {
|
||||
// Insert data into the database table teller_details
|
||||
conn.exec_drop(
|
||||
"insert into teller_details (teller_name, branch_name) values (:teller_name, :branch_name);",
|
||||
params! {
|
||||
"teller_name" => my_teller_name,
|
||||
"branch_name" => my_branch_name,
|
||||
},
|
||||
)
|
||||
.and_then(|_| Ok(conn.last_insert_id()))
|
||||
}
|
||||
|
||||
fn insert_customer_data(
|
||||
conn: &mut PooledConn,
|
||||
my_customer_name: String,
|
||||
my_branch_name: String,
|
||||
) -> std::result::Result<u64, mysql::error::Error> {
|
||||
// Insert data into the database table customer_details
|
||||
conn.exec_drop(
|
||||
"insert into customer_details (customer_name, branch_name) values (:customer_name, :branch_name);",
|
||||
params! {
|
||||
"customer_name" => my_customer_name,
|
||||
"branch_name" => my_branch_name,
|
||||
},
|
||||
)
|
||||
.and_then(|_| Ok(conn.last_insert_id()))
|
||||
}
|
||||
|
||||
fn select_bank_details(
|
||||
conn: &mut PooledConn,
|
||||
) -> std::result::Result<Vec<BankDetails>, mysql::error::Error> {
|
||||
let mut bank_data = Vec::new();
|
||||
|
||||
conn.query_map(
|
||||
"select bank_name, country from bank_details where length(trim(coalesce(bank_name,''))) > 0 and length(trim(coalesce(country,''))) > 0 order by id asc;",
|
||||
|(my_bank_name, my_country)| {
|
||||
let bank_details = BankDetails { bank_name: my_bank_name, country: my_country, };
|
||||
bank_data.push(bank_details);
|
||||
},
|
||||
)
|
||||
.and_then(|_| Ok(bank_data))
|
||||
}
|
||||
|
||||
fn select_branch_details(
|
||||
conn: &mut PooledConn,
|
||||
) -> std::result::Result<Vec<BranchDetails>, mysql::error::Error> {
|
||||
let mut branch_data = Vec::new();
|
||||
|
||||
conn.query_map(
|
||||
"select branch_name, location from branch_details where length(trim(coalesce(branch_name,''))) > 0 and length(trim(coalesce(location,''))) > 0 order by id asc;",
|
||||
|(my_branch_name, my_location)| {
|
||||
let branch_details = BranchDetails { branch_name: my_branch_name, location: my_location, };
|
||||
branch_data.push(branch_details);
|
||||
},
|
||||
)
|
||||
.and_then(|_| Ok(branch_data))
|
||||
}
|
||||
|
||||
fn select_teller_details(
|
||||
conn: &mut PooledConn,
|
||||
) -> std::result::Result<Vec<TellerDetails>, mysql::error::Error> {
|
||||
let mut teller_data = Vec::new();
|
||||
|
||||
conn.query_map(
|
||||
"select teller_name, branch_name from teller_details where length(trim(coalesce(teller_name,''))) > 0 and length(trim(coalesce(branch_name,''))) > 0 order by id asc;",
|
||||
|(my_teller_name, my_branch_name)| {
|
||||
let teller_details = TellerDetails { teller_name: my_teller_name, branch_name: my_branch_name, };
|
||||
teller_data.push(teller_details);
|
||||
},
|
||||
)
|
||||
.and_then(|_| Ok(teller_data))
|
||||
}
|
||||
|
||||
fn select_customer_details(
|
||||
conn: &mut PooledConn,
|
||||
) -> std::result::Result<Vec<CustomerDetails>, mysql::error::Error> {
|
||||
let mut customer_data = Vec::new();
|
||||
|
||||
conn.query_map(
|
||||
"select customer_name, branch_name from customer_details where length(trim(coalesce(customer_name,''))) > 0 and length(trim(coalesce(branch_name,''))) > 0 order by id asc;",
|
||||
|(my_customer_name, my_branch_name)| {
|
||||
let teller_details = CustomerDetails { customer_name: my_customer_name, branch_name: my_branch_name, };
|
||||
customer_data.push(teller_details);
|
||||
},
|
||||
)
|
||||
.and_then(|_| Ok(customer_data))
|
||||
}
|
246
databases/mysql/src/main.rs
Normal file
246
databases/mysql/src/main.rs
Normal file
@ -0,0 +1,246 @@
|
||||
mod db_layer;
|
||||
|
||||
use actix_web::{get, post, web, App, HttpServer, Responder};
|
||||
use dotenv::dotenv;
|
||||
use mysql::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::env;
|
||||
use std::str;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct BankData {
|
||||
bank_name: String,
|
||||
country: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct BranchData {
|
||||
branch_name: String,
|
||||
location: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct TellerData {
|
||||
teller_name: String,
|
||||
branch_name: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct CustomerData {
|
||||
customer_name: String,
|
||||
branch_name: String,
|
||||
}
|
||||
|
||||
// output
|
||||
#[derive(Serialize)]
|
||||
pub struct ResponseStatus {
|
||||
pub status_code: u8,
|
||||
pub status_description: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct BankDetails {
|
||||
pub bank_name: String,
|
||||
pub country: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct BankResponseData {
|
||||
pub status_code: u8,
|
||||
pub status_description: String,
|
||||
pub bank_data: Vec<BankDetails>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct BranchDetails {
|
||||
pub branch_name: String,
|
||||
pub location: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct BranchResponseData {
|
||||
pub status_code: u8,
|
||||
pub status_description: String,
|
||||
pub branch_data: Vec<BranchDetails>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct TellerDetails {
|
||||
pub teller_name: String,
|
||||
pub branch_name: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct TellerResponseData {
|
||||
pub status_code: u8,
|
||||
pub status_description: String,
|
||||
pub teller_data: Vec<TellerDetails>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct CustomerDetails {
|
||||
pub customer_name: String,
|
||||
pub branch_name: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct CustomerResponseData {
|
||||
pub status_code: u8,
|
||||
pub status_description: String,
|
||||
pub customer_data: Vec<CustomerDetails>,
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
async fn index() -> impl Responder {
|
||||
format!("")
|
||||
}
|
||||
|
||||
#[post("/addbank")]
|
||||
async fn add_bank(bank_data: web::Json<BankData>, data: web::Data<Pool>) -> impl Responder {
|
||||
let bank_name = &bank_data.bank_name;
|
||||
let _country = &bank_data.country;
|
||||
|
||||
let response_data = db_layer::create_bank(&data, bank_name.to_string(), _country.to_string());
|
||||
|
||||
web::Json(response_data)
|
||||
}
|
||||
|
||||
#[post("/addbranch")]
|
||||
async fn add_branch(branch_data: web::Json<BranchData>, data: web::Data<Pool>) -> impl Responder {
|
||||
let branch_name = &branch_data.branch_name;
|
||||
let _location = &branch_data.location;
|
||||
|
||||
let response_data =
|
||||
db_layer::create_branch(&data, branch_name.to_string(), _location.to_string());
|
||||
|
||||
web::Json(response_data)
|
||||
}
|
||||
|
||||
#[post("/addteller")]
|
||||
async fn add_teller(teller_data: web::Json<TellerData>, data: web::Data<Pool>) -> impl Responder {
|
||||
let teller_name = &teller_data.teller_name;
|
||||
let branch_name = &teller_data.branch_name;
|
||||
|
||||
let response_data =
|
||||
db_layer::create_teller(&data, teller_name.to_string(), branch_name.to_string());
|
||||
|
||||
web::Json(response_data)
|
||||
}
|
||||
|
||||
#[post("/addcustomer")]
|
||||
async fn add_customer(
|
||||
customer_data: web::Json<CustomerData>,
|
||||
data: web::Data<Pool>,
|
||||
) -> impl Responder {
|
||||
let customer_name = &customer_data.customer_name;
|
||||
let branch_name = &customer_data.branch_name;
|
||||
|
||||
let response_data =
|
||||
db_layer::create_customer(&data, customer_name.to_string(), branch_name.to_string());
|
||||
|
||||
web::Json(response_data)
|
||||
}
|
||||
|
||||
#[get("/getbank")]
|
||||
async fn get_bank(data: web::Data<Pool>) -> impl Responder {
|
||||
let bank_response_data = db_layer::get_bank_data(&data);
|
||||
|
||||
web::Json(bank_response_data)
|
||||
}
|
||||
|
||||
#[get("/getbranch")]
|
||||
async fn get_branch(data: web::Data<Pool>) -> impl Responder {
|
||||
let branch_response_data = db_layer::get_branch_data(&data);
|
||||
|
||||
web::Json(branch_response_data)
|
||||
}
|
||||
|
||||
#[get("/getteller")]
|
||||
async fn get_teller(data: web::Data<Pool>) -> impl Responder {
|
||||
let teller_response_data = db_layer::get_teller_data(&data);
|
||||
|
||||
web::Json(teller_response_data)
|
||||
}
|
||||
|
||||
#[get("/getcustomer")]
|
||||
async fn get_customer(data: web::Data<Pool>) -> impl Responder {
|
||||
let customer_response_data = db_layer::get_customer_data(&data);
|
||||
|
||||
web::Json(customer_response_data)
|
||||
}
|
||||
|
||||
fn get_conn_builder(
|
||||
db_user: String,
|
||||
db_password: String,
|
||||
db_host: String,
|
||||
db_port: u16,
|
||||
db_name: String,
|
||||
) -> OptsBuilder {
|
||||
let builder = OptsBuilder::new()
|
||||
.ip_or_hostname(Some(db_host))
|
||||
.tcp_port(db_port)
|
||||
.db_name(Some(db_name))
|
||||
.user(Some(db_user))
|
||||
.pass(Some(db_password));
|
||||
builder
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() {
|
||||
// get env vars
|
||||
dotenv().ok();
|
||||
let server_addr = env::var("SERVER_ADDR").expect("SERVER_ADDR is not set in .env file");
|
||||
let db_user = env::var("MYSQL_USER").expect("MYSQL_USER is not set in .env file");
|
||||
let db_password = env::var("MYSQL_PASSWORD").expect("MYSQL_PASSWORD is not set in .env file");
|
||||
let db_host = env::var("MYSQL_HOST").expect("MYSQL_HOST is not set in .env file");
|
||||
let my_db_port = env::var("MYSQL_PORT").expect("MYSQL_PORT is not set in .env file");
|
||||
let db_name = env::var("MYSQL_DBNAME").expect("MYSQL_DBNAME is not set in .env file");
|
||||
let mut http_server_status = String::from("[info] ActixWebHttpServer - Listening for HTTP on ");
|
||||
let db_port: u16 = match my_db_port.parse::<u16>() {
|
||||
Ok(a) => a,
|
||||
Err(e) => 0,
|
||||
};
|
||||
|
||||
http_server_status.push_str(&server_addr);
|
||||
|
||||
let builder: OptsBuilder = get_conn_builder(db_user, db_password, db_host, db_port, db_name);
|
||||
let pool = match Pool::new(builder) {
|
||||
Ok(pool) => pool,
|
||||
Err(e) => {
|
||||
println!("Failed to open DB connection. {:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let shared_data = web::Data::new(pool);
|
||||
|
||||
let server = match HttpServer::new(move || {
|
||||
App::new()
|
||||
.app_data(shared_data.clone())
|
||||
.service(index)
|
||||
.service(add_bank)
|
||||
.service(add_branch)
|
||||
.service(add_teller)
|
||||
.service(add_customer)
|
||||
.service(get_bank)
|
||||
.service(get_branch)
|
||||
.service(get_teller)
|
||||
.service(get_customer)
|
||||
})
|
||||
.bind(server_addr)
|
||||
{
|
||||
Ok(s) => {
|
||||
println!("{:?}", http_server_status);
|
||||
s
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Failed to bind port. {:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
match server.run().await {
|
||||
Ok(_) => println!("Server exited normally."),
|
||||
Err(e) => println!("Server exited with error: {:?}", e),
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user