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 compression and query to martin-cp #1019

Merged
merged 1 commit into from
Nov 22, 2023
Merged
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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 10 additions & 10 deletions docs/src/mbtiles-meta.md
Original file line number Diff line number Diff line change
@@ -4,21 +4,21 @@
Use `mbtiles summary` to get a summary of the contents of an MBTiles file. The command will print a table with the number of tiles per zoom level, the size of the smallest and largest tiles, and the average size of tiles at each zoom level. The command will also print the bounding box of the covered area per zoom level.

```shell
File: tests/fixtures/mbtiles/world_cities.mbtiles
MBTiles file summary for tests/fixtures/mbtiles/world_cities.mbtiles
Schema: flat
File size: 48.00KiB
Page size: 4.00KiB
Page count: 12

| Zoom | Count |Smallest | Largest | Average | BBox |
| 0| 1| 1.08KiB| 1.08KiB| 1.08KiB| -180,-85,180,85 |
| 1| 4| 160B| 650B| 366B| -180,-85,180,85 |
| 2| 7| 137B| 495B| 239B| -180,-67,180,67 |
| 3| 17| 67B| 246B| 134B| -135,-41,180,67 |
| 4| 38| 64B| 175B| 86B| -135,-41,180,67 |
| 5| 57| 64B| 107B| 72B| -124,-41,180,62 |
| 6| 72| 64B| 97B| 68B| -124,-41,180,62 |
| all| 196| 64B| 1.0KiB| 96B| -180,-85,180,85 |
Zoom | Count | Smallest | Largest | Average | Bounding Box
0 | 1 | 1.0KiB | 1.0KiB | 1.0KiB | -180,-85,180,85
1 | 4 | 160B | 650B | 366B | -180,-85,180,85
2 | 7 | 137B | 495B | 239B | -180,-67,180,67
3 | 17 | 67B | 246B | 134B | -135,-41,180,67
4 | 38 | 64B | 175B | 86B | -135,-41,180,67
5 | 57 | 64B | 107B | 72B | -124,-41,180,62
6 | 72 | 64B | 97B | 68B | -124,-41,180,62
all | 196 | 64B | 1.0KiB | 96B | -180,-85,180,85
```

## meta-all
102 changes: 72 additions & 30 deletions martin/src/bin/martin-cp.rs
Original file line number Diff line number Diff line change
@@ -4,16 +4,21 @@ use std::path::PathBuf;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::Duration;

use actix_http::error::ParseError;
use actix_http::test::TestRequest;
use actix_web::http::header::{AcceptEncoding, Header as _, ACCEPT_ENCODING};
use clap::Parser;
use futures::stream::{self, StreamExt};
use futures::TryStreamExt;
use log::{debug, error, info, log_enabled};
use martin::args::{Args, ExtraArgs, MetaArgs, OsEnv, PgArgs, SrvArgs};
use martin::srv::{get_tile_content, merge_tilejson, RESERVED_KEYWORDS};
use martin::{
append_rect, read_config, Config, IdResolver, MartinError, MartinResult, ServerState,
append_rect, read_config, Config, IdResolver, MartinError, MartinResult, ServerState, Source,
TileCoord, TileData, TileRect,
};
use martin_tile_utils::TileInfo;
use mbtiles::sqlx::SqliteConnection;
use mbtiles::{
init_mbtiles_schema, is_empty_database, CopyDuplicateMode, MbtType, MbtTypeCli, Mbtiles,
};
@@ -56,7 +61,15 @@ pub struct CopyArgs {
value_name = "SCHEMA",
value_enum
)]
pub dst_type: Option<MbtTypeCli>,
pub mbt_type: Option<MbtTypeCli>,
/// Optional query parameter (in URL query format) for the sources that support it (e.g. Postgres functions)
#[arg(long)]
pub url_query: Option<String>,
/// Optional accepted encoding parameter as if the browser sent it in the HTTP request.
/// May be multiple values separated by comma, e.g. `gzip,br`.
/// Use `identity` to disable compression.
#[arg(long, alias = "encodings", default_value = "gzip")]
pub encoding: String,
/// Specify the behaviour when generated tile already exists in the destination file.
#[arg(long, value_enum, default_value_t = CopyDuplicateMode::default())]
pub on_duplicate: CopyDuplicateMode,
@@ -82,8 +95,8 @@ pub struct CopyArgs {
pub zoom_levels: Vec<u8>,
}

