1 # SPDX-License-Identifier: GPL-3.0-or-later
3 # This file is part of Nominatim. (https://nominatim.org)
5 # Copyright (C) 2023 by the Nominatim developer community.
6 # For a full list of authors see the git log.
8 SQLAlchemy definitions for all tables used by the frontend.
10 from typing import Any
12 import sqlalchemy as sa
13 from geoalchemy2 import Geometry
14 from sqlalchemy.dialects.postgresql import HSTORE, ARRAY, JSONB
15 from sqlalchemy.dialects.sqlite import JSON as sqlite_json
17 #pylint: disable=too-many-instance-attributes
19 """ Data class that holds the tables of the Nominatim database.
22 def __init__(self, meta: sa.MetaData, engine_name: str) -> None:
23 if engine_name == 'postgresql':
24 Composite: Any = HSTORE
26 IntArray: Any = ARRAY(sa.Integer()) #pylint: disable=invalid-name
27 elif engine_name == 'sqlite':
28 Composite = sqlite_json
30 IntArray = sqlite_json
32 raise ValueError("Only 'postgresql' and 'sqlite' engines are supported.")
36 self.import_status = sa.Table('import_status', meta,
37 sa.Column('lastimportdate', sa.DateTime(True), nullable=False),
38 sa.Column('sequence_id', sa.Integer),
39 sa.Column('indexed', sa.Boolean))
41 self.properties = sa.Table('nominatim_properties', meta,
42 sa.Column('property', sa.Text, nullable=False),
43 sa.Column('value', sa.Text))
45 self.placex = sa.Table('placex', meta,
46 sa.Column('place_id', sa.BigInteger, nullable=False, unique=True),
47 sa.Column('parent_place_id', sa.BigInteger),
48 sa.Column('linked_place_id', sa.BigInteger),
49 sa.Column('importance', sa.Float),
50 sa.Column('indexed_date', sa.DateTime),
51 sa.Column('rank_address', sa.SmallInteger),
52 sa.Column('rank_search', sa.SmallInteger),
53 sa.Column('partition', sa.SmallInteger),
54 sa.Column('indexed_status', sa.SmallInteger),
55 sa.Column('osm_type', sa.String(1), nullable=False),
56 sa.Column('osm_id', sa.BigInteger, nullable=False),
57 sa.Column('class', sa.Text, nullable=False, key='class_'),
58 sa.Column('type', sa.Text, nullable=False),
59 sa.Column('admin_level', sa.SmallInteger),
60 sa.Column('name', Composite),
61 sa.Column('address', Composite),
62 sa.Column('extratags', Composite),
63 sa.Column('geometry', Geometry(srid=4326), nullable=False),
64 sa.Column('wikipedia', sa.Text),
65 sa.Column('country_code', sa.String(2)),
66 sa.Column('housenumber', sa.Text),
67 sa.Column('postcode', sa.Text),
68 sa.Column('centroid', Geometry(srid=4326, spatial_index=False)))
70 self.addressline = sa.Table('place_addressline', meta,
71 sa.Column('place_id', sa.BigInteger, index=True),
72 sa.Column('address_place_id', sa.BigInteger, index=True),
73 sa.Column('distance', sa.Float),
74 sa.Column('cached_rank_address', sa.SmallInteger),
75 sa.Column('fromarea', sa.Boolean),
76 sa.Column('isaddress', sa.Boolean))
78 self.postcode = sa.Table('location_postcode', meta,
79 sa.Column('place_id', sa.BigInteger, unique=True),
80 sa.Column('parent_place_id', sa.BigInteger),
81 sa.Column('rank_search', sa.SmallInteger),
82 sa.Column('rank_address', sa.SmallInteger),
83 sa.Column('indexed_status', sa.SmallInteger),
84 sa.Column('indexed_date', sa.DateTime),
85 sa.Column('country_code', sa.String(2)),
86 sa.Column('postcode', sa.Text, index=True),
87 sa.Column('geometry', Geometry(srid=4326)))
89 self.osmline = sa.Table('location_property_osmline', meta,
90 sa.Column('place_id', sa.BigInteger, nullable=False, unique=True),
91 sa.Column('osm_id', sa.BigInteger),
92 sa.Column('parent_place_id', sa.BigInteger),
93 sa.Column('indexed_date', sa.DateTime),
94 sa.Column('startnumber', sa.Integer),
95 sa.Column('endnumber', sa.Integer),
96 sa.Column('step', sa.SmallInteger),
97 sa.Column('partition', sa.SmallInteger),
98 sa.Column('indexed_status', sa.SmallInteger),
99 sa.Column('linegeo', Geometry(srid=4326)),
100 sa.Column('address', Composite),
101 sa.Column('postcode', sa.Text),
102 sa.Column('country_code', sa.String(2)))
104 self.word = sa.Table('word', meta,
105 sa.Column('word_id', sa.Integer),
106 sa.Column('word_token', sa.Text, nullable=False),
107 sa.Column('type', sa.Text, nullable=False),
108 sa.Column('word', sa.Text),
109 sa.Column('info', Json))
111 self.country_name = sa.Table('country_name', meta,
112 sa.Column('country_code', sa.String(2)),
113 sa.Column('name', Composite),
114 sa.Column('derived_name', Composite),
115 sa.Column('country_default_language_code', sa.Text),
116 sa.Column('partition', sa.Integer))
118 self.country_grid = sa.Table('country_osm_grid', meta,
119 sa.Column('country_code', sa.String(2)),
120 sa.Column('area', sa.Float),
121 sa.Column('geometry', Geometry(srid=4326)))
123 # The following tables are not necessarily present.
124 self.search_name = sa.Table('search_name', meta,
125 sa.Column('place_id', sa.BigInteger, index=True),
126 sa.Column('importance', sa.Float),
127 sa.Column('search_rank', sa.SmallInteger),
128 sa.Column('address_rank', sa.SmallInteger),
129 sa.Column('name_vector', IntArray, index=True),
130 sa.Column('nameaddress_vector', IntArray, index=True),
131 sa.Column('country_code', sa.String(2)),
132 sa.Column('centroid', Geometry(srid=4326)))
134 self.tiger = sa.Table('location_property_tiger', meta,
135 sa.Column('place_id', sa.BigInteger),
136 sa.Column('parent_place_id', sa.BigInteger),
137 sa.Column('startnumber', sa.Integer),
138 sa.Column('endnumber', sa.Integer),
139 sa.Column('step', sa.SmallInteger),
140 sa.Column('partition', sa.SmallInteger),
141 sa.Column('linegeo', Geometry(srid=4326, spatial_index=False)),
142 sa.Column('postcode', sa.Text))