Skip to content

Commit 6f644e3

Browse files
committed
fix: not working with different ids
1 parent 401cd65 commit 6f644e3

File tree

2 files changed

+63
-114
lines changed

2 files changed

+63
-114
lines changed

src/strawberry_sqlalchemy_mapper/loader.py

Lines changed: 23 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -75,130 +75,63 @@ async def load_fn(keys: List[Tuple]) -> List[Any]:
7575
)
7676
else:
7777
# Use another query when relationship uses a secondary table
78-
# *[remote[1] for remote in relationship.local_remote_pairs or []]
7978
self_model = relationship.parent.entity
8079

8180
self_model_key_label = relationship.local_remote_pairs[0][1].key
8281
related_model_key_label = relationship.local_remote_pairs[1][1].key
8382

8483
self_model_key = relationship.local_remote_pairs[0][0].key
85-
# breakpoint()
86-
# Gets the
84+
8785
remote_to_use = relationship.local_remote_pairs[0][1]
8886
query_keys = tuple([item[0] for item in keys])
89-
breakpoint()
87+
9088
query = (
91-
# select(related_model)
9289
select(
9390
label(self_model_key_label, getattr(
9491
self_model, self_model_key)),
9592
related_model
9693
)
97-
# .join(
98-
# related_model,
99-
# getattr(relationship.secondary.c, related_model_key_label) == getattr(
100-
# related_model, related_model_key)
101-
# )
102-
# .join(
103-
# relationship.secondary,
104-
# getattr(relationship.secondary.c, self_model_key_label) == getattr(
105-
# self_model, self_model_key)
106-
# )
107-
# .join(
108-
# relationship.secondary,
109-
# getattr(relationship.secondary.c, self_model_key_label) == getattr(
110-
# self_model, self_model_key)
111-
# )
11294
.join(
113-
relationship.secondary, # Join the secondary table
114-
getattr(relationship.secondary.c, related_model_key_label) == related_model.id # Match department_id
95+
relationship.secondary,
96+
getattr(relationship.secondary.c,
97+
related_model_key_label) == related_model.id
11598
)
11699
.join(
117-
self_model, # Join the Employee table
118-
getattr(relationship.secondary.c, self_model_key_label) == self_model.id # Match employee_id
100+
self_model,
101+
getattr(relationship.secondary.c,
102+
self_model_key_label) == self_model.id
119103
)
120104
.filter(
121105
remote_to_use.in_(query_keys)
122106
)
123107
)
124-
# query = (
125-
# # select(related_model)
126-
# select(
127-
# related_model,
128-
# label(self_model_key_label, getattr(self_model, self_model_key))
129-
# )
130-
# .join(relationship.secondary, relationship.secondaryjoin)
131-
# .filter(
132-
# remote_to_use.in_(query_keys)
133-
# )
134-
# )
135-
136-
# query = (
137-
# select(related_model)
138-
# .join(relationship.secondary, relationship.secondaryjoin)
139-
# .filter(
140-
# # emote_to_use.in_(keys)
141-
# tuple_(
142-
# *[remote[1] for remote in relationship.local_remote_pairs or []]
143-
# ).in_(keys)
144-
# )
145-
# )
146108

147109
if relationship.order_by:
148110
query = query.order_by(*relationship.order_by)
149111

150112
if relationship.secondary is not None:
151-
# We need get the self_model values too, so we need to remove the slqalchemy optimization that returns only the related_model values, this is needed because we use the keys var to match the related_model and the self_model
113+
# We need to retrieve values from both the self_model and related_model. To achieve this, we must disable the default SQLAlchemy optimization that returns only related_model values. This is necessary because we use the keys variable to match both related_model and self_model.
152114
rows = await self._scalars_all(query, disabled_optimization_to_secondary_tables=True)
153115
else:
154116
rows = await self._scalars_all(query)
155117

