Beispiel #1
0
 def test_wrong_schema(self):
     oid = self._create_type("type_ii", [("a", "integer"),
                                         ("b", "integer")])
     c = CompositeCaster("type_ii", oid, [("a", 23), ("b", 23), ("c", 23)])
     curs = self.conn.cursor()
     psycopg2.extensions.register_type(c.typecaster, curs)
     curs.execute("select (1,2)::type_ii")
     self.assertRaises(psycopg2.DataError, curs.fetchone)
 def ok(s, v):
     self.assertEqual(CompositeCaster.tokenize(s), v)
Beispiel #3
0
 def ok(s, v):
     self.assertEqual(CompositeCaster.tokenize(s), v)
Beispiel #4
0
def register_flexmap(conn, types):
    """
   Create flexmap type from
   
    1) 'schema.typename' str or
    2) (typename, oid, attrs, array_oid, schema) tuple where attrs = [(attname, atttypid)]
   
   For 1), type info will be looked up in database catalog. For 2), type info is
   taken as specified.
   """

    register_hstore(conn)
    register_json(conn)

    casters = {}

    class DictComposite(CompositeCaster):
        """
      A type caster returning composite types as Python dicts
      enriched with a type field containing 'schema.typename'.
      """
        def make(self, attrs):
            o = {}
            for i in xrange(len(self.attnames)):
                if attrs[i] is not None:
                    o[self.attnames[i]] = attrs[i]
            o['type'] = self.schema + '.' + self.name
            return o

    ## create type casters for whole list
    ##
    for t in types:
        if type(t) == str:
            caster = DictComposite._from_db(t, conn)
        elif type(t) in [tuple, list]:
            caster = CompositeCaster(*t)
        else:
            raise Exception("invalid type %s in flexmap type list" % type(t))

        ## register item and array casters
        ##
        register_type(caster.typecaster, conn)
        if caster.array_typecaster is not None:
            register_type(caster.array_typecaster, conn)

        ## remember caster under 'schema.typename'
        ##
        casters['%s.%s' % (caster.schema, caster.name)] = caster

    class DictAdapter(object):
        """
      A dictionary adapter converting Python dicts to PostgreSQL
      JSON, Hstore or Composite Types depending on the dict field 'type'.      
      """
        def __init__(self, adapted):
            ## remember value to be adaptated - a Python dict
            self.adapted = adapted

            ## remember type field of dict-value to be adapted
            if adapted.has_key('type'):
                self._type = adapted['type']
                #del(adapted['type'])
            else:
                self._type = None

            ## create adapter to hstore if requested
            if self._type == 'hstore':
                self._hstoreAdapter = HstoreAdapter(adapted)

        def prepare(self, conn):
            self._conn = conn
            if self._type == 'hstore':
                self._hstoreAdapter.prepare(conn)

        def getquoted(self):
            if self._type is not None:
                if self._type == 'json':
                    return adapt(Json(self.adapted)).getquoted() + '::json'
                elif self._type == 'hstore':
                    return self._hstoreAdapter.getquoted()
                elif casters.has_key(self._type):
                    c = casters[self._type]
                    v = []
                    for n in c.attnames:
                        v.append(self.adapted.get(n, None))
                    a = adapt(tuple(v))
                    a.prepare(self._conn)
                    return a.getquoted() + '::' + self._type
                else:
                    raise psycopg2.ProgrammingError(
                        "unknown type %s in dictionary type hint" % self._type)
            else:
                raise psycopg2.ProgrammingError(
                    "dictionary is missing type hint")

    register_adapter(dict, DictAdapter)