mirror of https://github.com/raftario/filite.git
Initial commit
This commit is contained in:
commit
d5ac4b8b6a
|
@ -0,0 +1,10 @@
|
||||||
|
# Rust build artifacts
|
||||||
|
target/
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# User specific files
|
||||||
|
.env
|
||||||
|
**/*.db
|
||||||
|
|
||||||
|
# JetBrains settings
|
||||||
|
.idea/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,18 @@
|
||||||
|
[package]
|
||||||
|
name = "filite"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Raphaël Thériault <raphael_theriault@outlook.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix-web = "1.0.8"
|
||||||
|
chrono = "0.4.9"
|
||||||
|
[dependencies.diesel]
|
||||||
|
version = "1.4.2"
|
||||||
|
features = ["r2d2", "sqlite"]
|
||||||
|
[dependencies.libsqlite3-sys]
|
||||||
|
version = "0.12.0"
|
||||||
|
features = ["bundled"]
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
dotenv = "0.14.1"
|
|
@ -0,0 +1,2 @@
|
||||||
|
[print_schema]
|
||||||
|
file = "src/schema.rs"
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE files
|
|
@ -0,0 +1,6 @@
|
||||||
|
CREATE TABLE files (
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
filepath TEXT NOT NULL,
|
||||||
|
created INTEGER NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated INTEGER NOT NULL DEFAULT (datetime('now'))
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE links
|
|
@ -0,0 +1,6 @@
|
||||||
|
CREATE TABLE links (
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
forward TEXT NOT NULL,
|
||||||
|
created INTEGER NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated INTEGER NOT NULL DEFAULT (datetime('now'))
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE texts
|
|
@ -0,0 +1,6 @@
|
||||||
|
CREATE TABLE texts (
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
contents TEXT NOT NULL,
|
||||||
|
created INTEGER NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated INTEGER NOT NULL DEFAULT (datetime('now'))
|
||||||
|
)
|
|
@ -0,0 +1,28 @@
|
||||||
|
#[macro_use]
|
||||||
|
extern crate diesel;
|
||||||
|
|
||||||
|
use diesel::r2d2::{self, ConnectionManager};
|
||||||
|
use diesel::sqlite::SqliteConnection;
|
||||||
|
|
||||||
|
pub mod models;
|
||||||
|
pub mod queries;
|
||||||
|
pub mod schema;
|
||||||
|
|
||||||
|
/// SQLite database connection pool
|
||||||
|
pub type Pool = r2d2::Pool<ConnectionManager<SqliteConnection>>;
|
||||||
|
|
||||||
|
/// Functions used for the initial setup
|
||||||
|
pub mod setup {
|
||||||
|
use crate::Pool;
|
||||||
|
|
||||||
|
use diesel::r2d2::{self, ConnectionManager};
|
||||||
|
use diesel::sqlite::SqliteConnection;
|
||||||
|
|
||||||
|
/// Creates a SQLite database connection pool
|
||||||
|
pub fn create_pool(url: &str) -> Pool {
|
||||||
|
let manager = ConnectionManager::<SqliteConnection>::new(url);
|
||||||
|
r2d2::Pool::builder()
|
||||||
|
.build(manager)
|
||||||
|
.expect("Can't create pool.")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
//! Database models
|
||||||
|
|
||||||
|
/// Models from the `files` table
|
||||||
|
pub mod files {
|
||||||
|
use crate::schema::files;
|
||||||
|
|
||||||
|
/// An entry from the `files` table
|
||||||
|
#[derive(Queryable, Identifiable)]
|
||||||
|
pub struct File {
|
||||||
|
pub id: i32,
|
||||||
|
pub filepath: String,
|
||||||
|
pub created: i32,
|
||||||
|
pub updated: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A new entry to the `files` table
|
||||||
|
#[derive(Insertable)]
|
||||||
|
#[table_name = "files"]
|
||||||
|
pub struct NewFile<'a> {
|
||||||
|
pub id: i32,
|
||||||
|
pub filepath: &'a str,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Models from the `links` table
|
||||||
|
pub mod links {
|
||||||
|
use crate::schema::links;
|
||||||
|
|
||||||
|
/// An entry from the `links` table
|
||||||
|
#[derive(Queryable, Identifiable)]
|
||||||
|
pub struct Link {
|
||||||
|
pub id: i32,
|
||||||
|
pub forward: String,
|
||||||
|
pub created: i32,
|
||||||
|
pub updated: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A new entry to the `links` table
|
||||||
|
#[derive(Insertable)]
|
||||||
|
#[table_name = "links"]
|
||||||
|
pub struct NewLink<'a> {
|
||||||
|
pub id: i32,
|
||||||
|
pub forward: &'a str,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Models from the `texts` table
|
||||||
|
pub mod texts {
|
||||||
|
use crate::schema::texts;
|
||||||
|
|
||||||
|
/// An entry from the `texts` table
|
||||||
|
#[derive(Queryable, Identifiable)]
|
||||||
|
pub struct Text {
|
||||||
|
pub id: i32,
|
||||||
|
pub contents: String,
|
||||||
|
pub created: i32,
|
||||||
|
pub updated: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A new entry to the `texts` table
|
||||||
|
#[derive(Insertable)]
|
||||||
|
#[table_name = "texts"]
|
||||||
|
pub struct NewText<'a> {
|
||||||
|
pub id: i32,
|
||||||
|
pub contents: &'a str,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,212 @@
|
||||||
|
//! Helper functions for SQL queries
|
||||||
|
|
||||||
|
// A lot of duplicate code here could be merged by using macros
|
||||||
|
|
||||||
|
/// Queries affecting the `files` table
|
||||||
|
pub mod files {
|
||||||
|
use crate::models::files::*;
|
||||||
|
use crate::schema::files::dsl::*;
|
||||||
|
use crate::schema::files::table;
|
||||||
|
use crate::Pool;
|
||||||
|
|
||||||
|
use actix_web::web::Data;
|
||||||
|
use diesel::prelude::*;
|
||||||
|
use diesel::result::QueryResult;
|
||||||
|
|
||||||
|
/// SELECT a single file entry given its id
|
||||||
|
pub fn find(g_id: i32, pool: Data<Pool>) -> QueryResult<File> {
|
||||||
|
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||||
|
files.find(g_id).first::<File>(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// INSERT a file entry
|
||||||
|
pub fn insert(p_id: i32, p_filepath: &str, pool: Data<Pool>) -> QueryResult<File> {
|
||||||
|
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||||
|
let new_file = NewFile {
|
||||||
|
id: p_id,
|
||||||
|
filepath: p_filepath,
|
||||||
|
};
|
||||||
|
diesel::insert_into(table).values(&new_file).execute(conn)?;
|
||||||
|
|
||||||
|
find(p_id, pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// UPDATE a file entry
|
||||||
|
pub fn update(
|
||||||
|
p_id: i32,
|
||||||
|
new_id: Option<i32>,
|
||||||
|
new_filepath: Option<&str>,
|
||||||
|
pool: Data<Pool>,
|
||||||
|
) -> QueryResult<File> {
|
||||||
|
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||||
|
let file = find(p_id, pool)?;
|
||||||
|
let query = diesel::update(&file);
|
||||||
|
let time_update = updated.eq(chrono::Utc::now().timestamp() as i32);
|
||||||
|
match (new_id, new_filepath) {
|
||||||
|
(Some(new_id), Some(new_filepath)) => {
|
||||||
|
query
|
||||||
|
.set((id.eq(new_id), filepath.eq(new_filepath), time_update))
|
||||||
|
.execute(conn)?;
|
||||||
|
}
|
||||||
|
(Some(new_id), None) => {
|
||||||
|
query.set((id.eq(new_id), time_update)).execute(conn)?;
|
||||||
|
}
|
||||||
|
(None, Some(new_filepath)) => {
|
||||||
|
query
|
||||||
|
.set((filepath.eq(new_filepath), time_update))
|
||||||
|
.execute(conn)?;
|
||||||
|
}
|
||||||
|
(None, None) => {
|
||||||
|
return Ok(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// DELETE a file entry
|
||||||
|
pub fn delete(d_id: i32, pool: Data<Pool>) -> QueryResult<()> {
|
||||||
|
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||||
|
diesel::delete(files.find(d_id)).execute(conn)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Queries affecting the `links` table
|
||||||
|
pub mod links {
|
||||||
|
use crate::models::links::*;
|
||||||
|
use crate::schema::links::dsl::*;
|
||||||
|
use crate::schema::links::table;
|
||||||
|
use crate::Pool;
|
||||||
|
|
||||||
|
use actix_web::web::Data;
|
||||||
|
use diesel::prelude::*;
|
||||||
|
use diesel::result::QueryResult;
|
||||||
|
|
||||||
|
/// SELECT a single link entry given its id
|
||||||
|
pub fn find(g_id: i32, pool: Data<Pool>) -> QueryResult<Link> {
|
||||||
|
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||||
|
links.find(g_id).first::<Link>(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// INSERT a link entry
|
||||||
|
pub fn insert(p_id: i32, p_forward: &str, pool: Data<Pool>) -> QueryResult<Link> {
|
||||||
|
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||||
|
let new_link = NewLink {
|
||||||
|
id: p_id,
|
||||||
|
forward: p_forward,
|
||||||
|
};
|
||||||
|
diesel::insert_into(table).values(&new_link).execute(conn)?;
|
||||||
|
|
||||||
|
find(p_id, pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// UPDATE a link entry
|
||||||
|
pub fn update(
|
||||||
|
p_id: i32,
|
||||||
|
new_id: Option<i32>,
|
||||||
|
new_forward: Option<&str>,
|
||||||
|
pool: Data<Pool>,
|
||||||
|
) -> QueryResult<Link> {
|
||||||
|
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||||
|
let link = find(p_id, pool)?;
|
||||||
|
let query = diesel::update(&link);
|
||||||
|
let time_update = updated.eq(chrono::Utc::now().timestamp() as i32);
|
||||||
|
match (new_id, new_forward) {
|
||||||
|
(Some(new_id), Some(new_forward)) => {
|
||||||
|
query
|
||||||
|
.set((id.eq(new_id), forward.eq(new_forward), time_update))
|
||||||
|
.execute(conn)?;
|
||||||
|
}
|
||||||
|
(Some(new_id), None) => {
|
||||||
|
query.set((id.eq(new_id), time_update)).execute(conn)?;
|
||||||
|
}
|
||||||
|
(None, Some(new_forward)) => {
|
||||||
|
query
|
||||||
|
.set((forward.eq(new_forward), time_update))
|
||||||
|
.execute(conn)?;
|
||||||
|
}
|
||||||
|
(None, None) => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(link)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// DELETE a link entry
|
||||||
|
pub fn delete(d_id: i32, pool: Data<Pool>) -> QueryResult<()> {
|
||||||
|
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||||
|
diesel::delete(links.find(d_id)).execute(conn)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Queries affecting the `texts` table
|
||||||
|
pub mod texts {
|
||||||
|
use crate::models::texts::*;
|
||||||
|
use crate::schema::texts::dsl::*;
|
||||||
|
use crate::schema::texts::table;
|
||||||
|
use crate::Pool;
|
||||||
|
|
||||||
|
use actix_web::web::Data;
|
||||||
|
use diesel::prelude::*;
|
||||||
|
use diesel::result::QueryResult;
|
||||||
|
|
||||||
|
/// SELECT a single text entry given its id
|
||||||
|
pub fn find(g_id: i32, pool: Data<Pool>) -> QueryResult<Text> {
|
||||||
|
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||||
|
texts.find(g_id).first::<Text>(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// INSERT a text entry
|
||||||
|
pub fn insert(p_id: i32, p_contents: &str, pool: Data<Pool>) -> QueryResult<Text> {
|
||||||
|
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||||
|
let new_text = NewText {
|
||||||
|
id: p_id,
|
||||||
|
contents: p_contents,
|
||||||
|
};
|
||||||
|
diesel::insert_into(table).values(&new_text).execute(conn)?;
|
||||||
|
|
||||||
|
find(p_id, pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// UPDATE a text entry
|
||||||
|
pub fn update(
|
||||||
|
p_id: i32,
|
||||||
|
new_id: Option<i32>,
|
||||||
|
new_contents: Option<&str>,
|
||||||
|
pool: Data<Pool>,
|
||||||
|
) -> QueryResult<Text> {
|
||||||
|
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||||
|
let text = find(p_id, pool)?;
|
||||||
|
let query = diesel::update(&text);
|
||||||
|
let time_update = updated.eq(chrono::Utc::now().timestamp() as i32);
|
||||||
|
match (new_id, new_contents) {
|
||||||
|
(Some(new_id), Some(new_contents)) => {
|
||||||
|
query
|
||||||
|
.set((id.eq(new_id), contents.eq(new_contents), time_update))
|
||||||
|
.execute(conn)?;
|
||||||
|
}
|
||||||
|
(Some(new_id), None) => {
|
||||||
|
query.set((id.eq(new_id), time_update)).execute(conn)?;
|
||||||
|
}
|
||||||
|
(None, Some(new_contents)) => {
|
||||||
|
query
|
||||||
|
.set((contents.eq(new_contents), time_update))
|
||||||
|
.execute(conn)?;
|
||||||
|
}
|
||||||
|
(None, None) => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// DELETE a text entry
|
||||||
|
pub fn delete(d_id: i32, pool: Data<Pool>) -> QueryResult<()> {
|
||||||
|
let conn: &SqliteConnection = &pool.get().unwrap();
|
||||||
|
diesel::delete(texts.find(d_id)).execute(conn)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
table! {
|
||||||
|
files (id) {
|
||||||
|
id -> Integer,
|
||||||
|
filepath -> Text,
|
||||||
|
created -> Integer,
|
||||||
|
updated -> Integer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table! {
|
||||||
|
links (id) {
|
||||||
|
id -> Integer,
|
||||||
|
forward -> Text,
|
||||||
|
created -> Integer,
|
||||||
|
updated -> Integer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table! {
|
||||||
|
texts (id) {
|
||||||
|
id -> Integer,
|
||||||
|
contents -> Text,
|
||||||
|
created -> Integer,
|
||||||
|
updated -> Integer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allow_tables_to_appear_in_same_query!(files, links, texts,);
|
Loading…
Reference in New Issue