Skip to content

Commit 111027d

Browse files
Match the model attribute when checking a relation was prefetched (v0.19.4).
The prefetch check added in v0.19.3 reads the field name from the resolve info, which on the batching path knows only the GraphQL name. That is camelCase while the model attribute is not, so a prefetched relation whose name has more than one word was still reported as falling back to one query per parent. Seen on a real schema: productModelDefinitions.productFieldDefinitions ran no query of its own and was reported anyway. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 9434dbc commit 111027d

3 files changed

Lines changed: 14 additions & 4 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "strawberry-orm"
3-
version = "0.19.3"
3+
version = "0.19.4"
44
description = "Unified, backend-agnostic ORM abstraction for Strawberry GraphQL"
55
readme = "README.md"
66
license = "MIT"

src/strawberry_orm/batching.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from __future__ import annotations
1919

20+
import re
2021
from inspect import isawaitable
2122
from typing import TYPE_CHECKING, Any
2223

@@ -90,6 +91,11 @@ def stash_parents(execution_context: Any, info: Any, rows: Any) -> None:
9091
store[path_key(info)] = rows
9192

9293

94+
def _to_snake(name: str) -> str:
95+
"""GraphQL camelCase to the model's attribute spelling."""
96+
return re.sub(r"(?<=[a-z0-9])([A-Z])", r"_\1", name).lower()
97+
98+
9399
def _already_loaded(root: Any, info: Any) -> bool:
94100
"""True when this field's rows were loaded with the parent.
95101
@@ -103,8 +109,12 @@ def _already_loaded(root: Any, info: Any) -> bool:
103109
_tortoise_relation_prefetched,
104110
)
105111

106-
name = getattr(info, "python_name", None) or _path_field_names(info)[-1:]
107-
field_name = name if isinstance(name, str) else (name[0] if name else None)
112+
field_name = getattr(info, "python_name", None)
113+
if field_name is None:
114+
# A raw resolve info knows only the GraphQL name, which is camelCase
115+
# while the model attribute is not.
116+
path = _path_field_names(info)
117+
field_name = _to_snake(path[-1]) if path else None
108118
if field_name is None:
109119
return False
110120
for probe in (

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)