This is a follow-up from this question. There I successfully made one global variable so I can access my database-connection in my whole code.
Now I switched the crate to Diesel, and this doesn't work anymore.
Code:
use actix_cors::Cors;
use actix_web::{web, get, middleware, Result, Responder, HttpResponse, HttpServer, App};
use actix_web::http::StatusCode;
use serde::Deserialize;
#[macro_use]
extern crate lazy_static;
extern crate regex;
#[macro_use]
extern crate diesel;
use regex::Regex;
use diesel::insert_into;
use diesel::mysql::Mysql;
use diesel::prelude::*;
use diesel::debug_query;
mod schema {
table! {
users (id) {
id -> Integer,
username -> VarChar,
email -> VarChar,
password -> VarChar,
birthdate -> Timestamp,
}
}
}
use schema::users;
lazy_static! {
static ref db : mysqldata::MySQLData = mysqldata::MySQLData::init_connection(&String::from("rustsite"), &String::from("root"), &String::from("toor"));
}
// Module for MySQL
pub mod mysqldata {
use crate::RegistrationForm;
use diesel::mysql::MysqlConnection;
use diesel::insert_into;
use diesel::mysql::Mysql;
use diesel::prelude::*;
use diesel::debug_query;
pub struct MySQLData {
pub conn: MysqlConnection
}
impl MySQLData {
//Return MySQLData object with conn field
pub fn init_connection(database_name : &String, database_user : &String, database_pass : &String) -> MySQLData {
let conn_str : String = format!("mysql://{user}:{pass}@localhost/{name}", user=database_user, pass=database_pass, name=database_name);
let conn = MysqlConnection::establish(&conn_str);
match conn {
Ok(_) => {
println!("Connection to {} successful!", database_name);
MySQLData {
conn: conn.unwrap()
}
},
Err(e) => {
eprintln!("Connection to {} failed: {}", database_name, e.to_string());
std::process::exit(-1);
}
}
}
pub fn add_user(&self, data: RegistrationForm) -> bool {
use crate::schema::users::dsl::*;
let new_user = (username.eq(data.username), email.eq(data.email), password.eq(data.password));
let query = insert_into(users)
.values(&new_user)
.execute(&self.conn);
match query {
Ok(_) => {
println!("User {} added!", data.username);
true
}
Err(e) => {
eprintln!("Failed to add user {}: {}", data.username, e.to_string());
false
}
}
}
pub fn read_user(&mut self, id: u8) -> RegistrationForm {
unimplemented!()
}
}
}
#[derive(Deserialize)]
pub struct RegistrationForm {
username: String,
email: String,
birthdate: String,
password: String,
rp_password: String
}
impl RegistrationForm {
pub fn is_valid(&self) -> bool {
if self.username.is_empty() ||
self.email.is_empty() ||
self.birthdate.is_empty() ||
self.password.is_empty() ||
self.rp_password.is_empty() {
println!("User {} did not fill in all inputs!", self.username);
return false
}
if self.password != self.rp_password {
println!("User {} did not repeat the password correctly!", self.username);
return false
}
let re_date = Regex::new(r"^\d{2}-\d{2}-\d{4}$").unwrap();
if !re_date.is_match(&*&self.birthdate) {
println!("{} for user {} is not a valid date", self.birthdate, self.username);
return false
}
let re_email = Regex::new(r"[\w._%+-]+@[\w.-]+\.[a-zA-Z]{2,3}").unwrap();
if !re_email.is_match(&*&self.email) {
println!("{} for user {} is not a valid mail-address", self.email, self.username);
return false
}
true
}
}
//Function which gets executed with correct route
async fn register(form: web::Form<RegistrationForm>) -> String {
let registration_form = form.into_inner();
if !registration_form.is_valid() {
return String::from("error");
}
}
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new()
.wrap(
Cors::new()
.allowed_origin("http://rustsite.local")
.finish()
)
.service(
web::resource("/register").route(web::post().to(register))
)
)
.bind("127.0.0.1:8088")?
.run()
.await
}
Error:
error[E0277]: `std::ptr::NonNull<mysqlclient_sys::st_mysql>` cannot be shared between threads safely
--> src/main.rs:34:1
|
34 | / lazy_static! {
35 | | static ref db : mysqldata::MySQLData = mysqldata::MySQLData::init_connection(&String::from("rustsite"), &String::from("root"), &Strin...
36 | | }
| |_^ `std::ptr::NonNull<mysqlclient_sys::st_mysql>` cannot be shared between threads safely
|
::: /Users/niel/.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-1.4.0/src/inline_lazy.rs:19:20
|
19 | pub struct Lazy<T: Sync>(Cell<Option<T>>, Once);
| ---- required by this bound in `lazy_static::lazy::Lazy`
|
= help: within `mysqldata::MySQLData`, the trait `std::marker::Sync` is not implemented for `std::ptr::NonNull<mysqlclient_sys::st_mysql>`
= note: required because it appears within the type `diesel::mysql::connection::raw::RawConnection`
= note: required because it appears within the type `diesel::MysqlConnection`
= note: required because it appears within the type `mysqldata::MySQLData`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: `std::cell::Cell<i32>` cannot be shared between threads safely
--> src/main.rs:34:1
|
34 | / lazy_static! {
35 | | static ref db : mysqldata::MySQLData = mysqldata::MySQLData::init_connection(&String::from("rustsite"), &String::from("root"), &Strin...
36 | | }
| |_^ `std::cell::Cell<i32>` cannot be shared between threads safely
|
::: /Users/niel/.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-1.4.0/src/inline_lazy.rs:19:20
|
19 | pub struct Lazy<T: Sync>(Cell<Option<T>>, Once);
| ---- required by this bound in `lazy_static::lazy::Lazy`
|
= help: within `mysqldata::MySQLData`, the trait `std::marker::Sync` is not implemented for `std::cell::Cell<i32>`
= note: required because it appears within the type `diesel::connection::AnsiTransactionManager`
= note: required because it appears within the type `diesel::MysqlConnection`
= note: required because it appears within the type `mysqldata::MySQLData`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: `std::cell::RefCell<std::collections::HashMap<diesel::connection::StatementCacheKey<diesel::mysql::Mysql>, diesel::mysql::connection::stmt::Statement>>` cannot be shared between threads safely
--> src/main.rs:34:1
|
34 | / lazy_static! {
35 | | static ref db : mysqldata::MySQLData = mysqldata::MySQLData::init_connection(&String::from("rustsite"), &String::from("root"), &Strin...
36 | | }
| |_^ `std::cell::RefCell<std::collections::HashMap<diesel::connection::StatementCacheKey<diesel::mysql::Mysql>, diesel::mysql::connection::stmt::Statement>>` cannot be shared between threads safely
|
::: /Users/niel/.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-1.4.0/src/inline_lazy.rs:19:20
|
19 | pub struct Lazy<T: Sync>(Cell<Option<T>>, Once);
| ---- required by this bound in `lazy_static::lazy::Lazy`
|
= help: within `mysqldata::MySQLData`, the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<std::collections::HashMap<diesel::connection::StatementCacheKey<diesel::mysql::Mysql>, diesel::mysql::connection::stmt::Statement>>`
= note: required because it appears within the type `diesel::connection::StatementCache<diesel::mysql::Mysql, diesel::mysql::connection::stmt::Statement>`
= note: required because it appears within the type `diesel::MysqlConnection`
= note: required because it appears within the type `mysqldata::MySQLData`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors; 9 warnings emitted
For more information about this error, try `rustc --explain E0277`.
error: could not compile `rustSite1`.
To learn more, run the command again with --verbose.