@@ -275,8 +275,8 @@ interfaces:
275275 Revocation list file path. [Currently not checked.]
276276
277277 ``category``
278- A `postgresql.api.Category` instance used to execute further database
279- initialization such as library bindings .
278+ A `postgresql.api.Category` instance used to further initialize
279+ the database .
280280
281281
282282Connections
@@ -347,6 +347,12 @@ The methods and properties on the connection object are ready for use:
347347 Create a new connection object based on the same factors that were used to
348348 create ``db``. The new connection returned will already be connected.
349349
350+ ``db.msghook(msg)``
351+ By default, the `msghook` attribute does not exist. If set to a callable, any
352+ message that occurs during an operation of the database or an operation of a
353+ database derived object will be given to the callable. See the
354+ `Message Management`_ section for more information.
355+
350356
351357Connection Metadata
352358-------------------
@@ -513,6 +519,12 @@ Prepared statement objects have a few execution methods:
513519 Create a new statement object based on the same factors that were used to
514520 create ``ps``.
515521
522+ ``ps.msghook(msg)``
523+ By default, the `msghook` attribute does not exist. If set to a callable, any
524+ message that occurs during an operation of the statement or an operation of a
525+ statement derived object will be given to the callable. See the
526+ `Message Management`_ section for more information.
527+
516528
517529Statement Metadata
518530------------------
@@ -831,6 +843,12 @@ those results:
831843 Create a new cursor object based on the same factors that were used to
832844 create ``c``.
833845
846+ ``c.msghook(msg)``
847+ By default, the `msghook` attribute does not exist. If set to a callable, any
848+ message that occurs during an operation of the cursor will be given to the
849+ callable. See the `Message Management`_ section for more information.
850+
851+
834852Cursors have some additional configuration properties that may be modified
835853during the use of the cursor:
836854
@@ -1298,6 +1316,11 @@ that change of state.
12981316 Prepare the transaction for the final commit. Once prepared, the second commit
12991317 may be ran to finalize the transaction, ``x.commit()``.
13001318
1319+ ``x.msghook(msg)``
1320+ By default, the `msghook` attribute does not exist. If set to a callable, any
1321+ message that occurs during an operation of the transaction will be given to
1322+ the callable. See the `Message Management`_ section for more information.
1323+
13011324These methods are primarily provided for applications that manage transactions
13021325in a way that cannot be formed around single, sequential blocks of code.
13031326Generally, using these methods require additional work to be performed by the
@@ -1605,3 +1628,81 @@ Or if use of a dictionary is desired::
16051628
16061629When a dictionary is given to construct the row, absent values are filled with
16071630`None`.
1631+
1632+
1633+ Message Management
1634+ ==================
1635+
1636+ By default, py-postgresql gives detailed reports of messages emitted by the
1637+ database. Often, the verbosity is excessive due to single target processes or
1638+ existing application infrastructure for tracing the sources of various events.
1639+
1640+ PostgreSQL itself provides a noise reduction tool for the client via the
1641+ ``client_min_messages`` setting. Altering this setting to a preferred level
1642+ either temporarily or permanently can be an appropriate solution in many cases.
1643+
1644+ When finer grained control over message details is needed, py-postgresql's
1645+ object relationship model provides a common protocol for controlling message
1646+ propagation and, ultimately, display.
1647+
1648+ The ``msghook`` attribute on elements is absent by default. However, when
1649+ present on an object--explicitly set--that contributed the cause of a message
1650+ event, it will be invoked with the Message, `postgresql.api.Message`, object as
1651+ its sole parameter. The attribute of the object that is closest to the event is
1652+ checked first, if present it will be called. If the ``msghook()`` call returns
1653+ a `True` value(specficially, ``bool(x) is True``), the message will not be
1654+ propagated any further. However, if a `False` value is returned, the next
1655+ element is checked until the list is exhausted and the message is given to
1656+ `postgresql.sys.msghook`. The normal list of elements is as follows::
1657+
1658+ Output -> Statement -> Connection -> Connector -> Driver [-> postgresql.sys]
1659+
1660+ Where ``Output`` can be a `postgresql.api.Cursor` object produced by
1661+ ``declare(...)`` or an implicit output management object used *internally* by
1662+ ``__call__()`` and other statement execution methods. Setting the ``msghook``
1663+ attribute on `postgresql.api.PreparedStatment` gives very fine control over
1664+ raised messages. Consider filtering the notice message on create table
1665+ statements that implicitly create indexes::
1666+
1667+ >>> db = postgresql.open(...)
1668+ >>> ct_this = db.prepare('CREATE TEMP TABLE "this" (i int PRIMARY KEY)')
1669+ >>> ct_that = db.prepare('CREATE TEMP TABLE "that" (i int PRIMARY KEY)')
1670+ >>> def filter_notices(msg):
1671+ ... if msg.details['severity'] == 'NOTICE':
1672+ ... return True
1673+ ...
1674+ >>> ct_that()
1675+ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "that_pkey" for table "that"
1676+ ...
1677+ ('CREATE', None)
1678+ >>> ct_this.msghook = filter_notices
1679+ >>> ct_this()
1680+ ('CREATE', None)
1681+ >>>
1682+
1683+ The above illustrates the quality of an installed ``msghook`` that simply
1684+ inhibits further propagation messages with a severity of 'NOTICE'--but, only
1685+ notices coming from objects derived from the ``ct_this``
1686+ `postgresql.api.PreparedStatement` object.
1687+
1688+ Subsequently, if the filter is installed on the connection's ``msghook``::
1689+
1690+ >>> db = postgresql.open(...)
1691+ >>> ct_this = db.prepare('CREATE TEMP TABLE "this" (i int PRIMARY KEY)')
1692+ >>> ct_that = db.prepare('CREATE TEMP TABLE "that" (i int PRIMARY KEY)')
1693+ >>> def filter_notices(msg):
1694+ ... if msg.details['severity'] == 'NOTICE':
1695+ ... return True
1696+ ...
1697+ >>> db.msghook = filter_notices
1698+ >>> ct_that()
1699+ ('CREATE', None)
1700+ >>> ct_this()
1701+ ('CREATE', None)
1702+ >>>
1703+
1704+ Any message with ``'NOTICE'`` severity coming from the connection, ``db``, will be
1705+ suffocated by the ``filter_notices`` function. However, if a ``msghook`` is
1706+ installed on either of those statements, it would be possible for display to
1707+ occur depending on the implementation of the hook installed on the statement
1708+ objects.
0 commit comments