API refactor
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-10-07 16:25:52 +09:00
parent 76d0d86211
commit 91c7e04474
1171 changed files with 81940 additions and 44117 deletions

View File

@@ -1,5 +1,5 @@
# sql/dml.py
# Copyright (C) 2009-2023 the SQLAlchemy authors and contributors
# Copyright (C) 2009-2025 the SQLAlchemy authors and contributors
# <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
@@ -23,6 +23,7 @@ from typing import NoReturn
from typing import Optional
from typing import overload
from typing import Sequence
from typing import Set
from typing import Tuple
from typing import Type
from typing import TYPE_CHECKING
@@ -42,6 +43,7 @@ from .base import _from_objects
from .base import _generative
from .base import _select_iterables
from .base import ColumnCollection
from .base import ColumnSet
from .base import CompileState
from .base import DialectKWArgs
from .base import Executable
@@ -91,14 +93,11 @@ if TYPE_CHECKING:
from .selectable import Select
from .selectable import Selectable
def isupdate(dml: DMLState) -> TypeGuard[UpdateDMLState]:
...
def isupdate(dml: DMLState) -> TypeGuard[UpdateDMLState]: ...
def isdelete(dml: DMLState) -> TypeGuard[DeleteDMLState]:
...
def isdelete(dml: DMLState) -> TypeGuard[DeleteDMLState]: ...
def isinsert(dml: DMLState) -> TypeGuard[InsertDMLState]:
...
def isinsert(dml: DMLState) -> TypeGuard[InsertDMLState]: ...
else:
isupdate = operator.attrgetter("isupdate")
@@ -137,9 +136,11 @@ class DMLState(CompileState):
@classmethod
def get_entity_description(cls, statement: UpdateBase) -> Dict[str, Any]:
return {
"name": statement.table.name
if is_named_from_clause(statement.table)
else None,
"name": (
statement.table.name
if is_named_from_clause(statement.table)
else None
),
"table": statement.table,
}
@@ -163,8 +164,7 @@ class DMLState(CompileState):
if TYPE_CHECKING:
@classmethod
def get_plugin_class(cls, statement: Executable) -> Type[DMLState]:
...
def get_plugin_class(cls, statement: Executable) -> Type[DMLState]: ...
@classmethod
def _get_multi_crud_kv_pairs(
@@ -190,13 +190,15 @@ class DMLState(CompileState):
return [
(
coercions.expect(roles.DMLColumnRole, k),
v
if not needs_to_be_cacheable
else coercions.expect(
roles.ExpressionElementRole,
v,
type_=NullType(),
is_crud=True,
(
v
if not needs_to_be_cacheable
else coercions.expect(
roles.ExpressionElementRole,
v,
type_=NullType(),
is_crud=True,
)
),
)
for k, v in kv_iterator
@@ -306,12 +308,14 @@ class InsertDMLState(DMLState):
def _process_multi_values(self, statement: ValuesBase) -> None:
for parameters in statement._multi_values:
multi_parameters: List[MutableMapping[_DMLColumnElement, Any]] = [
{
c.key: value
for c, value in zip(statement.table.c, parameter_set)
}
if isinstance(parameter_set, collections_abc.Sequence)
else parameter_set
(
{
c.key: value
for c, value in zip(statement.table.c, parameter_set)
}
if isinstance(parameter_set, collections_abc.Sequence)
else parameter_set
)
for parameter_set in parameters
]
@@ -396,9 +400,9 @@ class UpdateBase(
__visit_name__ = "update_base"
_hints: util.immutabledict[
Tuple[_DMLTableElement, str], str
] = util.EMPTY_DICT
_hints: util.immutabledict[Tuple[_DMLTableElement, str], str] = (
util.EMPTY_DICT
)
named_with_column = False
_label_style: SelectLabelStyle = (
@@ -407,19 +411,25 @@ class UpdateBase(
table: _DMLTableElement
_return_defaults = False
_return_defaults_columns: Optional[
Tuple[_ColumnsClauseElement, ...]
] = None
_return_defaults_columns: Optional[Tuple[_ColumnsClauseElement, ...]] = (
None
)
_supplemental_returning: Optional[Tuple[_ColumnsClauseElement, ...]] = None
_returning: Tuple[_ColumnsClauseElement, ...] = ()
is_dml = True
def _generate_fromclause_column_proxies(
self, fromclause: FromClause
self,
fromclause: FromClause,
columns: ColumnCollection[str, KeyedColumnElement[Any]],
primary_key: ColumnSet,
foreign_keys: Set[KeyedColumnElement[Any]],
) -> None:
fromclause._columns._populate_separate_keys(
col._make_proxy(fromclause)
columns._populate_separate_keys(
col._make_proxy(
fromclause, primary_key=primary_key, foreign_keys=foreign_keys
)
for col in self._all_selected_columns
if is_column_element(col)
)
@@ -523,11 +533,11 @@ class UpdateBase(
E.g.::
stmt = table.insert().values(data='newdata').return_defaults()
stmt = table.insert().values(data="newdata").return_defaults()
result = connection.execute(stmt)
server_created_at = result.returned_defaults['created_at']
server_created_at = result.returned_defaults["created_at"]
When used against an UPDATE statement
:meth:`.UpdateBase.return_defaults` instead looks for columns that
@@ -685,6 +695,16 @@ class UpdateBase(
return self
def is_derived_from(self, fromclause: Optional[FromClause]) -> bool:
"""Return ``True`` if this :class:`.ReturnsRows` is
'derived' from the given :class:`.FromClause`.
Since these are DMLs, we dont want such statements ever being adapted
so we return False for derives.
"""
return False
@_generative
def returning(
self,
@@ -1030,7 +1050,7 @@ class ValuesBase(UpdateBase):
users.insert().values(name="some name")
users.update().where(users.c.id==5).values(name="some name")
users.update().where(users.c.id == 5).values(name="some name")
:param \*args: As an alternative to passing key/value parameters,
a dictionary, tuple, or list of dictionaries or tuples can be passed
@@ -1060,13 +1080,17 @@ class ValuesBase(UpdateBase):
this syntax is supported on backends such as SQLite, PostgreSQL,
MySQL, but not necessarily others::
users.insert().values([
{"name": "some name"},
{"name": "some other name"},
{"name": "yet another name"},
])
users.insert().values(
[
{"name": "some name"},
{"name": "some other name"},
{"name": "yet another name"},
]
)
The above form would render a multiple VALUES statement similar to::
The above form would render a multiple VALUES statement similar to:
.. sourcecode:: sql
INSERT INTO users (name) VALUES
(:name_1),
@@ -1244,7 +1268,7 @@ class Insert(ValuesBase):
e.g.::
sel = select(table1.c.a, table1.c.b).where(table1.c.c > 5)
ins = table2.insert().from_select(['a', 'b'], sel)
ins = table2.insert().from_select(["a", "b"], sel)
:param names: a sequence of string column names or
:class:`_schema.Column`
@@ -1295,8 +1319,7 @@ class Insert(ValuesBase):
@overload
def returning(
self, __ent0: _TCCA[_T0], *, sort_by_parameter_order: bool = False
) -> ReturningInsert[Tuple[_T0]]:
...
) -> ReturningInsert[Tuple[_T0]]: ...
@overload
def returning(
@@ -1305,8 +1328,7 @@ class Insert(ValuesBase):
__ent1: _TCCA[_T1],
*,
sort_by_parameter_order: bool = False,
) -> ReturningInsert[Tuple[_T0, _T1]]:
...
) -> ReturningInsert[Tuple[_T0, _T1]]: ...
@overload
def returning(
@@ -1316,8 +1338,7 @@ class Insert(ValuesBase):
__ent2: _TCCA[_T2],
*,
sort_by_parameter_order: bool = False,
) -> ReturningInsert[Tuple[_T0, _T1, _T2]]:
...
) -> ReturningInsert[Tuple[_T0, _T1, _T2]]: ...
@overload
def returning(
@@ -1328,8 +1349,7 @@ class Insert(ValuesBase):
__ent3: _TCCA[_T3],
*,
sort_by_parameter_order: bool = False,
) -> ReturningInsert[Tuple[_T0, _T1, _T2, _T3]]:
...
) -> ReturningInsert[Tuple[_T0, _T1, _T2, _T3]]: ...
@overload
def returning(
@@ -1341,8 +1361,7 @@ class Insert(ValuesBase):
__ent4: _TCCA[_T4],
*,
sort_by_parameter_order: bool = False,
) -> ReturningInsert[Tuple[_T0, _T1, _T2, _T3, _T4]]:
...
) -> ReturningInsert[Tuple[_T0, _T1, _T2, _T3, _T4]]: ...
@overload
def returning(
@@ -1355,8 +1374,7 @@ class Insert(ValuesBase):
__ent5: _TCCA[_T5],
*,
sort_by_parameter_order: bool = False,
) -> ReturningInsert[Tuple[_T0, _T1, _T2, _T3, _T4, _T5]]:
...
) -> ReturningInsert[Tuple[_T0, _T1, _T2, _T3, _T4, _T5]]: ...
@overload
def returning(
@@ -1370,8 +1388,7 @@ class Insert(ValuesBase):
__ent6: _TCCA[_T6],
*,
sort_by_parameter_order: bool = False,
) -> ReturningInsert[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]]:
...
) -> ReturningInsert[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]]: ...
@overload
def returning(
@@ -1386,8 +1403,9 @@ class Insert(ValuesBase):
__ent7: _TCCA[_T7],
*,
sort_by_parameter_order: bool = False,
) -> ReturningInsert[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7]]:
...
) -> ReturningInsert[
Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7]
]: ...
# END OVERLOADED FUNCTIONS self.returning
@@ -1397,16 +1415,14 @@ class Insert(ValuesBase):
*cols: _ColumnsClauseArgument[Any],
sort_by_parameter_order: bool = False,
**__kw: Any,
) -> ReturningInsert[Any]:
...
) -> ReturningInsert[Any]: ...
def returning(
self,
*cols: _ColumnsClauseArgument[Any],
sort_by_parameter_order: bool = False,
**__kw: Any,
) -> ReturningInsert[Any]:
...
) -> ReturningInsert[Any]: ...
class ReturningInsert(Insert, TypedReturnsRows[_TP]):
@@ -1541,9 +1557,7 @@ class Update(DMLWhereBase, ValuesBase):
E.g.::
stmt = table.update().ordered_values(
("name", "ed"), ("ident": "foo")
)
stmt = table.update().ordered_values(("name", "ed"), ("ident", "foo"))
.. seealso::
@@ -1556,7 +1570,7 @@ class Update(DMLWhereBase, ValuesBase):
:paramref:`_expression.update.preserve_parameter_order`
parameter, which will be removed in SQLAlchemy 2.0.
"""
""" # noqa: E501
if self._values:
raise exc.ArgumentError(
"This statement already has values present"
@@ -1596,20 +1610,19 @@ class Update(DMLWhereBase, ValuesBase):
# statically generated** by tools/generate_tuple_map_overloads.py
@overload
def returning(self, __ent0: _TCCA[_T0]) -> ReturningUpdate[Tuple[_T0]]:
...
def returning(
self, __ent0: _TCCA[_T0]
) -> ReturningUpdate[Tuple[_T0]]: ...
@overload
def returning(
self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1]
) -> ReturningUpdate[Tuple[_T0, _T1]]:
...
) -> ReturningUpdate[Tuple[_T0, _T1]]: ...
@overload
def returning(
self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1], __ent2: _TCCA[_T2]
) -> ReturningUpdate[Tuple[_T0, _T1, _T2]]:
...
) -> ReturningUpdate[Tuple[_T0, _T1, _T2]]: ...
@overload
def returning(
@@ -1618,8 +1631,7 @@ class Update(DMLWhereBase, ValuesBase):
__ent1: _TCCA[_T1],
__ent2: _TCCA[_T2],
__ent3: _TCCA[_T3],
) -> ReturningUpdate[Tuple[_T0, _T1, _T2, _T3]]:
...
) -> ReturningUpdate[Tuple[_T0, _T1, _T2, _T3]]: ...
@overload
def returning(
@@ -1629,8 +1641,7 @@ class Update(DMLWhereBase, ValuesBase):
__ent2: _TCCA[_T2],
__ent3: _TCCA[_T3],
__ent4: _TCCA[_T4],
) -> ReturningUpdate[Tuple[_T0, _T1, _T2, _T3, _T4]]:
...
) -> ReturningUpdate[Tuple[_T0, _T1, _T2, _T3, _T4]]: ...
@overload
def returning(
@@ -1641,8 +1652,7 @@ class Update(DMLWhereBase, ValuesBase):
__ent3: _TCCA[_T3],
__ent4: _TCCA[_T4],
__ent5: _TCCA[_T5],
) -> ReturningUpdate[Tuple[_T0, _T1, _T2, _T3, _T4, _T5]]:
...
) -> ReturningUpdate[Tuple[_T0, _T1, _T2, _T3, _T4, _T5]]: ...
@overload
def returning(
@@ -1654,8 +1664,7 @@ class Update(DMLWhereBase, ValuesBase):
__ent4: _TCCA[_T4],
__ent5: _TCCA[_T5],
__ent6: _TCCA[_T6],
) -> ReturningUpdate[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]]:
...
) -> ReturningUpdate[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]]: ...
@overload
def returning(
@@ -1668,21 +1677,20 @@ class Update(DMLWhereBase, ValuesBase):
__ent5: _TCCA[_T5],
__ent6: _TCCA[_T6],
__ent7: _TCCA[_T7],
) -> ReturningUpdate[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7]]:
...
) -> ReturningUpdate[
Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7]
]: ...
# END OVERLOADED FUNCTIONS self.returning
@overload
def returning(
self, *cols: _ColumnsClauseArgument[Any], **__kw: Any
) -> ReturningUpdate[Any]:
...
) -> ReturningUpdate[Any]: ...
def returning(
self, *cols: _ColumnsClauseArgument[Any], **__kw: Any
) -> ReturningUpdate[Any]:
...
) -> ReturningUpdate[Any]: ...
class ReturningUpdate(Update, TypedReturnsRows[_TP]):
@@ -1734,20 +1742,19 @@ class Delete(DMLWhereBase, UpdateBase):
# statically generated** by tools/generate_tuple_map_overloads.py
@overload
def returning(self, __ent0: _TCCA[_T0]) -> ReturningDelete[Tuple[_T0]]:
...
def returning(
self, __ent0: _TCCA[_T0]
) -> ReturningDelete[Tuple[_T0]]: ...
@overload
def returning(
self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1]
) -> ReturningDelete[Tuple[_T0, _T1]]:
...
) -> ReturningDelete[Tuple[_T0, _T1]]: ...
@overload
def returning(
self, __ent0: _TCCA[_T0], __ent1: _TCCA[_T1], __ent2: _TCCA[_T2]
) -> ReturningDelete[Tuple[_T0, _T1, _T2]]:
...
) -> ReturningDelete[Tuple[_T0, _T1, _T2]]: ...
@overload
def returning(
@@ -1756,8 +1763,7 @@ class Delete(DMLWhereBase, UpdateBase):
__ent1: _TCCA[_T1],
__ent2: _TCCA[_T2],
__ent3: _TCCA[_T3],
) -> ReturningDelete[Tuple[_T0, _T1, _T2, _T3]]:
...
) -> ReturningDelete[Tuple[_T0, _T1, _T2, _T3]]: ...
@overload
def returning(
@@ -1767,8 +1773,7 @@ class Delete(DMLWhereBase, UpdateBase):
__ent2: _TCCA[_T2],
__ent3: _TCCA[_T3],
__ent4: _TCCA[_T4],
) -> ReturningDelete[Tuple[_T0, _T1, _T2, _T3, _T4]]:
...
) -> ReturningDelete[Tuple[_T0, _T1, _T2, _T3, _T4]]: ...
@overload
def returning(
@@ -1779,8 +1784,7 @@ class Delete(DMLWhereBase, UpdateBase):
__ent3: _TCCA[_T3],
__ent4: _TCCA[_T4],
__ent5: _TCCA[_T5],
) -> ReturningDelete[Tuple[_T0, _T1, _T2, _T3, _T4, _T5]]:
...
) -> ReturningDelete[Tuple[_T0, _T1, _T2, _T3, _T4, _T5]]: ...
@overload
def returning(
@@ -1792,8 +1796,7 @@ class Delete(DMLWhereBase, UpdateBase):
__ent4: _TCCA[_T4],
__ent5: _TCCA[_T5],
__ent6: _TCCA[_T6],
) -> ReturningDelete[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]]:
...
) -> ReturningDelete[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6]]: ...
@overload
def returning(
@@ -1806,21 +1809,20 @@ class Delete(DMLWhereBase, UpdateBase):
__ent5: _TCCA[_T5],
__ent6: _TCCA[_T6],
__ent7: _TCCA[_T7],
) -> ReturningDelete[Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7]]:
...
) -> ReturningDelete[
Tuple[_T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7]
]: ...
# END OVERLOADED FUNCTIONS self.returning
@overload
def returning(
self, *cols: _ColumnsClauseArgument[Any], **__kw: Any
) -> ReturningDelete[Any]:
...
) -> ReturningDelete[Any]: ...
def returning(
self, *cols: _ColumnsClauseArgument[Any], **__kw: Any
) -> ReturningDelete[Any]:
...
) -> ReturningDelete[Any]: ...
class ReturningDelete(Update, TypedReturnsRows[_TP]):