X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/72625dc72a628d843d7a3ebc0c813689408b4cf8..78c19bc006d5957f183968d086226be4b2b65fe3:/nominatim/db/status.py?ds=sidebyside diff --git a/nominatim/db/status.py b/nominatim/db/status.py index 71e58787..5f92d959 100644 --- a/nominatim/db/status.py +++ b/nominatim/db/status.py @@ -1,21 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# This file is part of Nominatim. (https://nominatim.org) +# +# Copyright (C) 2022 by the Nominatim developer community. +# For a full list of authors see the git log. """ Access and helper functions for the status and status log table. """ +from typing import Optional, Tuple, cast import datetime as dt import logging import re +from nominatim.db.connection import Connection from nominatim.tools.exec_utils import get_url from nominatim.errors import UsageError +from nominatim.typing import TypedDict LOG = logging.getLogger() ISODATE_FORMAT = '%Y-%m-%dT%H:%M:%S' -def compute_database_date(conn): + +class StatusRow(TypedDict): + """ Dictionary of columns of the import_status table. + """ + lastimportdate: dt.datetime + sequence_id: Optional[int] + indexed: Optional[bool] + + +def compute_database_date(conn: Connection, offline: bool = False) -> dt.datetime: """ Determine the date of the database from the newest object in the data base. """ - # First, find the node with the highest ID in the database + # If there is a date from osm2pgsql available, use that. + if conn.table_exists('osm2pgsql_properties'): + with conn.cursor() as cur: + cur.execute(""" SELECT value FROM osm2pgsql_properties + WHERE property = 'current_timestamp' """) + row = cur.fetchone() + if row is not None: + return dt.datetime.strptime(row[0], "%Y-%m-%dT%H:%M:%SZ")\ + .replace(tzinfo=dt.timezone.utc) + + if offline: + raise UsageError("Cannot determine database date from data in offline mode.") + + # Else, find the node with the highest ID in the database with conn.cursor() as cur: if conn.table_exists('place'): osmid = cur.scalar("SELECT max(osm_id) FROM place WHERE osm_type='N'") @@ -28,7 +59,7 @@ def compute_database_date(conn): LOG.info("Using node id %d for timestamp lookup", osmid) # Get the node from the API to find the timestamp when it was created. - node_url = 'https://www.openstreetmap.org/api/0.6/node/{}/1'.format(osmid) + node_url = f'https://www.openstreetmap.org/api/0.6/node/{osmid}/1' data = get_url(node_url) match = re.search(r'timestamp="((\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}))Z"', data) @@ -43,10 +74,12 @@ def compute_database_date(conn): return dt.datetime.strptime(match.group(1), ISODATE_FORMAT).replace(tzinfo=dt.timezone.utc) -def set_status(conn, date, seq=None, indexed=True): +def set_status(conn: Connection, date: Optional[dt.datetime], + seq: Optional[int] = None, indexed: bool = True) -> None: """ Replace the current status with the given status. If date is `None` then only sequence and indexed will be updated as given. Otherwise the whole status is replaced. + The change will be committed to the database. """ assert date is None or date.tzinfo == dt.timezone.utc with conn.cursor() as cur: @@ -61,7 +94,7 @@ def set_status(conn, date, seq=None, indexed=True): conn.commit() -def get_status(conn): +def get_status(conn: Connection) -> Tuple[Optional[dt.datetime], Optional[int], Optional[bool]]: """ Return the current status as a triple of (date, sequence, indexed). If status has not been set up yet, a triple of None is returned. """ @@ -70,11 +103,11 @@ def get_status(conn): if cur.rowcount < 1: return None, None, None - row = cur.fetchone() + row = cast(StatusRow, cur.fetchone()) return row['lastimportdate'], row['sequence_id'], row['indexed'] -def set_indexed(conn, state): +def set_indexed(conn: Connection, state: bool) -> None: """ Set the indexed flag in the status table to the given state. """ with conn.cursor() as cur: @@ -82,7 +115,8 @@ def set_indexed(conn, state): conn.commit() -def log_status(conn, start, event, batchsize=None): +def log_status(conn: Connection, start: dt.datetime, + event: str, batchsize: Optional[int] = None) -> None: """ Write a new status line to the `import_osmosis_log` table. """ with conn.cursor() as cur: @@ -90,3 +124,4 @@ def log_status(conn, start, event, batchsize=None): (batchend, batchseq, batchsize, starttime, endtime, event) SELECT lastimportdate, sequence_id, %s, %s, now(), %s FROM import_status""", (batchsize, start, event)) + conn.commit()