use std::path::Path;
use std::process::ExitCode;
use geopackage::{GeoPackage, Layer, SpatialIndexStatus};
use crate::error::Result;
pub fn build(path: &Path, layer_name: &str) -> Result<ExitCode> {
let gpkg = GeoPackage::open_lenient(path)?;
let layer = gpkg.layer(layer_name)?;
match layer.spatial_index_status()? {
SpatialIndexStatus::Current => {
println!("{layer_name}: already indexed, nothing to do");
Ok(ExitCode::SUCCESS)
}
status @ (SpatialIndexStatus::Legacy | SpatialIndexStatus::Stale) => {
eprintln!("gpkg: {layer_name} already has an index ({status}); run `gpkg repair`");
Ok(ExitCode::FAILURE)
}
SpatialIndexStatus::Absent => {
layer.create_spatial_index()?;
println!("{layer_name}: index built over {} rows", layer.count()?);
Ok(ExitCode::SUCCESS)
}
other => {
eprintln!("gpkg: {layer_name} has an index state this version does not know ({other})");
Ok(ExitCode::FAILURE)
}
}
}
pub fn repair(path: &Path, layer_name: Option<&str>) -> Result<ExitCode> {
let gpkg = GeoPackage::open_lenient(path)?;
let layers = match layer_name {
Some(name) => vec![gpkg.layer(name)?],
None => gpkg.layers()?,
};
let mut repaired = 0usize;
for layer in &layers {
if repair_one(layer)? {
repaired += 1;
}
}
if repaired == 0 {
println!("nothing to repair");
}
Ok(ExitCode::SUCCESS)
}
fn repair_one(layer: &Layer<'_>) -> Result<bool> {
if layer.geometry_column().is_none() {
return Ok(false);
}
let name = layer.table_name().to_owned();
match layer.spatial_index_status()? {
SpatialIndexStatus::Legacy | SpatialIndexStatus::Stale => {
let status = layer.spatial_index_status()?;
layer.repair_spatial_index()?;
println!("{name}: {status} index repaired to the 1.4 trigger set");
Ok(true)
}
SpatialIndexStatus::Absent | SpatialIndexStatus::Current => Ok(false),
other => {
eprintln!("gpkg: {name} has an index state this version does not know ({other})");
Ok(false)
}
}
}