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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use crate::db::models::groups::Group;
use crate::db::models::proposals::{
    community_choice, simple, FullProposalInfo, Proposal, ProposalVotePlan,
};
use crate::db::schema::{groups, proposals, proposals_voteplans};
use crate::db::{
    schema::{
        proposal_community_choice_challenge as community_choice_proposal_dsl,
        proposal_simple_challenge as simple_proposal_dsl,
    },
    views_schema::full_proposals_info::dsl as full_proposal_dsl,
    views_schema::full_proposals_info::dsl::full_proposals_info,
    DbConnection, DbConnectionPool,
};
use crate::v0::errors::HandleError;
use diesel::query_dsl::filter_dsl::FilterDsl;
use diesel::{ExpressionMethods, Insertable, QueryResult, RunQueryDsl};

pub async fn query_all_proposals(
    pool: &DbConnectionPool,
    voting_group: String,
) -> Result<Vec<FullProposalInfo>, HandleError> {
    let db_conn = pool.get().map_err(HandleError::DatabaseError)?;
    tokio::task::spawn_blocking(move || {
        full_proposals_info
            .filter(full_proposal_dsl::group_id.eq(voting_group))
            .load::<FullProposalInfo>(&db_conn)
            .map_err(|_e| HandleError::NotFound("proposals".to_string()))
    })
    .await
    .map_err(|_e| HandleError::InternalError("Error executing request".to_string()))?
}

pub async fn query_proposal_by_id(
    id: i32,
    voting_group: String,
    pool: &DbConnectionPool,
) -> Result<FullProposalInfo, HandleError> {
    let db_conn = pool.get().map_err(HandleError::DatabaseError)?;
    tokio::task::spawn_blocking(move || {
        full_proposals_info
            .filter(full_proposal_dsl::proposal_id.eq(id.to_string()))
            .filter(full_proposal_dsl::group_id.eq(voting_group))
            .first::<FullProposalInfo>(&db_conn)
            .map_err(|_e| HandleError::NotFound(format!("proposal with id {}", id)))
    })
    .await
    .map_err(|_e| HandleError::InternalError("Error executing request".to_string()))?
}

pub async fn query_proposals_by_voteplan_id_and_indexes(
    voteplan_id: String,
    indexes: Vec<i64>,
    pool: DbConnectionPool,
) -> Result<Vec<FullProposalInfo>, HandleError> {
    let db_conn = pool.get().map_err(HandleError::DatabaseError)?;
    tokio::task::spawn_blocking(move || {
        full_proposals_info
            .filter(full_proposal_dsl::chain_voteplan_id.eq(voteplan_id.clone()))
            .filter(full_proposal_dsl::chain_proposal_index.eq_any(&indexes))
            .load::<FullProposalInfo>(&db_conn)
            .map_err(|_e| {
                HandleError::NotFound(format!(
                    "proposal with voteplan id {} and indexes {:?}",
                    voteplan_id, indexes
                ))
            })
    })
    .await
    .map_err(|_e| HandleError::InternalError("Error executing request".to_string()))?
}

pub fn insert_proposal(proposal: Proposal, db_conn: &DbConnection) -> QueryResult<usize> {
    diesel::insert_into(proposals::table)
        .values(proposal.values())
        .execute(db_conn)
}

pub fn batch_insert_proposals(
    proposals_slice: &[Proposal],
    db_conn: &DbConnection,
) -> QueryResult<usize> {
    diesel::insert_into(proposals::table)
        .values(
            proposals_slice
                .iter()
                .cloned()
                .map(|proposal| proposal.values())
                .collect::<Vec<_>>(),
        )
        .execute(db_conn)
}

pub fn batch_insert_proposals_voteplans(
    pvs: impl Iterator<Item = ProposalVotePlan>,
    db_conn: &DbConnection,
) -> QueryResult<usize> {
    diesel::insert_into(proposals_voteplans::table)
        .values(pvs.map(|pv| pv.values()).collect::<Vec<_>>())
        .execute(db_conn)
}

pub fn batch_insert_groups(
    gs: impl Iterator<Item = Group>,
    db_conn: &DbConnection,
) -> QueryResult<usize> {
    diesel::insert_into(groups::table)
        .values(gs.map(|g| g.values()).collect::<Vec<_>>())
        .execute(db_conn)
}

pub fn batch_insert_community_choice_challenge_data(
    values: &[community_choice::ChallengeSqlValues],
    db_conn: &DbConnection,
) -> QueryResult<usize> {
    diesel::insert_into(community_choice_proposal_dsl::table)
        .values(values)
        .execute(db_conn)
}

pub fn batch_insert_simple_challenge_data(
    values: &[simple::ChallengeSqlValues],
    db_conn: &DbConnection,
) -> QueryResult<usize> {
    diesel::insert_into(simple_proposal_dsl::table)
        .values(values)
        .execute(db_conn)
}