piccolo 1.27.1__py3-none-any.whl → 1.29.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.
- piccolo/__init__.py +1 -1
- piccolo/apps/app/commands/new.py +3 -3
- piccolo/apps/asgi/commands/new.py +2 -3
- piccolo/apps/asgi/commands/templates/app/_blacksheep_app.py.jinja +57 -29
- piccolo/apps/asgi/commands/templates/app/_esmerald_app.py.jinja +48 -21
- piccolo/apps/asgi/commands/templates/app/_falcon_app.py.jinja +63 -8
- piccolo/apps/asgi/commands/templates/app/_fastapi_app.py.jinja +51 -24
- piccolo/apps/asgi/commands/templates/app/_litestar_app.py.jinja +34 -10
- piccolo/apps/asgi/commands/templates/app/_quart_app.py.jinja +38 -15
- piccolo/apps/asgi/commands/templates/app/_sanic_app.py.jinja +34 -11
- piccolo/apps/fixtures/commands/dump.py +8 -8
- piccolo/apps/fixtures/commands/load.py +5 -5
- piccolo/apps/fixtures/commands/shared.py +9 -9
- piccolo/apps/migrations/auto/diffable_table.py +12 -12
- piccolo/apps/migrations/auto/migration_manager.py +59 -66
- piccolo/apps/migrations/auto/operations.py +14 -14
- piccolo/apps/migrations/auto/schema_differ.py +35 -34
- piccolo/apps/migrations/auto/schema_snapshot.py +3 -4
- piccolo/apps/migrations/auto/serialisation.py +27 -24
- piccolo/apps/migrations/auto/serialisation_legacy.py +2 -2
- piccolo/apps/migrations/commands/backwards.py +1 -2
- piccolo/apps/migrations/commands/base.py +12 -12
- piccolo/apps/migrations/commands/check.py +2 -3
- piccolo/apps/migrations/commands/clean.py +3 -3
- piccolo/apps/migrations/commands/forwards.py +1 -2
- piccolo/apps/migrations/commands/new.py +6 -6
- piccolo/apps/migrations/tables.py +3 -3
- piccolo/apps/playground/commands/run.py +72 -13
- piccolo/apps/schema/commands/generate.py +49 -49
- piccolo/apps/schema/commands/graph.py +5 -5
- piccolo/apps/shell/commands/run.py +1 -2
- piccolo/apps/sql_shell/commands/run.py +4 -4
- piccolo/apps/tester/commands/run.py +3 -3
- piccolo/apps/user/commands/change_permissions.py +6 -6
- piccolo/apps/user/commands/create.py +7 -7
- piccolo/apps/user/commands/list.py +2 -2
- piccolo/apps/user/tables.py +8 -8
- piccolo/columns/base.py +84 -52
- piccolo/columns/choices.py +2 -2
- piccolo/columns/column_types.py +299 -177
- piccolo/columns/combination.py +15 -12
- piccolo/columns/defaults/base.py +4 -4
- piccolo/columns/defaults/date.py +4 -3
- piccolo/columns/defaults/interval.py +4 -3
- piccolo/columns/defaults/time.py +4 -3
- piccolo/columns/defaults/timestamp.py +4 -3
- piccolo/columns/defaults/timestamptz.py +4 -3
- piccolo/columns/defaults/uuid.py +3 -2
- piccolo/columns/m2m.py +28 -35
- piccolo/columns/readable.py +4 -3
- piccolo/columns/reference.py +9 -9
- piccolo/conf/apps.py +53 -54
- piccolo/custom_types.py +28 -6
- piccolo/engine/base.py +14 -14
- piccolo/engine/cockroach.py +5 -4
- piccolo/engine/finder.py +2 -2
- piccolo/engine/postgres.py +20 -19
- piccolo/engine/sqlite.py +23 -22
- piccolo/query/base.py +30 -29
- piccolo/query/functions/__init__.py +12 -0
- piccolo/query/functions/aggregate.py +4 -3
- piccolo/query/functions/array.py +151 -0
- piccolo/query/functions/base.py +3 -3
- piccolo/query/functions/datetime.py +22 -22
- piccolo/query/functions/string.py +4 -4
- piccolo/query/functions/type_conversion.py +30 -15
- piccolo/query/methods/alter.py +47 -46
- piccolo/query/methods/count.py +11 -10
- piccolo/query/methods/create.py +6 -5
- piccolo/query/methods/create_index.py +9 -8
- piccolo/query/methods/delete.py +7 -6
- piccolo/query/methods/drop_index.py +7 -6
- piccolo/query/methods/exists.py +6 -5
- piccolo/query/methods/indexes.py +4 -4
- piccolo/query/methods/insert.py +21 -14
- piccolo/query/methods/objects.py +60 -50
- piccolo/query/methods/raw.py +7 -6
- piccolo/query/methods/refresh.py +8 -7
- piccolo/query/methods/select.py +56 -49
- piccolo/query/methods/table_exists.py +5 -5
- piccolo/query/methods/update.py +8 -7
- piccolo/query/mixins.py +56 -61
- piccolo/query/operators/json.py +11 -11
- piccolo/query/proxy.py +8 -9
- piccolo/querystring.py +14 -15
- piccolo/schema.py +10 -10
- piccolo/table.py +105 -98
- piccolo/table_reflection.py +9 -9
- piccolo/testing/model_builder.py +16 -13
- piccolo/testing/random_builder.py +14 -2
- piccolo/testing/test_case.py +4 -4
- piccolo/utils/dictionary.py +3 -3
- piccolo/utils/encoding.py +5 -5
- piccolo/utils/lazy_loader.py +3 -3
- piccolo/utils/list.py +7 -8
- piccolo/utils/objects.py +4 -6
- piccolo/utils/pydantic.py +21 -24
- piccolo/utils/sql_values.py +3 -3
- piccolo/utils/sync.py +4 -3
- piccolo/utils/warnings.py +1 -2
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/METADATA +1 -1
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/RECORD +132 -131
- tests/apps/fixtures/commands/test_dump_load.py +1 -2
- tests/apps/migrations/auto/integration/test_migrations.py +32 -7
- tests/apps/migrations/auto/test_migration_manager.py +2 -2
- tests/apps/migrations/auto/test_schema_differ.py +22 -23
- tests/apps/migrations/commands/test_forwards_backwards.py +3 -3
- tests/columns/m2m/base.py +20 -49
- tests/columns/test_array.py +176 -10
- tests/columns/test_boolean.py +2 -4
- tests/columns/test_combination.py +29 -1
- tests/columns/test_db_column_name.py +2 -2
- tests/engine/test_extra_nodes.py +2 -2
- tests/engine/test_pool.py +3 -3
- tests/engine/test_transaction.py +4 -4
- tests/query/test_freeze.py +4 -4
- tests/table/instance/test_get_related.py +2 -2
- tests/table/test_alter.py +4 -4
- tests/table/test_indexes.py +1 -2
- tests/table/test_metaclass.py +7 -3
- tests/table/test_refresh.py +2 -2
- tests/table/test_select.py +58 -0
- tests/table/test_str.py +30 -22
- tests/table/test_update.py +18 -3
- tests/testing/test_model_builder.py +1 -2
- tests/testing/test_random_builder.py +5 -0
- tests/utils/test_pydantic.py +152 -134
- tests/utils/test_table_reflection.py +1 -2
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/WHEEL +0 -0
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/entry_points.txt +0 -0
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/licenses/LICENSE +0 -0
- {piccolo-1.27.1.dist-info → piccolo-1.29.0.dist-info}/top_level.txt +0 -0
piccolo/query/methods/select.py
CHANGED
@@ -1,8 +1,17 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import itertools
|
4
|
-
import typing as t
|
5
4
|
from collections import OrderedDict
|
5
|
+
from collections.abc import Callable, Sequence
|
6
|
+
from typing import (
|
7
|
+
TYPE_CHECKING,
|
8
|
+
Any,
|
9
|
+
Literal,
|
10
|
+
Optional,
|
11
|
+
TypeVar,
|
12
|
+
Union,
|
13
|
+
overload,
|
14
|
+
)
|
6
15
|
|
7
16
|
from piccolo.columns import Column, Selectable
|
8
17
|
from piccolo.columns.column_types import JSON, JSONB
|
@@ -33,7 +42,7 @@ from piccolo.utils.dictionary import make_nested
|
|
33
42
|
from piccolo.utils.encoding import dump_json, load_json
|
34
43
|
from piccolo.utils.warnings import colored_warning
|
35
44
|
|
36
|
-
if
|
45
|
+
if TYPE_CHECKING: # pragma: no cover
|
37
46
|
from piccolo.custom_types import Combinable
|
38
47
|
from piccolo.table import Table # noqa
|
39
48
|
|
@@ -48,7 +57,7 @@ from piccolo.query.functions.aggregate import ( # noqa: F401
|
|
48
57
|
|
49
58
|
|
50
59
|
class SelectRaw(Selectable):
|
51
|
-
def __init__(self, sql: str, *args:
|
60
|
+
def __init__(self, sql: str, *args: Any) -> None:
|
52
61
|
"""
|
53
62
|
Execute raw SQL in your select query.
|
54
63
|
|
@@ -69,7 +78,7 @@ class SelectRaw(Selectable):
|
|
69
78
|
return self.querystring
|
70
79
|
|
71
80
|
|
72
|
-
OptionalDict =
|
81
|
+
OptionalDict = Optional[dict[str, Any]]
|
73
82
|
|
74
83
|
|
75
84
|
class First(Proxy["Select", OptionalDict]):
|
@@ -82,7 +91,7 @@ class First(Proxy["Select", OptionalDict]):
|
|
82
91
|
|
83
92
|
async def run(
|
84
93
|
self,
|
85
|
-
node:
|
94
|
+
node: Optional[str] = None,
|
86
95
|
in_pool: bool = True,
|
87
96
|
) -> OptionalDict:
|
88
97
|
rows = await self.query.run(
|
@@ -96,16 +105,16 @@ class First(Proxy["Select", OptionalDict]):
|
|
96
105
|
return modified_response
|
97
106
|
|
98
107
|
|
99
|
-
class SelectList(Proxy["Select",
|
108
|
+
class SelectList(Proxy["Select", list]):
|
100
109
|
"""
|
101
110
|
This is for static typing purposes.
|
102
111
|
"""
|
103
112
|
|
104
113
|
async def run(
|
105
114
|
self,
|
106
|
-
node:
|
115
|
+
node: Optional[str] = None,
|
107
116
|
in_pool: bool = True,
|
108
|
-
) ->
|
117
|
+
) -> list:
|
109
118
|
rows = await self.query.run(
|
110
119
|
node=node, in_pool=in_pool, use_callbacks=False
|
111
120
|
)
|
@@ -131,14 +140,14 @@ class SelectJSON(Proxy["Select", str]):
|
|
131
140
|
|
132
141
|
async def run(
|
133
142
|
self,
|
134
|
-
node:
|
143
|
+
node: Optional[str] = None,
|
135
144
|
in_pool: bool = True,
|
136
145
|
) -> str:
|
137
146
|
rows = await self.query.run(node=node, in_pool=in_pool)
|
138
147
|
return dump_json(rows)
|
139
148
|
|
140
149
|
|
141
|
-
class Select(Query[TableInstance,
|
150
|
+
class Select(Query[TableInstance, list[dict[str, Any]]]):
|
142
151
|
__slots__ = (
|
143
152
|
"columns_list",
|
144
153
|
"exclude_secrets",
|
@@ -157,8 +166,8 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
157
166
|
|
158
167
|
def __init__(
|
159
168
|
self,
|
160
|
-
table:
|
161
|
-
columns_list:
|
169
|
+
table: type[TableInstance],
|
170
|
+
columns_list: Optional[Sequence[Union[Selectable, str]]] = None,
|
162
171
|
exclude_secrets: bool = False,
|
163
172
|
**kwargs,
|
164
173
|
):
|
@@ -181,22 +190,20 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
181
190
|
|
182
191
|
self.columns(*columns_list)
|
183
192
|
|
184
|
-
def columns(self: Self, *columns:
|
193
|
+
def columns(self: Self, *columns: Union[Selectable, str]) -> Self:
|
185
194
|
_columns = self.table._process_column_args(*columns)
|
186
195
|
self.columns_delegate.columns(*_columns)
|
187
196
|
return self
|
188
197
|
|
189
|
-
def distinct(
|
190
|
-
self: Self, *, on: t.Optional[t.Sequence[Column]] = None
|
191
|
-
) -> Self:
|
198
|
+
def distinct(self: Self, *, on: Optional[Sequence[Column]] = None) -> Self:
|
192
199
|
if on is not None and self.engine_type == "sqlite":
|
193
200
|
raise NotImplementedError("SQLite doesn't support DISTINCT ON")
|
194
201
|
|
195
202
|
self.distinct_delegate.distinct(enabled=True, on=on)
|
196
203
|
return self
|
197
204
|
|
198
|
-
def group_by(self: Self, *columns:
|
199
|
-
_columns:
|
205
|
+
def group_by(self: Self, *columns: Union[Column, str]) -> Self:
|
206
|
+
_columns: list[Column] = [
|
200
207
|
i
|
201
208
|
for i in self.table._process_column_args(*columns)
|
202
209
|
if isinstance(i, Column)
|
@@ -225,9 +232,9 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
225
232
|
|
226
233
|
def lock_rows(
|
227
234
|
self: Self,
|
228
|
-
lock_strength:
|
235
|
+
lock_strength: Union[
|
229
236
|
LockStrength,
|
230
|
-
|
237
|
+
Literal[
|
231
238
|
"UPDATE",
|
232
239
|
"NO KEY UPDATE",
|
233
240
|
"KEY SHARE",
|
@@ -236,7 +243,7 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
236
243
|
] = LockStrength.update,
|
237
244
|
nowait: bool = False,
|
238
245
|
skip_locked: bool = False,
|
239
|
-
of:
|
246
|
+
of: tuple[type[Table], ...] = (),
|
240
247
|
) -> Self:
|
241
248
|
self.lock_rows_delegate.lock_rows(
|
242
249
|
lock_strength, nowait, skip_locked, of
|
@@ -245,8 +252,8 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
245
252
|
|
246
253
|
async def _splice_m2m_rows(
|
247
254
|
self,
|
248
|
-
response:
|
249
|
-
secondary_table:
|
255
|
+
response: list[dict[str, Any]],
|
256
|
+
secondary_table: type[Table],
|
250
257
|
secondary_table_pk: Column,
|
251
258
|
m2m_name: str,
|
252
259
|
m2m_select: M2MSelect,
|
@@ -396,7 +403,7 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
396
403
|
return response
|
397
404
|
|
398
405
|
def order_by(
|
399
|
-
self: Self, *columns:
|
406
|
+
self: Self, *columns: Union[Column, str, OrderByRaw], ascending=True
|
400
407
|
) -> Self:
|
401
408
|
"""
|
402
409
|
:param columns:
|
@@ -405,7 +412,7 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
405
412
|
which allows you for complex use cases like
|
406
413
|
``OrderByRaw('random()')``.
|
407
414
|
"""
|
408
|
-
_columns:
|
415
|
+
_columns: list[Union[Column, OrderByRaw]] = []
|
409
416
|
for column in columns:
|
410
417
|
if isinstance(column, str):
|
411
418
|
_columns.append(self.table._meta.get_column_by_name(column))
|
@@ -415,25 +422,25 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
415
422
|
self.order_by_delegate.order_by(*_columns, ascending=ascending)
|
416
423
|
return self
|
417
424
|
|
418
|
-
@
|
425
|
+
@overload
|
419
426
|
def output(self: Self, *, as_list: bool) -> SelectList: # type: ignore
|
420
427
|
...
|
421
428
|
|
422
|
-
@
|
429
|
+
@overload
|
423
430
|
def output(self: Self, *, as_json: bool) -> SelectJSON: # type: ignore
|
424
431
|
...
|
425
432
|
|
426
|
-
@
|
433
|
+
@overload
|
427
434
|
def output(self: Self, *, load_json: bool) -> Self: ...
|
428
435
|
|
429
|
-
@
|
436
|
+
@overload
|
430
437
|
def output(self: Self, *, load_json: bool, as_list: bool) -> SelectJSON: # type: ignore # noqa: E501
|
431
438
|
...
|
432
439
|
|
433
|
-
@
|
440
|
+
@overload
|
434
441
|
def output(self: Self, *, load_json: bool, nested: bool) -> Self: ...
|
435
442
|
|
436
|
-
@
|
443
|
+
@overload
|
437
444
|
def output(self: Self, *, nested: bool) -> Self: ...
|
438
445
|
|
439
446
|
def output(
|
@@ -443,7 +450,7 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
443
450
|
as_json: bool = False,
|
444
451
|
load_json: bool = False,
|
445
452
|
nested: bool = False,
|
446
|
-
) ->
|
453
|
+
) -> Union[Self, SelectJSON, SelectList]:
|
447
454
|
self.output_delegate.output(
|
448
455
|
as_list=as_list,
|
449
456
|
as_json=as_json,
|
@@ -459,21 +466,21 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
459
466
|
|
460
467
|
def callback(
|
461
468
|
self: Self,
|
462
|
-
callbacks:
|
469
|
+
callbacks: Union[Callable, list[Callable]],
|
463
470
|
*,
|
464
471
|
on: CallbackType = CallbackType.success,
|
465
472
|
) -> Self:
|
466
473
|
self.callback_delegate.callback(callbacks, on=on)
|
467
474
|
return self
|
468
475
|
|
469
|
-
def where(self: Self, *where:
|
476
|
+
def where(self: Self, *where: Union[Combinable, QueryString]) -> Self:
|
470
477
|
self.where_delegate.where(*where)
|
471
478
|
return self
|
472
479
|
|
473
480
|
async def batch(
|
474
481
|
self,
|
475
|
-
batch_size:
|
476
|
-
node:
|
482
|
+
batch_size: Optional[int] = None,
|
483
|
+
node: Optional[str] = None,
|
477
484
|
**kwargs,
|
478
485
|
) -> BaseBatch:
|
479
486
|
if batch_size:
|
@@ -484,14 +491,14 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
484
491
|
|
485
492
|
###########################################################################
|
486
493
|
|
487
|
-
def _get_joins(self, columns:
|
494
|
+
def _get_joins(self, columns: Sequence[Selectable]) -> list[str]:
|
488
495
|
"""
|
489
496
|
A call chain is a sequence of foreign keys representing joins which
|
490
497
|
need to be made to retrieve a column in another table.
|
491
498
|
"""
|
492
|
-
joins:
|
499
|
+
joins: list[str] = []
|
493
500
|
|
494
|
-
readables:
|
501
|
+
readables: list[Readable] = [
|
495
502
|
i for i in columns if isinstance(i, Readable)
|
496
503
|
]
|
497
504
|
|
@@ -499,7 +506,7 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
499
506
|
for readable in readables:
|
500
507
|
columns += readable.columns
|
501
508
|
|
502
|
-
querystrings:
|
509
|
+
querystrings: list[QueryString] = [
|
503
510
|
i for i in columns if isinstance(i, QueryString)
|
504
511
|
]
|
505
512
|
for querystring in querystrings:
|
@@ -510,7 +517,7 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
510
517
|
if not isinstance(column, Column):
|
511
518
|
continue
|
512
519
|
|
513
|
-
_joins:
|
520
|
+
_joins: list[str] = []
|
514
521
|
for index, key in enumerate(column._meta.call_chain, 0):
|
515
522
|
table_alias = key.table_alias
|
516
523
|
|
@@ -542,7 +549,7 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
542
549
|
# Remove duplicates
|
543
550
|
return list(OrderedDict.fromkeys(joins))
|
544
551
|
|
545
|
-
def _check_valid_call_chain(self, keys:
|
552
|
+
def _check_valid_call_chain(self, keys: Sequence[Selectable]) -> bool:
|
546
553
|
for column in keys:
|
547
554
|
if not isinstance(column, Column):
|
548
555
|
continue
|
@@ -556,7 +563,7 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
556
563
|
return True
|
557
564
|
|
558
565
|
@property
|
559
|
-
def default_querystrings(self) ->
|
566
|
+
def default_querystrings(self) -> Sequence[QueryString]:
|
560
567
|
# JOIN
|
561
568
|
self._check_valid_call_chain(self.columns_delegate.selected_columns)
|
562
569
|
|
@@ -567,7 +574,7 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
567
574
|
)
|
568
575
|
|
569
576
|
# Combine all joins, and remove duplicates
|
570
|
-
joins:
|
577
|
+
joins: list[str] = list(
|
571
578
|
OrderedDict.fromkeys(select_joins + where_joins + order_by_joins)
|
572
579
|
)
|
573
580
|
|
@@ -584,14 +591,14 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
584
591
|
|
585
592
|
engine_type = self.table._meta.db.engine_type
|
586
593
|
|
587
|
-
select_strings:
|
594
|
+
select_strings: list[QueryString] = [
|
588
595
|
c.get_select_string(engine_type=engine_type)
|
589
596
|
for c in self.columns_delegate.selected_columns
|
590
597
|
]
|
591
598
|
|
592
599
|
#######################################################################
|
593
600
|
|
594
|
-
args:
|
601
|
+
args: list[Any] = []
|
595
602
|
|
596
603
|
query = "SELECT"
|
597
604
|
|
@@ -658,11 +665,11 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
658
665
|
|
659
666
|
async def run(
|
660
667
|
self,
|
661
|
-
node:
|
668
|
+
node: Optional[str] = None,
|
662
669
|
in_pool: bool = True,
|
663
670
|
use_callbacks: bool = True,
|
664
671
|
**kwargs,
|
665
|
-
) ->
|
672
|
+
) -> list[dict[str, Any]]:
|
666
673
|
results = await super().run(node=node, in_pool=in_pool)
|
667
674
|
if use_callbacks:
|
668
675
|
return await self.callback_delegate.invoke(
|
@@ -672,4 +679,4 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
672
679
|
return results
|
673
680
|
|
674
681
|
|
675
|
-
Self =
|
682
|
+
Self = TypeVar("Self", bound=Select)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
|
3
|
+
from collections.abc import Sequence
|
4
4
|
|
5
5
|
from piccolo.custom_types import TableInstance
|
6
6
|
from piccolo.query.base import Query
|
@@ -9,13 +9,13 @@ from piccolo.querystring import QueryString
|
|
9
9
|
|
10
10
|
class TableExists(Query[TableInstance, bool]):
|
11
11
|
|
12
|
-
__slots__:
|
12
|
+
__slots__: tuple = ()
|
13
13
|
|
14
14
|
async def response_handler(self, response):
|
15
15
|
return bool(response[0]["exists"])
|
16
16
|
|
17
17
|
@property
|
18
|
-
def sqlite_querystrings(self) ->
|
18
|
+
def sqlite_querystrings(self) -> Sequence[QueryString]:
|
19
19
|
return [
|
20
20
|
QueryString(
|
21
21
|
"SELECT EXISTS(SELECT * FROM sqlite_master WHERE "
|
@@ -25,7 +25,7 @@ class TableExists(Query[TableInstance, bool]):
|
|
25
25
|
]
|
26
26
|
|
27
27
|
@property
|
28
|
-
def postgres_querystrings(self) ->
|
28
|
+
def postgres_querystrings(self) -> Sequence[QueryString]:
|
29
29
|
subquery = QueryString(
|
30
30
|
"SELECT * FROM information_schema.tables WHERE table_name = {}",
|
31
31
|
self.table._meta.tablename,
|
@@ -41,5 +41,5 @@ class TableExists(Query[TableInstance, bool]):
|
|
41
41
|
return [query]
|
42
42
|
|
43
43
|
@property
|
44
|
-
def cockroach_querystrings(self) ->
|
44
|
+
def cockroach_querystrings(self) -> Sequence[QueryString]:
|
45
45
|
return self.postgres_querystrings
|
piccolo/query/methods/update.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
|
3
|
+
from collections.abc import Sequence
|
4
|
+
from typing import TYPE_CHECKING, Any, Optional, Union
|
4
5
|
|
5
6
|
from piccolo.custom_types import Combinable, TableInstance
|
6
7
|
from piccolo.query.base import Query
|
@@ -11,7 +12,7 @@ from piccolo.query.mixins import (
|
|
11
12
|
)
|
12
13
|
from piccolo.querystring import QueryString
|
13
14
|
|
14
|
-
if
|
15
|
+
if TYPE_CHECKING: # pragma: no cover
|
15
16
|
from piccolo.columns import Column
|
16
17
|
|
17
18
|
|
@@ -19,7 +20,7 @@ class UpdateError(Exception):
|
|
19
20
|
pass
|
20
21
|
|
21
22
|
|
22
|
-
class Update(Query[TableInstance,
|
23
|
+
class Update(Query[TableInstance, list[Any]]):
|
23
24
|
__slots__ = (
|
24
25
|
"force",
|
25
26
|
"returning_delegate",
|
@@ -28,7 +29,7 @@ class Update(Query[TableInstance, t.List[t.Any]]):
|
|
28
29
|
)
|
29
30
|
|
30
31
|
def __init__(
|
31
|
-
self, table:
|
32
|
+
self, table: type[TableInstance], force: bool = False, **kwargs
|
32
33
|
):
|
33
34
|
super().__init__(table, **kwargs)
|
34
35
|
self.force = force
|
@@ -41,7 +42,7 @@ class Update(Query[TableInstance, t.List[t.Any]]):
|
|
41
42
|
|
42
43
|
def values(
|
43
44
|
self,
|
44
|
-
values:
|
45
|
+
values: Optional[dict[Union[Column, str], Any]] = None,
|
45
46
|
**kwargs,
|
46
47
|
) -> Update:
|
47
48
|
if values is None:
|
@@ -50,7 +51,7 @@ class Update(Query[TableInstance, t.List[t.Any]]):
|
|
50
51
|
self.values_delegate.values(values)
|
51
52
|
return self
|
52
53
|
|
53
|
-
def where(self, *where:
|
54
|
+
def where(self, *where: Union[Combinable, QueryString]) -> Update:
|
54
55
|
self.where_delegate.where(*where)
|
55
56
|
return self
|
56
57
|
|
@@ -85,7 +86,7 @@ class Update(Query[TableInstance, t.List[t.Any]]):
|
|
85
86
|
###########################################################################
|
86
87
|
|
87
88
|
@property
|
88
|
-
def default_querystrings(self) ->
|
89
|
+
def default_querystrings(self) -> Sequence[QueryString]:
|
89
90
|
columns_str = ", ".join(
|
90
91
|
f'"{col._meta.db_column_name}" = {{}}'
|
91
92
|
for col, _ in self.values_delegate._values.items()
|