from nominatim.config import Configuration
from nominatim.api.connection import SearchConnection
from nominatim.api.status import get_status, StatusResult
-from nominatim.api.lookup import get_place_by_id
+from nominatim.api.lookup import get_detailed_place
from nominatim.api.reverse import ReverseGeocoder
from nominatim.api.types import PlaceRef, LookupDetails, AnyPoint, DataLayer
from nominatim.api.results import DetailedResult, ReverseResult
Returns None if there is no entry under the given ID.
"""
async with self.begin() as conn:
- return await get_place_by_id(conn, place, details or LookupDetails())
+ return await get_detailed_place(conn, place, details or LookupDetails())
async def reverse(self, coord: AnyPoint, max_rank: Optional[int] = None,
"""
Implementation of place lookup by ID.
"""
-from typing import Optional
+from typing import Optional, Callable, Tuple, Type
import datetime as dt
import sqlalchemy as sa
import nominatim.api.results as nres
from nominatim.api.logging import log
+RowFunc = Callable[[Optional[SaRow], Type[nres.BaseResultT]], Optional[nres.BaseResultT]]
+
def _select_column_geometry(column: SaColumn,
geometry_output: ntyp.GeometryFormat) -> SaLabel:
""" Create the appropriate column expression for selecting a
return (await conn.execute(sql)).one_or_none()
-async def get_place_by_id(conn: SearchConnection, place: ntyp.PlaceRef,
- details: ntyp.LookupDetails) -> Optional[nres.DetailedResult]:
+async def find_in_all_tables(conn: SearchConnection, place: ntyp.PlaceRef,
+ details: ntyp.LookupDetails
+ ) -> Tuple[Optional[SaRow], RowFunc[nres.BaseResultT]]:
+ """ Search for the given place in all data tables
+ and return the base information.
+ """
+ row = await find_in_placex(conn, place, details)
+ log().var_dump('Result (placex)', row)
+ if row is not None:
+ return row, nres.create_from_placex_row
+
+ row = await find_in_osmline(conn, place, details)
+ log().var_dump('Result (osmline)', row)
+ if row is not None:
+ return row, nres.create_from_osmline_row
+
+ row = await find_in_postcode(conn, place, details)
+ log().var_dump('Result (postcode)', row)
+ if row is not None:
+ return row, nres.create_from_postcode_row
+
+ row = await find_in_tiger(conn, place, details)
+ log().var_dump('Result (tiger)', row)
+ return row, nres.create_from_tiger_row
+
+
+async def get_detailed_place(conn: SearchConnection, place: ntyp.PlaceRef,
+ details: ntyp.LookupDetails) -> Optional[nres.DetailedResult]:
""" Retrieve a place with additional details from the database.
"""
log().function('get_place_by_id', place=place, details=details)
if details.geometry_output and details.geometry_output != ntyp.GeometryFormat.GEOJSON:
raise ValueError("lookup only supports geojosn polygon output.")
- row = await find_in_placex(conn, place, details)
- log().var_dump('Result (placex)', row)
- if row is not None:
- result = nres.create_from_placex_row(row, nres.DetailedResult)
- else:
- row = await find_in_osmline(conn, place, details)
- log().var_dump('Result (osmline)', row)
- if row is not None:
- result = nres.create_from_osmline_row(row, nres.DetailedResult)
- else:
- row = await find_in_postcode(conn, place, details)
- log().var_dump('Result (postcode)', row)
- if row is not None:
- result = nres.create_from_postcode_row(row, nres.DetailedResult)
- else:
- row = await find_in_tiger(conn, place, details)
- log().var_dump('Result (tiger)', row)
- if row is not None:
- result = nres.create_from_tiger_row(row, nres.DetailedResult)
- else:
- return None
+ row_func: RowFunc[nres.DetailedResult]
+ row, row_func = await find_in_all_tables(conn, place, details)
+
+ if row is None:
+ return None
+
+ result = row_func(row, nres.DetailedResult)
+ assert result is not None
# add missing details
assert result is not None