mithril_persistence/database/query/cardano_transaction/
insert_cardano_transaction.rs

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
use std::iter::repeat;

use sqlite::Value;

use mithril_common::StdResult;

use crate::database::record::CardanoTransactionRecord;
use crate::sqlite::{Query, SourceAlias, SqLiteEntity, WhereCondition};

/// Query to insert [CardanoTransactionRecord] in the sqlite database
pub struct InsertCardanoTransactionQuery {
    condition: WhereCondition,
}

impl InsertCardanoTransactionQuery {
    /// Query that insert one record.
    pub fn insert_one(record: &CardanoTransactionRecord) -> StdResult<Self> {
        Self::insert_many(vec![record.clone()])
    }

    /// Query that insert multiples records.
    pub fn insert_many(transactions_records: Vec<CardanoTransactionRecord>) -> StdResult<Self> {
        let columns = "(transaction_hash, block_number, slot_number, block_hash)";
        let values_columns: Vec<&str> = repeat("(?*, ?*, ?*, ?*)")
            .take(transactions_records.len())
            .collect();

        let values: StdResult<Vec<Value>> =
            transactions_records
                .into_iter()
                .try_fold(vec![], |mut vec, record| {
                    vec.append(&mut vec![
                        Value::String(record.transaction_hash),
                        Value::Integer(record.block_number.try_into()?),
                        Value::Integer(record.slot_number.try_into()?),
                        Value::String(record.block_hash.clone()),
                    ]);
                    Ok(vec)
                });
        let condition = WhereCondition::new(
            format!("{columns} values {}", values_columns.join(", ")).as_str(),
            values?,
        );

        Ok(Self { condition })
    }
}

impl Query for InsertCardanoTransactionQuery {
    type Entity = CardanoTransactionRecord;

    fn filters(&self) -> WhereCondition {
        self.condition.clone()
    }

    fn get_definition(&self, condition: &str) -> String {
        let aliases = SourceAlias::new(&[("{:cardano_tx:}", "cardano_tx")]);
        let projection = Self::Entity::get_projection().expand(aliases);

        format!("insert or ignore into cardano_tx {condition} returning {projection}")
    }
}