Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions sqlalchemy_crud_plus/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ async def select_model(
load_strategies: LoadStrategies | None = None,
join_conditions: JoinConditions | None = None,
**kwargs: Any,
) -> Model | None:
) -> Sequence[Row[tuple[Model, ...]] | None] | Model | None:
"""
Query by primary key(s) with optional relationship loading and joins.

Expand Down Expand Up @@ -276,8 +276,7 @@ async def select_model(

if join_conditions:
if has_join_fill_result(join_conditions):
result = query.first()
return result[0] if result else None
return query.first()

return query.scalars().first()

Expand All @@ -289,7 +288,7 @@ async def select_model_by_column(
load_strategies: LoadStrategies | None = None,
join_conditions: JoinConditions | None = None,
**kwargs: Any,
) -> Model | None:
) -> Sequence[Row[tuple[Model, ...]] | None] | Model | None:
"""
Query by column with optional relationship loading and joins.

Expand All @@ -313,8 +312,7 @@ async def select_model_by_column(

if join_conditions:
if has_join_fill_result(join_conditions):
result = query.first()
return result[0] if result else None
return query.first()

return query.scalars().first()

Expand Down
5 changes: 4 additions & 1 deletion sqlalchemy_crud_plus/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import Any, Literal, TypeVar

from pydantic import BaseModel, ConfigDict, Field
from sqlalchemy import Alias, Table
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm.util import AliasedClass
from sqlalchemy.sql.base import ExecutableOption
Expand Down Expand Up @@ -56,7 +57,9 @@
class JoinConfig(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)

model: type[Model] | AliasedClass = Field(description='The target model or aliased class to join with')
model: type[Model] | AliasedClass | Alias | Table = Field(
description='The target model, aliased class, alias, or table to join with'
)
join_on: Any = Field(description='The join condition expression (e.g., model.id == other_model.id)')
join_type: JoinType = Field(default='left', description='The type of join to perform')
fill_result: bool = Field(default=False, description='Whether to populate this model to the query result')
Expand Down
5 changes: 4 additions & 1 deletion tests/test_no_relationship.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,10 @@ async def test_join_fill_result_single_model(
)

if result is not None:
assert isinstance(result, NoRelUser)
assert isinstance(result, (tuple, Row))
assert isinstance(result[0], NoRelUser)
if result[1]:
assert isinstance(result[1], NoRelProfile)


@pytest.mark.asyncio
Expand Down