1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use crate::{
    db::{
        models::{challenges::Challenge, proposals::Proposal},
        schema::challenges::{self, dsl as challenges_dsl},
        views_schema::full_proposals_info::dsl as proposals_dsl,
        DbConnection, DbConnectionPool,
    },
    v0::errors::HandleError,
};
use diesel::{ExpressionMethods, Insertable, QueryDsl, QueryResult, RunQueryDsl};

pub async fn query_all_challenges(pool: &DbConnectionPool) -> Result<Vec<Challenge>, HandleError> {
    let db_conn = pool.get().map_err(HandleError::DatabaseError)?;
    tokio::task::spawn_blocking(move || {
        challenges_dsl::challenges
            .order_by(challenges_dsl::internal_id.asc())
            .load::<Challenge>(&db_conn)
            .map_err(|_| HandleError::InternalError("Error retrieving challenges".to_string()))
    })
    .await
    .map_err(|_e| HandleError::InternalError("Error executing request".to_string()))?
}

pub async fn query_challenge_by_id(
    id: i32,
    pool: &DbConnectionPool,
) -> Result<Challenge, HandleError> {
    let db_conn = pool.get().map_err(HandleError::DatabaseError)?;
    tokio::task::spawn_blocking(move || {
        challenges_dsl::challenges
            .filter(challenges_dsl::id.eq(id))
            .first::<Challenge>(&db_conn)
            .map_err(|_e| HandleError::NotFound("Error loading challenge".to_string()))
    })
    .await
    .map_err(|_e| HandleError::InternalError("Error executing request".to_string()))?
}

pub async fn query_challenges_by_fund_id(
    fund_id: i32,
    pool: &DbConnectionPool,
) -> Result<Vec<Challenge>, HandleError> {
    let db_conn = pool.get().map_err(HandleError::DatabaseError)?;
    tokio::task::spawn_blocking(move || {
        challenges_dsl::challenges
            .filter(challenges_dsl::fund_id.eq(fund_id))
            .order_by(challenges_dsl::internal_id.asc())
            .load::<Challenge>(&db_conn)
            .map_err(|_e| HandleError::NotFound("Error loading challenges for fund id".to_string()))
    })
    .await
    .map_err(|_e| HandleError::InternalError("Error executing request".to_string()))?
}

pub async fn query_challenge_proposals_by_id(
    id: i32,
    pool: &DbConnectionPool,
) -> Result<Vec<Proposal>, HandleError> {
    let db_conn = pool.get().map_err(HandleError::DatabaseError)?;
    tokio::task::spawn_blocking(move || {
        proposals_dsl::full_proposals_info
            .filter(proposals_dsl::challenge_id.eq(id))
            .load::<Proposal>(&db_conn)
            .map_err(|_e| HandleError::NotFound("Error loading challenge".to_string()))
    })
    .await
    .map_err(|_e| HandleError::InternalError("Error executing request".to_string()))?
}

pub async fn query_challenge_proposals_by_id_and_group_id(
    id: i32,
    voter_group_id: String,
    pool: &DbConnectionPool,
) -> Result<Vec<Proposal>, HandleError> {
    let db_conn = pool.get().map_err(HandleError::DatabaseError)?;
    tokio::task::spawn_blocking(move || {
        proposals_dsl::full_proposals_info
            .filter(proposals_dsl::challenge_id.eq(id))
            .filter(proposals_dsl::group_id.eq(voter_group_id))
            .load::<Proposal>(&db_conn)
            .map_err(|_e| HandleError::NotFound("Error loading challenge".to_string()))
    })
    .await
    .map_err(|_e| HandleError::InternalError("Error executing request".to_string()))?
}

pub fn batch_insert_challenges(
    challenges: &[<Challenge as Insertable<challenges::table>>::Values],
    db_conn: &DbConnection,
) -> QueryResult<usize> {
    diesel::insert_into(challenges::table)
        .values(challenges)
        .execute(db_conn)
}