From fdfa2de1a1744cabf918d8e4bf2a8740cbba101e Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Fri, 31 Dec 2010 19:21:44 +0100 Subject: [PATCH] Fixed adaptation of None in composite types (ticket #26). Added an adapter for None: it is usually not invoked as adaptation to NULL is a fast path in mogrify, but can be invoked by composite types. Notice that composite types still have the option to fast-path None (e.g. list adapter does). --- NEWS-2.3 | 7 +++++++ lib/__init__.py | 1 + lib/extensions.py | 13 +++++++++++++ tests/types_extras.py | 20 ++++++++++++++++++++ 4 files changed, 41 insertions(+) diff --git a/NEWS-2.3 b/NEWS-2.3 index 179ab299..ff211a31 100644 --- a/NEWS-2.3 +++ b/NEWS-2.3 @@ -1,3 +1,10 @@ +What's new in psycopg 2.3.3 +--------------------------- + + - Fixed adaptation of None in composite types (ticket #26). Bug report by + Karsten Hilbert. + + What's new in psycopg 2.3.2 --------------------------- diff --git a/lib/__init__.py b/lib/__init__.py index 2968284c..065b2a70 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -82,6 +82,7 @@ from _psycopg import __version__ import psycopg2.extensions as _ext _ext.register_adapter(tuple, _ext.SQL_IN) +_ext.register_adapter(type(None), _ext.NoneAdapter) __all__ = filter(lambda k: not k.startswith('_'), locals().keys()) diff --git a/lib/extensions.py b/lib/extensions.py index fca79738..24a9a6b8 100644 --- a/lib/extensions.py +++ b/lib/extensions.py @@ -128,4 +128,17 @@ class SQL_IN(object): __str__ = getquoted +class NoneAdapter(object): + """Adapt None to NULL. + + This adapter is not used normally as a fast path in mogrify uses NULL, + but it makes easier to adapt composite types. + """ + def __init__(self, obj): + pass + + def getquoted(self): + return "NULL" + + __all__ = filter(lambda k: not k.startswith('_'), locals().keys()) diff --git a/tests/types_extras.py b/tests/types_extras.py index 3986c77f..7f18c96e 100644 --- a/tests/types_extras.py +++ b/tests/types_extras.py @@ -364,6 +364,26 @@ class AdaptTypeTestCase(unittest.TestCase): d = curs.fetchone()[0] self.assertEqual("(42,)", d) + def test_none_fast_path(self): + # the None adapter is not actually invoked in regular adaptation + ext = psycopg2.extensions + + class WonkyAdapter(object): + def __init__(self, obj): pass + def getquoted(self): return "NOPE!" + + curs = self.conn.cursor() + + orig_adapter = ext.adapters[type(None), ext.ISQLQuote] + try: + ext.register_adapter(type(None), WonkyAdapter) + self.assertEqual(ext.adapt(None).getquoted(), "NOPE!") + + s = curs.mogrify("SELECT %s;", (None,)) + self.assertEqual("SELECT NULL;", s) + + finally: + ext.register_adapter(type(None), orig_adapter) def test_suite(): return unittest.TestLoader().loadTestsFromName(__name__)