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

Add Dataset::has_capability #585

Merged
merged 1 commit into from
Nov 28, 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 CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
- Add methods `alternative_name`, `is_nullable`, `is_unique`, `default_value` to `Field` ([#561](https://github.com/georust/gdal/pull/561))
- Add `Defn::geometry_type` ([#562](https://github.com/georust/gdal/pull/562))
- Add `Defn::field_index` and `Feature::field_index` ([#581](https://github.com/georust/gdal/pull/581))
- Add `Dataset::has_capability` for dataset capability check ([#581](https://github.com/georust/gdal/pull/585))

### Fixed

Expand Down
49 changes: 47 additions & 2 deletions src/dataset.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::{ffi::CString, ffi::NulError, path::Path, ptr};
use std::{
ffi::{CStr, CString, NulError},
path::Path,
ptr,
};

use gdal_sys::{CPLErr, GDALDatasetH, GDALMajorObjectH};

Expand All @@ -11,6 +15,29 @@ use crate::{
gdal_major_object::MajorObject, spatial_ref::SpatialRef, Driver, GeoTransform, Metadata,
};

pub struct DatasetCapability(&'static CStr);

/// Dataset capabilities
impl DatasetCapability {
/// Dataset can create new layers.
pub const CREATE_LAYER: DatasetCapability = DatasetCapability(c"CreateLayer");
/// Dataset can delete existing layers.
pub const DELETE_LAYER: DatasetCapability = DatasetCapability(c"DeleteLayer");
/// Layers of this datasource support CreateGeomField() just after layer creation.
pub const CREATE_GEOM_FIELD_AFTER_CREATE_LAYER: DatasetCapability =
DatasetCapability(c"CreateGeomFieldAfterCreateLayer");
/// Dataset supports curve geometries.
pub const CURVE_GEOMETRIES: DatasetCapability = DatasetCapability(c"CurveGeometries");
/// Dataset supports (efficient) transactions.
pub const TRANSACTIONS: DatasetCapability = DatasetCapability(c"Transactions");
/// Dataset supports transactions through emulation.
pub const EMULATED_TRANSACTIONS: DatasetCapability = DatasetCapability(c"EmulatedTransactions");
/// Dataset has a dedicated GetNextFeature() implementation, potentially returning features from layers in a non sequential way.
pub const RANDOM_LAYER_READ: DatasetCapability = DatasetCapability(c"RandomLayerRead");
/// Dataset supports calling CreateFeature() on layers in a non sequential way.
pub const RANDOM_LAYER_WRITE: DatasetCapability = DatasetCapability(c"RandomLayerWrite");
}

/// Wrapper around a [`GDALDataset`][GDALDataset] object.
///
/// Represents both a [vector dataset][vector-data-model]
Expand Down Expand Up @@ -327,6 +354,10 @@ impl Dataset {
}
Ok(transformation)
}

pub fn has_capability(&self, capability: DatasetCapability) -> bool {
unsafe { gdal_sys::GDALDatasetTestCapability(self.c_dataset(), capability.0.as_ptr()) == 1 }
Copy link
Member

@lnicola lnicola Nov 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I do hope that TRUE is 1 and not 0xFFFF_FFFF 😅.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what test cases are for. It's working for now.

}
}

impl MajorObject for Dataset {
Expand All @@ -351,7 +382,8 @@ impl Drop for Dataset {
mod tests {
use gdal_sys::GDALAccess;

use crate::test_utils::fixture;
use crate::dataset::DatasetCapability;
use crate::test_utils::{fixture, open_gpkg_for_update};
use crate::GdalOpenFlags;

use super::*;
Expand Down Expand Up @@ -446,6 +478,19 @@ mod tests {
.unwrap_err();
}

#[test]
fn test_dataset_capabilities() {
let ds = Dataset::open(fixture("poly.gpkg")).unwrap();
assert!(!ds.has_capability(DatasetCapability::CREATE_LAYER));
assert!(!ds.has_capability(DatasetCapability::DELETE_LAYER));
assert!(ds.has_capability(DatasetCapability::TRANSACTIONS));

let (_tmp_path, ds) = open_gpkg_for_update(&fixture("poly.gpkg"));
assert!(ds.has_capability(DatasetCapability::CREATE_LAYER));
assert!(ds.has_capability(DatasetCapability::DELETE_LAYER));
assert!(ds.has_capability(DatasetCapability::TRANSACTIONS));
}

#[test]
fn test_raster_count_on_vector() {
let ds = Dataset::open(fixture("roads.geojson")).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion src/vector/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub enum LayerCaps {
OLCAlterFieldDefn,
/// Layer capability for transactions
OLCTransactions,
/// Layer capability for feature deletiond
/// Layer capability for feature deletion
OLCDeleteFeature,
/// Layer capability for setting next feature index
OLCFastSetNextByIndex,
Expand Down