예제 #1
0
def test_fetch_info(conn, testcomp, name, fields):
    info = CompositeInfo.fetch(conn, name)
    assert info.name == "testcomp"
    assert info.oid > 0
    assert info.oid != info.array_oid > 0
    assert len(info.field_names) == 3
    assert len(info.field_types) == 3
    for i, (name, t) in enumerate(fields):
        assert info.field_names[i] == name
        assert info.field_types[i] == builtins[t].oid
예제 #2
0
def test_dump_tuple(conn, rec, obj):
    cur = conn.cursor()
    fields = [f"f{i} text" for i in range(len(obj))]
    cur.execute(f"""
        drop type if exists tmptype;
        create type tmptype as ({', '.join(fields)});
        """)
    info = CompositeInfo.fetch(conn, "tmptype")
    info.register(context=conn)

    res = conn.execute("select %s::tmptype", [obj]).fetchone()[0]
    assert res == obj
예제 #3
0
def test_callable_dumper_not_registered(conn, testcomp):
    info = CompositeInfo.fetch(conn, "testcomp")

    def fac(*args):
        return args + (args[-1], )

    register_composite(info, conn, factory=fac)
    assert info.python_type is None

    # but the loader is registered
    cur = conn.execute("select '(foo,42,3.14)'::testcomp")
    assert cur.fetchone()[0] == ("foo", 42, 3.14, 3.14)
예제 #4
0
def test_type_dumper_registered_binary(conn, testcomp):
    info = CompositeInfo.fetch(conn, "testcomp")
    register_composite(info, conn)
    assert issubclass(info.python_type, tuple)
    assert info.python_type.__name__ == "testcomp"
    d = conn.adapters.get_dumper(info.python_type, "b")
    assert issubclass(d, TupleBinaryDumper)
    assert d is not TupleBinaryDumper

    tc = info.python_type("foo", 42, 3.14)
    cur = conn.execute("select pg_typeof(%b)", [tc])
    assert cur.fetchone()[0] == "testcomp"
예제 #5
0
def testcomp(svcconn):
    cur = svcconn.cursor()
    cur.execute("""
        create schema if not exists testschema;

        drop type if exists testcomp cascade;
        drop type if exists testschema.testcomp cascade;

        create type testcomp as (foo text, bar int8, baz float8);
        create type testschema.testcomp as (foo text, bar int8, qux bool);
        """)
    return CompositeInfo.fetch(svcconn, "testcomp")
예제 #6
0
def test_dump_builtin_empty_range(conn, fmt_in):
    conn.execute("""
        drop type if exists tmptype;
        create type tmptype as (num integer, range daterange, nums integer[])
        """)
    info = CompositeInfo.fetch(conn, "tmptype")
    register_composite(info, conn)

    cur = conn.execute(
        f"select pg_typeof(%{fmt_in})",
        [info.python_type(10, Range(empty=True), [])],
    )
    assert cur.fetchone()[0] == "tmptype"
예제 #7
0
def test_load_composite(conn, testcomp, fmt_out):
    info = CompositeInfo.fetch(conn, "testcomp")
    info.register(conn)

    cur = conn.cursor(binary=fmt_out)
    res = cur.execute("select row('hello', 10, 20)::testcomp").fetchone()[0]
    assert res.foo == "hello"
    assert res.bar == 10
    assert res.baz == 20.0
    assert isinstance(res.baz, float)

    res = cur.execute(
        "select array[row('hello', 10, 30)::testcomp]").fetchone()[0]
    assert len(res) == 1
    assert res[0].baz == 30.0
    assert isinstance(res[0].baz, float)
예제 #8
0
def test_register_scope(conn, testcomp):
    info = CompositeInfo.fetch(conn, "testcomp")
    info.register()
    for fmt in (pq.Format.TEXT, pq.Format.BINARY):
        for oid in (info.oid, info.array_oid):
            assert global_adapters._loaders[fmt].pop(oid)

    cur = conn.cursor()
    info.register(cur)
    for fmt in (pq.Format.TEXT, pq.Format.BINARY):
        for oid in (info.oid, info.array_oid):
            assert oid not in global_adapters._loaders[fmt]
            assert oid not in conn.adapters._loaders[fmt]
            assert oid in cur.adapters._loaders[fmt]

    info.register(conn)
    for fmt in (pq.Format.TEXT, pq.Format.BINARY):
        for oid in (info.oid, info.array_oid):
            assert oid not in global_adapters._loaders[fmt]
            assert oid in conn.adapters._loaders[fmt]
예제 #9
0
def test_load_composite_factory(conn, testcomp, fmt_out):
    info = CompositeInfo.fetch(conn, "testcomp")

    class MyThing:
        def __init__(self, *args):
            self.foo, self.bar, self.baz = args

    info.register(conn, factory=MyThing)

    cur = conn.cursor(binary=fmt_out)
    res = cur.execute("select row('hello', 10, 20)::testcomp").fetchone()[0]
    assert isinstance(res, MyThing)
    assert res.baz == 20.0
    assert isinstance(res.baz, float)

    res = cur.execute(
        "select array[row('hello', 10, 30)::testcomp]").fetchone()[0]
    assert len(res) == 1
    assert res[0].baz == 30.0
    assert isinstance(res[0].baz, float)
예제 #10
0
def test_register_scope(conn, testcomp):
    info = CompositeInfo.fetch(conn, "testcomp")
    register_composite(info)
    for fmt in pq.Format:
        for oid in (info.oid, info.array_oid):
            assert postgres.adapters._loaders[fmt].pop(oid)

    for fmt in PyFormat:
        assert postgres.adapters._dumpers[fmt].pop(info.python_type)

    cur = conn.cursor()
    register_composite(info, cur)
    for fmt in pq.Format:
        for oid in (info.oid, info.array_oid):
            assert oid not in postgres.adapters._loaders[fmt]
            assert oid not in conn.adapters._loaders[fmt]
            assert oid in cur.adapters._loaders[fmt]

    register_composite(info, conn)
    for fmt in pq.Format:
        for oid in (info.oid, info.array_oid):
            assert oid not in postgres.adapters._loaders[fmt]
            assert oid in conn.adapters._loaders[fmt]