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 sqlalchemy.dialects.postgresql import HSTORE, ARRAY, JSONB
 
  14 from sqlalchemy.dialects.sqlite import JSON as sqlite_json
 
  16 from nominatim.db.sqlalchemy_types import Geometry
 
  19     """ Type definitions for complex types as used in Postgres variants.
 
  23     IntArray = ARRAY(sa.Integer()) #pylint: disable=invalid-name
 
  27     """ Type definitions for complex types as used in Postgres variants.
 
  29     Composite = sqlite_json
 
  31     IntArray = sqlite_json
 
  34 #pylint: disable=too-many-instance-attributes
 
  36     """ Data class that holds the tables of the Nominatim database.
 
  39     def __init__(self, meta: sa.MetaData, engine_name: str) -> None:
 
  40         if engine_name == 'postgresql':
 
  41             self.types: Any = PostgresTypes
 
  42         elif engine_name == 'sqlite':
 
  43             self.types = SqliteTypes
 
  45             raise ValueError("Only 'postgresql' and 'sqlite' engines are supported.")
 
  49         self.import_status = sa.Table('import_status', meta,
 
  50             sa.Column('lastimportdate', sa.DateTime(True), nullable=False),
 
  51             sa.Column('sequence_id', sa.Integer),
 
  52             sa.Column('indexed', sa.Boolean))
 
  54         self.properties = sa.Table('nominatim_properties', meta,
 
  55             sa.Column('property', sa.Text, nullable=False),
 
  56             sa.Column('value', sa.Text))
 
  58         self.placex = sa.Table('placex', meta,
 
  59             sa.Column('place_id', sa.BigInteger, nullable=False, unique=True),
 
  60             sa.Column('parent_place_id', sa.BigInteger),
 
  61             sa.Column('linked_place_id', sa.BigInteger),
 
  62             sa.Column('importance', sa.Float),
 
  63             sa.Column('indexed_date', sa.DateTime),
 
  64             sa.Column('rank_address', sa.SmallInteger),
 
  65             sa.Column('rank_search', sa.SmallInteger),
 
  66             sa.Column('partition', sa.SmallInteger),
 
  67             sa.Column('indexed_status', sa.SmallInteger),
 
  68             sa.Column('osm_type', sa.String(1), nullable=False),
 
  69             sa.Column('osm_id', sa.BigInteger, nullable=False),
 
  70             sa.Column('class', sa.Text, nullable=False, key='class_'),
 
  71             sa.Column('type', sa.Text, nullable=False),
 
  72             sa.Column('admin_level', sa.SmallInteger),
 
  73             sa.Column('name', self.types.Composite),
 
  74             sa.Column('address', self.types.Composite),
 
  75             sa.Column('extratags', self.types.Composite),
 
  76             sa.Column('geometry', Geometry, nullable=False),
 
  77             sa.Column('wikipedia', sa.Text),
 
  78             sa.Column('country_code', sa.String(2)),
 
  79             sa.Column('housenumber', sa.Text),
 
  80             sa.Column('postcode', sa.Text),
 
  81             sa.Column('centroid', Geometry))
 
  83         self.addressline = sa.Table('place_addressline', meta,
 
  84             sa.Column('place_id', sa.BigInteger, index=True),
 
  85             sa.Column('address_place_id', sa.BigInteger, index=True),
 
  86             sa.Column('distance', sa.Float),
 
  87             sa.Column('cached_rank_address', sa.SmallInteger),
 
  88             sa.Column('fromarea', sa.Boolean),
 
  89             sa.Column('isaddress', sa.Boolean))
 
  91         self.postcode = sa.Table('location_postcode', meta,
 
  92             sa.Column('place_id', sa.BigInteger, unique=True),
 
  93             sa.Column('parent_place_id', sa.BigInteger),
 
  94             sa.Column('rank_search', sa.SmallInteger),
 
  95             sa.Column('rank_address', sa.SmallInteger),
 
  96             sa.Column('indexed_status', sa.SmallInteger),
 
  97             sa.Column('indexed_date', sa.DateTime),
 
  98             sa.Column('country_code', sa.String(2)),
 
  99             sa.Column('postcode', sa.Text, index=True),
 
 100             sa.Column('geometry', Geometry))
 
 102         self.osmline = sa.Table('location_property_osmline', meta,
 
 103             sa.Column('place_id', sa.BigInteger, nullable=False, unique=True),
 
 104             sa.Column('osm_id', sa.BigInteger),
 
 105             sa.Column('parent_place_id', sa.BigInteger),
 
 106             sa.Column('indexed_date', sa.DateTime),
 
 107             sa.Column('startnumber', sa.Integer),
 
 108             sa.Column('endnumber', sa.Integer),
 
 109             sa.Column('step', sa.SmallInteger),
 
 110             sa.Column('partition', sa.SmallInteger),
 
 111             sa.Column('indexed_status', sa.SmallInteger),
 
 112             sa.Column('linegeo', Geometry),
 
 113             sa.Column('address', self.types.Composite),
 
 114             sa.Column('postcode', sa.Text),
 
 115             sa.Column('country_code', sa.String(2)))
 
 117         self.country_name = sa.Table('country_name', meta,
 
 118             sa.Column('country_code', sa.String(2)),
 
 119             sa.Column('name', self.types.Composite),
 
 120             sa.Column('derived_name', self.types.Composite),
 
 121             sa.Column('country_default_language_code', sa.Text),
 
 122             sa.Column('partition', sa.Integer))
 
 124         self.country_grid = sa.Table('country_osm_grid', meta,
 
 125             sa.Column('country_code', sa.String(2)),
 
 126             sa.Column('area', sa.Float),
 
 127             sa.Column('geometry', Geometry))
 
 129         # The following tables are not necessarily present.
 
 130         self.search_name = sa.Table('search_name', meta,
 
 131             sa.Column('place_id', sa.BigInteger, index=True),
 
 132             sa.Column('importance', sa.Float),
 
 133             sa.Column('search_rank', sa.SmallInteger),
 
 134             sa.Column('address_rank', sa.SmallInteger),
 
 135             sa.Column('name_vector', self.types.IntArray, index=True),
 
 136             sa.Column('nameaddress_vector', self.types.IntArray, index=True),
 
 137             sa.Column('country_code', sa.String(2)),
 
 138             sa.Column('centroid', Geometry))
 
 140         self.tiger = sa.Table('location_property_tiger', meta,
 
 141             sa.Column('place_id', sa.BigInteger),
 
 142             sa.Column('parent_place_id', sa.BigInteger),
 
 143             sa.Column('startnumber', sa.Integer),
 
 144             sa.Column('endnumber', sa.Integer),
 
 145             sa.Column('step', sa.SmallInteger),
 
 146             sa.Column('partition', sa.SmallInteger),
 
 147             sa.Column('linegeo', Geometry),
 
 148             sa.Column('postcode', sa.Text))