Database-handling: delete from backend since handled in its own crate

Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
This commit is contained in:
2020-06-09 15:42:32 +02:00
parent 37b5a50f50
commit ccf276e07a
7 changed files with 0 additions and 752 deletions

View File

@@ -1,6 +0,0 @@
# For documentation on how to configure this file,
# see diesel.rs/guides/configuring-diesel-cli
[print_schema]
file = "src/db/schema.rs"
#filter = { only_tables = [ "User", "UserRole" ] }

View File

@@ -1,17 +0,0 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2019 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: 0BSD
*/
DROP INDEX IF EXISTS NumberHarm_ix_numberHarm;
DROP TABLE IF EXISTS NumberHarm;
DROP INDEX IF EXISTS UserClaim_ix_userId;
DROP TABLE IF EXISTS UserClaim;
DROP VIEW IF EXISTS View_UserRole;
DROP INDEX IF EXISTS UserUserRole_ix_roleId;
DROP INDEX IF EXISTS UserUserRole_ix_userId;
DROP TABLE IF EXISTS UserUserRole;
DROP TABLE IF EXISTS UserRole;
DROP TABLE IF EXISTS User;

View File

@@ -1,81 +0,0 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2019 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD, MIT)
*/
-- sqlite3 advotracker.db \
-- .read advotracker_sqlite.sql
CREATE TABLE IF NOT EXISTS users
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
last_name VARCHAR,
first_name VARCHAR,
alias VARCHAR,
email VARCHAR,
/* email_confirmed boolean NOT NULL DEFAULT 0, */
email_confirmed INTEGER NOT NULL DEFAULT 0,
password_hash VARCHAR,
initials VARCHAR,
date_created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
date_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
-- Constraints
CONSTRAINT users_ck_email_confirmed CHECK (email_confirmed IN (0,1))
);
CREATE INDEX IF NOT EXISTS users_ix_email ON users (email);
CREATE TABLE IF NOT EXISTS user_roles(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR,
-- Constraints
CONSTRAINT user_roles_uk_name UNIQUE (name));
CREATE TABLE IF NOT EXISTS user_user_roles (
user_id INTEGER NOT NULL,
role_id INTEGER NOT NULL,
-- Constraints
CONSTRAINT user_user_roles_pk_user_id_role_id PRIMARY KEY (user_id, role_id),
CONSTRAINT user_user_roles_fk_user_id FOREIGN KEY (user_id)
REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT user_user_roles_fk_role_id FOREIGN KEY (role_id)
REFERENCES user_roles (id) ON DELETE CASCADE ON UPDATE CASCADE);
CREATE INDEX IF NOT EXISTS user_user_roles_ix_user_id ON user_user_roles (user_id);
CREATE INDEX IF NOT EXISTS user_user_roles_ix_role_id ON user_user_roles (role_id);
CREATE VIEW IF NOT EXISTS view_user_roles
AS SELECT
users.user_id AS user_id,
users.last_name AS last_name,
users.first_name AS first_name,
users.email AS email,
users.user_initials AS initials,
users_role.user_rolename AS role_name
FROM user_user_roles
INNER JOIN users ON users.user_id = user_user_roles.user_id
INNER JOIN user_roles ON user_roles.id = user_user_roles.role_id;
CREATE TABLE IF NOT EXISTS user_claims (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
type VARCHAR,
value VARCHAR,
-- CONSTRAINTS
CONSTRAINT user_claims_fk_user_id FOREIGN KEY (user_id)
REFERENCES users (id) ON DELETE CASCADE ON UPDATE CASCADE);
CREATE INDEX IF NOT EXISTS user_claims_ix_user_id ON user_claims (user_id);
CREATE TABLE IF NOT EXISTS harms (
id INTEGER primary key AUTOINCREMENT,
number_harm VARCHAR,
number_policyholder VARCHAR,
number_callback VARCHAR,
date_fallback TIMESTAMP,
date_recording TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
user_id INTEGER NOT NULL,
date_changed TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
user_id_changed INTEGER);
CREATE INDEX IF NOT EXISTS harms_ix_number_harm ON harms (number_harm);

