]> git.openstreetmap.org Git - nominatim.git/blob - nominatim/api/search/db_search_lookups.py
factor out SQL for filtering by location
[nominatim.git] / nominatim / api / search / db_search_lookups.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 Implementation of lookup functions for the search_name table.
9 """
10 from typing import List, Any
11
12 import sqlalchemy as sa
13 from sqlalchemy.ext.compiler import compiles
14
15 from nominatim.typing import SaFromClause
16 from nominatim.db.sqlalchemy_types import IntArray
17
18 # pylint: disable=consider-using-f-string
19
20 LookupType = sa.sql.expression.FunctionElement[Any]
21
22 class LookupAll(LookupType):
23     """ Find all entries in search_name table that contain all of
24         a given list of tokens using an index for the search.
25     """
26     inherit_cache = True
27
28     def __init__(self, table: SaFromClause, column: str, tokens: List[int]) -> None:
29         super().__init__(getattr(table.c, column),
30                          sa.type_coerce(tokens, IntArray))
31
32
33 @compiles(LookupAll) # type: ignore[no-untyped-call, misc]
34 def _default_lookup_all(element: LookupAll,
35                         compiler: 'sa.Compiled', **kw: Any) -> str:
36     col, tokens = list(element.clauses)
37     return "(%s @> %s)" % (compiler.process(col, **kw),
38                            compiler.process(tokens, **kw))
39
40
41
42 class LookupAny(LookupType):
43     """ Find all entries that contain at least one of the given tokens.
44         Use an index for the search.
45     """
46     inherit_cache = True
47
48     def __init__(self, table: SaFromClause, column: str, tokens: List[int]) -> None:
49         super().__init__(getattr(table.c, column),
50                          sa.type_coerce(tokens, IntArray))
51
52
53 @compiles(LookupAny) # type: ignore[no-untyped-call, misc]
54 def _default_lookup_any(element: LookupAny,
55                         compiler: 'sa.Compiled', **kw: Any) -> str:
56     col, tokens = list(element.clauses)
57     return "(%s && %s)" % (compiler.process(col, **kw),
58                            compiler.process(tokens, **kw))
59
60
61
62 class Restrict(LookupType):
63     """ Find all entries that contain all of the given tokens.
64         Do not use an index for the search.
65     """
66     inherit_cache = True
67
68     def __init__(self, table: SaFromClause, column: str, tokens: List[int]) -> None:
69         super().__init__(getattr(table.c, column),
70                          sa.type_coerce(tokens, IntArray))
71
72
73 @compiles(Restrict) # type: ignore[no-untyped-call, misc]
74 def _default_restrict(element: Restrict,
75                         compiler: 'sa.Compiled', **kw: Any) -> str:
76     arg1, arg2 = list(element.clauses)
77     return "(coalesce(null, %s) @> %s)" % (compiler.process(arg1, **kw),
78                                            compiler.process(arg2, **kw))