diff --git a/django/contrib/gis/db/backends/oracle/operations.py b/django/contrib/gis/db/backends/oracle/operations.py index 0c9bb5da0f..da6d7768f2 100644 --- a/django/contrib/gis/db/backends/oracle/operations.py +++ b/django/contrib/gis/db/backends/oracle/operations.py @@ -45,8 +45,8 @@ class SDORelate(SpatialOperator): raise ValueError('Invalid SDO_RELATE mask: "%s"' % arg) def as_sql(self, connection, lookup, template_params, sql_params): - template_params['mask'] = sql_params.pop() - return super().as_sql(connection, lookup, template_params, sql_params) + template_params['mask'] = sql_params[-1] + return super().as_sql(connection, lookup, template_params, sql_params[:-1]) class OracleOperations(BaseSpatialOperations, DatabaseOperations): diff --git a/django/contrib/gis/db/models/lookups.py b/django/contrib/gis/db/models/lookups.py index f2af05d9c1..8ac266b830 100644 --- a/django/contrib/gis/db/models/lookups.py +++ b/django/contrib/gis/db/models/lookups.py @@ -75,9 +75,9 @@ class GISLookup(Lookup): return connection.ops.gis_operators[self.lookup_name] def as_sql(self, compiler, connection): - lhs_sql, sql_params = self.process_lhs(compiler, connection) + lhs_sql, lhs_params = self.process_lhs(compiler, connection) rhs_sql, rhs_params = self.process_rhs(compiler, connection) - sql_params.extend(rhs_params) + sql_params = (*lhs_params, *rhs_params) template_params = {'lhs': lhs_sql, 'rhs': rhs_sql, 'value': '%s', **self.template_params} rhs_op = self.get_rhs_op(connection, rhs_sql) diff --git a/tests/gis_tests/geoapp/tests.py b/tests/gis_tests/geoapp/tests.py index 771bfb0903..aab83a161a 100644 --- a/tests/gis_tests/geoapp/tests.py +++ b/tests/gis_tests/geoapp/tests.py @@ -10,6 +10,7 @@ from django.contrib.gis.geos import ( ) from django.core.management import call_command from django.db import NotSupportedError, connection +from django.db.models import F, OuterRef, Subquery from django.test import TestCase, skipUnlessDBFeature from ..utils import ( @@ -17,8 +18,8 @@ from ..utils import ( spatialite, ) from .models import ( - City, Country, Feature, MinusOneSRID, NonConcreteModel, PennsylvaniaCity, - State, Track, + City, Country, Feature, MinusOneSRID, MultiFields, NonConcreteModel, + PennsylvaniaCity, State, Track, ) @@ -494,6 +495,21 @@ class GeoLookupTest(TestCase): with self.subTest(lookup): City.objects.filter(**{'point__' + lookup: functions.Union('point', 'point')}).exists() + def test_subquery_annotation(self): + multifields = MultiFields.objects.create( + city=City.objects.create(point=Point(1, 1)), + point=Point(2, 2), + poly=Polygon.from_bbox((0, 0, 2, 2)), + ) + qs = MultiFields.objects.annotate( + city_point=Subquery(City.objects.filter( + id=OuterRef('city'), + ).values('point')), + ).filter( + city_point__within=F('poly'), + ) + self.assertEqual(qs.get(), multifields) + class GeoQuerySetTest(TestCase): # TODO: GeoQuerySet is removed, organize these test better.