Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
sharkAndshark committed Feb 7, 2024
1 parent fe317e8 commit dc55d1f
Showing 1 changed file with 64 additions and 22 deletions.
86 changes: 64 additions & 22 deletions mbtiles/src/diff.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,48 @@
use log::debug;
use sqlite_hashes::rusqlite::Connection;
use sqlx::{query, Executor, Row, SqliteConnection};
use std::path::PathBuf;

use crate::MbtType::{Flat, FlatWithHash, Normalized};
use crate::{is_empty_database, CopyDuplicateMode, MbtError, MbtResult, MbtType, Mbtiles};
use crate::{
create_tiles_with_hash_view, init_mbtiles_schema, is_empty_database, reset_db_settings,
CopyDuplicateMode, MbtError, MbtResult, MbtType, Mbtiles,
};

pub const AGG_TILES_HASH: &str = "agg_tiles_hash";

pub const AGG_TILES_HASH_IN_DIFF: &str = "agg_tiles_hash_after_apply";
pub async fn diff(src: PathBuf, dst: PathBuf, diff_with: PathBuf) -> MbtResult<()> {
if src == dst {
return Err(MbtError::SameSourceAndDestination(src.clone()));
pub async fn diff(file: PathBuf, dif_result: PathBuf, diff_with: PathBuf) -> MbtResult<()> {
if file == dif_result {
return Err(MbtError::SameSourceAndDestination(file.clone()));
}
if file == diff_with {
return Err(MbtError::SameDiffAndSourceOrDestination(file.clone()));
}
if dif_result == diff_with {
return Err(MbtError::SameDiffAndSourceOrDestination(dif_result.clone()));
}

if dst.exists() {
return Err(MbtError::DestinationFileExists(dst.clone()));
if dif_result.exists() {
return Err(MbtError::DestinationFileExists(dif_result.clone()));
}

let src_mbt = Mbtiles::new(src)?;
let src_type = src_mbt.open_and_detect_type().await?;
let file_mbt = Mbtiles::new(file)?;
let file_type = file_mbt.open_and_detect_type().await?;

let dif_mbt = Mbtiles::new(diff_with)?;
let dif_type = dif_mbt.open_and_detect_type().await?;
let dif_with_mbt = Mbtiles::new(diff_with)?;
let dif_with_type = dif_with_mbt.open_and_detect_type().await?;

let dst_mbt = Mbtiles::new(dst.clone())?;
let mut conn = dst_mbt.open_or_new().await?;
let dif_result_mbt = Mbtiles::new(dif_result.clone())?;
let mut conn = dif_result_mbt.open_or_new().await?;
if !is_empty_database(&mut conn).await? {
return Err(MbtError::DestinationFileExists(dst.clone()));
return Err(MbtError::DestinationFileExists(dif_result.clone()));
}
let dst_type = src_type.clone();

src_mbt.attach_to(&mut conn, "sourceDb").await?;
dst_mbt.attach_to(&mut conn, "diffDb").await?;
let dst_type = file_type.clone(); // the result type should be same with source file

file_mbt.attach_to(&mut conn, "sourceDb").await?;
dif_with_mbt.attach_to(&mut conn, "diffDb").await?;
init_new_schema(&mut conn, file_type, dst_type).await?;
{
let mut handle_lock = conn.lock_handle().await?;
let handle = handle_lock.as_raw_handle().as_ptr();
Expand All @@ -41,16 +51,16 @@ pub async fn diff(src: PathBuf, dst: PathBuf, diff_with: PathBuf) -> MbtResult<(
let rusqlite_conn = unsafe { Connection::from_handle(handle) }?;
write_tiles_diff(
&rusqlite_conn,
dif_type,
src_type,
dif_with_type,
file_type,
dst_type,
CopyDuplicateMode::Override,
)
.await?;
write_meta_diff(&rusqlite_conn, dif_type, CopyDuplicateMode::Override).await?;
write_meta_diff(&rusqlite_conn, dif_with_type, CopyDuplicateMode::Override).await?;
}

todo!()
Ok(())
}
async fn write_meta_diff(
rusqlite_conn: &Connection,
Expand Down Expand Up @@ -192,7 +202,39 @@ fn get_select_from_with_diff(dif_type: MbtType, dst_type: MbtType) -> String {
OR difTiles.tile_data ISNULL)"
)
}
async fn init_new_schema(conn: &mut SqliteConnection, src: MbtType, dst: MbtType) -> MbtResult<()> {
if src == dst {
reset_db_settings(conn).await?;
debug!("Copying DB schema verbatim");
// DB objects must be created in a specific order: tables, views, triggers, indexes.
let sql_objects = conn
.fetch_all(
"SELECT sql
FROM sourceDb.sqlite_schema
WHERE tbl_name IN ('metadata', 'tiles', 'map', 'images', 'tiles_with_hash')
AND type IN ('table', 'view', 'trigger', 'index')
ORDER BY CASE
WHEN type = 'table' THEN 1
WHEN type = 'view' THEN 2
WHEN type = 'trigger' THEN 3
WHEN type = 'index' THEN 4
ELSE 5 END;",
)
.await?;

for row in sql_objects {
query(row.get(0)).execute(&mut *conn).await?;
}
if dst.is_normalized() {
// Some normalized mbtiles files might not have this view, so even if src == dst, it might not exist
create_tiles_with_hash_view(&mut *conn).await?;
}
} else {
init_mbtiles_schema(&mut *conn, dst).await?;
};

Ok(())
}
#[cfg(test)]
mod tests {
use sqlx::Connection;
Expand All @@ -203,7 +245,7 @@ mod tests {
#[actix_rt::test]
async fn diff_flat_to_flat() -> MbtResult<()> {
let src = PathBuf::from("../tests/fixtures/mbtiles/world_cities.mbtiles");
let diff = PathBuf::from("../tests/fixtures/mbtiles/world_cities_diff.mbtiles");
let diff = PathBuf::from("../tests/fixtures/mbtiles/zoomed_world_cities.mbtiles");
let dst = PathBuf::from("diff_flat_to_flat.mbtiles");

super::diff(src, dst, diff).await
Expand Down

0 comments on commit dc55d1f

Please sign in to comment.