diff --git a/CHANGES.md b/CHANGES.md index 6f03a5a0..62f63453 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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 diff --git a/src/dataset.rs b/src/dataset.rs index 280edd6c..27ce4cb0 100644 --- a/src/dataset.rs +++ b/src/dataset.rs @@ -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}; @@ -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] @@ -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 } + } } impl MajorObject for Dataset { @@ -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::*; @@ -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(); diff --git a/src/vector/layer.rs b/src/vector/layer.rs index 826e4372..456f031e 100644 --- a/src/vector/layer.rs +++ b/src/vector/layer.rs @@ -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,