From d8387d0c35a74a9b7c0e2ff2b9706669ded02032 Mon Sep 17 00:00:00 2001 From: Pavlo Mishchenko Date: Thu, 22 May 2025 16:50:09 +0300 Subject: [PATCH 1/2] Add simple delete test with through m2m --- tests/_utils/setup.sql | 10 ++++++++++ tests/delete/models.py | 25 +++++++++++++++++++++++++ tests/delete/tests.py | 16 ++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/tests/_utils/setup.sql b/tests/_utils/setup.sql index 94c797335d7f..8298a5b8a728 100644 --- a/tests/_utils/setup.sql +++ b/tests/_utils/setup.sql @@ -590,3 +590,13 @@ CREATE TABLE `backends_object_object` ( KEY (`from_object_id`), KEY (`to_object_id`) ); + +-- delete +CREATE TABLE `delete_player_game` ( + `player_id` BIGINT NOT NULL, + `game_id` BIGINT NOT NULL, + SHARD KEY (`player_id`), + UNIQUE KEY (`player_id`, `game_id`), + KEY (`player_id`), + KEY(`game_id`) +); diff --git a/tests/delete/models.py b/tests/delete/models.py index 4b627712bb65..9c49869825a9 100644 --- a/tests/delete/models.py +++ b/tests/delete/models.py @@ -2,6 +2,8 @@ from django.contrib.contenttypes.models import ContentType from django.db import models +from django_singlestore.schema import ModelStorageManager + class P(models.Model): pass @@ -241,3 +243,26 @@ class GenericDeleteBottomParent(models.Model): generic_delete_bottom = models.ForeignKey( GenericDeleteBottom, on_delete=models.CASCADE ) + + +class Game(models.Model): + home = models.CharField(max_length=100) + away = models.CharField(max_length=100) + + objects = ModelStorageManager("ROWSTORE") + + +class Player(models.Model): + name = models.CharField(max_length=100) + games = models.ManyToManyField(Game, related_name="players", through="PlayerGame") + + objects = ModelStorageManager("ROWSTORE") + + +class PlayerGame(models.Model): + player = models.ForeignKey(Player, on_delete=models.CASCADE) + game = models.ForeignKey(Game, on_delete=models.CASCADE) + + class Meta: + unique_together = (('player', 'game'),) + db_table = "delete_player_game" diff --git a/tests/delete/tests.py b/tests/delete/tests.py index 01228631f4ba..39f226d3270a 100644 --- a/tests/delete/tests.py +++ b/tests/delete/tests.py @@ -37,6 +37,8 @@ S, T, User, + Game, + Player, create_a, get_default_r, ) @@ -800,3 +802,17 @@ def test_fast_delete_full_match(self): with self.assertNumQueries(1): User.objects.filter(~Q(pk__in=[]) | Q(avatar__desc="foo")).delete() self.assertFalse(User.objects.exists()) + + def test_delete_with_custom_m2m(self): + """ + Test that deletion of a model with a custom through model + that doesn't have id field works correctly. + """ + g1 = Game.objects.create() + g2 = Game.objects.create() + + player = Player.objects.create() + player.games.add(g1, g2) + g1.delete() + g2.delete() + self.assertFalse(Game.objects.exists()) From f334c47d811dbb5503f4fcd1daf12a872c1cf4e3 Mon Sep 17 00:00:00 2001 From: Pavlo Mishchenko Date: Thu, 22 May 2025 17:12:43 +0300 Subject: [PATCH 2/2] change storage type for delete tests --- tests/_utils/local_test.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/_utils/local_test.sh b/tests/_utils/local_test.sh index 1a52aa1c88f7..fd8da6374c41 100755 --- a/tests/_utils/local_test.sh +++ b/tests/_utils/local_test.sh @@ -29,6 +29,10 @@ export DJANGO_SINGLESTORE_TABLE_STORAGE_TYPE_MANY_TO_MANY="ROWSTORE REFERENCE" # a number of models with unique keys, 13 many-to-many fields export DJANGO_SINGLESTORE_TABLE_STORAGE_TYPE_FIXTURES_REGRESS="ROWSTORE REFERENCE" +# a model with 3 many-to-many fields caused issues +export DJANGO_SINGLESTORE_TABLE_STORAGE_TYPE_DELETE="ROWSTORE REFERENCE" + + # queries app has a lot of models with OneToOne relationships export DJANGO_SINGLESTORE_NOT_ENFORCED_UNIQUE_QUERIES=1