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_difference = True
|
||||
supports_slicing_ordering_in_compound = False
|
||||
supports_parentheses_in_compound = True
|
||||
|
||||
# Does the database support SQL 2003 FILTER (WHERE ...) in aggregate
|
||||
# expressions?
|
||||
|
|
|
@ -37,6 +37,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||
supports_partial_indexes = Database.version_info >= (3, 8, 0)
|
||||
# Is "ALTER TABLE ... RENAME COLUMN" supported?
|
||||
can_alter_table_rename_column = Database.sqlite_version_info >= (3, 25, 0)
|
||||
supports_parentheses_in_compound = False
|
||||
|
||||
@cached_property
|
||||
def supports_stddev(self):
|
||||
|
|
|
@ -429,7 +429,17 @@ class SQLCompiler:
|
|||
*self.query.values_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:
|
||||
# Omit the empty queryset with UNION and with DIFFERENCE if the
|
||||
# first queryset is nonempty.
|
||||
|
|
|
@ -214,3 +214,9 @@ class QuerySetSetOperationTests(TestCase):
|
|||
list(qs1.union(qs2).order_by('num'))
|
||||
# switched order, now 'exists' again:
|
||||
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