Skip to content

Selecting array of enums breaks enum codecs #590

Closed
@neumond

Description

@neumond
  • 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())

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions