Merge branch 'none-in-composite' into python2

This commit is contained in:
Daniele Varrazzo 2011-01-01 17:09:37 +01:00
commit f9be48d89e
5 changed files with 57 additions and 5 deletions

View File

@ -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 What's new in psycopg 2.3.2
--------------------------- ---------------------------

View File

@ -82,6 +82,7 @@ from _psycopg import __version__
import psycopg2.extensions as _ext import psycopg2.extensions as _ext
_ext.register_adapter(tuple, _ext.SQL_IN) _ext.register_adapter(tuple, _ext.SQL_IN)
_ext.register_adapter(type(None), _ext.NoneAdapter)
__all__ = filter(lambda k: not k.startswith('_'), locals().keys()) __all__ = filter(lambda k: not k.startswith('_'), locals().keys())

View File

@ -128,4 +128,17 @@ class SQL_IN(object):
__str__ = getquoted __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()) __all__ = filter(lambda k: not k.startswith('_'), locals().keys())

View File

@ -136,11 +136,6 @@ microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
because the ISQLQuote type is abstract and there is no way to get a because the ISQLQuote type is abstract and there is no way to get a
quotable object to be its instance */ quotable object to be its instance */
/* None is always adapted to NULL */
if (obj == Py_None)
return PyString_FromString("NULL");
Dprintf("microprotocols_adapt: trying to adapt %s", obj->ob_type->tp_name); Dprintf("microprotocols_adapt: trying to adapt %s", obj->ob_type->tp_name);
/* look for an adapter in the registry */ /* look for an adapter in the registry */

View File

@ -349,6 +349,42 @@ class HstoreTestCase(unittest.TestCase):
ok(dict(zip(ab, ab))) ok(dict(zip(ab, ab)))
class AdaptTypeTestCase(unittest.TestCase):
def setUp(self):
self.conn = psycopg2.connect(tests.dsn)
def tearDown(self):
self.conn.close()
def test_none_in_record(self):
curs = self.conn.cursor()
s = curs.mogrify("SELECT %s;", [(42, None)])
self.assertEqual("SELECT (42, NULL);", s)
curs.execute("SELECT %s;", [(42, None)])
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(): def test_suite():
return unittest.TestLoader().loadTestsFromName(__name__) return unittest.TestLoader().loadTestsFromName(__name__)