plain.models 0.49.1__py3-none-any.whl → 0.50.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plain/models/CHANGELOG.md +23 -0
- plain/models/aggregates.py +42 -19
- plain/models/backends/base/base.py +125 -105
- plain/models/backends/base/client.py +11 -3
- plain/models/backends/base/creation.py +22 -12
- plain/models/backends/base/features.py +10 -4
- plain/models/backends/base/introspection.py +29 -16
- plain/models/backends/base/operations.py +187 -91
- plain/models/backends/base/schema.py +267 -165
- plain/models/backends/base/validation.py +12 -3
- plain/models/backends/ddl_references.py +85 -43
- plain/models/backends/mysql/base.py +29 -26
- plain/models/backends/mysql/client.py +7 -2
- plain/models/backends/mysql/compiler.py +12 -3
- plain/models/backends/mysql/creation.py +5 -2
- plain/models/backends/mysql/features.py +24 -22
- plain/models/backends/mysql/introspection.py +22 -13
- plain/models/backends/mysql/operations.py +106 -39
- plain/models/backends/mysql/schema.py +48 -24
- plain/models/backends/mysql/validation.py +13 -6
- plain/models/backends/postgresql/base.py +41 -34
- plain/models/backends/postgresql/client.py +7 -2
- plain/models/backends/postgresql/creation.py +10 -5
- plain/models/backends/postgresql/introspection.py +15 -8
- plain/models/backends/postgresql/operations.py +109 -42
- plain/models/backends/postgresql/schema.py +85 -46
- plain/models/backends/sqlite3/_functions.py +151 -115
- plain/models/backends/sqlite3/base.py +37 -23
- plain/models/backends/sqlite3/client.py +7 -1
- plain/models/backends/sqlite3/creation.py +9 -5
- plain/models/backends/sqlite3/features.py +5 -3
- plain/models/backends/sqlite3/introspection.py +32 -16
- plain/models/backends/sqlite3/operations.py +125 -42
- plain/models/backends/sqlite3/schema.py +82 -58
- plain/models/backends/utils.py +52 -29
- plain/models/backups/cli.py +8 -6
- plain/models/backups/clients.py +16 -7
- plain/models/backups/core.py +24 -13
- plain/models/base.py +113 -74
- plain/models/cli.py +94 -63
- plain/models/config.py +1 -1
- plain/models/connections.py +23 -7
- plain/models/constraints.py +65 -47
- plain/models/database_url.py +1 -1
- plain/models/db.py +6 -2
- plain/models/deletion.py +66 -43
- plain/models/entrypoints.py +1 -1
- plain/models/enums.py +22 -11
- plain/models/exceptions.py +23 -8
- plain/models/expressions.py +440 -257
- plain/models/fields/__init__.py +253 -202
- plain/models/fields/json.py +120 -54
- plain/models/fields/mixins.py +12 -8
- plain/models/fields/related.py +284 -252
- plain/models/fields/related_descriptors.py +34 -25
- plain/models/fields/related_lookups.py +23 -11
- plain/models/fields/related_managers.py +81 -47
- plain/models/fields/reverse_related.py +58 -55
- plain/models/forms.py +89 -63
- plain/models/functions/comparison.py +71 -18
- plain/models/functions/datetime.py +79 -29
- plain/models/functions/math.py +43 -10
- plain/models/functions/mixins.py +24 -7
- plain/models/functions/text.py +104 -25
- plain/models/functions/window.py +12 -6
- plain/models/indexes.py +52 -28
- plain/models/lookups.py +228 -153
- plain/models/migrations/autodetector.py +86 -43
- plain/models/migrations/exceptions.py +7 -3
- plain/models/migrations/executor.py +33 -7
- plain/models/migrations/graph.py +79 -50
- plain/models/migrations/loader.py +45 -22
- plain/models/migrations/migration.py +23 -18
- plain/models/migrations/operations/base.py +37 -19
- plain/models/migrations/operations/fields.py +89 -42
- plain/models/migrations/operations/models.py +245 -143
- plain/models/migrations/operations/special.py +82 -25
- plain/models/migrations/optimizer.py +7 -2
- plain/models/migrations/questioner.py +58 -31
- plain/models/migrations/recorder.py +18 -11
- plain/models/migrations/serializer.py +50 -39
- plain/models/migrations/state.py +220 -133
- plain/models/migrations/utils.py +29 -13
- plain/models/migrations/writer.py +17 -14
- plain/models/options.py +63 -56
- plain/models/otel.py +16 -6
- plain/models/preflight.py +35 -12
- plain/models/query.py +323 -228
- plain/models/query_utils.py +93 -58
- plain/models/registry.py +34 -16
- plain/models/sql/compiler.py +146 -97
- plain/models/sql/datastructures.py +38 -25
- plain/models/sql/query.py +255 -169
- plain/models/sql/subqueries.py +32 -21
- plain/models/sql/where.py +54 -29
- plain/models/test/pytest.py +15 -11
- plain/models/test/utils.py +4 -2
- plain/models/transaction.py +20 -7
- plain/models/utils.py +13 -5
- {plain_models-0.49.1.dist-info → plain_models-0.50.0.dist-info}/METADATA +1 -1
- plain_models-0.50.0.dist-info/RECORD +122 -0
- plain_models-0.49.1.dist-info/RECORD +0 -122
- {plain_models-0.49.1.dist-info → plain_models-0.50.0.dist-info}/WHEEL +0 -0
- {plain_models-0.49.1.dist-info → plain_models-0.50.0.dist-info}/entry_points.txt +0 -0
- {plain_models-0.49.1.dist-info → plain_models-0.50.0.dist-info}/licenses/LICENSE +0 -0
plain/models/expressions.py
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
1
3
|
import copy
|
2
4
|
import datetime
|
3
5
|
import functools
|
@@ -6,6 +8,7 @@ from collections import defaultdict
|
|
6
8
|
from decimal import Decimal
|
7
9
|
from functools import cached_property
|
8
10
|
from types import NoneType
|
11
|
+
from typing import TYPE_CHECKING, Any
|
9
12
|
from uuid import UUID
|
10
13
|
|
11
14
|
from plain.models import fields
|
@@ -20,6 +23,13 @@ from plain.models.query_utils import Q
|
|
20
23
|
from plain.utils.deconstruct import deconstructible
|
21
24
|
from plain.utils.hashable import make_hashable
|
22
25
|
|
26
|
+
if TYPE_CHECKING:
|
27
|
+
from collections.abc import Callable, Iterable, Sequence
|
28
|
+
|
29
|
+
from plain.models.backends.base.base import BaseDatabaseWrapper
|
30
|
+
from plain.models.fields import Field
|
31
|
+
from plain.models.sql.compiler import SQLCompiler
|
32
|
+
|
23
33
|
|
24
34
|
class SQLiteNumericMixin:
|
25
35
|
"""
|
@@ -27,10 +37,15 @@ class SQLiteNumericMixin:
|
|
27
37
|
numeric to be properly filtered.
|
28
38
|
"""
|
29
39
|
|
30
|
-
def as_sqlite(
|
31
|
-
|
40
|
+
def as_sqlite(
|
41
|
+
self,
|
42
|
+
compiler: SQLCompiler,
|
43
|
+
connection: BaseDatabaseWrapper,
|
44
|
+
**extra_context: Any,
|
45
|
+
) -> tuple[str, Sequence[Any]]:
|
46
|
+
sql, params = self.as_sql(compiler, connection, **extra_context) # type: ignore[attr-defined]
|
32
47
|
try:
|
33
|
-
if self.output_field.get_internal_type() == "DecimalField":
|
48
|
+
if self.output_field.get_internal_type() == "DecimalField": # type: ignore[attr-defined]
|
34
49
|
sql = f"CAST({sql} AS NUMERIC)"
|
35
50
|
except FieldError:
|
36
51
|
pass
|
@@ -62,7 +77,9 @@ class Combinable:
|
|
62
77
|
BITRIGHTSHIFT = ">>"
|
63
78
|
BITXOR = "#"
|
64
79
|
|
65
|
-
def _combine(
|
80
|
+
def _combine(
|
81
|
+
self, other: Any, connector: str, reversed: bool
|
82
|
+
) -> CombinedExpression:
|
66
83
|
if not hasattr(other, "resolve_expression"):
|
67
84
|
# everything must be resolvable to an expression
|
68
85
|
other = Value(other)
|
@@ -75,97 +92,97 @@ class Combinable:
|
|
75
92
|
# OPERATORS #
|
76
93
|
#############
|
77
94
|
|
78
|
-
def __neg__(self):
|
95
|
+
def __neg__(self) -> CombinedExpression:
|
79
96
|
return self._combine(-1, self.MUL, False)
|
80
97
|
|
81
|
-
def __add__(self, other):
|
98
|
+
def __add__(self, other: Any) -> CombinedExpression:
|
82
99
|
return self._combine(other, self.ADD, False)
|
83
100
|
|
84
|
-
def __sub__(self, other):
|
101
|
+
def __sub__(self, other: Any) -> CombinedExpression:
|
85
102
|
return self._combine(other, self.SUB, False)
|
86
103
|
|
87
|
-
def __mul__(self, other):
|
104
|
+
def __mul__(self, other: Any) -> CombinedExpression:
|
88
105
|
return self._combine(other, self.MUL, False)
|
89
106
|
|
90
|
-
def __truediv__(self, other):
|
107
|
+
def __truediv__(self, other: Any) -> CombinedExpression:
|
91
108
|
return self._combine(other, self.DIV, False)
|
92
109
|
|
93
|
-
def __mod__(self, other):
|
110
|
+
def __mod__(self, other: Any) -> CombinedExpression:
|
94
111
|
return self._combine(other, self.MOD, False)
|
95
112
|
|
96
|
-
def __pow__(self, other):
|
113
|
+
def __pow__(self, other: Any) -> CombinedExpression:
|
97
114
|
return self._combine(other, self.POW, False)
|
98
115
|
|
99
|
-
def __and__(self, other):
|
116
|
+
def __and__(self, other: Any) -> Q:
|
100
117
|
if getattr(self, "conditional", False) and getattr(other, "conditional", False):
|
101
|
-
return Q(self) & Q(other)
|
118
|
+
return Q(self) & Q(other) # type: ignore[unsupported-operator]
|
102
119
|
raise NotImplementedError(
|
103
120
|
"Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations."
|
104
121
|
)
|
105
122
|
|
106
|
-
def bitand(self, other):
|
123
|
+
def bitand(self, other: Any) -> CombinedExpression:
|
107
124
|
return self._combine(other, self.BITAND, False)
|
108
125
|
|
109
|
-
def bitleftshift(self, other):
|
126
|
+
def bitleftshift(self, other: Any) -> CombinedExpression:
|
110
127
|
return self._combine(other, self.BITLEFTSHIFT, False)
|
111
128
|
|
112
|
-
def bitrightshift(self, other):
|
129
|
+
def bitrightshift(self, other: Any) -> CombinedExpression:
|
113
130
|
return self._combine(other, self.BITRIGHTSHIFT, False)
|
114
131
|
|
115
|
-
def __xor__(self, other):
|
132
|
+
def __xor__(self, other: Any) -> Q:
|
116
133
|
if getattr(self, "conditional", False) and getattr(other, "conditional", False):
|
117
|
-
return Q(self) ^ Q(other)
|
134
|
+
return Q(self) ^ Q(other) # type: ignore[unsupported-operator]
|
118
135
|
raise NotImplementedError(
|
119
136
|
"Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations."
|
120
137
|
)
|
121
138
|
|
122
|
-
def bitxor(self, other):
|
139
|
+
def bitxor(self, other: Any) -> CombinedExpression:
|
123
140
|
return self._combine(other, self.BITXOR, False)
|
124
141
|
|
125
|
-
def __or__(self, other):
|
142
|
+
def __or__(self, other: Any) -> Q:
|
126
143
|
if getattr(self, "conditional", False) and getattr(other, "conditional", False):
|
127
|
-
return Q(self) | Q(other)
|
144
|
+
return Q(self) | Q(other) # type: ignore[unsupported-operator]
|
128
145
|
raise NotImplementedError(
|
129
146
|
"Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations."
|
130
147
|
)
|
131
148
|
|
132
|
-
def bitor(self, other):
|
149
|
+
def bitor(self, other: Any) -> CombinedExpression:
|
133
150
|
return self._combine(other, self.BITOR, False)
|
134
151
|
|
135
|
-
def __radd__(self, other):
|
152
|
+
def __radd__(self, other: Any) -> CombinedExpression:
|
136
153
|
return self._combine(other, self.ADD, True)
|
137
154
|
|
138
|
-
def __rsub__(self, other):
|
155
|
+
def __rsub__(self, other: Any) -> CombinedExpression:
|
139
156
|
return self._combine(other, self.SUB, True)
|
140
157
|
|
141
|
-
def __rmul__(self, other):
|
158
|
+
def __rmul__(self, other: Any) -> CombinedExpression:
|
142
159
|
return self._combine(other, self.MUL, True)
|
143
160
|
|
144
|
-
def __rtruediv__(self, other):
|
161
|
+
def __rtruediv__(self, other: Any) -> CombinedExpression:
|
145
162
|
return self._combine(other, self.DIV, True)
|
146
163
|
|
147
|
-
def __rmod__(self, other):
|
164
|
+
def __rmod__(self, other: Any) -> CombinedExpression:
|
148
165
|
return self._combine(other, self.MOD, True)
|
149
166
|
|
150
|
-
def __rpow__(self, other):
|
167
|
+
def __rpow__(self, other: Any) -> CombinedExpression:
|
151
168
|
return self._combine(other, self.POW, True)
|
152
169
|
|
153
|
-
def __rand__(self, other):
|
170
|
+
def __rand__(self, other: Any) -> None:
|
154
171
|
raise NotImplementedError(
|
155
172
|
"Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations."
|
156
173
|
)
|
157
174
|
|
158
|
-
def __ror__(self, other):
|
175
|
+
def __ror__(self, other: Any) -> None:
|
159
176
|
raise NotImplementedError(
|
160
177
|
"Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations."
|
161
178
|
)
|
162
179
|
|
163
|
-
def __rxor__(self, other):
|
180
|
+
def __rxor__(self, other: Any) -> None:
|
164
181
|
raise NotImplementedError(
|
165
182
|
"Use .bitand(), .bitor(), and .bitxor() for bitwise logical operations."
|
166
183
|
)
|
167
184
|
|
168
|
-
def __invert__(self):
|
185
|
+
def __invert__(self) -> NegatedExpression:
|
169
186
|
return NegatedExpression(self)
|
170
187
|
|
171
188
|
|
@@ -181,29 +198,31 @@ class BaseExpression:
|
|
181
198
|
# Can the expression can be used as a source expression in Window?
|
182
199
|
window_compatible = False
|
183
200
|
|
184
|
-
def __init__(self, output_field=None):
|
201
|
+
def __init__(self, output_field: Field | None = None):
|
185
202
|
if output_field is not None:
|
186
203
|
self.output_field = output_field
|
187
204
|
|
188
|
-
def __getstate__(self):
|
205
|
+
def __getstate__(self) -> dict[str, Any]:
|
189
206
|
state = self.__dict__.copy()
|
190
207
|
state.pop("convert_value", None)
|
191
208
|
return state
|
192
209
|
|
193
|
-
def get_db_converters(
|
210
|
+
def get_db_converters(
|
211
|
+
self, connection: BaseDatabaseWrapper
|
212
|
+
) -> list[Callable[..., Any]]:
|
194
213
|
return (
|
195
214
|
[]
|
196
|
-
if self.convert_value is self._convert_value_noop
|
197
|
-
else [self.convert_value]
|
198
|
-
) + self.output_field.get_db_converters(connection)
|
215
|
+
if self.convert_value is self._convert_value_noop # type: ignore[attr-defined]
|
216
|
+
else [self.convert_value] # type: ignore[attr-defined]
|
217
|
+
) + self.output_field.get_db_converters(connection) # type: ignore[attr-defined]
|
199
218
|
|
200
|
-
def get_source_expressions(self):
|
219
|
+
def get_source_expressions(self) -> list[Any]:
|
201
220
|
return []
|
202
221
|
|
203
|
-
def set_source_expressions(self, exprs):
|
222
|
+
def set_source_expressions(self, exprs: Sequence[Any]) -> None:
|
204
223
|
assert not exprs
|
205
224
|
|
206
|
-
def _parse_expressions(self, *expressions):
|
225
|
+
def _parse_expressions(self, *expressions: Any) -> list[Any]:
|
207
226
|
return [
|
208
227
|
arg
|
209
228
|
if hasattr(arg, "resolve_expression")
|
@@ -211,7 +230,9 @@ class BaseExpression:
|
|
211
230
|
for arg in expressions
|
212
231
|
]
|
213
232
|
|
214
|
-
def as_sql(
|
233
|
+
def as_sql(
|
234
|
+
self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
235
|
+
) -> tuple[str, Sequence[Any]]:
|
215
236
|
"""
|
216
237
|
Responsible for returning a (sql, [params]) tuple to be included
|
217
238
|
in the current query.
|
@@ -240,27 +261,32 @@ class BaseExpression:
|
|
240
261
|
raise NotImplementedError("Subclasses must implement as_sql()")
|
241
262
|
|
242
263
|
@cached_property
|
243
|
-
def contains_aggregate(self):
|
264
|
+
def contains_aggregate(self) -> bool:
|
244
265
|
return any(
|
245
266
|
expr and expr.contains_aggregate for expr in self.get_source_expressions()
|
246
267
|
)
|
247
268
|
|
248
269
|
@cached_property
|
249
|
-
def contains_over_clause(self):
|
270
|
+
def contains_over_clause(self) -> bool:
|
250
271
|
return any(
|
251
272
|
expr and expr.contains_over_clause for expr in self.get_source_expressions()
|
252
273
|
)
|
253
274
|
|
254
275
|
@cached_property
|
255
|
-
def contains_column_references(self):
|
276
|
+
def contains_column_references(self) -> bool:
|
256
277
|
return any(
|
257
278
|
expr and expr.contains_column_references
|
258
279
|
for expr in self.get_source_expressions()
|
259
280
|
)
|
260
281
|
|
261
282
|
def resolve_expression(
|
262
|
-
self,
|
263
|
-
|
283
|
+
self,
|
284
|
+
query: Any = None,
|
285
|
+
allow_joins: bool = True,
|
286
|
+
reuse: Any = None,
|
287
|
+
summarize: bool = False,
|
288
|
+
for_save: bool = False,
|
289
|
+
) -> BaseExpression:
|
264
290
|
"""
|
265
291
|
Provide the chance to do any preprocessing or validation before being
|
266
292
|
added to the query.
|
@@ -288,15 +314,15 @@ class BaseExpression:
|
|
288
314
|
return c
|
289
315
|
|
290
316
|
@property
|
291
|
-
def conditional(self):
|
292
|
-
return isinstance(self.output_field, fields.BooleanField)
|
317
|
+
def conditional(self) -> bool:
|
318
|
+
return isinstance(self.output_field, fields.BooleanField) # type: ignore[attr-defined]
|
293
319
|
|
294
320
|
@property
|
295
|
-
def field(self):
|
296
|
-
return self.output_field
|
321
|
+
def field(self) -> Field:
|
322
|
+
return self.output_field # type: ignore[attr-defined]
|
297
323
|
|
298
324
|
@cached_property
|
299
|
-
def output_field(self):
|
325
|
+
def output_field(self) -> Field:
|
300
326
|
"""Return the output type of this expressions."""
|
301
327
|
output_field = self._resolve_output_field()
|
302
328
|
if output_field is None:
|
@@ -305,7 +331,7 @@ class BaseExpression:
|
|
305
331
|
return output_field
|
306
332
|
|
307
333
|
@cached_property
|
308
|
-
def _output_field_or_none(self):
|
334
|
+
def _output_field_or_none(self) -> Field | None:
|
309
335
|
"""
|
310
336
|
Return the output field of this expression, or None if
|
311
337
|
_resolve_output_field() didn't return an output type.
|
@@ -315,8 +341,9 @@ class BaseExpression:
|
|
315
341
|
except FieldError:
|
316
342
|
if not self._output_field_resolved_to_none:
|
317
343
|
raise
|
344
|
+
return None
|
318
345
|
|
319
|
-
def _resolve_output_field(self):
|
346
|
+
def _resolve_output_field(self) -> Field | None:
|
320
347
|
"""
|
321
348
|
Attempt to infer the output type of the expression.
|
322
349
|
|
@@ -341,13 +368,16 @@ class BaseExpression:
|
|
341
368
|
"set output_field."
|
342
369
|
)
|
343
370
|
return output_field
|
371
|
+
return None
|
344
372
|
|
345
373
|
@staticmethod
|
346
|
-
def _convert_value_noop(
|
374
|
+
def _convert_value_noop(
|
375
|
+
value: Any, expression: Any, connection: BaseDatabaseWrapper
|
376
|
+
) -> Any:
|
347
377
|
return value
|
348
378
|
|
349
379
|
@cached_property
|
350
|
-
def convert_value(self):
|
380
|
+
def convert_value(self) -> Callable[[Any, Any, Any], Any]:
|
351
381
|
"""
|
352
382
|
Expressions provide their own converters because users have the option
|
353
383
|
of manually specifying the output_field which may be a different type
|
@@ -375,13 +405,13 @@ class BaseExpression:
|
|
375
405
|
)
|
376
406
|
return self._convert_value_noop
|
377
407
|
|
378
|
-
def get_lookup(self, lookup):
|
379
|
-
return self.output_field.get_lookup(lookup)
|
408
|
+
def get_lookup(self, lookup: str) -> type | None:
|
409
|
+
return self.output_field.get_lookup(lookup) # type: ignore[attr-defined]
|
380
410
|
|
381
|
-
def get_transform(self, name):
|
382
|
-
return self.output_field.get_transform(name)
|
411
|
+
def get_transform(self, name: str) -> type | None:
|
412
|
+
return self.output_field.get_transform(name) # type: ignore[attr-defined]
|
383
413
|
|
384
|
-
def relabeled_clone(self, change_map):
|
414
|
+
def relabeled_clone(self, change_map: dict[str, str]) -> BaseExpression:
|
385
415
|
clone = self.copy()
|
386
416
|
clone.set_source_expressions(
|
387
417
|
[
|
@@ -391,7 +421,9 @@ class BaseExpression:
|
|
391
421
|
)
|
392
422
|
return clone
|
393
423
|
|
394
|
-
def replace_expressions(
|
424
|
+
def replace_expressions(
|
425
|
+
self, replacements: dict[BaseExpression, Any]
|
426
|
+
) -> BaseExpression:
|
395
427
|
if replacement := replacements.get(self):
|
396
428
|
return replacement
|
397
429
|
clone = self.copy()
|
@@ -404,16 +436,16 @@ class BaseExpression:
|
|
404
436
|
)
|
405
437
|
return clone
|
406
438
|
|
407
|
-
def get_refs(self):
|
439
|
+
def get_refs(self) -> set[str]:
|
408
440
|
refs = set()
|
409
441
|
for expr in self.get_source_expressions():
|
410
442
|
refs |= expr.get_refs()
|
411
443
|
return refs
|
412
444
|
|
413
|
-
def copy(self):
|
445
|
+
def copy(self) -> BaseExpression:
|
414
446
|
return copy.copy(self)
|
415
447
|
|
416
|
-
def prefix_references(self, prefix):
|
448
|
+
def prefix_references(self, prefix: str) -> BaseExpression:
|
417
449
|
clone = self.copy()
|
418
450
|
clone.set_source_expressions(
|
419
451
|
[
|
@@ -425,7 +457,7 @@ class BaseExpression:
|
|
425
457
|
)
|
426
458
|
return clone
|
427
459
|
|
428
|
-
def get_group_by_cols(self):
|
460
|
+
def get_group_by_cols(self) -> list[BaseExpression]:
|
429
461
|
if not self.contains_aggregate:
|
430
462
|
return [self]
|
431
463
|
cols = []
|
@@ -433,20 +465,20 @@ class BaseExpression:
|
|
433
465
|
cols.extend(source.get_group_by_cols())
|
434
466
|
return cols
|
435
467
|
|
436
|
-
def get_source_fields(self):
|
468
|
+
def get_source_fields(self) -> list[Field | None]:
|
437
469
|
"""Return the underlying field types used by this aggregate."""
|
438
470
|
return [e._output_field_or_none for e in self.get_source_expressions()]
|
439
471
|
|
440
|
-
def asc(self, **kwargs):
|
472
|
+
def asc(self, **kwargs: Any) -> OrderBy:
|
441
473
|
return OrderBy(self, **kwargs)
|
442
474
|
|
443
|
-
def desc(self, **kwargs):
|
475
|
+
def desc(self, **kwargs: Any) -> OrderBy:
|
444
476
|
return OrderBy(self, descending=True, **kwargs)
|
445
477
|
|
446
|
-
def reverse_ordering(self):
|
478
|
+
def reverse_ordering(self) -> BaseExpression:
|
447
479
|
return self
|
448
480
|
|
449
|
-
def flatten(self):
|
481
|
+
def flatten(self) -> Iterable[Any]:
|
450
482
|
"""
|
451
483
|
Recursively yield this expression and all subexpressions, in
|
452
484
|
depth-first order.
|
@@ -459,13 +491,15 @@ class BaseExpression:
|
|
459
491
|
else:
|
460
492
|
yield expr
|
461
493
|
|
462
|
-
def select_format(
|
494
|
+
def select_format(
|
495
|
+
self, compiler: SQLCompiler, sql: str, params: Sequence[Any]
|
496
|
+
) -> tuple[str, Sequence[Any]]:
|
463
497
|
"""
|
464
498
|
Custom format for select clauses. For example, EXISTS expressions need
|
465
499
|
to be wrapped in CASE WHEN on Oracle.
|
466
500
|
"""
|
467
|
-
if hasattr(self.output_field, "select_format"):
|
468
|
-
return self.output_field.select_format(compiler, sql, params)
|
501
|
+
if hasattr(self.output_field, "select_format"): # type: ignore[attr-defined]
|
502
|
+
return self.output_field.select_format(compiler, sql, params) # type: ignore[attr-defined]
|
469
503
|
return sql, params
|
470
504
|
|
471
505
|
|
@@ -474,13 +508,13 @@ class Expression(BaseExpression, Combinable):
|
|
474
508
|
"""An expression that can be combined with other expressions."""
|
475
509
|
|
476
510
|
@cached_property
|
477
|
-
def identity(self):
|
511
|
+
def identity(self) -> tuple[Any, ...]:
|
478
512
|
constructor_signature = inspect.signature(self.__init__)
|
479
|
-
args, kwargs = self._constructor_args
|
513
|
+
args, kwargs = self._constructor_args # type: ignore[attr-defined]
|
480
514
|
signature = constructor_signature.bind_partial(*args, **kwargs)
|
481
515
|
signature.apply_defaults()
|
482
516
|
arguments = signature.arguments.items()
|
483
|
-
identity = [self.__class__]
|
517
|
+
identity: list[Any] = [self.__class__]
|
484
518
|
for arg, value in arguments:
|
485
519
|
if isinstance(value, fields.Field):
|
486
520
|
if value.name and value.model:
|
@@ -492,12 +526,12 @@ class Expression(BaseExpression, Combinable):
|
|
492
526
|
identity.append((arg, value))
|
493
527
|
return tuple(identity)
|
494
528
|
|
495
|
-
def __eq__(self, other):
|
529
|
+
def __eq__(self, other: object) -> bool:
|
496
530
|
if not isinstance(other, Expression):
|
497
531
|
return NotImplemented
|
498
532
|
return other.identity == self.identity
|
499
533
|
|
500
|
-
def __hash__(self):
|
534
|
+
def __hash__(self) -> int:
|
501
535
|
return hash(self.identity)
|
502
536
|
|
503
537
|
|
@@ -608,7 +642,9 @@ _connector_combinations = [
|
|
608
642
|
_connector_combinators = defaultdict(list)
|
609
643
|
|
610
644
|
|
611
|
-
def register_combinable_fields(
|
645
|
+
def register_combinable_fields(
|
646
|
+
lhs: type[Field], connector: str, rhs: type[Field], result: type[Field]
|
647
|
+
) -> None:
|
612
648
|
"""
|
613
649
|
Register combinable types:
|
614
650
|
lhs <connector> rhs -> result
|
@@ -627,35 +663,40 @@ for d in _connector_combinations:
|
|
627
663
|
|
628
664
|
|
629
665
|
@functools.lru_cache(maxsize=128)
|
630
|
-
def _resolve_combined_type(
|
666
|
+
def _resolve_combined_type(
|
667
|
+
connector: str, lhs_type: type[Field], rhs_type: type[Field]
|
668
|
+
) -> type[Field] | None:
|
631
669
|
combinators = _connector_combinators.get(connector, ())
|
632
670
|
for combinator_lhs_type, combinator_rhs_type, combined_type in combinators:
|
633
671
|
if issubclass(lhs_type, combinator_lhs_type) and issubclass(
|
634
672
|
rhs_type, combinator_rhs_type
|
635
673
|
):
|
636
674
|
return combined_type
|
675
|
+
return None
|
637
676
|
|
638
677
|
|
639
678
|
class CombinedExpression(SQLiteNumericMixin, Expression):
|
640
|
-
def __init__(
|
679
|
+
def __init__(
|
680
|
+
self, lhs: Any, connector: str, rhs: Any, output_field: Field | None = None
|
681
|
+
):
|
641
682
|
super().__init__(output_field=output_field)
|
642
683
|
self.connector = connector
|
643
684
|
self.lhs = lhs
|
644
685
|
self.rhs = rhs
|
645
686
|
|
646
|
-
def __repr__(self):
|
687
|
+
def __repr__(self) -> str:
|
647
688
|
return f"<{self.__class__.__name__}: {self}>"
|
648
689
|
|
649
|
-
def __str__(self):
|
690
|
+
def __str__(self) -> str:
|
650
691
|
return f"{self.lhs} {self.connector} {self.rhs}"
|
651
692
|
|
652
|
-
def get_source_expressions(self):
|
693
|
+
def get_source_expressions(self) -> list[Any]:
|
653
694
|
return [self.lhs, self.rhs]
|
654
695
|
|
655
|
-
def set_source_expressions(self, exprs):
|
696
|
+
def set_source_expressions(self, exprs: Sequence[Any]) -> None:
|
656
697
|
self.lhs, self.rhs = exprs
|
657
698
|
|
658
|
-
def _resolve_output_field(self):
|
699
|
+
def _resolve_output_field(self) -> Field | None:
|
659
700
|
# We avoid using super() here for reasons given in
|
660
701
|
# Expression._resolve_output_field()
|
661
702
|
combined_type = _resolve_combined_type(
|
@@ -672,7 +713,9 @@ class CombinedExpression(SQLiteNumericMixin, Expression):
|
|
672
713
|
)
|
673
714
|
return combined_type()
|
674
715
|
|
675
|
-
def as_sql(
|
716
|
+
def as_sql(
|
717
|
+
self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
718
|
+
) -> tuple[str, list[Any]]:
|
676
719
|
expressions = []
|
677
720
|
expression_params = []
|
678
721
|
sql, params = compiler.compile(self.lhs)
|
@@ -687,8 +730,13 @@ class CombinedExpression(SQLiteNumericMixin, Expression):
|
|
687
730
|
return expression_wrapper % sql, expression_params
|
688
731
|
|
689
732
|
def resolve_expression(
|
690
|
-
self,
|
691
|
-
|
733
|
+
self,
|
734
|
+
query: Any = None,
|
735
|
+
allow_joins: bool = True,
|
736
|
+
reuse: Any = None,
|
737
|
+
summarize: bool = False,
|
738
|
+
for_save: bool = False,
|
739
|
+
) -> CombinedExpression | DurationExpression | TemporalSubtraction:
|
692
740
|
lhs = self.lhs.resolve_expression(
|
693
741
|
query, allow_joins, reuse, summarize, for_save
|
694
742
|
)
|
@@ -735,7 +783,9 @@ class CombinedExpression(SQLiteNumericMixin, Expression):
|
|
735
783
|
|
736
784
|
|
737
785
|
class DurationExpression(CombinedExpression):
|
738
|
-
def compile(
|
786
|
+
def compile(
|
787
|
+
self, side: Any, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
788
|
+
) -> tuple[str, Sequence[Any]]:
|
739
789
|
try:
|
740
790
|
output = side.output_field
|
741
791
|
except FieldError:
|
@@ -746,9 +796,11 @@ class DurationExpression(CombinedExpression):
|
|
746
796
|
return connection.ops.format_for_duration_arithmetic(sql), params
|
747
797
|
return compiler.compile(side)
|
748
798
|
|
749
|
-
def as_sql(
|
799
|
+
def as_sql(
|
800
|
+
self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
801
|
+
) -> tuple[str, list[Any]]:
|
750
802
|
if connection.features.has_native_duration_field:
|
751
|
-
return super().as_sql(compiler, connection)
|
803
|
+
return super().as_sql(compiler, connection) # type: ignore[misc]
|
752
804
|
connection.ops.check_expression_support(self)
|
753
805
|
expressions = []
|
754
806
|
expression_params = []
|
@@ -763,7 +815,12 @@ class DurationExpression(CombinedExpression):
|
|
763
815
|
sql = connection.ops.combine_duration_expression(self.connector, expressions)
|
764
816
|
return expression_wrapper % sql, expression_params
|
765
817
|
|
766
|
-
def as_sqlite(
|
818
|
+
def as_sqlite(
|
819
|
+
self,
|
820
|
+
compiler: SQLCompiler,
|
821
|
+
connection: BaseDatabaseWrapper,
|
822
|
+
**extra_context: Any,
|
823
|
+
) -> tuple[str, Sequence[Any]]:
|
767
824
|
sql, params = self.as_sql(compiler, connection, **extra_context)
|
768
825
|
if self.connector in {Combinable.MUL, Combinable.DIV}:
|
769
826
|
try:
|
@@ -788,10 +845,12 @@ class DurationExpression(CombinedExpression):
|
|
788
845
|
class TemporalSubtraction(CombinedExpression):
|
789
846
|
output_field = fields.DurationField()
|
790
847
|
|
791
|
-
def __init__(self, lhs, rhs):
|
848
|
+
def __init__(self, lhs: Any, rhs: Any):
|
792
849
|
super().__init__(lhs, self.SUB, rhs)
|
793
850
|
|
794
|
-
def as_sql(
|
851
|
+
def as_sql(
|
852
|
+
self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
853
|
+
) -> tuple[str, Sequence[Any]]:
|
795
854
|
connection.ops.check_expression_support(self)
|
796
855
|
lhs = compiler.compile(self.lhs)
|
797
856
|
rhs = compiler.compile(self.rhs)
|
@@ -804,37 +863,44 @@ class TemporalSubtraction(CombinedExpression):
|
|
804
863
|
class F(Combinable):
|
805
864
|
"""An object capable of resolving references to existing query objects."""
|
806
865
|
|
807
|
-
def __init__(self, name):
|
866
|
+
def __init__(self, name: str):
|
808
867
|
"""
|
809
868
|
Arguments:
|
810
869
|
* name: the name of the field this expression references
|
811
870
|
"""
|
812
871
|
self.name = name
|
813
872
|
|
814
|
-
def __repr__(self):
|
873
|
+
def __repr__(self) -> str:
|
815
874
|
return f"{self.__class__.__name__}({self.name})"
|
816
875
|
|
817
876
|
def resolve_expression(
|
818
|
-
self,
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
877
|
+
self,
|
878
|
+
query: Any = None,
|
879
|
+
allow_joins: bool = True,
|
880
|
+
reuse: Any = None,
|
881
|
+
summarize: bool = False,
|
882
|
+
for_save: bool = False,
|
883
|
+
) -> Any:
|
884
|
+
return query.resolve_ref(self.name, allow_joins, reuse, summarize) # type: ignore[union-attr]
|
885
|
+
|
886
|
+
def replace_expressions(self, replacements: dict[Any, Any]) -> F:
|
823
887
|
return replacements.get(self, self)
|
824
888
|
|
825
|
-
def asc(self, **kwargs):
|
889
|
+
def asc(self, **kwargs: Any) -> OrderBy:
|
826
890
|
return OrderBy(self, **kwargs)
|
827
891
|
|
828
|
-
def desc(self, **kwargs):
|
892
|
+
def desc(self, **kwargs: Any) -> OrderBy:
|
829
893
|
return OrderBy(self, descending=True, **kwargs)
|
830
894
|
|
831
|
-
def __eq__(self, other):
|
832
|
-
return
|
895
|
+
def __eq__(self, other: object) -> bool:
|
896
|
+
return (
|
897
|
+
self.__class__ == other.__class__ and self.name == other.name # type: ignore[attr-defined]
|
898
|
+
)
|
833
899
|
|
834
|
-
def __hash__(self):
|
900
|
+
def __hash__(self) -> int:
|
835
901
|
return hash(self.name)
|
836
902
|
|
837
|
-
def copy(self):
|
903
|
+
def copy(self) -> F:
|
838
904
|
return copy.copy(self)
|
839
905
|
|
840
906
|
|
@@ -849,14 +915,14 @@ class ResolvedOuterRef(F):
|
|
849
915
|
contains_aggregate = False
|
850
916
|
contains_over_clause = False
|
851
917
|
|
852
|
-
def as_sql(self, *args, **kwargs):
|
918
|
+
def as_sql(self, *args: Any, **kwargs: Any) -> None:
|
853
919
|
raise ValueError(
|
854
920
|
"This queryset contains a reference to an outer query and may "
|
855
921
|
"only be used in a subquery."
|
856
922
|
)
|
857
923
|
|
858
|
-
def resolve_expression(self, *args, **kwargs):
|
859
|
-
col = super().resolve_expression(*args, **kwargs)
|
924
|
+
def resolve_expression(self, *args: Any, **kwargs: Any) -> Any:
|
925
|
+
col = super().resolve_expression(*args, **kwargs) # type: ignore[misc]
|
860
926
|
if col.contains_over_clause:
|
861
927
|
raise NotSupportedError(
|
862
928
|
f"Referencing outer query window expression is not supported: "
|
@@ -868,22 +934,22 @@ class ResolvedOuterRef(F):
|
|
868
934
|
col.possibly_multivalued = LOOKUP_SEP in self.name
|
869
935
|
return col
|
870
936
|
|
871
|
-
def relabeled_clone(self, relabels):
|
937
|
+
def relabeled_clone(self, relabels: dict[str, str]) -> ResolvedOuterRef:
|
872
938
|
return self
|
873
939
|
|
874
|
-
def get_group_by_cols(self):
|
940
|
+
def get_group_by_cols(self) -> list[Any]:
|
875
941
|
return []
|
876
942
|
|
877
943
|
|
878
944
|
class OuterRef(F):
|
879
945
|
contains_aggregate = False
|
880
946
|
|
881
|
-
def resolve_expression(self, *args, **kwargs):
|
947
|
+
def resolve_expression(self, *args: Any, **kwargs: Any) -> ResolvedOuterRef | F:
|
882
948
|
if isinstance(self.name, self.__class__):
|
883
949
|
return self.name
|
884
950
|
return ResolvedOuterRef(self.name)
|
885
951
|
|
886
|
-
def relabeled_clone(self, relabels):
|
952
|
+
def relabeled_clone(self, relabels: dict[str, str]) -> OuterRef:
|
887
953
|
return self
|
888
954
|
|
889
955
|
|
@@ -896,7 +962,9 @@ class Func(SQLiteNumericMixin, Expression):
|
|
896
962
|
arg_joiner = ", "
|
897
963
|
arity = None # The number of arguments the function accepts.
|
898
964
|
|
899
|
-
def __init__(
|
965
|
+
def __init__(
|
966
|
+
self, *expressions: Any, output_field: Field | None = None, **extra: Any
|
967
|
+
):
|
900
968
|
if self.arity is not None and len(expressions) != self.arity:
|
901
969
|
raise TypeError(
|
902
970
|
"'{}' takes exactly {} {} ({} given)".format(
|
@@ -910,7 +978,7 @@ class Func(SQLiteNumericMixin, Expression):
|
|
910
978
|
self.source_expressions = self._parse_expressions(*expressions)
|
911
979
|
self.extra = extra
|
912
980
|
|
913
|
-
def __repr__(self):
|
981
|
+
def __repr__(self) -> str:
|
914
982
|
args = self.arg_joiner.join(str(arg) for arg in self.source_expressions)
|
915
983
|
extra = {**self.extra, **self._get_repr_options()}
|
916
984
|
if extra:
|
@@ -920,19 +988,24 @@ class Func(SQLiteNumericMixin, Expression):
|
|
920
988
|
return f"{self.__class__.__name__}({args}, {extra})"
|
921
989
|
return f"{self.__class__.__name__}({args})"
|
922
990
|
|
923
|
-
def _get_repr_options(self):
|
991
|
+
def _get_repr_options(self) -> dict[str, Any]:
|
924
992
|
"""Return a dict of extra __init__() options to include in the repr."""
|
925
993
|
return {}
|
926
994
|
|
927
|
-
def get_source_expressions(self):
|
995
|
+
def get_source_expressions(self) -> list[Any]:
|
928
996
|
return self.source_expressions
|
929
997
|
|
930
|
-
def set_source_expressions(self, exprs):
|
998
|
+
def set_source_expressions(self, exprs: Sequence[Any]) -> None:
|
931
999
|
self.source_expressions = exprs
|
932
1000
|
|
933
1001
|
def resolve_expression(
|
934
|
-
self,
|
935
|
-
|
1002
|
+
self,
|
1003
|
+
query: Any = None,
|
1004
|
+
allow_joins: bool = True,
|
1005
|
+
reuse: Any = None,
|
1006
|
+
summarize: bool = False,
|
1007
|
+
for_save: bool = False,
|
1008
|
+
) -> Func:
|
936
1009
|
c = self.copy()
|
937
1010
|
c.is_summary = summarize
|
938
1011
|
for pos, arg in enumerate(c.source_expressions):
|
@@ -943,13 +1016,13 @@ class Func(SQLiteNumericMixin, Expression):
|
|
943
1016
|
|
944
1017
|
def as_sql(
|
945
1018
|
self,
|
946
|
-
compiler,
|
947
|
-
connection,
|
948
|
-
function=None,
|
949
|
-
template=None,
|
950
|
-
arg_joiner=None,
|
951
|
-
**extra_context,
|
952
|
-
):
|
1019
|
+
compiler: SQLCompiler,
|
1020
|
+
connection: BaseDatabaseWrapper,
|
1021
|
+
function: str | None = None,
|
1022
|
+
template: str | None = None,
|
1023
|
+
arg_joiner: str | None = None,
|
1024
|
+
**extra_context: Any,
|
1025
|
+
) -> tuple[str, list[Any]]:
|
953
1026
|
connection.ops.check_expression_support(self)
|
954
1027
|
sql_parts = []
|
955
1028
|
params = []
|
@@ -980,8 +1053,8 @@ class Func(SQLiteNumericMixin, Expression):
|
|
980
1053
|
data["expressions"] = data["field"] = arg_joiner.join(sql_parts)
|
981
1054
|
return template % data, params
|
982
1055
|
|
983
|
-
def copy(self):
|
984
|
-
copy = super().copy()
|
1056
|
+
def copy(self) -> Func:
|
1057
|
+
copy = super().copy() # type: ignore[misc]
|
985
1058
|
copy.source_expressions = self.source_expressions[:]
|
986
1059
|
copy.extra = self.extra.copy()
|
987
1060
|
return copy
|
@@ -995,7 +1068,7 @@ class Value(SQLiteNumericMixin, Expression):
|
|
995
1068
|
# instances to be compiled until a decision is taken in #25425.
|
996
1069
|
for_save = False
|
997
1070
|
|
998
|
-
def __init__(self, value, output_field=None):
|
1071
|
+
def __init__(self, value: Any, output_field: Field | None = None):
|
999
1072
|
"""
|
1000
1073
|
Arguments:
|
1001
1074
|
* value: the value this expression represents. The value will be
|
@@ -1007,10 +1080,12 @@ class Value(SQLiteNumericMixin, Expression):
|
|
1007
1080
|
super().__init__(output_field=output_field)
|
1008
1081
|
self.value = value
|
1009
1082
|
|
1010
|
-
def __repr__(self):
|
1083
|
+
def __repr__(self) -> str:
|
1011
1084
|
return f"{self.__class__.__name__}({self.value!r})"
|
1012
1085
|
|
1013
|
-
def as_sql(
|
1086
|
+
def as_sql(
|
1087
|
+
self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
1088
|
+
) -> tuple[str, list[Any]]:
|
1014
1089
|
connection.ops.check_expression_support(self)
|
1015
1090
|
val = self.value
|
1016
1091
|
output_field = self._output_field_or_none
|
@@ -1029,16 +1104,21 @@ class Value(SQLiteNumericMixin, Expression):
|
|
1029
1104
|
return "%s", [val]
|
1030
1105
|
|
1031
1106
|
def resolve_expression(
|
1032
|
-
self,
|
1033
|
-
|
1034
|
-
|
1107
|
+
self,
|
1108
|
+
query: Any = None,
|
1109
|
+
allow_joins: bool = True,
|
1110
|
+
reuse: Any = None,
|
1111
|
+
summarize: bool = False,
|
1112
|
+
for_save: bool = False,
|
1113
|
+
) -> Value:
|
1114
|
+
c = super().resolve_expression(query, allow_joins, reuse, summarize, for_save) # type: ignore[misc]
|
1035
1115
|
c.for_save = for_save
|
1036
1116
|
return c
|
1037
1117
|
|
1038
|
-
def get_group_by_cols(self):
|
1118
|
+
def get_group_by_cols(self) -> list[Any]:
|
1039
1119
|
return []
|
1040
1120
|
|
1041
|
-
def _resolve_output_field(self):
|
1121
|
+
def _resolve_output_field(self) -> Field | None:
|
1042
1122
|
if isinstance(self.value, str):
|
1043
1123
|
return fields.CharField()
|
1044
1124
|
if isinstance(self.value, bool):
|
@@ -1063,32 +1143,38 @@ class Value(SQLiteNumericMixin, Expression):
|
|
1063
1143
|
return fields.UUIDField()
|
1064
1144
|
|
1065
1145
|
@property
|
1066
|
-
def empty_result_set_value(self):
|
1146
|
+
def empty_result_set_value(self) -> Any:
|
1067
1147
|
return self.value
|
1068
1148
|
|
1069
1149
|
|
1070
1150
|
class RawSQL(Expression):
|
1071
|
-
def __init__(
|
1151
|
+
def __init__(
|
1152
|
+
self, sql: str, params: Sequence[Any], output_field: Field | None = None
|
1153
|
+
):
|
1072
1154
|
if output_field is None:
|
1073
1155
|
output_field = fields.Field()
|
1074
1156
|
self.sql, self.params = sql, params
|
1075
1157
|
super().__init__(output_field=output_field)
|
1076
1158
|
|
1077
|
-
def __repr__(self):
|
1159
|
+
def __repr__(self) -> str:
|
1078
1160
|
return f"{self.__class__.__name__}({self.sql}, {self.params})"
|
1079
1161
|
|
1080
|
-
def as_sql(
|
1162
|
+
def as_sql(
|
1163
|
+
self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
1164
|
+
) -> tuple[str, Sequence[Any]]:
|
1081
1165
|
return f"({self.sql})", self.params
|
1082
1166
|
|
1083
|
-
def get_group_by_cols(self):
|
1167
|
+
def get_group_by_cols(self) -> list[RawSQL]:
|
1084
1168
|
return [self]
|
1085
1169
|
|
1086
1170
|
|
1087
1171
|
class Star(Expression):
|
1088
|
-
def __repr__(self):
|
1172
|
+
def __repr__(self) -> str:
|
1089
1173
|
return "'*'"
|
1090
1174
|
|
1091
|
-
def as_sql(
|
1175
|
+
def as_sql(
|
1176
|
+
self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
1177
|
+
) -> tuple[str, list[Any]]:
|
1092
1178
|
return "*", []
|
1093
1179
|
|
1094
1180
|
|
@@ -1096,34 +1182,40 @@ class Col(Expression):
|
|
1096
1182
|
contains_column_references = True
|
1097
1183
|
possibly_multivalued = False
|
1098
1184
|
|
1099
|
-
def __init__(
|
1185
|
+
def __init__(
|
1186
|
+
self, alias: str | None, target: Any, output_field: Field | None = None
|
1187
|
+
):
|
1100
1188
|
if output_field is None:
|
1101
1189
|
output_field = target
|
1102
1190
|
super().__init__(output_field=output_field)
|
1103
1191
|
self.alias, self.target = alias, target
|
1104
1192
|
|
1105
|
-
def __repr__(self):
|
1193
|
+
def __repr__(self) -> str:
|
1106
1194
|
alias, target = self.alias, self.target
|
1107
1195
|
identifiers = (alias, str(target)) if alias else (str(target),)
|
1108
1196
|
return "{}({})".format(self.__class__.__name__, ", ".join(identifiers))
|
1109
1197
|
|
1110
|
-
def as_sql(
|
1198
|
+
def as_sql(
|
1199
|
+
self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
1200
|
+
) -> tuple[str, list[Any]]:
|
1111
1201
|
alias, column = self.alias, self.target.column
|
1112
1202
|
identifiers = (alias, column) if alias else (column,)
|
1113
1203
|
sql = ".".join(map(compiler.quote_name_unless_alias, identifiers))
|
1114
1204
|
return sql, []
|
1115
1205
|
|
1116
|
-
def relabeled_clone(self, relabels):
|
1206
|
+
def relabeled_clone(self, relabels: dict[str, str]) -> Col:
|
1117
1207
|
if self.alias is None:
|
1118
1208
|
return self
|
1119
1209
|
return self.__class__(
|
1120
1210
|
relabels.get(self.alias, self.alias), self.target, self.output_field
|
1121
1211
|
)
|
1122
1212
|
|
1123
|
-
def get_group_by_cols(self):
|
1213
|
+
def get_group_by_cols(self) -> list[Col]:
|
1124
1214
|
return [self]
|
1125
1215
|
|
1126
|
-
def get_db_converters(
|
1216
|
+
def get_db_converters(
|
1217
|
+
self, connection: BaseDatabaseWrapper
|
1218
|
+
) -> list[Callable[..., Any]]:
|
1127
1219
|
if self.target == self.output_field:
|
1128
1220
|
return self.output_field.get_db_converters(connection)
|
1129
1221
|
return self.output_field.get_db_converters(
|
@@ -1137,36 +1229,43 @@ class Ref(Expression):
|
|
1137
1229
|
qs.annotate(sum_cost=Sum('cost')) query.
|
1138
1230
|
"""
|
1139
1231
|
|
1140
|
-
def __init__(self, refs, source):
|
1232
|
+
def __init__(self, refs: str, source: Any):
|
1141
1233
|
super().__init__()
|
1142
1234
|
self.refs, self.source = refs, source
|
1143
1235
|
|
1144
|
-
def __repr__(self):
|
1236
|
+
def __repr__(self) -> str:
|
1145
1237
|
return f"{self.__class__.__name__}({self.refs}, {self.source})"
|
1146
1238
|
|
1147
|
-
def get_source_expressions(self):
|
1239
|
+
def get_source_expressions(self) -> list[Any]:
|
1148
1240
|
return [self.source]
|
1149
1241
|
|
1150
|
-
def set_source_expressions(self, exprs):
|
1242
|
+
def set_source_expressions(self, exprs: Sequence[Any]) -> None:
|
1151
1243
|
(self.source,) = exprs
|
1152
1244
|
|
1153
1245
|
def resolve_expression(
|
1154
|
-
self,
|
1155
|
-
|
1246
|
+
self,
|
1247
|
+
query: Any = None,
|
1248
|
+
allow_joins: bool = True,
|
1249
|
+
reuse: Any = None,
|
1250
|
+
summarize: bool = False,
|
1251
|
+
for_save: bool = False,
|
1252
|
+
) -> Ref:
|
1156
1253
|
# The sub-expression `source` has already been resolved, as this is
|
1157
1254
|
# just a reference to the name of `source`.
|
1158
1255
|
return self
|
1159
1256
|
|
1160
|
-
def get_refs(self):
|
1257
|
+
def get_refs(self) -> set[str]:
|
1161
1258
|
return {self.refs}
|
1162
1259
|
|
1163
|
-
def relabeled_clone(self, relabels):
|
1260
|
+
def relabeled_clone(self, relabels: dict[str, str]) -> Ref:
|
1164
1261
|
return self
|
1165
1262
|
|
1166
|
-
def as_sql(
|
1263
|
+
def as_sql(
|
1264
|
+
self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
1265
|
+
) -> tuple[str, list[Any]]:
|
1167
1266
|
return connection.ops.quote_name(self.refs), []
|
1168
1267
|
|
1169
|
-
def get_group_by_cols(self):
|
1268
|
+
def get_group_by_cols(self) -> list[Ref]:
|
1170
1269
|
return [self]
|
1171
1270
|
|
1172
1271
|
|
@@ -1179,17 +1278,22 @@ class ExpressionList(Func):
|
|
1179
1278
|
|
1180
1279
|
template = "%(expressions)s"
|
1181
1280
|
|
1182
|
-
def __init__(self, *expressions, **extra):
|
1281
|
+
def __init__(self, *expressions: Any, **extra: Any):
|
1183
1282
|
if not expressions:
|
1184
1283
|
raise ValueError(
|
1185
1284
|
f"{self.__class__.__name__} requires at least one expression."
|
1186
1285
|
)
|
1187
1286
|
super().__init__(*expressions, **extra)
|
1188
1287
|
|
1189
|
-
def __str__(self):
|
1288
|
+
def __str__(self) -> str:
|
1190
1289
|
return self.arg_joiner.join(str(arg) for arg in self.source_expressions)
|
1191
1290
|
|
1192
|
-
def as_sqlite(
|
1291
|
+
def as_sqlite(
|
1292
|
+
self,
|
1293
|
+
compiler: SQLCompiler,
|
1294
|
+
connection: BaseDatabaseWrapper,
|
1295
|
+
**extra_context: Any,
|
1296
|
+
) -> tuple[str, Sequence[Any]]:
|
1193
1297
|
# Casting to numeric is unnecessary.
|
1194
1298
|
return self.as_sql(compiler, connection, **extra_context)
|
1195
1299
|
|
@@ -1197,8 +1301,8 @@ class ExpressionList(Func):
|
|
1197
1301
|
class OrderByList(Func):
|
1198
1302
|
template = "ORDER BY %(expressions)s"
|
1199
1303
|
|
1200
|
-
def __init__(self, *expressions, **extra):
|
1201
|
-
|
1304
|
+
def __init__(self, *expressions: Any, **extra: Any):
|
1305
|
+
expressions_tuple = tuple(
|
1202
1306
|
(
|
1203
1307
|
OrderBy(F(expr[1:]), descending=True)
|
1204
1308
|
if isinstance(expr, str) and expr[0] == "-"
|
@@ -1206,14 +1310,14 @@ class OrderByList(Func):
|
|
1206
1310
|
)
|
1207
1311
|
for expr in expressions
|
1208
1312
|
)
|
1209
|
-
super().__init__(*
|
1313
|
+
super().__init__(*expressions_tuple, **extra)
|
1210
1314
|
|
1211
|
-
def as_sql(self, *args, **kwargs):
|
1315
|
+
def as_sql(self, *args: Any, **kwargs: Any) -> tuple[str, tuple[Any, ...]]:
|
1212
1316
|
if not self.source_expressions:
|
1213
1317
|
return "", ()
|
1214
|
-
return super().as_sql(*args, **kwargs)
|
1318
|
+
return super().as_sql(*args, **kwargs) # type: ignore[misc]
|
1215
1319
|
|
1216
|
-
def get_group_by_cols(self):
|
1320
|
+
def get_group_by_cols(self) -> list[Any]:
|
1217
1321
|
group_by_cols = []
|
1218
1322
|
for order_by in self.get_source_expressions():
|
1219
1323
|
group_by_cols.extend(order_by.get_group_by_cols())
|
@@ -1227,42 +1331,46 @@ class ExpressionWrapper(SQLiteNumericMixin, Expression):
|
|
1227
1331
|
extra context to the inner expression, such as the output_field.
|
1228
1332
|
"""
|
1229
1333
|
|
1230
|
-
def __init__(self, expression, output_field):
|
1334
|
+
def __init__(self, expression: Any, output_field: Field):
|
1231
1335
|
super().__init__(output_field=output_field)
|
1232
1336
|
self.expression = expression
|
1233
1337
|
|
1234
|
-
def set_source_expressions(self, exprs):
|
1338
|
+
def set_source_expressions(self, exprs: Sequence[Any]) -> None:
|
1235
1339
|
self.expression = exprs[0]
|
1236
1340
|
|
1237
|
-
def get_source_expressions(self):
|
1341
|
+
def get_source_expressions(self) -> list[Any]:
|
1238
1342
|
return [self.expression]
|
1239
1343
|
|
1240
|
-
def get_group_by_cols(self):
|
1344
|
+
def get_group_by_cols(self) -> list[Any]:
|
1241
1345
|
if isinstance(self.expression, Expression):
|
1242
1346
|
expression = self.expression.copy()
|
1243
1347
|
expression.output_field = self.output_field
|
1244
1348
|
return expression.get_group_by_cols()
|
1245
1349
|
# For non-expressions e.g. an SQL WHERE clause, the entire
|
1246
1350
|
# `expression` must be included in the GROUP BY clause.
|
1247
|
-
return super().get_group_by_cols()
|
1351
|
+
return super().get_group_by_cols() # type: ignore[misc]
|
1248
1352
|
|
1249
|
-
def as_sql(
|
1353
|
+
def as_sql(
|
1354
|
+
self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
1355
|
+
) -> tuple[str, Sequence[Any]]:
|
1250
1356
|
return compiler.compile(self.expression)
|
1251
1357
|
|
1252
|
-
def __repr__(self):
|
1358
|
+
def __repr__(self) -> str:
|
1253
1359
|
return f"{self.__class__.__name__}({self.expression})"
|
1254
1360
|
|
1255
1361
|
|
1256
1362
|
class NegatedExpression(ExpressionWrapper):
|
1257
1363
|
"""The logical negation of a conditional expression."""
|
1258
1364
|
|
1259
|
-
def __init__(self, expression):
|
1365
|
+
def __init__(self, expression: Any):
|
1260
1366
|
super().__init__(expression, output_field=fields.BooleanField())
|
1261
1367
|
|
1262
|
-
def __invert__(self):
|
1368
|
+
def __invert__(self) -> Any:
|
1263
1369
|
return self.expression.copy()
|
1264
1370
|
|
1265
|
-
def as_sql(
|
1371
|
+
def as_sql(
|
1372
|
+
self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
1373
|
+
) -> tuple[str, Sequence[Any]]:
|
1266
1374
|
try:
|
1267
1375
|
sql, params = super().as_sql(compiler, connection)
|
1268
1376
|
except EmptyResultSet:
|
@@ -1279,8 +1387,13 @@ class NegatedExpression(ExpressionWrapper):
|
|
1279
1387
|
return f"NOT {sql}", params
|
1280
1388
|
|
1281
1389
|
def resolve_expression(
|
1282
|
-
self,
|
1283
|
-
|
1390
|
+
self,
|
1391
|
+
query: Any = None,
|
1392
|
+
allow_joins: bool = True,
|
1393
|
+
reuse: Any = None,
|
1394
|
+
summarize: bool = False,
|
1395
|
+
for_save: bool = False,
|
1396
|
+
) -> NegatedExpression:
|
1284
1397
|
resolved = super().resolve_expression(
|
1285
1398
|
query, allow_joins, reuse, summarize, for_save
|
1286
1399
|
)
|
@@ -1288,7 +1401,9 @@ class NegatedExpression(ExpressionWrapper):
|
|
1288
1401
|
raise TypeError("Cannot negate non-conditional expressions.")
|
1289
1402
|
return resolved
|
1290
1403
|
|
1291
|
-
def select_format(
|
1404
|
+
def select_format(
|
1405
|
+
self, compiler: SQLCompiler, sql: str, params: Sequence[Any]
|
1406
|
+
) -> tuple[str, Sequence[Any]]:
|
1292
1407
|
# Wrap boolean expressions with a CASE WHEN expression if a database
|
1293
1408
|
# backend (e.g. Oracle) doesn't support boolean expression in SELECT or
|
1294
1409
|
# GROUP BY list.
|
@@ -1310,13 +1425,18 @@ class When(Expression):
|
|
1310
1425
|
# This isn't a complete conditional expression, must be used in Case().
|
1311
1426
|
conditional = False
|
1312
1427
|
|
1313
|
-
def __init__(self, condition=None, then=None, **lookups):
|
1314
|
-
|
1428
|
+
def __init__(self, condition: Any = None, then: Any = None, **lookups: Any):
|
1429
|
+
lookups_dict: dict[str, Any] | None = lookups or None
|
1430
|
+
if lookups_dict:
|
1315
1431
|
if condition is None:
|
1316
|
-
condition,
|
1432
|
+
condition, lookups_dict = Q(**lookups_dict), None
|
1317
1433
|
elif getattr(condition, "conditional", False):
|
1318
|
-
condition,
|
1319
|
-
if
|
1434
|
+
condition, lookups_dict = Q(condition, **lookups_dict), None
|
1435
|
+
if (
|
1436
|
+
condition is None
|
1437
|
+
or not getattr(condition, "conditional", False)
|
1438
|
+
or lookups_dict
|
1439
|
+
):
|
1320
1440
|
raise TypeError(
|
1321
1441
|
"When() supports a Q object, a boolean expression, or lookups "
|
1322
1442
|
"as a condition."
|
@@ -1327,25 +1447,30 @@ class When(Expression):
|
|
1327
1447
|
self.condition = condition
|
1328
1448
|
self.result = self._parse_expressions(then)[0]
|
1329
1449
|
|
1330
|
-
def __str__(self):
|
1450
|
+
def __str__(self) -> str:
|
1331
1451
|
return f"WHEN {self.condition!r} THEN {self.result!r}"
|
1332
1452
|
|
1333
|
-
def __repr__(self):
|
1453
|
+
def __repr__(self) -> str:
|
1334
1454
|
return f"<{self.__class__.__name__}: {self}>"
|
1335
1455
|
|
1336
|
-
def get_source_expressions(self):
|
1456
|
+
def get_source_expressions(self) -> list[Any]:
|
1337
1457
|
return [self.condition, self.result]
|
1338
1458
|
|
1339
|
-
def set_source_expressions(self, exprs):
|
1459
|
+
def set_source_expressions(self, exprs: Sequence[Any]) -> None:
|
1340
1460
|
self.condition, self.result = exprs
|
1341
1461
|
|
1342
|
-
def get_source_fields(self):
|
1462
|
+
def get_source_fields(self) -> list[Field | None]:
|
1343
1463
|
# We're only interested in the fields of the result expressions.
|
1344
1464
|
return [self.result._output_field_or_none]
|
1345
1465
|
|
1346
1466
|
def resolve_expression(
|
1347
|
-
self,
|
1348
|
-
|
1467
|
+
self,
|
1468
|
+
query: Any = None,
|
1469
|
+
allow_joins: bool = True,
|
1470
|
+
reuse: Any = None,
|
1471
|
+
summarize: bool = False,
|
1472
|
+
for_save: bool = False,
|
1473
|
+
) -> When:
|
1349
1474
|
c = self.copy()
|
1350
1475
|
c.is_summary = summarize
|
1351
1476
|
if hasattr(c.condition, "resolve_expression"):
|
@@ -1357,7 +1482,13 @@ class When(Expression):
|
|
1357
1482
|
)
|
1358
1483
|
return c
|
1359
1484
|
|
1360
|
-
def as_sql(
|
1485
|
+
def as_sql(
|
1486
|
+
self,
|
1487
|
+
compiler: SQLCompiler,
|
1488
|
+
connection: BaseDatabaseWrapper,
|
1489
|
+
template: str | None = None,
|
1490
|
+
**extra_context: Any,
|
1491
|
+
) -> tuple[str, tuple[Any, ...]]:
|
1361
1492
|
connection.ops.check_expression_support(self)
|
1362
1493
|
template_params = extra_context
|
1363
1494
|
sql_params = []
|
@@ -1372,7 +1503,7 @@ class When(Expression):
|
|
1372
1503
|
*result_params,
|
1373
1504
|
)
|
1374
1505
|
|
1375
|
-
def get_group_by_cols(self):
|
1506
|
+
def get_group_by_cols(self) -> list[Any]:
|
1376
1507
|
# This is not a complete expression and cannot be used in GROUP BY.
|
1377
1508
|
cols = []
|
1378
1509
|
for source in self.get_source_expressions():
|
@@ -1397,7 +1528,13 @@ class Case(SQLiteNumericMixin, Expression):
|
|
1397
1528
|
template = "CASE %(cases)s ELSE %(default)s END"
|
1398
1529
|
case_joiner = " "
|
1399
1530
|
|
1400
|
-
def __init__(
|
1531
|
+
def __init__(
|
1532
|
+
self,
|
1533
|
+
*cases: When,
|
1534
|
+
default: Any = None,
|
1535
|
+
output_field: Field | None = None,
|
1536
|
+
**extra: Any,
|
1537
|
+
):
|
1401
1538
|
if not all(isinstance(case, When) for case in cases):
|
1402
1539
|
raise TypeError("Positional arguments must all be When objects.")
|
1403
1540
|
super().__init__(output_field)
|
@@ -1405,24 +1542,29 @@ class Case(SQLiteNumericMixin, Expression):
|
|
1405
1542
|
self.default = self._parse_expressions(default)[0]
|
1406
1543
|
self.extra = extra
|
1407
1544
|
|
1408
|
-
def __str__(self):
|
1545
|
+
def __str__(self) -> str:
|
1409
1546
|
return "CASE {}, ELSE {!r}".format(
|
1410
1547
|
", ".join(str(c) for c in self.cases),
|
1411
1548
|
self.default,
|
1412
1549
|
)
|
1413
1550
|
|
1414
|
-
def __repr__(self):
|
1551
|
+
def __repr__(self) -> str:
|
1415
1552
|
return f"<{self.__class__.__name__}: {self}>"
|
1416
1553
|
|
1417
|
-
def get_source_expressions(self):
|
1554
|
+
def get_source_expressions(self) -> list[Any]:
|
1418
1555
|
return self.cases + [self.default]
|
1419
1556
|
|
1420
|
-
def set_source_expressions(self, exprs):
|
1557
|
+
def set_source_expressions(self, exprs: Sequence[Any]) -> None:
|
1421
1558
|
*self.cases, self.default = exprs
|
1422
1559
|
|
1423
1560
|
def resolve_expression(
|
1424
|
-
self,
|
1425
|
-
|
1561
|
+
self,
|
1562
|
+
query: Any = None,
|
1563
|
+
allow_joins: bool = True,
|
1564
|
+
reuse: Any = None,
|
1565
|
+
summarize: bool = False,
|
1566
|
+
for_save: bool = False,
|
1567
|
+
) -> Case:
|
1426
1568
|
c = self.copy()
|
1427
1569
|
c.is_summary = summarize
|
1428
1570
|
for pos, case in enumerate(c.cases):
|
@@ -1434,17 +1576,23 @@ class Case(SQLiteNumericMixin, Expression):
|
|
1434
1576
|
)
|
1435
1577
|
return c
|
1436
1578
|
|
1437
|
-
def copy(self):
|
1438
|
-
c = super().copy()
|
1579
|
+
def copy(self) -> Case:
|
1580
|
+
c = super().copy() # type: ignore[misc]
|
1439
1581
|
c.cases = c.cases[:]
|
1440
1582
|
return c
|
1441
1583
|
|
1442
1584
|
def as_sql(
|
1443
|
-
self,
|
1444
|
-
|
1585
|
+
self,
|
1586
|
+
compiler: SQLCompiler,
|
1587
|
+
connection: BaseDatabaseWrapper,
|
1588
|
+
template: str | None = None,
|
1589
|
+
case_joiner: str | None = None,
|
1590
|
+
**extra_context: Any,
|
1591
|
+
) -> tuple[str, list[Any]]:
|
1445
1592
|
connection.ops.check_expression_support(self)
|
1446
1593
|
if not self.cases:
|
1447
|
-
|
1594
|
+
sql, params = compiler.compile(self.default)
|
1595
|
+
return sql, list(params)
|
1448
1596
|
template_params = {**self.extra, **extra_context}
|
1449
1597
|
case_parts = []
|
1450
1598
|
sql_params = []
|
@@ -1460,7 +1608,7 @@ class Case(SQLiteNumericMixin, Expression):
|
|
1460
1608
|
case_parts.append(case_sql)
|
1461
1609
|
sql_params.extend(case_params)
|
1462
1610
|
if not case_parts:
|
1463
|
-
return default_sql, default_params
|
1611
|
+
return default_sql, list(default_params)
|
1464
1612
|
case_joiner = case_joiner or self.case_joiner
|
1465
1613
|
template_params["cases"] = case_joiner.join(case_parts)
|
1466
1614
|
template_params["default"] = default_sql
|
@@ -1471,10 +1619,10 @@ class Case(SQLiteNumericMixin, Expression):
|
|
1471
1619
|
sql = connection.ops.unification_cast_sql(self.output_field) % sql
|
1472
1620
|
return sql, sql_params
|
1473
1621
|
|
1474
|
-
def get_group_by_cols(self):
|
1622
|
+
def get_group_by_cols(self) -> list[Any]:
|
1475
1623
|
if not self.cases:
|
1476
1624
|
return self.default.get_group_by_cols()
|
1477
|
-
return super().get_group_by_cols()
|
1625
|
+
return super().get_group_by_cols() # type: ignore[misc]
|
1478
1626
|
|
1479
1627
|
|
1480
1628
|
class Subquery(BaseExpression, Combinable):
|
@@ -1487,35 +1635,41 @@ class Subquery(BaseExpression, Combinable):
|
|
1487
1635
|
contains_aggregate = False
|
1488
1636
|
empty_result_set_value = None
|
1489
1637
|
|
1490
|
-
def __init__(self, queryset, output_field=None, **extra):
|
1638
|
+
def __init__(self, queryset: Any, output_field: Field | None = None, **extra: Any):
|
1491
1639
|
# Allow the usage of both QuerySet and sql.Query objects.
|
1492
1640
|
self.query = getattr(queryset, "query", queryset).clone()
|
1493
1641
|
self.query.subquery = True
|
1494
1642
|
self.extra = extra
|
1495
1643
|
super().__init__(output_field)
|
1496
1644
|
|
1497
|
-
def get_source_expressions(self):
|
1645
|
+
def get_source_expressions(self) -> list[Any]:
|
1498
1646
|
return [self.query]
|
1499
1647
|
|
1500
|
-
def set_source_expressions(self, exprs):
|
1648
|
+
def set_source_expressions(self, exprs: Sequence[Any]) -> None:
|
1501
1649
|
self.query = exprs[0]
|
1502
1650
|
|
1503
|
-
def _resolve_output_field(self):
|
1651
|
+
def _resolve_output_field(self) -> Field | None:
|
1504
1652
|
return self.query.output_field
|
1505
1653
|
|
1506
|
-
def copy(self):
|
1654
|
+
def copy(self) -> Subquery:
|
1507
1655
|
clone = super().copy()
|
1508
1656
|
clone.query = clone.query.clone()
|
1509
1657
|
return clone
|
1510
1658
|
|
1511
1659
|
@property
|
1512
|
-
def external_aliases(self):
|
1660
|
+
def external_aliases(self) -> list[str]:
|
1513
1661
|
return self.query.external_aliases
|
1514
1662
|
|
1515
|
-
def get_external_cols(self):
|
1663
|
+
def get_external_cols(self) -> list[Any]:
|
1516
1664
|
return self.query.get_external_cols()
|
1517
1665
|
|
1518
|
-
def as_sql(
|
1666
|
+
def as_sql(
|
1667
|
+
self,
|
1668
|
+
compiler: SQLCompiler,
|
1669
|
+
connection: BaseDatabaseWrapper,
|
1670
|
+
template: str | None = None,
|
1671
|
+
**extra_context: Any,
|
1672
|
+
) -> tuple[str, tuple[Any, ...]]:
|
1519
1673
|
connection.ops.check_expression_support(self)
|
1520
1674
|
template_params = {**self.extra, **extra_context}
|
1521
1675
|
subquery_sql, sql_params = self.query.as_sql(compiler, connection)
|
@@ -1525,7 +1679,7 @@ class Subquery(BaseExpression, Combinable):
|
|
1525
1679
|
sql = template % template_params
|
1526
1680
|
return sql, sql_params
|
1527
1681
|
|
1528
|
-
def get_group_by_cols(self):
|
1682
|
+
def get_group_by_cols(self) -> list[Any]:
|
1529
1683
|
return self.query.get_group_by_cols(wrapper=self)
|
1530
1684
|
|
1531
1685
|
|
@@ -1534,11 +1688,13 @@ class Exists(Subquery):
|
|
1534
1688
|
output_field = fields.BooleanField()
|
1535
1689
|
empty_result_set_value = False
|
1536
1690
|
|
1537
|
-
def __init__(self, queryset, **kwargs):
|
1691
|
+
def __init__(self, queryset: Any, **kwargs: Any):
|
1538
1692
|
super().__init__(queryset, **kwargs)
|
1539
1693
|
self.query = self.query.exists()
|
1540
1694
|
|
1541
|
-
def select_format(
|
1695
|
+
def select_format(
|
1696
|
+
self, compiler: SQLCompiler, sql: str, params: Sequence[Any]
|
1697
|
+
) -> tuple[str, Sequence[Any]]:
|
1542
1698
|
# Wrap EXISTS() with a CASE WHEN expression if a database backend
|
1543
1699
|
# (e.g. Oracle) doesn't support boolean expression in SELECT or GROUP
|
1544
1700
|
# BY list.
|
@@ -1552,7 +1708,13 @@ class OrderBy(Expression):
|
|
1552
1708
|
template = "%(expression)s %(ordering)s"
|
1553
1709
|
conditional = False
|
1554
1710
|
|
1555
|
-
def __init__(
|
1711
|
+
def __init__(
|
1712
|
+
self,
|
1713
|
+
expression: Any,
|
1714
|
+
descending: bool = False,
|
1715
|
+
nulls_first: bool | None = None,
|
1716
|
+
nulls_last: bool | None = None,
|
1717
|
+
):
|
1556
1718
|
if nulls_first and nulls_last:
|
1557
1719
|
raise ValueError("nulls_first and nulls_last are mutually exclusive")
|
1558
1720
|
if nulls_first is False or nulls_last is False:
|
@@ -1564,16 +1726,22 @@ class OrderBy(Expression):
|
|
1564
1726
|
raise ValueError("expression must be an expression type")
|
1565
1727
|
self.expression = expression
|
1566
1728
|
|
1567
|
-
def __repr__(self):
|
1729
|
+
def __repr__(self) -> str:
|
1568
1730
|
return f"{self.__class__.__name__}({self.expression}, descending={self.descending})"
|
1569
1731
|
|
1570
|
-
def set_source_expressions(self, exprs):
|
1732
|
+
def set_source_expressions(self, exprs: Sequence[Any]) -> None:
|
1571
1733
|
self.expression = exprs[0]
|
1572
1734
|
|
1573
|
-
def get_source_expressions(self):
|
1735
|
+
def get_source_expressions(self) -> list[Any]:
|
1574
1736
|
return [self.expression]
|
1575
1737
|
|
1576
|
-
def as_sql(
|
1738
|
+
def as_sql(
|
1739
|
+
self,
|
1740
|
+
compiler: SQLCompiler,
|
1741
|
+
connection: BaseDatabaseWrapper,
|
1742
|
+
template: str | None = None,
|
1743
|
+
**extra_context: Any,
|
1744
|
+
) -> tuple[str, tuple[Any, ...]]:
|
1577
1745
|
template = template or self.template
|
1578
1746
|
if connection.features.supports_order_by_nulls_modifier:
|
1579
1747
|
if self.nulls_last:
|
@@ -1599,13 +1767,13 @@ class OrderBy(Expression):
|
|
1599
1767
|
params *= template.count("%(expression)s")
|
1600
1768
|
return (template % placeholders).rstrip(), params
|
1601
1769
|
|
1602
|
-
def get_group_by_cols(self):
|
1770
|
+
def get_group_by_cols(self) -> list[Any]:
|
1603
1771
|
cols = []
|
1604
1772
|
for source in self.get_source_expressions():
|
1605
1773
|
cols.extend(source.get_group_by_cols())
|
1606
1774
|
return cols
|
1607
1775
|
|
1608
|
-
def reverse_ordering(self):
|
1776
|
+
def reverse_ordering(self) -> OrderBy:
|
1609
1777
|
self.descending = not self.descending
|
1610
1778
|
if self.nulls_first:
|
1611
1779
|
self.nulls_last = True
|
@@ -1615,10 +1783,10 @@ class OrderBy(Expression):
|
|
1615
1783
|
self.nulls_last = None
|
1616
1784
|
return self
|
1617
1785
|
|
1618
|
-
def asc(self):
|
1786
|
+
def asc(self) -> None:
|
1619
1787
|
self.descending = False
|
1620
1788
|
|
1621
|
-
def desc(self):
|
1789
|
+
def desc(self) -> None:
|
1622
1790
|
self.descending = True
|
1623
1791
|
|
1624
1792
|
|
@@ -1632,11 +1800,11 @@ class Window(SQLiteNumericMixin, Expression):
|
|
1632
1800
|
|
1633
1801
|
def __init__(
|
1634
1802
|
self,
|
1635
|
-
expression,
|
1636
|
-
partition_by=None,
|
1637
|
-
order_by=None,
|
1638
|
-
frame=None,
|
1639
|
-
output_field=None,
|
1803
|
+
expression: Any,
|
1804
|
+
partition_by: Any = None,
|
1805
|
+
order_by: Any = None,
|
1806
|
+
frame: Any = None,
|
1807
|
+
output_field: Field | None = None,
|
1640
1808
|
):
|
1641
1809
|
self.partition_by = partition_by
|
1642
1810
|
self.order_by = order_by
|
@@ -1665,16 +1833,21 @@ class Window(SQLiteNumericMixin, Expression):
|
|
1665
1833
|
super().__init__(output_field=output_field)
|
1666
1834
|
self.source_expression = self._parse_expressions(expression)[0]
|
1667
1835
|
|
1668
|
-
def _resolve_output_field(self):
|
1836
|
+
def _resolve_output_field(self) -> Field | None:
|
1669
1837
|
return self.source_expression.output_field
|
1670
1838
|
|
1671
|
-
def get_source_expressions(self):
|
1839
|
+
def get_source_expressions(self) -> list[Any]:
|
1672
1840
|
return [self.source_expression, self.partition_by, self.order_by, self.frame]
|
1673
1841
|
|
1674
|
-
def set_source_expressions(self, exprs):
|
1842
|
+
def set_source_expressions(self, exprs: Sequence[Any]) -> None:
|
1675
1843
|
self.source_expression, self.partition_by, self.order_by, self.frame = exprs
|
1676
1844
|
|
1677
|
-
def as_sql(
|
1845
|
+
def as_sql(
|
1846
|
+
self,
|
1847
|
+
compiler: SQLCompiler,
|
1848
|
+
connection: BaseDatabaseWrapper,
|
1849
|
+
template: str | None = None,
|
1850
|
+
) -> tuple[str, tuple[Any, ...]]:
|
1678
1851
|
connection.ops.check_expression_support(self)
|
1679
1852
|
if not connection.features.supports_over_clause:
|
1680
1853
|
raise NotSupportedError("This backend does not support window expressions.")
|
@@ -1707,7 +1880,9 @@ class Window(SQLiteNumericMixin, Expression):
|
|
1707
1880
|
(*params, *window_params),
|
1708
1881
|
)
|
1709
1882
|
|
1710
|
-
def as_sqlite(
|
1883
|
+
def as_sqlite(
|
1884
|
+
self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
1885
|
+
) -> tuple[str, Sequence[Any]]:
|
1711
1886
|
if isinstance(self.output_field, fields.DecimalField):
|
1712
1887
|
# Casting to numeric must be outside of the window expression.
|
1713
1888
|
copy = self.copy()
|
@@ -1717,7 +1892,7 @@ class Window(SQLiteNumericMixin, Expression):
|
|
1717
1892
|
return super(Window, copy).as_sqlite(compiler, connection)
|
1718
1893
|
return self.as_sql(compiler, connection)
|
1719
1894
|
|
1720
|
-
def __str__(self):
|
1895
|
+
def __str__(self) -> str:
|
1721
1896
|
return "{} OVER ({}{}{})".format(
|
1722
1897
|
str(self.source_expression),
|
1723
1898
|
"PARTITION BY " + str(self.partition_by) if self.partition_by else "",
|
@@ -1725,10 +1900,10 @@ class Window(SQLiteNumericMixin, Expression):
|
|
1725
1900
|
str(self.frame or ""),
|
1726
1901
|
)
|
1727
1902
|
|
1728
|
-
def __repr__(self):
|
1903
|
+
def __repr__(self) -> str:
|
1729
1904
|
return f"<{self.__class__.__name__}: {self}>"
|
1730
1905
|
|
1731
|
-
def get_group_by_cols(self):
|
1906
|
+
def get_group_by_cols(self) -> list[Any]:
|
1732
1907
|
group_by_cols = []
|
1733
1908
|
if self.partition_by:
|
1734
1909
|
group_by_cols.extend(self.partition_by.get_group_by_cols())
|
@@ -1748,17 +1923,19 @@ class WindowFrame(Expression):
|
|
1748
1923
|
|
1749
1924
|
template = "%(frame_type)s BETWEEN %(start)s AND %(end)s"
|
1750
1925
|
|
1751
|
-
def __init__(self, start=None, end=None):
|
1926
|
+
def __init__(self, start: int | None = None, end: int | None = None):
|
1752
1927
|
self.start = Value(start)
|
1753
1928
|
self.end = Value(end)
|
1754
1929
|
|
1755
|
-
def set_source_expressions(self, exprs):
|
1930
|
+
def set_source_expressions(self, exprs: Sequence[Any]) -> None:
|
1756
1931
|
self.start, self.end = exprs
|
1757
1932
|
|
1758
|
-
def get_source_expressions(self):
|
1933
|
+
def get_source_expressions(self) -> list[Any]:
|
1759
1934
|
return [self.start, self.end]
|
1760
1935
|
|
1761
|
-
def as_sql(
|
1936
|
+
def as_sql(
|
1937
|
+
self, compiler: SQLCompiler, connection: BaseDatabaseWrapper
|
1938
|
+
) -> tuple[str, list[Any]]:
|
1762
1939
|
connection.ops.check_expression_support(self)
|
1763
1940
|
start, end = self.window_frame_start_end(
|
1764
1941
|
connection, self.start.value, self.end.value
|
@@ -1773,13 +1950,13 @@ class WindowFrame(Expression):
|
|
1773
1950
|
[],
|
1774
1951
|
)
|
1775
1952
|
|
1776
|
-
def __repr__(self):
|
1953
|
+
def __repr__(self) -> str:
|
1777
1954
|
return f"<{self.__class__.__name__}: {self}>"
|
1778
1955
|
|
1779
|
-
def get_group_by_cols(self):
|
1956
|
+
def get_group_by_cols(self) -> list[Any]:
|
1780
1957
|
return []
|
1781
1958
|
|
1782
|
-
def __str__(self):
|
1959
|
+
def __str__(self) -> str:
|
1783
1960
|
if self.start.value is not None and self.start.value < 0:
|
1784
1961
|
start = f"{abs(self.start.value)} {db_connection.ops.PRECEDING}"
|
1785
1962
|
elif self.start.value is not None and self.start.value == 0:
|
@@ -1799,19 +1976,25 @@ class WindowFrame(Expression):
|
|
1799
1976
|
"end": end,
|
1800
1977
|
}
|
1801
1978
|
|
1802
|
-
def window_frame_start_end(
|
1979
|
+
def window_frame_start_end(
|
1980
|
+
self, connection: BaseDatabaseWrapper, start: int | None, end: int | None
|
1981
|
+
) -> tuple[str, str]:
|
1803
1982
|
raise NotImplementedError("Subclasses must implement window_frame_start_end().")
|
1804
1983
|
|
1805
1984
|
|
1806
1985
|
class RowRange(WindowFrame):
|
1807
1986
|
frame_type = "ROWS"
|
1808
1987
|
|
1809
|
-
def window_frame_start_end(
|
1988
|
+
def window_frame_start_end(
|
1989
|
+
self, connection: BaseDatabaseWrapper, start: int | None, end: int | None
|
1990
|
+
) -> tuple[str, str]:
|
1810
1991
|
return connection.ops.window_frame_rows_start_end(start, end)
|
1811
1992
|
|
1812
1993
|
|
1813
1994
|
class ValueRange(WindowFrame):
|
1814
1995
|
frame_type = "RANGE"
|
1815
1996
|
|
1816
|
-
def window_frame_start_end(
|
1997
|
+
def window_frame_start_end(
|
1998
|
+
self, connection: BaseDatabaseWrapper, start: int | None, end: int | None
|
1999
|
+
) -> tuple[str, str]:
|
1817
2000
|
return connection.ops.window_frame_range_start_end(start, end)
|