1 # SPDX-License-Identifier: GPL-3.0-or-later
3 # This file is part of Nominatim. (https://nominatim.org)
5 # Copyright (C) 2024 by the Nominatim developer community.
6 # For a full list of authors see the git log.
10 from pathlib import Path
12 from nominatim_db.tools.exec_utils import run_osm2pgsql
13 from nominatim_db.tools.replication import run_osm2pgsql_updates
15 from geometry_alias import ALIASES
18 def get_osm2pgsql_options(nominatim_env, fname, append):
19 return dict(import_file=fname,
20 osm2pgsql='osm2pgsql',
22 osm2pgsql_style=str(nominatim_env.get_test_config().get_import_style_file()),
23 osm2pgsql_style_path=nominatim_env.get_test_config().lib_dir.lua,
25 dsn=nominatim_env.get_libpq_dsn(),
27 tablespaces=dict(slim_data='', slim_index='',
28 main_data='', main_index=''),
32 def write_opl_file(opl, grid):
33 """ Create a temporary OSM file from OPL and return the file name. It is
34 the responsibility of the caller to delete the file again.
36 Node with missing coordinates, can retrieve their coordinates from
37 a supplied grid. Failing that a random coordinate is assigned.
39 with tempfile.NamedTemporaryFile(suffix='.opl', delete=False) as fd:
40 for line in opl.splitlines():
41 if line.startswith('n') and line.find(' x') < 0:
42 coord = grid.grid_node(int(line[1:].split(' ')[0]))
44 coord = (random.uniform(-180, 180), random.uniform(-90, 90))
45 line += " x%f y%f" % coord
46 fd.write(line.encode('utf-8'))
52 @given('the lua style file')
53 def lua_style_file(context):
54 """ Define a custom style file to use for the import.
56 style = Path(context.nominatim.website_dir.name) / 'custom.lua'
57 style.write_text(context.text)
58 context.nominatim.test_env['NOMINATIM_IMPORT_STYLE'] = str(style)
61 @given(u'the ([0-9.]+ )?grid(?: with origin (?P<origin>.*))?')
62 def define_node_grid(context, grid_step, origin):
64 Define a grid of node positions.
65 Use a table to define the grid. The nodes must be integer ids. Optionally
66 you can give the grid distance. The default is 0.00001 degrees.
68 if grid_step is not None:
69 grid_step = float(grid_step.strip())
76 coords = origin.split(',')
78 raise RuntimeError('Grid origin expects origin with x,y coordinates.')
79 origin = (float(coords[0]), float(coords[1]))
80 elif origin in ALIASES:
81 origin = ALIASES[origin]
83 raise RuntimeError('Grid origin must be either coordinate or alias.')
87 context.osm.set_grid([context.table.headings] + [list(h) for h in context.table],
91 @when(u'loading osm data')
92 def load_osm_file(context):
94 Load the given data into a freshly created test database using osm2pgsql.
95 No further indexing is done.
97 The data is expected as attached text in OPL format.
99 # create an OSM file and import it
100 fname = write_opl_file(context.text, context.osm)
102 run_osm2pgsql(get_osm2pgsql_options(context.nominatim, fname, append=False))
106 # reintroduce the triggers/indexes we've lost by having osm2pgsql set up place again
107 cur = context.db.cursor()
108 cur.execute("""CREATE TRIGGER place_before_delete BEFORE DELETE ON place
109 FOR EACH ROW EXECUTE PROCEDURE place_delete()""")
110 cur.execute("""CREATE TRIGGER place_before_insert BEFORE INSERT ON place
111 FOR EACH ROW EXECUTE PROCEDURE place_insert()""")
112 cur.execute("""CREATE UNIQUE INDEX idx_place_osm_unique ON place
113 USING btree(osm_id,osm_type,class,type)""")
117 @when(u'updating osm data')
118 def update_from_osm_file(context):
120 Update a database previously populated with 'loading osm data'.
121 Needs to run indexing on the existing data first to yield the correct result.
123 The data is expected as attached text in OPL format.
125 context.nominatim.copy_from_place(context.db)
126 context.nominatim.run_nominatim('index')
127 context.nominatim.run_nominatim('refresh', '--functions')
129 # create an OSM file and import it
130 fname = write_opl_file(context.text, context.osm)
132 run_osm2pgsql_updates(context.db,
133 get_osm2pgsql_options(context.nominatim, fname, append=True))
139 def index_database(context):
141 Run the Nominatim indexing step. This will process data previously
142 loaded with 'updating osm data'
144 context.nominatim.run_nominatim('index')