Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!(pgstac): add readonly #570

Merged
merged 3 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/pgstac/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

- `Pgstac` trait ([#551](https://github.com/stac-utils/stac-rs/pull/551))
- `python` feature ([#558](https://github.com/stac-utils/stac-rs/pull/558))
- `readonly` ([#570](https://github.com/stac-utils/stac-rs/pull/570))

### Changed

Expand Down
69 changes: 47 additions & 22 deletions crates/pgstac/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,12 @@ pub type JsonValue = serde_json::Value;
pub trait Pgstac: GenericClient {
/// Returns the **pgstac** version.
async fn pgstac_version(&self) -> Result<String> {
self.string("get_version", &[]).await
self.pgstac_string("get_version", &[]).await
}

/// Returns whether the **pgstac** database is readonly.
async fn readonly(&self) -> Result<bool> {
self.pgstac_bool("readonly", &[]).await
}

/// Returns the value of the `context` **pgstac** setting.
Expand All @@ -122,7 +127,7 @@ pub trait Pgstac: GenericClient {
/// docs](https://github.com/stac-utils/pgstac/blob/main/docs/src/pgstac.md#pgstac-settings)
/// for more information on the settings and their meaning.
async fn context(&self) -> Result<bool> {
self.string("get_setting", &[&"context"])
self.pgstac_string("get_setting", &[&"context"])
.await
.map(|value| value == "on")
}
Expand All @@ -142,12 +147,12 @@ pub trait Pgstac: GenericClient {

/// Fetches all collections.
async fn collections(&self) -> Result<Vec<JsonValue>> {
self.vec("all_collections", &[]).await
self.pgstac_vec("all_collections", &[]).await
}

/// Fetches a collection by id.
async fn collection(&self, id: &str) -> Result<Option<JsonValue>> {
self.opt("get_collection", &[&id]).await
self.pgstac_opt("get_collection", &[&id]).await
}

/// Adds a collection.
Expand All @@ -156,7 +161,7 @@ pub trait Pgstac: GenericClient {
T: Serialize,
{
let collection = serde_json::to_value(collection)?;
self.void("create_collection", &[&collection]).await
self.pgstac_void("create_collection", &[&collection]).await
}

/// Adds or updates a collection.
Expand All @@ -165,7 +170,7 @@ pub trait Pgstac: GenericClient {
T: Serialize,
{
let collection = serde_json::to_value(collection)?;
self.void("upsert_collection", &[&collection]).await
self.pgstac_void("upsert_collection", &[&collection]).await
}

/// Updates a collection.
Expand All @@ -174,17 +179,17 @@ pub trait Pgstac: GenericClient {
T: Serialize,
{
let collection = serde_json::to_value(collection)?;
self.void("update_collection", &[&collection]).await
self.pgstac_void("update_collection", &[&collection]).await
}

/// Deletes a collection.
async fn delete_collection(&self, id: &str) -> Result<()> {
self.void("delete_collection", &[&id]).await
self.pgstac_void("delete_collection", &[&id]).await
}

/// Fetches an item.
async fn item(&self, id: &str, collection: Option<&str>) -> Result<Option<JsonValue>> {
self.opt("get_item", &[&id, &collection]).await
self.pgstac_opt("get_item", &[&id, &collection]).await
}

/// Adds an item.
Expand All @@ -193,7 +198,7 @@ pub trait Pgstac: GenericClient {
T: Serialize,
{
let item = serde_json::to_value(item)?;
self.void("create_item", &[&item]).await
self.pgstac_void("create_item", &[&item]).await
}

/// Adds items.
Expand All @@ -202,7 +207,7 @@ pub trait Pgstac: GenericClient {
T: Serialize,
{
let items = serde_json::to_value(items)?;
self.void("create_items", &[&items]).await
self.pgstac_void("create_items", &[&items]).await
}

/// Updates an item.
Expand All @@ -211,7 +216,7 @@ pub trait Pgstac: GenericClient {
T: Serialize,
{
let item = serde_json::to_value(item)?;
self.void("update_item", &[&item]).await
self.pgstac_void("update_item", &[&item]).await
}

/// Upserts an item.
Expand All @@ -220,7 +225,7 @@ pub trait Pgstac: GenericClient {
T: Serialize,
{
let item = serde_json::to_value(item)?;
self.void("upsert_item", &[&item]).await
self.pgstac_void("upsert_item", &[&item]).await
}

/// Upserts items.
Expand All @@ -232,19 +237,19 @@ pub trait Pgstac: GenericClient {
T: Serialize,
{
let items = serde_json::to_value(items)?;
self.void("upsert_items", &[&items]).await
self.pgstac_void("upsert_items", &[&items]).await
}

/// Deletes an item.
async fn delete_item(&self, id: &str, collection: Option<&str>) -> Result<()> {
self.void("delete_item", &[&id, &collection]).await
self.pgstac_void("delete_item", &[&id, &collection]).await
}

/// Searches for items.
async fn search(&self, search: Search) -> Result<Page> {
let search = search.into_cql2_json()?;
let search = serde_json::to_value(search)?;
self.value("search", &[&search]).await
self.pgstac_value("search", &[&search]).await
}

/// Runs a pgstac function.
Expand All @@ -262,25 +267,39 @@ pub trait Pgstac: GenericClient {
}

/// Returns a string result from a pgstac function.
async fn string(&self, function: &str, params: &[&(dyn ToSql + Sync)]) -> Result<String> {
async fn pgstac_string(
&self,
function: &str,
params: &[&(dyn ToSql + Sync)],
) -> Result<String> {
let row = self.pgstac(function, params).await?;
row.try_get(function).map_err(Error::from)
}

/// Returns a bool result from a pgstac function.
async fn pgstac_bool(&self, function: &str, params: &[&(dyn ToSql + Sync)]) -> Result<bool> {
let row = self.pgstac(function, params).await?;
row.try_get(function).map_err(Error::from)
}

/// Returns a vector from a pgstac function.
async fn vec<T>(&self, function: &str, params: &[&(dyn ToSql + Sync)]) -> Result<Vec<T>>
async fn pgstac_vec<T>(&self, function: &str, params: &[&(dyn ToSql + Sync)]) -> Result<Vec<T>>
where
T: DeserializeOwned,
{
if let Some(value) = self.opt(function, params).await? {
if let Some(value) = self.pgstac_opt(function, params).await? {
Ok(value)
} else {
Ok(Vec::new())
}
}

/// Returns an optional value from a pgstac function.
async fn opt<T>(&self, function: &str, params: &[&(dyn ToSql + Sync)]) -> Result<Option<T>>
async fn pgstac_opt<T>(
&self,
function: &str,
params: &[&(dyn ToSql + Sync)],
) -> Result<Option<T>>
where
T: DeserializeOwned,
{
Expand All @@ -291,7 +310,7 @@ pub trait Pgstac: GenericClient {
}

/// Returns a deserializable value from a pgstac function.
async fn value<T>(&self, function: &str, params: &[&(dyn ToSql + Sync)]) -> Result<T>
async fn pgstac_value<T>(&self, function: &str, params: &[&(dyn ToSql + Sync)]) -> Result<T>
where
T: DeserializeOwned,
{
Expand All @@ -301,7 +320,7 @@ pub trait Pgstac: GenericClient {
}

/// Returns nothing from a pgstac function.
async fn void(&self, function: &str, params: &[&(dyn ToSql + Sync)]) -> Result<()> {
async fn pgstac_void(&self, function: &str, params: &[&(dyn ToSql + Sync)]) -> Result<()> {
let _ = self.pgstac(function, params).await?;
Ok(())
}
Expand Down Expand Up @@ -424,6 +443,12 @@ pub(crate) mod tests {
let _ = client.pgstac_version().await.unwrap();
}

#[rstest]
#[tokio::test]
async fn readonly(#[future(awt)] client: TestClient) {
assert!(!client.readonly().await.unwrap());
}

#[rstest]
#[tokio::test]
async fn context(#[future(awt)] client: TestClient) {
Expand Down
Loading