async fn start(copy_args: CopierArgs) -> MartinResult<()> {
info!("Starting Martin v{VERSION}");
async fn start(copy_args: CopierArgs) -> MartinCpResult<()> {
info!("Martin-CP tile copier v{VERSION}");

let env = OsEnv::default();
let save_config = copy_args.meta.save_config.clone();
@@ -185,6 +198,20 @@ impl Progress {
}
}

type MartinCpResult<T> = Result<T, MartinCpError>;

#[derive(Debug, thiserror::Error)]
enum MartinCpError {
#[error(transparent)]
Martin(#[from] MartinError),
#[error("Unable to parse encodings argument: {0}")]
EncodingParse(#[from] ParseError),
#[error(transparent)]
Actix(#[from] actix_web::Error),
#[error(transparent)]
Mbt(#[from] mbtiles::MbtError),
}

impl Display for Progress {
#[allow(clippy::cast_precision_loss)]
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
@@ -225,7 +252,7 @@ fn iterate_tiles(tiles: Vec<TileRect>) -> impl Iterator<Item = TileCoord> {
})
}

async fn run_tile_copy(args: CopyArgs, state: ServerState) -> MartinResult<()> {
async fn run_tile_copy(args: CopyArgs, state: ServerState) -> MartinCpResult<()> {
let output_file = &args.output_file;
let concurrency = args.concurrency.unwrap_or(1);
let (sources, _use_url_query, info) = state.tiles.get_sources(args.source.as_str(), None)?;
@@ -235,28 +262,13 @@ async fn run_tile_copy(args: CopyArgs, state: ServerState) -> MartinResult<()> {
let tiles = compute_tile_ranges(&args);
let mbt = Mbtiles::new(output_file)?;
let mut conn = mbt.open_or_new().await?;

let dst_type = if is_empty_database(&mut conn).await? {
let dst_type = match args.dst_type.unwrap_or(MbtTypeCli::Normalized) {
MbtTypeCli::Flat => MbtType::Flat,
MbtTypeCli::FlatWithHash => MbtType::FlatWithHash,
MbtTypeCli::Normalized => MbtType::Normalized { hash_view: true },
};
init_mbtiles_schema(&mut conn, dst_type).await?;
let mut tj = merge_tilejson(sources, String::new());
tj.other.insert(
"format".to_string(),
serde_json::Value::String(tile_info.format.to_string()),
);
tj.other.insert(
"generator".to_string(),
serde_json::Value::String(format!("martin-cp v{VERSION}")),
);
mbt.insert_metadata(&mut conn, &tj).await?;
dst_type
} else {
mbt.detect_type(&mut conn).await?
};
let mbt_type = init_schema(&mbt, &mut conn, sources, tile_info, args.mbt_type).await?;
let query = args.url_query.as_deref();
let req = TestRequest::default()
.insert_header((ACCEPT_ENCODING, args.encoding.as_str()))
.finish();
let accept_encoding = AcceptEncoding::parse(&req)?;
let encodings = Some(&accept_encoding);

let progress = Progress::new(&tiles);
info!(
@@ -274,7 +286,7 @@ async fn run_tile_copy(args: CopyArgs, state: ServerState) -> MartinResult<()> {
.try_for_each_concurrent(concurrency, |xyz| {
let tx = tx.clone();
async move {
let tile = get_tile_content(sources, info, &xyz, None, None).await?;
let tile = get_tile_content(sources, info, &xyz, query, encodings).await?;
let data = tile.data;
tx.send(TileXyz { xyz, data })
.await
@@ -295,7 +307,7 @@ async fn run_tile_copy(args: CopyArgs, state: ServerState) -> MartinResult<()> {
} else {
batch.push((tile.xyz.z, tile.xyz.x, tile.xyz.y, tile.data));
if batch.len() >= BATCH_SIZE || last_saved.elapsed() > SAVE_EVERY {
mbt.insert_tiles(&mut conn, dst_type, args.on_duplicate, &batch)
mbt.insert_tiles(&mut conn, mbt_type, args.on_duplicate, &batch)
.await?;
batch.clear();
last_saved = Instant::now();
@@ -310,7 +322,7 @@ async fn run_tile_copy(args: CopyArgs, state: ServerState) -> MartinResult<()> {
}
}
if !batch.is_empty() {
mbt.insert_tiles(&mut conn, dst_type, args.on_duplicate, &batch)
mbt.insert_tiles(&mut conn, mbt_type, args.on_duplicate, &batch)
.await?;
}
Ok(())
@@ -321,6 +333,36 @@ async fn run_tile_copy(args: CopyArgs, state: ServerState) -> MartinResult<()> {
Ok(())
}

async fn init_schema(
mbt: &Mbtiles,
conn: &mut SqliteConnection,
sources: &[&dyn Source],
tile_info: TileInfo,
mbt_type: Option<MbtTypeCli>,
) -> Result<MbtType, MartinError> {
Ok(if is_empty_database(&mut *conn).await? {
let mbt_type = match mbt_type.unwrap_or(MbtTypeCli::Normalized) {
MbtTypeCli::Flat => MbtType::Flat,
MbtTypeCli::FlatWithHash => MbtType::FlatWithHash,
MbtTypeCli::Normalized => MbtType::Normalized { hash_view: true },
};
init_mbtiles_schema(&mut *conn, mbt_type).await?;
let mut tj = merge_tilejson(sources, String::new());
tj.other.insert(
"format".to_string(),
serde_json::Value::String(tile_info.format.to_string()),
);
tj.other.insert(
"generator".to_string(),
serde_json::Value::String(format!("martin-cp v{VERSION}")),
);
mbt.insert_metadata(&mut *conn, &tj).await?;
mbt_type
} else {
mbt.detect_type(&mut *conn).await?
})
}

#[actix_web::main]
async fn main() {
let env = env_logger::Env::default().default_filter_or("martin_cp=info");
11 changes: 4 additions & 7 deletions martin/src/srv/server.rs
Original file line number Diff line number Diff line change
@@ -354,10 +354,8 @@ pub async fn get_tile_response(
) -> ActixResult<HttpResponse> {
let (sources, use_url_query, info) = sources.get_sources(source_ids, Some(xyz.z))?;

let sources = sources.as_slice();
let query = use_url_query.then_some(query);

let tile = get_tile_content(sources, info, &xyz, query, encodings.as_ref()).await?;
let tile = get_tile_content(sources.as_slice(), info, &xyz, query, encodings.as_ref()).await?;

Ok(if tile.data.is_empty() {
HttpResponse::NoContent().finish()
@@ -381,10 +379,9 @@ pub async fn get_tile_content(
if sources.is_empty() {
return Err(ErrorNotFound("No valid sources found"));
}
let query = if let Some(v) = query {
Some(Query::<UrlQuery>::from_query(v)?.into_inner())
} else {
None
let query = match query {
Some(v) if !v.is_empty() => Some(Query::<UrlQuery>::from_query(v)?.into_inner()),
_ => None,
};

let mut tiles = try_join_all(sources.iter().map(|s| s.get_tile(xyz, &query)))
2 changes: 1 addition & 1 deletion mbtiles/Cargo.toml
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ lints.workspace = true

[package]
name = "mbtiles"
version = "0.8.0"
version = "0.8.1"
authors = ["Yuri Astrakhan <[email protected]>", "MapLibre contributors"]
description = "A simple low-level MbTiles access and processing library, with some tile format detection and other relevant heuristics."
keywords = ["mbtiles", "maps", "tiles", "mvt", "tilejson"]
3 changes: 3 additions & 0 deletions mbtiles/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#![doc = include_str!("../README.md")]

// Re-export sqlx
pub use sqlx;

mod copier;
pub use copier::{CopyDuplicateMode, MbtilesCopier};

4 changes: 4 additions & 0 deletions mbtiles/src/metadata.rs
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ use tilejson::{tilejson, Bounds, Center, TileJSON};
use crate::errors::MbtResult;
use crate::Mbtiles;

#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct Metadata {
pub id: String,
@@ -155,6 +156,9 @@ impl Mbtiles {
);
}
}
if obj.is_empty() {
json = None;
}
}

Ok((tj, layer_type, json))
17 changes: 8 additions & 9 deletions mbtiles/src/summary.rs
Original file line number Diff line number Diff line change
@@ -58,8 +58,8 @@ impl Display for Summary {
writeln!(f)?;
writeln!(
f,
"|{:^9}|{:^9}|{:^9}|{:^9}|{:^9}| {:^20} |",
"Zoom", "Count", "Smallest", "Largest", "Average", "BBox"
" {:^4} | {:^9} | {:^9} | {:^9} | {:^9} | Bounding Box",
"Zoom", "Count", "Smallest", "Largest", "Average"
)?;

for l in &self.zoom_info {
@@ -70,13 +70,13 @@ impl Display for Summary {

writeln!(
f,
"|{:>9}|{:>9}|{:>9}|{:>9}|{:>9}| {:<20} |",
" {:>4} | {:>9} | {:>9} | {:>9} | {:>9} | {:.prec$}",
l.zoom,
l.tile_count,
format!("{min:.2}B"),
format!("{max:.2}B"),
format!("{avg:.2}B"),
format!("{:.prec$}", l.bbox),
format!("{min:.1}B"),
format!("{max:.1}B"),
format!("{avg:.1}B"),
l.bbox,
)?;
}

@@ -93,13 +93,12 @@ impl Display for Summary {
let prec = get_zoom_precision(max_zoom);
writeln!(
f,
"|{:>9}|{:>9}|{:>9}|{:>9}|{:>9}| {:<20} |",
" {:>4} | {:>9} | {:>9} | {:>9} | {:>9} | {bbox:.prec$}",
"all",
self.tile_count,
format!("{min}B"),
format!("{max}B"),
format!("{avg}B"),
format!("{:.prec$}", bbox),
)?;
}
}
16 changes: 2 additions & 14 deletions tests/expected/martin-cp/flat-with-hash_metadata.txt
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
[INFO ] cp_flat-with-hash has an unrecognized metadata value foo={"bar":"foo"}
[INFO ] Using 'mvt' tile format from metadata table in file cp_flat-with-hash
id: cp_flat-with-hash
tile_info:
format: mvt
encoding: ''
layer_type: null
tilejson:
tilejson: 3.0.0
tiles: []
vector_layers:
- id: table_source
fields:
gid: int4
bounds:
- -2.0
- -1.0
- 142.84131509869133
- 45.0
name: table_source
foo: '{"bar":"foo"}'
description: public.function_zxy_query_test
name: function_zxy_query_test
format: mvt
generator: martin-cp v0.11.1
json: {}

20 changes: 9 additions & 11 deletions tests/expected/martin-cp/flat-with-hash_summary.txt
Original file line number Diff line number Diff line change
@@ -2,15 +2,13 @@ MBTiles file summary for tests/mbtiles_temp_files/cp_flat-with-hash.mbtiles
Schema: flat-with-hash
Page size: 512B

| Zoom | Count |Smallest | Largest | Average | BBox |
| 0| 1| 1.07KiB| 1.07KiB| 1.07KiB| -180,-85,180,85 |
| 1| 2| 141B| 167B| 154B| -180,-85,0,85 |
| 2| 4| 418B| 988B| 589B| -90,-67,90,67 |
| 3| 7| 52B| 962B| 311B| -45,-41,90,67 |
| 4| 13| 52B| 867B| 249B| -22,-22,157,56 |
| 5| 27| 52B| 741B| 193B| -11,-11,146,49 |
| 6| 69| 52B| 679B| 144B| -6,-6,146,45 |
| 7| 214| 48B| 633B| 118B| -3,-3,143,45 |
| 8| 751| 48B| 420B| 103B| -3,-1,143,45 |
| all| 1088| 48B| 1.0KiB| 117B| -180,-85,180,85 |
Zoom | Count | Smallest | Largest | Average | Bounding Box
0 | 1 | 892B | 892B | 892B | -180,-85,180,85
1 | 4 | 474B | 983B | 609B | -180,-85,180,85
2 | 5 | 150B | 865B | 451B | -90,-67,180,67
3 | 8 | 57B | 839B | 264B | -45,-41,180,67
4 | 13 | 57B | 751B | 216B | -22,-22,157,56
5 | 27 | 57B | 666B | 167B | -11,-11,146,49
6 | 69 | 57B | 636B | 127B | -6,-6,146,45
all | 127 | 57B | 983B | 187B | -180,-85,180,85

5 changes: 1 addition & 4 deletions tests/expected/martin-cp/flat_metadata.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
[INFO ] cp_flat has an unrecognized metadata value foo={"bar":"foo"}
[INFO ] Using 'mvt' tile format from metadata table in file cp_flat
id: cp_flat
tile_info:
format: mvt
encoding: ''
layer_type: null
encoding: gzip
tilejson:
tilejson: 3.0.0
tiles: []
@@ -21,5 +19,4 @@ tilejson:
foo: '{"bar":"foo"}'
format: mvt
generator: martin-cp v0.11.1
json: {}

20 changes: 9 additions & 11 deletions tests/expected/martin-cp/flat_summary.txt
Original file line number Diff line number Diff line change
@@ -2,15 +2,13 @@ MBTiles file summary for tests/mbtiles_temp_files/cp_flat.mbtiles
Schema: flat
Page size: 512B

| Zoom | Count |Smallest | Largest | Average | BBox |
| 0| 1| 1.07KiB| 1.07KiB| 1.07KiB| -180,-85,180,85 |
| 1| 2| 141B| 167B| 154B| -180,-85,0,85 |
| 2| 4| 418B| 988B| 589B| -90,-67,90,67 |
| 3| 7| 52B| 962B| 311B| -45,-41,90,67 |
| 4| 13| 52B| 867B| 249B| -22,-22,157,56 |
| 5| 27| 52B| 741B| 193B| -11,-11,146,49 |
| 6| 69| 52B| 679B| 144B| -6,-6,146,45 |
| 7| 214| 48B| 633B| 118B| -3,-3,143,45 |
| 8| 751| 48B| 420B| 103B| -3,-1,143,45 |
| all| 1088| 48B| 1.0KiB| 117B| -180,-85,180,85 |
Zoom | Count | Smallest | Largest | Average | Bounding Box
0 | 1 | 643B | 643B | 643B | -180,-85,180,85
1 | 2 | 150B | 172B | 161B | -180,-85,0,85
2 | 4 | 291B | 690B | 414B | -90,-67,90,67
3 | 7 | 75B | 727B | 263B | -45,-41,90,67
4 | 13 | 75B | 684B | 225B | -22,-22,157,56
5 | 27 | 75B | 659B | 195B | -11,-11,146,49
6 | 69 | 75B | 633B | 155B | -6,-6,146,45
all | 123 | 75B | 727B | 190B | -180,-85,180,85

46 changes: 30 additions & 16 deletions tests/expected/martin-cp/normalized_metadata.txt
Original file line number Diff line number Diff line change
@@ -1,25 +1,39 @@
[INFO ] cp_normalized has an unrecognized metadata value foo={"bar":"foo"}
[INFO ] Using 'mvt' tile format from metadata table in file cp_normalized
id: cp_normalized
tile_info:
format: mvt
format: png
encoding: ''
layer_type: null
tilejson:
tilejson: 3.0.0
tiles: []
vector_layers:
- id: table_source
fields:
gid: int4
bounds:
- -2.0
- -1.0
- 142.84131509869133
- 45.0
name: table_source
foo: '{"bar":"foo"}'
format: mvt
- -180.0
- -85.0511
- 180.0
- 85.0511
center:
- 0.0
- 20.0
- 0
description: 'One of the example maps that comes with TileMill - a bright & colorful world map that blends retro and high-tech with its folded paper texture and interactive flag tooltips. '
legend: |-
<div style="text-align:center;">

<div style="font:12pt/16pt Georgia,serif;">Geography Class</div>
<div style="font:italic 10pt/16pt Georgia,serif;">by MapBox</div>

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAACWCAYAAAA8AXHiAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEUwAABFMBAq/upQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACIsSURBVHja7Z0JvI1V98dlSlHSICWSBpkvSmmSEEoyh9JAMke9ikb0Ns80Dxr16m2eVDIklShRqSgJlfImUWmS7P/6Pp19/vvuu5/nPGfAde9en8/6uPc49wx7/5611/qt4SmhlCrh1Wuu1S+CVw8srx5YXj2w/CLkW5ASJSqI9hVd2DgvT7Vt3ZoHh1jP2UP0fNF19erU4YFPRXv69fPAigOwA8qXL79g1tSpatjgwZvk926O55woukq0pF8zD6x0wHVClcqVn144b566dNSojfL7cdb/lxS9x6+VB1a6wGorWrbmfvvNWr54sRrcv//v8nsjG3x+rTyw0gaW9rsa1K+/cNXy5aprp05r5fea9nO8emClDSztsB91xBErVn/9tTq+VauV8ntlDywPrKyBlfi9Rvt27X4AXEc2a7ZIft/JA8sDK2tgJR6r37tXr1+/W7ZM1ahefZb8fpJfKw+sdEC1o2jvkP87aviQIRsenTCBX4b79fLASgdYbUTvj/j/Dj27d//bA8sDKy6g9hG9WHT17rvtxgN3iXZ2kaAifUSH+XXzwNocQNzBr4MHllcPLK8eWMXjyCMvWM6vhQdWroHVUHSiXwsPrFwDq6PoR34tPLByDazLRL/3a+GBlWtgPe6B5YG1OYD1juh3onv69fDAyiWwFor+LHq4Xw8PrFwC60tRfjjdr4cHVq5AVVH0mwSwbvJr4oEVV3cRPUqUTpyholeJThCdLDp/3rx5q3fffXdApdq0afOXPLZYdKboJNFbREeKniF6vOhBfj2LN7AOFh2RAAhgCZVnn31W7bzzzgGwDj30UBVDloneJtpGdHsPrKKtZURbJizMEpWGXHHFFapGjRoBsOrUqaPSlPWiz4meLbqXB1bR0WNFnxT9KR00/PXXX2rFihVq4cKF6tRTT1UNGzYMgMWRuGrVquRz0pRNovNELxQt74G1bWoT0Slxd/zqq69WrVu3Vo8++mjw+5NPPqnKlCmjmjVrpk466SSVl5cXAKts2bJq6tSpwXOGDRumdthhBzV06NDg9x9//FHdcsstasmSWAZxVcKfK+uBtW1oLdEnEtbBKRs3blS33XYbjrj64osvgsdefPFF9eCDD6pFixYln7Np0z8v0a1btySwdtppJzV79uzg8d9++y0A0dKlS4PfP//8c9W2bVu15557Jq2ZOP6pLBv+GBRGSQ+swqnVRKlR3+javTlz5qhrr702+TvH26233qp++OGHlKbl9NNPTwILBYCpjlHkjz/+UNWqVVMVK1ZUn376aaq3+Vi0owdW4dHdRW9mH8N2DEuCb3TWWWcFm52OrFu3LjjqTGANHz48vlMlVu/9999Pgq1Lly4BoP/888+wP5kj2sIDa+tq64SvUkCwEOeee25wpGnrkUq+/vpr9cYbb6j//ve/aty4cWrUqFGqQ4cO6oILLsgHrL322it4bfwyrNcrr7yiPvjgg1jO/KuvvqoOOeQQ9e6776Z66p2i5TywtqyWFr0mzI/ieOP4wblev3595JEFkC688EJVt25dVaVKFXXUUUep7t27B1bp+uuvD16DI9QE1gEHHKBuv/12dckllwRWEL+qXr16atdddw38sYceekj973//i2XNeK+nn3467CkfJvg2D6wtoNVFZxcIsVatCiwLDjXy009udmH16tXqkUceUaecckoABAjPsWPHBseVS8aMGaMmTJiQD1hhXBaA5rUBS6VKlVTTpk0DDozX1oGAKX///be6//77A44sIpJcn2D1PbA2ozYQ/dZeefyVmjVrBhsaZim++uor1bdvX7XLLruoTp06BWDRfFSUYIGIGE1g7bvvvgEoUjnwM2bMUOeff7466KCDVIMGDYLXcYl+LS4K6Ap9fNs8rQfW5iM614VtCmSmS77//vvgWKtcuXJgmX755Ze0nPfDDjssiChtH+ubb75J63WmTZsWWMcjjjhCzZw50/kcXrN+/foBbxYi94qW8sDKnXazoz4sAg70kCFDQqO5yy67TO2xxx5qxIgRsWgFl+B7ffnll/mABZf11ltvZfR6Tz31lDr44IPV8ccfr957770C/w/wNQEblrrcFpz6bQFUPTBMrOjkyZOT5OQLL7wQRFdEcjbgcLohKfv3769WrlypspH99tsv2GwTWOgDDzyQ8Wty1HEUV69ePaAfPvvsM+fzOEb5zhCwRKDGMf9qIvfpgZWhtsKF2rBhQwCiChUqBNFeq1atnLk6rFKLFi3UiSeemGTU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">
</div>
maxzoom: 1
minzoom: 0
name: Geography Class
template: |-
{{#__location__}}{{/__location__}}{{#__teaser__}}<div style="text-align:center;">

<img src="data:image/png;base64,{{flag_png}}" style="-moz-box-shadow:0px 1px 3px #222;-webkit-box-shadow:0px 1px 5px #222;box-shadow:0px 1px 3px #222;"><br>
<strong>{{admin}}</strong>

</div>{{/__teaser__}}{{#__full__}}{{/__full__}}
version: 1.0.0
format: png
generator: martin-cp v0.11.1
json: {}

15 changes: 4 additions & 11 deletions tests/expected/martin-cp/normalized_summary.txt
Original file line number Diff line number Diff line change
@@ -2,15 +2,8 @@ MBTiles file summary for tests/mbtiles_temp_files/cp_normalized.mbtiles
Schema: normalized
Page size: 512B

| Zoom | Count |Smallest | Largest | Average | BBox |
| 0| 1| 1.07KiB| 1.07KiB| 1.07KiB| -180,-85,180,85 |
| 1| 2| 141B| 167B| 154B| -180,-85,0,85 |
| 2| 4| 418B| 988B| 589B| -90,-67,90,67 |
| 3| 7| 52B| 962B| 311B| -45,-41,90,67 |
| 4| 13| 52B| 867B| 249B| -22,-22,157,56 |
| 5| 27| 52B| 741B| 193B| -11,-11,146,49 |
| 6| 69| 52B| 679B| 144B| -6,-6,146,45 |
| 7| 214| 48B| 633B| 118B| -3,-3,143,45 |
| 8| 751| 48B| 420B| 103B| -3,-1,143,45 |
| all| 1088| 48B| 1.0KiB| 117B| -180,-85,180,85 |
Zoom | Count | Smallest | Largest | Average | Bounding Box
0 | 1 | 20.7KiB | 20.7KiB | 20.7KiB | -180,-85,180,85
1 | 4 | 11.8KiB | 20.6KiB | 16.4KiB | -180,-85,180,85
all | 5 | 11.8KiB | 20.7KiB | 17.2KiB | -180,-85,180,85

18 changes: 9 additions & 9 deletions tests/expected/mbtiles/summary.txt
Original file line number Diff line number Diff line change
@@ -4,13 +4,13 @@ File size: 48.00KiB
Page size: 4.00KiB
Page count: 12

| Zoom | Count |Smallest | Largest | Average | BBox |
| 0| 1| 1.08KiB| 1.08KiB| 1.08KiB| -180,-85,180,85 |
| 1| 4| 160B| 650B| 366B| -180,-85,180,85 |
| 2| 7| 137B| 495B| 239B| -180,-67,180,67 |
| 3| 17| 67B| 246B| 134B| -135,-41,180,67 |
| 4| 38| 64B| 175B| 86B| -135,-41,180,67 |
| 5| 57| 64B| 107B| 72B| -124,-41,180,62 |
| 6| 72| 64B| 97B| 68B| -124,-41,180,62 |
| all| 196| 64B| 1.0KiB| 96B| -180,-85,180,85 |
Zoom | Count | Smallest | Largest | Average | Bounding Box
0 | 1 | 1.0KiB | 1.0KiB | 1.0KiB | -180,-85,180,85
1 | 4 | 160B | 650B | 366B | -180,-85,180,85
2 | 7 | 137B | 495B | 239B | -180,-67,180,67
3 | 17 | 67B | 246B | 134B | -135,-41,180,67
4 | 38 | 64B | 175B | 86B | -135,-41,180,67
5 | 57 | 64B | 107B | 72B | -124,-41,180,62
6 | 72 | 64B | 97B | 68B | -124,-41,180,62
all | 196 | 64B | 1.0KiB | 96B | -180,-85,180,85

10 changes: 5 additions & 5 deletions tests/test.sh
Original file line number Diff line number Diff line change
@@ -386,13 +386,13 @@ if [[ "$MARTIN_CP_BIN" != "-" ]]; then

test_martin_cp "flat" "${CFG[@]}" \
--source table_source --mbtiles-type flat --concurrency 3 \
--min-zoom 0 --max-zoom 8 "--bbox=-2,-1,142.84,45"
--min-zoom 0 --max-zoom 6 "--bbox=-2,-1,142.84,45"
test_martin_cp "flat-with-hash" "${CFG[@]}" \
--source table_source --mbtiles-type flat-with-hash --concurrency 3 \
--min-zoom 0 --max-zoom 8 "--bbox=-2,-1,142.84,45"
--source function_zxy_query_test --url-query 'foo=bar&token=martin' --encoding 'identity' --mbtiles-type flat-with-hash --concurrency 3 \
--min-zoom 0 --max-zoom 6 "--bbox=-2,-1,142.84,45"
test_martin_cp "normalized" "${CFG[@]}" \
--source table_source --mbtiles-type normalized --concurrency 3 \
--min-zoom 0 --max-zoom 8 "--bbox=-2,-1,142.84,45"
--source geography-class-png --mbtiles-type normalized --concurrency 3 \
--min-zoom 0 --max-zoom 6 "--bbox=-2,-1,142.84,45"

unset DATABASE_URL