From ca44463c0f1ab41401e9dd2c83becfe0f70ad29a Mon Sep 17 00:00:00 2001 From: Stepan Kuzmin Date: Mon, 27 Nov 2017 17:52:07 +0300 Subject: [PATCH] refactor tile query --- src/db.rs | 83 ++++++++++++++++++++++++++++++++++----------------- src/routes.rs | 6 +++- 2 files changed, 60 insertions(+), 29 deletions(-) diff --git a/src/db.rs b/src/db.rs index 935d1b7d..d6357473 100644 --- a/src/db.rs +++ b/src/db.rs @@ -8,7 +8,7 @@ use r2d2::{Config, Pool, PooledConnection}; use r2d2_postgres::{TlsMode, PostgresConnectionManager}; pub type PostgresPool = Pool; -pub type PostgresPooledConnection = PooledConnection; +pub type PostgresConnection = PooledConnection; pub struct DB; impl Key for DB { type Value = PostgresPool; } @@ -20,64 +20,91 @@ pub fn setup_connection_pool(cn_str: &str, pool_size: u32) -> Result Result> { +pub fn get_connection(req: &mut Request) -> Result> { let pool = try!(req.get::>()); let conn = try!(pool.get()); Ok(conn) } -pub fn get_tile(conn: PostgresPooledConnection, schema: &str, table: &str, z: &str, x: &str, y: &str) -> Result, Box> { - let query = format!( - "SELECT ST_AsMVT(q, '{1}', 4096, 'geom') FROM ( \ - SELECT ST_AsMVTGeom( \ - geom, \ - TileBBox({2}, {3}, {4}, 4326), \ - 4096, \ - 256, \ - true \ - ) AS geom FROM {0}.{1} \ - ) AS q;", - schema, table, z, x, y - ); - - let rows = try!(conn.query(&query, &[])); +pub fn get_tile(conn: PostgresConnection, tileset: &Tileset, z: &i32, x: &i32, y: &i32) -> Result, Box> { + let rows = try!(conn.query(&tileset.query, &[&z, &x, &y])); let tile = rows.get(0).get("st_asmvt"); Ok(tile) } #[derive(Debug)] pub struct Tileset { - pub schema: String, - pub table: String, - pub geometry_column: String, - pub srid: i32, - pub _type: String + schema: String, + table: String, + geometry_column: String, + srid: i32, + extent: i32, + buffer: i32, + clip_geom: bool, + geometry_type: String, + query: String } pub struct Tilesets; impl Key for Tilesets { type Value = HashMap; } -pub fn get_tilesets(conn: PostgresPooledConnection) -> Result, Box> { +pub fn get_tilesets(conn: PostgresConnection) -> Result, Box> { let query = " select f_table_schema, f_table_name, f_geometry_column, srid, type from geometry_columns "; + let default_extent = 4096; + let default_buffer = 256; + let default_clip_geom = true; + let mut tilesets = HashMap::new(); let rows = try!(conn.query(&query, &[])); for row in &rows { - let schema = row.get("f_table_schema"); - let table = row.get("f_table_name"); + let schema: String = row.get("f_table_schema"); + let table: String = row.get("f_table_name"); let id = format!("{}.{}", schema, table); + let geometry_column: String = row.get("f_geometry_column"); + let srid: i32 = row.get("srid"); + + let transformed_geometry = if srid == 3857 { + geometry_column.clone() + } else { + format!("ST_Transform({0}, 3857)", geometry_column) + }; + + let query = format!( + "SELECT ST_AsMVT(q, '{1}', {4}, '{2}') FROM (\ + SELECT ST_AsMVTGeom(\ + {3}, \ + TileBBox($1, $2, $3, 3857), \ + {4}, \ + {5}, \ + {6}\ + ) AS geom FROM {0}.{1}\ + ) AS q;", + schema, + table, + geometry_column, + transformed_geometry, + default_extent, + default_buffer, + default_clip_geom + ); + let tileset = Tileset { schema: schema, table: table, - geometry_column: row.get("f_geometry_column"), - srid: row.get("srid"), - _type: row.get("type") + geometry_column: geometry_column, + srid: srid, + extent: default_extent, + buffer: default_buffer, + clip_geom: default_clip_geom, + geometry_type: row.get("type"), + query: query }; tilesets.insert(id, tileset); diff --git a/src/routes.rs b/src/routes.rs index 7f21d96d..50bb4778 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -29,7 +29,11 @@ pub fn tile(req: &mut Request, caps: Captures) -> IronResult { } }; - let tile = match db::get_tile(conn, &tileset.schema, &tileset.table, &caps["z"], &caps["x"], &caps["y"]) { + let z: &i32 = &caps["z"].parse().unwrap(); + let x: &i32 = &caps["x"].parse().unwrap(); + let y: &i32 = &caps["y"].parse().unwrap(); + + let tile = match db::get_tile(conn, &tileset, z, x, y) { Ok(tile) => tile, Err(error) => { eprintln!("Couldn't get a tile: {}", error);