Skip to content
Open
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
17 changes: 15 additions & 2 deletions sqlmodel/ext/asyncio/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
overload,
)

from sqlalchemy import util
from sqlalchemy import TextClause, util
from sqlalchemy.engine.cursor import CursorResult
from sqlalchemy.engine.interfaces import _CoreAnyExecuteParams
from sqlalchemy.engine.result import Result, ScalarResult, TupleResult
Expand Down Expand Up @@ -66,12 +66,25 @@ async def exec(
_add_event: Any | None = None,
) -> CursorResult[Any]: ...

@overload
async def exec(
self,
statement: TextClause,
*,
params: Mapping[str, Any] | Sequence[Mapping[str, Any]] | None = None,
execution_options: Mapping[str, Any] = util.EMPTY_DICT,
bind_arguments: dict[str, Any] | None = None,
_parent_execute_state: Any | None = None,
_add_event: Any | None = None,
) -> CursorResult[Any]: ...

async def exec(
self,
statement: Select[_TSelectParam]
| SelectOfScalar[_TSelectParam]
| Executable[_TSelectParam]
| UpdateBase,
| UpdateBase
| TextClause,
*,
params: Mapping[str, Any] | Sequence[Mapping[str, Any]] | None = None,
execution_options: Mapping[str, Any] = util.EMPTY_DICT,
Expand Down
17 changes: 15 additions & 2 deletions sqlmodel/orm/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
overload,
)

from sqlalchemy import util
from sqlalchemy import TextClause, util
from sqlalchemy.engine.cursor import CursorResult
from sqlalchemy.engine.interfaces import _CoreAnyExecuteParams
from sqlalchemy.engine.result import Result, ScalarResult, TupleResult
Expand Down Expand Up @@ -59,12 +59,25 @@ def exec(
_add_event: Any | None = None,
) -> CursorResult[Any]: ...

@overload
def exec(
self,
statement: TextClause,
*,
params: Mapping[str, Any] | Sequence[Mapping[str, Any]] | None = None,
execution_options: Mapping[str, Any] = util.EMPTY_DICT,
bind_arguments: dict[str, Any] | None = None,
_parent_execute_state: Any | None = None,
_add_event: Any | None = None,
) -> CursorResult[Any]: ...

def exec(
self,
statement: Select[_TSelectParam]
| SelectOfScalar[_TSelectParam]
| Executable[_TSelectParam]
| UpdateBase,
| UpdateBase
| TextClause,
*,
params: Mapping[str, Any] | Sequence[Mapping[str, Any]] | None = None,
execution_options: Mapping[str, Any] = util.EMPTY_DICT,
Expand Down
47 changes: 47 additions & 0 deletions tests/test_exec_text.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from sqlmodel import Field, Session, SQLModel, create_engine, text


def test_select_using_text_statement(clear_sqlmodel):
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
secret_name: str
age: int | None = None

hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")

engine = create_engine("sqlite://")

SQLModel.metadata.create_all(engine)

with Session(engine) as session:
session.add(hero_1)
session.commit()
session.refresh(hero_1)

with Session(engine) as session:
res = session.exec(text("SELECT * FROM hero")).all()
assert len(res) == 1
assert res[0] == (1, "Deadpond", "Dive Wilson", None)


def test_insert_using_text_statement(clear_sqlmodel):
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
secret_name: str
age: int | None = None

engine = create_engine("sqlite://")

SQLModel.metadata.create_all(engine)

with Session(engine) as session:
res = session.exec(
text(
"INSERT INTO hero (name, secret_name) VALUES ('Deadpond', 'Dive Wilson')"
)
)
session.commit()

assert res.rowcount == 1