View File

@@ -1,313 +0,0 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2019 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
//use diesel::{debug_query, dsl::insert_into};
#[cfg(test)]
use diesel::debug_query;
use diesel::dsl::*;
use diesel::prelude::*;
//use diesel::sql_query;
#[cfg(test)]
use diesel::sqlite::Sqlite;
use diesel::sqlite::SqliteConnection;
use dotenv::dotenv;
use std::env;
use std::error::Error;
//use models::ConfirmState;
// modules
pub mod models;
pub mod schema;
pub mod types;
// functions
pub fn establish_connection() -> SqliteConnection {
dotenv().ok();
let database_url = env::var("DATABASE_URL")
.expect("DATABASE_URL must be set");
SqliteConnection::establish(&database_url)
.unwrap_or_else(|_| panic!("Error connecting to {}",
&database_url))
/*
* WIP: integrate tracing!
trace!(
target: "diesel",
type: "Sqlite3",
status: "connected"
);
*/
}
pub fn users_insert_default_values(conn: &SqliteConnection) -> QueryResult<usize> {
use schema::users::dsl::*;
insert_into(users).default_values().execute(conn)
}
#[test]
fn examine_sql_users_insert_default_values() {
use schema::users::dsl::*;
let query = insert_into(users).default_values();
let sql = "INSERT INTO `users` DEFAULT VALUES -- binds: []";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
pub fn user_roles_insert_default_values(conn: &SqliteConnection) -> QueryResult<usize> {
use schema::user_roles::dsl::*;
insert_into(user_roles).default_values().execute(conn)
}
#[test]
fn examine_sql_user_roles_insert_default_values() {
use schema::user_roles::dsl::*;
let query = insert_into(user_roles).default_values();
let sql = "INSERT INTO `user_roles` DEFAULT VALUES -- binds: []";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
pub fn user_harms_insert_default_values(conn: &SqliteConnection) -> QueryResult<usize> {
use schema::harms::dsl::*;
insert_into(harms).default_values().execute(conn)
}
#[test]
fn examine_sql_harms_insert_default_values() {
use schema::harms::dsl::*;
let query = insert_into(harms).default_values();
let sql = "INSERT INTO `harms` DEFAULT VALUES -- binds: []";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
pub fn users_insert_single_column(conn: &SqliteConnection) -> QueryResult<usize> {
use schema::users::dsl::*;
insert_into(users).values(alias.eq("Hiedemann")).execute(conn)
}
#[test]
fn examine_sql_users_insert_single_column() {
use schema::users::dsl::*;
let query = insert_into(users).values(alias.eq("Hiedemann"));
let sql = "INSERT INTO `users` (`alias`) VALUES (?) \
-- binds: [\"Hiedemann\"]";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
pub fn users_insert_multiple_columns(conn: &SqliteConnection) -> QueryResult<usize> {
use schema::users::dsl::*;
insert_into(users)
.values((first_name.eq("Lothar"),
last_name.eq("Schlömer"),
alias.eq("102")))
.execute(conn)
}
#[test]
fn examine_sql_user_insert_multiple_columns() {
use schema::users::dsl::*;
let query = insert_into(users)
.values((first_name.eq("Lothar"),
last_name.eq("Schlömer"),
alias.eq("102")));
let sql = "INSERT INTO `users` (`first_name`, `last_name`, `alias`) \
VALUES (?, ?, ?) \
-- binds: [\"Lothar\", \"Schlömer\", \"102\"]";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
/*
pub fn user_insert_struct_via_json(conn: &SqliteConnection) -> Result<(), Box<dyn Error>> {
use models::NewUser;
use schema::users::dsl::*;
let json = r#"{ "alias": "Daniela", "first_name": "Daniela","last_name": "Knocke" }"#;
let user_struct = serde_json::from_str::<NewUser>(json)?;
insert_into(users).values(&user_struct).execute(conn)?;
Ok(())
}
*/
/*
#[test]
fn examine_sql_user_insert_struct_via_json() {
use models::NewUser;
use schema::users::dsl::*;
let json = r#"{ "last_name": "Knocke", "first_name": "Daniela", "alias": "Sekretariat" }"#;
let user_form = serde_json::from_str::<NewUser>(json).unwrap();
let query = insert_into(users).values(&user_form);
let sql = "INSERT INTO `users` (`last_name`, `first_name`, `alias`) \
VALUES (?, ?, ?) \
-- binds: [\"Knocke\", \"Daniela\", \"Sekretariat\"]";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
*/
/*
pub fn user_insert_struct_json_option(conn: &SqliteConnection) -> Result<(), Box<dyn Error>> {
use models::NewUser;
use schema::users::dsl::*;
let json = r#"{ "alias": "Networkx", "email_confirmed": true,
"email": "support@networkx.de", "first_name": null, "last_name": null }"#; let user_form =
serde_json::from_str::<NewUser>(json)?;
insert_into(users).values(&user_form).execute(conn)?;
Ok(())
}
*/
/*
#[test]
fn examine_sql_user_insert_struct_json_option() {
use schema::users::dsl::*;
use models::NewUser;
let json = r#"{ "alias": "Networkx", "email_confirmed": true, "email": "support@networkx.de", "first_name": null, "last_name": null }"#;
let user_form = serde_json::from_str::<NewUser>(json).unwrap();
let query = insert_into(users).values(&user_form);
let sql = "INSERT INTO `users` (`alias`, `email`, `email_confirmed`) \
VALUES (?, ?, ?) \
-- binds: [\"Networkx\", \"support@networkx.de\", \"$true\"]";
assert_eq!(sql, debug_query::<Sqlite, _>(&query).to_string());
}
*/
// WIP
/*
#[test]
fn examine_sql_users_insert_get_results() {
use diesel::result::Error;
let conn = establish_connection();
conn.test_transaction::<_, Error, _>(|| {
use diesel::select;
use chrono::NaiveDateTime;
use schema::users::dsl::*;
//use schema::users::*;
let now = select(diesel::dsl::now).get_result::<NaiveDateTime>(&conn)?;
let inserted_users = conn.transaction::<_, Error, _>(|| {
let inserted_count = insert_into(users)
.values(&vec![
(id.eq(1), last_name.eq("Hiedemann"), first_name.eq("Eric")),
(id.eq(2), last_name.eq("Schlömer"), first_name.eq("Lothar")),
//(id.eq(1), first_name.eq("Eric"), last_name.eq("Hiedemann"), alias.eq("Eric.Hiedemann")),
//(id.eq(2), first_name.eq("Lothar"), last_name.eq("Schlömer"), alias.eq("othar.Schlömer")),
])
.execute(&conn)?;
/*
Ok(users
.order(id.desc())
.limit(inserted_count as i64)
.load(&conn)?
.into_iter()
.rev()
.collect::<Vec<_>>())
*/
})?;
/*
let expected_users = vec![
User {
id: 1,
last_name: "Hiedemann".into(),
first_name: "Eric".into(),
alias: "Eric.Hiedemann".into(),
email: None,
email_confirmed: false,
password_hash: None,
initials: None,
date_created: now,
date_updated: now,
},
User {
id: 2,
last_name: "Schlömer".into(),
first_name: "Lothar".into(),
alias: "Lothar.Schlömer".into(),
email: None,
email_confirmed: false,
password_hash: None,
initials: None,
date_created: now,
date_updated: now,
},
];
assert_eq!(expected_users, inserted_users);
*/
Ok(())
});
}
*/
/*
pub fn create_numberharm<'a>(connection: &SqliteConnection, NumberHarm: &'a str) {
let numberHarm = models::NewNumberHarm { NumberHarm };
diesel::insert_into(schema::NumberHarm::table)
.values(&numberHarm)
.execute(connection)
.expect("Error inserting new task");
}
*/
/*
pub fn create_userid<'a>(connection: &SqliteConnection, User: &'a str) {
let user = models::NewUser { User };
diesel::insert_into(schema::User::table)
.values(&user)
.execute(connection)
.expect("Error inserting new task");
}
*/
/*
pub fn create_userclaimid<'a>(connection: &SqliteConnection, UserClaim: &'a str) {
let userClaim = models::NewUserClaim { UserClaim };
diesel::insert_into(schema::UserClaim::table)
.values(&userClaim)
.execute(connection)
.expect("Error inserting new task");
}
pub fn create_userrole<'a>(connection: &SqliteConnection, UserRole: &'a str) {
let userRole = models::NewUserRole { UserRole };
diesel::insert_into(schema::UserRole::table)
.values(&userRole)
.execute(connection)
.expect("Error inserting new task");
}
pub fn create_useruserrole<'a>(connection: &SqliteConnection, UserUserRole: &'a str) {
let userUserRole = models::NewUserUserRole { UserUserRole };
diesel::insert_into(schema::UserUserRole::table)
.values(&userUserRole)
.execute(connection)
.expect("Error inserting new task");
}
*/

