]> git.openstreetmap.org Git - nominatim.git/blob - nominatim/db/status.py
Merge remote-tracking branch 'upstream/master'
[nominatim.git] / nominatim / db / status.py
1 """
2 Access and helper functions for the status and status log table.
3 """
4 import datetime as dt
5 import logging
6 import re
7
8 from nominatim.tools.exec_utils import get_url
9 from nominatim.errors import UsageError
10
11 LOG = logging.getLogger()
12 ISODATE_FORMAT = '%Y-%m-%dT%H:%M:%S'
13
14 def compute_database_date(conn):
15     """ Determine the date of the database from the newest object in the
16         data base.
17     """
18     # First, find the node with the highest ID in the database
19     with conn.cursor() as cur:
20         if conn.table_exists('place'):
21             osmid = cur.scalar("SELECT max(osm_id) FROM place WHERE osm_type='N'")
22         else:
23             osmid = cur.scalar("SELECT max(osm_id) FROM placex WHERE osm_type='N'")
24
25         if osmid is None:
26             LOG.fatal("No data found in the database.")
27             raise UsageError("No data found in the database.")
28
29     LOG.info("Using node id %d for timestamp lookup", osmid)
30     # Get the node from the API to find the timestamp when it was created.
31     node_url = 'https://www.openstreetmap.org/api/0.6/node/{}/1'.format(osmid)
32     data = get_url(node_url)
33
34     match = re.search(r'timestamp="((\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}))Z"', data)
35
36     if match is None:
37         LOG.fatal("The node data downloaded from the API does not contain valid data.\n"
38                   "URL used: %s", node_url)
39         raise UsageError("Bad API data.")
40
41     LOG.debug("Found timestamp %s", match.group(1))
42
43     return dt.datetime.strptime(match.group(1), ISODATE_FORMAT).replace(tzinfo=dt.timezone.utc)
44
45
46 def set_status(conn, date, seq=None, indexed=True):
47     """ Replace the current status with the given status. If date is `None`
48         then only sequence and indexed will be updated as given. Otherwise
49         the whole status is replaced.
50     """
51     assert date is None or date.tzinfo == dt.timezone.utc
52     with conn.cursor() as cur:
53         if date is None:
54             cur.execute("UPDATE import_status set sequence_id = %s, indexed = %s",
55                         (seq, indexed))
56         else:
57             cur.execute("TRUNCATE TABLE import_status")
58             cur.execute("""INSERT INTO import_status (lastimportdate, sequence_id, indexed)
59                            VALUES (%s, %s, %s)""", (date, seq, indexed))
60
61     conn.commit()
62
63
64 def get_status(conn):
65     """ Return the current status as a triple of (date, sequence, indexed).
66         If status has not been set up yet, a triple of None is returned.
67     """
68     with conn.cursor() as cur:
69         cur.execute("SELECT * FROM import_status LIMIT 1")
70         if cur.rowcount < 1:
71             return None, None, None
72
73         row = cur.fetchone()
74         return row['lastimportdate'], row['sequence_id'], row['indexed']
75
76
77 def set_indexed(conn, state):
78     """ Set the indexed flag in the status table to the given state.
79     """
80     with conn.cursor() as cur:
81         cur.execute("UPDATE import_status SET indexed = %s", (state, ))
82     conn.commit()
83
84
85 def log_status(conn, start, event, batchsize=None):
86     """ Write a new status line to the `import_osmosis_log` table.
87     """
88     with conn.cursor() as cur:
89         cur.execute("""INSERT INTO import_osmosis_log
90                        (batchend, batchseq, batchsize, starttime, endtime, event)
91                        SELECT lastimportdate, sequence_id, %s, %s, now(), %s FROM import_status""",
92                     (batchsize, start, event))