piccolo 1.25.0__py3-none-any.whl → 1.26.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/migrations/auto/migration_manager.py +36 -2
- piccolo/apps/schema/commands/generate.py +4 -19
- piccolo/query/constraints.py +92 -0
- piccolo/query/methods/alter.py +66 -9
- piccolo/utils/sync.py +7 -3
- {piccolo-1.25.0.dist-info → piccolo-1.26.0.dist-info}/METADATA +1 -1
- {piccolo-1.25.0.dist-info → piccolo-1.26.0.dist-info}/RECORD +13 -12
- {piccolo-1.25.0.dist-info → piccolo-1.26.0.dist-info}/WHEEL +1 -1
- tests/apps/migrations/auto/test_migration_manager.py +50 -0
- {piccolo-1.25.0.dist-info → piccolo-1.26.0.dist-info}/entry_points.txt +0 -0
- {piccolo-1.25.0.dist-info → piccolo-1.26.0.dist-info}/licenses/LICENSE +0 -0
- {piccolo-1.25.0.dist-info → piccolo-1.26.0.dist-info}/top_level.txt +0 -0
piccolo/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__VERSION__ = "1.
|
1
|
+
__VERSION__ = "1.26.0"
|
@@ -19,6 +19,7 @@ from piccolo.columns.column_types import ForeignKey, Serial
|
|
19
19
|
from piccolo.engine import engine_finder
|
20
20
|
from piccolo.query import Query
|
21
21
|
from piccolo.query.base import DDL
|
22
|
+
from piccolo.query.constraints import get_fk_constraint_name
|
22
23
|
from piccolo.schema import SchemaDDLBase
|
23
24
|
from piccolo.table import Table, create_table_class, sort_table_classes
|
24
25
|
from piccolo.utils.warnings import colored_warning
|
@@ -423,8 +424,8 @@ class MigrationManager:
|
|
423
424
|
|
424
425
|
async def _run_query(self, query: t.Union[DDL, Query, SchemaDDLBase]):
|
425
426
|
"""
|
426
|
-
If MigrationManager is
|
427
|
-
|
427
|
+
If MigrationManager is in preview mode then it just print the query
|
428
|
+
instead of executing it.
|
428
429
|
"""
|
429
430
|
if self.preview:
|
430
431
|
await self._print_query(query)
|
@@ -534,6 +535,39 @@ class MigrationManager:
|
|
534
535
|
|
535
536
|
###############################################################
|
536
537
|
|
538
|
+
on_delete = params.get("on_delete")
|
539
|
+
on_update = params.get("on_update")
|
540
|
+
if on_delete is not None or on_update is not None:
|
541
|
+
existing_table = await self.get_table_from_snapshot(
|
542
|
+
table_class_name=table_class_name,
|
543
|
+
app_name=self.app_name,
|
544
|
+
)
|
545
|
+
|
546
|
+
fk_column = existing_table._meta.get_column_by_name(
|
547
|
+
alter_column.column_name
|
548
|
+
)
|
549
|
+
|
550
|
+
assert isinstance(fk_column, ForeignKey)
|
551
|
+
|
552
|
+
# First drop the existing foreign key constraint
|
553
|
+
constraint_name = await get_fk_constraint_name(
|
554
|
+
column=fk_column
|
555
|
+
)
|
556
|
+
await self._run_query(
|
557
|
+
_Table.alter().drop_constraint(
|
558
|
+
constraint_name=constraint_name
|
559
|
+
)
|
560
|
+
)
|
561
|
+
|
562
|
+
# Then add a new foreign key constraint
|
563
|
+
await self._run_query(
|
564
|
+
_Table.alter().add_foreign_key_constraint(
|
565
|
+
column=fk_column,
|
566
|
+
on_delete=on_delete,
|
567
|
+
on_update=on_update,
|
568
|
+
)
|
569
|
+
)
|
570
|
+
|
537
571
|
null = params.get("null")
|
538
572
|
if null is not None:
|
539
573
|
await self._run_query(
|
@@ -501,6 +501,8 @@ async def get_fk_triggers(
|
|
501
501
|
Any Table subclass - just used to execute raw queries on the database.
|
502
502
|
|
503
503
|
"""
|
504
|
+
# TODO - Move this query to `piccolo.query.constraints` or use:
|
505
|
+
# `piccolo.query.constraints.referential_constraints`
|
504
506
|
triggers = await table_class.raw(
|
505
507
|
(
|
506
508
|
"SELECT tc.constraint_name, "
|
@@ -537,23 +539,6 @@ async def get_fk_triggers(
|
|
537
539
|
)
|
538
540
|
|
539
541
|
|
540
|
-
ONDELETE_MAP = {
|
541
|
-
"NO ACTION": OnDelete.no_action,
|
542
|
-
"RESTRICT": OnDelete.restrict,
|
543
|
-
"CASCADE": OnDelete.cascade,
|
544
|
-
"SET NULL": OnDelete.set_null,
|
545
|
-
"SET DEFAULT": OnDelete.set_default,
|
546
|
-
}
|
547
|
-
|
548
|
-
ONUPDATE_MAP = {
|
549
|
-
"NO ACTION": OnUpdate.no_action,
|
550
|
-
"RESTRICT": OnUpdate.restrict,
|
551
|
-
"CASCADE": OnUpdate.cascade,
|
552
|
-
"SET NULL": OnUpdate.set_null,
|
553
|
-
"SET DEFAULT": OnUpdate.set_default,
|
554
|
-
}
|
555
|
-
|
556
|
-
|
557
542
|
async def get_constraints(
|
558
543
|
table_class: t.Type[Table], tablename: str, schema_name: str = "public"
|
559
544
|
) -> TableConstraints:
|
@@ -765,8 +750,8 @@ async def create_table_class_from_db(
|
|
765
750
|
column_name, constraint_table.name
|
766
751
|
)
|
767
752
|
if trigger:
|
768
|
-
kwargs["on_update"] =
|
769
|
-
kwargs["on_delete"] =
|
753
|
+
kwargs["on_update"] = OnUpdate(trigger.on_update)
|
754
|
+
kwargs["on_delete"] = OnDelete(trigger.on_delete)
|
770
755
|
else:
|
771
756
|
output_schema.trigger_warnings.append(
|
772
757
|
f"{tablename}.{column_name}"
|
@@ -0,0 +1,92 @@
|
|
1
|
+
from dataclasses import dataclass
|
2
|
+
|
3
|
+
from piccolo.columns import ForeignKey
|
4
|
+
from piccolo.columns.base import OnDelete, OnUpdate
|
5
|
+
|
6
|
+
|
7
|
+
async def get_fk_constraint_name(column: ForeignKey) -> str:
|
8
|
+
"""
|
9
|
+
Checks what the foreign key constraint is called in the database.
|
10
|
+
"""
|
11
|
+
|
12
|
+
table = column._meta.table
|
13
|
+
|
14
|
+
if table._meta.db.engine_type == "sqlite":
|
15
|
+
# TODO - add the query for SQLite
|
16
|
+
raise ValueError("SQLite isn't currently supported.")
|
17
|
+
|
18
|
+
schema = table._meta.schema or "public"
|
19
|
+
table_name = table._meta.tablename
|
20
|
+
column_name = column._meta.db_column_name
|
21
|
+
|
22
|
+
constraints = await table.raw(
|
23
|
+
"""
|
24
|
+
SELECT
|
25
|
+
kcu.constraint_name AS fk_constraint_name
|
26
|
+
FROM
|
27
|
+
information_schema.referential_constraints AS rc
|
28
|
+
INNER JOIN
|
29
|
+
information_schema.key_column_usage AS kcu
|
30
|
+
ON kcu.constraint_catalog = rc.constraint_catalog
|
31
|
+
AND kcu.constraint_schema = rc.constraint_schema
|
32
|
+
AND kcu.constraint_name = rc.constraint_name
|
33
|
+
WHERE
|
34
|
+
kcu.table_schema = {} AND
|
35
|
+
kcu.table_name = {} AND
|
36
|
+
kcu.column_name = {}
|
37
|
+
""",
|
38
|
+
schema,
|
39
|
+
table_name,
|
40
|
+
column_name,
|
41
|
+
)
|
42
|
+
|
43
|
+
return constraints[0]["fk_constraint_name"]
|
44
|
+
|
45
|
+
|
46
|
+
@dataclass
|
47
|
+
class ConstraintRules:
|
48
|
+
on_delete: OnDelete
|
49
|
+
on_update: OnUpdate
|
50
|
+
|
51
|
+
|
52
|
+
async def get_fk_constraint_rules(column: ForeignKey) -> ConstraintRules:
|
53
|
+
"""
|
54
|
+
Checks the constraint rules for this foreign key in the database.
|
55
|
+
"""
|
56
|
+
table = column._meta.table
|
57
|
+
|
58
|
+
if table._meta.db.engine_type == "sqlite":
|
59
|
+
# TODO - add the query for SQLite
|
60
|
+
raise ValueError("SQLite isn't currently supported.")
|
61
|
+
|
62
|
+
schema = table._meta.schema or "public"
|
63
|
+
table_name = table._meta.tablename
|
64
|
+
column_name = column._meta.db_column_name
|
65
|
+
|
66
|
+
constraints = await table.raw(
|
67
|
+
"""
|
68
|
+
SELECT
|
69
|
+
kcu.constraint_name,
|
70
|
+
kcu.table_name,
|
71
|
+
kcu.column_name,
|
72
|
+
rc.update_rule,
|
73
|
+
rc.delete_rule
|
74
|
+
FROM
|
75
|
+
information_schema.key_column_usage AS kcu
|
76
|
+
INNER JOIN
|
77
|
+
information_schema.referential_constraints AS rc
|
78
|
+
ON kcu.constraint_name = rc.constraint_name
|
79
|
+
WHERE
|
80
|
+
kcu.table_schema = {} AND
|
81
|
+
kcu.table_name = {} AND
|
82
|
+
kcu.column_name = {}
|
83
|
+
""",
|
84
|
+
schema,
|
85
|
+
table_name,
|
86
|
+
column_name,
|
87
|
+
)
|
88
|
+
|
89
|
+
return ConstraintRules(
|
90
|
+
on_delete=OnDelete(constraints[0]["delete_rule"]),
|
91
|
+
on_update=OnUpdate(constraints[0]["update_rule"]),
|
92
|
+
)
|
piccolo/query/methods/alter.py
CHANGED
@@ -36,6 +36,18 @@ class RenameTable(AlterStatement):
|
|
36
36
|
return f"RENAME TO {self.new_name}"
|
37
37
|
|
38
38
|
|
39
|
+
@dataclass
|
40
|
+
class RenameConstraint(AlterStatement):
|
41
|
+
__slots__ = ("old_name", "new_name")
|
42
|
+
|
43
|
+
old_name: str
|
44
|
+
new_name: str
|
45
|
+
|
46
|
+
@property
|
47
|
+
def ddl(self) -> str:
|
48
|
+
return f"RENAME CONSTRAINT {self.old_name} TO {self.new_name}"
|
49
|
+
|
50
|
+
|
39
51
|
@dataclass
|
40
52
|
class AlterColumnStatement(AlterStatement):
|
41
53
|
__slots__ = ("column",)
|
@@ -194,6 +206,7 @@ class AddForeignKeyConstraint(AlterStatement):
|
|
194
206
|
"constraint_name",
|
195
207
|
"foreign_key_column_name",
|
196
208
|
"referenced_table_name",
|
209
|
+
"referenced_column_name",
|
197
210
|
"on_delete",
|
198
211
|
"on_update",
|
199
212
|
)
|
@@ -201,9 +214,9 @@ class AddForeignKeyConstraint(AlterStatement):
|
|
201
214
|
constraint_name: str
|
202
215
|
foreign_key_column_name: str
|
203
216
|
referenced_table_name: str
|
217
|
+
referenced_column_name: str
|
204
218
|
on_delete: t.Optional[OnDelete]
|
205
219
|
on_update: t.Optional[OnUpdate]
|
206
|
-
referenced_column_name: str = "id"
|
207
220
|
|
208
221
|
@property
|
209
222
|
def ddl(self) -> str:
|
@@ -273,8 +286,8 @@ class DropTable:
|
|
273
286
|
|
274
287
|
class Alter(DDL):
|
275
288
|
__slots__ = (
|
276
|
-
"_add_foreign_key_constraint",
|
277
289
|
"_add",
|
290
|
+
"_add_foreign_key_constraint",
|
278
291
|
"_drop_constraint",
|
279
292
|
"_drop_default",
|
280
293
|
"_drop_table",
|
@@ -288,6 +301,7 @@ class Alter(DDL):
|
|
288
301
|
"_set_null",
|
289
302
|
"_set_schema",
|
290
303
|
"_set_unique",
|
304
|
+
"_rename_constraint",
|
291
305
|
)
|
292
306
|
|
293
307
|
def __init__(self, table: t.Type[Table], **kwargs):
|
@@ -307,6 +321,7 @@ class Alter(DDL):
|
|
307
321
|
self._set_null: t.List[SetNull] = []
|
308
322
|
self._set_schema: t.List[SetSchema] = []
|
309
323
|
self._set_unique: t.List[SetUnique] = []
|
324
|
+
self._rename_constraint: t.List[RenameConstraint] = []
|
310
325
|
|
311
326
|
def add_column(self: Self, name: str, column: Column) -> Self:
|
312
327
|
"""
|
@@ -372,6 +387,24 @@ class Alter(DDL):
|
|
372
387
|
self._rename_table = [RenameTable(new_name=new_name)]
|
373
388
|
return self
|
374
389
|
|
390
|
+
def rename_constraint(self, old_name: str, new_name: str) -> Alter:
|
391
|
+
"""
|
392
|
+
Rename a constraint on the table::
|
393
|
+
|
394
|
+
>>> await Band.alter().rename_constraint(
|
395
|
+
... 'old_constraint_name',
|
396
|
+
... 'new_constraint_name',
|
397
|
+
... )
|
398
|
+
|
399
|
+
"""
|
400
|
+
self._rename_constraint = [
|
401
|
+
RenameConstraint(
|
402
|
+
old_name=old_name,
|
403
|
+
new_name=new_name,
|
404
|
+
)
|
405
|
+
]
|
406
|
+
return self
|
407
|
+
|
375
408
|
def rename_column(
|
376
409
|
self, column: t.Union[str, Column], new_name: str
|
377
410
|
) -> Alter:
|
@@ -488,7 +521,7 @@ class Alter(DDL):
|
|
488
521
|
def _get_constraint_name(self, column: t.Union[str, ForeignKey]) -> str:
|
489
522
|
column_name = AlterColumnStatement(column=column).column_name
|
490
523
|
tablename = self.table._meta.tablename
|
491
|
-
return f"{tablename}_{column_name}
|
524
|
+
return f"{tablename}_{column_name}_fkey"
|
492
525
|
|
493
526
|
def drop_constraint(self, constraint_name: str) -> Alter:
|
494
527
|
self._drop_constraint.append(
|
@@ -500,37 +533,58 @@ class Alter(DDL):
|
|
500
533
|
self, column: t.Union[str, ForeignKey]
|
501
534
|
) -> Alter:
|
502
535
|
constraint_name = self._get_constraint_name(column=column)
|
503
|
-
|
536
|
+
self._drop_constraint.append(
|
537
|
+
DropConstraint(constraint_name=constraint_name)
|
538
|
+
)
|
539
|
+
return self
|
504
540
|
|
505
541
|
def add_foreign_key_constraint(
|
506
542
|
self,
|
507
543
|
column: t.Union[str, ForeignKey],
|
508
|
-
referenced_table_name: str,
|
544
|
+
referenced_table_name: t.Optional[str] = None,
|
545
|
+
referenced_column_name: t.Optional[str] = None,
|
546
|
+
constraint_name: t.Optional[str] = None,
|
509
547
|
on_delete: t.Optional[OnDelete] = None,
|
510
548
|
on_update: t.Optional[OnUpdate] = None,
|
511
|
-
referenced_column_name: str = "id",
|
512
549
|
) -> Alter:
|
513
550
|
"""
|
514
551
|
Add a new foreign key constraint::
|
515
552
|
|
516
553
|
>>> await Band.alter().add_foreign_key_constraint(
|
517
554
|
... Band.manager,
|
518
|
-
... referenced_table_name='manager',
|
519
555
|
... on_delete=OnDelete.cascade
|
520
556
|
... )
|
521
557
|
|
522
558
|
"""
|
523
|
-
constraint_name = self._get_constraint_name(
|
559
|
+
constraint_name = constraint_name or self._get_constraint_name(
|
560
|
+
column=column
|
561
|
+
)
|
524
562
|
column_name = AlterColumnStatement(column=column).column_name
|
525
563
|
|
564
|
+
if referenced_column_name is None:
|
565
|
+
if isinstance(column, ForeignKey):
|
566
|
+
referenced_column_name = (
|
567
|
+
column._foreign_key_meta.resolved_target_column._meta.db_column_name # noqa: E501
|
568
|
+
)
|
569
|
+
else:
|
570
|
+
raise ValueError("Please pass in `referenced_column_name`.")
|
571
|
+
|
572
|
+
if referenced_table_name is None:
|
573
|
+
if isinstance(column, ForeignKey):
|
574
|
+
referenced_table_name = (
|
575
|
+
column._foreign_key_meta.resolved_references._meta.tablename # noqa: E501
|
576
|
+
)
|
577
|
+
else:
|
578
|
+
raise ValueError("Please pass in `referenced_table_name`.")
|
579
|
+
|
526
580
|
self._add_foreign_key_constraint.append(
|
527
581
|
AddForeignKeyConstraint(
|
528
582
|
constraint_name=constraint_name,
|
529
583
|
foreign_key_column_name=column_name,
|
530
584
|
referenced_table_name=referenced_table_name,
|
585
|
+
referenced_column_name=referenced_column_name,
|
531
586
|
on_delete=on_delete,
|
532
587
|
on_update=on_update,
|
533
|
-
referenced_column_name=referenced_column_name,
|
534
588
|
)
|
535
589
|
)
|
536
590
|
return self
|
@@ -579,9 +633,12 @@ class Alter(DDL):
|
|
579
633
|
i.ddl
|
580
634
|
for i in itertools.chain(
|
581
635
|
self._add,
|
636
|
+
self._add_foreign_key_constraint,
|
582
637
|
self._rename_columns,
|
583
638
|
self._rename_table,
|
639
|
+
self._rename_constraint,
|
584
640
|
self._drop,
|
641
|
+
self._drop_constraint,
|
585
642
|
self._drop_default,
|
586
643
|
self._set_column_type,
|
587
644
|
self._set_unique,
|
piccolo/utils/sync.py
CHANGED
@@ -2,10 +2,14 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import asyncio
|
4
4
|
import typing as t
|
5
|
-
from concurrent.futures import ThreadPoolExecutor
|
5
|
+
from concurrent.futures import Future, ThreadPoolExecutor
|
6
6
|
|
7
|
+
ReturnType = t.TypeVar("ReturnType")
|
7
8
|
|
8
|
-
|
9
|
+
|
10
|
+
def run_sync(
|
11
|
+
coroutine: t.Coroutine[t.Any, t.Any, ReturnType],
|
12
|
+
) -> ReturnType:
|
9
13
|
"""
|
10
14
|
Run the coroutine synchronously - trying to accommodate as many edge cases
|
11
15
|
as possible.
|
@@ -20,5 +24,5 @@ def run_sync(coroutine: t.Coroutine):
|
|
20
24
|
except RuntimeError:
|
21
25
|
# An event loop already exists.
|
22
26
|
with ThreadPoolExecutor(max_workers=1) as executor:
|
23
|
-
future = executor.submit(asyncio.run, coroutine)
|
27
|
+
future: Future = executor.submit(asyncio.run, coroutine)
|
24
28
|
return future.result()
|
@@ -1,4 +1,4 @@
|
|
1
|
-
piccolo/__init__.py,sha256=
|
1
|
+
piccolo/__init__.py,sha256=ZVRfjDuz3xhQA4e78KxBcezkGjqcWBkBGlP0bm-NFD8,23
|
2
2
|
piccolo/custom_types.py,sha256=7HMQAze-5mieNLfbQ5QgbRQgR2abR7ol0qehv2SqROY,604
|
3
3
|
piccolo/main.py,sha256=1VsFV67FWTUikPTysp64Fmgd9QBVa_9wcwKfwj2UCEA,5117
|
4
4
|
piccolo/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -66,7 +66,7 @@ piccolo/apps/migrations/piccolo_app.py,sha256=1EcS2ComBPCaMCC2C3WaPR_GqLwt3XiIJN
|
|
66
66
|
piccolo/apps/migrations/tables.py,sha256=jqBnK-Rk545v1Eu6GaLHTVz7-uwBTUnz2m58OA-mxTc,799
|
67
67
|
piccolo/apps/migrations/auto/__init__.py,sha256=eYb1rZQaalumv_bhbcEe6x3dUglmpFtw7Egg6k7597U,316
|
68
68
|
piccolo/apps/migrations/auto/diffable_table.py,sha256=1HdqGeWFUYVJ2cJg6DZWOCh67SbgCxFVc554uD7N71A,7405
|
69
|
-
piccolo/apps/migrations/auto/migration_manager.py,sha256=
|
69
|
+
piccolo/apps/migrations/auto/migration_manager.py,sha256=5M2_01_FsZj6zIGXLEwkyEAPF2e-ICNB2_ZcBWwifCQ,37267
|
70
70
|
piccolo/apps/migrations/auto/operations.py,sha256=169IrCLR3FtTRxHsEHNg6dTG45lcEM7Aoyy3SwgX_hU,1329
|
71
71
|
piccolo/apps/migrations/auto/schema_differ.py,sha256=VA1rK-_wNSdyZZgfA3ZOlpVGJCcvLyouKtT9k2YKhiA,26266
|
72
72
|
piccolo/apps/migrations/auto/schema_snapshot.py,sha256=ZqUg4NpChOeoACKF2gkhqsz1BW3wOWFnzJCccq-CNNQ,4719
|
@@ -93,7 +93,7 @@ piccolo/apps/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
|
|
93
93
|
piccolo/apps/schema/piccolo_app.py,sha256=De9eujzB6zWsP6J1gHYUk_f5_DpjvTZVXJsQ3eXBgnA,432
|
94
94
|
piccolo/apps/schema/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
95
95
|
piccolo/apps/schema/commands/exceptions.py,sha256=ZOGL3iV-xtWbWsImXObrXNaKtNPY_Qk1OmaOMOV6Ps0,236
|
96
|
-
piccolo/apps/schema/commands/generate.py,sha256=
|
96
|
+
piccolo/apps/schema/commands/generate.py,sha256=xYRz9P4cdahSHzAIiXhXBzg6eUqV0WB2THSRZH7uPhU,30415
|
97
97
|
piccolo/apps/schema/commands/graph.py,sha256=FuQUPavUXpr-Y_11XRr11DbVLsgK8uG0IN8uBZIe5G4,3190
|
98
98
|
piccolo/apps/schema/commands/templates/graphviz.dot.jinja,sha256=-legygtsueOC70aboX35ZJpbCAXcv3E8RXXvFDQTeIY,1443
|
99
99
|
piccolo/apps/shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -153,6 +153,7 @@ piccolo/engine/postgres.py,sha256=DekL3KafCdzSAEQ6_EgOiUB1ERXh2xpePYwI9QvmN-c,18
|
|
153
153
|
piccolo/engine/sqlite.py,sha256=Oe0GBrIUSUkutvk5LoXGWC6HFQzKeusfql5-NMssH_s,25735
|
154
154
|
piccolo/query/__init__.py,sha256=bcsMV4813rMRAIqGv4DxI4eyO4FmpXkDv9dfTk5pt3A,699
|
155
155
|
piccolo/query/base.py,sha256=sO5VyicbWjgYaQukr6jqUqUUrOctL6QJ1MjcsgDKHXM,14912
|
156
|
+
piccolo/query/constraints.py,sha256=menFcqLKSM4697OSvMRZPsTgxHfR9GTvZZMrGDk2PrA,2601
|
156
157
|
piccolo/query/mixins.py,sha256=X9HEYnj6uOjgTkGr4vgqTwN_dokJPzVagwbFx385atQ,24468
|
157
158
|
piccolo/query/proxy.py,sha256=Yq4jNc7IWJvdeO3u7_7iPyRy2WhVj8KsIUcIYHBIi9Q,1839
|
158
159
|
piccolo/query/functions/__init__.py,sha256=pZkzOIh7Sg9HPNOeegOwAS46Oxt31ATlSVmwn-lxCbc,605
|
@@ -163,7 +164,7 @@ piccolo/query/functions/math.py,sha256=2Wapq0lpXZh77z0uzXUhnOfmUkbkM0xjQ4tiyuCsb
|
|
163
164
|
piccolo/query/functions/string.py,sha256=X3g_4qomJJCkYOcKcK-zZEqC6qJBrS4VTogPp9Xw4Cs,2506
|
164
165
|
piccolo/query/functions/type_conversion.py,sha256=OYbZc6TEk6b5yTwCMw2rmZ-UiQiUiWZOyxwMLzUjXwE,2583
|
165
166
|
piccolo/query/methods/__init__.py,sha256=tm4gLeV_obDqpgnouVjFbGubbaoJcqm_cbNd4LPo48Q,622
|
166
|
-
piccolo/query/methods/alter.py,sha256=
|
167
|
+
piccolo/query/methods/alter.py,sha256=tL8IIuEldBwegQOZM5N4IaoO2fH0tYLk8R7ra6PLD3s,18519
|
167
168
|
piccolo/query/methods/count.py,sha256=Vxn_7Ry-rleC6OGRxh-cLbuEMsy1DNjAZJThGED-_do,1748
|
168
169
|
piccolo/query/methods/create.py,sha256=hJ-6VVsWczzKDH6fQRN1WmYhcitixuXJ-eNOuCo_JgM,2742
|
169
170
|
piccolo/query/methods/create_index.py,sha256=gip_cRXZkLfpJqCL7KHk2l_7HLptoa-Ae8qu6I5d5c8,2224
|
@@ -195,11 +196,11 @@ piccolo/utils/printing.py,sha256=5VWNSfOrIGPh1VM-7fd4K18RGCYk0FQ5o-D4aLhzXZE,174
|
|
195
196
|
piccolo/utils/pydantic.py,sha256=RhoQZ7ddmFmepVcslHXMqmynbSVch7XLKUSgJkLuQS0,12327
|
196
197
|
piccolo/utils/repr.py,sha256=K3w-TAP9WPx8tbAIB2XDab_C4PHsPrB9TzwWfOHa4cc,787
|
197
198
|
piccolo/utils/sql_values.py,sha256=pGXmVTw6pWr8q7QA4xs7NiKSwjBzhN--3HXVjQv2SQQ,1749
|
198
|
-
piccolo/utils/sync.py,sha256=
|
199
|
+
piccolo/utils/sync.py,sha256=irmdTsYtURZNEBmIP6i2v2PyjgE-gK4t6VSxnBZ75Qo,920
|
199
200
|
piccolo/utils/warnings.py,sha256=ONrurw3HVCClUuHnpenMjg45dcFesrXqMgG9ifgP4_8,1247
|
200
201
|
piccolo/utils/graphlib/__init__.py,sha256=SUJ5Yh7LiRun3nkBuLUSVmGNHF6fANrxSoYan0mtYB0,200
|
201
202
|
piccolo/utils/graphlib/_graphlib.py,sha256=9FNGDSmTIEAk86FktniCe_J2yXjSE_sRZHDBAJJAUOw,9677
|
202
|
-
piccolo-1.
|
203
|
+
piccolo-1.26.0.dist-info/licenses/LICENSE,sha256=zFIpi-16uIJ420UMIG75NU0JbDBykvrdnXcj5U_EYBI,1059
|
203
204
|
profiling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
204
205
|
profiling/run_profile.py,sha256=264qsSFu93NTpExePnKQ9GkcN5fiuRBQ72WOSt0ZHck,829
|
205
206
|
tests/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -221,7 +222,7 @@ tests/apps/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
|
|
221
222
|
tests/apps/migrations/test_migration.py,sha256=JmPLtf2BCWX3Yofe0GQe40m8I_yWa_-3vk1lDfFDfIo,308
|
222
223
|
tests/apps/migrations/auto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
223
224
|
tests/apps/migrations/auto/test_diffable_table.py,sha256=p0cKDkfhmu96-rB9bonOlg5bmfQ7U9S2kRppOt4YxyU,3338
|
224
|
-
tests/apps/migrations/auto/test_migration_manager.py,sha256=
|
225
|
+
tests/apps/migrations/auto/test_migration_manager.py,sha256=qzYHC8nKm4pRtsgIyPDSZdXEWLOl2UDgTv6Mv8QO49k,37362
|
225
226
|
tests/apps/migrations/auto/test_schema_differ.py,sha256=UdsaZisA02j15wr1bXkXD6Cqu3p0A23NwFQLXsJdQL4,19391
|
226
227
|
tests/apps/migrations/auto/test_schema_snapshot.py,sha256=ZyvGZqn3N3cwd-3S-FME5AJ8buDSHesw7yPIvY6mE5k,6196
|
227
228
|
tests/apps/migrations/auto/test_serialisation.py,sha256=EFkhES1w9h51UCamWrhxs3mf4I718ggeP7Yl5J_UID4,13548
|
@@ -380,8 +381,8 @@ tests/utils/test_sql_values.py,sha256=vzxRmy16FfLZPH-sAQexBvsF9MXB8n4smr14qoEOS5
|
|
380
381
|
tests/utils/test_sync.py,sha256=9ytVo56y2vPQePvTeIi9lHIouEhWJbodl1TmzkGFrSo,799
|
381
382
|
tests/utils/test_table_reflection.py,sha256=SIzuat-IpcVj1GCFyOWKShI8YkhdOPPFH7qVrvfyPNE,3794
|
382
383
|
tests/utils/test_warnings.py,sha256=NvSC_cvJ6uZcwAGf1m-hLzETXCqprXELL8zg3TNLVMw,269
|
383
|
-
piccolo-1.
|
384
|
-
piccolo-1.
|
385
|
-
piccolo-1.
|
386
|
-
piccolo-1.
|
387
|
-
piccolo-1.
|
384
|
+
piccolo-1.26.0.dist-info/METADATA,sha256=UE7oErMiVueu8PQJLKAzHWoVIaXJtA2r9d1VZsOzwbU,5531
|
385
|
+
piccolo-1.26.0.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
|
386
|
+
piccolo-1.26.0.dist-info/entry_points.txt,sha256=SJPHET4Fi1bN5F3WqcKkv9SClK3_F1I7m4eQjk6AFh0,46
|
387
|
+
piccolo-1.26.0.dist-info/top_level.txt,sha256=-SR74VGbk43VoPy1HH-mHm97yoGukLK87HE5kdBW6qM,24
|
388
|
+
piccolo-1.26.0.dist-info/RECORD,,
|
@@ -12,8 +12,10 @@ from piccolo.columns.base import OnDelete, OnUpdate
|
|
12
12
|
from piccolo.columns.column_types import ForeignKey
|
13
13
|
from piccolo.conf.apps import AppConfig
|
14
14
|
from piccolo.engine import engine_finder
|
15
|
+
from piccolo.query.constraints import get_fk_constraint_rules
|
15
16
|
from piccolo.table import Table, sort_table_classes
|
16
17
|
from piccolo.utils.lazy_loader import LazyLoader
|
18
|
+
from piccolo.utils.sync import run_sync
|
17
19
|
from tests.base import AsyncMock, DBTestCase, engine_is, engines_only
|
18
20
|
from tests.example_apps.music.tables import Band, Concert, Manager, Venue
|
19
21
|
|
@@ -618,6 +620,54 @@ class TestMigrationManager(DBTestCase):
|
|
618
620
|
response = self.run_sync("SELECT * FROM manager;")
|
619
621
|
self.assertEqual(response, [{"id": id[0]["id"], "name": "Dave"}])
|
620
622
|
|
623
|
+
@engines_only("postgres", "cockroach")
|
624
|
+
def test_alter_fk_on_delete_on_update(self):
|
625
|
+
"""
|
626
|
+
Test altering OnDelete and OnUpdate with MigrationManager.
|
627
|
+
"""
|
628
|
+
# before performing migrations - OnDelete.no_action
|
629
|
+
self.assertEqual(
|
630
|
+
run_sync(get_fk_constraint_rules(column=Band.manager)).on_delete,
|
631
|
+
OnDelete.no_action,
|
632
|
+
)
|
633
|
+
|
634
|
+
manager = MigrationManager(app_name="music")
|
635
|
+
manager.alter_column(
|
636
|
+
table_class_name="Band",
|
637
|
+
tablename="band",
|
638
|
+
column_name="manager",
|
639
|
+
db_column_name="manager",
|
640
|
+
params={
|
641
|
+
"on_delete": OnDelete.set_null,
|
642
|
+
"on_update": OnUpdate.set_null,
|
643
|
+
},
|
644
|
+
old_params={
|
645
|
+
"on_delete": OnDelete.no_action,
|
646
|
+
"on_update": OnUpdate.no_action,
|
647
|
+
},
|
648
|
+
column_class=ForeignKey,
|
649
|
+
old_column_class=ForeignKey,
|
650
|
+
schema=None,
|
651
|
+
)
|
652
|
+
|
653
|
+
asyncio.run(manager.run())
|
654
|
+
|
655
|
+
# after performing migrations - OnDelete.set_null
|
656
|
+
self.assertEqual(
|
657
|
+
run_sync(get_fk_constraint_rules(column=Band.manager)).on_delete,
|
658
|
+
OnDelete.set_null,
|
659
|
+
)
|
660
|
+
|
661
|
+
# Reverse
|
662
|
+
asyncio.run(manager.run(backwards=True))
|
663
|
+
|
664
|
+
# after performing reverse migrations we have
|
665
|
+
# OnDelete.no_action again
|
666
|
+
self.assertEqual(
|
667
|
+
run_sync(get_fk_constraint_rules(column=Band.manager)).on_delete,
|
668
|
+
OnDelete.no_action,
|
669
|
+
)
|
670
|
+
|
621
671
|
@engines_only("postgres")
|
622
672
|
def test_alter_column_unique(self):
|
623
673
|
"""
|
File without changes
|
File without changes
|
File without changes
|