Skip to content
This repository was archived by the owner on Aug 19, 2025. It is now read-only.

Commit 94f8281

Browse files
Merge pull request #59 from ricardomomm/improve-row-data-retrieval
fix issue with duplicate column names
2 parents f69ed5e + 4481436 commit 94f8281

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

databases/backends/postgres.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from sqlalchemy.dialects.postgresql import pypostgresql
77
from sqlalchemy.engine.interfaces import Dialect
88
from sqlalchemy.sql import ClauseElement
9+
from sqlalchemy.sql.schema import Column
910

1011
from databases.core import DatabaseURL
1112
from databases.interfaces import ConnectionBackend, DatabaseBackend, TransactionBackend
@@ -73,9 +74,16 @@ def __init__(self, row: tuple, result_columns: tuple, dialect: Dialect) -> None:
7374
column_name: (idx, datatype)
7475
for idx, (column_name, _, _, datatype) in enumerate(self._result_columns)
7576
}
77+
self._column_map_full = {
78+
str(column[0]): (idx, datatype)
79+
for idx, (_, _, column, datatype) in enumerate(self._result_columns)
80+
}
7681

77-
def __getitem__(self, key: str) -> typing.Any:
78-
idx, datatype = self._column_map[key]
82+
def __getitem__(self, key: typing.Any) -> typing.Any:
83+
if type(key) is Column:
84+
idx, datatype = self._column_map_full[str(key)]
85+
else:
86+
idx, datatype = self._column_map[key]
7987
raw = self._row[idx]
8088
try:
8189
processor = _result_processors[datatype]

tests/test_databases.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,37 @@ async def test_results_support_mapping_interface(database_url):
178178
assert results_as_dicts[0]["completed"] == True
179179

180180

181+
@pytest.mark.parametrize("database_url", DATABASE_URLS)
182+
@async_adapter
183+
async def test_results_support_column_reference(database_url):
184+
"""
185+
Casting results to a dict should work, since the interface defines them
186+
as supporting the mapping interface.
187+
"""
188+
async with Database(database_url) as database:
189+
async with database.transaction(force_rollback=True):
190+
now = datetime.datetime.now().replace(microsecond=0)
191+
today = datetime.date.today()
192+
193+
# execute()
194+
query = articles.insert()
195+
values = {"title": "Hello, world Article", "published": now}
196+
await database.execute(query, values)
197+
198+
query = custom_date.insert()
199+
values = {"title": "Hello, world Custom", "published": today}
200+
await database.execute(query, values)
201+
202+
# fetch_all()
203+
query = sqlalchemy.select([articles, custom_date])
204+
results = await database.fetch_all(query=query)
205+
assert len(results) == 1
206+
assert results[0][articles.c.title] == "Hello, world Article"
207+
assert results[0][articles.c.published] == now
208+
assert results[0][custom_date.c.title] == "Hello, world Custom"
209+
assert results[0][custom_date.c.published] == today
210+
211+
181212
@pytest.mark.parametrize("database_url", DATABASE_URLS)
182213
@async_adapter
183214
async def test_fetch_one_returning_no_results(database_url):

0 commit comments

Comments
 (0)