Skip to content

Commit ae4f87c

Browse files
authored
fix: keep converting tuples to strings for composite primary keys in relay ID field (#399)
1 parent c927ada commit ae4f87c

File tree

3 files changed

+59
-1
lines changed

3 files changed

+59
-1
lines changed

graphene_sqlalchemy/tests/models.py

+7
Original file line numberDiff line numberDiff line change
@@ -436,3 +436,10 @@ class CustomColumnModel(Base):
436436

437437
id = Column(Integer(), primary_key=True)
438438
custom_col = Column(CustomIntegerColumn)
439+
440+
441+
class CompositePrimaryKeyTestModel(Base):
442+
__tablename__ = "compositekeytestmodel"
443+
444+
first_name = Column(String(30), primary_key=True)
445+
last_name = Column(String(30), primary_key=True)

graphene_sqlalchemy/tests/test_types.py

+51
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from graphene import (
1111
Boolean,
12+
DefaultGlobalIDType,
1213
Dynamic,
1314
Field,
1415
Float,
@@ -42,6 +43,7 @@
4243
from .models import (
4344
Article,
4445
CompositeFullName,
46+
CompositePrimaryKeyTestModel,
4547
Employee,
4648
NonAbstractPerson,
4749
Person,
@@ -513,6 +515,55 @@ async def resolve_reporter(self, _info):
513515
# Test Custom SQLAlchemyObjectType Implementation
514516

515517

518+
@pytest.mark.asyncio
519+
async def test_composite_id_resolver(session):
520+
"""Test that the correct resolver functions are called"""
521+
522+
composite_reporter = CompositePrimaryKeyTestModel(
523+
first_name="graphql", last_name="foundation"
524+
)
525+
526+
session.add(composite_reporter)
527+
await eventually_await_session(session, "commit")
528+
529+
class CompositePrimaryKeyTestModelType(SQLAlchemyObjectType):
530+
class Meta:
531+
model = CompositePrimaryKeyTestModel
532+
interfaces = (Node,)
533+
534+
class Query(ObjectType):
535+
composite_reporter = Field(CompositePrimaryKeyTestModelType)
536+
537+
async def resolve_composite_reporter(self, _info):
538+
session = utils.get_session(_info.context)
539+
if SQL_VERSION_HIGHER_EQUAL_THAN_1_4 and isinstance(session, AsyncSession):
540+
return (
541+
(await session.scalars(select(CompositePrimaryKeyTestModel)))
542+
.unique()
543+
.first()
544+
)
545+
return session.query(CompositePrimaryKeyTestModel).first()
546+
547+
schema = Schema(query=Query)
548+
result = await schema.execute_async(
549+
"""
550+
query {
551+
compositeReporter {
552+
id
553+
firstName
554+
lastName
555+
}
556+
}
557+
""",
558+
context_value={"session": session},
559+
)
560+
561+
assert not result.errors
562+
assert result.data["compositeReporter"]["id"] == DefaultGlobalIDType.to_global_id(
563+
CompositePrimaryKeyTestModelType, str(("graphql", "foundation"))
564+
)
565+
566+
516567
def test_custom_objecttype_registered():
517568
class CustomSQLAlchemyObjectType(SQLAlchemyObjectType):
518569
class Meta:

graphene_sqlalchemy/types.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ async def get_result() -> Any:
577577
def resolve_id(self, info):
578578
# graphene_type = info.parent_type.graphene_type
579579
keys = self.__mapper__.primary_key_from_instance(self)
580-
return tuple(keys) if len(keys) > 1 else keys[0]
580+
return str(tuple(keys)) if len(keys) > 1 else keys[0]
581581

582582
@classmethod
583583
def enum_for_field(cls, field_name):

0 commit comments

Comments
 (0)