Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selecting array of enums breaks enum codecs #590

Closed
neumond opened this issue Jun 16, 2020 · 1 comment · Fixed by #662
Closed

Selecting array of enums breaks enum codecs #590

neumond opened this issue Jun 16, 2020 · 1 comment · Fixed by #662

Comments

@neumond
Copy link

neumond commented Jun 16, 2020

  • asyncpg version: 0.20.0
  • PostgreSQL version: 10
  • Do you use a PostgreSQL SaaS? If so, which? Can you reproduce
    the issue with a local PostgreSQL install?
    : local Postgres in docker
  • Python version: 3.7.4
  • Platform: Alpine Linux
  • Do you use pgbouncer?: no
  • Did you install asyncpg with pip?: yes

I've made script to reproduce the bug with explanations in comments:

import asyncio
from enum import Enum

import asyncpg


class Choice(Enum):
    rock = 'rock'
    paper = 'paper'
    scissors = 'scissors'


ACTIVATE_KRAKEN = True


async def main():
    conn = await asyncpg.connect('postgresql://postgres@localhost/test')

    # make test repeatable
    await conn.execute("DROP TABLE IF EXISTS game")
    await conn.execute("DROP TYPE IF EXISTS choice")

    await conn.execute(
        "CREATE TYPE choice AS ENUM ('rock', 'paper', 'scissors')")
    await conn.execute("""
        CREATE TABLE game(
            id serial PRIMARY KEY,
            ch choice
        )
    """)
    await conn.execute(
        "INSERT INTO game (ch) VALUES ('rock'), ('paper'), ('rock')")

    await conn.set_type_codec(
        'choice',
        encoder=lambda c: c.name,
        decoder=Choice,
        schema='public',
        format='text',
    )

    if not ACTIVATE_KRAKEN:
        # looks like we're preheating some internal cache here
        await conn.fetchval("SELECT 'paper'::choice")
        await conn.fetch("SELECT * FROM game WHERE ch = $1", Choice.paper)

    # moment when things do happen
    print(repr(
        await conn.fetchval("SELECT '{paper,rock}'::choice[]")
    ))
    # ['paper', 'rock']
    # ^ it returns reasonable result here, but if we do the following

    print(repr(
        await conn.fetchval("SELECT 'paper'::choice")
    ))
    print(repr(
        await conn.fetch("SELECT * FROM game WHERE ch = $1", Choice.paper)
    ))

    # if kraken was asleep, everything is fine:
    # <Choice.paper: 'paper'>
    # [<Record id=2 ch=<Choice.paper: 'paper'>>]

    # if kraken has been activated:
    # 'paper'
    # asyncpg.exceptions.DataError: invalid input for query argument $1:
    #   <Choice.paper: 'paper'> (expected str, got Choice)

asyncio.run(main())
elprans added a commit that referenced this issue Nov 26, 2020
Asyncpg currently erroneously prefers binary I/O for underlying type of
arrays effectively ignoring a possible custom text codec that might have
been configured on a type.

Fix this by removing the explicit preference for binary I/O, so that the
codec selection preference is now in the following order:

- custom binary codec
- custom text codec
- builtin binary codec
- builtin text codec

Fixes: #590
Reported-by: @neumond
@elprans
Copy link
Member

elprans commented Nov 26, 2020

Ouch, this is one gnarly kraken! Thanks for a detailed report. The fix is in #662.

elprans added a commit that referenced this issue Nov 29, 2020
Asyncpg currently erroneously prefers binary I/O for underlying type of
arrays effectively ignoring a possible custom text codec that might have
been configured on a type.

Fix this by removing the explicit preference for binary I/O, so that the
codec selection preference is now in the following order:

- custom binary codec
- custom text codec
- builtin binary codec
- builtin text codec

Fixes: #590
Reported-by: @neumond
elprans added a commit that referenced this issue Dec 2, 2020
Asyncpg currently erroneously prefers binary I/O for underlying type of
arrays effectively ignoring a possible custom text codec that might have
been configured on a type.

Fix this by removing the explicit preference for binary I/O, so that the
codec selection preference is now in the following order:

- custom binary codec
- custom text codec
- builtin binary codec
- builtin text codec

Fixes: #590
Reported-by: @neumond
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants