bindizr_db/repository/postgres/
zone_change_repository_impl.rs1use 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}