You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
5.4 KiB
175 lines
5.4 KiB
"""
|
|
Objects to return information about a PostgreSQL connection.
|
|
"""
|
|
|
|
# Copyright (C) 2020 The Psycopg Team
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from datetime import tzinfo
|
|
|
|
from . import pq
|
|
from ._tz import get_tzinfo
|
|
from ._encodings import pgconn_encoding
|
|
from .conninfo import make_conninfo
|
|
|
|
|
|
class ConnectionInfo:
|
|
"""Allow access to information about the connection."""
|
|
|
|
__module__ = "psycopg"
|
|
|
|
def __init__(self, pgconn: pq.abc.PGconn):
|
|
self.pgconn = pgconn
|
|
|
|
@property
|
|
def vendor(self) -> str:
|
|
"""A string representing the database vendor connected to."""
|
|
return "PostgreSQL"
|
|
|
|
@property
|
|
def host(self) -> str:
|
|
"""The server host name of the active connection. See :pq:`PQhost()`."""
|
|
return self._get_pgconn_attr("host")
|
|
|
|
@property
|
|
def hostaddr(self) -> str:
|
|
"""The server IP address of the connection. See :pq:`PQhostaddr()`."""
|
|
return self._get_pgconn_attr("hostaddr")
|
|
|
|
@property
|
|
def port(self) -> int:
|
|
"""The port of the active connection. See :pq:`PQport()`."""
|
|
return int(self._get_pgconn_attr("port"))
|
|
|
|
@property
|
|
def dbname(self) -> str:
|
|
"""The database name of the connection. See :pq:`PQdb()`."""
|
|
return self._get_pgconn_attr("db")
|
|
|
|
@property
|
|
def user(self) -> str:
|
|
"""The user name of the connection. See :pq:`PQuser()`."""
|
|
return self._get_pgconn_attr("user")
|
|
|
|
@property
|
|
def password(self) -> str:
|
|
"""The password of the connection. See :pq:`PQpass()`."""
|
|
return self._get_pgconn_attr("password")
|
|
|
|
@property
|
|
def options(self) -> str:
|
|
"""
|
|
The command-line options passed in the connection request.
|
|
See :pq:`PQoptions`.
|
|
"""
|
|
return self._get_pgconn_attr("options")
|
|
|
|
def get_parameters(self) -> dict[str, str]:
|
|
"""Return the connection parameters values.
|
|
|
|
Return all the parameters set to a non-default value, which might come
|
|
either from the connection string and parameters passed to
|
|
`~Connection.connect()` or from environment variables. The password
|
|
is never returned (you can read it using the `password` attribute).
|
|
"""
|
|
pyenc = self.encoding
|
|
|
|
# Get the known defaults to avoid reporting them
|
|
defaults = {
|
|
i.keyword: i.compiled
|
|
for i in pq.Conninfo.get_defaults()
|
|
if i.compiled is not None
|
|
}
|
|
# Not returned by the libq. Bug? Bet we're using SSH.
|
|
defaults.setdefault(b"channel_binding", b"prefer")
|
|
defaults[b"passfile"] = str(Path.home() / ".pgpass").encode()
|
|
|
|
return {
|
|
i.keyword.decode(pyenc): i.val.decode(pyenc)
|
|
for i in self.pgconn.info
|
|
if i.val is not None
|
|
and i.keyword != b"password"
|
|
and i.val != defaults.get(i.keyword)
|
|
}
|
|
|
|
@property
|
|
def dsn(self) -> str:
|
|
"""Return the connection string to connect to the database.
|
|
|
|
The string contains all the parameters set to a non-default value,
|
|
which might come either from the connection string and parameters
|
|
passed to `~Connection.connect()` or from environment variables. The
|
|
password is never returned (you can read it using the `password`
|
|
attribute).
|
|
"""
|
|
return make_conninfo(**self.get_parameters())
|
|
|
|
@property
|
|
def status(self) -> pq.ConnStatus:
|
|
"""The status of the connection. See :pq:`PQstatus()`."""
|
|
return pq.ConnStatus(self.pgconn.status)
|
|
|
|
@property
|
|
def transaction_status(self) -> pq.TransactionStatus:
|
|
"""
|
|
The current in-transaction status of the session.
|
|
See :pq:`PQtransactionStatus()`.
|
|
"""
|
|
return pq.TransactionStatus(self.pgconn.transaction_status)
|
|
|
|
@property
|
|
def pipeline_status(self) -> pq.PipelineStatus:
|
|
"""
|
|
The current pipeline status of the client.
|
|
See :pq:`PQpipelineStatus()`.
|
|
"""
|
|
return pq.PipelineStatus(self.pgconn.pipeline_status)
|
|
|
|
def parameter_status(self, param_name: str) -> str | None:
|
|
"""
|
|
Return a parameter setting of the connection.
|
|
|
|
Return `None` is the parameter is unknown.
|
|
"""
|
|
res = self.pgconn.parameter_status(param_name.encode(self.encoding))
|
|
return res.decode(self.encoding) if res is not None else None
|
|
|
|
@property
|
|
def server_version(self) -> int:
|
|
"""
|
|
An integer representing the server version. See :pq:`PQserverVersion()`.
|
|
"""
|
|
return self.pgconn.server_version
|
|
|
|
@property
|
|
def backend_pid(self) -> int:
|
|
"""
|
|
The process ID (PID) of the backend process handling this connection.
|
|
See :pq:`PQbackendPID()`.
|
|
"""
|
|
return self.pgconn.backend_pid
|
|
|
|
@property
|
|
def error_message(self) -> str:
|
|
"""
|
|
The error message most recently generated by an operation on the connection.
|
|
See :pq:`PQerrorMessage()`.
|
|
"""
|
|
return self._get_pgconn_attr("error_message")
|
|
|
|
@property
|
|
def timezone(self) -> tzinfo:
|
|
"""The Python timezone info of the connection's timezone."""
|
|
return get_tzinfo(self.pgconn)
|
|
|
|
@property
|
|
def encoding(self) -> str:
|
|
"""The Python codec name of the connection's client encoding."""
|
|
return pgconn_encoding(self.pgconn)
|
|
|
|
def _get_pgconn_attr(self, name: str) -> str:
|
|
value: bytes = getattr(self.pgconn, name)
|
|
return value.decode(self.encoding)
|