summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorMatthew Wilkes <git@matthewwilkes.name>2017-06-18 16:53:40 +0100
committerTim Graham <timograham@gmail.com>2018-02-10 19:08:55 -0500
commit2162f0983de0dfe2178531638ce7ea56f54dd4e7 (patch)
treebb1e859159200fa7ebeeaa02ec3908e1cf5d2655 /tests
parentbf26f66029bca94b007a2452679ac004598364a6 (diff)
Fixed #24747 -- Allowed transforms in QuerySet.order_by() and distinct(*fields).
Diffstat (limited to 'tests')
-rw-r--r--tests/backends/base/test_operations.py2
-rw-r--r--tests/custom_lookups/tests.py17
-rw-r--r--tests/distinct_on_fields/tests.py30
-rw-r--r--tests/expressions/tests.py34
-rw-r--r--tests/postgres_tests/test_array.py16
-rw-r--r--tests/postgres_tests/test_hstore.py12
-rw-r--r--tests/postgres_tests/test_json.py25
7 files changed, 127 insertions, 9 deletions
diff --git a/tests/backends/base/test_operations.py b/tests/backends/base/test_operations.py
index e83857500d..510436f0d4 100644
--- a/tests/backends/base/test_operations.py
+++ b/tests/backends/base/test_operations.py
@@ -17,7 +17,7 @@ class DatabaseOperationTests(SimpleTestCase):
def test_distinct_on_fields(self):
msg = 'DISTINCT ON fields is not supported by this database backend'
with self.assertRaisesMessage(NotSupportedError, msg):
- self.ops.distinct_sql(['a', 'b'])
+ self.ops.distinct_sql(['a', 'b'], None)
def test_deferrable_sql(self):
self.assertEqual(self.ops.deferrable_sql(), '')
diff --git a/tests/custom_lookups/tests.py b/tests/custom_lookups/tests.py
index 9661aebc49..418525c3ed 100644
--- a/tests/custom_lookups/tests.py
+++ b/tests/custom_lookups/tests.py
@@ -63,6 +63,14 @@ class Mult3BilateralTransform(models.Transform):
return '3 * (%s)' % lhs, lhs_params
+class LastDigitTransform(models.Transform):
+ lookup_name = 'lastdigit'
+
+ def as_sql(self, compiler, connection):
+ lhs, lhs_params = compiler.compile(self.lhs)
+ return 'SUBSTR(CAST(%s AS CHAR(2)), 2, 1)' % lhs, lhs_params
+
+
class UpperBilateralTransform(models.Transform):
bilateral = True
lookup_name = 'upper'
@@ -379,6 +387,15 @@ class BilateralTransformTests(TestCase):
self.assertSequenceEqual(baseqs.filter(age__mult3__div3=42), [a1, a2, a3, a4])
self.assertSequenceEqual(baseqs.filter(age__div3__mult3=42), [a3])
+ def test_transform_order_by(self):
+ with register_lookup(models.IntegerField, LastDigitTransform):
+ a1 = Author.objects.create(name='a1', age=11)
+ a2 = Author.objects.create(name='a2', age=23)
+ a3 = Author.objects.create(name='a3', age=32)
+ a4 = Author.objects.create(name='a4', age=40)
+ qs = Author.objects.order_by('age__lastdigit')
+ self.assertSequenceEqual(qs, [a4, a1, a3, a2])
+
def test_bilateral_fexpr(self):
with register_lookup(models.IntegerField, Mult3BilateralTransform):
a1 = Author.objects.create(name='a1', age=1, average_rating=3.2)
diff --git a/tests/distinct_on_fields/tests.py b/tests/distinct_on_fields/tests.py
index 93a332cf83..ae4eb3bd19 100644
--- a/tests/distinct_on_fields/tests.py
+++ b/tests/distinct_on_fields/tests.py
@@ -1,4 +1,5 @@
-from django.db.models import Max
+from django.db.models import CharField, Max
+from django.db.models.functions import Lower
from django.test import TestCase, skipUnlessDBFeature
from .models import Celebrity, Fan, Staff, StaffTag, Tag
@@ -8,19 +9,19 @@ from .models import Celebrity, Fan, Staff, StaffTag, Tag
@skipUnlessDBFeature('supports_nullable_unique_constraints')
class DistinctOnTests(TestCase):
def setUp(self):
- t1 = Tag.objects.create(name='t1')
- Tag.objects.create(name='t2', parent=t1)
- t3 = Tag.objects.create(name='t3', parent=t1)
- Tag.objects.create(name='t4', parent=t3)
- Tag.objects.create(name='t5', parent=t3)
+ self.t1 = Tag.objects.create(name='t1')
+ self.t2 = Tag.objects.create(name='t2', parent=self.t1)
+ self.t3 = Tag.objects.create(name='t3', parent=self.t1)
+ self.t4 = Tag.objects.create(name='t4', parent=self.t3)
+ self.t5 = Tag.objects.create(name='t5', parent=self.t3)
self.p1_o1 = Staff.objects.create(id=1, name="p1", organisation="o1")
self.p2_o1 = Staff.objects.create(id=2, name="p2", organisation="o1")
self.p3_o1 = Staff.objects.create(id=3, name="p3", organisation="o1")
self.p1_o2 = Staff.objects.create(id=4, name="p1", organisation="o2")
self.p1_o1.coworkers.add(self.p2_o1, self.p3_o1)
- StaffTag.objects.create(staff=self.p1_o1, tag=t1)
- StaffTag.objects.create(staff=self.p1_o1, tag=t1)
+ StaffTag.objects.create(staff=self.p1_o1, tag=self.t1)
+ StaffTag.objects.create(staff=self.p1_o1, tag=self.t1)
celeb1 = Celebrity.objects.create(name="c1")
celeb2 = Celebrity.objects.create(name="c2")
@@ -95,6 +96,19 @@ class DistinctOnTests(TestCase):
c2 = c1.distinct('pk')
self.assertNotIn('OUTER JOIN', str(c2.query))
+ def test_transform(self):
+ new_name = self.t1.name.upper()
+ self.assertNotEqual(self.t1.name, new_name)
+ Tag.objects.create(name=new_name)
+ CharField.register_lookup(Lower)
+ try:
+ self.assertCountEqual(
+ Tag.objects.order_by().distinct('name__lower'),
+ [self.t1, self.t2, self.t3, self.t4, self.t5],
+ )
+ finally:
+ CharField._unregister_lookup(Lower)
+
def test_distinct_not_implemented_checks(self):
# distinct + annotate not allowed
msg = 'annotate() + distinct(fields) is not implemented.'
diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py
index c2e3fb391a..2980d750c8 100644
--- a/tests/expressions/tests.py
+++ b/tests/expressions/tests.py
@@ -1363,6 +1363,40 @@ class ValueTests(TestCase):
ExpressionList()
+class FieldTransformTests(TestCase):
+
+ @classmethod
+ def setUpTestData(cls):
+ cls.sday = sday = datetime.date(2010, 6, 25)
+ cls.stime = stime = datetime.datetime(2010, 6, 25, 12, 15, 30, 747000)
+ cls.ex1 = Experiment.objects.create(
+ name='Experiment 1',
+ assigned=sday,
+ completed=sday + datetime.timedelta(2),
+ estimated_time=datetime.timedelta(2),
+ start=stime,
+ end=stime + datetime.timedelta(2),
+ )
+
+ def test_month_aggregation(self):
+ self.assertEqual(
+ Experiment.objects.aggregate(month_count=Count('assigned__month')),
+ {'month_count': 1}
+ )
+
+ def test_transform_in_values(self):
+ self.assertQuerysetEqual(
+ Experiment.objects.values('assigned__month'),
+ ["{'assigned__month': 6}"]
+ )
+
+ def test_multiple_transforms_in_values(self):
+ self.assertQuerysetEqual(
+ Experiment.objects.values('end__date__month'),
+ ["{'end__date__month': 6}"]
+ )
+
+
class ReprTests(TestCase):
def test_expressions(self):
diff --git a/tests/postgres_tests/test_array.py b/tests/postgres_tests/test_array.py
index 4776bda934..03ffa4d637 100644
--- a/tests/postgres_tests/test_array.py
+++ b/tests/postgres_tests/test_array.py
@@ -309,6 +309,22 @@ class TestQuerying(PostgreSQLTestCase):
self.objs[2:3]
)
+ def test_order_by_slice(self):
+ more_objs = (
+ NullableIntegerArrayModel.objects.create(field=[1, 637]),
+ NullableIntegerArrayModel.objects.create(field=[2, 1]),
+ NullableIntegerArrayModel.objects.create(field=[3, -98123]),
+ NullableIntegerArrayModel.objects.create(field=[4, 2]),
+ )
+ self.assertSequenceEqual(
+ NullableIntegerArrayModel.objects.order_by('field__1'),
+ [
+ more_objs[2], more_objs[1], more_objs[3], self.objs[2],
+ self.objs[3], more_objs[0], self.objs[4], self.objs[1],
+ self.objs[0],
+ ]
+ )
+
@unittest.expectedFailure
def test_slice_nested(self):
instance = NestedIntegerArrayModel.objects.create(field=[[1, 2], [3, 4]])
diff --git a/tests/postgres_tests/test_hstore.py b/tests/postgres_tests/test_hstore.py
index 069e570f51..b58e5e5e20 100644
--- a/tests/postgres_tests/test_hstore.py
+++ b/tests/postgres_tests/test_hstore.py
@@ -148,6 +148,18 @@ class TestQuerying(HStoreTestCase):
self.objs[:2]
)
+ def test_order_by_field(self):
+ more_objs = (
+ HStoreModel.objects.create(field={'g': '637'}),
+ HStoreModel.objects.create(field={'g': '002'}),
+ HStoreModel.objects.create(field={'g': '042'}),
+ HStoreModel.objects.create(field={'g': '981'}),
+ )
+ self.assertSequenceEqual(
+ HStoreModel.objects.filter(field__has_key='g').order_by('field__g'),
+ [more_objs[1], more_objs[2], more_objs[0], more_objs[3]]
+ )
+
def test_keys_contains(self):
self.assertSequenceEqual(
HStoreModel.objects.filter(field__keys__contains=['a']),
diff --git a/tests/postgres_tests/test_json.py b/tests/postgres_tests/test_json.py
index a572e670ac..b22cbfc571 100644
--- a/tests/postgres_tests/test_json.py
+++ b/tests/postgres_tests/test_json.py
@@ -141,6 +141,31 @@ class TestQuerying(PostgreSQLTestCase):
[self.objs[0]]
)
+ def test_ordering_by_transform(self):
+ objs = [
+ JSONModel.objects.create(field={'ord': 93, 'name': 'bar'}),
+ JSONModel.objects.create(field={'ord': 22.1, 'name': 'foo'}),
+ JSONModel.objects.create(field={'ord': -1, 'name': 'baz'}),
+ JSONModel.objects.create(field={'ord': 21.931902, 'name': 'spam'}),
+ JSONModel.objects.create(field={'ord': -100291029, 'name': 'eggs'}),
+ ]
+ query = JSONModel.objects.filter(field__name__isnull=False).order_by('field__ord')
+ self.assertSequenceEqual(query, [objs[4], objs[2], objs[3], objs[1], objs[0]])
+
+ def test_deep_values(self):
+ query = JSONModel.objects.values_list('field__k__l')
+ self.assertSequenceEqual(
+ query,
+ [
+ (None,), (None,), (None,), (None,), (None,), (None,),
+ (None,), (None,), ('m',), (None,), (None,), (None,),
+ ]
+ )
+
+ def test_deep_distinct(self):
+ query = JSONModel.objects.distinct('field__k__l').values_list('field__k__l')
+ self.assertSequenceEqual(query, [('m',), (None,)])
+
def test_isnull_key(self):
# key__isnull works the same as has_key='key'.
self.assertSequenceEqual(