]> git.openstreetmap.org Git - nominatim.git/blobdiff - nominatim/api/connection.py
add API functions for search functions
[nominatim.git] / nominatim / api / connection.py
index 79a5e3470d7b43340500aaa64c8739986e3467d4..e157d06208a48403de26c7b87189c087a6dcc99c 100644 (file)
@@ -7,12 +7,15 @@
 """
 Extended SQLAlchemy connection class that also includes access to the schema.
 """
 """
 Extended SQLAlchemy connection class that also includes access to the schema.
 """
-from typing import Any, Mapping, Sequence, Union, Dict, cast
+from typing import cast, Any, Mapping, Sequence, Union, Dict, Optional, Set
 
 import sqlalchemy as sa
 
 import sqlalchemy as sa
+from geoalchemy2 import Geometry
 from sqlalchemy.ext.asyncio import AsyncConnection
 
 from sqlalchemy.ext.asyncio import AsyncConnection
 
+from nominatim.typing import SaFromClause
 from nominatim.db.sqlalchemy_schema import SearchTables
 from nominatim.db.sqlalchemy_schema import SearchTables
+from nominatim.api.logging import log
 
 class SearchConnection:
     """ An extended SQLAlchemy connection class, that also contains
 
 class SearchConnection:
     """ An extended SQLAlchemy connection class, that also contains
@@ -27,6 +30,7 @@ class SearchConnection:
         self.connection = conn
         self.t = tables # pylint: disable=invalid-name
         self._property_cache = properties
         self.connection = conn
         self.t = tables # pylint: disable=invalid-name
         self._property_cache = properties
+        self._classtables: Optional[Set[str]] = None
 
 
     async def scalar(self, sql: sa.sql.base.Executable,
 
 
     async def scalar(self, sql: sa.sql.base.Executable,
@@ -34,14 +38,16 @@ class SearchConnection:
                     ) -> Any:
         """ Execute a 'scalar()' query on the connection.
         """
                     ) -> Any:
         """ Execute a 'scalar()' query on the connection.
         """
+        log().sql(self.connection, sql)
         return await self.connection.scalar(sql, params)
 
 
         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
                       params: Union[Mapping[str, Any], Sequence[Mapping[str, Any]], None] = None
-                     ) -> 'sa.engine.Result[Any]':
+                     ) -> 'sa.Result[Any]':
         """ Execute a 'execute()' query on the connection.
         """
         """ Execute a 'execute()' query on the connection.
         """
+        log().sql(self.connection, sql)
         return await self.connection.execute(sql, params)
 
 
         return await self.connection.execute(sql, params)
 
 
@@ -84,3 +90,26 @@ class SearchConnection:
             raise ValueError(f"DB setting '{name}' not found in database.")
 
         return self._property_cache['DB:server_version']
             raise ValueError(f"DB setting '{name}' not found in database.")
 
         return self._property_cache['DB:server_version']
+
+
+    async def get_class_table(self, cls: str, typ: str) -> Optional[SaFromClause]:
+        """ Lookup up if there is a classtype table for the given category
+            and return a SQLAlchemy table for it, if it exists.
+        """
+        if self._classtables is None:
+            res = await self.execute(sa.text("""SELECT tablename FROM pg_tables
+                                                WHERE tablename LIKE 'place_classtype_%'
+                                             """))
+            self._classtables = {r[0] for r in res}
+
+        tablename = f"place_classtype_{cls}_{typ}"
+
+        if tablename not in self._classtables:
+            return None
+
+        if tablename in self.t.meta.tables:
+            return self.t.meta.tables[tablename]
+
+        return sa.Table(tablename, self.t.meta,
+                        sa.Column('place_id', sa.BigInteger),
+                        sa.Column('centroid', Geometry(srid=4326, spatial_index=False)))