Fixed #29932 -- Fixed combining compound queries with sub-compound queries on SQLite and Oracle.
This commit is contained in:
parent
ae180fa4b7
commit
f9a33e3c3f
|
@ -226,6 +226,7 @@ class BaseDatabaseFeatures:
|
||||||
supports_select_intersection = True
|
supports_select_intersection = True
|
||||||
supports_select_difference = True
|
supports_select_difference = True
|
||||||
supports_slicing_ordering_in_compound = False
|
supports_slicing_ordering_in_compound = False
|
||||||
|
supports_parentheses_in_compound = True
|
||||||
|
|
||||||
# Does the database support SQL 2003 FILTER (WHERE ...) in aggregate
|
# Does the database support SQL 2003 FILTER (WHERE ...) in aggregate
|
||||||
# expressions?
|
# expressions?
|
||||||
|
|
|
@ -37,6 +37,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||||
supports_partial_indexes = Database.version_info >= (3, 8, 0)
|
supports_partial_indexes = Database.version_info >= (3, 8, 0)
|
||||||
# Is "ALTER TABLE ... RENAME COLUMN" supported?
|
# Is "ALTER TABLE ... RENAME COLUMN" supported?
|
||||||
can_alter_table_rename_column = Database.sqlite_version_info >= (3, 25, 0)
|
can_alter_table_rename_column = Database.sqlite_version_info >= (3, 25, 0)
|
||||||
|
supports_parentheses_in_compound = False
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def supports_stddev(self):
|
def supports_stddev(self):
|
||||||
|
|
|
@ -429,7 +429,17 @@ class SQLCompiler:
|
||||||
*self.query.values_select,
|
*self.query.values_select,
|
||||||
*self.query.annotation_select,
|
*self.query.annotation_select,
|
||||||
))
|
))
|
||||||
parts += (compiler.as_sql(),)
|
part_sql, part_args = compiler.as_sql()
|
||||||
|
if compiler.query.combinator:
|
||||||
|
# Wrap in a subquery if wrapping in parentheses isn't
|
||||||
|
# supported.
|
||||||
|
if not features.supports_parentheses_in_compound:
|
||||||
|
part_sql = 'SELECT * FROM ({})'.format(part_sql)
|
||||||
|
# Add parentheses when combining with compound query if not
|
||||||
|
# already added for all compound queries.
|
||||||
|
elif not features.supports_slicing_ordering_in_compound:
|
||||||
|
part_sql = '({})'.format(part_sql)
|
||||||
|
parts += ((part_sql, part_args),)
|
||||||
except EmptyResultSet:
|
except EmptyResultSet:
|
||||||
# Omit the empty queryset with UNION and with DIFFERENCE if the
|
# Omit the empty queryset with UNION and with DIFFERENCE if the
|
||||||
# first queryset is nonempty.
|
# first queryset is nonempty.
|
||||||
|
|
|
@ -214,3 +214,9 @@ class QuerySetSetOperationTests(TestCase):
|
||||||
list(qs1.union(qs2).order_by('num'))
|
list(qs1.union(qs2).order_by('num'))
|
||||||
# switched order, now 'exists' again:
|
# switched order, now 'exists' again:
|
||||||
list(qs2.union(qs1).order_by('num'))
|
list(qs2.union(qs1).order_by('num'))
|
||||||
|
|
||||||
|
@skipUnlessDBFeature('supports_select_difference', 'supports_select_intersection')
|
||||||
|
def test_qs_with_subcompound_qs(self):
|
||||||
|
qs1 = Number.objects.all()
|
||||||
|
qs2 = Number.objects.intersection(Number.objects.filter(num__gt=1))
|
||||||
|
self.assertEqual(qs1.difference(qs2).count(), 2)
|
||||||
|
|
Loading…
Reference in New Issue