X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/386b4c82da79999046fe899339ed264bfc5d7fa6..e7dc24c026cb8059493b4a04df8debe9809b311b:/nominatim/api/core.py?ds=sidebyside diff --git a/nominatim/api/core.py b/nominatim/api/core.py index fe7cfa3a..44ac9160 100644 --- a/nominatim/api/core.py +++ b/nominatim/api/core.py @@ -29,7 +29,7 @@ import nominatim.api.types as ntyp from nominatim.api.results import DetailedResult, ReverseResult, SearchResults -class NominatimAPIAsync: +class NominatimAPIAsync: #pylint: disable=too-many-instance-attributes """ The main frontend to the Nominatim database implements the functions for lookup, forward and reverse geocoding using asynchronous functions. @@ -58,6 +58,7 @@ class NominatimAPIAsync: self.config = Configuration(project_dir, environ) self.query_timeout = self.config.get_int('QUERY_TIMEOUT') \ if self.config.QUERY_TIMEOUT else None + self.reverse_restrict_to_country_area = self.config.get_bool('SEARCH_WITHIN_COUNTRIES') self.server_version = 0 if sys.version_info >= (3, 10): @@ -80,21 +81,34 @@ class NominatimAPIAsync: if self._engine: return - dsn = self.config.get_database_params() - pool_size = self.config.get_int('API_POOL_SIZE') + extra_args: Dict[str, Any] = {'future': True, + 'echo': self.config.get_bool('DEBUG_SQL')} - query = {k: v for k, v in dsn.items() - if k not in ('user', 'password', 'dbname', 'host', 'port')} + is_sqlite = self.config.DATABASE_DSN.startswith('sqlite:') - dburl = sa.engine.URL.create( - f'postgresql+{PGCORE_LIB}', - database=dsn.get('dbname'), - username=dsn.get('user'), password=dsn.get('password'), - host=dsn.get('host'), port=int(dsn['port']) if 'port' in dsn else None, - query=query) - engine = sa_asyncio.create_async_engine(dburl, future=True, - max_overflow=0, pool_size=pool_size, - echo=self.config.get_bool('DEBUG_SQL')) + if is_sqlite: + params = dict((p.split('=', 1) + for p in self.config.DATABASE_DSN[7:].split(';'))) + dburl = sa.engine.URL.create('sqlite+aiosqlite', + database=params.get('dbname')) + + else: + dsn = self.config.get_database_params() + query = {k: v for k, v in dsn.items() + if k not in ('user', 'password', 'dbname', 'host', 'port')} + + dburl = sa.engine.URL.create( + f'postgresql+{PGCORE_LIB}', + database=dsn.get('dbname'), + username=dsn.get('user'), + password=dsn.get('password'), + host=dsn.get('host'), + port=int(dsn['port']) if 'port' in dsn else None, + query=query) + extra_args['max_overflow'] = 0 + extra_args['pool_size'] = self.config.get_int('API_POOL_SIZE') + + engine = sa_asyncio.create_async_engine(dburl, **extra_args) try: async with engine.begin() as conn: @@ -103,7 +117,7 @@ class NominatimAPIAsync: except (PGCORE_ERROR, sa.exc.OperationalError): server_version = 0 - if server_version >= 110000: + if server_version >= 110000 and not is_sqlite: @sa.event.listens_for(engine.sync_engine, "connect") def _on_connect(dbapi_con: Any, _: Any) -> None: cursor = dbapi_con.cursor() @@ -112,6 +126,15 @@ class NominatimAPIAsync: # Make sure that all connections get the new settings await self.close() + if is_sqlite: + @sa.event.listens_for(engine.sync_engine, "connect") + def _on_sqlite_connect(dbapi_con: Any, _: Any) -> None: + dbapi_con.run_async(lambda conn: conn.enable_load_extension(True)) + cursor = dbapi_con.cursor() + cursor.execute("SELECT load_extension('mod_spatialite')") + cursor.execute('SELECT SetDecimalPrecision(7)') + dbapi_con.run_async(lambda conn: conn.enable_load_extension(False)) + self._property_cache['DB:server_version'] = server_version self._tables = SearchTables(sa.MetaData(), engine.name) # pylint: disable=no-member @@ -201,7 +224,8 @@ class NominatimAPIAsync: conn.set_query_timeout(self.query_timeout) if details.keywords: await make_query_analyzer(conn) - geocoder = ReverseGeocoder(conn, details) + geocoder = ReverseGeocoder(conn, details, + self.reverse_restrict_to_country_area) return await geocoder.lookup(coord)