]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Add doc section about server messages handling
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 6 Feb 2022 00:23:09 +0000 (01:23 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 6 Feb 2022 00:23:09 +0000 (01:23 +0100)
docs/advanced/async.rst
docs/api/connections.rst
psycopg/psycopg/connection.py

index a9a49d52468c54dd8c0626923b8d799723b9d4b7..a89273d6ef7f7be5847ce95e4cca66ab43051667 100644 (file)
@@ -106,6 +106,72 @@ Note that the `AsyncConnection.cursor()` function is not an `!async` function
 you can use the normal `async with` context manager.
 
 
+.. index::
+    pair: Asynchronous; Notifications
+    pair: LISTEN; SQL command
+    pair: NOTIFY; SQL command
+
+.. _async-messages:
+
+Server messages
+---------------
+
+PostgreSQL can send, together with the query results, `informative messages`__
+about the operation just performed, such as warnings or debug information.
+Notices may be raised even if the operations are successful and don't indicate
+an error. You are probably familiar with some of them, because they are
+reported by :program:`psql`::
+
+    $ psql
+    =# ROLLBACK;
+    WARNING:  there is no transaction in progress
+    ROLLBACK
+
+.. __: https://www.postgresql.org/docs/current/runtime-config-logging.html
+    #RUNTIME-CONFIG-SEVERITY-LEVELS
+
+Messages can be also sent by the `PL/pgSQL 'RAISE' statement`__ (at a level
+lower than EXCEPTION, otherwise the appropriate `DatabaseError` will be
+raised). The level of the messages received can be controlled using the
+client_min_messages__ setting.
+
+.. __: https://www.postgresql.org/docs/current/plpgsql-errors-and-messages.html
+.. __: https://www.postgresql.org/docs/current/runtime-config-client.html
+    #GUC-CLIENT-MIN-MESSAGES
+
+
+By default, the messages received are ignored. If you want to process them on
+the client you can use the `Connection.add_notice_handler()` function to
+register a function that will be invoked whenever a message is received. The
+message is passed to the callback as a `~errors.Diagnostic` instance,
+containing all the information passed by the server, such as the message text
+and the severity. The object is the same found on the `~psycopg.Error.diag`
+attribute of the errors raised by the server:
+
+.. code:: python
+
+    >>> import psycopg
+
+    >>> def log_notice(diag):
+    ...     print(f"The server says: {diag.severity} - {diag.message_primary}")
+
+    >>> conn = psycopg.connect(autocommit=True)
+    >>> conn.add_notice_handler(log_notice)
+
+    >>> cur = conn.execute("ROLLBACK")
+    The server says: WARNING - there is no transaction in progress
+    >>> print(cur.statusmessage)
+    ROLLBACK
+
+.. warning::
+
+    The `!Diagnostic` object received by the callback should not be used after
+    the callback function terminates, because its data is deallocated after
+    the callbacks have been processed. If you need to use the information
+    later please extract the attributes requested and forward them instead of
+    forwarding the whole `!Diagnostic` object.
+
+
 .. index::
     pair: Asynchronous; Notifications
     pair: LISTEN; SQL command
index 8e05dc13b7b626800cb5c93c3c5e763f4d933282..440679025cad688d841f710f39ea45f589501180 100644 (file)
@@ -254,16 +254,13 @@ The `!Connection` class
 
     .. automethod:: add_notify_handler
 
-        :param callback: a callable taking a `Notify` parameter.
+        See :ref:`async-notify` for details.
 
     .. automethod:: remove_notify_handler
 
-    See :ref:`async-notify` for details.
-
     .. automethod:: add_notice_handler
 
-        :param callback: a callable taking a `~psycopg.errors.Diagnostic`
-            object containing all the details about the notice.
+        See :ref:`async-messages` for details.
 
     .. automethod:: remove_notice_handler
 
index f4e17b9ede9b8d2490cd9894def433dc28e3d18b..0ca56d10475fb2a176218f5e02bd6d234d3415e0 100644 (file)
@@ -293,12 +293,18 @@ class BaseConnection(Generic[Row]):
     def add_notice_handler(self, callback: NoticeHandler) -> None:
         """
         Register a callable to be invoked when a notice message is received.
+
+        :param callback: the callback to call upon message received.
+        :type callback: Callable[[~psycopg.errors.Diagnostic], None]
         """
         self._notice_handlers.append(callback)
 
     def remove_notice_handler(self, callback: NoticeHandler) -> None:
         """
         Unregister a notice message callable previously registered.
+
+        :param callback: the callback to remove.
+        :type callback: Callable[[~psycopg.errors.Diagnostic], None]
         """
         self._notice_handlers.remove(callback)
 
@@ -320,12 +326,18 @@ class BaseConnection(Generic[Row]):
     def add_notify_handler(self, callback: NotifyHandler) -> None:
         """
         Register a callable to be invoked whenever a notification is received.
+
+        :param callback: the callback to call upon notification received.
+        :type callback: Callable[[~psycopg.Notify], None]
         """
         self._notify_handlers.append(callback)
 
     def remove_notify_handler(self, callback: NotifyHandler) -> None:
         """
         Unregister a notification callable previously registered.
+
+        :param callback: the callback to remove.
+        :type callback: Callable[[~psycopg.Notify], None]
         """
         self._notify_handlers.remove(callback)