2727
2828import java .io .IOException ;
2929import java .util .Objects ;
30- import java .util .function .Predicate ;
3130
3231import static org .elasticsearch .xpack .esql .core .expression .TypeResolutions .ParamOrdinal .FIRST ;
3332import static org .elasticsearch .xpack .esql .core .expression .TypeResolutions .ParamOrdinal .SECOND ;
@@ -56,17 +55,15 @@ protected BinarySpatialFunction(
5655 Expression right ,
5756 boolean leftDocValues ,
5857 boolean rightDocValues ,
59- boolean pointsOnly ,
60- boolean supportsGrid
58+ boolean pointsOnly
6159 ) {
6260 super (source , left , right );
6361 this .leftDocValues = leftDocValues ;
6462 this .rightDocValues = rightDocValues ;
65- this .spatialTypeResolver = new SpatialTypeResolver (this , pointsOnly , supportsGrid );
63+ this .spatialTypeResolver = new SpatialTypeResolver (this , pointsOnly );
6664 }
6765
68- protected BinarySpatialFunction (StreamInput in , boolean leftDocValues , boolean rightDocValues , boolean pointsOnly , boolean supportsGrid )
69- throws IOException {
66+ protected BinarySpatialFunction (StreamInput in , boolean leftDocValues , boolean rightDocValues , boolean pointsOnly ) throws IOException {
7067 // The doc-values fields are only used on data nodes local planning, and therefor never serialized
7168 this (
7269 in .getTransportVersion ().onOrAfter (TransportVersions .ESQL_SERIALIZE_SOURCE_FUNCTIONS_WARNINGS )
@@ -76,8 +73,7 @@ protected BinarySpatialFunction(StreamInput in, boolean leftDocValues, boolean r
7673 in .readNamedWriteable (Expression .class ),
7774 leftDocValues ,
7875 rightDocValues ,
79- pointsOnly ,
80- supportsGrid
76+ pointsOnly
8177 );
8278 }
8379
@@ -123,12 +119,10 @@ protected TypeResolution resolveType() {
123119 static class SpatialTypeResolver {
124120 private final SpatialEvaluatorFactory .SpatialSourceResolution supplier ;
125121 private final boolean pointsOnly ;
126- private final boolean supportsGrid ;
127122
128- SpatialTypeResolver (SpatialEvaluatorFactory .SpatialSourceResolution supplier , boolean pointsOnly , boolean supportsGrid ) {
123+ SpatialTypeResolver (SpatialEvaluatorFactory .SpatialSourceResolution supplier , boolean pointsOnly ) {
129124 this .supplier = supplier ;
130125 this .pointsOnly = pointsOnly ;
131- this .supportsGrid = supportsGrid ;
132126 }
133127
134128 public Expression left () {
@@ -153,16 +147,10 @@ protected TypeResolution resolveType() {
153147 }
154148 }
155149
156- protected Expression .TypeResolution isCompatibleSpatial (Expression e , TypeResolutions .ParamOrdinal paramOrd ) {
150+ protected Expression .TypeResolution isSpatial (Expression e , TypeResolutions .ParamOrdinal paramOrd ) {
157151 return pointsOnly
158152 ? EsqlTypeResolutions .isSpatialPoint (e , sourceText (), paramOrd )
159- : (supportsGrid
160- ? EsqlTypeResolutions .isSpatialOrGrid (e , sourceText (), paramOrd )
161- : EsqlTypeResolutions .isSpatial (e , sourceText (), paramOrd ));
162- }
163-
164- protected Expression .TypeResolution isGeoPoint (Expression e , TypeResolutions .ParamOrdinal paramOrd ) {
165- return isType (e , GEO_POINT ::equals , sourceText (), paramOrd , GEO_POINT .typeName ());
153+ : EsqlTypeResolutions .isSpatial (e , sourceText (), paramOrd );
166154 }
167155
168156 private TypeResolution resolveType (
@@ -171,8 +159,8 @@ private TypeResolution resolveType(
171159 TypeResolutions .ParamOrdinal leftOrdinal ,
172160 TypeResolutions .ParamOrdinal rightOrdinal
173161 ) {
174- TypeResolution leftResolution = isCompatibleSpatial (leftExpression , leftOrdinal );
175- TypeResolution rightResolution = isCompatibleSpatial (rightExpression , rightOrdinal );
162+ TypeResolution leftResolution = isSpatial (leftExpression , leftOrdinal );
163+ TypeResolution rightResolution = isSpatial (rightExpression , rightOrdinal );
176164 if (leftResolution .resolved ()) {
177165 return resolveType (leftExpression , rightExpression , rightOrdinal );
178166 } else if (rightResolution .resolved ()) {
@@ -188,16 +176,9 @@ protected TypeResolution resolveType(
188176 TypeResolutions .ParamOrdinal otherParamOrdinal
189177 ) {
190178 if (isNull (spatialExpression .dataType ())) {
191- return isCompatibleSpatial (otherExpression , otherParamOrdinal );
179+ return isSpatial (otherExpression , otherParamOrdinal );
192180 }
193181 TypeResolution resolution = isSameSpatialType (spatialExpression .dataType (), otherExpression , sourceText (), otherParamOrdinal );
194- // TODO Remove these grid checks once we support geo_shape relation to geoGrid
195- if (resolution .resolved () && DataType .isGeoGrid (spatialExpression .dataType ())) {
196- resolution = isGeoPoint (otherExpression , otherParamOrdinal );
197- }
198- if (resolution .resolved () && DataType .isGeoGrid (otherExpression .dataType ())) {
199- resolution = isGeoPoint (spatialExpression , otherParamOrdinal == FIRST ? SECOND : FIRST );
200- }
201182 if (resolution .unresolved ()) {
202183 return resolution ;
203184 }
@@ -211,12 +192,15 @@ protected TypeResolution isSameSpatialType(
211192 String operationName ,
212193 TypeResolutions .ParamOrdinal paramOrd
213194 ) {
214- Predicate <DataType > isSpatialType = pointsOnly
215- ? dt -> dt == spatialDataType
216- : (supportsGrid
217- ? dt -> DataType .isSpatialOrGrid (dt ) && spatialCRSCompatible (spatialDataType , dt )
218- : dt -> DataType .isSpatial (dt ) && spatialCRSCompatible (spatialDataType , dt ));
219- return isType (expression , isSpatialType , operationName , paramOrd , compatibleTypeNames (spatialDataType ));
195+ return pointsOnly
196+ ? isType (expression , dt -> dt == spatialDataType , operationName , paramOrd , compatibleTypeNames (spatialDataType ))
197+ : isType (
198+ expression ,
199+ dt -> DataType .isSpatial (dt ) && spatialCRSCompatible (spatialDataType , dt ),
200+ operationName ,
201+ paramOrd ,
202+ compatibleTypeNames (spatialDataType )
203+ );
220204 }
221205 }
222206
@@ -264,7 +248,7 @@ public enum SpatialCrsType {
264248
265249 public static SpatialCrsType fromDataType (DataType dataType ) {
266250 return DataType .isSpatialGeo (dataType ) ? SpatialCrsType .GEO
267- : DataType .isSpatialOrGrid (dataType ) ? SpatialCrsType .CARTESIAN
251+ : DataType .isSpatial (dataType ) ? SpatialCrsType .CARTESIAN
268252 : SpatialCrsType .UNSPECIFIED ;
269253 }
270254 }
@@ -294,8 +278,8 @@ public TranslationAware.Translatable translatable(LucenePushdownPredicates pushd
294278 // The use of foldable here instead of SpatialEvaluatorFieldKey.isConstant is intentional to match the behavior of the
295279 // Lucene pushdown code in EsqlTranslationHandler::SpatialRelatesTranslator
296280 // We could enhance both places to support ReferenceAttributes that refer to constants, but that is a larger change
297- return isPushableSpatialAttribute (left (), pushdownPredicates ) && isPushableLiteralAttribute ( right ())
298- || isPushableSpatialAttribute (right (), pushdownPredicates ) && isPushableLiteralAttribute ( left ())
281+ return isPushableSpatialAttribute (left (), pushdownPredicates ) && right (). foldable ( )
282+ || isPushableSpatialAttribute (right (), pushdownPredicates ) && left (). foldable ( )
299283 ? TranslationAware .Translatable .YES
300284 : TranslationAware .Translatable .NO ;
301285
@@ -304,9 +288,4 @@ public TranslationAware.Translatable translatable(LucenePushdownPredicates pushd
304288 private static boolean isPushableSpatialAttribute (Expression exp , LucenePushdownPredicates p ) {
305289 return exp instanceof FieldAttribute fa && DataType .isSpatial (fa .dataType ()) && fa .getExactInfo ().hasExact () && p .isIndexed (fa );
306290 }
307-
308- private static boolean isPushableLiteralAttribute (Expression exp ) {
309- // TODO: Support pushdown of geo-grid queries where the constant is a geo-grid-id literal
310- return DataType .isSpatial (exp .dataType ()) && exp .foldable ();
311- }
312291}
0 commit comments