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

Custom converter support in select() #346

Open
lambda-xyz opened this issue May 16, 2018 · 2 comments
Open

Custom converter support in select() #346

lambda-xyz opened this issue May 16, 2018 · 2 comments

Comments

@lambda-xyz
Copy link

It's easy to add a new type to entity attributes with custom Converter but I would like to be able to filter query in select using this new type.

Here is a small example:

from enum import Enum
from pony import orm
from pony.orm import Database, Required, db_session, select
from pony.orm.dbapiprovider import StrConverter

class EnumConverter(StrConverter):
    def validate(self, val, obj=None):
        if not isinstance(val, Enum):
            raise ValueError('Must be an Enum. Got {}'.format(val))
        return val

    def py2sql(self, val):
        return val.name

    def sql2py(self, val):
        return self.py_type[val]

    def sql_type(self):
        return 'VARCHAR(30)'

db = Database('sqlite', ':memory:', create_db=True)
db.provider.converter_classes.append((Enum, EnumConverter))


class ProcState(Enum):
    idle = 0
    running = 1
    error = 2


class Process(db.Entity):
    name = Required(str)
    state = Required(ProcState)
    pid = Required(int)


db.generate_mapping(create_tables=True)

with db_session:
    Process(name='chromium', state=ProcState.idle, pid=12)
    Process(name='firefox', state=ProcState.error, pid=15)
    Process(name='surf', state=ProcState.running, pid=19)
    Process(name='epiphany', state=ProcState.running, pid=22)

Actually the only way I found is to use raw_sql like in req3:

with db_session:
    # doesn't work: TypeError
    # req1 = select(p for p in Process if p.state == ProcState.running)
    # doesn't work: TypeError
    # req2 = select(p for p in Process if getattr(p, 'state') == ProcState.running)
    # works!
    req3 = select(p for p in Process if orm.raw_sql('p.state == "running"'))

    req3[:].show(500)

Is there any possibility to use select using req1 syntax?

@GammaGames
Copy link

I would at least like Enum support (hopefully this can get completed and merged) because the reason I found this issue was to try and select based on an enum.

@pykler
Copy link

pykler commented Nov 4, 2020

Adding an

class ProcState(Enum):
...
    def __str__(self):
        return self.name

Allows you to use the enum in queries. It is a hack but it works

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

No branches or pull requests

3 participants