Skip to content

Commit

Permalink
begin adding support for lists
Browse files Browse the repository at this point in the history
also run migration before compiling, so schema.rs is up to date
  • Loading branch information
trinity-1686a committed Apr 13, 2019
1 parent c009cba commit b89b07b
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ aliases:
name: Set cache key
command: echo "$FEATURES" > /FEATURES
- *restore_cache_plume_dead_code
- run:
name: run migration
command: diesel migration run
- run:
name: install server
command: cargo install --debug --no-default-features --features="${FEATURES}",test --path . || cargo install --debug --no-default-features --features="${FEATURES}",test --path .
Expand Down
2 changes: 2 additions & 0 deletions migrations/postgres/2019-04-11-145757_timeline/down.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@

DROP TABLE timeline;
DROP TABLE timeline_definition;
DROP TABLE list_elems;
DROP TABLE lists;
15 changes: 15 additions & 0 deletions migrations/postgres/2019-04-11-145757_timeline/up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,18 @@ CREATE TABLE timeline(
post_id integer NOT NULL REFERENCES posts ON DELETE CASCADE,
timeline_id integer NOT NULL REFERENCES timeline_definition ON DELETE CASCADE
);

CREATE TABLE lists(
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL,
user_id integer REFERENCES users ON DELETE CASCADE,
type integer NOT NULL
);

CREATE TABLE list_elems(
id SERIAL PRIMARY KEY,
list_id integer NOT NULL REFERENCES lists ON DELETE CASCADE,
user_id integer REFERENCES users ON DELETE CASCADE,
blog_id integer REFERENCES blogs ON DELETE CASCADE,
word VARCHAR
);
1 change: 1 addition & 0 deletions plume-models/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ pub mod follows;
pub mod headers;
pub mod instance;
pub mod likes;
pub mod lists;
pub mod medias;
pub mod mentions;
pub mod notifications;
Expand Down
200 changes: 200 additions & 0 deletions plume-models/src/lists.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};

use schema::{lists, list_elems};
use users::User;
use {Connection, Error, Result};
use std::convert::{TryFrom, TryInto};

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ListType {
User,
Blog,
Word,
Prefix,
}

impl TryFrom<i32> for ListType {
type Error = ();

fn try_from(i: i32) -> std::result::Result<Self, ()> {
match i {
0 => Ok(ListType::User),
1 => Ok(ListType::Blog),
2 => Ok(ListType::Word),
3 => Ok(ListType::Prefix),
_ => Err(()),
}
}
}

impl Into<i32> for ListType {
fn into(self) -> i32 {
match self {
ListType::User => 0,
ListType::Blog => 1,
ListType::Word => 2,
ListType::Prefix => 3,
}
}
}

#[derive(Clone, Queryable, Identifiable)]
pub struct List {
pub id: i32,
pub name: String,
pub user_id: Option<i32>,
type_: i32,
}

#[derive(Default, Insertable)]
#[table_name = "lists"]
struct NewList {
pub name: String,
pub user_id: Option<i32>,
type_: i32,
}

#[derive(Clone, Queryable, Identifiable)]
struct ListElem {
pub id: i32,
pub list_id: i32,
pub user_id: Option<i32>,
pub blog_id: Option<i32>,
pub word: Option<String>,
}

#[derive(Default, Insertable)]
#[table_name = "list_elems"]
struct NewListElem {
pub list_id: i32,
pub user_id: Option<i32>,
pub blog_id: Option<i32>,
pub word: Option<String>,
}

