Skip to main content

shared/models/
location_database_agent_host.rs

1use crate::{models::InsertQueryBuilder, prelude::*};
2use garde::Validate;
3use serde::{Deserialize, Serialize};
4use sqlx::{Row, postgres::PgRow};
5use std::{
6    collections::BTreeMap,
7    sync::{Arc, LazyLock},
8};
9use utoipa::ToSchema;
10
11#[derive(Serialize, Deserialize, Clone)]
12pub struct LocationDatabaseAgentHost {
13    pub location: Fetchable<super::location::Location>,
14    pub database_agent_host: super::database_agent_host::DatabaseAgentHost,
15
16    pub created: chrono::NaiveDateTime,
17
18    extension_data: super::ModelExtensionData,
19}
20
21impl BaseModel for LocationDatabaseAgentHost {
22    const NAME: &'static str = "location_database_agent_host";
23
24    fn get_extension_list() -> &'static super::ModelExtensionList {
25        static EXTENSIONS: LazyLock<super::ModelExtensionList> =
26            LazyLock::new(|| parking_lot::RwLock::new(Vec::new()));
27
28        &EXTENSIONS
29    }
30
31    fn get_extension_data(&self) -> &super::ModelExtensionData {
32        &self.extension_data
33    }
34
35    #[inline]
36    fn base_columns(prefix: Option<&str>) -> BTreeMap<&'static str, compact_str::CompactString> {
37        let prefix = prefix.unwrap_or_default();
38
39        let mut columns = BTreeMap::from([
40            (
41                "location_database_agent_hosts.location_uuid",
42                compact_str::format_compact!("{prefix}location_uuid"),
43            ),
44            (
45                "location_database_agent_hosts.created",
46                compact_str::format_compact!("{prefix}created"),
47            ),
48        ]);
49
50        columns.extend(super::database_agent_host::DatabaseAgentHost::base_columns(
51            Some("database_agent_host_"),
52        ));
53
54        columns
55    }
56
57    #[inline]
58    fn map(prefix: Option<&str>, row: &PgRow) -> Result<Self, crate::database::DatabaseError> {
59        let prefix = prefix.unwrap_or_default();
60
61        Ok(Self {
62            location: super::location::Location::get_fetchable(
63                row.try_get(compact_str::format_compact!("{prefix}location_uuid").as_str())?,
64            ),
65            database_agent_host: super::database_agent_host::DatabaseAgentHost::map(
66                Some("database_agent_host_"),
67                row,
68            )?,
69            created: row.try_get(compact_str::format_compact!("{prefix}created").as_str())?,
70            extension_data: Self::map_extensions(prefix, row)?,
71        })
72    }
73}
74
75impl LocationDatabaseAgentHost {
76    pub async fn by_location_uuid_database_agent_host_uuid(
77        database: &crate::database::Database,
78        location_uuid: uuid::Uuid,
79        database_agent_host_uuid: uuid::Uuid,
80    ) -> Result<Option<Self>, crate::database::DatabaseError> {
81        let row = sqlx::query(sqlx::AssertSqlSafe(format!(
82            r#"
83            SELECT {}
84            FROM location_database_agent_hosts
85            JOIN database_agent_hosts ON location_database_agent_hosts.database_agent_host_uuid = database_agent_hosts.uuid
86            WHERE location_database_agent_hosts.location_uuid = $1 AND location_database_agent_hosts.database_agent_host_uuid = $2
87            "#,
88            Self::columns_sql(None)
89        )))
90        .bind(location_uuid)
91        .bind(database_agent_host_uuid)
92        .fetch_optional(database.read())
93        .await?;
94
95        row.try_map(|row| Self::map(None, &row))
96    }
97
98    pub async fn by_location_uuid_database_agent_host_uuid_with_transaction(
99        transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
100        location_uuid: uuid::Uuid,
101        database_agent_host_uuid: uuid::Uuid,
102    ) -> Result<Option<Self>, crate::database::DatabaseError> {
103        let row = sqlx::query(sqlx::AssertSqlSafe(format!(
104            r#"
105            SELECT {}
106            FROM location_database_agent_hosts
107            JOIN database_agent_hosts ON location_database_agent_hosts.database_agent_host_uuid = database_agent_hosts.uuid
108            WHERE location_database_agent_hosts.location_uuid = $1 AND location_database_agent_hosts.database_agent_host_uuid = $2
109            "#,
110            Self::columns_sql(None)
111        )))
112        .bind(location_uuid)
113        .bind(database_agent_host_uuid)
114        .fetch_optional(&mut **transaction)
115        .await?;
116
117        row.try_map(|row| Self::map(None, &row))
118    }
119
120    pub async fn by_location_uuid_with_pagination(
121        database: &crate::database::Database,
122        location_uuid: uuid::Uuid,
123        page: i64,
124        per_page: i64,
125        search: Option<&str>,
126    ) -> Result<super::Pagination<Self>, crate::database::DatabaseError> {
127        super::PaginatedQueryBuilder::new(
128            Self::columns_sql(None),
129            format!(
130                r#"
131                FROM location_database_agent_hosts
132                JOIN database_agent_hosts ON location_database_agent_hosts.database_agent_host_uuid = database_agent_hosts.uuid
133                WHERE location_database_agent_hosts.location_uuid = $1 AND {search}
134                "#,
135                search = super::search_sql(2, &["database_agent_hosts.name"], &["database_agent_hosts.uuid"]),
136            ),
137            "location_database_agent_hosts.created, location_database_agent_hosts.location_uuid, location_database_agent_hosts.database_agent_host_uuid",
138        )
139        .bind(location_uuid)
140        .bind(search)
141        .fetch(database, page, per_page)
142        .await
143    }
144}
145
146#[async_trait::async_trait]
147impl IntoAdminApiObject for LocationDatabaseAgentHost {
148    type AdminApiObject = AdminApiLocationDatabaseAgentHost;
149    type ExtraArgs<'a> = ();
150
151    async fn into_admin_api_object<'a>(
152        self,
153        state: &crate::State,
154        _args: Self::ExtraArgs<'a>,
155    ) -> Result<Self::AdminApiObject, crate::database::DatabaseError> {
156        let api_object = AdminApiLocationDatabaseAgentHost::init_hooks(&self, state).await?;
157
158        let api_object = finish_extendible!(
159            AdminApiLocationDatabaseAgentHost {
160                database_agent_host: self
161                    .database_agent_host
162                    .into_admin_api_object(state, ())
163                    .await?,
164                created: self.created.and_utc(),
165            },
166            api_object,
167            state
168        )?;
169
170        Ok(api_object)
171    }
172}
173
174#[derive(ToSchema, Deserialize, Validate)]
175pub struct CreateLocationDatabaseAgentHostOptions {
176    #[garde(skip)]
177    pub location_uuid: uuid::Uuid,
178    #[garde(skip)]
179    pub database_agent_host_uuid: uuid::Uuid,
180}
181
182#[async_trait::async_trait]
183impl CreatableModel for LocationDatabaseAgentHost {
184    type CreateOptions<'a> = CreateLocationDatabaseAgentHostOptions;
185    type CreateResult = Self;
186
187    fn get_create_handlers() -> &'static LazyLock<CreateListenerList<Self>> {
188        static CREATE_LISTENERS: LazyLock<CreateListenerList<LocationDatabaseAgentHost>> =
189            LazyLock::new(|| Arc::new(ModelHandlerList::default()));
190
191        &CREATE_LISTENERS
192    }
193
194    async fn create_with_transaction(
195        state: &crate::State,
196        mut options: Self::CreateOptions<'_>,
197        transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
198    ) -> Result<Self, crate::database::DatabaseError> {
199        options.validate()?;
200
201        super::database_agent_host::DatabaseAgentHost::by_uuid_optional_cached(
202            &state.database,
203            options.database_agent_host_uuid,
204        )
205        .await?
206        .ok_or(crate::database::InvalidRelationError("database_agent_host"))?;
207
208        let mut query_builder = InsertQueryBuilder::new("location_database_agent_hosts");
209
210        Self::run_create_handlers(&mut options, &mut query_builder, state, transaction).await?;
211
212        query_builder
213            .set("location_uuid", options.location_uuid)
214            .set("database_agent_host_uuid", options.database_agent_host_uuid);
215
216        query_builder.execute(&mut **transaction).await?;
217
218        let mut result = match Self::by_location_uuid_database_agent_host_uuid_with_transaction(
219            transaction,
220            options.location_uuid,
221            options.database_agent_host_uuid,
222        )
223        .await?
224        {
225            Some(location_database_agent_host) => location_database_agent_host,
226            None => return Err(sqlx::Error::RowNotFound.into()),
227        };
228
229        Self::run_after_create_handlers(&mut result, &options, state, transaction).await?;
230
231        Ok(result)
232    }
233}
234
235#[async_trait::async_trait]
236impl DeletableModel for LocationDatabaseAgentHost {
237    type DeleteOptions = ();
238
239    fn get_delete_handlers() -> &'static LazyLock<DeleteHandlerList<Self>> {
240        static DELETE_LISTENERS: LazyLock<DeleteHandlerList<LocationDatabaseAgentHost>> =
241            LazyLock::new(|| Arc::new(ModelHandlerList::default()));
242
243        &DELETE_LISTENERS
244    }
245
246    async fn delete_with_transaction(
247        &self,
248        state: &crate::State,
249        options: Self::DeleteOptions,
250        transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
251    ) -> Result<(), anyhow::Error> {
252        self.run_delete_handlers(&options, state, transaction)
253            .await?;
254
255        sqlx::query(
256            r#"
257            DELETE FROM location_database_agent_hosts
258            WHERE location_database_agent_hosts.location_uuid = $1 AND location_database_agent_hosts.database_agent_host_uuid = $2
259            "#,
260        )
261        .bind(self.location.uuid)
262        .bind(self.database_agent_host.uuid)
263        .execute(&mut **transaction)
264        .await?;
265
266        self.run_after_delete_handlers(&options, state, transaction)
267            .await?;
268
269        Ok(())
270    }
271}
272
273#[schema_extension_derive::extendible]
274#[init_args(LocationDatabaseAgentHost, crate::State)]
275#[hook_args(crate::State)]
276#[derive(ToSchema, Serialize)]
277#[schema(title = "LocationDatabaseAgentHost")]
278pub struct AdminApiLocationDatabaseAgentHost {
279    pub database_agent_host: super::database_agent_host::AdminApiDatabaseAgentHost,
280
281    pub created: chrono::DateTime<chrono::Utc>,
282}