mirror of
https://github.com/psycopg/psycopg2.git
synced 2025-01-31 09:24:07 +03:00
Don't limit the hstore search to the public schema only
Looks like there is a case for installing hstore somewhere else (see ticket #45). And after all the typecaster can be registered on a list of OIDs, so let's grab them all.
This commit is contained in:
parent
29ac03ef04
commit
5211e1474b
2
NEWS
2
NEWS
|
@ -28,6 +28,8 @@ What's new in psycopg 2.4
|
||||||
- Adapt types 'bytearray' (from Python 2.6), 'memoryview' (from Python 2.7)
|
- Adapt types 'bytearray' (from Python 2.6), 'memoryview' (from Python 2.7)
|
||||||
and other objects implementing the "Revised Buffer Protocol" to 'bytea'
|
and other objects implementing the "Revised Buffer Protocol" to 'bytea'
|
||||||
data type.
|
data type.
|
||||||
|
- The 'hstore' adapter can work even when the data type is not installed
|
||||||
|
in the 'public' namespace.
|
||||||
- Raise a clean exception instead of returning bad data when receiving bytea
|
- Raise a clean exception instead of returning bad data when receiving bytea
|
||||||
in 'hex' format and the client libpq can't parse them.
|
in 'hex' format and the client libpq can't parse them.
|
||||||
- Empty lists correctly roundtrip Python -> PostgreSQL -> Python.
|
- Empty lists correctly roundtrip Python -> PostgreSQL -> Python.
|
||||||
|
|
|
@ -145,9 +145,9 @@ key/value pairs as well as regular BTree indexes for equality, uniqueness etc.
|
||||||
|
|
||||||
Psycopg can convert Python `!dict` objects to and from |hstore| structures.
|
Psycopg can convert Python `!dict` objects to and from |hstore| structures.
|
||||||
Only dictionaries with string/unicode keys and values are supported. `!None`
|
Only dictionaries with string/unicode keys and values are supported. `!None`
|
||||||
is also allowed as value. Psycopg uses a more efficient |hstore|
|
is also allowed as value but not as a key. Psycopg uses a more efficient |hstore|
|
||||||
representation when dealing with PostgreSQL 9.0 but previous server versions
|
representation when dealing with PostgreSQL 9.0 but previous server versions
|
||||||
are supportes as well. By default the adapter/typecaster are disabled: they
|
are supported as well. By default the adapter/typecaster are disabled: they
|
||||||
can be enabled using the `register_hstore()` function.
|
can be enabled using the `register_hstore()` function.
|
||||||
|
|
||||||
.. autofunction:: register_hstore
|
.. autofunction:: register_hstore
|
||||||
|
|
|
@ -663,7 +663,7 @@ class HstoreAdapter(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_oids(self, conn_or_curs):
|
def get_oids(self, conn_or_curs):
|
||||||
"""Return the oid of the hstore and hstore[] types.
|
"""Return the lists of OID of the hstore and hstore[] types.
|
||||||
|
|
||||||
Return None if hstore is not available.
|
Return None if hstore is not available.
|
||||||
"""
|
"""
|
||||||
|
@ -680,28 +680,32 @@ class HstoreAdapter(object):
|
||||||
# column typarray not available before PG 8.3
|
# column typarray not available before PG 8.3
|
||||||
typarray = conn.server_version >= 80300 and "typarray" or "NULL"
|
typarray = conn.server_version >= 80300 and "typarray" or "NULL"
|
||||||
|
|
||||||
|
rv0, rv1 = [], []
|
||||||
|
|
||||||
# get the oid for the hstore
|
# get the oid for the hstore
|
||||||
curs.execute("""\
|
curs.execute("""\
|
||||||
SELECT t.oid, %s
|
SELECT t.oid, %s
|
||||||
FROM pg_type t JOIN pg_namespace ns
|
FROM pg_type t JOIN pg_namespace ns
|
||||||
ON typnamespace = ns.oid
|
ON typnamespace = ns.oid
|
||||||
WHERE typname = 'hstore' and nspname = 'public';
|
WHERE typname = 'hstore';
|
||||||
""" % typarray)
|
""" % typarray)
|
||||||
oids = curs.fetchone()
|
for oids in curs:
|
||||||
|
rv0.append(oids[0])
|
||||||
|
rv1.append(oids[1])
|
||||||
|
|
||||||
# revert the status of the connection as before the command
|
# revert the status of the connection as before the command
|
||||||
if (conn_status != _ext.STATUS_IN_TRANSACTION
|
if (conn_status != _ext.STATUS_IN_TRANSACTION
|
||||||
and conn.isolation_level != _ext.ISOLATION_LEVEL_AUTOCOMMIT):
|
and conn.isolation_level != _ext.ISOLATION_LEVEL_AUTOCOMMIT):
|
||||||
conn.rollback()
|
conn.rollback()
|
||||||
|
|
||||||
return oids
|
return tuple(rv0), tuple(rv1)
|
||||||
|
|
||||||
def register_hstore(conn_or_curs, globally=False, unicode=False, oid=None):
|
def register_hstore(conn_or_curs, globally=False, unicode=False, oid=None):
|
||||||
"""Register adapter and typecaster for `!dict`\-\ |hstore| conversions.
|
"""Register adapter and typecaster for `!dict`\-\ |hstore| conversions.
|
||||||
|
|
||||||
:param conn_or_curs: a connection or cursor: the typecaster will be
|
:param conn_or_curs: a connection or cursor: the typecaster will be
|
||||||
registered only on this object unless *globally* is set to `!True`
|
registered only on this object unless *globally* is set to `!True`
|
||||||
:param globally: register the adapter globally not only on *conn_or_curs*
|
:param globally: register the adapter globally, not only on *conn_or_curs*
|
||||||
:param unicode: if `!True`, keys and values returned from the database
|
:param unicode: if `!True`, keys and values returned from the database
|
||||||
will be `!unicode` instead of `!str`. The option is not available on
|
will be `!unicode` instead of `!str`. The option is not available on
|
||||||
Python 3
|
Python 3
|
||||||
|
@ -724,7 +728,9 @@ def register_hstore(conn_or_curs, globally=False, unicode=False, oid=None):
|
||||||
Raise `~psycopg2.ProgrammingError` if the type is not found.
|
Raise `~psycopg2.ProgrammingError` if the type is not found.
|
||||||
|
|
||||||
.. versionchanged:: 2.4
|
.. versionchanged:: 2.4
|
||||||
added the *oid* parameter.
|
added the *oid* parameter. If not specified, the typecaster is
|
||||||
|
installed also if |hstore| is not installed in the :sql:`public`
|
||||||
|
schema.
|
||||||
"""
|
"""
|
||||||
if oid is None:
|
if oid is None:
|
||||||
oid = HstoreAdapter.get_oids(conn_or_curs)
|
oid = HstoreAdapter.get_oids(conn_or_curs)
|
||||||
|
@ -735,13 +741,16 @@ def register_hstore(conn_or_curs, globally=False, unicode=False, oid=None):
|
||||||
else:
|
else:
|
||||||
oid = oid[0] # for the moment we don't have a HSTOREARRAY
|
oid = oid[0] # for the moment we don't have a HSTOREARRAY
|
||||||
|
|
||||||
|
if isinstance(oid, int):
|
||||||
|
oid = (oid,)
|
||||||
|
|
||||||
# create and register the typecaster
|
# create and register the typecaster
|
||||||
if sys.version_info[0] < 3 and unicode:
|
if sys.version_info[0] < 3 and unicode:
|
||||||
cast = HstoreAdapter.parse_unicode
|
cast = HstoreAdapter.parse_unicode
|
||||||
else:
|
else:
|
||||||
cast = HstoreAdapter.parse
|
cast = HstoreAdapter.parse
|
||||||
|
|
||||||
HSTORE = _ext.new_type((oid,), "HSTORE", cast)
|
HSTORE = _ext.new_type(oid, "HSTORE", cast)
|
||||||
_ext.register_type(HSTORE, not globally and conn_or_curs or None)
|
_ext.register_type(HSTORE, not globally and conn_or_curs or None)
|
||||||
_ext.register_adapter(dict, HstoreAdapter)
|
_ext.register_adapter(dict, HstoreAdapter)
|
||||||
|
|
||||||
|
|
|
@ -276,7 +276,7 @@ class HstoreTestCase(unittest.TestCase):
|
||||||
finally:
|
finally:
|
||||||
conn2.close()
|
conn2.close()
|
||||||
finally:
|
finally:
|
||||||
psycopg2.extensions.string_types.pop(oids[0])
|
psycopg2.extensions.string_types.pop(oids[0][0])
|
||||||
|
|
||||||
# verify the caster is not around anymore
|
# verify the caster is not around anymore
|
||||||
cur = self.conn.cursor()
|
cur = self.conn.cursor()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user