Replaced @no_oracle skips with DatabaseFeatures.allows_group_by_lob.
This commit is contained in:
parent
ad11f5b8c9
commit
755dbf39fc
|
@ -4,6 +4,8 @@ from django.utils.functional import cached_property
|
||||||
|
|
||||||
class BaseDatabaseFeatures:
|
class BaseDatabaseFeatures:
|
||||||
gis_enabled = False
|
gis_enabled = False
|
||||||
|
# Oracle can't group by LOB (large object) data types.
|
||||||
|
allows_group_by_lob = True
|
||||||
allows_group_by_pk = False
|
allows_group_by_pk = False
|
||||||
allows_group_by_selected_pks = False
|
allows_group_by_selected_pks = False
|
||||||
empty_fetchmany_value = []
|
empty_fetchmany_value = []
|
||||||
|
|
|
@ -4,6 +4,9 @@ from django.utils.functional import cached_property
|
||||||
|
|
||||||
|
|
||||||
class DatabaseFeatures(BaseDatabaseFeatures):
|
class DatabaseFeatures(BaseDatabaseFeatures):
|
||||||
|
# Oracle crashes with "ORA-00932: inconsistent datatypes: expected - got
|
||||||
|
# BLOB" when grouping by LOBs (#24096).
|
||||||
|
allows_group_by_lob = False
|
||||||
interprets_empty_strings_as_nulls = True
|
interprets_empty_strings_as_nulls = True
|
||||||
has_select_for_update = True
|
has_select_for_update = True
|
||||||
has_select_for_update_nowait = True
|
has_select_for_update_nowait = True
|
||||||
|
|
|
@ -5,6 +5,7 @@ from operator import attrgetter, itemgetter
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from django.core.exceptions import FieldError
|
from django.core.exceptions import FieldError
|
||||||
|
from django.db import connection
|
||||||
from django.db.models import (
|
from django.db.models import (
|
||||||
BinaryField, BooleanField, Case, Count, DecimalField, F,
|
BinaryField, BooleanField, Case, Count, DecimalField, F,
|
||||||
GenericIPAddressField, IntegerField, Max, Min, Q, Sum, TextField, Value,
|
GenericIPAddressField, IntegerField, Max, Min, Q, Sum, TextField, Value,
|
||||||
|
@ -56,10 +57,13 @@ class CaseExpressionTests(TestCase):
|
||||||
O2OCaseTestModel.objects.create(o2o=o, integer=1)
|
O2OCaseTestModel.objects.create(o2o=o, integer=1)
|
||||||
FKCaseTestModel.objects.create(fk=o, integer=5)
|
FKCaseTestModel.objects.create(fk=o, integer=5)
|
||||||
|
|
||||||
# GROUP BY on Oracle fails with TextField/BinaryField; see #24096.
|
cls.group_by_fields = [
|
||||||
cls.non_lob_fields = [
|
|
||||||
f.name for f in CaseTestModel._meta.get_fields()
|
f.name for f in CaseTestModel._meta.get_fields()
|
||||||
if not (f.is_relation and f.auto_created) and not isinstance(f, (BinaryField, TextField))
|
if not (f.is_relation and f.auto_created) and
|
||||||
|
(
|
||||||
|
connection.features.allows_group_by_lob or
|
||||||
|
not isinstance(f, (BinaryField, TextField))
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
def test_annotate(self):
|
def test_annotate(self):
|
||||||
|
@ -197,7 +201,7 @@ class CaseExpressionTests(TestCase):
|
||||||
|
|
||||||
def test_annotate_with_aggregation_in_value(self):
|
def test_annotate_with_aggregation_in_value(self):
|
||||||
self.assertQuerysetEqual(
|
self.assertQuerysetEqual(
|
||||||
CaseTestModel.objects.values(*self.non_lob_fields).annotate(
|
CaseTestModel.objects.values(*self.group_by_fields).annotate(
|
||||||
min=Min('fk_rel__integer'),
|
min=Min('fk_rel__integer'),
|
||||||
max=Max('fk_rel__integer'),
|
max=Max('fk_rel__integer'),
|
||||||
).annotate(
|
).annotate(
|
||||||
|
@ -212,7 +216,7 @@ class CaseExpressionTests(TestCase):
|
||||||
|
|
||||||
def test_annotate_with_aggregation_in_condition(self):
|
def test_annotate_with_aggregation_in_condition(self):
|
||||||
self.assertQuerysetEqual(
|
self.assertQuerysetEqual(
|
||||||
CaseTestModel.objects.values(*self.non_lob_fields).annotate(
|
CaseTestModel.objects.values(*self.group_by_fields).annotate(
|
||||||
min=Min('fk_rel__integer'),
|
min=Min('fk_rel__integer'),
|
||||||
max=Max('fk_rel__integer'),
|
max=Max('fk_rel__integer'),
|
||||||
).annotate(
|
).annotate(
|
||||||
|
@ -227,7 +231,7 @@ class CaseExpressionTests(TestCase):
|
||||||
|
|
||||||
def test_annotate_with_aggregation_in_predicate(self):
|
def test_annotate_with_aggregation_in_predicate(self):
|
||||||
self.assertQuerysetEqual(
|
self.assertQuerysetEqual(
|
||||||
CaseTestModel.objects.values(*self.non_lob_fields).annotate(
|
CaseTestModel.objects.values(*self.group_by_fields).annotate(
|
||||||
max=Max('fk_rel__integer'),
|
max=Max('fk_rel__integer'),
|
||||||
).annotate(
|
).annotate(
|
||||||
test=Case(
|
test=Case(
|
||||||
|
@ -483,7 +487,7 @@ class CaseExpressionTests(TestCase):
|
||||||
|
|
||||||
def test_filter_with_aggregation_in_value(self):
|
def test_filter_with_aggregation_in_value(self):
|
||||||
self.assertQuerysetEqual(
|
self.assertQuerysetEqual(
|
||||||
CaseTestModel.objects.values(*self.non_lob_fields).annotate(
|
CaseTestModel.objects.values(*self.group_by_fields).annotate(
|
||||||
min=Min('fk_rel__integer'),
|
min=Min('fk_rel__integer'),
|
||||||
max=Max('fk_rel__integer'),
|
max=Max('fk_rel__integer'),
|
||||||
).filter(
|
).filter(
|
||||||
|
@ -498,7 +502,7 @@ class CaseExpressionTests(TestCase):
|
||||||
|
|
||||||
def test_filter_with_aggregation_in_condition(self):
|
def test_filter_with_aggregation_in_condition(self):
|
||||||
self.assertQuerysetEqual(
|
self.assertQuerysetEqual(
|
||||||
CaseTestModel.objects.values(*self.non_lob_fields).annotate(
|
CaseTestModel.objects.values(*self.group_by_fields).annotate(
|
||||||
min=Min('fk_rel__integer'),
|
min=Min('fk_rel__integer'),
|
||||||
max=Max('fk_rel__integer'),
|
max=Max('fk_rel__integer'),
|
||||||
).filter(
|
).filter(
|
||||||
|
@ -513,7 +517,7 @@ class CaseExpressionTests(TestCase):
|
||||||
|
|
||||||
def test_filter_with_aggregation_in_predicate(self):
|
def test_filter_with_aggregation_in_predicate(self):
|
||||||
self.assertQuerysetEqual(
|
self.assertQuerysetEqual(
|
||||||
CaseTestModel.objects.values(*self.non_lob_fields).annotate(
|
CaseTestModel.objects.values(*self.group_by_fields).annotate(
|
||||||
max=Max('fk_rel__integer'),
|
max=Max('fk_rel__integer'),
|
||||||
).filter(
|
).filter(
|
||||||
integer=Case(
|
integer=Case(
|
||||||
|
|
|
@ -5,7 +5,6 @@ from django.contrib.gis.shortcuts import render_to_kmz
|
||||||
from django.db.models import Count, Min
|
from django.db.models import Count, Min
|
||||||
from django.test import TestCase, skipUnlessDBFeature
|
from django.test import TestCase, skipUnlessDBFeature
|
||||||
|
|
||||||
from ..utils import no_oracle
|
|
||||||
from .models import City, PennsylvaniaCity, State, Truth
|
from .models import City, PennsylvaniaCity, State, Truth
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,10 +64,7 @@ class GeoRegressionTests(TestCase):
|
||||||
# .count() should not throw TypeError in __eq__
|
# .count() should not throw TypeError in __eq__
|
||||||
self.assertEqual(cities_within_state.count(), 1)
|
self.assertEqual(cities_within_state.count(), 1)
|
||||||
|
|
||||||
# TODO: fix on Oracle -- get the following error because the SQL is ordered
|
@skipUnlessDBFeature('allows_group_by_lob')
|
||||||
# by a geometry object, which Oracle apparently doesn't like:
|
|
||||||
# ORA-22901: cannot compare nested table or VARRAY or LOB attributes of an object type
|
|
||||||
@no_oracle
|
|
||||||
def test_defer_or_only_with_annotate(self):
|
def test_defer_or_only_with_annotate(self):
|
||||||
"Regression for #16409. Make sure defer() and only() work with annotate()"
|
"Regression for #16409. Make sure defer() and only() work with annotate()"
|
||||||
self.assertIsInstance(list(City.objects.annotate(Count('point')).defer('name')), list)
|
self.assertIsInstance(list(City.objects.annotate(Count('point')).defer('name')), list)
|
||||||
|
|
|
@ -222,10 +222,7 @@ class RelatedGeoModelTest(TestCase):
|
||||||
self.assertIn('Aurora', names)
|
self.assertIn('Aurora', names)
|
||||||
self.assertIn('Kecksburg', names)
|
self.assertIn('Kecksburg', names)
|
||||||
|
|
||||||
# TODO: fix on Oracle -- get the following error because the SQL is ordered
|
@skipUnlessDBFeature('allows_group_by_lob')
|
||||||
# by a geometry object, which Oracle apparently doesn't like:
|
|
||||||
# ORA-22901: cannot compare nested table or VARRAY or LOB attributes of an object type
|
|
||||||
@no_oracle
|
|
||||||
def test12a_count(self):
|
def test12a_count(self):
|
||||||
"Testing `Count` aggregate on geo-fields."
|
"Testing `Count` aggregate on geo-fields."
|
||||||
# The City, 'Fort Worth' uses the same location as Dallas.
|
# The City, 'Fort Worth' uses the same location as Dallas.
|
||||||
|
@ -247,10 +244,7 @@ class RelatedGeoModelTest(TestCase):
|
||||||
self.assertEqual(1, len(vqs))
|
self.assertEqual(1, len(vqs))
|
||||||
self.assertEqual(3, vqs[0]['num_books'])
|
self.assertEqual(3, vqs[0]['num_books'])
|
||||||
|
|
||||||
# TODO: fix on Oracle -- get the following error because the SQL is ordered
|
@skipUnlessDBFeature('allows_group_by_lob')
|
||||||
# by a geometry object, which Oracle apparently doesn't like:
|
|
||||||
# ORA-22901: cannot compare nested table or VARRAY or LOB attributes of an object type
|
|
||||||
@no_oracle
|
|
||||||
def test13c_count(self):
|
def test13c_count(self):
|
||||||
"Testing `Count` aggregate with `.values()`. See #15305."
|
"Testing `Count` aggregate with `.values()`. See #15305."
|
||||||
qs = Location.objects.filter(id=5).annotate(num_cities=Count('city')).values('id', 'point', 'num_cities')
|
qs = Location.objects.filter(id=5).annotate(num_cities=Count('city')).values('id', 'point', 'num_cities')
|
||||||
|
|
|
@ -355,7 +355,7 @@ class TestQuerying(TestCase):
|
||||||
operator.itemgetter('key', 'count'),
|
operator.itemgetter('key', 'count'),
|
||||||
)
|
)
|
||||||
|
|
||||||
@skipIf(connection.vendor == 'oracle', "Oracle doesn't support grouping by LOBs, see #24096.")
|
@skipUnlessDBFeature('allows_group_by_lob')
|
||||||
def test_ordering_grouping_by_count(self):
|
def test_ordering_grouping_by_count(self):
|
||||||
qs = NullableJSONModel.objects.filter(
|
qs = NullableJSONModel.objects.filter(
|
||||||
value__isnull=False,
|
value__isnull=False,
|
||||||
|
|
Loading…
Reference in New Issue