Changeset 774 for trunk/pg.py


Ignore:
Timestamp:
Jan 21, 2016, 1:49:28 PM (4 years ago)
Author:
cito
Message:

Add support for JSON and JSONB to pg and pgdb

This adds all necessary functions to make PyGreSQL automatically
convert between JSON columns and Python objects representing them.

The documentation has also been updated, see there for the details.

Also, tuples automatically bind to ROW expressions in pgdb now.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/pg.py

    r770 r774  
    3939from functools import partial
    4040from operator import itemgetter
     41from json import loads as jsondecode, dumps as jsonencode
    4142
    4243try:
     
    4445except NameError:  # Python >= 3.0
    4546    basestring = (str, bytes)
    46 
    47 set_decimal(Decimal)
    4847
    4948try:
     
    131130        def _read_only_error(*args, **kw):
    132131            raise TypeError('This object is read-only')
    133 
    134132
    135133
     
    157155    if typ.startswith('bytea'):
    158156        return 'bytea'
     157    if typ.startswith('json'):
     158        return 'json'
    159159    return 'text'
    160160
     
    164164    row = namedtuple('Row', q.listfields())
    165165    return [row(*r) for r in q.getresult()]
    166 
    167 set_namedresult(_namedresult)
    168166
    169167
     
    201199    return _db_error(msg, ProgrammingError)
    202200
     201
     202# Initialize the C module
     203
     204set_namedresult(_namedresult)
     205set_decimal(Decimal)
     206set_jsondecode(jsondecode)
     207
     208
     209# The notification handler
    203210
    204211class NotificationHandler(object):
     
    468475        return self.escape_bytea(d)
    469476
     477    def _prepare_json(self, d):
     478        """Prepare a json parameter."""
     479        return self.encode_json(d)
     480
    470481    _prepare_funcs = dict(  # quote methods for each type
    471482        bool=_prepare_bool, date=_prepare_date,
    472483        int=_prepare_num, num=_prepare_num, float=_prepare_num,
    473         money=_prepare_num, bytea=_prepare_bytea)
     484        money=_prepare_num, bytea=_prepare_bytea, json=_prepare_json)
    474485
    475486    def _prepare_param(self, value, typ, params):
     
    509520    # so we define unescape_bytea as a method as well
    510521    unescape_bytea = staticmethod(unescape_bytea)
     522
     523    def decode_json(self, s):
     524        """Decode a JSON string coming from the database."""
     525        return (get_jsondecode() or jsondecode)(s)
     526
     527    def encode_json(self, d):
     528        """Encode a JSON string for use within SQL."""
     529        return jsonencode(d)
    511530
    512531    def close(self):
     
    14421461        if keytuple or rowtuple:
    14431462            namedresult = get_namedresult()
    1444             if keytuple:
    1445                 keys = namedresult(_MemoryQuery(keys, keyname))
    1446             if rowtuple:
    1447                 fields = [f for f in fields if f not in keyset]
    1448                 rows = namedresult(_MemoryQuery(rows, fields))
     1463            if namedresult:
     1464                if keytuple:
     1465                    keys = namedresult(_MemoryQuery(keys, keyname))
     1466                if rowtuple:
     1467                    fields = [f for f in fields if f not in keyset]
     1468                    rows = namedresult(_MemoryQuery(rows, fields))
    14491469        return cls(zip(keys, rows))
    14501470
Note: See TracChangeset for help on using the changeset viewer.