X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/5226cd2a0bc2baa06d32752f29d4e1f3c632dd13..5184a8aff9686c4035e236be65c3615fe97859a0:/nominatim/api/connection.py diff --git a/nominatim/api/connection.py b/nominatim/api/connection.py index 1502ba01..efa4490e 100644 --- a/nominatim/api/connection.py +++ b/nominatim/api/connection.py @@ -7,12 +7,13 @@ """ Extended SQLAlchemy connection class that also includes access to the schema. """ -from typing import Any, Mapping, Sequence, Union +from typing import Any, Mapping, Sequence, Union, Dict, cast import sqlalchemy as sa from sqlalchemy.ext.asyncio import AsyncConnection from nominatim.db.sqlalchemy_schema import SearchTables +from nominatim.api.logging import log class SearchConnection: """ An extended SQLAlchemy connection class, that also contains @@ -22,9 +23,11 @@ class SearchConnection: """ def __init__(self, conn: AsyncConnection, - tables: SearchTables) -> None: + tables: SearchTables, + properties: Dict[str, Any]) -> None: self.connection = conn self.t = tables # pylint: disable=invalid-name + self._property_cache = properties async def scalar(self, sql: sa.sql.base.Executable, @@ -32,12 +35,55 @@ class SearchConnection: ) -> Any: """ Execute a 'scalar()' query on the connection. """ + log().sql(self.connection, sql) return await self.connection.scalar(sql, params) - async def execute(self, sql: sa.sql.base.Executable, + async def execute(self, sql: 'sa.Executable', params: Union[Mapping[str, Any], Sequence[Mapping[str, Any]], None] = None - ) -> sa.engine.Result: + ) -> 'sa.Result[Any]': """ Execute a 'execute()' query on the connection. """ + log().sql(self.connection, sql) return await self.connection.execute(sql, params) + + + async def get_property(self, name: str, cached: bool = True) -> str: + """ Get a property from Nominatim's property table. + + Property values are normally cached so that they are only + retrieved from the database when they are queried for the + first time with this function. Set 'cached' to False to force + reading the property from the database. + + Raises a ValueError if the property does not exist. + """ + if name.startswith('DB:'): + raise ValueError(f"Illegal property value '{name}'.") + + if cached and name in self._property_cache: + return cast(str, self._property_cache[name]) + + sql = sa.select(self.t.properties.c.value)\ + .where(self.t.properties.c.property == name) + value = await self.connection.scalar(sql) + + if value is None: + raise ValueError(f"Property '{name}' not found in database.") + + self._property_cache[name] = cast(str, value) + + return cast(str, value) + + + async def get_db_property(self, name: str) -> Any: + """ Get a setting from the database. At the moment, only + 'server_version', the version of the database software, can + be retrieved with this function. + + Raises a ValueError if the property does not exist. + """ + if name != 'server_version': + raise ValueError(f"DB setting '{name}' not found in database.") + + return self._property_cache['DB:server_version']