hiku
hiku copied to clipboard
FieldsQuery does not work for aiopg + sqlalchemy >= 1.4
aiopg does not compatible with sqlalchemy >= 1.4.
Error occurs when we pass into select
same field twice:
File "/Users/max/code/evo/hiku/__pypackages__/3.11/lib/aiopg/sa/result.py", line 252, in __init__
self._init_metadata()
File "/Users/max/code/evo/hiku/__pypackages__/3.11/lib/aiopg/sa/result.py", line 304, in _init_metadata
self._metadata = ResultMetaData(self, cursor_description)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/max/code/evo/hiku/__pypackages__/3.11/lib/aiopg/sa/result.py", line 97, in __init__
map_type, map_column_name = self.result_map(result_proxy._result_map)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/max/code/evo/hiku/__pypackages__/3.11/lib/aiopg/sa/result.py", line 174, in result_map
priority_name = getattr(elem[2][0], "key", None) or name
~~~~~~~^^^
IndexError: tuple index out of range
Reproducible example:
pip install aiopg=1.4.0 sqlalchemy==1.4.48
import aiopg.sa
import sqlalchemy
from sqlalchemy.types import Integer, Unicode
from sqlalchemy.schema import MetaData, Table, Column, ForeignKey
metadata = MetaData()
foo_table = Table(
"foo",
metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("name", Unicode),
Column("count", Integer),
Column("bar_id", ForeignKey("bar.id")),
)
pg_dsn = f'postgresql://postgres:postgres@localhost:5432/postgres'
db_dsn = 'postgresql://postgres:postgres@localhost:5432/mydb'
def setup_db(db_engine):
metadata.create_all(db_engine)
for r in [
{"name": "foo1", "count": 5, "bar_id": 1},
]:
db_engine.execute(foo_table.insert(), r)
db_engine = sqlalchemy.create_engine(db_dsn)
setup_db(db_engine)
db_engine.dispose()
sa_engine = await aiopg.sa.create_engine(db_dsn, minsize=0)
ids = [3,2,1]
fields_ = ['name', 'count', 'bar_id', 'bar_id']. # <-- HERE bar declared twice
columns = [foo_table.c[f] for f in fields_]
(primary_key,) = foo_table.primary_key
expr = (
sqlalchemy.select([primary_key] + columns)
.select_from(foo_table)
.where(primary_key == sqlalchemy.any_(ids))
)
async with sa_engine.acquire() as connection:
res = await connection.execute(expr)
Patch that fixes problem:
from aiopg.sa.result import ResultMetaData
def result_map(self: Any, data_map: dict) -> Tuple[dict, dict]:
data_map = data_map or {}
map_type = {}
map_column_name = {}
for elem in data_map:
name = elem[0]
try:
priority_name = getattr(elem[2][0], "key", None) or name
except IndexError:
map_column_name[name] = name
else:
map_column_name[name] = priority_name
map_type[name] = elem[3] # type column
return map_type, map_column_name
ResultMetaData.result_map = result_map