Skip to content

Commit

Permalink
Add force-simple parameter when copying
Browse files Browse the repository at this point in the history
  • Loading branch information
upsicleclown committed Jun 21, 2023
1 parent 8b3a589 commit 4d2da6b
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 18 deletions.
5 changes: 5 additions & 0 deletions martin-mbtiles/src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ enum Commands {
src_file: PathBuf,
/// MBTiles file to write to
dst_file: PathBuf,
/// Force the output file to be in a simple MBTiles format with a `tiles` table
#[arg(long)]
force_simple: bool,
/// Minimum zoom level to copy
#[arg(long)]
min_zoom: Option<u8>,
Expand All @@ -72,12 +75,14 @@ async fn main() -> Result<()> {
Commands::Copy {
src_file,
dst_file,
force_simple,
min_zoom,
max_zoom,
zoom_levels,
} => {
let copy_opts = TileCopierOptions::new()
.verbose(args.verbose)
.force_simple(force_simple)
.min_zoom(min_zoom)
.max_zoom(max_zoom)
.zooms(zoom_levels);
Expand Down
82 changes: 64 additions & 18 deletions martin-mbtiles/src/tile_copier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use std::path::PathBuf;
#[derive(Clone, Default, Debug)]
pub struct TileCopierOptions {
zooms: HashSet<u8>,
force_simple: bool,
min_zoom: Option<u8>,
max_zoom: Option<u8>,
//self.bbox = bbox
verbose: bool,
}

Expand All @@ -28,12 +28,18 @@ impl TileCopierOptions {
pub fn new() -> Self {
Self {
zooms: HashSet::new(),
force_simple: false,
min_zoom: None,
max_zoom: None,
verbose: false,
}
}

pub fn force_simple(mut self, force_simple: bool) -> Self {
self.force_simple = force_simple;
self
}

pub fn zooms(mut self, zooms: Vec<u8>) -> Self {
for zoom in zooms {
self.zooms.insert(zoom);
Expand Down Expand Up @@ -71,12 +77,6 @@ impl TileCopier {
}

pub async fn run(self) -> MbtResult<()> {
let opt = SqliteConnectOptions::new()
.read_only(true)
.filename(self.src_mbtiles.filepath());
let mut conn = SqliteConnection::connect_with(&opt).await?;
let storage_type = self.src_mbtiles.detect_type(&mut conn).await?;

let opt = SqliteConnectOptions::new()
.create_if_missing(true)
.filename(&self.dst_filepath);
Expand All @@ -98,22 +98,39 @@ impl TileCopier {
.execute(&mut conn)
.await?;

let schema = query("SELECT sql FROM sourceDb.sqlite_schema WHERE tbl_name IN ('metadata', 'tiles', 'map', 'images')")
.fetch_all(&mut conn)
.await?;

for row in &schema {
let row: String = row.get(0);
query(row.as_str()).execute(&mut conn).await?;
}
if !self.options.force_simple {
for row in query("SELECT sql FROM sourceDb.sqlite_schema WHERE tbl_name IN ('metadata', 'tiles', 'map', 'images')")
.fetch_all(&mut conn)
.await? {
query(row.get(0)).execute(&mut conn).await?;
}
} else {
for statement in vec![
"CREATE TABLE metadata (name text, value text);",
"CREATE TABLE tiles (zoom_level integer, tile_column integer, tile_row integer, tile_data blob);",
"CREATE UNIQUE INDEX name on metadata (name);",
"CREATE UNIQUE INDEX tile_index on tiles (zoom_level, tile_column, tile_row);",
] {
query(statement).execute(&mut conn).await?;
}
};

query("INSERT INTO metadata SELECT * FROM sourceDb.metadata")
.execute(&mut conn)
.await?;

match storage_type {
MbtType::TileTables => self.copy_tile_tables(&mut conn).await,
MbtType::DeDuplicated => self.copy_deduplicated(&mut conn).await,
if !self.options.force_simple {
let src_opt = SqliteConnectOptions::new()
.read_only(true)
.filename(PathBuf::from(&self.src_mbtiles.filepath()));
let mut src_conn = SqliteConnection::connect_with(&src_opt).await?;

match self.src_mbtiles.detect_type(&mut src_conn).await? {
MbtType::TileTables => self.copy_tile_tables(&mut conn).await,
MbtType::DeDuplicated => self.copy_deduplicated(&mut conn).await,
}
} else {
self.copy_tile_tables(&mut conn).await
}
}

Expand Down Expand Up @@ -267,6 +284,35 @@ mod tests {
));
}

#[actix_rt::test]
async fn copy_force_simple() {
let src_filepath = PathBuf::from("../tests/fixtures/files/world_cities.mbtiles");
let dst_filepath = PathBuf::from("../tests/tmp_force_simple.mbtiles");

let copy_opts = TileCopierOptions::new().force_simple(true);

let tile_copier =
TileCopier::new(src_filepath.clone(), dst_filepath.clone(), copy_opts).unwrap();

tile_copier.run().await.unwrap();

let mut dst_conn = SqliteConnection::connect_with(
&SqliteConnectOptions::new().filename(dst_filepath.clone()),
)
.await
.unwrap();

assert!(
query("SELECT 1 FROM sqlite_schema WHERE type='table' AND tbl_name='tiles';")
.fetch_optional(&mut dst_conn)
.await
.unwrap()
.is_some()
);

remove_file(dst_filepath).unwrap();
}

#[actix_rt::test]
async fn copy_with_min_max_zoom() {
let src = PathBuf::from("../tests/fixtures/files/world_cities.mbtiles");
Expand Down

0 comments on commit 4d2da6b

Please sign in to comment.