The pipeline mode is available on any currently supported PostgreSQL version,
but, in order to make use of it, the client must use a libpq from PostgreSQL
-14 or higher. You can use `Pipeline.is_supported()` to make sure your client
-has the right library.
+14 or higher. You can use the `~Capabilities.has_pipeline` capability to make
+sure your client has the right library.
Starting from 3.2, Psycopg supports prepared statements when using the
PgBouncer__ middleware, using the following caveats:
-- PgBouncer version must be at least version `1.22`__.
+- PgBouncer version must be version `1.22`__ or newer.
- PgBouncer `max_prepared_statements`__ must be greater than 0.
-- The libpq version on the client must be from PostgreSQL 17 or higher.
+- The libpq version on the client must be from PostgreSQL 17 or newer
+ (you can check the `~Capabilities.has_pgbouncer_prepared` capability to
+ verify it).
.. __: https://www.pgbouncer.org/
.. __: https://www.pgbouncer.org/2024/01/pgbouncer-1-22-0
.. automethod:: cancel_safe
+ .. note::
+
+ You can use the `~Capabilities.has_cancel_safe` capability to check
+ if `!cancel_safe()` will not fall back on the legacy implementation.
+
.. warning::
This method shouldn't be used as a `~signal.signal` handler.
If you need an asynchronous connection use `AsyncConnection.connect`
instead.
+.. data:: capabilities
+
+ An object that can be used to verify that the client library used by
+ psycopg implements a certain feature. For instance::
+
+ # Fail at import time if encrypted passwords is not available
+ import psycopg
+ psycopg.capabilities.has_encrypt_password(check=True)
+
+ # Verify at runtime if a feature can be used
+ if psycopg.capabilities.has_hostaddr():
+ print(conn.info.hostaddr)
+ else:
+ print("unknown connection hostadd")
+
+ :type: `Capabilities`
+
+ .. versionadded:: 3.2
+
.. rubric:: Exceptions
.. autoattribute:: hostaddr
- Only available if the libpq used is at least from PostgreSQL 12.
- Raise `~psycopg.NotSupportedError` otherwise.
+ Only available if the libpq used is from PostgreSQL 12 or newer.
+ Raise `~psycopg.NotSupportedError` otherwise. You can use the
+ `~Capabilities.has_hostaddr` capability to check for support.
.. autoattribute:: port
.. autoattribute:: dbname
.. __: https://www.postgresql.org/docs/current/multibyte.html
+.. _capabilities:
+
+Libpq capabilities information
+------------------------------
+
+.. autoclass:: Capabilities
+
+ An instance of this object is normally exposed by the module as the object
+ `psycopg.capabilities`.
+
+ Every feature check is implemented by an `!has_SOMETHING()` method. All
+ the methods return a boolean value stating if the capability is supported,
+ which can be used by a program to degrade gracefully::
+
+ if psycopg.capabilities.has_pipeline()
+ with conn.pipeline():
+ operations(conn)
+ else:
+ logger.warning("slower")
+ operations(conn)
+
+ If `check` is `!True`, and the capability is not supported, raise a
+ `NotSupportedError` instead of returning `!False`, explaining why the
+ feature is not supported. This allows to make a check at import time,
+ crashing early and with a clear description of the problem.
+
+ >>> import psycopg
+ >>> psycopg.capabilities.has_pipeline(check=True)
+ Traceback (most recent call last):
+ ...
+ psycopg.NotSupportedError: the feature 'Connection.pipeline()' is not available:
+ the client libpq version (imported from system libraries) is 13.4; the
+ feature requires libpq version 14.0 or newer
+
+ .. versionadded:: 3.2
+
+ .. automethod:: has_encrypt_password
+ .. automethod:: has_hostaddr
+ .. automethod:: has_pipeline
+ .. automethod:: has_set_trace_flags
+ .. automethod:: has_cancel_safe
+
+ .. note::
+
+ The `!cancel_safe()` method is implemented anyway, but it will use
+ the legacy :pq:`PQcancel` implementation.
+
+ .. automethod:: has_pgbouncer_prepared
+
+ .. seealso:: :ref:`pgbouncer`
+
+
The description `Column` object
-------------------------------
(:ticket:`340`).
- Add :ref:`raw-query-cursors` to execute queries using placeholders in
PostgreSQL format (`$1`, `$2`...) (:ticket:`#560`).
+- Add `psycopg.capabilities` object to :ref:`inspect the libpq capabilities
+ <capabilities>` (:ticket:`#772`).
- Add `~rows.scalar_row` to return scalar values from a query (:ticket:`#723`).
- Prepared statements are now :ref:`compatible with PgBouncer <pgbouncer>`.
(:ticket:`#589`).
class Capabilities:
"""
- Check if a feature is supported.
-
- Every feature check is implemented by a check method `has_SOMETHING`.
- All the methods return a boolean stating if the capability is supported.
- If not supported and `check` is True, raise a `NotSupportedError` instead
- explaining why the feature is not supported.
+ An object to check if a feature is supported by the libpq available on the client.
"""
def has_encrypt_password(self, check: bool = False) -> bool:
- """Check if the `~PGconn.encrypt_password()` method is implemented."""
- return self._has_feature("PGconn.encrypt_password()", 100000, check=check)
+ """Check if the `PGconn.encrypt_password()` method is implemented.
+
+ The feature requires libpq 10.0 and greater.
+ """
+ return self._has_feature("pq.PGconn.encrypt_password()", 100000, check=check)
def has_hostaddr(self, check: bool = False) -> bool:
- """Check if the `~ConnectionInfo.hostaddr` attribute is implemented."""
- return self._has_feature("Connection.pipeline()", 120000, check=check)
+ """Check if the `ConnectionInfo.hostaddr` attribute is implemented.
+
+ The feature requires libpq 12.0 and greater.
+ """
+ return self._has_feature("Connection.info.hostaddr", 120000, check=check)
def has_pipeline(self, check: bool = False) -> bool:
- """Check if the `~Connection.pipeline()` method is implemented."""
+ """Check if the :ref:`pipeline mode <pipeline-mode>` is supported.
+
+ The feature requires libpq 14.0 and greater.
+ """
return self._has_feature("Connection.pipeline()", 140000, check=check)
- def has_set_trace_flag(self, check: bool = False) -> bool:
- """Check if the `~PGconn.set_trace_flag()` method is implemented."""
- return self._has_feature("PGconn.set_trace_flag()", 140000, check=check)
+ def has_set_trace_flags(self, check: bool = False) -> bool:
+ """Check if the `pq.PGconn.set_trace_flags()` method is implemented.
+
+ The feature requires libpq 14.0 and greater.
+ """
+ return self._has_feature("PGconn.set_trace_flags()", 140000, check=check)
def has_cancel_safe(self, check: bool = False) -> bool:
- """Check if the `Connection.cancel_safe()` method is implemented."""
+ """Check if the `Connection.cancel_safe()` method is implemented.
+
+ The feature requires libpq 17.0 and greater.
+ """
return self._has_feature("Connection.cancel_safe()", 170000, check=check)
def has_pgbouncer_prepared(self, check: bool = False) -> bool:
- """Check if prepared statements in PgBouncer are supported."""
+ """Check if prepared statements in PgBouncer are supported.
+
+ The feature requires libpq 17.0 and greater.
+ """
return self._has_feature(
"PgBouncer prepared statements compatibility", 170000, check=check
)
from psycopg import capabilities, NotSupportedError
caps = [
- ("has_encrypt_password", "encrypt_password", 10),
- ("has_hostaddr", "PGconn.hostaddr", 12),
+ ("has_encrypt_password", "pq.PGconn.encrypt_password()", 10),
+ ("has_hostaddr", "Connection.info.hostaddr", 12),
("has_pipeline", "Connection.pipeline()", 14),
- ("has_set_trace_flag", "PGconn.set_trace_flag()", 14),
+ ("has_set_trace_flags", "PGconn.set_trace_flags()", 14),
("has_cancel_safe", "Connection.cancel_safe()", 17),
("has_pgbouncer_prepared", "PgBouncer prepared statements compatibility", 17),
]