Commit 0c763317 authored by Anssi Kääriäinen's avatar Anssi Kääriäinen Committed by Tim Graham
Browse files

Fixed #24020 -- Refactored SQL compiler to use expressions

Refactored compiler SELECT, GROUP BY and ORDER BY generation.
While there, also refactored select_related() implementation
(get_cached_row() and get_klass_info() are now gone!).

Made get_db_converters() method work on expressions instead of
internal_type. This allows the backend converters to target
specific expressions if need be.

Added query.context, this can be used to set per-query state.

Also changed the signature of database converters. They now accept
context as an argument.
parent b8abfe14
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@ from django.db.models import signals, DO_NOTHING
from django.db.models.base import ModelBase
from django.db.models.fields.related import ForeignObject, ForeignObjectRel
from django.db.models.query_utils import PathInfo
from django.db.models.expressions import Col
from django.contrib.contenttypes.models import ContentType
from django.utils.encoding import smart_text, python_2_unicode_compatible

@@ -367,7 +366,7 @@ class GenericRelation(ForeignObject):
        field = self.rel.to._meta.get_field(self.content_type_field_name)
        contenttype_pk = self.get_content_type().pk
        cond = where_class()
        lookup = field.get_lookup('exact')(Col(remote_alias, field, field), contenttype_pk)
        lookup = field.get_lookup('exact')(field.get_col(remote_alias), contenttype_pk)
        cond.add(lookup, 'AND')
        return cond

+2 −2
Original line number Diff line number Diff line
@@ -158,10 +158,10 @@ class BaseSpatialOperations(object):

    # Default conversion functions for aggregates; will be overridden if implemented
    # for the spatial backend.
    def convert_extent(self, box):
    def convert_extent(self, box, srid):
        raise NotImplementedError('Aggregate extent not implemented for this spatial backend.')

    def convert_extent3d(self, box):
    def convert_extent3d(self, box, srid):
        raise NotImplementedError('Aggregate 3D extent not implemented for this spatial backend.')

    def convert_geom(self, geom_val, geom_field):
+0 −1
Original line number Diff line number Diff line
@@ -7,7 +7,6 @@ from django.contrib.gis.db.backends.utils import SpatialOperator

class MySQLOperations(DatabaseOperations, BaseSpatialOperations):

    compiler_module = 'django.contrib.gis.db.models.sql.compiler'
    mysql = True
    name = 'mysql'
    select = 'AsText(%s)'
+0 −24
Original line number Diff line number Diff line
from django.contrib.gis.db.models.sql.compiler import GeoSQLCompiler as BaseGeoSQLCompiler
from django.db.backends.oracle import compiler

SQLCompiler = compiler.SQLCompiler


class GeoSQLCompiler(BaseGeoSQLCompiler, SQLCompiler):
    pass


class SQLInsertCompiler(compiler.SQLInsertCompiler, GeoSQLCompiler):
    pass


class SQLDeleteCompiler(compiler.SQLDeleteCompiler, GeoSQLCompiler):
    pass


class SQLUpdateCompiler(compiler.SQLUpdateCompiler, GeoSQLCompiler):
    pass


class SQLAggregateCompiler(compiler.SQLAggregateCompiler, GeoSQLCompiler):
    pass
+15 −6
Original line number Diff line number Diff line
@@ -52,7 +52,6 @@ class SDORelate(SpatialOperator):


class OracleOperations(DatabaseOperations, BaseSpatialOperations):
    compiler_module = "django.contrib.gis.db.backends.oracle.compiler"

    name = 'oracle'
    oracle = True
@@ -111,8 +110,9 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
    def geo_quote_name(self, name):
        return super(OracleOperations, self).geo_quote_name(name).upper()

    def get_db_converters(self, internal_type):
        converters = super(OracleOperations, self).get_db_converters(internal_type)
    def get_db_converters(self, expression):
        converters = super(OracleOperations, self).get_db_converters(expression)
        internal_type = expression.output_field.get_internal_type()
        geometry_fields = (
            'PointField', 'GeometryField', 'LineStringField',
            'PolygonField', 'MultiPointField', 'MultiLineStringField',
@@ -121,14 +121,23 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
        )
        if internal_type in geometry_fields:
            converters.append(self.convert_textfield_value)
        if hasattr(expression.output_field, 'geom_type'):
            converters.append(self.convert_geometry)
        return converters

    def convert_extent(self, clob):
    def convert_geometry(self, value, expression, context):
        if value:
            value = Geometry(value)
            if 'transformed_srid' in context:
                value.srid = context['transformed_srid']
        return value

    def convert_extent(self, clob, srid):
        if clob:
            # Generally, Oracle returns a polygon for the extent -- however,
            # it can return a single point if there's only one Point in the
            # table.
            ext_geom = Geometry(clob.read())
            ext_geom = Geometry(clob.read(), srid)
            gtype = str(ext_geom.geom_type)
            if gtype == 'Polygon':
                # Construct the 4-tuple from the coordinates in the polygon.
@@ -226,7 +235,7 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
        else:
            sql_template = '%(function)s(SDOAGGRTYPE(%(expressions)s,%(tolerance)s))'
        sql_function = getattr(self, agg_name)
        return self.select % sql_template, sql_function
        return sql_template, sql_function

    # Routines for getting the OGC-compliant models.
    def geometry_columns(self):
Loading