impl List {
fn insert(conn: &Connection, val: NewList) -> Result<Self> {
diesel::insert_into(lists::table)
.values(val)
.execute(conn)?;
List::last(conn)
}
last!(lists);
get!(lists);
list_by!(lists, list_for_user, user_id as Option<i32>);
find_by!(lists, find_by_name, user_id as Option<i32>, name as &str);

pub fn new(conn: &Connection, name: String, user: Option<&User>, kind: ListType) -> Result<Self> {
Self::insert(conn, NewList {
name,
user_id: user.map(|u| u.id),
type_: kind.into(),
})
}

pub fn kind(&self) -> ListType {
self.type_.try_into().expect("invalide list was constructed")
}

pub fn contains_user(&self, conn: &Connection, user: i32) -> Result<bool> {
private::ListElem::user_in_list(conn, self, user)
}

pub fn contains_blog(&self, conn: &Connection, blog: i32) -> Result<bool> {
private::ListElem::user_in_list(conn, self, blog)
}

pub fn contains_word(&self, conn: &Connection, word: &str) -> Result<bool> {
private::ListElem::word_in_list(conn, self, word)
}

pub fn contains_prefix(&self, conn: &Connection, word: &str) -> Result<bool> {
private::ListElem::prefix_in_list(conn, self, word)
}

/// returns Ok(false) if this list isn't for users
pub fn add_users(&self, conn: &Connection, user: &[i32]) -> Result<bool> {
if self.kind() != ListType::User {
return Ok(false);
}
let _ = (conn, user);
unimplemented!();
}

/// returns Ok(false) if this list isn't for blog
pub fn add_blogs(&self, conn: &Connection, blog: &[i32]) -> Result<bool> {
if self.kind() != ListType::Blog {
return Ok(false);
}
let _ = (conn, blog);
unimplemented!();
}

/// returns Ok(false) if this list isn't for words
pub fn add_words(&self, conn: &Connection, word: &[&str]) -> Result<bool> {
if self.kind() != ListType::Word {
return Ok(false);
}
let _ = (conn, word);
unimplemented!();
}

/// returns Ok(false) if this list isn't for prefix
pub fn add_prefixs(&self, conn: &Connection, prefix: &[&str]) -> Result<bool> {
if self.kind() != ListType::Prefix {
return Ok(false);
}
let _ = (conn, prefix);
unimplemented!();
}
}

pub(super) mod private {
pub use super::*;
use diesel::{dsl, IntoSql, TextExpressionMethods, sql_types::{Nullable, Text}};

impl ListElem {
insert!(list_elems, NewListElem);
list_by!(list_elems, for_list, list_id as i32);

pub fn user_in_list(conn: &Connection, list: &List, user: i32) -> Result<bool> {
dsl::select(dsl::exists(
list_elems::table
.filter(list_elems::list_id.eq(list.id))
.filter(list_elems::user_id.eq(Some(user)))
))
.get_result(conn)
.map_err(Error::from)
}

pub fn blog_in_list(conn: &Connection, list: &List, blog: i32) -> Result<bool> {
dsl::select(dsl::exists(
list_elems::table
.filter(list_elems::list_id.eq(list.id))
.filter(list_elems::blog_id.eq(Some(blog)))
))
.get_result(conn)
.map_err(Error::from)
}

pub fn word_in_list(conn: &Connection, list: &List, word: &str) -> Result<bool> {
dsl::select(dsl::exists(
list_elems::table
.filter(list_elems::list_id.eq(list.id))
.filter(list_elems::word.eq(word))
))
.get_result(conn)
.map_err(Error::from)
}

pub fn prefix_in_list(conn: &Connection, list: &List, word: &str) -> Result<bool> {
dsl::select(dsl::exists(
list_elems::table
.filter(word.into_sql::<Nullable<Text>>().like(list_elems::word.concat("%")))
.filter(list_elems::list_id.eq(list.id))
))
.get_result(conn)
.map_err(Error::from)
}
}
}
26 changes: 26 additions & 0 deletions plume-models/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,26 @@ table! {
}
}

table! {
list_elems (id) {
id -> Int4,
list_id -> Int4,
user_id -> Nullable<Int4>,
blog_id -> Nullable<Int4>,
word -> Nullable<Varchar>,
}
}

table! {
lists (id) {
id -> Int4,
name -> Varchar,
user_id -> Nullable<Int4>,
#[sql_name = "type"]
type_ -> Int4,
}
}

table! {
medias (id) {
id -> Int4,
Expand Down Expand Up @@ -238,6 +258,10 @@ joinable!(comments -> posts (post_id));
joinable!(comments -> users (author_id));
joinable!(likes -> posts (post_id));
joinable!(likes -> users (user_id));
joinable!(list_elems -> blogs (blog_id));
joinable!(list_elems -> lists (list_id));
joinable!(list_elems -> users (user_id));
joinable!(lists -> users (user_id));
joinable!(mentions -> comments (comment_id));
joinable!(mentions -> posts (post_id));
joinable!(mentions -> users (mentioned_id));
Expand All @@ -264,6 +288,8 @@ allow_tables_to_appear_in_same_query!(
follows,
instances,
likes,
list_elems,
lists,
medias,
mentions,
notifications,
Expand Down

0 comments on commit b89b07b

Please sign in to comment.