Skip to main content

bindizr_db/repository/sqlite/
zone_change_repository_impl.rs

1use async_trait::async_trait;
2use sqlx::{Pool, Sqlite};
3
4use crate::{
5    error::DatabaseError,
6    model::zone_change::ZoneChange,
7    repository::{RepositoryTx, RepositoryTxKind, ZoneChangeRepository},
8};
9
10pub struct SqliteZoneChangeRepository {
11    pool: Pool<Sqlite>,
12}
13
14impl SqliteZoneChangeRepository {
15    pub fn new(pool: Pool<Sqlite>) -> Self {
16        Self { pool }
17    }
18}
19
20#[async_trait]
21impl ZoneChangeRepository for SqliteZoneChangeRepository {
22    async fn create(&self, zone_change: ZoneChange) -> Result<ZoneChange, DatabaseError> {
23        let result = sqlx::query(
24            r#"
25            INSERT INTO zone_changes (zone_id, serial, operation, record_name, record_type, record_value, record_ttl, record_priority)
26            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
27            "#
28        )
29        .bind(zone_change.zone_id)
30        .bind(zone_change.serial)
31        .bind(&zone_change.operation)
32        .bind(&zone_change.record_name)
33        .bind(&zone_change.record_type)
34        .bind(&zone_change.record_value)
35        .bind(zone_change.record_ttl)
36        .bind(zone_change.record_priority)
37        .execute(&self.pool)
38        .await
39        .map_err(|e| DatabaseError::QueryFailed(e.to_string()))?;
40
41        let id = result.last_insert_rowid() as i32;
42
43        sqlx::query_as::<_, ZoneChange>(
44            r#"
45            SELECT id, zone_id, serial, operation, record_name, record_type, record_value, record_ttl, record_priority
46            FROM zone_changes
47            WHERE id = ?
48            "#
49        )
50        .bind(id)
51        .fetch_one(&self.pool)
52        .await
53        .map_err(|e| DatabaseError::QueryFailed(e.to_string()))
54    }
55
56    async fn create_tx(
57        &self,
58        tx: &mut RepositoryTx<'_>,
59        zone_change: ZoneChange,
60    ) -> Result<ZoneChange, DatabaseError> {
61        let sqlite_tx = match &mut tx.0 {
62            RepositoryTxKind::SQLite(tx) => tx,
63            _ => {
64                return Err(DatabaseError::TransactionFailed(
65                    "transaction kind mismatch (expected SQLite)".to_string(),
66                ));
67            }
68        };
69
70        let result = sqlx::query(
71            r#"
72            INSERT INTO zone_changes (zone_id, serial, operation, record_name, record_type, record_value, record_ttl, record_priority)
73            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
74            "#,
75        )
76        .bind(zone_change.zone_id)
77        .bind(zone_change.serial)
78        .bind(&zone_change.operation)
79        .bind(&zone_change.record_name)
80        .bind(&zone_change.record_type)
81        .bind(&zone_change.record_value)
82        .bind(zone_change.record_ttl)
83        .bind(zone_change.record_priority)
84        .execute(&mut **sqlite_tx)
85        .await
86        .map_err(|e| DatabaseError::QueryFailed(e.to_string()))?;
87
88        let id = result.last_insert_rowid() as i32;
89
90        sqlx::query_as::<_, ZoneChange>(
91            r#"
92            SELECT id, zone_id, serial, operation, record_name, record_type, record_value, record_ttl, record_priority
93            FROM zone_changes
94            WHERE id = ?
95            "#,
96        )
97        .bind(id)
98        .fetch_one(&mut **sqlite_tx)
99        .await
100        .map_err(|e| DatabaseError::QueryFailed(e.to_string()))
101    }
102
103    async fn get_changes_between_serials(
104        &self,
105        zone_id: i32,
106        from_serial: i32,
107        to_serial: i32,
108    ) -> Result<Vec<ZoneChange>, DatabaseError> {
109        sqlx::query_as::<_, ZoneChange>(
110            r#"
111            SELECT id, zone_id, serial, operation, record_name, record_type, record_value, record_ttl, record_priority
112            FROM zone_changes
113            WHERE zone_id = ? AND serial > ? AND serial <= ?
114            ORDER BY serial, id
115            "#
116        )
117        .bind(zone_id)
118        .bind(from_serial)
119        .bind(to_serial)
120        .fetch_all(&self.pool)
121        .await
122        .map_err(|e| DatabaseError::QueryFailed(e.to_string()))
123    }
124}