]> git.openstreetmap.org Git - nominatim.git/blob - nominatim/db/sqlalchemy_schema.py
add SQLAlchemy table schema for Nominatim tables
[nominatim.git] / nominatim / db / sqlalchemy_schema.py
1 # SPDX-License-Identifier: GPL-3.0-or-later
2 #
3 # This file is part of Nominatim. (https://nominatim.org)
4 #
5 # Copyright (C) 2023 by the Nominatim developer community.
6 # For a full list of authors see the git log.
7 """
8 SQLAlchemy definitions for all tables used by the frontend.
9 """
10 from typing import Any
11
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
16
17 #pylint: disable=too-many-instance-attributes
18 class SearchTables:
19     """ Data class that holds the tables of the Nominatim database.
20     """
21
22     def __init__(self, meta: sa.MetaData, engine_name: str) -> None:
23         if engine_name == 'postgresql':
24             Composite: Any = HSTORE
25             Json: Any = JSONB
26             IntArray: Any = ARRAY(sa.Integer()) #pylint: disable=invalid-name
27         elif engine_name == 'sqlite':
28             Composite = sqlite_json
29             Json = sqlite_json
30             IntArray = sqlite_json
31         else:
32             raise ValueError("Only 'postgresql' and 'sqlite' engines are supported.")
33
34         self.meta = meta
35
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))
40
41         self.properties = sa.Table('nominatim_properties', meta,
42             sa.Column('property', sa.Text, nullable=False),
43             sa.Column('value', sa.Text))
44
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)))
69
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))
77
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)))
88
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)))
103
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))
110
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))
117
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)))
122
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)))
133
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))