---------------
The psycopg2 dialect will log PostgreSQL NOTICE messages
-via the ``sqlalchemy.dialects.postgresql`` logger::
+via the ``sqlalchemy.dialects.postgresql`` logger. When this logger
+is set to the ``logging.INFO`` level, notice messages will be logged::
import logging
+
+ logging.getLogger('sqlalchemy.dialects.postgresql').setLevel(logging.INFO)
+
+Above, it is assumed that logging is configured externally. If this is not
+the case, configuration such as ``logging.basicConfig()`` must be utilized::
+
+ import logging
+
+ logging.basicConfig() # log messages to stdout
logging.getLogger('sqlalchemy.dialects.postgresql').setLevel(logging.INFO)
+.. seealso::
+
+ `Logging HOWTO <https://docs.python.org/3/howto/logging.html>`_ - on the python.org website
+
.. _psycopg2_hstore:
HSTORE type
from ... import types as sqltypes
from ... import util
from ...engine import result as _result
-
+from ...util import collections_abc
try:
from uuid import UUID as _python_UUID # noqa
return self._dbapi_connection.cursor(ident)
def get_result_proxy(self):
- # TODO: ouch
- if logger.isEnabledFor(logging.INFO):
- self._log_notices(self.cursor)
+ self._log_notices(self.cursor)
if self._is_server_side:
return _result.BufferedRowResultProxy(self)
return _result.ResultProxy(self)
def _log_notices(self, cursor):
+ # check also that notices is an iterable, after it's already
+ # established that we will be iterating through it. This is to get
+ # around test suites such as SQLAlchemy's using a Mock object for
+ # cursor
+ if not cursor.connection.notices or not isinstance(
+ cursor.connection.notices, collections_abc.Iterable
+ ):
+ return
+
for notice in cursor.connection.notices:
# NOTICE messages have a
# newline character at the end
from sqlalchemy.testing.assertions import AssertsCompiledSQL
from sqlalchemy.testing.assertions import AssertsExecutionResults
from sqlalchemy.testing.assertions import eq_
+from sqlalchemy.testing.assertions import eq_regex
from sqlalchemy.testing.assertions import ne_
from sqlalchemy.testing.mock import Mock
from ...engine import test_execute
)
assert isinstance(exception, exc.OperationalError)
- # currently not passing with pg 9.3 that does not seem to generate
- # any notices here, would rather find a way to mock this
@testing.requires.no_coverage
@testing.requires.psycopg2_compatibility
- def _test_notice_logging(self):
+ def test_notice_logging(self):
log = logging.getLogger("sqlalchemy.dialects.postgresql")
buf = logging.handlers.BufferingHandler(100)
lev = log.level
conn = testing.db.connect()
trans = conn.begin()
try:
- conn.execute("create table foo (id serial primary key)")
+ conn.execute(
+ """
+CREATE OR REPLACE FUNCTION note(message varchar) RETURNS integer AS $$
+BEGIN
+ RAISE NOTICE 'notice: %%', message;
+ RETURN NULL;
+END;
+$$ LANGUAGE plpgsql;
+"""
+ )
+ conn.execute("SELECT note('hi there')")
+ conn.execute("SELECT note('another note')")
finally:
trans.rollback()
finally:
log.removeHandler(buf)
log.setLevel(lev)
msgs = " ".join(b.msg for b in buf.buffer)
- assert "will create implicit sequence" in msgs
- assert "will create implicit index" in msgs
+ eq_regex(
+ msgs,
+ "NOTICE: notice: hi there(\nCONTEXT: .*?)? "
+ "NOTICE: notice: another note(\nCONTEXT: .*?)?",
+ )
@testing.requires.psycopg2_or_pg8000_compatibility
@engines.close_open_connections