View File

@@ -1,110 +0,0 @@
/*
* advotracker - Hotline tackingtool for Advocats
*
* Copyright 2019 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
use chrono::NaiveDateTime;
use super::types::ConfirmState;
//use diesel::sql_types::Bool;
use super::schema::*;
// usage: INSERT
//#[table_name = "users"]
#[derive(Debug, Deserialize)]
pub struct NewUser<'a> {
last_name: &'a str,
first_name: &'a str,
alias: &'a str,
email: Option<&'a str>,
//email_confirmed: &'a ConfirmState,
password_hash: Option<&'a str>,
initials: Option<&'a str>,
//date_created: &'a NaiveDateTime,
//date_updated: &'a NaiveDateTime
}
// usage: SELECT, UPDATE
//#[derive(Debug, Deserialize, PartialEq, Queryable)]
#[derive(Queryable, PartialEq, Debug)]
struct User {
// id: the auto incremented primary index
id: i32,
last_name: String,
first_name: String,
alias: Option<String>,
email: Option<String>,
email_confirmed: Option<ConfirmState>,
password_hash: Option<String>,
initials: Option<String>,
date_created: NaiveDateTime,
date_updated: NaiveDateTime
}
/*
impl NewUser<'_> {
// Given 'User' struct is converted to a 'NewUser' struct
// used to insert new rows
pub fn from_user<'a>(user: User) -> NewUser<'a> {
NewUser {
// id: not needed, since autupdated from db-backend
//user_id: user.user_id,
email: user.email,
//email_confirmed: user.email_confirmed,
password_hash: user.password_hash,
initials: user.initials,
last_name: user.last_name,
first_name: user.first_name,
//date_created: user.date_created,
//date_updated: user.date_updated,
}
}
}
*/
// usage: INSERT
#[derive(Deserialize, Insertable)]
#[table_name = "user_roles"]
pub struct NewUserRole<'a> {
//id: &'a i32,
name: &'a str
}
// usage: SELECT, UPDATE
#[derive(Debug, Deserialize, PartialEq, Queryable)]
struct UserRoles {
id: i32,
name: String,
}
// usage: INSERT
#[derive(Deserialize, Insertable)]
#[table_name = "harms"]
pub struct NewHarm<'a> {
//id: &'a i32,
number_harm: &'a str,
number_policyholder: &'a str,
number_callback: &'a str,
//date_fallback: &'a NaiveDateTime,
//date_recording: &'a NaiveDateTime,
//user_id: &'a i32,
//date_changed: &'a NaiveDateTime,
//user_id_changed: &'a i32
}
// usage: SELECT, UPDATE
//#[derive(Debug, Deserialize, PartialEq, Queryable)]
#[derive(Queryable, PartialEq, Debug)]
struct Harms {
id: i32,
number_harm: String,
number_policyholder: String,
number_callback: String,
date_fallback: NaiveDateTime,
date_recording: NaiveDateTime,
user_id: i32,
date_changed: NaiveDateTime,
user_id_changed: i32
}

