CanopyTax/asyncpgsa

process_result_value callback for column type is not handled

Opened this issue · 1 comments

I need TypeDecorator for my data column, it is handled by SQLAlchemy + psycopg2 correctly. Is it possible to make it work with asyncpgsa?

import asyncio
from datetime import datetime

from asyncpgsa import PG
from pytz import timezone
from sqlalchemy import (
    Column, DateTime, Integer, MetaData, Table, TypeDecorator, create_engine
)


DB_URL = 'postgresql://user:hackme@0.0.0.0/db'


class DateTime_(TypeDecorator):
    impl = DateTime

    def __init__(self):
        TypeDecorator.__init__(self, timezone=True)

    def process_bind_param(self, value, dialect):
        if value is not None:
            return datetime.fromtimestamp(value, timezone('UTC'))

    def process_result_value(self, value, dialect):
        return int(value.timestamp())


metadata = MetaData()
example_table = Table('example', metadata,
                      Column('id', Integer, primary_key=True),
                      Column('some_date', DateTime_))

engine = create_engine(DB_URL)

# Create table & add row
metadata.create_all(engine)
engine.execute(example_table.insert().values({
    'some_date': int(datetime.now().timestamp())
}))

# psycopg2 with sqlalchemy handles process_result_value correctly
rows = engine.execute(example_table.select()).fetchall()
assert isinstance(rows[0]['some_date'], int)


# asyncpgsa does not handle process_result_value callback
async def main():
    db = PG()
    await db.init(DB_URL)
    rows = await db.fetch(example_table.select())
    assert isinstance(rows[0]['some_date'], datetime)  # True
    assert isinstance(rows[0]['some_date'], int)  # False!


asyncio.run(main())

Perhaps such callbacks should be called in SAConnection.execute?

This sounds awesome. It sounds doable. I dont have much time to work in this currently. Would you be willing to start a pull request with the changes? Would be happy to guide you in the right direction if needed.