Skip to main content

bindizr_db/repository/postgres/
zone_change_repository_impl.rs

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