This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# engine/result.py
|
||||
# Copyright (C) 2005-2023 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -52,11 +52,11 @@ else:
|
||||
from sqlalchemy.cyextension.resultproxy import tuplegetter as tuplegetter
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from ..sql.schema import Column
|
||||
from ..sql.elements import SQLCoreOperations
|
||||
from ..sql.type_api import _ResultProcessorType
|
||||
|
||||
_KeyType = Union[str, "Column[Any]"]
|
||||
_KeyIndexType = Union[str, "Column[Any]", int]
|
||||
_KeyType = Union[str, "SQLCoreOperations[Any]"]
|
||||
_KeyIndexType = Union[_KeyType, int]
|
||||
|
||||
# is overridden in cursor using _CursorKeyMapRecType
|
||||
_KeyMapRecType = Any
|
||||
@@ -64,7 +64,7 @@ _KeyMapRecType = Any
|
||||
_KeyMapType = Mapping[_KeyType, _KeyMapRecType]
|
||||
|
||||
|
||||
_RowData = Union[Row, RowMapping, Any]
|
||||
_RowData = Union[Row[Any], RowMapping, Any]
|
||||
"""A generic form of "row" that accommodates for the different kinds of
|
||||
"rows" that different result objects return, including row, row mapping, and
|
||||
scalar values"""
|
||||
@@ -82,7 +82,7 @@ across all the result types
|
||||
|
||||
"""
|
||||
|
||||
_InterimSupportsScalarsRowType = Union[Row, Any]
|
||||
_InterimSupportsScalarsRowType = Union[Row[Any], Any]
|
||||
|
||||
_ProcessorsType = Sequence[Optional["_ResultProcessorType[Any]"]]
|
||||
_TupleGetterType = Callable[[Sequence[Any]], Sequence[Any]]
|
||||
@@ -116,8 +116,7 @@ class ResultMetaData:
|
||||
@overload
|
||||
def _key_fallback(
|
||||
self, key: Any, err: Optional[Exception], raiseerr: Literal[True] = ...
|
||||
) -> NoReturn:
|
||||
...
|
||||
) -> NoReturn: ...
|
||||
|
||||
@overload
|
||||
def _key_fallback(
|
||||
@@ -125,14 +124,12 @@ class ResultMetaData:
|
||||
key: Any,
|
||||
err: Optional[Exception],
|
||||
raiseerr: Literal[False] = ...,
|
||||
) -> None:
|
||||
...
|
||||
) -> None: ...
|
||||
|
||||
@overload
|
||||
def _key_fallback(
|
||||
self, key: Any, err: Optional[Exception], raiseerr: bool = ...
|
||||
) -> Optional[NoReturn]:
|
||||
...
|
||||
) -> Optional[NoReturn]: ...
|
||||
|
||||
def _key_fallback(
|
||||
self, key: Any, err: Optional[Exception], raiseerr: bool = True
|
||||
@@ -329,9 +326,6 @@ class SimpleResultMetaData(ResultMetaData):
|
||||
_tuplefilter=_tuplefilter,
|
||||
)
|
||||
|
||||
def _contains(self, value: Any, row: Row[Any]) -> bool:
|
||||
return value in row._data
|
||||
|
||||
def _index_for_key(self, key: Any, raiseerr: bool = True) -> int:
|
||||
if int in key.__class__.__mro__:
|
||||
key = self._keys[key]
|
||||
@@ -728,14 +722,21 @@ class ResultInternal(InPlaceGenerative, Generic[_R]):
|
||||
|
||||
return manyrows
|
||||
|
||||
@overload
|
||||
def _only_one_row(
|
||||
self: ResultInternal[Row[Any]],
|
||||
raise_for_second_row: bool,
|
||||
raise_for_none: bool,
|
||||
scalar: Literal[True],
|
||||
) -> Any: ...
|
||||
|
||||
@overload
|
||||
def _only_one_row(
|
||||
self,
|
||||
raise_for_second_row: bool,
|
||||
raise_for_none: Literal[True],
|
||||
scalar: bool,
|
||||
) -> _R:
|
||||
...
|
||||
) -> _R: ...
|
||||
|
||||
@overload
|
||||
def _only_one_row(
|
||||
@@ -743,8 +744,7 @@ class ResultInternal(InPlaceGenerative, Generic[_R]):
|
||||
raise_for_second_row: bool,
|
||||
raise_for_none: bool,
|
||||
scalar: bool,
|
||||
) -> Optional[_R]:
|
||||
...
|
||||
) -> Optional[_R]: ...
|
||||
|
||||
def _only_one_row(
|
||||
self,
|
||||
@@ -817,7 +817,6 @@ class ResultInternal(InPlaceGenerative, Generic[_R]):
|
||||
"was required"
|
||||
)
|
||||
else:
|
||||
next_row = _NO_ROW
|
||||
# if we checked for second row then that would have
|
||||
# closed us :)
|
||||
self._soft_close(hard=True)
|
||||
@@ -1107,17 +1106,15 @@ class Result(_WithKeys, ResultInternal[Row[_TP]]):
|
||||
statement = select(table.c.x, table.c.y, table.c.z)
|
||||
result = connection.execute(statement)
|
||||
|
||||
for z, y in result.columns('z', 'y'):
|
||||
# ...
|
||||
|
||||
for z, y in result.columns("z", "y"):
|
||||
...
|
||||
|
||||
Example of using the column objects from the statement itself::
|
||||
|
||||
for z, y in result.columns(
|
||||
statement.selected_columns.c.z,
|
||||
statement.selected_columns.c.y
|
||||
statement.selected_columns.c.z, statement.selected_columns.c.y
|
||||
):
|
||||
# ...
|
||||
...
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
@@ -1132,18 +1129,15 @@ class Result(_WithKeys, ResultInternal[Row[_TP]]):
|
||||
return self._column_slices(col_expressions)
|
||||
|
||||
@overload
|
||||
def scalars(self: Result[Tuple[_T]]) -> ScalarResult[_T]:
|
||||
...
|
||||
def scalars(self: Result[Tuple[_T]]) -> ScalarResult[_T]: ...
|
||||
|
||||
@overload
|
||||
def scalars(
|
||||
self: Result[Tuple[_T]], index: Literal[0]
|
||||
) -> ScalarResult[_T]:
|
||||
...
|
||||
) -> ScalarResult[_T]: ...
|
||||
|
||||
@overload
|
||||
def scalars(self, index: _KeyIndexType = 0) -> ScalarResult[Any]:
|
||||
...
|
||||
def scalars(self, index: _KeyIndexType = 0) -> ScalarResult[Any]: ...
|
||||
|
||||
def scalars(self, index: _KeyIndexType = 0) -> ScalarResult[Any]:
|
||||
"""Return a :class:`_engine.ScalarResult` filtering object which
|
||||
@@ -1352,7 +1346,7 @@ class Result(_WithKeys, ResultInternal[Row[_TP]]):
|
||||
def fetchmany(self, size: Optional[int] = None) -> Sequence[Row[_TP]]:
|
||||
"""Fetch many rows.
|
||||
|
||||
When all rows are exhausted, returns an empty list.
|
||||
When all rows are exhausted, returns an empty sequence.
|
||||
|
||||
This method is provided for backwards compatibility with
|
||||
SQLAlchemy 1.x.x.
|
||||
@@ -1360,7 +1354,7 @@ class Result(_WithKeys, ResultInternal[Row[_TP]]):
|
||||
To fetch rows in groups, use the :meth:`_engine.Result.partitions`
|
||||
method.
|
||||
|
||||
:return: a list of :class:`_engine.Row` objects.
|
||||
:return: a sequence of :class:`_engine.Row` objects.
|
||||
|
||||
.. seealso::
|
||||
|
||||
@@ -1371,14 +1365,14 @@ class Result(_WithKeys, ResultInternal[Row[_TP]]):
|
||||
return self._manyrow_getter(self, size)
|
||||
|
||||
def all(self) -> Sequence[Row[_TP]]:
|
||||
"""Return all rows in a list.
|
||||
"""Return all rows in a sequence.
|
||||
|
||||
Closes the result set after invocation. Subsequent invocations
|
||||
will return an empty list.
|
||||
will return an empty sequence.
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
:return: a list of :class:`_engine.Row` objects.
|
||||
:return: a sequence of :class:`_engine.Row` objects.
|
||||
|
||||
.. seealso::
|
||||
|
||||
@@ -1454,22 +1448,20 @@ class Result(_WithKeys, ResultInternal[Row[_TP]]):
|
||||
)
|
||||
|
||||
@overload
|
||||
def scalar_one(self: Result[Tuple[_T]]) -> _T:
|
||||
...
|
||||
def scalar_one(self: Result[Tuple[_T]]) -> _T: ...
|
||||
|
||||
@overload
|
||||
def scalar_one(self) -> Any:
|
||||
...
|
||||
def scalar_one(self) -> Any: ...
|
||||
|
||||
def scalar_one(self) -> Any:
|
||||
"""Return exactly one scalar result or raise an exception.
|
||||
|
||||
This is equivalent to calling :meth:`_engine.Result.scalars` and
|
||||
then :meth:`_engine.Result.one`.
|
||||
then :meth:`_engine.ScalarResult.one`.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:meth:`_engine.Result.one`
|
||||
:meth:`_engine.ScalarResult.one`
|
||||
|
||||
:meth:`_engine.Result.scalars`
|
||||
|
||||
@@ -1479,22 +1471,20 @@ class Result(_WithKeys, ResultInternal[Row[_TP]]):
|
||||
)
|
||||
|
||||
@overload
|
||||
def scalar_one_or_none(self: Result[Tuple[_T]]) -> Optional[_T]:
|
||||
...
|
||||
def scalar_one_or_none(self: Result[Tuple[_T]]) -> Optional[_T]: ...
|
||||
|
||||
@overload
|
||||
def scalar_one_or_none(self) -> Optional[Any]:
|
||||
...
|
||||
def scalar_one_or_none(self) -> Optional[Any]: ...
|
||||
|
||||
def scalar_one_or_none(self) -> Optional[Any]:
|
||||
"""Return exactly one scalar result or ``None``.
|
||||
|
||||
This is equivalent to calling :meth:`_engine.Result.scalars` and
|
||||
then :meth:`_engine.Result.one_or_none`.
|
||||
then :meth:`_engine.ScalarResult.one_or_none`.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:meth:`_engine.Result.one_or_none`
|
||||
:meth:`_engine.ScalarResult.one_or_none`
|
||||
|
||||
:meth:`_engine.Result.scalars`
|
||||
|
||||
@@ -1506,8 +1496,8 @@ class Result(_WithKeys, ResultInternal[Row[_TP]]):
|
||||
def one(self) -> Row[_TP]:
|
||||
"""Return exactly one row or raise an exception.
|
||||
|
||||
Raises :class:`.NoResultFound` if the result returns no
|
||||
rows, or :class:`.MultipleResultsFound` if multiple rows
|
||||
Raises :class:`_exc.NoResultFound` if the result returns no
|
||||
rows, or :class:`_exc.MultipleResultsFound` if multiple rows
|
||||
would be returned.
|
||||
|
||||
.. note:: This method returns one **row**, e.g. tuple, by default.
|
||||
@@ -1537,12 +1527,10 @@ class Result(_WithKeys, ResultInternal[Row[_TP]]):
|
||||
)
|
||||
|
||||
@overload
|
||||
def scalar(self: Result[Tuple[_T]]) -> Optional[_T]:
|
||||
...
|
||||
def scalar(self: Result[Tuple[_T]]) -> Optional[_T]: ...
|
||||
|
||||
@overload
|
||||
def scalar(self) -> Any:
|
||||
...
|
||||
def scalar(self) -> Any: ...
|
||||
|
||||
def scalar(self) -> Any:
|
||||
"""Fetch the first column of the first row, and close the result set.
|
||||
@@ -1776,7 +1764,7 @@ class ScalarResult(FilterResult[_R]):
|
||||
return self._manyrow_getter(self, size)
|
||||
|
||||
def all(self) -> Sequence[_R]:
|
||||
"""Return all scalar values in a list.
|
||||
"""Return all scalar values in a sequence.
|
||||
|
||||
Equivalent to :meth:`_engine.Result.all` except that
|
||||
scalar values, rather than :class:`_engine.Row` objects,
|
||||
@@ -1880,7 +1868,7 @@ class TupleResult(FilterResult[_R], util.TypingOnly):
|
||||
...
|
||||
|
||||
def all(self) -> Sequence[_R]: # noqa: A001
|
||||
"""Return all scalar values in a list.
|
||||
"""Return all scalar values in a sequence.
|
||||
|
||||
Equivalent to :meth:`_engine.Result.all` except that
|
||||
tuple values, rather than :class:`_engine.Row` objects,
|
||||
@@ -1889,11 +1877,9 @@ class TupleResult(FilterResult[_R], util.TypingOnly):
|
||||
"""
|
||||
...
|
||||
|
||||
def __iter__(self) -> Iterator[_R]:
|
||||
...
|
||||
def __iter__(self) -> Iterator[_R]: ...
|
||||
|
||||
def __next__(self) -> _R:
|
||||
...
|
||||
def __next__(self) -> _R: ...
|
||||
|
||||
def first(self) -> Optional[_R]:
|
||||
"""Fetch the first object or ``None`` if no object is present.
|
||||
@@ -1927,22 +1913,20 @@ class TupleResult(FilterResult[_R], util.TypingOnly):
|
||||
...
|
||||
|
||||
@overload
|
||||
def scalar_one(self: TupleResult[Tuple[_T]]) -> _T:
|
||||
...
|
||||
def scalar_one(self: TupleResult[Tuple[_T]]) -> _T: ...
|
||||
|
||||
@overload
|
||||
def scalar_one(self) -> Any:
|
||||
...
|
||||
def scalar_one(self) -> Any: ...
|
||||
|
||||
def scalar_one(self) -> Any:
|
||||
"""Return exactly one scalar result or raise an exception.
|
||||
|
||||
This is equivalent to calling :meth:`_engine.Result.scalars`
|
||||
and then :meth:`_engine.Result.one`.
|
||||
and then :meth:`_engine.ScalarResult.one`.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:meth:`_engine.Result.one`
|
||||
:meth:`_engine.ScalarResult.one`
|
||||
|
||||
:meth:`_engine.Result.scalars`
|
||||
|
||||
@@ -1950,22 +1934,22 @@ class TupleResult(FilterResult[_R], util.TypingOnly):
|
||||
...
|
||||
|
||||
@overload
|
||||
def scalar_one_or_none(self: TupleResult[Tuple[_T]]) -> Optional[_T]:
|
||||
...
|
||||
def scalar_one_or_none(
|
||||
self: TupleResult[Tuple[_T]],
|
||||
) -> Optional[_T]: ...
|
||||
|
||||
@overload
|
||||
def scalar_one_or_none(self) -> Optional[Any]:
|
||||
...
|
||||
def scalar_one_or_none(self) -> Optional[Any]: ...
|
||||
|
||||
def scalar_one_or_none(self) -> Optional[Any]:
|
||||
"""Return exactly one or no scalar result.
|
||||
|
||||
This is equivalent to calling :meth:`_engine.Result.scalars`
|
||||
and then :meth:`_engine.Result.one_or_none`.
|
||||
and then :meth:`_engine.ScalarResult.one_or_none`.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:meth:`_engine.Result.one_or_none`
|
||||
:meth:`_engine.ScalarResult.one_or_none`
|
||||
|
||||
:meth:`_engine.Result.scalars`
|
||||
|
||||
@@ -1973,12 +1957,10 @@ class TupleResult(FilterResult[_R], util.TypingOnly):
|
||||
...
|
||||
|
||||
@overload
|
||||
def scalar(self: TupleResult[Tuple[_T]]) -> Optional[_T]:
|
||||
...
|
||||
def scalar(self: TupleResult[Tuple[_T]]) -> Optional[_T]: ...
|
||||
|
||||
@overload
|
||||
def scalar(self) -> Any:
|
||||
...
|
||||
def scalar(self) -> Any: ...
|
||||
|
||||
def scalar(self) -> Any:
|
||||
"""Fetch the first column of the first row, and close the result
|
||||
@@ -2031,7 +2013,7 @@ class MappingResult(_WithKeys, FilterResult[RowMapping]):
|
||||
return self
|
||||
|
||||
def columns(self, *col_expressions: _KeyIndexType) -> Self:
|
||||
r"""Establish the columns that should be returned in each row."""
|
||||
"""Establish the columns that should be returned in each row."""
|
||||
return self._column_slices(col_expressions)
|
||||
|
||||
def partitions(
|
||||
@@ -2086,7 +2068,7 @@ class MappingResult(_WithKeys, FilterResult[RowMapping]):
|
||||
return self._manyrow_getter(self, size)
|
||||
|
||||
def all(self) -> Sequence[RowMapping]:
|
||||
"""Return all scalar values in a list.
|
||||
"""Return all scalar values in a sequence.
|
||||
|
||||
Equivalent to :meth:`_engine.Result.all` except that
|
||||
:class:`_engine.RowMapping` values, rather than :class:`_engine.Row`
|
||||
|
||||
Reference in New Issue
Block a user