156118
def group_by_remote_key(row: Any) -> Tuple:
157-
if relationship.secondary is None:
158-
return tuple(
159-
[
160-
getattr(row, remote.key)
161-
for _, remote in relationship.local_remote_pairs or []
162-
if remote.key
163-
]
164-
)
165-
else:
166-
# Use another query when relationship uses a secondary table
167-
# breakpoint()
168-
related_model_table = relationship.entity.entity.__table__
169-
# breakpoint()
170-
# return tuple(
171-
# [
172-
# getattr(row, remote[0].key)
173-
# for remote in relationship.local_remote_pairs or []
174-
# if remote[0].key is not None and remote[0].table == related_model_table
175-
# ]
176-
# )
177-
result = []
178-
for remote in relationship.local_remote_pairs or []:
179-
if remote[0].key is not None and relationship.local_remote_pairs[1][0].table == related_model_table:
180-
result.extend(
181-
[
182-
183-
getattr(row, remote[0].key)
184-
185-
]
186-
)
187-
breakpoint()
188-
return tuple(
189-
[
190-
getattr(row, remote[0].key)
191-
for remote in relationship.local_remote_pairs or []
192-
if remote[0].key is not None and relationship.local_remote_pairs[1][0].table == related_model_table
193-
]
194-
)
119+
return tuple(
120+
[
121+
getattr(row, remote.key)
122+
for _, remote in relationship.local_remote_pairs or []
123+
if remote.key
124+
]
125+
)
195126

196127
grouped_keys: Mapping[Tuple, List[Any]] = defaultdict(list)
197-
breakpoint()
198-
for row in rows:
199-
grouped_keys[group_by_remote_key(row)].append(row)
200-
201-
breakpoint()
128+
if relationship.secondary is None:
129+
for row in rows:
130+
grouped_keys[group_by_remote_key(row)].append(row)
131+
else:
132+
for row in rows:
133+
grouped_keys[(row[0],)].append(row[1])
134+
202135
if relationship.uselist:
203136
return [grouped_keys[key] for key in keys]
204137
else:

tests/relay/test_connection.py

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,52 +1109,68 @@ async def employees(self) -> List[Employee]:
11091109
)
11101110
})
11111111
assert result.errors is None
1112-
breakpoint()
11131112
assert result.data == {
11141113
'employees': [
11151114
{
1116-
'id': 1,
1117-
'name': 'John',
1118-
'role': 'Developer',
1115+
'id': 5,
1116+
'name': 'Bill',
1117+
'role': 'Doctor',
11191118
'department': {
1120-
'edges': [
1121-
{
1122-
'node': {
1123-
'id': 1,
1124-
'name': 'Department Test',
1125-
'employees': {
1126-
'id': 1,
1127-
'name': 'John',
1128-
'role': 'Developer'
1129-
}
1119+
'edges': [
1120+
{
1121+
'node': {
1122+
'id': 10,
1123+
'name': 'Department Test 1',
1124+
'employees': {
1125+
'id': 5,
1126+
'name': 'Bill',
1127+
'role': 'Doctor'
11301128
}
11311129
}
1132-
]
1130+
}
1131+
]
11331132
}
11341133
},
11351134
{
1136-
'id': 2,
1137-
'name': 'Bill',
1138-
'role': 'Doctor',
1135+
'id': 1,
1136+
'name': 'John',
1137+
'role': 'Developer',
11391138
'department': {
1140-
'edges': []
1139+
'edges': [
1140+
{
1141+
'node': {
1142+
'id': 3,
1143+
'name': 'Department Test 2',
1144+
'employees': {
1145+
'id': 1,
1146+
'name': 'John',
1147+
'role': 'Developer'
1148+
}
1149+
}
1150+
}
1151+
]
11411152
}
11421153
},
11431154
{
1144-
'id': 3,
1155+
'id': 4,
11451156
'name': 'Maria',
11461157
'role': 'Teacher',
11471158
'department': {
1148-
'edges': []
1159+
'edges': []
11491160
}
11501161
}
11511162
]
11521163
}
11531164

1165+
1166+
11541167

11551168
# TODO
1156-
# test with different ids
1169+
# test with different ids # TESTED
1170+
# test with different ids and more than 1 value (use a employee with more than 2 departments)
11571171
# test with foreinkey different than id
1158-
# add a test on Loader to see
1159-
# Add test with query by secondary id]
1172+
# Add test with query by secondary id (use Department - Employee)
1173+
# Test with secondaryu table with more than 1 model
11601174
# try syncronous
1175+
1176+
# add a test on Loader to see

0 commit comments

Comments
 (0)