mirror of
https://github.com/maplibre/martin.git
synced 2024-12-19 21:01:45 +03:00
move tile query to db
This commit is contained in:
parent
25e4a8b8cb
commit
31ec5f8615
34
Cargo.lock
generated
34
Cargo.lock
generated
@ -52,7 +52,7 @@ dependencies = [
|
||||
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"skeptic 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -233,8 +233,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -666,7 +666,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -744,8 +744,8 @@ dependencies = [
|
||||
"postgres 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"r2d2 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"r2d2_postgres 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1191,7 +1191,7 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1201,23 +1201,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.33"
|
||||
version = "1.0.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.33"
|
||||
version = "1.0.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive_internals 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive_internals 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive_internals"
|
||||
version = "0.21.0"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1230,9 +1230,9 @@ version = "1.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itoa 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1774,7 +1774,7 @@ dependencies = [
|
||||
"checksum indexmap 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9378f1f3923647a9aea6af4c6b5de68cc8a71415459ad25ef191191c48f5b7"
|
||||
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
|
||||
"checksum ipconfig 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec4e18c0a0d4340870c14284293632d8421f419008371422dd327892b88877c"
|
||||
"checksum itoa 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92a9df60778f789c37f76778ae8d0a2471c41baa8b059d98a5873c978f549587"
|
||||
"checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
||||
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
||||
@ -1838,9 +1838,9 @@ dependencies = [
|
||||
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||
"checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe95aa0d46f04ce5c3a88bdcd4114ecd6144ed0b2725ebca2f1127744357807"
|
||||
"checksum serde_derive 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "23b163a6ce7e1aa897919f9d8e40bd1f8a6f95342ed57727ae31387a01a7a356"
|
||||
"checksum serde_derive_internals 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "370aa477297975243dc914d0b0e1234927520ec311de507a560fbd1c80f7ab8c"
|
||||
"checksum serde 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "0e100d00fb985a5bf16b857a436450e404fa613de3321b2e383947a93cbd75df"
|
||||
"checksum serde_derive 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "86daebd995aa948b069d886f2105f2425cd66103049855e45c15c58c573f12c5"
|
||||
"checksum serde_derive_internals 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3f714f52a41e371c5e141e9dafcead60921349bec76b44d79000c88aba3cfc"
|
||||
"checksum serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5c508584d9913df116b91505eec55610a2f5b16e9ed793c46e4d0152872b3e74"
|
||||
"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
|
||||
"checksum sha2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7daca11f2fdb8559c4f6c588386bed5e2ad4b6605c1442935a7f08144a918688"
|
||||
|
44
src/db.rs
44
src/db.rs
@ -4,8 +4,11 @@ use r2d2::{Config, Pool, PooledConnection};
|
||||
use std::error::Error;
|
||||
use std::io;
|
||||
|
||||
use super::utils;
|
||||
use super::source::Source;
|
||||
|
||||
// static GET_SOURCES_QUERY: &'static str = include_str!("scripts/get_sources.sql");
|
||||
|
||||
pub type PostgresPool = Pool<PostgresConnectionManager>;
|
||||
pub type PostgresConnection = PooledConnection<PostgresConnectionManager>;
|
||||
|
||||
@ -25,10 +28,11 @@ impl Actor for DbExecutor {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GetTile {
|
||||
pub source: Source,
|
||||
pub z: u32,
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
pub source: Source,
|
||||
pub condition: Option<String>,
|
||||
}
|
||||
|
||||
impl Message for GetTile {
|
||||
@ -40,7 +44,43 @@ impl Handler<GetTile> for DbExecutor {
|
||||
|
||||
fn handle(&mut self, msg: GetTile, _: &mut Self::Context) -> Self::Result {
|
||||
let conn = self.0.get().unwrap();
|
||||
let query = msg.source.get_query(msg.z, msg.x, msg.y, None);
|
||||
let source = msg.source;
|
||||
|
||||
let mercator_bounds = utils::tilebbox(msg.z, msg.x, msg.y);
|
||||
|
||||
let (geometry_column_mercator, original_bounds) = if source.srid == 3857 {
|
||||
(source.geometry_column.clone(), mercator_bounds.clone())
|
||||
} else {
|
||||
(
|
||||
format!("ST_Transform({0}, 3857)", source.geometry_column),
|
||||
format!("ST_Transform({0}, {1})", mercator_bounds, source.srid),
|
||||
)
|
||||
};
|
||||
|
||||
let columns: Vec<String> = source
|
||||
.properties
|
||||
.keys()
|
||||
.map(|column| format!("\"{0}\"", column))
|
||||
.collect();
|
||||
|
||||
let properties = columns.join(",");
|
||||
|
||||
let condition = msg.condition
|
||||
.map_or("".to_string(), |condition| format!("AND {}", condition));
|
||||
|
||||
let query = format!(
|
||||
include_str!("scripts/get_tile.sql"),
|
||||
id = source.id,
|
||||
geometry_column = source.geometry_column,
|
||||
geometry_column_mercator = geometry_column_mercator,
|
||||
original_bounds = original_bounds,
|
||||
mercator_bounds = mercator_bounds,
|
||||
extent = source.extent,
|
||||
buffer = source.buffer,
|
||||
clip_geom = source.clip_geom,
|
||||
properties = properties,
|
||||
condition = condition,
|
||||
);
|
||||
|
||||
let tile: Vec<u8> = conn.query(&query, &[])
|
||||
.map(|rows| rows.get(0).get("st_asmvt"))
|
||||
|
@ -59,13 +59,16 @@ fn tile(req: HttpRequest<State>) -> Box<Future<Item = HttpResponse, Error = Erro
|
||||
.ok_or(error::ErrorNotFound("invalid y"))
|
||||
.unwrap();
|
||||
|
||||
let condition = None;
|
||||
|
||||
req.state()
|
||||
.db
|
||||
.send(GetTile {
|
||||
source: source.clone(),
|
||||
z: z,
|
||||
x: x,
|
||||
y: y,
|
||||
source: source.clone(),
|
||||
condition: condition,
|
||||
})
|
||||
.from_err()
|
||||
.and_then(|res| match res {
|
||||
|
20
src/scripts/get_sources.sql
Normal file
20
src/scripts/get_sources.sql
Normal file
@ -0,0 +1,20 @@
|
||||
WITH columns AS (
|
||||
SELECT
|
||||
ns.nspname AS table_schema,
|
||||
class.relname AS table_name,
|
||||
attr.attname AS column_name,
|
||||
trim(leading '_' from tp.typname) AS type_name
|
||||
FROM pg_attribute attr
|
||||
JOIN pg_catalog.pg_class AS class ON class.oid = attr.attrelid
|
||||
JOIN pg_catalog.pg_namespace AS ns ON ns.oid = class.relnamespace
|
||||
JOIN pg_catalog.pg_type AS tp ON tp.oid = attr.atttypid
|
||||
WHERE NOT attr.attisdropped AND attr.attnum > 0)
|
||||
SELECT
|
||||
f_table_schema, f_table_name, f_geometry_column, srid, type,
|
||||
jsonb_object_agg(columns.column_name, columns.type_name) as properties
|
||||
FROM geometry_columns
|
||||
LEFT JOIN columns ON
|
||||
geometry_columns.f_table_schema = columns.table_schema AND
|
||||
geometry_columns.f_table_name = columns.table_name AND
|
||||
geometry_columns.f_geometry_column != columns.column_name
|
||||
GROUP BY f_table_schema, f_table_name, f_geometry_column, srid, type;
|
14
src/scripts/get_tile.sql
Normal file
14
src/scripts/get_tile.sql
Normal file
@ -0,0 +1,14 @@
|
||||
WITH bounds AS (SELECT {mercator_bounds} as mercator, {original_bounds} as original)
|
||||
SELECT ST_AsMVT(tile, '{id}', {extent}, 'geom') FROM (
|
||||
SELECT
|
||||
ST_AsMVTGeom(
|
||||
{geometry_column_mercator},
|
||||
bounds.mercator,
|
||||
{extent},
|
||||
{buffer},
|
||||
{clip_geom}
|
||||
) AS geom,
|
||||
{properties}
|
||||
FROM {id}, bounds
|
||||
WHERE {geometry_column} && bounds.original {condition}
|
||||
) AS tile WHERE geom IS NOT NULL
|
@ -1,4 +1,3 @@
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
|
||||
@ -10,75 +9,17 @@ pub struct Source {
|
||||
pub id: String,
|
||||
schema: String,
|
||||
table: String,
|
||||
geometry_column: String,
|
||||
srid: u32,
|
||||
extent: u32,
|
||||
buffer: u32,
|
||||
clip_geom: bool,
|
||||
pub geometry_column: String,
|
||||
pub srid: u32,
|
||||
pub extent: u32,
|
||||
pub buffer: u32,
|
||||
pub clip_geom: bool,
|
||||
geometry_type: String,
|
||||
properties: HashMap<String, String>,
|
||||
pub properties: HashMap<String, String>,
|
||||
}
|
||||
|
||||
pub type Sources = HashMap<String, Source>;
|
||||
|
||||
impl Source {
|
||||
fn geometry_column_mercator(&self) -> Cow<str> {
|
||||
if self.srid == 3857 {
|
||||
self.geometry_column.as_str().into()
|
||||
} else {
|
||||
format!("ST_Transform({0}, 3857)", self.geometry_column).into()
|
||||
}
|
||||
}
|
||||
|
||||
fn properties_query(&self) -> String {
|
||||
let keys: Vec<String> = self.properties
|
||||
.keys()
|
||||
.map(|key| format!("\"{0}\"", key))
|
||||
.collect();
|
||||
|
||||
keys.join(",")
|
||||
}
|
||||
|
||||
pub fn get_query(&self, z: u32, x: u32, y: u32, condition: Option<String>) -> String {
|
||||
let mercator_bounds = utils::tilebbox(z, x, y);
|
||||
|
||||
let original_bounds: Cow<str> = if self.srid == 3857 {
|
||||
mercator_bounds.as_str().into()
|
||||
} else {
|
||||
format!("ST_Transform({0}, {1})", mercator_bounds, self.srid).into()
|
||||
};
|
||||
|
||||
let query = format!(
|
||||
"WITH bounds AS (SELECT {mercator_bounds} as mercator, {original_bounds} as original) \
|
||||
SELECT ST_AsMVT(tile, '{id}', {extent}, 'geom') FROM (\
|
||||
SELECT \
|
||||
ST_AsMVTGeom(\
|
||||
{geometry_column_mercator},\
|
||||
bounds.mercator,\
|
||||
{extent},\
|
||||
{buffer},\
|
||||
{clip_geom}\
|
||||
) AS geom,\
|
||||
{properties} \
|
||||
FROM {id}, bounds \
|
||||
WHERE {geometry_column} && bounds.original {condition}\
|
||||
) AS tile WHERE geom IS NOT NULL",
|
||||
id = self.id,
|
||||
geometry_column = self.geometry_column,
|
||||
geometry_column_mercator = self.geometry_column_mercator(),
|
||||
original_bounds = original_bounds,
|
||||
mercator_bounds = mercator_bounds,
|
||||
extent = self.extent,
|
||||
buffer = self.buffer,
|
||||
clip_geom = self.clip_geom,
|
||||
properties = self.properties_query(),
|
||||
condition = condition.map_or("".to_string(), |condition| format!("AND {}", condition)),
|
||||
);
|
||||
|
||||
query
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_sources(conn: PostgresConnection) -> Result<HashMap<String, Source>, Box<Error>> {
|
||||
let query = "
|
||||
WITH columns AS (
|
||||
|
Loading…
Reference in New Issue
Block a user