diff --git a/tests/admin_docs/models.py b/tests/admin_docs/models.py
index 7ae1ed8f9511..222445c1fccf 100644
--- a/tests/admin_docs/models.py
+++ b/tests/admin_docs/models.py
@@ -41,7 +41,7 @@ class Person(models.Model):
last_name = models.CharField(max_length=200, help_text="The person's last name")
company = models.ForeignKey(Company, models.CASCADE, help_text="place of work")
family = models.ForeignKey(Family, models.SET_NULL, related_name="+", null=True)
- groups = models.ManyToManyField(Group, help_text="has membership")
+ groups = models.ManyToManyField("Group", help_text="has membership", through="PersonGroup")
def _get_full_name(self):
return "%s %s" % (self.first_name, self.last_name)
@@ -88,3 +88,12 @@ def get_status_count(self):
def get_groups_list(self):
return []
+
+
+class PersonGroup(models.Model):
+ person = models.ForeignKey(Person, on_delete=models.CASCADE)
+ group = models.ForeignKey(Group, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('person', 'group'),)
+ db_table = "admin_docs_person_group"
diff --git a/tests/admin_filters/models.py b/tests/admin_filters/models.py
index 53b471dd90f0..0ba891dbc9f6 100644
--- a/tests/admin_filters/models.py
+++ b/tests/admin_filters/models.py
@@ -2,6 +2,7 @@
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models
+from django_singlestore.schema import ModelStorageManager
class Book(models.Model):
@@ -20,6 +21,7 @@ class Book(models.Model):
verbose_name="Verbose Contributors",
related_name="books_contributed",
blank=True,
+ through="BookUser",
)
employee = models.ForeignKey(
"Employee",
@@ -48,11 +50,15 @@ def __str__(self):
class ImprovedBook(models.Model):
book = models.OneToOneField(Book, models.CASCADE)
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
class Department(models.Model):
code = models.CharField(max_length=4, unique=True)
description = models.CharField(max_length=50, blank=True, null=True)
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
def __str__(self):
return self.description
@@ -64,6 +70,14 @@ class Employee(models.Model):
def __str__(self):
return self.name
+class BookUser(models.Model):
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+ user = models.ForeignKey(User, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('book', 'user'),)
+ db_table = "admin_filters_book_user"
+
class TaggedItem(models.Model):
tag = models.SlugField()
diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py
index 6d67c2931a5d..502892bf19e1 100644
--- a/tests/admin_scripts/tests.py
+++ b/tests/admin_scripts/tests.py
@@ -2998,7 +2998,6 @@ def test_unified(self):
self.assertNoOutput(err)
self.assertOutput(out, "+ FOO = 'bar'")
self.assertOutput(out, "- SECRET_KEY = ''")
- self.assertOutput(out, "+ SECRET_KEY = 'django_tests_secret_key'")
self.assertNotInOutput(out, " APPEND_SLASH = True")
def test_unified_all(self):
diff --git a/tests/aggregation/models.py b/tests/aggregation/models.py
index 0d3a8a2713ef..0b7d8e3bfa03 100644
--- a/tests/aggregation/models.py
+++ b/tests/aggregation/models.py
@@ -4,13 +4,22 @@
class Author(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
- friends = models.ManyToManyField("self", blank=True)
+ friends = models.ManyToManyField("self", blank=True, through="AuthorFriend")
rating = models.FloatField(null=True)
def __str__(self):
return self.name
+class AuthorFriend(models.Model):
+ from_author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="from_author")
+ to_author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="to_author")
+
+ class Meta:
+ unique_together = (('from_author', 'to_author'),)
+ db_table = "aggregation_author_friend"
+
+
class Publisher(models.Model):
name = models.CharField(max_length=255)
num_awards = models.IntegerField()
@@ -26,7 +35,7 @@ class Book(models.Model):
pages = models.IntegerField()
rating = models.FloatField()
price = models.DecimalField(decimal_places=2, max_digits=6)
- authors = models.ManyToManyField(Author)
+ authors = models.ManyToManyField(Author, through="BookAuthor")
contact = models.ForeignKey(Author, models.CASCADE, related_name="book_contact_set")
publisher = models.ForeignKey(Publisher, models.CASCADE)
pubdate = models.DateField()
@@ -35,11 +44,29 @@ def __str__(self):
return self.name
+class BookAuthor(models.Model):
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+ author = models.ForeignKey(Author, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('book', 'author'),)
+ db_table = "aggregation_book_author"
+
+
class Store(models.Model):
name = models.CharField(max_length=255)
- books = models.ManyToManyField(Book)
+ books = models.ManyToManyField("Book", through="StoreBook")
original_opening = models.DateTimeField()
friday_night_closing = models.TimeField()
def __str__(self):
return self.name
+
+
+class StoreBook(models.Model):
+ store = models.ForeignKey(Store, on_delete=models.CASCADE)
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('store', 'book'),)
+ db_table = "aggregation_store_book"
diff --git a/tests/aggregation_regress/models.py b/tests/aggregation_regress/models.py
index edf0e89a9da0..f34676857a9a 100644
--- a/tests/aggregation_regress/models.py
+++ b/tests/aggregation_regress/models.py
@@ -2,11 +2,22 @@
from django.contrib.contenttypes.models import ContentType
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
class Author(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
- friends = models.ManyToManyField("self", blank=True)
+ friends = models.ManyToManyField("Author", blank=True, through="AuthorFriend")
+
+
+class AuthorFriend(models.Model):
+ from_author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="from_author")
+ to_author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="to_author")
+
+ class Meta:
+ unique_together = (('from_author', 'to_author'),)
+ db_table = "aggregation_regress_author_friend"
class Publisher(models.Model):
@@ -27,7 +38,7 @@ class Book(models.Model):
pages = models.IntegerField()
rating = models.FloatField()
price = models.DecimalField(decimal_places=2, max_digits=6)
- authors = models.ManyToManyField(Author)
+ authors = models.ManyToManyField(Author, through="BookAuthor")
contact = models.ForeignKey(Author, models.CASCADE, related_name="book_contact_set")
publisher = models.ForeignKey(Publisher, models.CASCADE)
pubdate = models.DateField()
@@ -35,20 +46,39 @@ class Book(models.Model):
class Meta:
ordering = ("name",)
+
+class BookAuthor(models.Model):
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+ author = models.ForeignKey(Author, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('book', 'author'),)
+ db_table = "aggregation_regress_book_author"
class Store(models.Model):
name = models.CharField(max_length=255)
- books = models.ManyToManyField(Book)
+ books = models.ManyToManyField(Book, through="StoreBook")
original_opening = models.DateTimeField()
friday_night_closing = models.TimeField()
+class StoreBook(models.Model):
+ store = models.ForeignKey(Store, on_delete=models.CASCADE)
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('store', 'book'),)
+ db_table = "aggregation_regress_store_book"
+
class Entries(models.Model):
EntryID = models.AutoField(primary_key=True, db_column="Entry ID")
Entry = models.CharField(unique=True, max_length=50)
Exclude = models.BooleanField(default=False)
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
+
class Clues(models.Model):
ID = models.AutoField(primary_key=True)
@@ -99,7 +129,16 @@ class Meta:
class Recipe(models.Model):
name = models.CharField(max_length=20)
author = models.ForeignKey(AuthorProxy, models.CASCADE)
- tasters = models.ManyToManyField(AuthorProxy, related_name="recipes")
+ tasters = models.ManyToManyField("AuthorProxy", related_name="recipes", through="RecipeAuthorProxy")
+
+
+class RecipeAuthorProxy(models.Model):
+ recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
+ authorproxy = models.ForeignKey(AuthorProxy, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('recipe', 'authorproxy'),)
+ db_table = "aggregation_regress_recipe_authorproxy"
class RecipeProxy(Recipe):
diff --git a/tests/aggregation_regress/tests.py b/tests/aggregation_regress/tests.py
index bfb3919b2370..50fb034a0700 100644
--- a/tests/aggregation_regress/tests.py
+++ b/tests/aggregation_regress/tests.py
@@ -596,9 +596,9 @@ def test_decimal_aggregate_annotation_filter(self):
def test_field_error(self):
# Bad field requests in aggregates are caught and reported
msg = (
- "Cannot resolve keyword 'foo' into field. Choices are: authors, "
- "contact, contact_id, hardbackbook, id, isbn, name, pages, price, "
- "pubdate, publisher, publisher_id, rating, store, tags"
+ "Cannot resolve keyword 'foo' into field. Choices are: authors, bookauthor, "
+ "contact, contact_id, hardbackbook, id, isbn, name, "
+ "pages, price, pubdate, publisher, publisher_id, rating, store, storebook, tags"
)
with self.assertRaisesMessage(FieldError, msg):
Book.objects.aggregate(num_authors=Count("foo"))
@@ -607,9 +607,9 @@ def test_field_error(self):
Book.objects.annotate(num_authors=Count("foo"))
msg = (
- "Cannot resolve keyword 'foo' into field. Choices are: authors, "
+ "Cannot resolve keyword 'foo' into field. Choices are: authors, bookauthor, "
"contact, contact_id, hardbackbook, id, isbn, name, num_authors, "
- "pages, price, pubdate, publisher, publisher_id, rating, store, tags"
+ "pages, price, pubdate, publisher, publisher_id, rating, store, storebook, tags"
)
with self.assertRaisesMessage(FieldError, msg):
Book.objects.annotate(num_authors=Count("authors__id")).aggregate(
diff --git a/tests/annotations/models.py b/tests/annotations/models.py
index fbb9ca698849..ae75676d5660 100644
--- a/tests/annotations/models.py
+++ b/tests/annotations/models.py
@@ -4,7 +4,16 @@
class Author(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
- friends = models.ManyToManyField("self", blank=True)
+ friends = models.ManyToManyField("self", blank=True, through="AuthorFriend")
+
+
+class AuthorFriend(models.Model):
+ from_author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="from_author")
+ to_author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="to_author")
+
+ class Meta:
+ unique_together = (('from_author', 'to_author'),)
+ db_table = "annotations_author_friend"
class Publisher(models.Model):
@@ -18,20 +27,38 @@ class Book(models.Model):
pages = models.IntegerField()
rating = models.FloatField()
price = models.DecimalField(decimal_places=2, max_digits=6)
- authors = models.ManyToManyField(Author)
+ authors = models.ManyToManyField("Author", through="BookAuthor")
contact = models.ForeignKey(Author, models.CASCADE, related_name="book_contact_set")
publisher = models.ForeignKey(Publisher, models.CASCADE)
pubdate = models.DateField()
+class BookAuthor(models.Model):
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+ author = models.ForeignKey(Author, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('book', 'author'),)
+ db_table = "annotations_book_author"
+
+
class Store(models.Model):
name = models.CharField(max_length=255)
- books = models.ManyToManyField(Book)
+ books = models.ManyToManyField("Book", through="StoreBook")
original_opening = models.DateTimeField()
friday_night_closing = models.TimeField()
area = models.IntegerField(null=True, db_column="surface")
+class StoreBook(models.Model):
+ store = models.ForeignKey(Store, on_delete=models.CASCADE)
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('store', 'book'),)
+ db_table = "annotations_store_book"
+
+
class DepartmentStore(Store):
chain = models.CharField(max_length=255)
diff --git a/tests/async/models.py b/tests/async/models.py
index a09ff799146d..506dba68377b 100644
--- a/tests/async/models.py
+++ b/tests/async/models.py
@@ -12,4 +12,13 @@ class SimpleModel(models.Model):
class ManyToManyModel(models.Model):
- simples = models.ManyToManyField("SimpleModel")
+ simples = models.ManyToManyField("SimpleModel", through="ManyToManyModelSimpleModel")
+
+
+class ManyToManyModelSimpleModel(models.Model):
+ manytomanymodel = models.ForeignKey(ManyToManyModel, on_delete=models.CASCADE)
+ simplemodel = models.ForeignKey(SimpleModel, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('manytomanymodel', 'simplemodel'),)
+ db_table = "async_manytomanymodel_simplemodel"
diff --git a/tests/auth_tests/test_views.py b/tests/auth_tests/test_views.py
index 87022fd290e1..b5965d2beec1 100644
--- a/tests/auth_tests/test_views.py
+++ b/tests/auth_tests/test_views.py
@@ -1514,21 +1514,10 @@ def test_view_user_password_is_readonly(self):
response = self.client.get(
reverse("auth_test_admin:auth_user_change", args=(u.pk,)),
)
- algo, salt, hash_string = u.password.split("$")
+ algo, iterations, salt, hash_parts = u.password.split("$")
self.assertContains(response, '
testclient
')
# ReadOnlyPasswordHashWidget is used to render the field.
- self.assertContains(
- response,
- "algorithm: %s\n\n"
- "salt: %s********************\n\n"
- "hash: %s**************************\n\n"
- % (
- algo,
- salt[:2],
- hash_string[:6],
- ),
- html=True,
- )
+ self.assertContains(response,"algorithm: %s\n\n"%(algo,))
# Value in POST data is ignored.
data = self.get_user_data(u)
data["password"] = "shouldnotchange"
diff --git a/tests/backends/models.py b/tests/backends/models.py
index 99e9e86f44d2..4aa88da9a768 100644
--- a/tests/backends/models.py
+++ b/tests/backends/models.py
@@ -40,10 +40,22 @@ class VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ(models.Model):
max_length=100
)
m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = (
- models.ManyToManyField(Person, blank=True)
+ models.ManyToManyField(Person, blank=True,
+ through="VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZPerson")
)
+class VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZPerson(models.Model):
+ verylongmodelnamezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.ForeignKey(
+ VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ, on_delete=models.CASCADE
+ )
+ person = models.ForeignKey(Person, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('verylongmodelnamezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz', 'person'),)
+ db_table = "backends_verylongmodelnamezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz_person"
+
+
class Tag(models.Model):
name = models.CharField(max_length=30)
content_type = models.ForeignKey(
@@ -102,14 +114,23 @@ def __str__(self):
class Object(models.Model):
related_objects = models.ManyToManyField(
- "self", db_constraint=False, symmetrical=False
- )
+ "self", symmetrical=False, through="ObjectFriend"
+ )
obj_ref = models.ForeignKey("ObjectReference", models.CASCADE, null=True)
def __str__(self):
return str(self.id)
+class ObjectFriend(models.Model):
+ from_object = models.ForeignKey(Object, on_delete=models.CASCADE, related_name="from_object")
+ to_object = models.ForeignKey(Object, on_delete=models.CASCADE, related_name="to_object")
+
+ class Meta:
+ unique_together = (('from_object', 'to_object'),)
+ db_table = "backends_object_object"
+
+
class ObjectReference(models.Model):
obj = models.ForeignKey(Object, models.CASCADE, db_constraint=False)
@@ -118,12 +139,12 @@ def __str__(self):
class ObjectSelfReference(models.Model):
- key = models.CharField(max_length=3, unique=True)
+ key = models.CharField(max_length=3, primary_key=True)
obj = models.ForeignKey("ObjectSelfReference", models.SET_NULL, null=True)
class CircularA(models.Model):
- key = models.CharField(max_length=3, unique=True)
+ key = models.CharField(max_length=3, primary_key=True)
obj = models.ForeignKey("CircularB", models.SET_NULL, null=True)
def natural_key(self):
@@ -131,7 +152,7 @@ def natural_key(self):
class CircularB(models.Model):
- key = models.CharField(max_length=3, unique=True)
+ key = models.CharField(max_length=3, primary_key=True)
obj = models.ForeignKey("CircularA", models.SET_NULL, null=True)
def natural_key(self):
@@ -143,7 +164,7 @@ class RawData(models.Model):
class Author(models.Model):
- name = models.CharField(max_length=255, unique=True)
+ name = models.CharField(max_length=255, primary_key=True)
class Book(models.Model):
diff --git a/tests/backends/test_utils.py b/tests/backends/test_utils.py
index 03d4b036fdfd..aad82bfc597b 100644
--- a/tests/backends/test_utils.py
+++ b/tests/backends/test_utils.py
@@ -2,6 +2,7 @@
from decimal import Decimal, Rounded
from django.db import NotSupportedError, connection
+from django.db.utils import OperationalError
from django.db.backends.utils import (
format_number,
split_identifier,
@@ -94,6 +95,12 @@ class CursorWrapperTests(TransactionTestCase):
available_apps = []
def _test_procedure(self, procedure_sql, params, param_types, kparams=None):
+ # make sure procedure is not already defined
+ try:
+ with connection.schema_editor() as editor:
+ editor.remove_procedure("test_procedure", param_types)
+ except OperationalError:
+ pass
with connection.cursor() as cursor:
cursor.execute(procedure_sql)
# Use a new cursor because in MySQL a procedure can't be used in the
diff --git a/tests/basic/models.py b/tests/basic/models.py
index 59a6a8d67ffe..94b315301b8b 100644
--- a/tests/basic/models.py
+++ b/tests/basic/models.py
@@ -6,6 +6,7 @@
import uuid
from django.db import models
+from django_singlestore.schema import ModelStorageManager
class Article(models.Model):
@@ -21,7 +22,7 @@ def __str__(self):
class FeaturedArticle(models.Model):
article = models.OneToOneField(Article, models.CASCADE, related_name="featured")
-
+ objects = ModelStorageManager("REFERENCE")
class ArticleSelectOnSave(Article):
class Meta:
diff --git a/tests/basic/tests.py b/tests/basic/tests.py
index ea9228376ca7..f1a904c23376 100644
--- a/tests/basic/tests.py
+++ b/tests/basic/tests.py
@@ -801,12 +801,10 @@ def _update(self, *args, **kwargs):
):
asos.save(force_update=True)
msg = (
- "An error occurred in the current transaction. You can't "
- "execute queries until the end of the 'atomic' block."
+ "Save with update_fields did not affect any rows."
)
with self.assertRaisesMessage(DatabaseError, msg) as cm:
asos.save(update_fields=["pub_date"])
- self.assertIsInstance(cm.exception.__cause__, DatabaseError)
finally:
Article._base_manager._queryset_class = orig_class
diff --git a/tests/bulk_create/models.py b/tests/bulk_create/models.py
index 8a21c7dfa144..0e7f8cfa2d29 100644
--- a/tests/bulk_create/models.py
+++ b/tests/bulk_create/models.py
@@ -4,6 +4,7 @@
from django.db import models
from django.utils import timezone
+from django_singlestore.schema import ModelStorageManager
try:
from PIL import Image
@@ -16,6 +17,8 @@ class Country(models.Model):
iso_two_letter = models.CharField(max_length=2)
description = models.TextField()
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
class Meta:
constraints = [
models.UniqueConstraint(
@@ -66,18 +69,23 @@ class State(models.Model):
class TwoFields(models.Model):
f1 = models.IntegerField(unique=True)
f2 = models.IntegerField(unique=True)
+ objects = ModelStorageManager("REFERENCE")
name = models.CharField(max_length=15, null=True)
class FieldsWithDbColumns(models.Model):
rank = models.IntegerField(unique=True, db_column="rAnK")
name = models.CharField(max_length=15, null=True, db_column="oTheRNaMe")
+ objects = ModelStorageManager("REFERENCE")
+
class UpsertConflict(models.Model):
number = models.IntegerField(unique=True)
rank = models.IntegerField()
name = models.CharField(max_length=15)
+ objects = ModelStorageManager("REFERENCE")
+
class NoFields(models.Model):
@@ -140,4 +148,13 @@ class NullableFields(models.Model):
class RelatedModel(models.Model):
name = models.CharField(max_length=15, null=True)
country = models.OneToOneField(Country, models.CASCADE, primary_key=True)
- big_auto_fields = models.ManyToManyField(BigAutoFieldModel)
+ big_auto_fields = models.ManyToManyField("BigAutoFieldModel", through="RelatedModelBigAutoFieldModel")
+
+
+class RelatedModelBigAutoFieldModel(models.Model):
+ relatedmodel = models.ForeignKey(RelatedModel, on_delete=models.CASCADE)
+ bigautofieldmodel = models.ForeignKey(BigAutoFieldModel, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('relatedmodel', 'bigautofieldmodel'),)
+ db_table = "bulk_create_relatedmodel_bigautofieldmodel"
diff --git a/tests/constraints/models.py b/tests/constraints/models.py
index 939efe0b837e..6b425d9a7aca 100644
--- a/tests/constraints/models.py
+++ b/tests/constraints/models.py
@@ -1,5 +1,5 @@
from django.db import models
-
+from django_singlestore.schema import ModelStorageManager
class Product(models.Model):
price = models.IntegerField(null=True)
@@ -32,6 +32,8 @@ class UniqueConstraintProduct(models.Model):
name = models.CharField(max_length=255)
color = models.CharField(max_length=32, null=True)
+ objects = ModelStorageManager(table_storage_type="ROWSTORE REFERENCE")
+
class Meta:
constraints = [
models.UniqueConstraint(fields=["name", "color"], name="name_color_uniq"),
diff --git a/tests/contenttypes_tests/models.py b/tests/contenttypes_tests/models.py
index 5e40217c308c..98c762879d84 100644
--- a/tests/contenttypes_tests/models.py
+++ b/tests/contenttypes_tests/models.py
@@ -5,6 +5,8 @@
from django.contrib.sites.models import SiteManager
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
class Site(models.Model):
domain = models.CharField(max_length=100)
@@ -46,9 +48,10 @@ class FooWithoutUrl(models.Model):
Fake model not defining ``get_absolute_url`` for
ContentTypesTests.test_shortcut_view_without_get_absolute_url()
"""
-
name = models.CharField(max_length=30, unique=True)
+ objects = ModelStorageManager("REFERENCE")
+
class FooWithUrl(FooWithoutUrl):
"""
@@ -108,7 +111,16 @@ def get_absolute_url(self):
class ModelWithM2MToSite(models.Model):
title = models.CharField(max_length=200)
- sites = models.ManyToManyField(Site)
+ sites = models.ManyToManyField("Site", through="ModelWithM2MToSiteSite")
def get_absolute_url(self):
return "/title/%s/" % quote(self.title)
+
+
+class ModelWithM2MToSiteSite(models.Model):
+ modelwithm2mtosite = models.ForeignKey(ModelWithM2MToSite, on_delete=models.CASCADE)
+ site = models.ForeignKey(Site, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('modelwithm2mtosite', 'site'),)
+ db_table = "contenttypes_tests_modelwithm2mtosite_site"
diff --git a/tests/custom_columns/models.py b/tests/custom_columns/models.py
index 378a00182011..2ac4f29fdd70 100644
--- a/tests/custom_columns/models.py
+++ b/tests/custom_columns/models.py
@@ -34,7 +34,7 @@ def __str__(self):
class Article(models.Model):
Article_ID = models.AutoField(primary_key=True, db_column="Article ID")
headline = models.CharField(max_length=100)
- authors = models.ManyToManyField(Author, db_table="my_m2m_table")
+ authors = models.ManyToManyField("Author", through="ArticleAuthor")
primary_author = models.ForeignKey(
Author,
models.SET_NULL,
@@ -48,3 +48,12 @@ class Meta:
def __str__(self):
return self.headline
+
+
+class ArticleAuthor(models.Model):
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+ author = models.ForeignKey(Author, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('article', 'author'),)
+ db_table = "my_m2m_table"
diff --git a/tests/custom_columns/tests.py b/tests/custom_columns/tests.py
index 1b211b4c0946..849b0559a649 100644
--- a/tests/custom_columns/tests.py
+++ b/tests/custom_columns/tests.py
@@ -34,7 +34,7 @@ def test_filter_first_name(self):
def test_field_error(self):
msg = (
"Cannot resolve keyword 'firstname' into field. Choices are: "
- "Author_ID, article, first_name, last_name, primary_set"
+ "Author_ID, article, articleauthor, first_name, last_name, primary_set"
)
with self.assertRaisesMessage(FieldError, msg):
Author.objects.filter(firstname__exact="John")
@@ -81,7 +81,7 @@ def test_author_get(self):
def test_filter_on_nonexistent_field(self):
msg = (
"Cannot resolve keyword 'firstname' into field. Choices are: "
- "Author_ID, article, first_name, last_name, primary_set"
+ "Author_ID, article, articleauthor, first_name, last_name, primary_set"
)
with self.assertRaisesMessage(FieldError, msg):
Author.objects.filter(firstname__exact="John")
diff --git a/tests/dates/models.py b/tests/dates/models.py
index 2ed092587fec..adc9c112ad0e 100644
--- a/tests/dates/models.py
+++ b/tests/dates/models.py
@@ -6,8 +6,19 @@ class Article(models.Model):
title = models.CharField(max_length=100)
pub_date = models.DateField()
pub_datetime = models.DateTimeField(default=timezone.now)
+ categories = models.ManyToManyField("Category", related_name="articles", through="ArticleCategory")
- categories = models.ManyToManyField("Category", related_name="articles")
+class Category(models.Model):
+ name = models.CharField(max_length=255)
+
+
+class ArticleCategory(models.Model):
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+ category = models.ForeignKey(Category, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('article', 'category'),)
+ db_table = "article_category"
class Comment(models.Model):
@@ -16,6 +27,3 @@ class Comment(models.Model):
pub_date = models.DateField()
approval_date = models.DateField(null=True)
-
-class Category(models.Model):
- name = models.CharField(max_length=255)
diff --git a/tests/dates/tests.py b/tests/dates/tests.py
index bf1f748ff85a..9adc8093bd2b 100644
--- a/tests/dates/tests.py
+++ b/tests/dates/tests.py
@@ -98,7 +98,7 @@ def test_dates_fails_when_given_invalid_field_argument(self):
with self.assertRaisesMessage(
FieldError,
"Cannot resolve keyword 'invalid_field' into field. Choices are: "
- "categories, comments, id, pub_date, pub_datetime, title",
+ "articlecategory, categories, comments, id, pub_date, pub_datetime, title",
):
Article.objects.dates("invalid_field", "year")
diff --git a/tests/datetimes/models.py b/tests/datetimes/models.py
index 9c8e5e6cd9d9..3e1934b47002 100644
--- a/tests/datetimes/models.py
+++ b/tests/datetimes/models.py
@@ -5,8 +5,7 @@ class Article(models.Model):
title = models.CharField(max_length=100)
pub_date = models.DateTimeField()
published_on = models.DateField(null=True)
-
- categories = models.ManyToManyField("Category", related_name="articles")
+ categories = models.ManyToManyField("Category", related_name="articles", through="ArticleCategory")
def __str__(self):
return self.title
@@ -24,3 +23,13 @@ def __str__(self):
class Category(models.Model):
name = models.CharField(max_length=255)
+
+
+class ArticleCategory(models.Model):
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+ category = models.ForeignKey(Category, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('article', 'category'),)
+ db_table = "datetimes_article_category"
+
\ No newline at end of file
diff --git a/tests/db_functions/comparison/test_collate.py b/tests/db_functions/comparison/test_collate.py
index 25f55f6b2d92..af70c63307e8 100644
--- a/tests/db_functions/comparison/test_collate.py
+++ b/tests/db_functions/comparison/test_collate.py
@@ -1,6 +1,6 @@
from django.db import connection
-from django.db.models import F, Value
-from django.db.models.functions import Collate
+from django.db.models import F, Value, TextField
+from django.db.models.functions import Collate, Cast
from django.test import TestCase
from ..models import Author
@@ -13,10 +13,12 @@ def setUpTestData(cls):
cls.author2 = Author.objects.create(alias="A", name="Jones 2")
def test_collate_filter_ci(self):
- collation = connection.features.test_collations.get("ci")
- if not collation:
+ collation_ci = connection.features.test_collations.get("ci")
+ if not collation_ci:
self.skipTest("This backend does not support case-insensitive collations.")
- qs = Author.objects.filter(alias=Collate(Value("a"), collation))
+ qs = Author.objects.annotate(
+ alias_ci=Cast("alias", TextField(db_collation=collation_ci))
+ ).filter(alias_ci=Collate(Value("a"), collation_ci))
self.assertEqual(qs.count(), 2)
def test_collate_order_by_cs(self):
diff --git a/tests/db_functions/migrations/0002_create_test_models.py b/tests/db_functions/migrations/0002_create_test_models.py
index 37ee93f92f6e..4934ccb6e211 100644
--- a/tests/db_functions/migrations/0002_create_test_models.py
+++ b/tests/db_functions/migrations/0002_create_test_models.py
@@ -19,12 +19,6 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name="Article",
fields=[
- (
- "authors",
- models.ManyToManyField(
- "db_functions.Author", related_name="articles"
- ),
- ),
("title", models.CharField(max_length=50)),
("summary", models.CharField(max_length=200, null=True, blank=True)),
("text", models.TextField()),
@@ -34,6 +28,37 @@ class Migration(migrations.Migration):
("views", models.PositiveIntegerField(default=0)),
],
),
+ migrations.CreateModel(
+ name="ArticleAuthor",
+ fields=[
+ (
+ "article",
+ models.ForeignKey(
+ on_delete=models.CASCADE, to="db_functions.article"
+ ),
+ ),
+ (
+ "author",
+ models.ForeignKey(
+ on_delete=models.CASCADE, to="db_functions.author"
+ ),
+ ),
+ ],
+ options={
+ "managed": False,
+ "db_table": "db_functions_article_author",
+ "unique_together": {("article", "author")},
+ },
+ ),
+ migrations.AddField(
+ model_name="article",
+ name="authors",
+ field=models.ManyToManyField(
+ related_name="articles",
+ through="db_functions.ArticleAuthor",
+ to="db_functions.author",
+ ),
+ ),
migrations.CreateModel(
name="Fan",
fields=[
diff --git a/tests/db_functions/models.py b/tests/db_functions/models.py
index d6a06511bcc1..7b4336d0aacb 100644
--- a/tests/db_functions/models.py
+++ b/tests/db_functions/models.py
@@ -12,7 +12,7 @@ class Author(models.Model):
class Article(models.Model):
- authors = models.ManyToManyField(Author, related_name="articles")
+ authors = models.ManyToManyField("Author", related_name="articles", through="ArticleAuthor")
title = models.CharField(max_length=50)
summary = models.CharField(max_length=200, null=True, blank=True)
text = models.TextField()
@@ -22,6 +22,15 @@ class Article(models.Model):
views = models.PositiveIntegerField(default=0)
+class ArticleAuthor(models.Model):
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+ author = models.ForeignKey(Author, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('article', 'author'),)
+ db_table = "db_functions_article_author"
+
+
class Fan(models.Model):
name = models.CharField(max_length=50)
age = models.PositiveSmallIntegerField(default=30)
diff --git a/tests/defer_regress/models.py b/tests/defer_regress/models.py
index dd492993b739..a7c0757cc15b 100644
--- a/tests/defer_regress/models.py
+++ b/tests/defer_regress/models.py
@@ -3,6 +3,7 @@
"""
from django.db import models
+from django_singlestore.schema import ModelStorageManager
class Item(models.Model):
@@ -61,6 +62,7 @@ class SpecialFeature(models.Model):
class OneToOneItem(models.Model):
item = models.OneToOneField(Item, models.CASCADE, related_name="one_to_one_item")
name = models.CharField(max_length=15)
+ objects = ModelStorageManager("REFERENCE")
class ItemAndSimpleItem(models.Model):
@@ -79,7 +81,7 @@ class Location(models.Model):
class Request(models.Model):
profile = models.ForeignKey(Profile, models.SET_NULL, null=True, blank=True)
location = models.ForeignKey(Location, models.CASCADE)
- items = models.ManyToManyField(Item)
+ items = models.ManyToManyField("Item", through="RequestItem")
request1 = models.CharField(default="request1", max_length=255)
request2 = models.CharField(default="request2", max_length=255)
@@ -87,6 +89,15 @@ class Request(models.Model):
request4 = models.CharField(default="request4", max_length=255)
+class RequestItem(models.Model):
+ request = models.ForeignKey(Request, on_delete=models.CASCADE)
+ item = models.ForeignKey(Item, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('request', 'item'),)
+ db_table = "defer_regress_request_item"
+
+
class Base(models.Model):
text = models.TextField()
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())
diff --git a/tests/delete_regress/models.py b/tests/delete_regress/models.py
index cbe6fef33434..bec2d939b974 100644
--- a/tests/delete_regress/models.py
+++ b/tests/delete_regress/models.py
@@ -39,6 +39,10 @@ class PlayedWith(models.Model):
toy = models.ForeignKey(Toy, models.CASCADE)
date = models.DateField(db_column="date_col")
+ class Meta:
+ unique_together = (('child', 'toy'),)
+ db_table = "delete_regress_played_with"
+
class PlayedWithNote(models.Model):
played = models.ForeignKey(PlayedWith, models.CASCADE)
@@ -54,7 +58,7 @@ class Email(Contact):
class Researcher(models.Model):
- contacts = models.ManyToManyField(Contact, related_name="research_contacts")
+ contacts = models.ManyToManyField(Contact, related_name="research_contacts", through="ResearcherContact")
primary_contact = models.ForeignKey(
Contact, models.SET_NULL, null=True, related_name="primary_contacts"
)
@@ -63,8 +67,17 @@ class Researcher(models.Model):
)
+class ResearcherContact(models.Model):
+ researcher = models.ForeignKey(Researcher, on_delete=models.CASCADE)
+ contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('researcher', 'contact'),)
+ db_table = "delete_regress_researcher_contact"
+
+
class Food(models.Model):
- name = models.CharField(max_length=20, unique=True)
+ name = models.CharField(max_length=20, primary_key=True)
class Eaten(models.Model):
@@ -133,7 +146,7 @@ class Meta:
class OrgUnit(models.Model):
- name = models.CharField(max_length=64, unique=True)
+ name = models.CharField(max_length=64, primary_key=True)
class Login(models.Model):
diff --git a/tests/delete_regress/tests.py b/tests/delete_regress/tests.py
index 173f767b28fa..ce1bc2c90bf5 100644
--- a/tests/delete_regress/tests.py
+++ b/tests/delete_regress/tests.py
@@ -302,7 +302,7 @@ def setUpTestData(cls):
@skipUnlessDBFeature("update_can_self_select")
def test_ticket_19102_annotate(self):
- with self.assertNumQueries(1):
+ with self.assertNumQueries(3):
Login.objects.order_by("description").filter(
orgunit__name__isnull=False
).annotate(n=models.Count("description")).filter(
@@ -313,7 +313,7 @@ def test_ticket_19102_annotate(self):
@skipUnlessDBFeature("update_can_self_select")
def test_ticket_19102_extra(self):
- with self.assertNumQueries(1):
+ with self.assertNumQueries(3):
Login.objects.order_by("description").filter(
orgunit__name__isnull=False
).extra(select={"extraf": "1"}).filter(pk=self.l1.pk).delete()
@@ -322,7 +322,7 @@ def test_ticket_19102_extra(self):
@skipUnlessDBFeature("update_can_self_select")
def test_ticket_19102_select_related(self):
- with self.assertNumQueries(1):
+ with self.assertNumQueries(3):
Login.objects.filter(pk=self.l1.pk).filter(
orgunit__name__isnull=False
).order_by("description").select_related("orgunit").delete()
@@ -331,7 +331,8 @@ def test_ticket_19102_select_related(self):
@skipUnlessDBFeature("update_can_self_select")
def test_ticket_19102_defer(self):
- with self.assertNumQueries(1):
+ # BEGIN, actual query, COMMIT
+ with self.assertNumQueries(3):
Login.objects.filter(pk=self.l1.pk).filter(
orgunit__name__isnull=False
).order_by("description").only("id").delete()
@@ -411,5 +412,5 @@ def test_set_querycount(self):
location_value=location,
)
# 3 UPDATEs for SET of item values and one for DELETE locations.
- with self.assertNumQueries(4):
+ with self.assertNumQueries(6):
location.delete()
diff --git a/tests/expressions/test_queryset_values.py b/tests/expressions/test_queryset_values.py
index 80addef37be2..0957422f8b47 100644
--- a/tests/expressions/test_queryset_values.py
+++ b/tests/expressions/test_queryset_values.py
@@ -30,7 +30,7 @@ def setUpTestData(cls):
def test_values_expression(self):
self.assertSequenceEqual(
- Company.objects.values(salary=F("ceo__salary")),
+ Company.objects.values(salary=F("ceo__salary")).order_by("salary"),
[{"salary": 10}, {"salary": 20}, {"salary": 30}],
)
diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py
index a928b76bab9a..3b7fbd48a756 100644
--- a/tests/expressions/tests.py
+++ b/tests/expressions/tests.py
@@ -657,8 +657,8 @@ def test_nested_subquery_join_outer_ref(self):
),
)
self.assertSequenceEqual(
- qs.values_list("ceo_company", flat=True),
- [self.example_inc.pk, self.foobar_ltd.pk, self.gmbh.pk],
+ sorted(qs.values_list("ceo_company", flat=True)),
+ sorted([self.example_inc.pk, self.foobar_ltd.pk, self.gmbh.pk]),
)
def test_nested_subquery_outer_ref_2(self):
@@ -1563,8 +1563,10 @@ def test_right_hand_multiplication(self):
def test_right_hand_division(self):
# RH Division of floats and integers
+ # in SingleStore we need to explicitly cast to integer under default
+ # @@data_conversion_compatibility_level = 8.0
Number.objects.filter(pk=self.n.pk).update(
- integer=640 / F("integer"), float=42.7 / F("float")
+ integer=Func(640 / F("integer"), function="FLOOR"), float=42.7 / F("float")
)
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 15)
@@ -1725,10 +1727,10 @@ def test_delta_add(self):
e.name for e in Experiment.objects.filter(end__lt=F("start") + delta)
]
self.assertEqual(test_set, self.expnames[:i])
-
- test_set = [
- e.name for e in Experiment.objects.filter(end__lt=delta + F("start"))
- ]
+ # in SingleStore, interval expression (delta) must come after the datetime expression
+ # test_set = [
+ # e.name for e in Experiment.objects.filter(end__lt=delta + F("start"))
+ # ]
self.assertEqual(test_set, self.expnames[:i])
test_set = [
diff --git a/tests/expressions_case/models.py b/tests/expressions_case/models.py
index 3f73aec85314..ae2722ef39d1 100644
--- a/tests/expressions_case/models.py
+++ b/tests/expressions_case/models.py
@@ -41,7 +41,7 @@ class CaseTestModel(models.Model):
class O2OCaseTestModel(models.Model):
- o2o = models.OneToOneField(CaseTestModel, models.CASCADE, related_name="o2o_rel")
+ o2o = models.OneToOneField(CaseTestModel, models.CASCADE, primary_key=True, related_name="o2o_rel")
integer = models.IntegerField()
diff --git a/tests/filtered_relation/models.py b/tests/filtered_relation/models.py
index d34a86305fcc..8b1283532309 100644
--- a/tests/filtered_relation/models.py
+++ b/tests/filtered_relation/models.py
@@ -1,6 +1,7 @@
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models
+from django_singlestore.schema import ModelStorageManager
class Author(models.Model):
@@ -9,10 +10,12 @@ class Author(models.Model):
"Book",
related_name="preferred_by_authors",
related_query_name="preferred_by_authors",
+ through="AuthorBook",
)
content_type = models.ForeignKey(ContentType, models.CASCADE, null=True)
object_id = models.PositiveIntegerField(null=True)
content_object = GenericForeignKey()
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
class Editor(models.Model):
@@ -40,9 +43,21 @@ class Book(models.Model):
state = models.CharField(max_length=9, choices=STATES, default=AVAILABLE)
+class AuthorBook(models.Model):
+ author = models.ForeignKey(Author, on_delete=models.CASCADE)
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('author', 'book'),)
+ db_table = "filtered_relation_author_book"
+
+
class Borrower(models.Model):
name = models.CharField(max_length=50, unique=True)
+ objects = ModelStorageManager("REFERENCE")
+
+
class Reservation(models.Model):
NEW = "new"
diff --git a/tests/filtered_relation/tests.py b/tests/filtered_relation/tests.py
index 0fce8b092ab7..cb59b40371d0 100644
--- a/tests/filtered_relation/tests.py
+++ b/tests/filtered_relation/tests.py
@@ -363,7 +363,7 @@ def test_union(self):
"book", condition=Q(book__title__iexact="the book by jane a")
),
).filter(book_jane__isnull=False)
- self.assertSequenceEqual(qs1.union(qs2), [self.author1, self.author2])
+ self.assertCountEqual(qs1.union(qs2), [self.author1, self.author2])
@skipUnlessDBFeature("supports_select_intersection")
def test_intersection(self):
diff --git a/tests/fixtures/models.py b/tests/fixtures/models.py
index 37b0066d70c3..2ae62378b7e9 100644
--- a/tests/fixtures/models.py
+++ b/tests/fixtures/models.py
@@ -15,6 +15,8 @@
from django.contrib.contenttypes.models import ContentType
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
class Category(models.Model):
title = models.CharField(max_length=100)
@@ -44,13 +46,21 @@ class Blog(models.Model):
Article, models.CASCADE, related_name="fixtures_featured_set"
)
articles = models.ManyToManyField(
- Article, blank=True, related_name="fixtures_articles_set"
- )
+ Article, blank=True, related_name="fixtures_articles_set", through="BlogArticle")
def __str__(self):
return self.name
+class BlogArticle(models.Model):
+ blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('blog', 'article'),)
+ db_table = "fixtures_blog_article"
+
+
class Tag(models.Model):
name = models.CharField(max_length=100)
tagged_type = models.ForeignKey(
@@ -74,7 +84,7 @@ def get_by_natural_key(self, name):
class Person(models.Model):
objects = PersonManager()
- name = models.CharField(max_length=100, unique=True)
+ name = models.CharField(max_length=100, primary_key=True)
class Meta:
ordering = ("name",)
@@ -103,7 +113,7 @@ class Meta:
class Visa(models.Model):
person = models.ForeignKey(Person, models.CASCADE)
- permissions = models.ManyToManyField(Permission, blank=True)
+ permissions = models.ManyToManyField(Permission, blank=True, through="VisaPermission")
def __str__(self):
return "%s %s" % (
@@ -112,9 +122,18 @@ def __str__(self):
)
+class VisaPermission(models.Model):
+ visa = models.ForeignKey(Visa, on_delete=models.CASCADE)
+ permission = models.ForeignKey(Permission, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('visa', 'permission'),)
+ db_table = "fixtures_visa_permission"
+
+
class Book(models.Model):
name = models.CharField(max_length=100)
- authors = models.ManyToManyField(Person)
+ authors = models.ManyToManyField(Person, through="BookPerson")
class Meta:
ordering = ("name",)
@@ -124,6 +143,15 @@ def __str__(self):
return "%s by %s" % (self.name, authors) if authors else self.name
+class BookPerson(models.Model):
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+ person = models.ForeignKey(Person, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('book', 'person'),)
+ db_table = "fixtures_book_person"
+
+
class PrimaryKeyUUIDModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
@@ -139,10 +167,11 @@ class NaturalKeyThing(models.Model):
"NaturalKeyThing", on_delete=models.CASCADE, null=True
)
other_things = models.ManyToManyField(
- "NaturalKeyThing", related_name="thing_m2m_set"
- )
+ "NaturalKeyThing", related_name="thing_m2m_set", through="NaturalKeyThingNaturalKeyThing")
objects = NaturalKeyManager()
+ storage = ModelStorageManager(table_storage_type="REFERENCE")
+
def natural_key(self):
return (self.key,)
@@ -151,11 +180,22 @@ def __str__(self):
return self.key
+class NaturalKeyThingNaturalKeyThing(models.Model):
+ from_naturalkeything = models.ForeignKey(NaturalKeyThing, on_delete=models.CASCADE, related_name="from_naturalkeything")
+ to_naturalkeything = models.ForeignKey(NaturalKeyThing, on_delete=models.CASCADE, related_name="to_naturalkeything")
+
+ class Meta:
+ unique_together = (('from_naturalkeything', 'to_naturalkeything'),)
+ db_table = "fixtures_naturalkeything_naturalkeything"
+
+
class CircularA(models.Model):
key = models.CharField(max_length=3, unique=True)
obj = models.ForeignKey("CircularB", models.SET_NULL, null=True)
objects = NaturalKeyManager()
+ storage = ModelStorageManager(table_storage_type="REFERENCE")
+
def natural_key(self):
return (self.key,)
@@ -166,6 +206,8 @@ class CircularB(models.Model):
obj = models.ForeignKey("CircularA", models.SET_NULL, null=True)
objects = NaturalKeyManager()
+ storage = ModelStorageManager(table_storage_type="REFERENCE")
+
def natural_key(self):
return (self.key,)
diff --git a/tests/generic_inline_admin/models.py b/tests/generic_inline_admin/models.py
index fa1b64d94877..a1a1025c0efa 100644
--- a/tests/generic_inline_admin/models.py
+++ b/tests/generic_inline_admin/models.py
@@ -1,6 +1,7 @@
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models
+from django_singlestore.schema import ModelStorageManager
class Episode(models.Model):
@@ -39,6 +40,8 @@ class PhoneNumber(models.Model):
phone_number = models.CharField(max_length=30)
category = models.ForeignKey(Category, models.SET_NULL, null=True, blank=True)
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
class Meta:
unique_together = (
(
diff --git a/tests/generic_relations_regress/models.py b/tests/generic_relations_regress/models.py
index dc55b2a83b3c..3dc47b25b5dd 100644
--- a/tests/generic_relations_regress/models.py
+++ b/tests/generic_relations_regress/models.py
@@ -96,7 +96,16 @@ class Contact(models.Model):
class Organization(models.Model):
name = models.CharField(max_length=255)
- contacts = models.ManyToManyField(Contact, related_name="organizations")
+ contacts = models.ManyToManyField("Contact", related_name="organizations", through="OrganizationContact")
+
+
+class OrganizationContact(models.Model):
+ organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
+ contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('organization', 'contact'),)
+ db_table = "generic_relations_regress_organization_contact"
class Company(models.Model):
diff --git a/tests/generic_views/models.py b/tests/generic_views/models.py
index aef0ae23f507..c936cc7fe261 100644
--- a/tests/generic_views/models.py
+++ b/tests/generic_views/models.py
@@ -42,7 +42,7 @@ class Book(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField()
pages = models.IntegerField()
- authors = models.ManyToManyField(Author)
+ authors = models.ManyToManyField("Author", through="BookAuthor")
pubdate = models.DateField()
objects = models.Manager()
@@ -55,6 +55,15 @@ def __str__(self):
return self.name
+class BookAuthor(models.Model):
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+ author = models.ForeignKey(Author, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('book', 'author'),)
+ db_table = "book_author"
+
+
class Page(models.Model):
content = models.TextField()
template = models.CharField(max_length=255)
diff --git a/tests/get_object_or_404/models.py b/tests/get_object_or_404/models.py
index d130883c53a5..d33f79df8b8c 100644
--- a/tests/get_object_or_404/models.py
+++ b/tests/get_object_or_404/models.py
@@ -28,8 +28,17 @@ def get_queryset(self):
class Article(models.Model):
- authors = models.ManyToManyField(Author)
+ authors = models.ManyToManyField("Author", through="ArticleAuthor")
title = models.CharField(max_length=50)
objects = models.Manager()
by_a_sir = ArticleManager()
attribute_error_objects = AttributeErrorManager()
+
+
+class ArticleAuthor(models.Model):
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+ author = models.ForeignKey(Author, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('article', 'author'),)
+ db_table = "get_object_or_404_article_author"
diff --git a/tests/get_or_create/models.py b/tests/get_or_create/models.py
index 68756715018c..e5cfb1391610 100644
--- a/tests/get_or_create/models.py
+++ b/tests/get_or_create/models.py
@@ -2,7 +2,7 @@
class Person(models.Model):
- first_name = models.CharField(max_length=100, unique=True)
+ first_name = models.CharField(max_length=100, primary_key=True)
last_name = models.CharField(max_length=100)
birthday = models.DateField()
defaults = models.TextField()
@@ -22,12 +22,12 @@ class Profile(models.Model):
class Tag(models.Model):
- text = models.CharField(max_length=255, unique=True)
+ text = models.CharField(max_length=255, primary_key=True)
class Thing(models.Model):
name = models.CharField(max_length=255)
- tags = models.ManyToManyField(Tag)
+ tags = models.ManyToManyField(Tag, through="ThingTag")
@property
def capitalized_name_property(self):
@@ -42,6 +42,15 @@ def name_in_all_caps(self):
return self.name.upper()
+class ThingTag(models.Model):
+ thing = models.ForeignKey(Thing, on_delete=models.CASCADE)
+ tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('thing', 'tag'),)
+ db_table = "get_or_create_thing_tag"
+
+
class Publisher(models.Model):
name = models.CharField(max_length=100)
@@ -56,7 +65,7 @@ class Journalist(Author):
class Book(models.Model):
name = models.CharField(max_length=100)
- authors = models.ManyToManyField(Author, related_name="books")
+ authors = models.ManyToManyField(Author, related_name="books", through="BookAuthor")
publisher = models.ForeignKey(
Publisher,
models.CASCADE,
@@ -64,3 +73,12 @@ class Book(models.Model):
db_column="publisher_id_column",
)
updated = models.DateTimeField(auto_now=True)
+
+
+class BookAuthor(models.Model):
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+ author = models.ForeignKey(Author, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('book', 'author'),)
+ db_table = "get_or_create_book_author"
diff --git a/tests/indexes/models.py b/tests/indexes/models.py
index 68827cb6659c..d7330c4c0cb2 100644
--- a/tests/indexes/models.py
+++ b/tests/indexes/models.py
@@ -1,5 +1,7 @@
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
class CurrentTranslation(models.ForeignObject):
"""
@@ -25,6 +27,8 @@ class ArticleTranslation(models.Model):
language = models.CharField(max_length=10, unique=True)
content = models.TextField()
+ objects = ModelStorageManager("REFERENCE")
+
class Article(models.Model):
headline = models.CharField(max_length=100)
@@ -45,6 +49,8 @@ class IndexedArticle(models.Model):
body = models.TextField(db_index=True)
slug = models.CharField(max_length=40, unique=True)
+ objects = ModelStorageManager("REFERENCE")
+
class Meta:
required_db_features = {"supports_index_on_text_field"}
diff --git a/tests/inline_formsets/models.py b/tests/inline_formsets/models.py
index f4c06e8fac47..a44266f0e02c 100644
--- a/tests/inline_formsets/models.py
+++ b/tests/inline_formsets/models.py
@@ -1,4 +1,5 @@
from django.db import models
+from django_singlestore.schema import ModelStorageManager
class School(models.Model):
@@ -27,6 +28,8 @@ class Poem(models.Model):
poet = models.ForeignKey(Poet, models.CASCADE)
name = models.CharField(max_length=100)
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
class Meta:
unique_together = ("poet", "name")
diff --git a/tests/inspectdb/models.py b/tests/inspectdb/models.py
index 9e6871ce46cd..932df2c467f0 100644
--- a/tests/inspectdb/models.py
+++ b/tests/inspectdb/models.py
@@ -1,6 +1,7 @@
from django.db import connection, models
from django.db.models.functions import Lower
+from django_singlestore.schema import ModelStorageManager
class People(models.Model):
name = models.CharField(max_length=255)
@@ -18,7 +19,7 @@ class PeopleData(models.Model):
class PeopleMoreData(models.Model):
- people_unique = models.ForeignKey(People, models.CASCADE, unique=True)
+ people_unique = models.ForeignKey(People, models.CASCADE, primary_key=True)
message = models.ForeignKey(Message, models.CASCADE, blank=True, null=True)
license = models.CharField(max_length=255)
@@ -114,11 +115,14 @@ class Meta:
class UniqueTogether(models.Model):
+
field1 = models.IntegerField()
field2 = models.CharField(max_length=10)
from_field = models.IntegerField(db_column="from")
non_unique = models.IntegerField(db_column="non__unique_column")
non_unique_0 = models.IntegerField(db_column="non_unique__column")
+
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
class Meta:
unique_together = [
diff --git a/tests/inspectdb/tests.py b/tests/inspectdb/tests.py
index ad929fd9bcbe..7892a2dfe066 100644
--- a/tests/inspectdb/tests.py
+++ b/tests/inspectdb/tests.py
@@ -72,27 +72,53 @@ def assertFieldType(name, definition):
return assertFieldType
def test_field_types(self):
- """Test introspection of various Django field types"""
+ """
+ Test introspection of various Django field types. In SingleStore,
+ db_collation is always included to the introspection result of a char field
+ """
+ with connection.cursor() as cur:
+ cur.execute("SELECT @@collation_database")
+ results = cur.fetchall()
+ default_collation = results[0][0]
+
assertFieldType = self.make_field_type_asserter()
introspected_field_types = connection.features.introspected_field_types
char_field_type = introspected_field_types["CharField"]
- # Inspecting Oracle DB doesn't produce correct results (#19884):
- # - it reports fields as blank=True when they aren't.
if (
not connection.features.interprets_empty_strings_as_nulls
and char_field_type == "CharField"
):
- assertFieldType("char_field", "models.CharField(max_length=10)")
+ assertFieldType(
+ "char_field",
+ f"models.CharField(max_length=10, db_collation='{default_collation}')",
+ )
assertFieldType(
"null_char_field",
- "models.CharField(max_length=10, blank=True, null=True)",
+ f"models.CharField(max_length=10, db_collation='{default_collation}', blank=True, null=True)",
+ )
+ assertFieldType(
+ "email_field",
+ f"models.CharField(max_length=254, db_collation='{default_collation}')",
+ )
+ assertFieldType(
+ "file_field",
+ f"models.CharField(max_length=100, db_collation='{default_collation}')",
+ )
+ assertFieldType(
+ "file_path_field",
+ f"models.CharField(max_length=100, db_collation='{default_collation}')",
+ )
+ assertFieldType(
+ "slug_field",
+ f"models.CharField(max_length=50, db_collation='{default_collation}')",
+ )
+ assertFieldType(
+ "text_field", f"models.TextField(db_collation='{default_collation}')"
+ )
+ assertFieldType(
+ "url_field",
+ f"models.CharField(max_length=200, db_collation='{default_collation}')",
)
- assertFieldType("email_field", "models.CharField(max_length=254)")
- assertFieldType("file_field", "models.CharField(max_length=100)")
- assertFieldType("file_path_field", "models.CharField(max_length=100)")
- assertFieldType("slug_field", "models.CharField(max_length=50)")
- assertFieldType("text_field", "models.TextField()")
- assertFieldType("url_field", "models.CharField(max_length=200)")
if char_field_type == "TextField":
assertFieldType("char_field", "models.TextField()")
assertFieldType(
@@ -109,14 +135,20 @@ def test_field_types(self):
if introspected_field_types["GenericIPAddressField"] == "GenericIPAddressField":
assertFieldType("gen_ip_address_field", "models.GenericIPAddressField()")
elif not connection.features.interprets_empty_strings_as_nulls:
- assertFieldType("gen_ip_address_field", "models.CharField(max_length=39)")
+ assertFieldType(
+ "gen_ip_address_field",
+ f"models.CharField(max_length=39, db_collation='{default_collation}')",
+ )
assertFieldType(
"time_field", "models.%s()" % introspected_field_types["TimeField"]
)
if connection.features.has_native_uuid_field:
assertFieldType("uuid_field", "models.UUIDField()")
elif not connection.features.interprets_empty_strings_as_nulls:
- assertFieldType("uuid_field", "models.CharField(max_length=32)")
+ assertFieldType(
+ "uuid_field",
+ f"models.CharField(max_length=32, db_collation='{default_collation}')",
+ )
@skipUnlessDBFeature("can_introspect_json_field", "supports_json_field")
def test_json_field(self):
diff --git a/tests/introspection/models.py b/tests/introspection/models.py
index d31eb0cbfafc..59f799a758a3 100644
--- a/tests/introspection/models.py
+++ b/tests/introspection/models.py
@@ -1,4 +1,5 @@
from django.db import models
+from django_singlestore.schema import ModelStorageManager
class City(models.Model):
@@ -25,6 +26,8 @@ class Reporter(models.Model):
small_int = models.SmallIntegerField()
interval = models.DurationField()
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
class Meta:
unique_together = ("first_name", "last_name")
@@ -38,6 +41,8 @@ class Article(models.Model):
unmanaged_reporters = models.ManyToManyField(
Reporter, through="ArticleReporter", related_name="+"
)
+
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
class Meta:
ordering = ("headline",)
@@ -62,6 +67,8 @@ class Comment(models.Model):
pub_date = models.DateTimeField()
body = models.TextField()
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
class Meta:
constraints = [
models.UniqueConstraint(
diff --git a/tests/known_related_objects/models.py b/tests/known_related_objects/models.py
index 027d1628287a..503588c686b0 100644
--- a/tests/known_related_objects/models.py
+++ b/tests/known_related_objects/models.py
@@ -5,6 +5,7 @@
"""
from django.db import models
+from django_singlestore.schema import ModelStorageManager
class Tournament(models.Model):
@@ -27,3 +28,6 @@ class PoolStyle(models.Model):
another_pool = models.OneToOneField(
Pool, models.CASCADE, null=True, related_name="another_style"
)
+
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
diff --git a/tests/lookup/models.py b/tests/lookup/models.py
index 75f3e3b6ba4a..f676049ac0cc 100644
--- a/tests/lookup/models.py
+++ b/tests/lookup/models.py
@@ -7,6 +7,8 @@
from django.db import models
from django.db.models.lookups import IsNull
+from django_singlestore.schema import ModelStorageManager
+
class Alarm(models.Model):
desc = models.CharField(max_length=100)
@@ -30,6 +32,8 @@ class Article(models.Model):
pub_date = models.DateTimeField()
author = models.ForeignKey(Author, models.SET_NULL, blank=True, null=True)
slug = models.SlugField(unique=True, blank=True, null=True)
+
+ objects = ModelStorageManager("REFERENCE")
class Meta:
ordering = ("-pub_date", "headline")
@@ -39,13 +43,22 @@ def __str__(self):
class Tag(models.Model):
- articles = models.ManyToManyField(Article)
+ articles = models.ManyToManyField(Article, through="TagArticle")
name = models.CharField(max_length=100)
class Meta:
ordering = ("name",)
+class TagArticle(models.Model):
+ tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('tag', 'article'),)
+ db_table = "lookup_tag_article"
+
+
class NulledTextField(models.TextField):
def get_prep_value(self, value):
return None if value == "" else value
@@ -64,15 +77,10 @@ class IsNullWithNoneAsRHS(IsNull):
class Season(models.Model):
- year = models.PositiveSmallIntegerField()
+ year = models.PositiveSmallIntegerField(primary_key=True)
gt = models.IntegerField(null=True, blank=True)
nulled_text_field = NulledTextField(null=True)
- class Meta:
- constraints = [
- models.UniqueConstraint(fields=["year"], name="season_year_unique"),
- ]
-
def __str__(self):
return str(self.year)
@@ -85,7 +93,16 @@ class Game(models.Model):
class Player(models.Model):
name = models.CharField(max_length=100)
- games = models.ManyToManyField(Game, related_name="players")
+ games = models.ManyToManyField(Game, related_name="players", through="PlayerGame")
+
+
+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 = "lookup_player_game"
class Product(models.Model):
diff --git a/tests/m2m_and_m2o/models.py b/tests/m2m_and_m2o/models.py
index 6a5b0b29c984..9a4faba053e0 100644
--- a/tests/m2m_and_m2o/models.py
+++ b/tests/m2m_and_m2o/models.py
@@ -12,7 +12,7 @@ class User(models.Model):
class Issue(models.Model):
num = models.IntegerField()
- cc = models.ManyToManyField(User, blank=True, related_name="test_issue_cc")
+ cc = models.ManyToManyField("User", blank=True, related_name="test_issue_cc", through="IssueUser")
client = models.ForeignKey(User, models.CASCADE, related_name="test_issue_client")
class Meta:
@@ -22,5 +22,23 @@ def __str__(self):
return str(self.num)
+class IssueUser(models.Model):
+ issue = models.ForeignKey(Issue, on_delete=models.CASCADE)
+ user = models.ForeignKey(User, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('issue', 'user'),)
+ db_table = "m2m_and_m2o_issue_user"
+
+
class StringReferenceModel(models.Model):
- others = models.ManyToManyField("StringReferenceModel")
+ others = models.ManyToManyField("StringReferenceModel", through="StringReferenceModelStringReferenceModel")
+
+
+class StringReferenceModelStringReferenceModel(models.Model):
+ from_stringreferencemodel = models.ForeignKey(StringReferenceModel, on_delete=models.CASCADE, related_name="from_stringreferencemodel")
+ to_stringreferencemodel = models.ForeignKey(StringReferenceModel, on_delete=models.CASCADE, related_name="to_stringreferencemodel")
+
+ class Meta:
+ unique_together = (('from_stringreferencemodel', 'to_stringreferencemodel'),)
+ db_table = "m2m_and_m2o_stringreferencemodel_stringreferencemodel"
diff --git a/tests/m2m_multiple/models.py b/tests/m2m_multiple/models.py
index 2146a8920163..b2788b66ab5c 100644
--- a/tests/m2m_multiple/models.py
+++ b/tests/m2m_multiple/models.py
@@ -24,10 +24,10 @@ class Article(models.Model):
headline = models.CharField(max_length=50)
pub_date = models.DateTimeField()
primary_categories = models.ManyToManyField(
- Category, related_name="primary_article_set"
+ Category, related_name="primary_article_set", through="ArticleCategory"
)
secondary_categories = models.ManyToManyField(
- Category, related_name="secondary_article_set"
+ Category, related_name="secondary_article_set", through="ArticleCategoryS"
)
class Meta:
@@ -35,3 +35,20 @@ class Meta:
def __str__(self):
return self.headline
+
+class ArticleCategory(models.Model):
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+ category = models.ForeignKey(Category, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('article', 'category'),)
+ db_table = "m2m_multiple_article_category"
+
+
+class ArticleCategoryS(models.Model):
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+ category = models.ForeignKey(Category, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('article', 'category'),)
+ db_table = "m2m_multiple_article_category_second"
diff --git a/tests/m2m_through/models.py b/tests/m2m_through/models.py
index 47a0b75f4bbb..851a94e0231e 100644
--- a/tests/m2m_through/models.py
+++ b/tests/m2m_through/models.py
@@ -134,14 +134,14 @@ class Relationship(models.Model):
class Ingredient(models.Model):
- iname = models.CharField(max_length=20, unique=True)
+ iname = models.CharField(max_length=20, primary_key=True)
class Meta:
ordering = ("iname",)
class Recipe(models.Model):
- rname = models.CharField(max_length=20, unique=True)
+ rname = models.CharField(max_length=20, primary_key=True)
ingredients = models.ManyToManyField(
Ingredient,
through="RecipeIngredient",
diff --git a/tests/m2m_through/tests.py b/tests/m2m_through/tests.py
index 83449a7c7b74..df6b48d83f7a 100644
--- a/tests/m2m_through/tests.py
+++ b/tests/m2m_through/tests.py
@@ -482,7 +482,7 @@ def test_set_on_symmetrical_m2m_with_intermediate_model(self):
[anne, kate],
through_defaults={"date_friended": date_friended_set},
)
- self.assertSequenceEqual(tony.sym_friends.all(), [anne, kate])
+ self.assertCountEqual(tony.sym_friends.all(), [kate, anne])
self.assertSequenceEqual(anne.sym_friends.all(), [tony])
self.assertSequenceEqual(kate.sym_friends.all(), [tony])
self.assertEqual(
diff --git a/tests/managers_regress/models.py b/tests/managers_regress/models.py
index dd365d961d2f..88aa1a4f9742 100644
--- a/tests/managers_regress/models.py
+++ b/tests/managers_regress/models.py
@@ -127,8 +127,7 @@ def __str__(self):
class RelationModel(models.Model):
fk = models.ForeignKey(RelatedModel, models.CASCADE, related_name="test_fk")
-
- m2m = models.ManyToManyField(RelatedModel, related_name="test_m2m")
+ m2m = models.ManyToManyField("RelatedModel", related_name="test_m2m", through="RelationModelRelatedModel")
gfk_ctype = models.ForeignKey(ContentType, models.SET_NULL, null=True)
gfk_id = models.IntegerField(null=True)
@@ -136,3 +135,12 @@ class RelationModel(models.Model):
def __str__(self):
return str(self.pk)
+
+
+class RelationModelRelatedModel(models.Model):
+ relationmodel = models.ForeignKey(RelationModel, on_delete=models.CASCADE)
+ relatedmodel = models.ForeignKey(RelatedModel, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('relationmodel', 'relatedmodel'),)
+ db_table = "managers_regress_relationmodel_relatedmodel"
diff --git a/tests/many_to_many/models.py b/tests/many_to_many/models.py
index 541928e94d64..dbafa8f9dd8b 100644
--- a/tests/many_to_many/models.py
+++ b/tests/many_to_many/models.py
@@ -8,8 +8,11 @@
"""
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
class Publication(models.Model):
+ objects = ModelStorageManager("")
title = models.CharField(max_length=30)
class Meta:
@@ -20,6 +23,7 @@ def __str__(self):
class Tag(models.Model):
+ objects = ModelStorageManager("")
id = models.BigAutoField(primary_key=True)
name = models.CharField(max_length=50)
diff --git a/tests/many_to_one/models.py b/tests/many_to_one/models.py
index cca7e798179f..e2adc9c2f310 100644
--- a/tests/many_to_one/models.py
+++ b/tests/many_to_one/models.py
@@ -4,6 +4,7 @@
To define a many-to-one relationship, use ``ForeignKey()``.
"""
from django.db import models
+from django_singlestore.schema import ModelStorageManager
class Reporter(models.Model):
@@ -72,6 +73,7 @@ class Parent(models.Model):
bestchild = models.ForeignKey(
"Child", models.SET_NULL, null=True, related_name="favored_by"
)
+ objects = ModelStorageManager("REFERENCE")
class ParentStringPrimaryKey(models.Model):
diff --git a/tests/many_to_one_null/models.py b/tests/many_to_one_null/models.py
index a0fcfa6ce5b6..11e43edc0a1e 100644
--- a/tests/many_to_one_null/models.py
+++ b/tests/many_to_one_null/models.py
@@ -6,6 +6,7 @@
"""
from django.db import models
+from django_singlestore.schema import ModelStorageManager
class Reporter(models.Model):
@@ -25,6 +26,7 @@ def __str__(self):
class Car(models.Model):
make = models.CharField(max_length=100, null=True, unique=True)
+ objects = ModelStorageManager("REFERENCE")
class Driver(models.Model):
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index 0e4b32fea7bd..9bfa6708dc71 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -860,12 +860,12 @@ def test_sqlmigrate_forwards(self):
lines[:3],
[
"--",
- "-- Create model Author",
+ "-- Create model Tribble",
"--",
],
)
self.assertIn(
- "create table %s" % connection.ops.quote_name("migrations_author").lower(),
+ "create table %s" % connection.ops.quote_name("migrations_tribble").lower(),
lines[3].lower(),
)
pos = lines.index("--", 3)
@@ -873,31 +873,17 @@ def test_sqlmigrate_forwards(self):
lines[pos : pos + 3],
[
"--",
- "-- Create model Tribble",
+ "-- Create model Author",
"--",
],
)
self.assertIn(
- "create table %s" % connection.ops.quote_name("migrations_tribble").lower(),
+ "create rowstore reference table %s" % connection.ops.quote_name("migrations_author").lower(),
lines[pos + 3].lower(),
)
- pos = lines.index("--", pos + 3)
- self.assertEqual(
- lines[pos : pos + 3],
- [
- "--",
- "-- Add field bool to tribble",
- "--",
- ],
- )
- pos = lines.index("--", pos + 3)
- self.assertEqual(
- lines[pos : pos + 3],
- [
- "--",
- "-- Alter unique_together for author (1 constraint(s))",
- "--",
- ],
+ self.assertIn(
+ "create index",
+ lines[pos + 4].lower(),
)
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
@@ -922,20 +908,13 @@ def test_sqlmigrate_backwards(self):
lines[:3],
[
"--",
- "-- Alter unique_together for author (1 constraint(s))",
- "--",
- ],
- )
- pos = lines.index("--", 3)
- self.assertEqual(
- lines[pos : pos + 3],
- [
- "--",
- "-- Add field bool to tribble",
+ "-- Create model Author",
"--",
],
)
- pos = lines.index("--", pos + 3)
+ self.assertIn("DROP TABLE `migrations_author`;", lines[3])
+
+ pos = lines.index("--", 4)
self.assertEqual(
lines[pos : pos + 3],
[
@@ -944,33 +923,7 @@ def test_sqlmigrate_backwards(self):
"--",
],
)
- next_pos = lines.index("--", pos + 3)
- drop_table_sql = (
- "drop table %s"
- % connection.ops.quote_name("migrations_tribble").lower()
- )
- for line in lines[pos + 3 : next_pos]:
- if drop_table_sql in line.lower():
- break
- else:
- self.fail("DROP TABLE (tribble) not found.")
- pos = next_pos
- self.assertEqual(
- lines[pos : pos + 3],
- [
- "--",
- "-- Create model Author",
- "--",
- ],
- )
- drop_table_sql = (
- "drop table %s" % connection.ops.quote_name("migrations_author").lower()
- )
- for line in lines[pos + 3 :]:
- if drop_table_sql in line.lower():
- break
- else:
- self.fail("DROP TABLE (author) not found.")
+ self.assertIn("DROP TABLE `migrations_tribble`;", lines[pos + 3])
finally:
# Unmigrate everything.
call_command("migrate", "migrations", "zero", verbosity=0)
@@ -1127,7 +1080,7 @@ def test_migrate_syncdb_deferred_sql_executed_with_schemaeditor(self):
"migrate", run_syncdb=True, verbosity=1, stdout=stdout, no_color=True
)
create_table_count = len(
- [call for call in execute.mock_calls if "CREATE TABLE" in str(call)]
+ [call for call in execute.mock_calls if "CREATE TABLE" in str(call)] #There is extra space in Create table sql query
)
self.assertEqual(create_table_count, 2)
# There's at least one deferred SQL for creating the foreign key
@@ -1164,7 +1117,7 @@ def test_migrate_syncdb_app_label(self):
"migrate", "unmigrated_app_syncdb", run_syncdb=True, stdout=stdout
)
create_table_count = len(
- [call for call in execute.mock_calls if "CREATE TABLE" in str(call)]
+ [call for call in execute.mock_calls if "CREATE TABLE" in str(call)]
)
self.assertEqual(create_table_count, 2)
self.assertGreater(len(execute.mock_calls), 2)
@@ -1986,7 +1939,8 @@ class Meta:
):
with captured_stdout() as out:
call_command("makemigrations", "migrations", interactive=True)
- self.assertIn("Rename model SillyModel to RenamedModel", out.getvalue())
+ self.assertIn("Create model RenamedModel", out.getvalue())
+ self.assertIn("Delete model SillyModel", out.getvalue())
@mock.patch("builtins.input", return_value="Y")
def test_makemigrations_field_rename_interactive(self, mock_input):
@@ -2775,13 +2729,14 @@ def test_squashmigrations_squashes(self):
migration_dir, "0001_squashed_0002_second.py"
)
self.assertTrue(os.path.exists(squashed_migration_file))
+ #As modifications have been made to the migration file we're squashing.
self.assertEqual(
out.getvalue(),
"Will squash the following migrations:\n"
" - 0001_initial\n"
" - 0002_second\n"
"Optimizing...\n"
- " Optimized from 8 operations to 2 operations.\n"
+ " Optimized from 6 operations to 2 operations.\n"
"Created new squashed migration %s\n"
" You should commit this migration but leave the old ones in place;\n"
" the new migration will be used for new installs. Once you are sure\n"
@@ -2819,7 +2774,8 @@ def test_squashmigrations_optimizes(self):
verbosity=1,
stdout=out,
)
- self.assertIn("Optimized from 8 operations to 2 operations.", out.getvalue())
+ #As modifications have been made to the migration file we're squashing.
+ self.assertIn("Optimized from 6 operations to 2 operations.", out.getvalue())
def test_ticket_23799_squashmigrations_no_optimize(self):
"""
@@ -3093,6 +3049,7 @@ def test_optimization(self):
)
initial_migration_file = os.path.join(migration_dir, "0001_initial.py")
self.assertTrue(os.path.exists(initial_migration_file))
+ #As modifications have been made to the migration file we're using here.
with open(initial_migration_file) as fp:
content = fp.read()
self.assertIn(
@@ -3103,8 +3060,7 @@ def test_optimization(self):
)
self.assertEqual(
out.getvalue(),
- f"Optimizing from 4 operations to 2 operations.\n"
- f"Optimized migration {initial_migration_file}\n",
+ f"No optimizations possible.\n",
)
def test_optimization_no_verbosity(self):
@@ -3188,11 +3144,8 @@ def test_fails_squash_migration_manual_porting(self):
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
def test_optimizemigration_check(self):
- with self.assertRaises(SystemExit):
- call_command(
- "optimizemigration", "--check", "migrations", "0001", verbosity=0
- )
-
+ # Expect no error for optimized migration
+ call_command("optimizemigration", "--check", "migrations", "0001", verbosity=0)
call_command("optimizemigration", "--check", "migrations", "0002", verbosity=0)
@override_settings(
diff --git a/tests/migrations/test_migrations/0001_initial.py b/tests/migrations/test_migrations/0001_initial.py
index 20ca1391f6fe..2a7e9200f6ea 100644
--- a/tests/migrations/test_migrations/0001_initial.py
+++ b/tests/migrations/test_migrations/0001_initial.py
@@ -1,4 +1,5 @@
from django.db import migrations, models
+import django_singlestore.schema
class Migration(migrations.Migration):
@@ -6,29 +7,28 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
- "Author",
- [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=255)),
- ("slug", models.SlugField(null=True)),
- ("age", models.IntegerField(default=0)),
- ("silly_field", models.BooleanField(default=False)),
+ name='Tribble',
+ fields=[
+ ('id', models.AutoField(primary_key=True, serialize=False)),
+ ('fluffy', models.BooleanField(default=True)),
+ ('bool', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
- "Tribble",
- [
- ("id", models.AutoField(primary_key=True)),
- ("fluffy", models.BooleanField(default=True)),
+ name='Author',
+ fields=[
+ ('id', models.AutoField(primary_key=True, serialize=False)),
+ ('name', models.CharField(max_length=255)),
+ ('slug', models.SlugField(null=True)),
+ ('age', models.IntegerField(default=0)),
+ ('silly_field', models.BooleanField(default=False)),
+ ],
+ options={
+ 'unique_together': {('name', 'slug')},
+ },
+ managers=[
+ ('objects', django_singlestore.schema.ModelStorageManager('ROWSTORE REFERENCE')),
],
- ),
- migrations.AddField(
- model_name="tribble",
- name="bool",
- field=models.BooleanField(default=False),
- ),
- migrations.AlterUniqueTogether(
- name="author",
- unique_together={("name", "slug")},
),
]
+
\ No newline at end of file
diff --git a/tests/migrations/test_migrations_fake_split_initial/0001_initial.py b/tests/migrations/test_migrations_fake_split_initial/0001_initial.py
index 99bf99b61571..2a7e9200f6ea 100644
--- a/tests/migrations/test_migrations_fake_split_initial/0001_initial.py
+++ b/tests/migrations/test_migrations_fake_split_initial/0001_initial.py
@@ -1,4 +1,5 @@
from django.db import migrations, models
+import django_singlestore.schema
class Migration(migrations.Migration):
@@ -6,24 +7,28 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
- "Author",
- [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=255)),
- ("slug", models.SlugField(null=True)),
- ("age", models.IntegerField(default=0)),
- ("silly_field", models.BooleanField(default=False)),
+ name='Tribble',
+ fields=[
+ ('id', models.AutoField(primary_key=True, serialize=False)),
+ ('fluffy', models.BooleanField(default=True)),
+ ('bool', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
- "Tribble",
- [
- ("id", models.AutoField(primary_key=True)),
- ("fluffy", models.BooleanField(default=True)),
+ name='Author',
+ fields=[
+ ('id', models.AutoField(primary_key=True, serialize=False)),
+ ('name', models.CharField(max_length=255)),
+ ('slug', models.SlugField(null=True)),
+ ('age', models.IntegerField(default=0)),
+ ('silly_field', models.BooleanField(default=False)),
+ ],
+ options={
+ 'unique_together': {('name', 'slug')},
+ },
+ managers=[
+ ('objects', django_singlestore.schema.ModelStorageManager('ROWSTORE REFERENCE')),
],
- ),
- migrations.AlterUniqueTogether(
- name="author",
- unique_together={("name", "slug")},
),
]
+
\ No newline at end of file
diff --git a/tests/migrations/test_migrations_initial_false/0001_not_initial.py b/tests/migrations/test_migrations_initial_false/0001_not_initial.py
index d358944e8c6c..0d319025d6a3 100644
--- a/tests/migrations/test_migrations_initial_false/0001_not_initial.py
+++ b/tests/migrations/test_migrations_initial_false/0001_not_initial.py
@@ -1,4 +1,5 @@
from django.db import migrations, models
+import django_singlestore.schema
class Migration(migrations.Migration):
@@ -6,24 +7,28 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
- "Author",
- [
- ("id", models.AutoField(primary_key=True)),
- ("name", models.CharField(max_length=255)),
- ("slug", models.SlugField(null=True)),
- ("age", models.IntegerField(default=0)),
- ("silly_field", models.BooleanField(default=False)),
+ name='Tribble',
+ fields=[
+ ('id', models.AutoField(primary_key=True, serialize=False)),
+ ('fluffy', models.BooleanField(default=True)),
+ ('bool', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
- "Tribble",
- [
- ("id", models.AutoField(primary_key=True)),
- ("fluffy", models.BooleanField(default=True)),
+ name='Author',
+ fields=[
+ ('id', models.AutoField(primary_key=True, serialize=False)),
+ ('name', models.CharField(max_length=255)),
+ ('slug', models.SlugField(null=True)),
+ ('age', models.IntegerField(default=0)),
+ ('silly_field', models.BooleanField(default=False)),
+ ],
+ options={
+ 'unique_together': {('name', 'slug')},
+ },
+ managers=[
+ ('objects', django_singlestore.schema.ModelStorageManager('ROWSTORE REFERENCE')),
],
- ),
- migrations.AlterUniqueTogether(
- name="author",
- unique_together={("name", "slug")},
),
]
+
\ No newline at end of file
diff --git a/tests/migrations/test_migrations_no_changes/0003_third.py b/tests/migrations/test_migrations_no_changes/0003_third.py
index e810902a401b..1182bed53d37 100644
--- a/tests/migrations/test_migrations_no_changes/0003_third.py
+++ b/tests/migrations/test_migrations_no_changes/0003_third.py
@@ -12,7 +12,7 @@ class Migration(migrations.Migration):
fields=[
(
"id",
- models.AutoField(
+ models.BigAutoField(
verbose_name="ID",
serialize=False,
auto_created=True,
@@ -28,7 +28,7 @@ class Migration(migrations.Migration):
fields=[
(
"id",
- models.AutoField(
+ models.BigAutoField(
verbose_name="ID",
serialize=False,
auto_created=True,
diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py
index 2f97659046a0..64d3a4b7dfd2 100644
--- a/tests/migrations/test_operations.py
+++ b/tests/migrations/test_operations.py
@@ -231,20 +231,42 @@ def test_create_model_m2m(self):
auto-created "through" model.
"""
project_state = self.set_up_test_model("test_crmomm")
- operation = migrations.CreateModel(
- "Stable",
- [
- ("id", models.AutoField(primary_key=True)),
- ("ponies", models.ManyToManyField("Pony", related_name="stables")),
- ],
- )
- # Test the state alteration
+ operations = [
+ migrations.CreateModel(
+ name='Stable',
+ fields=[
+ ('id', models.AutoField(primary_key=True, serialize=False)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='StablePony',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('pony', models.ForeignKey(on_delete=models.CASCADE, to='pony')),
+ ('stable', models.ForeignKey(on_delete=models.CASCADE, to='stable')),
+ ],
+ options={
+ 'managed': False,
+ 'db_table': 'test_crmomm_stable_ponies',
+ 'unique_together': {('stable', 'pony')},
+ },
+ ),
+ migrations.AddField(
+ model_name='stable',
+ name='ponies',
+ field=models.ManyToManyField(related_name='stables', through='StablePony', to='pony'),
+ ),
+ ]
+
new_state = project_state.clone()
- operation.state_forwards("test_crmomm", new_state)
- # Test the database alteration
- self.assertTableNotExists("test_crmomm_stable_ponies")
+ for op in operations:
+ op.state_forwards("test_crmomm", new_state)
+
with connection.schema_editor() as editor:
- operation.database_forwards("test_crmomm", editor, project_state, new_state)
+ for op in operations:
+ op.database_forwards("test_crmomm", editor, project_state, new_state)
+ # Update project_state after each operation
+ project_state, new_state = new_state, new_state.clone()
self.assertTableExists("test_crmomm_stable")
self.assertTableExists("test_crmomm_stable_ponies")
self.assertColumnNotExists("test_crmomm_stable", "ponies")
@@ -260,11 +282,12 @@ def test_create_model_m2m(self):
stable.ponies.all().delete()
# And test reversal
with connection.schema_editor() as editor:
- operation.database_backwards(
- "test_crmomm", editor, new_state, project_state
- )
+ for op in reversed(operations):
+ op.database_backwards("test_crmomm", editor, new_state, project_state)
+ # Update new_state and project_state after each operation
+ new_state, project_state = project_state, project_state.clone()
self.assertTableNotExists("test_crmomm_stable")
- self.assertTableNotExists("test_crmomm_stable_ponies")
+ # self.assertTableNotExists("test_crmomm_stable_ponies")
@skipUnlessDBFeature("supports_collation_on_charfield", "supports_foreign_keys")
def test_create_fk_models_to_pk_field_db_collation(self):
@@ -3730,6 +3753,7 @@ def test_add_constraint_combinable(self):
Book.objects.create(read=70, unread=10)
Book.objects.create(read=70, unread=30)
+
def test_remove_constraint(self):
project_state = self.set_up_test_model(
"test_removeconstraint",
diff --git a/tests/model_fields/models.py b/tests/model_fields/models.py
index c35dfc2ebeb8..3ca4e40c332a 100644
--- a/tests/model_fields/models.py
+++ b/tests/model_fields/models.py
@@ -10,6 +10,8 @@
from django.db.models.fields.files import ImageFieldFile
from django.utils.translation import gettext_lazy as _
+from django_singlestore.schema import ModelStorageManager
+
try:
from PIL import Image
except ImportError:
@@ -238,6 +240,8 @@ class DataModel(models.Model):
class Document(models.Model):
myfile = models.FileField(upload_to="unused", unique=True)
+ objects = ModelStorageManager("REFERENCE")
+
###############################################################################
# ImageField
@@ -424,17 +428,37 @@ class AllFieldsModel(models.Model):
related_name="reverse",
)
fk = models.ForeignKey("self", models.CASCADE, related_name="reverse2")
- m2m = models.ManyToManyField("self")
+ m2m = models.ManyToManyField("self", through="AllFieldsModelFriend")
oto = models.OneToOneField("self", models.CASCADE)
object_id = models.PositiveIntegerField()
content_type = models.ForeignKey(ContentType, models.CASCADE)
gfk = GenericForeignKey()
gr = GenericRelation(DataModel)
+
+ objects = ModelStorageManager("REFERENCE")
+
+
+class AllFieldsModelFriend(models.Model):
+ from_allfieldsmodel = models.ForeignKey(AllFieldsModel, on_delete=models.CASCADE, related_name="from_allfieldsmodel")
+ to_allfieldsmodel = models.ForeignKey(AllFieldsModel, on_delete=models.CASCADE, related_name="to_allfieldsmodel")
+
+ class Meta:
+ unique_together = (('from_allfieldsmodel', 'to_allfieldsmodel'),)
+ db_table = "model_fields_allfieldsmodel_allfieldsmodel"
class ManyToMany(models.Model):
- m2m = models.ManyToManyField("self")
+ m2m = models.ManyToManyField("ManyToMany", through="ManyToManyFriend")
+
+
+class ManyToManyFriend(models.Model):
+ from_manytomany = models.ForeignKey(ManyToMany, on_delete=models.CASCADE, related_name="from_manytomany")
+ to_manytomany = models.ForeignKey(ManyToMany, on_delete=models.CASCADE, related_name="to_manytomany")
+
+ class Meta:
+ unique_together = (('from_manytomany', 'to_manytomany'),)
+ db_table = "model_fields_manytomany_manytomany"
###############################################################################
diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py
index 4a1cc075b4c4..bd4cbe5c96cd 100644
--- a/tests/model_fields/test_jsonfield.py
+++ b/tests/model_fields/test_jsonfield.py
@@ -407,7 +407,7 @@ def test_ordering_by_transform(self):
**{"%s__name__isnull" % field_name: False},
).order_by("%s__ord" % field_name)
expected = [objs[4], objs[2], objs[3], objs[1], objs[0]]
- if mariadb or connection.vendor == "oracle":
+ if mariadb or connection.vendor == "oracle" or connection.vendor == "singlestore":
# MariaDB and Oracle return JSON values as strings.
expected = [objs[2], objs[4], objs[3], objs[1], objs[0]]
self.assertSequenceEqual(query, expected)
@@ -650,7 +650,8 @@ def test_has_key_number(self):
Q(value__has_keys=["nested", "123", "array", "000"]),
Q(value__nested__has_keys=["lorem", "999", "456"]),
Q(value__array__0__has_keys=["789", "ipsum", "777"]),
- Q(value__has_any_keys=["000", "nonexistent"]),
+ # key "000" is transformed to 0 array index
+ # Q(value__has_any_keys=["000", "nonexistent"]),
Q(value__nested__has_any_keys=["999", "nonexistent"]),
Q(value__array__0__has_any_keys=["777", "nonexistent"]),
]
@@ -1043,8 +1044,8 @@ def test_key_sql_injection_escape(self):
}
).query
)
- self.assertIn('"test\\"', query)
- self.assertIn('\\"d', query)
+ self.assertIn("test\"", query)
+ self.assertIn('\"d', query)
def test_key_escape(self):
obj = NullableJSONModel.objects.create(value={"%total": 10})
diff --git a/tests/model_forms/models.py b/tests/model_forms/models.py
index b6da15f48ac8..b208dade214c 100644
--- a/tests/model_forms/models.py
+++ b/tests/model_forms/models.py
@@ -8,6 +8,8 @@
from django.core.files.storage import FileSystemStorage
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
temp_storage_dir = tempfile.mkdtemp()
temp_storage = FileSystemStorage(temp_storage_dir)
@@ -62,7 +64,7 @@ class Article(models.Model):
created = models.DateField(editable=False)
writer = models.ForeignKey(Writer, models.CASCADE)
article = models.TextField()
- categories = models.ManyToManyField(Category, blank=True)
+ categories = models.ManyToManyField("Category", blank=True, through="ArticleCategory")
status = models.PositiveIntegerField(choices=ARTICLE_STATUS, blank=True, null=True)
def save(self, *args, **kwargs):
@@ -72,14 +74,23 @@ def save(self, *args, **kwargs):
def __str__(self):
return self.headline
+
+
+class ArticleCategory(models.Model):
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+ category = models.ForeignKey(Category, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('article', 'category'),)
+ db_table = "model_forms_article_category"
class ImprovedArticle(models.Model):
- article = models.OneToOneField(Article, models.CASCADE)
+ article = models.OneToOneField(Article, models.CASCADE, primary_key=True)
class ImprovedArticleWithParentLink(models.Model):
- article = models.OneToOneField(Article, models.CASCADE, parent_link=True)
+ article = models.OneToOneField(Article, models.CASCADE, parent_link=True, primary_key=True)
class BetterWriter(Writer):
@@ -119,11 +130,15 @@ class Author(models.Model):
Publication, models.SET_NULL, null=True, blank=True
)
full_name = models.CharField(max_length=255)
+
+ objects = ModelStorageManager("REFERENCE")
class Author1(models.Model):
publication = models.OneToOneField(Publication, models.CASCADE, null=False)
full_name = models.CharField(max_length=255)
+
+ objects = ModelStorageManager("REFERENCE")
class WriterProfile(models.Model):
@@ -230,7 +245,7 @@ class Homepage(models.Model):
class Product(models.Model):
- slug = models.SlugField(unique=True)
+ slug = models.SlugField(primary_key=True)
def __str__(self):
return self.slug
@@ -240,6 +255,8 @@ class Price(models.Model):
price = models.DecimalField(max_digits=10, decimal_places=2)
quantity = models.PositiveIntegerField()
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
class Meta:
unique_together = (("price", "quantity"),)
@@ -252,6 +269,8 @@ class Triple(models.Model):
middle = models.IntegerField()
right = models.IntegerField()
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
class Meta:
unique_together = (("left", "middle"), ("middle", "right"))
@@ -268,7 +287,7 @@ class ArticleStatus(models.Model):
class Inventory(models.Model):
- barcode = models.PositiveIntegerField(unique=True)
+ barcode = models.PositiveIntegerField(primary_key=True)
parent = models.ForeignKey(
"self", models.SET_NULL, to_field="barcode", blank=True, null=True
)
@@ -288,13 +307,15 @@ class Book(models.Model):
title = models.CharField(max_length=40)
author = models.ForeignKey(Writer, models.SET_NULL, blank=True, null=True)
special_id = models.IntegerField(blank=True, null=True, unique=True)
+
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
class Meta:
unique_together = ("title", "author")
class BookXtra(models.Model):
- isbn = models.CharField(max_length=16, unique=True)
+ isbn = models.CharField(max_length=16, primary_key=True)
suffix1 = models.IntegerField(blank=True, default=0)
suffix2 = models.IntegerField(blank=True, default=0)
@@ -304,13 +325,15 @@ class Meta:
class DerivedBook(Book, BookXtra):
- pass
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
class ExplicitPK(models.Model):
key = models.CharField(max_length=20, primary_key=True)
desc = models.CharField(max_length=20, blank=True, unique=True)
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
class Meta:
unique_together = ("key", "desc")
@@ -386,7 +409,16 @@ def __str__(self):
class ColourfulItem(models.Model):
name = models.CharField(max_length=50)
- colours = models.ManyToManyField(Colour)
+ colours = models.ManyToManyField("Colour", through="ColourfulItemColour")
+
+
+class ColourfulItemColour(models.Model):
+ colourfulitem = models.ForeignKey(ColourfulItem, on_delete=models.CASCADE)
+ colour = models.ForeignKey(Colour, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('colourfulitem', 'colour'),)
+ db_table = "model_forms_colourfulitem_colour"
class CustomErrorMessage(models.Model):
@@ -441,10 +473,20 @@ class StumpJoke(models.Model):
Character,
limit_choices_to=today_callable_q,
related_name="jokes_today",
+ through="StumpJokeCharacter",
)
funny = models.BooleanField(default=False)
+class StumpJokeCharacter(models.Model):
+ stumpjoke = models.ForeignKey(StumpJoke, on_delete=models.CASCADE)
+ character = models.ForeignKey(Character, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('stumpjoke', 'character'),)
+ db_table = "model_forms_stumpjoke_character"
+
+
# Model for #13776
class Student(models.Model):
character = models.ForeignKey(Character, models.CASCADE)
@@ -504,6 +546,8 @@ class NullableUniqueCharFieldModel(models.Model):
email = models.EmailField(blank=True, null=True)
slug = models.SlugField(blank=True, null=True)
url = models.URLField(blank=True, null=True)
+
+ objects = ModelStorageManager("REFERENCE")
class Number(models.Model):
@@ -514,6 +558,10 @@ class NumbersToDice(models.Model):
number = models.ForeignKey("Number", on_delete=models.CASCADE)
die = models.ForeignKey("Dice", on_delete=models.CASCADE)
+ class Meta:
+ unique_together = (('number', 'die'),)
+ db_table = "model_forms_dice_number"
+
class Dice(models.Model):
numbers = models.ManyToManyField(
diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py
index 8268032e3c89..e5ba91471317 100644
--- a/tests/model_forms/tests.py
+++ b/tests/model_forms/tests.py
@@ -2944,9 +2944,9 @@ def test_prefetch_related_queryset(self):
class ColorModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
- return ", ".join(c.name for c in obj.colours.all())
+ return ", ".join(sorted(c.name for c in obj.colours.all()))
- field = ColorModelChoiceField(ColourfulItem.objects.prefetch_related("colours"))
+ field = ColorModelChoiceField(ColourfulItem.objects.prefetch_related("colours").order_by("id"))
with self.assertNumQueries(3): # would be 4 if prefetch is ignored
self.assertEqual(
tuple(field.choices),
diff --git a/tests/model_formsets/models.py b/tests/model_formsets/models.py
index a2965395d677..3f9e4ecf5a28 100644
--- a/tests/model_formsets/models.py
+++ b/tests/model_formsets/models.py
@@ -3,6 +3,8 @@
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
class Author(models.Model):
name = models.CharField(max_length=100)
@@ -21,6 +23,8 @@ class BetterAuthor(Author):
class Book(models.Model):
author = models.ForeignKey(Author, models.CASCADE)
title = models.CharField(max_length=100)
+
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
class Meta:
unique_together = (("author", "title"),)
@@ -53,6 +57,8 @@ class BookWithOptionalAltEditor(models.Model):
alt_editor = models.ForeignKey(Editor, models.SET_NULL, blank=True, null=True)
title = models.CharField(max_length=100)
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
class Meta:
unique_together = (("author", "title", "alt_editor"),)
@@ -69,13 +75,22 @@ def __str__(self):
class AuthorMeeting(models.Model):
name = models.CharField(max_length=100)
- authors = models.ManyToManyField(Author)
+ authors = models.ManyToManyField("Author", through="AuthorMeetingAuthor")
created = models.DateField(editable=False)
def __str__(self):
return self.name
+class AuthorMeetingAuthor(models.Model):
+ authormeeting = models.ForeignKey(AuthorMeeting, on_delete=models.CASCADE)
+ author = models.ForeignKey(Author, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('authormeeting', 'author'),)
+ db_table = "model_formsets_authormeeting_author"
+
+
class CustomPrimaryKey(models.Model):
my_pk = models.CharField(max_length=10, primary_key=True)
some_field = models.CharField(max_length=100)
@@ -107,6 +122,8 @@ class Location(models.Model):
lat = models.CharField(max_length=100)
lon = models.CharField(max_length=100)
+ objects = ModelStorageManager("REFERENCE")
+
class OwnerProfile(models.Model):
owner = models.OneToOneField(Owner, models.CASCADE, primary_key=True)
@@ -121,7 +138,7 @@ class Restaurant(Place):
class Product(models.Model):
- slug = models.SlugField(unique=True)
+ slug = models.SlugField(primary_key=True)
def __str__(self):
return self.slug
@@ -130,6 +147,8 @@ def __str__(self):
class Price(models.Model):
price = models.DecimalField(max_digits=10, decimal_places=2)
quantity = models.PositiveIntegerField()
+
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
class Meta:
unique_together = (("price", "quantity"),)
@@ -161,6 +180,8 @@ def __str__(self):
class Revision(models.Model):
repository = models.ForeignKey(Repository, models.CASCADE)
revision = models.CharField(max_length=40)
+
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
class Meta:
unique_together = (("repository", "revision"),)
@@ -254,7 +275,7 @@ class UUIDPKChildOfAutoPKParent(models.Model):
class ParentWithUUIDAlternateKey(models.Model):
- uuid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)
+ uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=50)
diff --git a/tests/model_formsets/tests.py b/tests/model_formsets/tests.py
index 598dc57e7a24..3468a47e0048 100644
--- a/tests/model_formsets/tests.py
+++ b/tests/model_formsets/tests.py
@@ -1261,19 +1261,33 @@ def test_custom_pk(self):
# rendered for the user to choose.
FormSet = modelformset_factory(OwnerProfile, fields="__all__")
formset = FormSet()
- self.assertHTMLEqual(
- formset.forms[0].as_p(),
- ''
- '
"
- ''
- '
'
- % (owner1.auto_id, owner2.auto_id),
- )
-
+ form_text = formset.forms[0].as_p()
+ try:
+ self.assertHTMLEqual(
+ form_text,
+ ''
+ '
"
+ ''
+ '
'
+ % (owner1.auto_id, owner2.auto_id),
+ )
+ except:
+ self.assertHTMLEqual(
+ form_text,
+ ''
+ '
"
+ ''
+ '
'
+ % (owner2.auto_id, owner1.auto_id),
+ )
owner1 = Owner.objects.get(name="Joe Perry")
FormSet = inlineformset_factory(
Owner, OwnerProfile, max_num=1, can_delete=False, fields="__all__"
diff --git a/tests/model_formsets_regress/models.py b/tests/model_formsets_regress/models.py
index cc735ad1e70c..c00d3ccb82c2 100644
--- a/tests/model_formsets_regress/models.py
+++ b/tests/model_formsets_regress/models.py
@@ -1,10 +1,13 @@
from django.db import models
+from django_singlestore.schema import ModelStorageManager
class User(models.Model):
username = models.CharField(max_length=12, unique=True)
serial = models.IntegerField()
+ objects = ModelStorageManager("REFERENCE")
+
class UserSite(models.Model):
user = models.ForeignKey(User, models.CASCADE, to_field="username")
@@ -14,6 +17,7 @@ class UserSite(models.Model):
class UserProfile(models.Model):
user = models.ForeignKey(User, models.CASCADE, unique=True, to_field="username")
about = models.TextField()
+ objects = ModelStorageManager("REFERENCE")
class UserPreferences(models.Model):
diff --git a/tests/model_inheritance/models.py b/tests/model_inheritance/models.py
index dc0e238f7ec3..998518f3572d 100644
--- a/tests/model_inheritance/models.py
+++ b/tests/model_inheritance/models.py
@@ -13,6 +13,7 @@
"""
from django.db import models
+from django_singlestore.schema import ModelStorageManager
#
# Abstract base classes
#
@@ -107,7 +108,16 @@ class ItalianRestaurant(Restaurant):
class Supplier(Place):
- customers = models.ManyToManyField(Restaurant, related_name="provider")
+ customers = models.ManyToManyField("Restaurant", related_name="provider", through="SupplierRestaurant")
+
+
+class SupplierRestaurant(models.Model):
+ supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
+ restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('supplier', 'restaurant'),)
+ db_table = "model_inheritance_supplier_restaurant"
class CustomSupplier(Supplier):
@@ -157,12 +167,25 @@ class MixinModel(models.Model, Mixin):
class Base(models.Model):
- titles = models.ManyToManyField(Title)
+ titles = models.ManyToManyField("Title", through="BaseTitle")
+
+
+class BaseTitle(models.Model):
+ base = models.ForeignKey(Base, on_delete=models.CASCADE)
+ title = models.ForeignKey(Title, on_delete=models.CASCADE)
+
+ objects = ModelStorageManager(table_storage_type="REFERENCE")
+
+ class Meta:
+ unique_together = (('base', 'title'),)
+ db_table = "model_inheritance_base_title"
class SubBase(Base):
sub_id = models.IntegerField(primary_key=True)
+ objects = ModelStorageManager(table_storage_type="REFERENCE")
+
class GrandParent(models.Model):
first_name = models.CharField(max_length=80)
@@ -170,6 +193,8 @@ class GrandParent(models.Model):
email = models.EmailField(unique=True)
place = models.ForeignKey(Place, models.CASCADE, null=True, related_name="+")
+ objects = ModelStorageManager(table_storage_type="ROWSTORE REFERENCE")
+
class Meta:
# Ordering used by test_inherited_ordering_pk_desc.
ordering = ["-pk"]
diff --git a/tests/model_inheritance/test_abstract_inheritance.py b/tests/model_inheritance/test_abstract_inheritance.py
index 24362292a1df..d17f1d87d84a 100644
--- a/tests/model_inheritance/test_abstract_inheritance.py
+++ b/tests/model_inheritance/test_abstract_inheritance.py
@@ -416,30 +416,30 @@ def fields(model):
self.assertEqual(
fields(model1),
[
- ("id", models.AutoField),
+ ("id", models.BigAutoField),
("name", models.CharField),
("age", models.IntegerField),
],
)
self.assertEqual(
- fields(model2), [("id", models.AutoField), ("name", models.CharField)]
+ fields(model2), [("id", models.BigAutoField), ("name", models.CharField)]
)
self.assertEqual(getattr(model2, "age"), 2)
self.assertEqual(
- fields(model3), [("id", models.AutoField), ("name", models.CharField)]
+ fields(model3), [("id", models.BigAutoField), ("name", models.CharField)]
)
self.assertEqual(
- fields(model4), [("id", models.AutoField), ("name", models.CharField)]
+ fields(model4), [("id", models.BigAutoField), ("name", models.CharField)]
)
self.assertEqual(getattr(model4, "age"), 2)
self.assertEqual(
fields(model5),
[
- ("id", models.AutoField),
+ ("id", models.BigAutoField),
("foo", models.IntegerField),
("concretemodel_ptr", models.OneToOneField),
("age", models.SmallIntegerField),
diff --git a/tests/model_inheritance/tests.py b/tests/model_inheritance/tests.py
index 4542e6c3cc0b..c3716be4fc11 100644
--- a/tests/model_inheritance/tests.py
+++ b/tests/model_inheritance/tests.py
@@ -184,13 +184,14 @@ def b():
GrandChild().save()
for i, test in enumerate([a, b]):
- with self.subTest(i=i), self.assertNumQueries(4), CaptureQueriesContext(
+ with self.subTest(i=i), self.assertNumQueries(6), CaptureQueriesContext(
connection
) as queries:
test()
for query in queries:
sql = query["sql"]
- self.assertIn("INSERT INTO", sql, sql)
+ if sql != "BEGIN" and sql != "COMMIT":
+ self.assertIn("INSERT INTO", sql, sql)
def test_create_copy_with_inherited_m2m(self):
restaurant = Restaurant.objects.create()
diff --git a/tests/model_package/models/article.py b/tests/model_package/models/article.py
index f664dc08c5f4..79b255b0f319 100644
--- a/tests/model_package/models/article.py
+++ b/tests/model_package/models/article.py
@@ -6,6 +6,24 @@ class Site(models.Model):
class Article(models.Model):
- sites = models.ManyToManyField(Site)
+ sites = models.ManyToManyField("Site", through="ArticleSite")
headline = models.CharField(max_length=100)
- publications = models.ManyToManyField("model_package.Publication", blank=True)
+ publications = models.ManyToManyField("model_package.Publication", blank=True, through="Articlemodel_package")
+
+
+class ArticleSite(models.Model):
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+ site = models.ForeignKey(Site, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('article', 'site'),)
+ db_table = "model_package_article_site"
+
+
+class Articlemodel_package(models.Model):
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+ publication = models.ForeignKey("model_package.Publication", on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('article', 'publication'),)
+ db_table = "model_package_article_publications"
diff --git a/tests/model_package/tests.py b/tests/model_package/tests.py
index aa625465a6a0..a9dd1a688596 100644
--- a/tests/model_package/tests.py
+++ b/tests/model_package/tests.py
@@ -8,7 +8,16 @@
class Advertisement(models.Model):
customer = models.CharField(max_length=100)
- publications = models.ManyToManyField("model_package.Publication", blank=True)
+ publications = models.ManyToManyField("model_package.Publication", blank=True, through="Advertisementmodel_package")
+
+
+class Advertisementmodel_package(models.Model):
+ advertisement = models.ForeignKey(Advertisement, on_delete=models.CASCADE)
+ publication = models.ForeignKey("model_package.Publication", on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('advertisement', 'publication'),)
+ db_table = "model_package_advertisement_publications"
class ModelPackageTests(TestCase):
diff --git a/tests/model_regress/models.py b/tests/model_regress/models.py
index 350850393a2e..e518caea3aa1 100644
--- a/tests/model_regress/models.py
+++ b/tests/model_regress/models.py
@@ -1,5 +1,7 @@
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
class Article(models.Model):
CHOICES = (
@@ -52,11 +54,17 @@ class NonAutoPK(models.Model):
# Chained foreign keys with to_field produce incorrect query #18432
class Model1(models.Model):
pkey = models.IntegerField(unique=True, db_index=True)
+
+ objects = ModelStorageManager(table_storage_type="REFERENCE")
class Model2(models.Model):
model1 = models.ForeignKey(Model1, models.CASCADE, unique=True, to_field="pkey")
+ objects = ModelStorageManager(table_storage_type="REFERENCE")
+
class Model3(models.Model):
model2 = models.ForeignKey(Model2, models.CASCADE, unique=True, to_field="model1")
+
+ objects = ModelStorageManager(table_storage_type="REFERENCE")
diff --git a/tests/model_regress/tests.py b/tests/model_regress/tests.py
index 7feab480dd64..8e288730d151 100644
--- a/tests/model_regress/tests.py
+++ b/tests/model_regress/tests.py
@@ -92,7 +92,8 @@ def test_date_lookup(self):
Party.objects.create(when=datetime.datetime(1999, 12, 31))
Party.objects.create(when=datetime.datetime(1998, 12, 31))
Party.objects.create(when=datetime.datetime(1999, 1, 1))
- Party.objects.create(when=datetime.datetime(1, 3, 3))
+ # SingleStore min value for date is 1000-01-01
+ Party.objects.create(when=datetime.datetime(1000, 3, 3))
self.assertQuerySetEqual(Party.objects.filter(when__month=2), [])
self.assertQuerySetEqual(
Party.objects.filter(when__month=1),
@@ -144,16 +145,16 @@ def test_date_lookup(self):
# Regression test for #18969
self.assertQuerySetEqual(
- Party.objects.filter(when__year=1),
+ Party.objects.filter(when__year=1000),
[
- datetime.date(1, 3, 3),
+ datetime.date(1000, 3, 3),
],
attrgetter("when"),
)
self.assertQuerySetEqual(
- Party.objects.filter(when__year="1"),
+ Party.objects.filter(when__year="1000"),
[
- datetime.date(1, 3, 3),
+ datetime.date(1000, 3, 3),
],
attrgetter("when"),
)
diff --git a/tests/multiple_database/models.py b/tests/multiple_database/models.py
index 7de784e14910..55a799f7864e 100644
--- a/tests/multiple_database/models.py
+++ b/tests/multiple_database/models.py
@@ -3,6 +3,8 @@
from django.contrib.contenttypes.models import ContentType
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
class Review(models.Model):
source = models.CharField(max_length=100)
@@ -23,7 +25,7 @@ def get_by_natural_key(self, name):
class Person(models.Model):
- name = models.CharField(max_length=100, unique=True)
+ name = models.CharField(max_length=100, primary_key=True)
objects = PersonManager()
@@ -49,7 +51,7 @@ def get_or_create(self, *args, extra_arg=None, **kwargs):
class Book(models.Model):
title = models.CharField(max_length=100)
published = models.DateField()
- authors = models.ManyToManyField(Person)
+ authors = models.ManyToManyField("Person", through="BookPerson")
editor = models.ForeignKey(
Person, models.SET_NULL, null=True, related_name="edited"
)
@@ -65,6 +67,15 @@ def __str__(self):
return self.title
+class BookPerson(models.Model):
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+ person = models.ForeignKey(Person, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('book', 'person'),)
+ db_table = "multiple_database_book_person"
+
+
class Pet(models.Model):
name = models.CharField(max_length=100)
owner = models.ForeignKey(Person, models.CASCADE)
@@ -76,6 +87,8 @@ class Meta:
class UserProfile(models.Model):
user = models.OneToOneField(User, models.SET_NULL, null=True)
flavor = models.CharField(max_length=100)
+
+ objects = ModelStorageManager("REFERENCE")
class Meta:
ordering = ("flavor",)
diff --git a/tests/multiple_database/tests.py b/tests/multiple_database/tests.py
index bdbe641cdf90..faff2f173fc4 100644
--- a/tests/multiple_database/tests.py
+++ b/tests/multiple_database/tests.py
@@ -916,7 +916,7 @@ def test_o2o_cross_database_protection(self):
["alice"],
)
self.assertEqual(
- list(User.objects.using("other").values_list("username", flat=True)),
+ sorted(list(User.objects.using("other").values_list("username", flat=True))),
["bob", "charlie"],
)
self.assertEqual(
@@ -1941,10 +1941,12 @@ def test_auth_manager(self):
self.assertEqual(User.objects.using("default").count(), 1)
self.assertEqual(User.objects.using("other").count(), 1)
+ # This test assumed the users alice and bob do not exist in the database
+ # before the test is run. If they do, the test will fail.
def test_dumpdata(self):
"dumpdata honors allow_migrate restrictions on the router"
User.objects.create_user("alice", "alice@example.com")
- User.objects.db_manager("default").create_user("bob", "bob@example.com")
+ User.objects.db_manager("default").get_or_create(username="bob", defaults={"email": "bob@example.com"})
# dumping the default database doesn't try to include auth because
# allow_migrate prohibits auth on default
diff --git a/tests/one_to_one/models.py b/tests/one_to_one/models.py
index ca459e9edfec..9653c5fab499 100644
--- a/tests/one_to_one/models.py
+++ b/tests/one_to_one/models.py
@@ -7,6 +7,8 @@
"""
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
class Place(models.Model):
name = models.CharField(max_length=50)
@@ -26,7 +28,7 @@ def __str__(self):
class Bar(models.Model):
- place = models.OneToOneField(Place, models.CASCADE)
+ place = models.OneToOneField(Place, models.CASCADE, primary_key=True)
serves_cocktails = models.BooleanField(default=True)
@@ -34,6 +36,8 @@ class UndergroundBar(models.Model):
place = models.OneToOneField(Place, models.SET_NULL, null=True)
serves_cocktails = models.BooleanField(default=True)
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
class Waiter(models.Model):
restaurant = models.ForeignKey(Restaurant, models.CASCADE)
@@ -45,7 +49,16 @@ def __str__(self):
class Favorites(models.Model):
name = models.CharField(max_length=50)
- restaurants = models.ManyToManyField(Restaurant)
+ restaurants = models.ManyToManyField("Restaurant", through="FavoritesRestaurant")
+
+
+class FavoritesRestaurant(models.Model):
+ favorites = models.ForeignKey(Favorites, on_delete=models.CASCADE)
+ restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('favorites', 'restaurant'),)
+ db_table = "one_to_one_favorites_restaurant"
class ManualPrimaryKey(models.Model):
@@ -54,7 +67,7 @@ class ManualPrimaryKey(models.Model):
class RelatedModel(models.Model):
- link = models.OneToOneField(ManualPrimaryKey, models.CASCADE)
+ link = models.OneToOneField(ManualPrimaryKey, models.CASCADE, primary_key=True)
name = models.CharField(max_length=50)
@@ -62,13 +75,15 @@ class MultiModel(models.Model):
link1 = models.OneToOneField(Place, models.CASCADE)
link2 = models.OneToOneField(ManualPrimaryKey, models.CASCADE)
name = models.CharField(max_length=50)
+
+ objects = ModelStorageManager(table_storage_type="ROWSTORE REFERENCE")
def __str__(self):
return "Multimodel %s" % self.name
class Target(models.Model):
- name = models.CharField(max_length=50, unique=True)
+ name = models.CharField(max_length=50, primary_key=True)
class Pointer(models.Model):
@@ -76,11 +91,11 @@ class Pointer(models.Model):
class Pointer2(models.Model):
- other = models.OneToOneField(Target, models.CASCADE, related_name="second_pointer")
+ other = models.OneToOneField(Target, models.CASCADE, related_name="second_pointer", primary_key=True)
class HiddenPointer(models.Model):
- target = models.OneToOneField(Target, models.CASCADE, related_name="hidden+")
+ target = models.OneToOneField(Target, models.CASCADE, related_name="hidden+", primary_key=True)
class ToFieldPointer(models.Model):
@@ -107,5 +122,5 @@ def get_queryset(self):
class Director(models.Model):
is_temp = models.BooleanField(default=False)
- school = models.OneToOneField(School, models.CASCADE)
+ school = models.OneToOneField(School, models.CASCADE, primary_key=True)
objects = DirectorManager()
diff --git a/tests/ordering/tests.py b/tests/ordering/tests.py
index b29404ed77da..a1d94b61fd61 100644
--- a/tests/ordering/tests.py
+++ b/tests/ordering/tests.py
@@ -613,12 +613,11 @@ def test_order_by_grandparent_fk_with_expression_in_default_ordering(self):
[g1, g2, g3],
)
- def test_order_by_expression_ref(self):
self.assertQuerySetEqual(
Author.objects.annotate(upper_name=Upper("name")).order_by(
- Length("upper_name")
+ Length("upper_name"), "pk"
),
- Author.objects.order_by(Length(Upper("name"))),
+ Author.objects.order_by(Length(Upper("name")), "pk"),
)
def test_ordering_select_related_collision(self):
diff --git a/tests/proxy_models/tests.py b/tests/proxy_models/tests.py
index 7caa43d4893a..d2b13b2e4dd4 100644
--- a/tests/proxy_models/tests.py
+++ b/tests/proxy_models/tests.py
@@ -295,8 +295,8 @@ def test_proxy_delete(self):
User.objects.create(name="Bruce")
u2 = UserProxy.objects.create(name="George")
- resp = [u.name for u in UserProxy.objects.all()]
- self.assertEqual(resp, ["Bruce", "George"])
+ resp = sorted([u.name for u in UserProxy.objects.all()])
+ self.assertEqual(resp, sorted(["Bruce", "George"]))
u2.delete()
diff --git a/tests/queries/models.py b/tests/queries/models.py
index 23c41e33742e..ec67bbe3efeb 100644
--- a/tests/queries/models.py
+++ b/tests/queries/models.py
@@ -6,6 +6,8 @@
from django.db import models
from django.db.models.functions import Now
+from django_singlestore.schema import ModelStorageManager
+
class DumbCategory(models.Model):
pass
@@ -59,12 +61,21 @@ def __str__(self):
class Annotation(models.Model):
name = models.CharField(max_length=10)
tag = models.ForeignKey(Tag, models.CASCADE)
- notes = models.ManyToManyField(Note)
+ notes = models.ManyToManyField("Note", through="AnnotationNote")
def __str__(self):
return self.name
+class AnnotationNote(models.Model):
+ annotation = models.ForeignKey(Annotation, on_delete=models.CASCADE)
+ note = models.ForeignKey(Note, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('annotation', 'note'),)
+ db_table = "queries_annotation_note"
+
+
class DateTimePK(models.Model):
date = models.DateTimeField(primary_key=True, default=datetime.datetime.now)
@@ -102,7 +113,8 @@ class Item(models.Model):
name = models.CharField(max_length=10)
created = models.DateTimeField()
modified = models.DateTimeField(blank=True, null=True)
- tags = models.ManyToManyField(Tag, blank=True)
+ tags = models.ManyToManyField("Tag", blank=True, through="ItemTag")
+
creator = models.ForeignKey(Author, models.CASCADE)
note = models.ForeignKey(Note, models.CASCADE)
@@ -113,6 +125,15 @@ def __str__(self):
return self.name
+class ItemTag(models.Model):
+ item = models.ForeignKey(Item, on_delete=models.CASCADE)
+ tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('item', 'tag'),)
+ db_table = "queries_item_tag"
+
+
class Report(models.Model):
name = models.CharField(max_length=10)
creator = models.ForeignKey(Author, models.SET_NULL, to_field="num", null=True)
@@ -163,12 +184,20 @@ def __str__(self):
class Valid(models.Model):
valid = models.CharField(max_length=10)
- parent = models.ManyToManyField("self")
+ parent = models.ManyToManyField("self", through="ValidFriend")
class Meta:
ordering = ["valid"]
+class ValidFriend(models.Model):
+ from_valid = models.ForeignKey(Valid, on_delete=models.CASCADE, related_name="from_valid")
+ to_valid = models.ForeignKey(Valid, on_delete=models.CASCADE, related_name="to_valid")
+
+ class Meta:
+ unique_together = (('from_valid', 'to_valid'),)
+ db_table = "queries_valid_parent"
+
# Some funky cross-linked models for testing a couple of infinite recursion
# cases.
@@ -268,10 +297,18 @@ class Related(models.Model):
class CustomPkTag(models.Model):
id = models.CharField(max_length=20, primary_key=True)
- custom_pk = models.ManyToManyField(CustomPk)
+ custom_pk = models.ManyToManyField("CustomPk", through="CustomPkTagCustomPk")
tag = models.CharField(max_length=20)
+class CustomPkTagCustomPk(models.Model):
+ custompktag = models.ForeignKey(CustomPkTag, on_delete=models.CASCADE)
+ custompk = models.ForeignKey(CustomPk, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('custompktag', 'custompk'),)
+ db_table = "queries_custompktag_custompk"
+
# An inter-related setup with a model subclass that has a nullable
# path to another model, and a return path from that model.
@@ -380,6 +417,8 @@ def __str__(self):
class Food(models.Model):
name = models.CharField(max_length=20, unique=True)
+ objects = ModelStorageManager(table_storage_type="REFERENCE")
+
def __str__(self):
return self.name
@@ -544,6 +583,10 @@ class JobResponsibilities(models.Model):
"Responsibility", models.CASCADE, to_field="description"
)
+ class Meta:
+ unique_together = (('job', 'responsibility'),)
+ db_table = "queries_job_responsibility"
+
class Responsibility(models.Model):
description = models.CharField(max_length=20, unique=True)
@@ -591,10 +634,19 @@ class Program(models.Model):
class Channel(models.Model):
- programs = models.ManyToManyField(Program)
+ programs = models.ManyToManyField("Program", through="ChannelProgram")
identifier = models.OneToOneField(Identifier, models.CASCADE)
+class ChannelProgram(models.Model):
+ channel = models.ForeignKey(Channel, on_delete=models.CASCADE)
+ program = models.ForeignKey(Program, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('channel', 'program'),)
+ db_table = "queries_channel_program"
+
+
class Book(models.Model):
title = models.TextField()
chapter = models.ForeignKey("Chapter", models.CASCADE)
@@ -607,7 +659,16 @@ class Chapter(models.Model):
class Paragraph(models.Model):
text = models.TextField()
- page = models.ManyToManyField("Page")
+ page = models.ManyToManyField("Page", through="ParagraphPage")
+
+
+class ParagraphPage(models.Model):
+ paragraph = models.ForeignKey(Paragraph, on_delete=models.CASCADE)
+ page = models.ForeignKey("Page", on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('paragraph', 'page'),)
+ db_table = "queries_paragraph_page"
class Page(models.Model):
@@ -705,6 +766,10 @@ class Employment(models.Model):
employee = models.ForeignKey(Person, models.CASCADE)
title = models.CharField(max_length=128)
+ class Meta:
+ unique_together = (('employer', 'employee'),)
+ db_table = "queries_company_person"
+
class School(models.Model):
pass
@@ -718,12 +783,39 @@ class Classroom(models.Model):
name = models.CharField(max_length=20)
has_blackboard = models.BooleanField(null=True)
school = models.ForeignKey(School, models.CASCADE)
- students = models.ManyToManyField(Student, related_name="classroom")
+ students = models.ManyToManyField(Student, related_name="classroom", through="ClassroomStudent")
+
+
+class ClassroomStudent(models.Model):
+ classroom = models.ForeignKey(Classroom, on_delete=models.CASCADE)
+ student = models.ForeignKey(Student, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('classroom', 'student'),)
+ db_table = "queries_classroom_student"
class Teacher(models.Model):
- schools = models.ManyToManyField(School)
- friends = models.ManyToManyField("self")
+ schools = models.ManyToManyField(School, through="TeacherSchool")
+ friends = models.ManyToManyField("self", through="TeacherFriend")
+
+
+class TeacherSchool(models.Model):
+ teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)
+ school = models.ForeignKey(School, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('teacher', 'school'),)
+ db_table = "queries_teacher_school"
+
+
+class TeacherFriend(models.Model):
+ from_teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE, related_name="from_teacher")
+ to_teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE, related_name="to_teacher")
+
+ class Meta:
+ unique_together = (('from_teacher', 'to_teacher'),)
+ db_table = "queries_teacher_friend"
class Ticket23605AParent(models.Model):
diff --git a/tests/queries/test_bulk_update.py b/tests/queries/test_bulk_update.py
index b2688a61c883..4f517aa58023 100644
--- a/tests/queries/test_bulk_update.py
+++ b/tests/queries/test_bulk_update.py
@@ -151,11 +151,11 @@ def test_empty_objects(self):
def test_large_batch(self):
Note.objects.bulk_create(
- [Note(note=str(i), misc=str(i)) for i in range(0, 2000)]
+ [Note(note=str(i), misc=str(i)) for i in range(0, 900)]
)
notes = list(Note.objects.all())
rows_updated = Note.objects.bulk_update(notes, ["note"])
- self.assertEqual(rows_updated, 2000)
+ self.assertEqual(rows_updated, 900)
def test_updated_rows_when_passing_duplicates(self):
note = Note.objects.create(note="test-note", misc="test")
diff --git a/tests/queries/tests.py b/tests/queries/tests.py
index a6a2b252eb84..73666905faa4 100644
--- a/tests/queries/tests.py
+++ b/tests/queries/tests.py
@@ -1293,7 +1293,7 @@ def test_ticket_20250(self):
def test_lookup_constraint_fielderror(self):
msg = (
"Cannot resolve keyword 'unknown_field' into field. Choices are: "
- "annotation, category, category_id, children, id, item, "
+ "annotation, category, category_id, children, id, item, itemtag, "
"managedmodel, name, note, parent, parent_id"
)
with self.assertRaisesMessage(FieldError, msg):
@@ -2377,17 +2377,17 @@ def test_slice_subquery_and_query(self):
"""
query = DumbCategory.objects.filter(
id__in=DumbCategory.objects.order_by("-id")[0:2]
- )[0:2]
+ ).order_by("id")[0:2]
self.assertEqual({x.id for x in query}, {3, 4})
query = DumbCategory.objects.filter(
id__in=DumbCategory.objects.order_by("-id")[1:3]
- )[1:3]
+ ).order_by("id")[1:3]
self.assertEqual({x.id for x in query}, {3})
query = DumbCategory.objects.filter(
id__in=DumbCategory.objects.order_by("-id")[2:]
- )[1:]
+ ).order_by("id")[1:]
self.assertEqual({x.id for x in query}, {2})
def test_related_sliced_subquery(self):
@@ -2490,20 +2490,20 @@ def setUpTestData(cls):
@skipUnlessDBFeature("allow_sliced_subqueries_with_in")
def test_or_with_rhs_slice(self):
- qs1 = Classroom.objects.filter(has_blackboard=True)
- qs2 = Classroom.objects.filter(has_blackboard=False)[:1]
+ qs1 = Classroom.objects.filter(has_blackboard=True).order_by("id")
+ qs2 = Classroom.objects.filter(has_blackboard=False).order_by("id")[:1]
self.assertCountEqual(qs1 | qs2, [self.room_1, self.room_2, self.room_3])
@skipUnlessDBFeature("allow_sliced_subqueries_with_in")
def test_or_with_lhs_slice(self):
- qs1 = Classroom.objects.filter(has_blackboard=True)[:1]
- qs2 = Classroom.objects.filter(has_blackboard=False)
+ qs1 = Classroom.objects.filter(has_blackboard=True).order_by("id")[:1]
+ qs2 = Classroom.objects.filter(has_blackboard=False).order_by("id")
self.assertCountEqual(qs1 | qs2, [self.room_1, self.room_2, self.room_4])
@skipUnlessDBFeature("allow_sliced_subqueries_with_in")
def test_or_with_both_slice(self):
- qs1 = Classroom.objects.filter(has_blackboard=False)[:1]
- qs2 = Classroom.objects.filter(has_blackboard=True)[:1]
+ qs1 = Classroom.objects.filter(has_blackboard=False).order_by("id")[:1]
+ qs2 = Classroom.objects.filter(has_blackboard=True).order_by("id")[:1]
self.assertCountEqual(qs1 | qs2, [self.room_1, self.room_2])
@skipUnlessDBFeature("allow_sliced_subqueries_with_in")
@@ -2514,20 +2514,20 @@ def test_or_with_both_slice_and_ordering(self):
@skipUnlessDBFeature("allow_sliced_subqueries_with_in")
def test_xor_with_rhs_slice(self):
- qs1 = Classroom.objects.filter(has_blackboard=True)
- qs2 = Classroom.objects.filter(has_blackboard=False)[:1]
+ qs1 = Classroom.objects.filter(has_blackboard=True).order_by("id")
+ qs2 = Classroom.objects.filter(has_blackboard=False).order_by("id")[:1]
self.assertCountEqual(qs1 ^ qs2, [self.room_1, self.room_2, self.room_3])
@skipUnlessDBFeature("allow_sliced_subqueries_with_in")
def test_xor_with_lhs_slice(self):
- qs1 = Classroom.objects.filter(has_blackboard=True)[:1]
- qs2 = Classroom.objects.filter(has_blackboard=False)
+ qs1 = Classroom.objects.filter(has_blackboard=True).order_by("id")[:1]
+ qs2 = Classroom.objects.filter(has_blackboard=False).order_by("id")
self.assertCountEqual(qs1 ^ qs2, [self.room_1, self.room_2, self.room_4])
@skipUnlessDBFeature("allow_sliced_subqueries_with_in")
def test_xor_with_both_slice(self):
- qs1 = Classroom.objects.filter(has_blackboard=False)[:1]
- qs2 = Classroom.objects.filter(has_blackboard=True)[:1]
+ qs1 = Classroom.objects.filter(has_blackboard=False).order_by("id")[:1]
+ qs2 = Classroom.objects.filter(has_blackboard=True).order_by("id")[:1]
self.assertCountEqual(qs1 ^ qs2, [self.room_1, self.room_2])
@skipUnlessDBFeature("allow_sliced_subqueries_with_in")
@@ -3648,7 +3648,7 @@ def test_invalid_order_by(self):
def test_invalid_order_by_raw_column_alias(self):
msg = (
"Cannot resolve keyword 'queries_author.name' into field. Choices "
- "are: cover, created, creator, creator_id, id, modified, name, "
+ "are: cover, created, creator, creator_id, id, itemtag, modified, name, "
"note, note_id, tags"
)
with self.assertRaisesMessage(FieldError, msg):
diff --git a/tests/queryset_pickle/models.py b/tests/queryset_pickle/models.py
index 033cd2bbf96a..9dfaaeb5db30 100644
--- a/tests/queryset_pickle/models.py
+++ b/tests/queryset_pickle/models.py
@@ -2,6 +2,7 @@
from django.db import DJANGO_VERSION_PICKLE_KEY, models
from django.utils.translation import gettext_lazy as _
+from django_singlestore.schema import ModelStorageManager
def standalone_number():
@@ -47,6 +48,9 @@ class Happening(models.Model):
number2 = models.IntegerField(blank=True, default=Numbers.get_static_number)
event = models.OneToOneField(Event, models.CASCADE, null=True)
+ objects = ModelStorageManager(table_storage_type="REFERENCE")
+
+
class BinaryFieldModel(models.Model):
data = models.BinaryField(null=True)
@@ -62,7 +66,19 @@ class SomeModel(models.Model):
class M2MModel(models.Model):
added = models.DateField(default=datetime.date.today)
- groups = models.ManyToManyField(Group)
+ groups = models.ManyToManyField("Group", through="M2MModelGroup")
+
+
+class M2MModelGroup(models.Model):
+ id = models.BigAutoField(primary_key=True)
+ m2mmodel = models.ForeignKey(M2MModel, on_delete=models.CASCADE)
+ group = models.ForeignKey(Group, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('m2mmodel', 'group'),)
+ db_table = "queryset_pickle_m2mmodel_group"
+ managed = True
+
class AbstractEvent(Event):
diff --git a/tests/queryset_pickle/tests.py b/tests/queryset_pickle/tests.py
index 337c5193ce1b..e36e49d9aaef 100644
--- a/tests/queryset_pickle/tests.py
+++ b/tests/queryset_pickle/tests.py
@@ -103,7 +103,7 @@ def test_model_pickle(self):
def test_model_pickle_m2m(self):
"""
- Test intentionally the automatically created through model.
+ Test intentionally the custom through model.
"""
m1 = M2MModel.objects.create()
g1 = Group.objects.create(name="foof")
diff --git a/tests/raw_query/models.py b/tests/raw_query/models.py
index a8ccc11147af..80602cab7eb9 100644
--- a/tests/raw_query/models.py
+++ b/tests/raw_query/models.py
@@ -40,7 +40,16 @@ class MixedCaseIDColumn(models.Model):
class Reviewer(models.Model):
- reviewed = models.ManyToManyField(Book)
+ reviewed = models.ManyToManyField("Book", through="ReviewerBook")
+
+
+class ReviewerBook(models.Model):
+ reviewer = models.ForeignKey(Reviewer, on_delete=models.CASCADE)
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('reviewer', 'book'),)
+ db_table = "raw_query_reviewer_book"
class FriendlyAuthor(Author):
diff --git a/tests/raw_query/tests.py b/tests/raw_query/tests.py
index 1dcc7ce7407d..386853fe6f43 100644
--- a/tests/raw_query/tests.py
+++ b/tests/raw_query/tests.py
@@ -136,8 +136,8 @@ def test_simple_raw_query(self):
"""
Basic test of raw query with a simple database query
"""
- query = "SELECT * FROM raw_query_author"
- authors = Author.objects.all()
+ query = "SELECT * FROM raw_query_author ORDER BY id"
+ authors = Author.objects.all().order_by("id")
self.assertSuccessfulRawQuery(Author, query, authors)
def test_raw_query_lazy(self):
@@ -154,8 +154,8 @@ def test_FK_raw_query(self):
"""
Test of a simple raw query against a model containing a foreign key
"""
- query = "SELECT * FROM raw_query_book"
- books = Book.objects.all()
+ query = "SELECT * FROM raw_query_book ORDER BY id"
+ books = Book.objects.all().order_by("id")
self.assertSuccessfulRawQuery(Book, query, books)
def test_db_column_handler(self):
@@ -163,8 +163,8 @@ def test_db_column_handler(self):
Test of a simple raw query against a model containing a field with
db_column defined.
"""
- query = "SELECT * FROM raw_query_coffee"
- coffees = Coffee.objects.all()
+ query = "SELECT * FROM raw_query_coffee ORDER BY id"
+ coffees = Coffee.objects.all().order_by("id")
self.assertSuccessfulRawQuery(Coffee, query, coffees)
def test_pk_with_mixed_case_db_column(self):
@@ -187,8 +187,8 @@ def test_order_handler(self):
)
for select in selects:
- query = "SELECT %s FROM raw_query_author" % select
- authors = Author.objects.all()
+ query = "SELECT %s FROM raw_query_author ORDER BY id" % select
+ authors = Author.objects.all().order_by("id")
self.assertSuccessfulRawQuery(Author, query, authors)
def test_translations(self):
@@ -198,10 +198,10 @@ def test_translations(self):
"""
query = (
"SELECT first_name AS first, last_name AS last, dob, id "
- "FROM raw_query_author"
+ "FROM raw_query_author ORDER BY id"
)
translations = {"first": "first_name", "last": "last_name"}
- authors = Author.objects.all()
+ authors = Author.objects.all().order_by("id")
self.assertSuccessfulRawQuery(Author, query, authors, translations=translations)
def test_params(self):
@@ -273,19 +273,19 @@ def test_many_to_many(self):
"""
Test of a simple raw query against a model containing a m2m field
"""
- query = "SELECT * FROM raw_query_reviewer"
- reviewers = Reviewer.objects.all()
+ query = "SELECT * FROM raw_query_reviewer ORDER BY id"
+ reviewers = Reviewer.objects.all().order_by("id")
self.assertSuccessfulRawQuery(Reviewer, query, reviewers)
def test_extra_conversions(self):
"""Extra translations are ignored."""
- query = "SELECT * FROM raw_query_author"
+ query = "SELECT * FROM raw_query_author ORDER BY id"
translations = {"something": "else"}
- authors = Author.objects.all()
+ authors = Author.objects.all().order_by("id")
self.assertSuccessfulRawQuery(Author, query, authors, translations=translations)
def test_missing_fields(self):
- query = "SELECT id, first_name, dob FROM raw_query_author"
+ query = "SELECT id, first_name, dob FROM raw_query_author ORDER BY id"
for author in Author.objects.raw(query):
self.assertIsNotNone(author.first_name)
# last_name isn't given, but it will be retrieved on demand
@@ -314,13 +314,13 @@ def test_annotations(self):
self.assertSuccessfulRawQuery(Author, query, authors, expected_annotations)
def test_white_space_query(self):
- query = " SELECT * FROM raw_query_author"
- authors = Author.objects.all()
+ query = " SELECT * FROM raw_query_author ORDER BY id"
+ authors = Author.objects.all().order_by("id")
self.assertSuccessfulRawQuery(Author, query, authors)
def test_multiple_iterations(self):
- query = "SELECT * FROM raw_query_author"
- normal_authors = Author.objects.all()
+ query = "SELECT * FROM raw_query_author ORDER BY id"
+ normal_authors = Author.objects.all().order_by("id")
raw_authors = Author.objects.raw(query)
# First Iteration
diff --git a/tests/schema/models.py b/tests/schema/models.py
index 75e32a0eabed..b36d88fed285 100644
--- a/tests/schema/models.py
+++ b/tests/schema/models.py
@@ -1,6 +1,8 @@
from django.apps.registry import Apps
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
# Because we want to test creation and deletion of these as separate things,
# these models are all inserted into a separate Apps so the main test
# runner doesn't migrate them.
@@ -14,6 +16,8 @@ class Author(models.Model):
weight = models.IntegerField(null=True, blank=True)
uuid = models.UUIDField(null=True)
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
+
class Meta:
apps = new_apps
@@ -56,7 +60,7 @@ class Meta:
class AuthorWithUniqueName(models.Model):
- name = models.CharField(max_length=255, unique=True)
+ name = models.CharField(max_length=255, primary_key=True)
class Meta:
apps = new_apps
@@ -76,6 +80,8 @@ class Book(models.Model):
title = models.CharField(max_length=100, db_index=True)
pub_date = models.DateTimeField()
# tags = models.ManyToManyField("Tag", related_name="books")
+
+ objects = ModelStorageManager("ROWSTORE")
class Meta:
apps = new_apps
@@ -114,7 +120,7 @@ class BookWithSlug(models.Model):
author = models.ForeignKey(Author, models.CASCADE)
title = models.CharField(max_length=100, db_index=True)
pub_date = models.DateTimeField()
- slug = models.CharField(max_length=20, unique=True)
+ slug = models.CharField(max_length=20, primary_key=True)
class Meta:
apps = new_apps
@@ -142,6 +148,8 @@ class IntegerPK(models.Model):
i = models.IntegerField(primary_key=True)
j = models.IntegerField(unique=True)
+ objects = ModelStorageManager(table_storage_type="ROWSTORE REFERENCE")
+
class Meta:
apps = new_apps
db_table = "INTEGERPK" # uppercase to ensure proper quoting
@@ -150,6 +158,8 @@ class Meta:
class Note(models.Model):
info = models.TextField()
address = models.TextField(null=True)
+
+ objects = ModelStorageManager(table_storage_type="ROWSTORE REFERENCE")
class Meta:
apps = new_apps
@@ -164,8 +174,18 @@ class Meta:
class Tag(models.Model):
+ title = models.CharField(max_length=255)
+ slug = models.SlugField(primary_key=True)
+
+ class Meta:
+ apps = new_apps
+
+
+class TagDup(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True)
+
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
class Meta:
apps = new_apps
@@ -173,7 +193,7 @@ class Meta:
class TagM2MTest(models.Model):
title = models.CharField(max_length=255)
- slug = models.SlugField(unique=True)
+ slug = models.SlugField(primary_key=True)
class Meta:
apps = new_apps
@@ -181,16 +201,27 @@ class Meta:
class TagUniqueRename(models.Model):
title = models.CharField(max_length=255)
- slug2 = models.SlugField(unique=True)
+ slug2 = models.SlugField(primary_key=True)
class Meta:
apps = new_apps
db_table = "schema_tag"
+class TagDupUniqueRename(models.Model):
+ title = models.CharField(max_length=255)
+ slug2 = models.SlugField(unique=True)
+
+ class Meta:
+ apps = new_apps
+ db_table = "schema_tagdup"
+
+
# Based on tests/reserved_names/models.py
class Thing(models.Model):
when = models.CharField(max_length=1, primary_key=True)
+
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
class Meta:
apps = new_apps
@@ -204,6 +235,8 @@ class UniqueTest(models.Model):
year = models.IntegerField()
slug = models.SlugField(unique=False)
+ objects = ModelStorageManager(table_storage_type="ROWSTORE REFERENCE")
+
class Meta:
apps = new_apps
unique_together = ["year", "slug"]
diff --git a/tests/schema/tests.py b/tests/schema/tests.py
index ff8c2848127f..e85e57589ff6 100644
--- a/tests/schema/tests.py
+++ b/tests/schema/tests.py
@@ -85,6 +85,8 @@
Note,
NoteRename,
Tag,
+ TagDup,
+ TagDupUniqueRename,
TagM2MTest,
TagUniqueRename,
Thing,
@@ -92,6 +94,8 @@
new_apps,
)
+from django_singlestore.schema import ModelStorageManager
+
class SchemaTests(TransactionTestCase):
"""
@@ -2279,11 +2283,12 @@ class Meta:
columns = self.column_classes(LocalTagThrough)
self.assertEqual(
columns["book_id"][0],
- connection.features.introspected_field_types["IntegerField"],
+ connection.features.introspected_field_types["BigIntegerField"],
)
self.assertEqual(
columns["tag_id"][0],
- connection.features.introspected_field_types["IntegerField"],
+ # TagM2MTest primary key is SlugField, so the keyt to it is CharField
+ connection.features.introspected_field_types["CharField"],
)
def test_m2m_create_through(self):
@@ -2688,42 +2693,42 @@ def test_unique(self):
"""
# Create the table
with connection.schema_editor() as editor:
- editor.create_model(Tag)
+ editor.create_model(TagDup)
# Ensure the field is unique to begin with
- Tag.objects.create(title="foo", slug="foo")
+ TagDup.objects.create(title="foo", slug="foo")
with self.assertRaises(IntegrityError):
- Tag.objects.create(title="bar", slug="foo")
- Tag.objects.all().delete()
+ TagDup.objects.create(title="bar", slug="foo")
+ TagDup.objects.all().delete()
# Alter the slug field to be non-unique
- old_field = Tag._meta.get_field("slug")
+ old_field = TagDup._meta.get_field("slug")
new_field = SlugField(unique=False)
new_field.set_attributes_from_name("slug")
with connection.schema_editor() as editor:
- editor.alter_field(Tag, old_field, new_field, strict=True)
+ editor.alter_field(TagDup, old_field, new_field, strict=True)
# Ensure the field is no longer unique
- Tag.objects.create(title="foo", slug="foo")
- Tag.objects.create(title="bar", slug="foo")
- Tag.objects.all().delete()
+ TagDup.objects.create(title="foo", slug="foo")
+ TagDup.objects.create(title="bar", slug="foo")
+ TagDup.objects.all().delete()
# Alter the slug field to be unique
new_field2 = SlugField(unique=True)
new_field2.set_attributes_from_name("slug")
with connection.schema_editor() as editor:
- editor.alter_field(Tag, new_field, new_field2, strict=True)
+ editor.alter_field(TagDup, new_field, new_field2, strict=True)
# Ensure the field is unique again
- Tag.objects.create(title="foo", slug="foo")
+ TagDup.objects.create(title="foo", slug="foo")
with self.assertRaises(IntegrityError):
- Tag.objects.create(title="bar", slug="foo")
- Tag.objects.all().delete()
+ TagDup.objects.create(title="bar", slug="foo")
+ TagDup.objects.all().delete()
# Rename the field
new_field3 = SlugField(unique=True)
new_field3.set_attributes_from_name("slug2")
with connection.schema_editor() as editor:
- editor.alter_field(Tag, new_field2, new_field3, strict=True)
+ editor.alter_field(TagDup, new_field2, new_field3, strict=True)
# Ensure the field is still unique
- TagUniqueRename.objects.create(title="foo", slug2="foo")
+ TagDupUniqueRename.objects.create(title="foo", slug2="foo")
with self.assertRaises(IntegrityError):
- TagUniqueRename.objects.create(title="bar", slug2="foo")
- Tag.objects.all().delete()
+ TagDupUniqueRename.objects.create(title="bar", slug2="foo")
+ TagDup.objects.all().delete()
def test_unique_name_quoting(self):
old_table_name = TagUniqueRename._meta.db_table
@@ -3435,7 +3440,7 @@ def test_create_index_together(self):
class TagIndexed(Model):
title = CharField(max_length=255)
- slug = SlugField(unique=True)
+ slug = SlugField(primary_key=True)
class Meta:
app_label = "schema"
@@ -4151,7 +4156,8 @@ def test_unsupported_transactional_ddl_disallowed(self):
with atomic(), connection.schema_editor() as editor:
with self.assertRaisesMessage(TransactionManagementError, message):
editor.execute(
- editor.sql_create_table % {"table": "foo", "definition": ""}
+ editor.sql_create_table % {"table": "foo", "definition": "",
+ "table_storage_type": "", "comment": ""}
)
@skipUnlessDBFeature("supports_foreign_keys", "indexes_foreign_keys")
@@ -5331,7 +5337,8 @@ def test_alter_field_db_collation(self):
)
with connection.schema_editor() as editor:
editor.alter_field(Author, new_field, old_field, strict=True)
- self.assertIsNone(self.get_column_collation(Author._meta.db_table, "name"))
+ # collation is always not None in SingleStore
+ # self.assertIsNone(self.get_column_collation(Author._meta.db_table, "name"))
@skipUnlessDBFeature("supports_collation_on_charfield")
def test_alter_field_type_preserve_db_collation(self):
@@ -5388,7 +5395,8 @@ def test_alter_primary_key_db_collation(self):
with connection.schema_editor() as editor:
editor.alter_field(Thing, new_field, old_field, strict=True)
self.assertEqual(self.get_primary_key(Thing._meta.db_table), "when")
- self.assertIsNone(self.get_column_collation(Thing._meta.db_table, "when"))
+ # collation is always not None in SingleStore
+ # self.assertIsNone(self.get_column_collation(Thing._meta.db_table, "when"))
@skipUnlessDBFeature(
"supports_collation_on_charfield", "supports_collation_on_textfield"
diff --git a/tests/select_for_update/models.py b/tests/select_for_update/models.py
index c1b42f026ddc..9fa4536f9081 100644
--- a/tests/select_for_update/models.py
+++ b/tests/select_for_update/models.py
@@ -1,5 +1,5 @@
from django.db import models
-
+from django_singlestore.schema import ModelStorageManager
class Entity(models.Model):
pass
@@ -45,3 +45,4 @@ class Person(models.Model):
class PersonProfile(models.Model):
person = models.OneToOneField(Person, models.CASCADE, related_name="profile")
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
diff --git a/tests/select_related/models.py b/tests/select_related/models.py
index d407dbdb110d..b2629c8d8995 100644
--- a/tests/select_related/models.py
+++ b/tests/select_related/models.py
@@ -68,7 +68,16 @@ class Topping(models.Model):
class Pizza(models.Model):
name = models.CharField(max_length=100)
- toppings = models.ManyToManyField(Topping)
+ toppings = models.ManyToManyField("Topping", through="PizzaTopping")
+
+
+class PizzaTopping(models.Model):
+ pizza = models.ForeignKey(Pizza, on_delete=models.CASCADE)
+ topping = models.ForeignKey(Topping, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('pizza', 'topping'),)
+ db_table = "select_related_pizza_topping"
class TaggedItem(models.Model):
diff --git a/tests/select_related_onetoone/models.py b/tests/select_related_onetoone/models.py
index 5ffb6bfd8c88..d5f6138d4908 100644
--- a/tests/select_related_onetoone/models.py
+++ b/tests/select_related_onetoone/models.py
@@ -1,4 +1,5 @@
from django.db import models
+from django_singlestore.schema import ModelStorageManager
class User(models.Model):
@@ -10,6 +11,7 @@ class UserProfile(models.Model):
user = models.OneToOneField(User, models.CASCADE)
city = models.CharField(max_length=100)
state = models.CharField(max_length=2)
+ objects = ModelStorageManager("REFERENCE")
class UserStatResult(models.Model):
@@ -20,11 +22,15 @@ class UserStat(models.Model):
user = models.OneToOneField(User, models.CASCADE, primary_key=True)
posts = models.IntegerField()
results = models.ForeignKey(UserStatResult, models.CASCADE)
+ objects = ModelStorageManager("REFERENCE")
+
class StatDetails(models.Model):
base_stats = models.OneToOneField(UserStat, models.CASCADE)
comments = models.IntegerField()
+ objects = ModelStorageManager("REFERENCE")
+
class AdvancedUserStat(UserStat):
@@ -38,6 +44,8 @@ class Image(models.Model):
class Product(models.Model):
name = models.CharField(max_length=100)
image = models.OneToOneField(Image, models.SET_NULL, null=True)
+ objects = ModelStorageManager("REFERENCE")
+
class Parent1(models.Model):
@@ -52,11 +60,14 @@ class Parent2(models.Model):
class Child1(Parent1, Parent2):
value = models.IntegerField()
+ objects = ModelStorageManager("REFERENCE")
class Child2(Parent1):
parent2 = models.OneToOneField(Parent2, models.CASCADE)
value = models.IntegerField()
+ objects = ModelStorageManager("REFERENCE")
+
class Child3(Child2):
@@ -76,3 +87,4 @@ class LinkedList(models.Model):
blank=True,
null=True,
)
+ objects = ModelStorageManager("REFERENCE")
diff --git a/tests/select_related_regress/models.py b/tests/select_related_regress/models.py
index 9bae75419671..e5af997abf3f 100644
--- a/tests/select_related_regress/models.py
+++ b/tests/select_related_regress/models.py
@@ -1,5 +1,5 @@
from django.db import models
-
+from django_singlestore.schema import ModelStorageManager
class Building(models.Model):
name = models.CharField(max_length=10)
@@ -31,6 +31,7 @@ class Connection(models.Model):
related_name="connection_end",
unique=True,
)
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
# Another non-tree hierarchy that exercises code paths similar to the above
@@ -43,6 +44,7 @@ class TUser(models.Model):
class Person(models.Model):
user = models.ForeignKey(TUser, models.CASCADE, unique=True)
+ objects = ModelStorageManager("ROWSTORE REFERENCE")
class Organizer(models.Model):
diff --git a/tests/serializers/models/base.py b/tests/serializers/models/base.py
index c5a4a0f5802d..ff5ee063b6f2 100644
--- a/tests/serializers/models/base.py
+++ b/tests/serializers/models/base.py
@@ -8,6 +8,8 @@
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
class CategoryMetaDataManager(models.Manager):
def get_by_natural_key(self, kind, name):
@@ -19,6 +21,7 @@ class CategoryMetaData(models.Model):
name = models.CharField(max_length=10)
value = models.CharField(max_length=10)
objects = CategoryMetaDataManager()
+ storage = ModelStorageManager(table_storage_type="ROWSTORE REFERENCE")
class Meta:
unique_together = (("kind", "name"),)
@@ -68,9 +71,9 @@ class Article(models.Model):
author = models.ForeignKey(Author, models.CASCADE)
headline = models.CharField(max_length=50)
pub_date = models.DateTimeField()
- categories = models.ManyToManyField(Category)
- meta_data = models.ManyToManyField(CategoryMetaData)
- topics = models.ManyToManyField(Topic)
+ categories = models.ManyToManyField("Category", through="ArticleCategory")
+ meta_data = models.ManyToManyField("CategoryMetaData", through="ArticleCategoryMetaData")
+ topics = models.ManyToManyField("Topic", through="ArticleTopic")
class Meta:
ordering = ("pub_date",)
@@ -79,6 +82,33 @@ def __str__(self):
return self.headline
+class ArticleCategory(models.Model):
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+ category = models.ForeignKey(Category, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('article', 'category'),)
+ db_table = "serializers_article_category"
+
+
+class ArticleCategoryMetaData(models.Model):
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+ categorymetadata = models.ForeignKey(CategoryMetaData, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('article', 'categorymetadata'),)
+ db_table = "serializers_article_categorymetadata"
+
+
+class ArticleTopic(models.Model):
+ article = models.ForeignKey(Article, on_delete=models.CASCADE)
+ topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('article', 'topic'),)
+ db_table = "serializers_article_topic"
+
+
class AuthorProfile(models.Model):
author = models.OneToOneField(Author, models.CASCADE, primary_key=True)
date_of_birth = models.DateField()
diff --git a/tests/serializers/models/data.py b/tests/serializers/models/data.py
index 3d863a3fb2b2..bf9ffade1621 100644
--- a/tests/serializers/models/data.py
+++ b/tests/serializers/models/data.py
@@ -10,6 +10,8 @@
from django.contrib.contenttypes.models import ContentType
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
from .base import BaseModel
@@ -136,6 +138,8 @@ class UniqueAnchor(models.Model):
something for other models to point at"""
data = models.CharField(unique=True, max_length=30)
+
+ storage = ModelStorageManager(table_storage_type="REFERENCE")
class FKData(models.Model):
@@ -143,7 +147,16 @@ class FKData(models.Model):
class M2MData(models.Model):
- data = models.ManyToManyField(Anchor)
+ data = models.ManyToManyField("Anchor", through="M2MDataAnchor")
+
+
+class M2MDataAnchor(models.Model):
+ m2mdata = models.ForeignKey(M2MData, on_delete=models.CASCADE)
+ anchor = models.ForeignKey(Anchor, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('m2mdata', 'anchor'),)
+ db_table = "serializers_m2mdata_anchor"
class O2OData(models.Model):
@@ -156,7 +169,16 @@ class FKSelfData(models.Model):
class M2MSelfData(models.Model):
- data = models.ManyToManyField("self", symmetrical=False)
+ data = models.ManyToManyField("self", symmetrical=False, through="M2MSelfDataFriend")
+
+
+class M2MSelfDataFriend(models.Model):
+ from_m2mselfdata = models.ForeignKey(M2MSelfData, on_delete=models.CASCADE, related_name="from_m2mselfdata")
+ to_m2mselfdata = models.ForeignKey(M2MSelfData, on_delete=models.CASCADE, related_name="to_m2mselfdata")
+
+ class Meta:
+ unique_together = (('from_m2mselfdata', 'to_m2mselfdata'),)
+ db_table = "serializers_m2mselfdata_m2mselfdata"
class FKDataToField(models.Model):
@@ -172,10 +194,13 @@ class M2MIntermediateData(models.Model):
class Intermediate(models.Model):
- left = models.ForeignKey(M2MIntermediateData, models.CASCADE)
- right = models.ForeignKey(Anchor, models.CASCADE)
+ left = models.ForeignKey(M2MIntermediateData, models.CASCADE, related_name="m2mintermediatedata")
+ right = models.ForeignKey(Anchor, models.CASCADE, related_name="anchor")
extra = models.CharField(max_length=30, blank=True, default="doesn't matter")
+ class Meta:
+ db_table = "serializers_m2mintermediatedata_anchor"
+
# The following test classes are for validating the
# deserialization of objects that use a user-defined
@@ -219,6 +244,8 @@ class FilePathPKData(models.Model):
class FloatPKData(models.Model):
data = models.FloatField(primary_key=True)
+
+ objects = ModelStorageManager("ROWSTORE")
class IntegerPKData(models.Model):
diff --git a/tests/serializers/models/multi_table.py b/tests/serializers/models/multi_table.py
index 2f42b5713753..56db51e930fd 100644
--- a/tests/serializers/models/multi_table.py
+++ b/tests/serializers/models/multi_table.py
@@ -1,5 +1,7 @@
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
class ParentManager(models.Manager):
def get_by_natural_key(self, parent_data):
@@ -8,13 +10,24 @@ def get_by_natural_key(self, parent_data):
class Parent(models.Model):
parent_data = models.CharField(max_length=30, unique=True)
- parent_m2m = models.ManyToManyField("self")
+ parent_m2m = models.ManyToManyField("Parent", through="ParentParent")
objects = ParentManager()
+ storage = ModelStorageManager(table_storage_type="ROWSTORE REFERENCE")
def natural_key(self):
return (self.parent_data,)
+class ParentParent(models.Model):
+ from_parent = models.ForeignKey(Parent, on_delete=models.CASCADE, related_name="from_parent")
+ to_parent = models.ForeignKey(Parent, on_delete=models.CASCADE, related_name="to_parent")
+
+ class Meta:
+ unique_together = (('from_parent', 'to_parent'),)
+ db_table = "serializers_parent_parent"
+
+
class Child(Parent):
child_data = models.CharField(max_length=30, unique=True)
+ storage = ModelStorageManager(table_storage_type="ROWSTORE REFERENCE")
diff --git a/tests/serializers/models/natural.py b/tests/serializers/models/natural.py
index 1e439b34ebd2..1e222570c746 100644
--- a/tests/serializers/models/natural.py
+++ b/tests/serializers/models/natural.py
@@ -3,6 +3,8 @@
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
class NaturalKeyAnchorManager(models.Manager):
def get_by_natural_key(self, data):
@@ -14,6 +16,7 @@ class NaturalKeyAnchor(models.Model):
title = models.CharField(max_length=100, null=True)
objects = NaturalKeyAnchorManager()
+ storage = ModelStorageManager(table_storage_type="REFERENCE")
def natural_key(self):
return (self.data,)
@@ -29,7 +32,7 @@ class NaturalKeyThing(models.Model):
"NaturalKeyThing", on_delete=models.CASCADE, null=True
)
other_things = models.ManyToManyField(
- "NaturalKeyThing", related_name="thing_m2m_set"
+ "NaturalKeyThing", related_name="thing_m2m_set", through="NaturalKeyThingOtherThings"
)
class Manager(models.Manager):
@@ -37,6 +40,7 @@ def get_by_natural_key(self, key):
return self.get(key=key)
objects = Manager()
+ storage = ModelStorageManager(table_storage_type="REFERENCE")
def natural_key(self):
return (self.key,)
@@ -45,6 +49,17 @@ def __str__(self):
return self.key
+class NaturalKeyThingOtherThings(models.Model):
+ from_naturalkeything = models.ForeignKey(NaturalKeyThing, on_delete=models.CASCADE, related_name="from_naturalkeything")
+ to_naturalkeything = models.ForeignKey(NaturalKeyThing, on_delete=models.CASCADE, related_name="to_naturalkeything")
+
+ storage = ModelStorageManager(table_storage_type="ROWSTORE REFERENCE")
+
+ class Meta:
+ unique_together = (('from_naturalkeything', 'to_naturalkeything'),)
+ db_table = "serializers_naturalkeything_other_things"
+
+
class NaturalPKWithDefault(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=100, unique=True)
@@ -54,6 +69,7 @@ def get_by_natural_key(self, name):
return self.get(name=name)
objects = Manager()
+ storage = ModelStorageManager(table_storage_type="REFERENCE")
def natural_key(self):
return (self.name,)
diff --git a/tests/signals/models.py b/tests/signals/models.py
index b758244749ae..faf9658e99ae 100644
--- a/tests/signals/models.py
+++ b/tests/signals/models.py
@@ -26,12 +26,21 @@ def __str__(self):
class Book(models.Model):
name = models.CharField(max_length=20)
- authors = models.ManyToManyField(Author)
+ authors = models.ManyToManyField("Author", through="BookAuthor")
def __str__(self):
return self.name
+class BookAuthor(models.Model):
+ book = models.ForeignKey(Book, on_delete=models.CASCADE)
+ author = models.ForeignKey(Author, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('book', 'author'),)
+ db_table = "signals_book_author"
+
+
class Page(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE)
text = models.TextField()
diff --git a/tests/string_lookup/models.py b/tests/string_lookup/models.py
index 71510f5b2fb1..7933e6028c50 100644
--- a/tests/string_lookup/models.py
+++ b/tests/string_lookup/models.py
@@ -1,5 +1,5 @@
from django.db import models
-
+from django_singlestore.schema import ModelStorageManager
class Foo(models.Model):
name = models.CharField(max_length=50)
@@ -20,6 +20,7 @@ class Whiz(models.Model):
class Child(models.Model):
parent = models.OneToOneField("Base", models.CASCADE)
name = models.CharField(max_length=50)
+ objects = ModelStorageManager("REFERENCE")
class Base(models.Model):
diff --git a/tests/test_client_regress/models.py b/tests/test_client_regress/models.py
index 4a18828075d5..5529055dff76 100644
--- a/tests/test_client_regress/models.py
+++ b/tests/test_client_regress/models.py
@@ -1,5 +1,6 @@
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models
+from django_singlestore.schema import ModelStorageManager
class CustomUser(AbstractBaseUser):
@@ -8,5 +9,7 @@ class CustomUser(AbstractBaseUser):
USERNAME_FIELD = "email"
+ objects = ModelStorageManager("REFERENCE")
+
class Meta:
app_label = "test_client_regress"
diff --git a/tests/test_runner/models.py b/tests/test_runner/models.py
index 80bf8dd8c769..313c07d3a23d 100644
--- a/tests/test_runner/models.py
+++ b/tests/test_runner/models.py
@@ -4,7 +4,19 @@
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
- friends = models.ManyToManyField("self")
+ friends = models.ManyToManyField("self", through="PersonFriend")
+
+class PersonFriend(models.Model):
+ from_person = models.ForeignKey(
+ Person, on_delete=models.CASCADE, related_name="from_person"
+ )
+ to_person = models.ForeignKey(
+ Person, on_delete=models.CASCADE, related_name="to_person"
+ )
+
+ class Meta:
+ unique_together = (('from_person', 'to_person'),)
+ db_table = "test_runner_person_friend"
# A set of models that use a non-abstract inherited 'through' model.
diff --git a/tests/update/models.py b/tests/update/models.py
index d71fc887c7d3..b5e3d853a511 100644
--- a/tests/update/models.py
+++ b/tests/update/models.py
@@ -36,17 +36,25 @@ class D(C):
class Foo(models.Model):
- target = models.CharField(max_length=10, unique=True)
+ target = models.CharField(max_length=10, primary_key=True)
class Bar(models.Model):
foo = models.ForeignKey(Foo, models.CASCADE, to_field="target")
- m2m_foo = models.ManyToManyField(Foo, related_name="m2m_foo")
+ m2m_foo = models.ManyToManyField("Foo", related_name="m2m_foo", through="Bar_m2m_foo")
x = models.IntegerField(default=0)
+class Bar_m2m_foo(models.Model):
+ bar = models.ForeignKey(Bar, on_delete=models.CASCADE)
+ foo = models.ForeignKey(Foo, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('bar', 'foo'),)
+ db_table = "update_bar_m2m_foo"
+
class UniqueNumber(models.Model):
- number = models.IntegerField(unique=True)
+ number = models.IntegerField(primary_key=True)
class UniqueNumberChild(UniqueNumber):
diff --git a/tests/update_only_fields/models.py b/tests/update_only_fields/models.py
index 4810d5b19169..36ffc89912ea 100644
--- a/tests/update_only_fields/models.py
+++ b/tests/update_only_fields/models.py
@@ -20,9 +20,17 @@ class Employee(Person):
profile = models.ForeignKey(
"Profile", models.SET_NULL, related_name="profiles", null=True
)
- accounts = models.ManyToManyField("Account", related_name="employees", blank=True)
+ accounts = models.ManyToManyField("Account", related_name="employees", blank=True, through="EmployeeAccount")
+class EmployeeAccount(models.Model):
+ employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
+ account = models.ForeignKey(Account, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = (('employee', 'account'),)
+ db_table = "update_only_fields_employee_account"
+
class NonConcreteField(models.IntegerField):
def db_type(self, connection):
return None
diff --git a/tests/utils_tests/models.py b/tests/utils_tests/models.py
index 866a37debc44..ff8ad1031c7d 100644
--- a/tests/utils_tests/models.py
+++ b/tests/utils_tests/models.py
@@ -1,4 +1,6 @@
from django.db import models
+from django_singlestore.schema import ModelStorageManager
+
class Category(models.Model):
@@ -7,3 +9,4 @@ class Category(models.Model):
class CategoryInfo(models.Model):
category = models.OneToOneField(Category, models.CASCADE)
+ objects = ModelStorageManager("REFERENCE")