2020-08-08 19:37:06 +08:00
|
|
|
from django.db import connection
|
|
|
|
from django.db.models import F, Value
|
|
|
|
from django.db.models.functions import Collate
|
|
|
|
from django.test import TestCase
|
|
|
|
|
|
|
|
from ..models import Author
|
|
|
|
|
|
|
|
|
|
|
|
class CollateTests(TestCase):
|
|
|
|
@classmethod
|
|
|
|
def setUpTestData(cls):
|
|
|
|
cls.author1 = Author.objects.create(alias="a", name="Jones 1")
|
|
|
|
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:
|
|
|
|
self.skipTest("This backend does not support case-insensitive collations.")
|
|
|
|
qs = Author.objects.filter(alias=Collate(Value("a"), collation))
|
|
|
|
self.assertEqual(qs.count(), 2)
|
|
|
|
|
|
|
|
def test_collate_order_by_cs(self):
|
|
|
|
collation = connection.features.test_collations.get("cs")
|
|
|
|
if not collation:
|
|
|
|
self.skipTest("This backend does not support case-sensitive collations.")
|
|
|
|
qs = Author.objects.order_by(Collate("alias", collation))
|
|
|
|
self.assertSequenceEqual(qs, [self.author2, self.author1])
|
|
|
|
|
|
|
|
def test_language_collation_order_by(self):
|
2020-09-18 18:12:27 +08:00
|
|
|
collation = connection.features.test_collations.get("swedish_ci")
|
2020-08-08 19:37:06 +08:00
|
|
|
if not collation:
|
|
|
|
self.skipTest("This backend does not support language collations.")
|
|
|
|
author3 = Author.objects.create(alias="O", name="Jones")
|
|
|
|
author4 = Author.objects.create(alias="Ö", name="Jones")
|
|
|
|
author5 = Author.objects.create(alias="P", name="Jones")
|
|
|
|
qs = Author.objects.order_by(Collate(F("alias"), collation), "name")
|
|
|
|
self.assertSequenceEqual(
|
|
|
|
qs,
|
|
|
|
[self.author1, self.author2, author3, author5, author4],
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_invalid_collation(self):
|
|
|
|
tests = [
|
|
|
|
None,
|
|
|
|
"",
|
|
|
|
'et-x-icu" OR ',
|
|
|
|
'"schema"."collation"',
|
|
|
|
]
|
|
|
|
msg = "Invalid collation name: %r."
|
|
|
|
for value in tests:
|
|
|
|
with self.subTest(value), self.assertRaisesMessage(ValueError, msg % value):
|
|
|
|
Collate(F("alias"), value)
|