X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/17bbe2637a32e93b19ff887a896bf1b444cd9792..e7b8e1a2c2d82f3f31f033df17adc5d14bbc5374:/nominatim/db/connection.py diff --git a/nominatim/db/connection.py b/nominatim/db/connection.py index 4f32dfce..12fc22d4 100644 --- a/nominatim/db/connection.py +++ b/nominatim/db/connection.py @@ -31,7 +31,7 @@ class Cursor(psycopg2.extras.DictCursor): """ Query execution that logs the SQL query when debugging is enabled. """ if LOG.isEnabledFor(logging.DEBUG): - LOG.debug(self.mogrify(query, args).decode('utf-8')) # type: ignore[no-untyped-call] + LOG.debug(self.mogrify(query, args).decode('utf-8')) super().execute(query, args) @@ -55,7 +55,7 @@ class Cursor(psycopg2.extras.DictCursor): if self.rowcount != 1: raise RuntimeError("Query did not return a single row.") - result = self.fetchone() # type: ignore[no-untyped-call] + result = self.fetchone() assert result is not None return result[0] @@ -63,7 +63,7 @@ class Cursor(psycopg2.extras.DictCursor): def drop_table(self, name: str, if_exists: bool = True, cascade: bool = False) -> None: """ Drop the table with the given name. - Set `if_exists` to False if a non-existant table should raise + Set `if_exists` to False if a non-existent table should raise an exception instead of just being ignored. If 'cascade' is set to True then all dependent tables are deleted as well. """ @@ -131,7 +131,7 @@ class Connection(psycopg2.extensions.connection): return False if table is not None: - row = cur.fetchone() # type: ignore[no-untyped-call] + row = cur.fetchone() if row is None or not isinstance(row[0], str): return False return row[0] == table @@ -141,7 +141,7 @@ class Connection(psycopg2.extensions.connection): def drop_table(self, name: str, if_exists: bool = True, cascade: bool = False) -> None: """ Drop the table with the given name. - Set `if_exists` to False if a non-existant table should raise + Set `if_exists` to False if a non-existent table should raise an exception instead of just being ignored. """ with self.cursor() as cur: @@ -174,6 +174,24 @@ class Connection(psycopg2.extensions.connection): return (int(version_parts[0]), int(version_parts[1])) + def hstore_version_tuple(self) -> Tuple[int, int]: + """ Return the hstore version installed in the database as a + tuple of (major, minor). Assumes that the hstore extension + has been installed already. + """ + with self.cursor() as cur: + version = cur.scalar( + 'SELECT extversion FROM pg_extension WHERE extname = %s', + ('hstore') + ) + + version_parts = version.split('.') + if len(version_parts) < 2: + raise UsageError(f"Error fetching hstore version. Bad format: {version}") + + return (int(version_parts[0]), int(version_parts[1])) + + class ConnectionContext(ContextManager[Connection]): """ Context manager of the connection that also provides direct access to the underlying connection. @@ -189,7 +207,7 @@ def connect(dsn: str) -> ConnectionContext: try: conn = psycopg2.connect(dsn, connection_factory=Connection) ctxmgr = cast(ConnectionContext, contextlib.closing(conn)) - ctxmgr.connection = cast(Connection, conn) + ctxmgr.connection = conn return ctxmgr except psycopg2.OperationalError as err: raise UsageError(f"Cannot connect to database: {err}") from err @@ -236,7 +254,7 @@ def get_pg_env(dsn: str, """ env = dict(base_env if base_env is not None else os.environ) - for param, value in psycopg2.extensions.parse_dsn(dsn).items(): # type: ignore + for param, value in psycopg2.extensions.parse_dsn(dsn).items(): if param in _PG_CONNECTION_STRINGS: env[_PG_CONNECTION_STRINGS[param]] = value else: