Skip to content

Commit

Permalink
Basic database (#19)
Browse files Browse the repository at this point in the history
# Fixes

This adds a lot of basic database interactions and provides examples with the members type

## Related Issues

- #4 
- #5 
- #6
  • Loading branch information
mirdaki authored Dec 27, 2018
1 parent a0ec560 commit 64dee34
Show file tree
Hide file tree
Showing 12 changed files with 270 additions and 15 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ before_script:
script:
- cargo fmt --all -- --check
- cargo build
- cargo test
- cargo test -- --test-threads=1

Binary file modified docs/database-schema.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/database-schema.xml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<mxfile userAgent="Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0" version="9.1.8" editor="www.draw.io" type="device"><diagram name="Page-1" id="e56a1550-8fbb-45ad-956c-1786394a9013">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</diagram></mxfile>
<mxfile modified="2018-12-19T19:13:11.991Z" host="www.draw.io" agent="Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:64.0) Gecko/20100101 Firefox/64.0" etag="3uZ1maLCMbelq1j8_JPj" version="10.0.5" type="device"><diagram name="Page-1" id="e56a1550-8fbb-45ad-956c-1786394a9013">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</diagram></mxfile>
3 changes: 2 additions & 1 deletion docs/extra-docker-info.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ docker-compose exec backend bash
```

From there all normal Diesel or Rust maintenance commands can be run. Please go to the official documentation for details, a list of commonly used commands are below.
- `cargo upgrade`
- `cargo fmt`
- `cargo test -- --test-threads=1`
- `cargo upgrade`
- `cargo clippy`
- `diesel setup`
- `diesel migration generate {name}`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- Remove the member, event, and attendance table
DROP TABLE attendance; -- Remove this first, because it depends on the other tables
DROP TABLE member;
DROP TABLE event;
30 changes: 30 additions & 0 deletions migrations/2018-12-19-163802_create_students_and_events/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-- Create a member table
CREATE TABLE member (
ufl_username TEXT PRIMARY KEY,
is_info_filled_out BOOLEAN NOT NULL DEFAULT FALSE,
first_name TEXT NOT NULL DEFAULT '',
last_name TEXT NOT NULL DEFAULT '',
discord_username TEXT NOT NULL DEFAULT '',
github_username TEXT NOT NULL DEFAULT '',
server_username TEXT NOT NULL DEFAULT '',
server_key TEXT NOT NULL DEFAULT '',
is_acm_shareable BOOLEAN NOT NULL DEFAULT FALSE,
is_in_email_list BOOLEAN NOT NULL DEFAULT FALSE
);

-- Create an event table
CREATE TABLE event (
start_timestamp TIMESTAMPTZ PRIMARY KEY, -- Events can not start at the same time and day
title TEXT NOT NULL, -- Must have title
location TEXT NOT NULL, -- Must have location
description TEXT NOT NULL DEFAULT '',
end_timestamp TIMESTAMPTZ NOT NULL, -- Events must have an end time
image BYTEA NOT NULL DEFAULT '\000'-- Image binary defaults to 0
);

-- Create a many to many attendance table
CREATE TABLE attendance (
ufl_username TEXT REFERENCES member,
start_timestamp TIMESTAMPTZ REFERENCES event,
PRIMARY KEY (ufl_username, start_timestamp)
);
11 changes: 11 additions & 0 deletions src/attendance.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use diesel::prelude::*;
use diesel::sql_types::Timestamptz;

use super::database;
use super::schema::attendance;

#[derive(Queryable)]
pub struct Attendance {
pub ufl_username: String,
pub start_timestamp: Timestamptz,
}
15 changes: 15 additions & 0 deletions src/database.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
extern crate diesel;

use diesel::pg::PgConnection;
use diesel::prelude::*;
use std::env;

// club_data data is defined in Rocket.toml
#[database("club_data")]
pub struct ClubDbConn(diesel::PgConnection);

// Create connection for other functions to use
pub fn establish_connection() -> PgConnection {
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
PgConnection::establish(&database_url).expect(&format!("Error connecting to {}", database_url))
}
16 changes: 16 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use diesel::prelude::*;
use diesel::sql_types::Bytea;
use diesel::sql_types::Timestamptz;

use super::database;
use super::schema::event;

#[derive(Queryable)]
pub struct Event {
pub start_timestamp: Timestamptz,
pub title: String,
pub location: String,
pub description: String,
pub end_timestamp: Timestamptz,
pub image: Bytea,
}
27 changes: 15 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
#![feature(proc_macro_hygiene, decl_macro)]
// Temporarily silence warnings caused by Diesel (https://github.com/diesel-rs/diesel/issues/1785)
#![allow(proc_macro_derive_resolution_fallback)]

#[macro_use]
extern crate rocket;
#[macro_use]
extern crate rocket_contrib;
#[macro_use]
extern crate diesel;

use diesel::pg::PgConnection;
use diesel::prelude::*;
use rocket_contrib::databases::diesel;
use std::env;

#[database("club_data")]
struct ClubDbConn(diesel::PgConnection);
// Utility local dependencies
mod database;
mod schema;

pub fn establish_connection() -> PgConnection {
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
PgConnection::establish(&database_url).expect(&format!("Error connecting to {}", database_url))
}
// Table specifc local dependencies
mod attendance;
mod event;
mod member;

// Check to see if the server is working
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}

// Launch the REST server with the database connection
fn main() {
rocket::ignite()
.attach(ClubDbConn::fairing())
.attach(database::ClubDbConn::fairing())
// Note: Be sure to mount all the routes from differnt modules
.mount("/", routes![index])
.launch();
}
137 changes: 137 additions & 0 deletions src/member.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use diesel::prelude::*;

use super::database;
use super::schema::member;

/* Struct Setup */

// Struct for interacting with the member table
#[derive(Insertable, Queryable)]
#[table_name = "member"]
pub struct Member {
pub ufl_username: String,
pub is_info_filled_out: bool,
pub first_name: String,
pub last_name: String,
pub discord_username: String,
pub github_username: String,
pub server_username: String,
pub server_key: String,
pub is_acm_shareable: bool,
pub is_in_email_list: bool,
}

// Support creating new members that supply just a UFL username
impl Member {
fn new(ufl_username: &str) -> Self {
Member {
ufl_username: ufl_username.to_string(),
..Default::default()
}
}
}

// Set default values for Member
// Note: the UFL username should never be not set (Rust requires all values to have a default)
impl Default for Member {
fn default() -> Member {
Member {
ufl_username: "".to_string(),
is_info_filled_out: false,
first_name: "".to_string(),
last_name: "".to_string(),
github_username: "".to_string(),
discord_username: "".to_string(),
server_username: "".to_string(),
server_key: "".to_string(),
is_acm_shareable: false,
is_in_email_list: false,
}
}
}

/* CRUD and other functions */

// Return all members
pub fn list_members() -> Vec<Member> {
let connection = database::establish_connection();
let results = member::table
.load::<Member>(&connection)
.expect("Error loading members");
results
}

// Add a member with a UFL username
pub fn add_member(ufl_username: &str) {
let connection = database::establish_connection();

let new_member = Member::new(&ufl_username);

diesel::insert_into(member::table)
.values(&new_member)
.get_result::<Member>(&connection)
.expect("Error saving new member");
}

// Remove a member by their username
pub fn remove_member(ufl_username: &str) {
let connection = database::establish_connection();

let num_deleted =
diesel::delete(member::table.filter(member::columns::ufl_username.eq(ufl_username))) //.like(ufl_username)))
.execute(&connection)
.expect("Error deleting members");

println!("Deleted {} members", num_deleted);
}

/* Unit testing */

// Note: Do run the test as `cargo test -- --test-threads=1` to run the database calls in order
#[cfg(test)]
mod tests {
use super::*;

// Utility function to clear out the whole member table
fn clear_table() {
let connection = database::establish_connection();

diesel::delete(member::table)
.execute(&connection)
.expect("Error deleting all members");
}

// Check to make sure no members exist by default
#[test]
fn no_members() {
clear_table();
assert_eq!(Vec::len(&list_members()), 0);
}

// Check that one member exists after they are created
#[test]
fn one_member() {
clear_table();
add_member("[email protected]");
assert_eq!(Vec::len(&list_members()), 1);
}

// Check that two members exist agter they are both created
#[test]
fn two_member() {
clear_table();
add_member("[email protected]");
add_member("[email protected]");
assert_eq!(Vec::len(&list_members()), 2);
}

// Checl that a single member can be deleted after being created
#[test]
fn delete_member() {
clear_table();
add_member("[email protected]");
remove_member("[email protected]");
assert_eq!(Vec::len(&list_members()), 0);
}

}
37 changes: 37 additions & 0 deletions src/schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
table! {
attendance (ufl_username, start_timestamp) {
ufl_username -> Text,
start_timestamp -> Timestamptz,
}
}

table! {
event (start_timestamp) {
start_timestamp -> Timestamptz,
title -> Text,
location -> Text,
description -> Text,
end_timestamp -> Timestamptz,
image -> Bytea,
}
}

table! {
member (ufl_username) {
ufl_username -> Text,
is_info_filled_out -> Bool,
first_name -> Text,
last_name -> Text,
discord_username -> Text,
github_username -> Text,
server_username -> Text,
server_key -> Text,
is_acm_shareable -> Bool,
is_in_email_list -> Bool,
}
}

joinable!(attendance -> event (start_timestamp));
joinable!(attendance -> member (ufl_username));

allow_tables_to_appear_in_same_query!(attendance, event, member,);

0 comments on commit 64dee34

Please sign in to comment.