mirror of
https://github.com/maplibre/martin.git
synced 2024-12-20 05:11:57 +03:00
Fix handling for null-returning PG queries (#521)
Handle cases when a query returns a NULL or a table with no rows, or a single row with a null value in it. This fully fixes #519 in the main branch
This commit is contained in:
parent
3f7f35ecdc
commit
9efa364eb0
@ -73,19 +73,22 @@ impl Source for PgSource {
|
||||
let json = query_to_json(url_query);
|
||||
debug!("SQL: {query} [{xyz}, {json:?}]");
|
||||
let params: &[&(dyn ToSql + Sync)] = &[&xyz.z, &xyz.x, &xyz.y, &json];
|
||||
conn.query_one(&prep_query, params).await
|
||||
conn.query_opt(&prep_query, params).await
|
||||
} else {
|
||||
debug!("SQL: {query} [{xyz}]");
|
||||
conn.query_one(&prep_query, &[&xyz.z, &xyz.x, &xyz.y]).await
|
||||
conn.query_opt(&prep_query, &[&xyz.z, &xyz.x, &xyz.y]).await
|
||||
};
|
||||
|
||||
let tile = tile.map(|row| row.get(0)).map_err(|e| {
|
||||
let tile = tile
|
||||
.map(|row| row.map_or(Default::default(), |r| r.get::<_, Option<Tile>>(0)))
|
||||
.map_err(|e| {
|
||||
if self.info.has_query_params {
|
||||
GetTileWithQueryError(e, self.id.to_string(), *xyz, url_query.clone())
|
||||
} else {
|
||||
GetTileError(e, self.id.to_string(), *xyz)
|
||||
}
|
||||
})?;
|
||||
})?
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(tile)
|
||||
}
|
||||
|
@ -134,10 +134,10 @@ pub enum PgError {
|
||||
String,
|
||||
),
|
||||
|
||||
#[error(r#"Unable to get tile {1}/{2:#}: {0}"#)]
|
||||
#[error(r#"Unable to get tile {2:#} from {1}: {0}"#)]
|
||||
GetTileError(#[source] bb8_postgres::tokio_postgres::Error, String, Xyz),
|
||||
|
||||
#[error(r#"Unable to get tile {1}/{2:#} with {:?} params: {0}"#, query_to_json(.3))]
|
||||
#[error(r#"Unable to get tile {2:#} with {:?} params from {1}: {0}"#, query_to_json(.3))]
|
||||
GetTileWithQueryError(
|
||||
#[source] bb8_postgres::tokio_postgres::Error,
|
||||
String,
|
||||
|
7
tests/fixtures/functions/function_null.sql
vendored
Normal file
7
tests/fixtures/functions/function_null.sql
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
DROP FUNCTION IF EXISTS public.function_null;
|
||||
|
||||
CREATE OR REPLACE FUNCTION public.function_null(z integer, x integer, y integer) RETURNS bytea AS $$
|
||||
BEGIN
|
||||
RETURN null;
|
||||
END
|
||||
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
6
tests/fixtures/functions/function_null_row.sql
vendored
Normal file
6
tests/fixtures/functions/function_null_row.sql
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
DROP FUNCTION IF EXISTS public.function_null_row;
|
||||
|
||||
CREATE OR REPLACE FUNCTION public.function_null_row(z integer, x integer, y integer)
|
||||
RETURNS TABLE(mvt bytea, key text) AS $$
|
||||
SELECT NULL::bytea, NULL::text
|
||||
$$ LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE;
|
6
tests/fixtures/functions/function_null_row2.sql
vendored
Normal file
6
tests/fixtures/functions/function_null_row2.sql
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
DROP FUNCTION IF EXISTS public.function_null_row2;
|
||||
|
||||
CREATE OR REPLACE FUNCTION public.function_null_row2(z integer, x integer, y integer)
|
||||
RETURNS TABLE(mvt bytea, key text) AS $$
|
||||
SELECT NULL::bytea, NULL::text WHERE FALSE;
|
||||
$$ LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE;
|
@ -316,6 +316,23 @@ async fn get_composite_source_tile_minmax_zoom_ok() {
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn null_functions() {
|
||||
let app = create_app!(mock_empty_config());
|
||||
|
||||
let req = test_get("/function_null/0/0/0");
|
||||
let response = call_service(&app, req).await;
|
||||
assert_eq!(response.status(), StatusCode::NO_CONTENT);
|
||||
|
||||
let req = test_get("/function_null_row/0/0/0");
|
||||
let response = call_service(&app, req).await;
|
||||
assert_eq!(response.status(), StatusCode::NO_CONTENT);
|
||||
|
||||
let req = test_get("/function_null_row2/0/0/0");
|
||||
let response = call_service(&app, req).await;
|
||||
assert_eq!(response.status(), StatusCode::NO_CONTENT);
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn get_function_source_ok() {
|
||||
let app = create_app!(mock_empty_config());
|
||||
|
Loading…
Reference in New Issue
Block a user