View File

@@ -1,64 +0,0 @@
table! {
harms (id) {
id -> Nullable<Integer>,
number_harm -> Nullable<Text>,
number_policyholder -> Nullable<Text>,
number_callback -> Nullable<Text>,
date_fallback -> Nullable<Timestamp>,
date_recording -> Timestamp,
user_id -> Integer,
date_changed -> Timestamp,
user_id_changed -> Nullable<Integer>,
}
}
table! {
user_claims (id) {
id -> Nullable<Integer>,
user_id -> Nullable<Integer>,
#[sql_name = "type"]
type_ -> Nullable<Text>,
value -> Nullable<Text>,
}
}
table! {
user_roles (id) {
id -> Nullable<Integer>,
name -> Nullable<Text>,
}
}
table! {
user_user_roles (user_id, role_id) {
user_id -> Integer,
role_id -> Integer,
}
}
table! {
users (id) {
id -> Nullable<Integer>,
last_name -> Nullable<Text>,
first_name -> Nullable<Text>,
alias -> Nullable<Text>,
email -> Nullable<Text>,
email_confirmed -> Integer,
password_hash -> Nullable<Text>,
initials -> Nullable<Text>,
date_created -> Timestamp,
date_updated -> Timestamp,
}
}
joinable!(user_claims -> users (user_id));
joinable!(user_user_roles -> user_roles (role_id));
joinable!(user_user_roles -> users (user_id));
allow_tables_to_appear_in_same_query!(
harms,
user_claims,
user_roles,
user_user_roles,
users,
);

