Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kce7S-0003A1-4e for psycopg@arkaria.postgresql.org; Wed, 11 Nov 2020 00:36:14 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1kce7P-0002fD-Sb for psycopg@arkaria.postgresql.org; Wed, 11 Nov 2020 00:36:11 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kce7P-0002f6-KJ for psycopg@lists.postgresql.org; Wed, 11 Nov 2020 00:36:11 +0000 Received: from mail-vs1-xe31.google.com ([2607:f8b0:4864:20::e31]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1kce7N-0003JR-Fu for psycopg@postgresql.org; Wed, 11 Nov 2020 00:36:11 +0000 Received: by mail-vs1-xe31.google.com with SMTP id y78so199163vsy.6 for ; Tue, 10 Nov 2020 16:36:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=OB6fHKXpxoMfne8H6WoaU2OPZVv0FSIR9JQ7naCaKFE=; b=r8eFmqA3jdsndyPLyFG+q3Ssa0NMWSUnJV6v/QnLfwt7zUge2Su/efdnhI2JDi//zV YHD/JdaQGCTETj6/T2iAp/JtL4kV5IruWcsqIkmLlDB7GqKi2UwkbSFjekOkdLA2hz0I keYQhWlFQ4/uOyuDS6VASb3CIg/uuTlp8IAA/bNSszqr+mbYudkTYRp3hEa95dKfub98 64v8kVke5zSNEdhf7+pXvmQdPjB+ytmM0wAIEo2A/va1nZPTzWUYLs44YzL9zxl3yRb8 UAZutlSoUJJvesRs2cD9Flt9YuLwhwEAzz3Pk75E5HaAPPAH0yqtRAm4P6kcEsaADH9w x2Lg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=OB6fHKXpxoMfne8H6WoaU2OPZVv0FSIR9JQ7naCaKFE=; b=Tuc7SSltY7eozD6kVKEgJrF2UNxAJeIDrzG73A2mOehkXOZSNWA4zSydRvscFzOmTU mdfKt9FgKY+mtpl31aBcxVjcw/CAnueH8MLS7plp1FOrIaHlQw81XpSPmz484O57AWHu fxFC/bYgT8MG0BddFnjY9ri9EiOcnCSPwSqNK6Crsx6Yf8Gw8m1ctZHsavhEnxbKojfV +qYXUK6afhwfvRisSRX1qwudRCvO0FMleaQKTRjh1lkEnMX+vv27zEkXO7Kguo5e5bZV 7tSGJnpYpSEfDscElhABPYwKwgXJMIRFrC6XJAj0BEGBnpOw8EUPw6orK4TRnHNRkAiB /q3A== X-Gm-Message-State: AOAM530W9YQhacJGBNF48XiFd81vFw1JiTtOomeg3ZftLjeyPVB0fJzX DtP6/cZJvU8oY1dLdW8BqFJzoeinmT17LfCSACQ= X-Google-Smtp-Source: ABdhPJwNL0bZ4GXKW3Uf/4GrG8aNYRt06rCZkuuDLFrEeER6t7OkzN30qRF9cGoSorboQFH9x3MOG3uOGDeSzs5bzBE= X-Received: by 2002:a67:f909:: with SMTP id t9mr10810021vsq.4.1605054968120; Tue, 10 Nov 2020 16:36:08 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Vladimir Ryabtsev Date: Tue, 10 Nov 2020 16:35:57 -0800 Message-ID: Subject: Re: Using composite types in psycopg3 To: Daniele Varrazzo Cc: psycopg@postgresql.org Content-Type: multipart/alternative; boundary="00000000000038481905b3c9fba5" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --00000000000038481905b3c9fba5 Content-Type: text/plain; charset="UTF-8" Awesome, thanks. It would be great if it worked out of the box, as in other drivers. Appreciate your efforts. Vladimir On Tue, 10 Nov 2020 at 16:24, Daniele Varrazzo wrote: > On Tue, 10 Nov 2020 at 21:59, Vladimir Ryabtsev > wrote: > > > psycopg2 returns the 'result' as a basic string, while > > in asyncpg and py-postgresql I have structured data > > (roughly 'List[Tuple[int, List[str]]]'). > > > > I tried the same in psycopg3 and it is little bit better, but > > not entirely: it shows the outer list, the tuples inside it, > > but the innermost list is still represented as a basic string: > > '{one,"one more"}'. > > > > Is it something you are still working on? Any workarounds? > Yes: by obtaining data from the db in binary mode you can get > information about deeply nested objects. psycopg2 works only in text > mode, psycopg3 in both. > > In [1]: query = """ > ...: with test as ( > ...: select 1 as id, 'one' val > ...: union all > ...: select 1, 'one more' > ...: union all > ...: select 2, 'two' > ...: ) > ...: select array( > ...: select (id, array_agg(val)) > ...: from test > ...: group by id > ...: )""" > > In [2]: import psycopg3 > > In [3]: from psycopg3.pq import Format > > In [4]: cnn = psycopg3.connect("") > > In [5]: cnn.cursor().execute(query).fetchone()[0] > Out[5]: [('1', '{one,"one more"}'), ('2', '{two}')] > > In [6]: cnn.cursor(format=Format.BINARY).execute(query).fetchone()[0] > Out[6]: [(1, ['one', 'one more']), (2, ['two'])] > > Binary loading/dumping is not supported yet for all the data types, > but the plan is to cover all the builtins. Still not sure about the > interface to request text/binary results, or whether binary shouldn't > be the default as opposed to text. There is still ground to cover, but > we are getting there. > > -- Daniele > --00000000000038481905b3c9fba5 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Awesome, thanks.

It would be great = if it worked out of the box, as in other drivers.
Appreciate your= efforts.

Vladimir

On Tue, 10 Nov 2020 at 16:= 24, Daniele Varrazzo <dani= ele.varrazzo@gmail.com> wrote:
On Tue, 10 Nov 2020 at 21:59, Vladimir Ryabtsev <<= a href=3D"mailto:greatvovan@gmail.com" target=3D"_blank">greatvovan@gmail.c= om> wrote:

> psycopg2 returns the 'result' as a basic string, while
> in asyncpg and py-postgresql I have structured data
> (roughly 'List[Tuple[int, List[str]]]').
>
> I tried the same in psycopg3 and it is little bit better, but
> not entirely: it shows the outer list, the tuples inside it,
> but the innermost list is still represented as a basic string:
> '{one,"one more"}'.
>
> Is it something you are still working on? Any workarounds?
Yes: by obtaining data from the db in binary mode you can get
information about deeply nested objects. psycopg2 works only in text
mode, psycopg3 in both.

=C2=A0 =C2=A0 In [1]: query =3D """
=C2=A0 =C2=A0 =C2=A0 =C2=A0...: with test as (
=C2=A0 =C2=A0 =C2=A0 =C2=A0...:=C2=A0 =C2=A0 =C2=A0select 1 as id, 'one= ' val
=C2=A0 =C2=A0 =C2=A0 =C2=A0...:=C2=A0 =C2=A0 =C2=A0union all
=C2=A0 =C2=A0 =C2=A0 =C2=A0...:=C2=A0 =C2=A0 =C2=A0select 1, 'one more&= #39;
=C2=A0 =C2=A0 =C2=A0 =C2=A0...:=C2=A0 =C2=A0 =C2=A0union all
=C2=A0 =C2=A0 =C2=A0 =C2=A0...:=C2=A0 =C2=A0 =C2=A0select 2, 'two'<= br> =C2=A0 =C2=A0 =C2=A0 =C2=A0...: )
=C2=A0 =C2=A0 =C2=A0 =C2=A0...: select array(
=C2=A0 =C2=A0 =C2=A0 =C2=A0...:=C2=A0 =C2=A0 =C2=A0select (id, array_agg(va= l))
=C2=A0 =C2=A0 =C2=A0 =C2=A0...:=C2=A0 =C2=A0 =C2=A0from test
=C2=A0 =C2=A0 =C2=A0 =C2=A0...:=C2=A0 =C2=A0 =C2=A0group by id
=C2=A0 =C2=A0 =C2=A0 =C2=A0...: )"""

=C2=A0 =C2=A0 In [2]: import psycopg3

=C2=A0 =C2=A0 In [3]: from psycopg3.pq import Format

=C2=A0 =C2=A0 In [4]: cnn =3D psycopg3.connect("")

=C2=A0 =C2=A0 In [5]: cnn.cursor().execute(query).fetchone()[0]
=C2=A0 =C2=A0 Out[5]: [('1', '{one,"one more"}'),= ('2', '{two}')]

=C2=A0 =C2=A0 In [6]: cnn.cursor(format=3DFormat.BINARY).execute(query).fet= chone()[0]
=C2=A0 =C2=A0 Out[6]: [(1, ['one', 'one more']), (2, ['= two'])]

Binary loading/dumping is not supported yet for all the data types,
but the plan is to cover all the builtins. Still not sure about the
interface to request text/binary results, or whether binary shouldn't be the default as opposed to text. There is still ground to cover, but
we are getting there.

-- Daniele
--00000000000038481905b3c9fba5--