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)
|
||||
and other objects implementing the "Revised Buffer Protocol" to 'bytea'
|
||||
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
|
||||
in 'hex' format and the client libpq can't parse them.
|
||||
- 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.
|
||||
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
|
||||
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.
|
||||
|
||||
.. autofunction:: register_hstore
|
||||
|
|
|
@ -663,7 +663,7 @@ class HstoreAdapter(object):
|
|||
|
||||
@classmethod
|
||||
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.
|
||||
"""
|
||||
|
@ -680,28 +680,32 @@ class HstoreAdapter(object):
|
|||
# column typarray not available before PG 8.3
|
||||
typarray = conn.server_version >= 80300 and "typarray" or "NULL"
|
||||
|
||||
rv0, rv1 = [], []
|
||||
|
||||
# get the oid for the hstore
|
||||
curs.execute("""\
|
||||
SELECT t.oid, %s
|
||||
FROM pg_type t JOIN pg_namespace ns
|
||||
ON typnamespace = ns.oid
|
||||
WHERE typname = 'hstore' and nspname = 'public';
|
||||
WHERE typname = 'hstore';
|
||||
""" % 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
|
||||
if (conn_status != _ext.STATUS_IN_TRANSACTION
|
||||
and conn.isolation_level != _ext.ISOLATION_LEVEL_AUTOCOMMIT):
|
||||
conn.rollback()
|
||||
|
||||
return oids
|
||||
return tuple(rv0), tuple(rv1)
|
||||
|
||||
def register_hstore(conn_or_curs, globally=False, unicode=False, oid=None):
|
||||
"""Register adapter and typecaster for `!dict`\-\ |hstore| conversions.
|
||||
|
||||
:param conn_or_curs: a connection or cursor: the typecaster will be
|
||||
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
|
||||
will be `!unicode` instead of `!str`. The option is not available on
|
||||
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.
|
||||
|
||||
.. 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:
|
||||
oid = HstoreAdapter.get_oids(conn_or_curs)
|
||||
|
@ -735,13 +741,16 @@ def register_hstore(conn_or_curs, globally=False, unicode=False, oid=None):
|
|||
else:
|
||||
oid = oid[0] # for the moment we don't have a HSTOREARRAY
|
||||
|
||||
if isinstance(oid, int):
|
||||
oid = (oid,)
|
||||
|
||||
# create and register the typecaster
|
||||
if sys.version_info[0] < 3 and unicode:
|
||||
cast = HstoreAdapter.parse_unicode
|
||||
else:
|
||||
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_adapter(dict, HstoreAdapter)
|
||||
|
||||
|
|
|
@ -276,7 +276,7 @@ class HstoreTestCase(unittest.TestCase):
|
|||
finally:
|
||||
conn2.close()
|
||||
finally:
|
||||
psycopg2.extensions.string_types.pop(oids[0])
|
||||
psycopg2.extensions.string_types.pop(oids[0][0])
|
||||
|
||||
# verify the caster is not around anymore
|
||||
cur = self.conn.cursor()
|
||||
|
|
Loading…
Reference in New Issue
Block a user