View File

@@ -1,161 +0,0 @@
// WIP
use diesel::sqlite::Sqlite;
use diesel::deserialize::FromSql;
use diesel::backend::Backend;
use diesel::sql_types::{Bool, Integer};
use diesel::serialize::{ToSql, Output};
//use super::models::ConfirmState;
//use crate::db::models::ConfirmState;
// trait: meaningful enum/types for email confirmation states
// in analogy: https://noyez.gitlab.io/post/2018-08-05-a-small-custom-bool-type-in-diesel/
#[repr(i32)]
#[derive(AsExpression, Copy, Clone, Debug, PartialEq, FromSqlRow)]
#[sql_type = "Integer"]
pub enum ConfirmState {
Unconfirmed = 0,
Confirmed = 1,
Authorized = 2,
Blocked = 3,
}
impl<DB> ToSql<Integer, DB> for ConfirmState
where
DB: Backend,
Bool: ToSql<Integer, DB> {
fn to_sql<W: std::io::Write>(
&self,
out: &mut Output<W, DB>,
) -> diesel::serialize::Result {
let int_value;
match &self {
ConfirmState::Unconfirmed => int_value = 0,
ConfirmState::Confirmed => int_value = 1,
ConfirmState::Authorized => int_value = 2,
ConfirmState::Blocked => int_value = 3,
}
println!("Writing to sql: i32:{:?}", &int_value);
<i32 as ToSql<Integer, DB>>::to_sql(&int_value, out)
}
}
/*
impl FromSql<Integer, Sqlite>
for ConfirmState
{
fn from_sql(
bytes: Option<&<diesel::sqlite::Sqlite as diesel::backend::Backend>::RawValue>,
) -> diesel::deserialize::Result<Self> {
<i32 as diesel::deserialize::FromSql<
diesel::sql_types::Integer, diesel::sqlite::Sqlite>>::from_sql()
.map(ConfirmState::Confirmed)
}
}
*/
impl <DB> FromSql<Integer, DB> for ConfirmState
where
DB: Backend<RawValue = [u8]>,
i32: FromSql<Integer, DB>
{
fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
match <i32 as FromSql<Integer, DB>>::from_sql(bytes)? {
0 => Ok(ConfirmState::Unconfirmed),
1 => Ok(ConfirmState::Confirmed),
2 => Ok(ConfirmState::Authorized),
3 => Ok(ConfirmState::Blocked),
x => Err(format!("Unrecognized variant {}", x).into()),
}
}
}
/*
impl<DB> FromSql<Integer, DB> for ConfirmState
where
DB: Backend,
i32: FromSql<Bool, DB> {
//fn from_sql(bytes: Option<diesel::backend::Backend>::RawValue<DB>) -> diesel::deserialize::Result<Self> {
fn from_sql(
bytes: Option<&<DB>::RawValue>,
) -> diesel::deserialize::Result<Self> {
//println!("Reading from sql: bytes:{:?}", bytes);
match bytes {
<i32 as diesel::deserialize::FromSql<Integer, DB>>::from_sql(bytes)
.map(ConfirmState::Confirmed)
}
/*
Some(bytes) => if bytes[0] != 0 {
Ok(ConfirmState::Confirmed) }
else { Ok(ConfirmState::Unconfirmed) }
}
//<i32 as diesel::deserialize::FromSql<Integer, DB>>::from_sql(bytes).map(ConfirmState::Confirmed)
//fn from_sql(bytes: Option<Bool>) -> diesel::deserialize::Result<Self> {
// println!("Reading from sql: bytes:{:?}", bytes);
// match bytes {
// Some(bytes) => if bytes[0] != 0 {
// Ok(ConfirmState::Confirmed) }
// else { Ok(ConfirmState::Unconfirmed) },
// None => Ok(ConfirmState::Unconfirmed),
// }
*/
}
}
*/
/*
impl<DB: diesel::backend::Backend<RawValue = [u8]>>
diesel::deserialize::FromSql<diesel::sql_types::Integer, DB> for ConfirmState
{
fn from_sql(bytes: Option<&[u8]>) -> diesel::deserialize::Result<Self> {
<i32 as diesel::deserialize::FromSql<diesel::sql_types::Integer, DB>>::from_sql(
bytes,
)
.map($name)
}
}
*/
struct ConfirmStateVisitor;
use serde::de::{self, Visitor};
use serde::de::Deserialize;
use serde::de::Deserializer;
impl<'de> Visitor<'de> for ConfirmStateVisitor {
type Value = ConfirmState;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
//formatter.write_str("a boolean or string of \"Confirmed\", \"Unconfirmed\", \"Authorized\", \"Unauthorized\".")
formatter.write_str("a boolean or string of \"Confirmed\", \"Unconfirmed\".")
}
fn visit_bool<E>(self, value: bool) -> Result<ConfirmState, E>
where
E: de::Error, {
match value {
true => Ok(ConfirmState::Confirmed),
false => Ok(ConfirmState::Unconfirmed),
}
}
fn visit_str<E>(self, value: &str) -> Result<ConfirmState, E>
where
E: de::Error,
{
match value {
//"Confirmed" | "Authorized" => Ok(ConfirmState::Confirmed),
//"Unconfirmed" | "Unauthorized" => Ok(ConfirmState::Unconfirmed),
"Confirmed" => Ok(ConfirmState::Confirmed),
"Unconfirmed" => Ok(ConfirmState::Unconfirmed),
_s => Err(E::custom(format!("Unknown string value: {}", _s))),
}
}
}
impl<'de> Deserialize<'de> for ConfirmState {
fn deserialize<D>(deserializer: D) -> Result<ConfirmState, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(ConfirmStateVisitor)
}
}