From ab3d9d61c2d9b6a7327dd5810d7e927fc5f09865 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Fri, 14 Mar 2025 18:36:51 +0100 Subject: [PATCH 01/34] Add initial geohash function to ESQL --- .../src/main/resources/spatial-grid.csv-spec | 135 +++++++++++++ .../esql/expression/ExpressionWritables.java | 10 +- .../function/EsqlFunctionRegistry.java | 4 +- .../function/scalar/spatial/StGeohash.java | 185 ++++++++++++++++++ .../spatial/UnarySpatialBinaryFunction.java | 58 ++++++ .../local/SpatialDocValuesExtraction.java | 16 +- 6 files changed, 404 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/UnarySpatialBinaryFunction.java diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec new file mode 100644 index 0000000000000..49a968b985e19 --- /dev/null +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -0,0 +1,135 @@ +############################################### +# Tests for geo_grid functions: geohash, geotile, geohex +############################################### + +geohashLiteral +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") +| EVAL geohash = ST_GEOHASH(location, 4) +; + +location:geo_point | geohash:keyword +POINT(12.6493508684508 55.6285017221528) | u3bu +; + +geohashLiteralMv +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] +| MV_EXPAND precision +| EVAL geohash = ST_GEOHASH(location, precision) +; + +location:geo_point | precision:integer | geohash:keyword +POINT (12.6493508684508 55.6285017221528) | 1 | u +POINT (12.6493508684508 55.6285017221528) | 2 | u3 +POINT (12.6493508684508 55.6285017221528) | 3 | u3b +POINT (12.6493508684508 55.6285017221528) | 4 | u3bu +POINT (12.6493508684508 55.6285017221528) | 5 | u3bur +; + +geohashField +FROM airports +| WHERE abbrev == "CPH" +| EVAL geohash = ST_GEOHASH(location, 7) +| KEEP geohash, abbrev, name, location +; + +geohash:keyword | abbrev:keyword | name:text | location:geo_point +u3buryf | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) +; + +gridGeohashStatsBy +// tag::st_geohash-grid[] +FROM airports +| EVAL geohash = ST_GEOHASH(location, 1) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geohash +| SORT count DESC, geohash ASC +// end::st_geohash-grid[] +; + +// tag::st_geohash-grid-result[] +count:long | centroid:geo_point | geohash:keyword +118 | POINT (-77.41857436454018 26.96522968734409) | d +96 | POINT (23.181679135886952 27.295384635654045) | s +94 | POINT (70.94076107503807 25.691916451026547) | t +90 | POINT (-104.3941700803116 30.811849871650338) | 9 +89 | POINT (18.71573683606942 53.165169130707305) | u +85 | POINT (114.3722876966657 24.908398092505248) | w +51 | POINT (-61.44522591713159 -22.87209844956284) | 6 +38 | POINT (-9.429514887252529 25.497624435045413) | e +34 | POINT (-111.8071846965262 52.464381378993174) | c +30 | POINT (28.7045472683385 -14.706001980230212) | k +28 | POINT (159.52750137208827 -25.555616633001982) | r +22 | POINT (-4.410395708612421 54.90304926367985) | g +21 | POINT (-69.40534970590046 50.93379438189523) | f +17 | POINT (114.05526293222519 -10.898114638950895) | q +16 | POINT (147.40052131412085 21.054660080408212) | x +13 | POINT (63.64716878519035 54.37333276101317) | v +12 | POINT (-39.53510569408536 -11.72166372067295) | 7 +9 | POINT (-150.36503398790956 63.14222150482237) | b +7 | POINT (-167.3069146488394 -17.976190628084755) | 2 +6 | POINT (-157.0227657398209 17.60691551025957) | 8 +5 | POINT (114.40185610949993 48.99013584572822) | y +4 | POINT (-69.98911972157657 -52.170535867335275) | 4 +4 | POINT (51.48641954641789 -14.176777086686343) | m +1 | POINT (-109.43006442859769 -27.15877384878695) | 3 +1 | POINT (170.20002692006528 -45.92343100346625) | p +// end::st_geohash-grid-result[] +; + +gridGeohashStatsByWhereUK +FROM airports +| WHERE ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) +| EVAL geohash = ST_GEOHASH(location, 2) +| STATS + count = COUNT(location), + centroid = ST_CENTROID_AGG(location) + BY geohash +| SORT count DESC +; + +count:long | centroid:geo_point | geohash:keyword +14 | POINT (-2.5644131543646966 53.38093495994274) | gc +3 | POINT (-2.7510103583335876 58.79020635969937) | gf +; + +gridGeohashInStatsBy +FROM airports +| STATS + count = COUNT(location), + centroid = ST_CENTROID_AGG(location) + BY ST_GEOHASH(location, 1) +| SORT count DESC +| KEEP count, centroid +| LIMIT 10 +; + +count:long | centroid:geo_point + 118 | POINT (-77.41857436454018 26.96522968734409) + 96 | POINT (23.181679135886952 27.295384635654045) + 94 | POINT (70.94076107503807 25.691916451026547) + 90 | POINT (-104.3941700803116 30.811849871650338) + 89 | POINT (18.71573683606942 53.165169130707305) + 85 | POINT (114.3722876966657 24.908398092505248) + 51 | POINT (-61.44522591713159 -22.87209844956284) + 38 | POINT (-9.429514887252529 25.497624435045413) + 34 | POINT (-111.8071846965262 52.464381378993174) + 30 | POINT (28.7045472683385 -14.706001980230212) +; + +gridGeohashInStatsByWhereUK +FROM airports +| WHERE ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) +| STATS + count = COUNT(location), + centroid = ST_CENTROID_AGG(location) + BY ST_GEOHASH(location, 2) +| KEEP count, centroid +| SORT count DESC +; + +count:long | centroid:geo_point +14 | POINT (-2.5644131543646966 53.38093495994274) +3 | POINT (-2.7510103583335876 58.79020635969937) +; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java index 4ffa778b8287a..3cb062fb566df 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java @@ -58,6 +58,7 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.SpatialWithin; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StDistance; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StEnvelope; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohash; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StX; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMax; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMin; @@ -212,7 +213,14 @@ public static List unaryScalars() { } private static List spatials() { - return List.of(SpatialContains.ENTRY, SpatialDisjoint.ENTRY, SpatialIntersects.ENTRY, SpatialWithin.ENTRY, StDistance.ENTRY); + return List.of( + SpatialContains.ENTRY, + SpatialDisjoint.ENTRY, + SpatialIntersects.ENTRY, + SpatialWithin.ENTRY, + StDistance.ENTRY, + StGeohash.ENTRY + ); } private static List arithmetics() { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index 0bd4e4bda7c5b..e8beaadf998ec 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -128,6 +128,7 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.SpatialWithin; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StDistance; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StEnvelope; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohash; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StX; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMax; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMin; @@ -376,7 +377,8 @@ private static FunctionDefinition[][] functions() { def(StYMax.class, StYMax::new, "st_ymax"), def(StYMin.class, StYMin::new, "st_ymin"), def(StX.class, StX::new, "st_x"), - def(StY.class, StY::new, "st_y") }, + def(StY.class, StY::new, "st_y"), + def(StGeohash.class, StGeohash::new, "st_geohash") }, // conditional new FunctionDefinition[] { def(Case.class, Case::new, "case") }, // null diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java new file mode 100644 index 0000000000000..1ac96e01cda34 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java @@ -0,0 +1,185 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.Evaluator; +import org.elasticsearch.compute.ann.Fixed; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.expression.FoldContext; +import org.elasticsearch.xpack.esql.core.expression.function.scalar.BinaryScalarFunction; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; + +import java.io.IOException; + +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isType; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isWholeNumber; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT; +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; + +/** + * Calculates the geohash of geo_point geometries. + */ +public class StGeohash extends UnarySpatialBinaryFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeohash", + StGeohash::new + ); + + @FunctionInfo( + returnType = "keyword", + description = "Calculates the `geohash` of the supplied geo_point at the specified precision.", + examples = @Example(file = "spatial-grid", tag = "st_geohash-grid") + ) + public StGeohash( + Source source, + @Param( + name = "point", + type = { "geo_point" }, + description = "Expression of type `geo_point`. If `null`, the function returns `null`." + ) Expression field, + @Param( + name = "precision", + type = { "integer" }, + description = "Expression of type `integer`. If `null`, the function returns `null`." + ) Expression precision + ) { + this(source, field, precision, false); + } + + private StGeohash(Source source, Expression field, Expression precision, boolean spatialDocValues) { + super(source, field, precision, spatialDocValues); + } + + private StGeohash(StreamInput in) throws IOException { + super(in, false); + } + + @Override + public UnarySpatialBinaryFunction withDocValues(boolean useDocValues) { + // Only update the docValues flags if the field is found in the attributes + boolean leftDV = this.spatialDocsValues || useDocValues; + return new StGeohash(source(), left(), right(), leftDV); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + public DataType dataType() { + return KEYWORD; + } + + @Override + protected BinaryScalarFunction replaceChildren(Expression newLeft, Expression newRight) { + return new StGeohash(source(), newLeft, newRight); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeohash::new, left(), right()); + } + + @Override + protected TypeResolution resolveType() { + if (childrenResolved() == false) { + return new TypeResolution("Unresolved children"); + } + + TypeResolution resolution = isGeoPoint(left(), sourceText()); + if (resolution.unresolved()) { + return resolution; + } + + resolution = isWholeNumber(right(), sourceText(), SECOND); + if (resolution.unresolved()) { + return resolution; + } + + return TypeResolution.TYPE_RESOLVED; + } + + protected static Expression.TypeResolution isGeoPoint(Expression e, String operationName) { + + return isType(e, t -> t.equals(GEO_POINT), operationName, FIRST, GEO_POINT.typeName()); + } + + @Override + public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) { + // TODO: Implement + if (left().foldable()) { + // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() + var point = (BytesRef) left().fold(toEvaluator.foldCtx()); + return new StGeohashFromLiteralAndFieldEvaluator.Factory(source(), point, toEvaluator.apply(right())); + } else if (right().foldable()) { + // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() + int precision = (int) right().fold(toEvaluator.foldCtx()); + return spatialDocsValues + ? new StGeohashFromFieldDocValuesAndLiteralEvaluator.Factory(source(), toEvaluator.apply(left()), precision) + : new StGeohashFromFieldAndLiteralEvaluator.Factory(source(), toEvaluator.apply(left()), precision); + } else { + // Both arguments come from index fields + return spatialDocsValues + ? new StGeohashFromFieldDocValuesAndFieldEvaluator.Factory(source(), toEvaluator.apply(left()), toEvaluator.apply(right())) + : new StGeohashFromFieldAndFieldEvaluator.Factory(source(), toEvaluator.apply(left()), toEvaluator.apply(right())); + } + } + + @Override + public Object fold(FoldContext ctx) { + var point = (BytesRef) left().fold(ctx); + int precision = (int) right().fold(ctx); + return calculateGeohash(GEO.wkbAsPoint(point), precision); + } + + @Evaluator(extraName = "FromFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static BytesRef fromFieldAndLiteral(BytesRef in, @Fixed int precision) { + return calculateGeohash(GEO.wkbAsPoint(in), precision); + } + + @Evaluator(extraName = "FromFieldDocValuesAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static BytesRef fromFieldDocValuesAndLiteral(long encoded, @Fixed int precision) { + return calculateGeohash(GEO.longAsPoint(encoded), precision); + } + + @Evaluator(extraName = "FromFieldAndField", warnExceptions = { IllegalArgumentException.class }) + static BytesRef fromFieldAndField(BytesRef in, int precision) { + return calculateGeohash(GEO.wkbAsPoint(in), precision); + } + + @Evaluator(extraName = "FromFieldDocValuesAndField", warnExceptions = { IllegalArgumentException.class }) + static BytesRef fromFieldDocValuesAndField(long encoded, int precision) { + return calculateGeohash(GEO.longAsPoint(encoded), precision); + } + + @Evaluator(extraName = "FromLiteralAndField", warnExceptions = { IllegalArgumentException.class }) + static BytesRef fromLiteralAndField(@Fixed BytesRef in, int precision) { + return calculateGeohash(GEO.wkbAsPoint(in), precision); + } + + protected static BytesRef calculateGeohash(Point point, int precision) { + return new BytesRef(Geohash.stringEncode(point.getX(), point.getY(), precision)); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/UnarySpatialBinaryFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/UnarySpatialBinaryFunction.java new file mode 100644 index 0000000000000..0424c3219de55 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/UnarySpatialBinaryFunction.java @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.expression.function.scalar.BinaryScalarFunction; +import org.elasticsearch.xpack.esql.core.tree.Source; + +import java.io.IOException; +import java.util.Objects; + +/** + * Spatial functions that take one spatial argument can inherit from this class. + */ +public abstract class UnarySpatialBinaryFunction extends BinaryScalarFunction { + protected final boolean spatialDocsValues; + + protected UnarySpatialBinaryFunction(Source source, Expression left, Expression right, boolean spatialDocsValues) { + super(source, left, right); + this.spatialDocsValues = spatialDocsValues; + } + + protected UnarySpatialBinaryFunction(StreamInput in, boolean spatialDocsValues) throws IOException { + super(in); + this.spatialDocsValues = spatialDocsValues; + } + + /** + * Mark the function as expecting the specified fields to arrive as doc-values. + */ + public abstract UnarySpatialBinaryFunction withDocValues(boolean useDocValues); + + @Override + public int hashCode() { + // NB: the hashcode is currently used for key generation so + // to avoid clashes between aggs with the same arguments, add the class name as variation + return Objects.hash(getClass(), children(), spatialDocsValues); + } + + @Override + public boolean equals(Object obj) { + if (super.equals(obj)) { + UnarySpatialBinaryFunction other = (UnarySpatialBinaryFunction) obj; + return Objects.equals(other.children(), children()) && Objects.equals(other.spatialDocsValues, spatialDocsValues); + } + return false; + } + + public boolean spatialDocsValues() { + return spatialDocsValues; + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/SpatialDocValuesExtraction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/SpatialDocValuesExtraction.java index d70153258871e..1018de02e06d3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/SpatialDocValuesExtraction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/SpatialDocValuesExtraction.java @@ -17,6 +17,7 @@ import org.elasticsearch.xpack.esql.expression.function.aggregate.SpatialAggregateFunction; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.BinarySpatialFunction; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.SpatialRelatesFunction; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.UnarySpatialBinaryFunction; import org.elasticsearch.xpack.esql.optimizer.LocalPhysicalOptimizerContext; import org.elasticsearch.xpack.esql.optimizer.PhysicalOptimizerRules; import org.elasticsearch.xpack.esql.plan.physical.AggregateExec; @@ -110,7 +111,10 @@ && allowedForDocValues(fieldAttribute, ctx.searchStats(), agg, foundAttributes)) if (exec instanceof EvalExec evalExec) { List fields = evalExec.fields(); List changed = fields.stream() - .map(f -> (Alias) f.transformDown(BinarySpatialFunction.class, s -> withDocValues(s, foundAttributes))) + .map( + f -> (Alias) f.transformDown(BinarySpatialFunction.class, s -> withDocValues(s, foundAttributes)) + .transformDown(UnarySpatialBinaryFunction.class, s -> withDocValues(s, foundAttributes)) + ) .toList(); if (changed.equals(fields) == false) { exec = new EvalExec(exec.source(), exec.child(), changed); @@ -119,7 +123,9 @@ && allowedForDocValues(fieldAttribute, ctx.searchStats(), agg, foundAttributes)) if (exec instanceof FilterExec filterExec) { // Note that ST_CENTROID does not support shapes, but SpatialRelatesFunction does, so when we extend the centroid // to support shapes, we need to consider loading shape doc-values for both centroid and relates (ST_INTERSECTS) - var condition = filterExec.condition().transformDown(BinarySpatialFunction.class, s -> withDocValues(s, foundAttributes)); + var condition = filterExec.condition() + .transformDown(BinarySpatialFunction.class, s -> withDocValues(s, foundAttributes)) + .transformDown(UnarySpatialBinaryFunction.class, s -> withDocValues(s, foundAttributes)); if (filterExec.condition().equals(condition) == false) { exec = new FilterExec(filterExec.source(), filterExec.child(), condition); } @@ -149,6 +155,12 @@ private BinarySpatialFunction withDocValues(BinarySpatialFunction spatial, Set foundAttributes) { + // Only update the docValues flags if the field is found in the attributes + boolean found = foundField(spatial.left(), foundAttributes); + return found ? spatial.withDocValues(found) : spatial; + } + private boolean hasFieldAttribute(BinarySpatialFunction spatial, Set foundAttributes) { return foundField(spatial.left(), foundAttributes) || foundField(spatial.right(), foundAttributes); } From 89559f640dba1ddbe43ededdce2b836407feef5c Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Fri, 14 Mar 2025 18:37:31 +0100 Subject: [PATCH 02/34] Add generated files --- .../StGeohashFromFieldAndFieldEvaluator.java | 161 ++++++++++++++++++ ...StGeohashFromFieldAndLiteralEvaluator.java | 141 +++++++++++++++ ...shFromFieldDocValuesAndFieldEvaluator.java | 161 ++++++++++++++++++ ...FromFieldDocValuesAndLiteralEvaluator.java | 139 +++++++++++++++ ...StGeohashFromLiteralAndFieldEvaluator.java | 140 +++++++++++++++ 5 files changed, 742 insertions(+) create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldEvaluator.java diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldEvaluator.java new file mode 100644 index 0000000000000..513c42c8d0aad --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldEvaluator.java @@ -0,0 +1,161 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohash}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohashFromFieldAndFieldEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator in; + + private final EvalOperator.ExpressionEvaluator precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohashFromFieldAndFieldEvaluator(Source source, EvalOperator.ExpressionEvaluator in, + EvalOperator.ExpressionEvaluator precision, DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock inBlock = (BytesRefBlock) in.eval(page)) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + BytesRefVector inVector = inBlock.asVector(); + if (inVector == null) { + return eval(page.getPositionCount(), inBlock, precisionBlock); + } + IntVector precisionVector = precisionBlock.asVector(); + if (precisionVector == null) { + return eval(page.getPositionCount(), inBlock, precisionBlock); + } + return eval(page.getPositionCount(), inVector, precisionVector); + } + } + } + + public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + BytesRef inScratch = new BytesRef(); + position: for (int p = 0; p < positionCount; p++) { + if (inBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (inBlock.getValueCount(p) != 1) { + if (inBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + try { + result.appendBytesRef(StGeohash.fromFieldAndField(inBlock.getBytesRef(inBlock.getFirstValueIndex(p), inScratch), precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + public BytesRefBlock eval(int positionCount, BytesRefVector inVector, IntVector precisionVector) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + BytesRef inScratch = new BytesRef(); + position: for (int p = 0; p < positionCount; p++) { + try { + result.appendBytesRef(StGeohash.fromFieldAndField(inVector.getBytesRef(p, inScratch), precisionVector.getInt(p))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohashFromFieldAndFieldEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(in, precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory in; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, + EvalOperator.ExpressionEvaluator.Factory precision) { + this.source = source; + this.in = in; + this.precision = precision; + } + + @Override + public StGeohashFromFieldAndFieldEvaluator get(DriverContext context) { + return new StGeohashFromFieldAndFieldEvaluator(source, in.get(context), precision.get(context), context); + } + + @Override + public String toString() { + return "StGeohashFromFieldAndFieldEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralEvaluator.java new file mode 100644 index 0000000000000..94f6ed4acdfa6 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralEvaluator.java @@ -0,0 +1,141 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohash}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohashFromFieldAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator in; + + private final int precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohashFromFieldAndLiteralEvaluator(Source source, EvalOperator.ExpressionEvaluator in, + int precision, DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock inBlock = (BytesRefBlock) in.eval(page)) { + BytesRefVector inVector = inBlock.asVector(); + if (inVector == null) { + return eval(page.getPositionCount(), inBlock); + } + return eval(page.getPositionCount(), inVector); + } + } + + public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + BytesRef inScratch = new BytesRef(); + position: for (int p = 0; p < positionCount; p++) { + if (inBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (inBlock.getValueCount(p) != 1) { + if (inBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + try { + result.appendBytesRef(StGeohash.fromFieldAndLiteral(inBlock.getBytesRef(inBlock.getFirstValueIndex(p), inScratch), this.precision)); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + public BytesRefBlock eval(int positionCount, BytesRefVector inVector) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + BytesRef inScratch = new BytesRef(); + position: for (int p = 0; p < positionCount; p++) { + try { + result.appendBytesRef(StGeohash.fromFieldAndLiteral(inVector.getBytesRef(p, inScratch), this.precision)); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohashFromFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(in); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory in; + + private final int precision; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, int precision) { + this.source = source; + this.in = in; + this.precision = precision; + } + + @Override + public StGeohashFromFieldAndLiteralEvaluator get(DriverContext context) { + return new StGeohashFromFieldAndLiteralEvaluator(source, in.get(context), precision, context); + } + + @Override + public String toString() { + return "StGeohashFromFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldEvaluator.java new file mode 100644 index 0000000000000..ae43b7364b11d --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldEvaluator.java @@ -0,0 +1,161 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.LongVector; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohash}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohashFromFieldDocValuesAndFieldEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encoded; + + private final EvalOperator.ExpressionEvaluator precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohashFromFieldDocValuesAndFieldEvaluator(Source source, + EvalOperator.ExpressionEvaluator encoded, EvalOperator.ExpressionEvaluator precision, + DriverContext driverContext) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + LongVector encodedVector = encodedBlock.asVector(); + if (encodedVector == null) { + return eval(page.getPositionCount(), encodedBlock, precisionBlock); + } + IntVector precisionVector = precisionBlock.asVector(); + if (precisionVector == null) { + return eval(page.getPositionCount(), encodedBlock, precisionBlock); + } + return eval(page.getPositionCount(), encodedVector, precisionVector); + } + } + } + + public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + if (encodedBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (encodedBlock.getValueCount(p) != 1) { + if (encodedBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + try { + result.appendBytesRef(StGeohash.fromFieldDocValuesAndField(encodedBlock.getLong(encodedBlock.getFirstValueIndex(p)), precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + public BytesRefBlock eval(int positionCount, LongVector encodedVector, + IntVector precisionVector) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + try { + result.appendBytesRef(StGeohash.fromFieldDocValuesAndField(encodedVector.getLong(p), precisionVector.getInt(p))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohashFromFieldDocValuesAndFieldEvaluator[" + "encoded=" + encoded + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encoded, precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory encoded; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, + EvalOperator.ExpressionEvaluator.Factory precision) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + } + + @Override + public StGeohashFromFieldDocValuesAndFieldEvaluator get(DriverContext context) { + return new StGeohashFromFieldDocValuesAndFieldEvaluator(source, encoded.get(context), precision.get(context), context); + } + + @Override + public String toString() { + return "StGeohashFromFieldDocValuesAndFieldEvaluator[" + "encoded=" + encoded + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralEvaluator.java new file mode 100644 index 0000000000000..da6caa422a803 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralEvaluator.java @@ -0,0 +1,139 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.LongVector; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohash}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohashFromFieldDocValuesAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encoded; + + private final int precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohashFromFieldDocValuesAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator encoded, int precision, DriverContext driverContext) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { + LongVector encodedVector = encodedBlock.asVector(); + if (encodedVector == null) { + return eval(page.getPositionCount(), encodedBlock); + } + return eval(page.getPositionCount(), encodedVector); + } + } + + public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + if (encodedBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (encodedBlock.getValueCount(p) != 1) { + if (encodedBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + try { + result.appendBytesRef(StGeohash.fromFieldDocValuesAndLiteral(encodedBlock.getLong(encodedBlock.getFirstValueIndex(p)), this.precision)); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + public BytesRefBlock eval(int positionCount, LongVector encodedVector) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + try { + result.appendBytesRef(StGeohash.fromFieldDocValuesAndLiteral(encodedVector.getLong(p), this.precision)); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohashFromFieldDocValuesAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encoded); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory encoded; + + private final int precision; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, int precision) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + } + + @Override + public StGeohashFromFieldDocValuesAndLiteralEvaluator get(DriverContext context) { + return new StGeohashFromFieldDocValuesAndLiteralEvaluator(source, encoded.get(context), precision, context); + } + + @Override + public String toString() { + return "StGeohashFromFieldDocValuesAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldEvaluator.java new file mode 100644 index 0000000000000..f4698177a88ae --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldEvaluator.java @@ -0,0 +1,140 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohash}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohashFromLiteralAndFieldEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final BytesRef in; + + private final EvalOperator.ExpressionEvaluator precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohashFromLiteralAndFieldEvaluator(Source source, BytesRef in, + EvalOperator.ExpressionEvaluator precision, DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + IntVector precisionVector = precisionBlock.asVector(); + if (precisionVector == null) { + return eval(page.getPositionCount(), precisionBlock); + } + return eval(page.getPositionCount(), precisionVector); + } + } + + public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + try { + result.appendBytesRef(StGeohash.fromLiteralAndField(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + public BytesRefBlock eval(int positionCount, IntVector precisionVector) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + try { + result.appendBytesRef(StGeohash.fromLiteralAndField(this.in, precisionVector.getInt(p))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohashFromLiteralAndFieldEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final BytesRef in; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + public Factory(Source source, BytesRef in, EvalOperator.ExpressionEvaluator.Factory precision) { + this.source = source; + this.in = in; + this.precision = precision; + } + + @Override + public StGeohashFromLiteralAndFieldEvaluator get(DriverContext context) { + return new StGeohashFromLiteralAndFieldEvaluator(source, in, precision.get(context), context); + } + + @Override + public String toString() { + return "StGeohashFromLiteralAndFieldEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + } +} From dd346c2480e943d9d2e4964a700ba7d95b7d97bb Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 18 Mar 2025 17:43:58 +0100 Subject: [PATCH 03/34] Add support for optional bounds parameter --- .../src/main/resources/spatial-grid.csv-spec | 38 ++ ...hFromFieldAndFieldAndLiteralEvaluator.java | 139 ++++++++ .../StGeohashFromFieldAndFieldEvaluator.java | 44 +-- ...romFieldAndLiteralAndLiteralEvaluator.java | 125 +++++++ ...StGeohashFromFieldAndLiteralEvaluator.java | 64 ++-- ...dDocValuesAndFieldAndLiteralEvaluator.java | 140 ++++++++ ...shFromFieldDocValuesAndFieldEvaluator.java | 42 +-- ...ocValuesAndLiteralAndLiteralEvaluator.java | 126 +++++++ ...FromFieldDocValuesAndLiteralEvaluator.java | 34 +- ...romLiteralAndFieldAndLiteralEvaluator.java | 148 ++++++++ .../scalar/spatial/SpatialGridFunction.java | 122 +++++++ .../function/scalar/spatial/StGeohash.java | 334 +++++++++++++++--- .../spatial/UnarySpatialBinaryFunction.java | 58 --- .../local/SpatialDocValuesExtraction.java | 10 +- 14 files changed, 1177 insertions(+), 247 deletions(-) create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java delete mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/UnarySpatialBinaryFunction.java diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index 49a968b985e19..0eaadfd64ff5f 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -78,6 +78,26 @@ count:long | centroid:geo_point | geohash:keyword // end::st_geohash-grid-result[] ; +gridGeohashStatsByBounds +FROM airports +| EVAL geohash = ST_GEOHASH(location, 2, TO_GEOSHAPE("BBOX(0, 12, 60, 30)")) +| WHERE geohash IS NOT NULL +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geohash +| SORT count DESC, geohash ASC +; + +count:long | centroid:geo_point | geohash:keyword +19 | POINT (6.360728044651057 47.94084087577894) | u0 +8 | POINT (6.351574736181647 51.8981519783847) | u1 +7 | POINT (5.268637698941997 42.747250193330856) | sp +4 | POINT (7.7012718468904495 36.39783004182391) | sn +2 | POINT (11.7787727387622 48.351816879585385) | u2 +1 | POINT (5.629810290411115 58.88215648010373) | u4 +; + gridGeohashStatsByWhereUK FROM airports | WHERE ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) @@ -94,6 +114,24 @@ count:long | centroid:geo_point | geohash:keyword 3 | POINT (-2.7510103583335876 58.79020635969937) | gf ; +gridGeohashStatsByBoundsUK +FROM airports +| EVAL bounds = ST_ENVELOPE(TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) +| EVAL geohash = ST_GEOHASH(location, 2, bounds) +| WHERE geohash IS NOT NULL +| STATS + count = COUNT(location), + centroid = ST_CENTROID_AGG(location) + BY geohash +| SORT count DESC +; + +count:long | centroid:geo_point | geohash:keyword +17 | POINT (-3.5034258844440473 53.25306422789307) | gc +3 | POINT (-2.7510103583335876 58.79020635969937) | gf +1 | POINT (0.15865350142121315 49.36166098807007) | u0 +; + gridGeohashInStatsBy FROM airports | STATS diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldAndLiteralEvaluator.java new file mode 100644 index 0000000000000..3351b560df248 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldAndLiteralEvaluator.java @@ -0,0 +1,139 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohash}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohashFromFieldAndFieldAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator in; + + private final EvalOperator.ExpressionEvaluator precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohashFromFieldAndFieldAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator in, EvalOperator.ExpressionEvaluator precision, + Rectangle bounds, DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock inBlock = (BytesRefBlock) in.eval(page)) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + return eval(page.getPositionCount(), inBlock, precisionBlock); + } + } + } + + public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!inBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeohash.fromFieldAndFieldAndLiteral(result, p, inBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohashFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(in, precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory in; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + private final Rectangle bounds; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, + EvalOperator.ExpressionEvaluator.Factory precision, Rectangle bounds) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeohashFromFieldAndFieldAndLiteralEvaluator get(DriverContext context) { + return new StGeohashFromFieldAndFieldAndLiteralEvaluator(source, in.get(context), precision.get(context), bounds, context); + } + + @Override + public String toString() { + return "StGeohashFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldEvaluator.java index 513c42c8d0aad..443bcd333d33e 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldEvaluator.java @@ -7,12 +7,9 @@ import java.lang.IllegalArgumentException; import java.lang.Override; import java.lang.String; -import org.apache.lucene.util.BytesRef; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; -import org.elasticsearch.compute.data.BytesRefVector; import org.elasticsearch.compute.data.IntBlock; -import org.elasticsearch.compute.data.IntVector; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -47,33 +44,17 @@ public StGeohashFromFieldAndFieldEvaluator(Source source, EvalOperator.Expressio public Block eval(Page page) { try (BytesRefBlock inBlock = (BytesRefBlock) in.eval(page)) { try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { - BytesRefVector inVector = inBlock.asVector(); - if (inVector == null) { - return eval(page.getPositionCount(), inBlock, precisionBlock); - } - IntVector precisionVector = precisionBlock.asVector(); - if (precisionVector == null) { - return eval(page.getPositionCount(), inBlock, precisionBlock); - } - return eval(page.getPositionCount(), inVector, precisionVector); + return eval(page.getPositionCount(), inBlock, precisionBlock); } } } public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - BytesRef inScratch = new BytesRef(); position: for (int p = 0; p < positionCount; p++) { - if (inBlock.isNull(p)) { - result.appendNull(); - continue position; - } - if (inBlock.getValueCount(p) != 1) { - if (inBlock.getValueCount(p) > 1) { - warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); - } - result.appendNull(); - continue position; + boolean allBlocksAreNulls = true; + if (!inBlock.isNull(p)) { + allBlocksAreNulls = false; } if (precisionBlock.isNull(p)) { result.appendNull(); @@ -86,23 +67,12 @@ public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock pre result.appendNull(); continue position; } - try { - result.appendBytesRef(StGeohash.fromFieldAndField(inBlock.getBytesRef(inBlock.getFirstValueIndex(p), inScratch), precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)))); - } catch (IllegalArgumentException e) { - warnings().registerException(e); + if (allBlocksAreNulls) { result.appendNull(); + continue position; } - } - return result.build(); - } - } - - public BytesRefBlock eval(int positionCount, BytesRefVector inVector, IntVector precisionVector) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - BytesRef inScratch = new BytesRef(); - position: for (int p = 0; p < positionCount; p++) { try { - result.appendBytesRef(StGeohash.fromFieldAndField(inVector.getBytesRef(p, inScratch), precisionVector.getInt(p))); + StGeohash.fromFieldAndField(result, p, inBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p))); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java new file mode 100644 index 0000000000000..233eeb2ceaf08 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java @@ -0,0 +1,125 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohash}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohashFromFieldAndLiteralAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator in; + + private final int precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohashFromFieldAndLiteralAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator in, int precision, Rectangle bounds, + DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock inBlock = (BytesRefBlock) in.eval(page)) { + return eval(page.getPositionCount(), inBlock); + } + } + + public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!inBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeohash.fromFieldAndLiteralAndLiteral(result, p, inBlock, this.precision, this.bounds); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohashFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(in); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory in; + + private final int precision; + + private final Rectangle bounds; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, int precision, + Rectangle bounds) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeohashFromFieldAndLiteralAndLiteralEvaluator get(DriverContext context) { + return new StGeohashFromFieldAndLiteralAndLiteralEvaluator(source, in.get(context), precision, bounds, context); + } + + @Override + public String toString() { + return "StGeohashFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralEvaluator.java index 94f6ed4acdfa6..9e2a159106b12 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralEvaluator.java @@ -7,10 +7,8 @@ import java.lang.IllegalArgumentException; import java.lang.Override; import java.lang.String; -import org.apache.lucene.util.BytesRef; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; -import org.elasticsearch.compute.data.BytesRefVector; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -25,7 +23,7 @@ public final class StGeohashFromFieldAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { private final Source source; - private final EvalOperator.ExpressionEvaluator in; + private final EvalOperator.ExpressionEvaluator wkbBlock; private final int precision; @@ -33,57 +31,34 @@ public final class StGeohashFromFieldAndLiteralEvaluator implements EvalOperator private Warnings warnings; - public StGeohashFromFieldAndLiteralEvaluator(Source source, EvalOperator.ExpressionEvaluator in, - int precision, DriverContext driverContext) { + public StGeohashFromFieldAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator wkbBlock, int precision, DriverContext driverContext) { this.source = source; - this.in = in; + this.wkbBlock = wkbBlock; this.precision = precision; this.driverContext = driverContext; } @Override public Block eval(Page page) { - try (BytesRefBlock inBlock = (BytesRefBlock) in.eval(page)) { - BytesRefVector inVector = inBlock.asVector(); - if (inVector == null) { - return eval(page.getPositionCount(), inBlock); - } - return eval(page.getPositionCount(), inVector); + try (BytesRefBlock wkbBlockBlock = (BytesRefBlock) wkbBlock.eval(page)) { + return eval(page.getPositionCount(), wkbBlockBlock); } } - public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock) { + public BytesRefBlock eval(int positionCount, BytesRefBlock wkbBlockBlock) { try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - BytesRef inScratch = new BytesRef(); position: for (int p = 0; p < positionCount; p++) { - if (inBlock.isNull(p)) { - result.appendNull(); - continue position; + boolean allBlocksAreNulls = true; + if (!wkbBlockBlock.isNull(p)) { + allBlocksAreNulls = false; } - if (inBlock.getValueCount(p) != 1) { - if (inBlock.getValueCount(p) > 1) { - warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); - } + if (allBlocksAreNulls) { result.appendNull(); continue position; } try { - result.appendBytesRef(StGeohash.fromFieldAndLiteral(inBlock.getBytesRef(inBlock.getFirstValueIndex(p), inScratch), this.precision)); - } catch (IllegalArgumentException e) { - warnings().registerException(e); - result.appendNull(); - } - } - return result.build(); - } - } - - public BytesRefBlock eval(int positionCount, BytesRefVector inVector) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - BytesRef inScratch = new BytesRef(); - position: for (int p = 0; p < positionCount; p++) { - try { - result.appendBytesRef(StGeohash.fromFieldAndLiteral(inVector.getBytesRef(p, inScratch), this.precision)); + StGeohash.fromFieldAndLiteral(result, p, wkbBlockBlock, this.precision); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -95,12 +70,12 @@ public BytesRefBlock eval(int positionCount, BytesRefVector inVector) { @Override public String toString() { - return "StGeohashFromFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + return "StGeohashFromFieldAndLiteralEvaluator[" + "wkbBlock=" + wkbBlock + ", precision=" + precision + "]"; } @Override public void close() { - Releasables.closeExpectNoException(in); + Releasables.closeExpectNoException(wkbBlock); } private Warnings warnings() { @@ -118,24 +93,25 @@ private Warnings warnings() { static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final Source source; - private final EvalOperator.ExpressionEvaluator.Factory in; + private final EvalOperator.ExpressionEvaluator.Factory wkbBlock; private final int precision; - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, int precision) { + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory wkbBlock, + int precision) { this.source = source; - this.in = in; + this.wkbBlock = wkbBlock; this.precision = precision; } @Override public StGeohashFromFieldAndLiteralEvaluator get(DriverContext context) { - return new StGeohashFromFieldAndLiteralEvaluator(source, in.get(context), precision, context); + return new StGeohashFromFieldAndLiteralEvaluator(source, wkbBlock.get(context), precision, context); } @Override public String toString() { - return "StGeohashFromFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + return "StGeohashFromFieldAndLiteralEvaluator[" + "wkbBlock=" + wkbBlock + ", precision=" + precision + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator.java new file mode 100644 index 0000000000000..84401fd376f94 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator.java @@ -0,0 +1,140 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohash}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encoded; + + private final EvalOperator.ExpressionEvaluator precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator encoded, EvalOperator.ExpressionEvaluator precision, + Rectangle bounds, DriverContext driverContext) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + return eval(page.getPositionCount(), encodedBlock, precisionBlock); + } + } + } + + public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeohash.fromFieldDocValuesAndFieldAndLiteral(result, p, encodedBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encoded, precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory encoded; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + private final Rectangle bounds; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, + EvalOperator.ExpressionEvaluator.Factory precision, Rectangle bounds) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator get(DriverContext context) { + return new StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator(source, encoded.get(context), precision.get(context), bounds, context); + } + + @Override + public String toString() { + return "StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldEvaluator.java index ae43b7364b11d..7135a0b166196 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldEvaluator.java @@ -10,9 +10,7 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; -import org.elasticsearch.compute.data.IntVector; import org.elasticsearch.compute.data.LongBlock; -import org.elasticsearch.compute.data.LongVector; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -48,15 +46,7 @@ public StGeohashFromFieldDocValuesAndFieldEvaluator(Source source, public Block eval(Page page) { try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { - LongVector encodedVector = encodedBlock.asVector(); - if (encodedVector == null) { - return eval(page.getPositionCount(), encodedBlock, precisionBlock); - } - IntVector precisionVector = precisionBlock.asVector(); - if (precisionVector == null) { - return eval(page.getPositionCount(), encodedBlock, precisionBlock); - } - return eval(page.getPositionCount(), encodedVector, precisionVector); + return eval(page.getPositionCount(), encodedBlock, precisionBlock); } } } @@ -64,16 +54,9 @@ public Block eval(Page page) { public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { - if (encodedBlock.isNull(p)) { - result.appendNull(); - continue position; - } - if (encodedBlock.getValueCount(p) != 1) { - if (encodedBlock.getValueCount(p) > 1) { - warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); - } - result.appendNull(); - continue position; + boolean allBlocksAreNulls = true; + if (!encodedBlock.isNull(p)) { + allBlocksAreNulls = false; } if (precisionBlock.isNull(p)) { result.appendNull(); @@ -86,23 +69,12 @@ public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock pr result.appendNull(); continue position; } - try { - result.appendBytesRef(StGeohash.fromFieldDocValuesAndField(encodedBlock.getLong(encodedBlock.getFirstValueIndex(p)), precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)))); - } catch (IllegalArgumentException e) { - warnings().registerException(e); + if (allBlocksAreNulls) { result.appendNull(); + continue position; } - } - return result.build(); - } - } - - public BytesRefBlock eval(int positionCount, LongVector encodedVector, - IntVector precisionVector) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - position: for (int p = 0; p < positionCount; p++) { try { - result.appendBytesRef(StGeohash.fromFieldDocValuesAndField(encodedVector.getLong(p), precisionVector.getInt(p))); + StGeohash.fromFieldDocValuesAndField(result, p, encodedBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p))); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java new file mode 100644 index 0000000000000..56a50ac8c6fed --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java @@ -0,0 +1,126 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohash}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encoded; + + private final int precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator encoded, int precision, Rectangle bounds, + DriverContext driverContext) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { + return eval(page.getPositionCount(), encodedBlock); + } + } + + public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeohash.fromFieldDocValuesAndLiteralAndLiteral(result, p, encodedBlock, this.precision, this.bounds); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encoded); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory encoded; + + private final int precision; + + private final Rectangle bounds; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, int precision, + Rectangle bounds) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator get(DriverContext context) { + return new StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator(source, encoded.get(context), precision, bounds, context); + } + + @Override + public String toString() { + return "StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralEvaluator.java index da6caa422a803..da73fa0495145 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralEvaluator.java @@ -10,7 +10,6 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.LongBlock; -import org.elasticsearch.compute.data.LongVector; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -44,44 +43,23 @@ public StGeohashFromFieldDocValuesAndLiteralEvaluator(Source source, @Override public Block eval(Page page) { try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { - LongVector encodedVector = encodedBlock.asVector(); - if (encodedVector == null) { - return eval(page.getPositionCount(), encodedBlock); - } - return eval(page.getPositionCount(), encodedVector); + return eval(page.getPositionCount(), encodedBlock); } } public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { - if (encodedBlock.isNull(p)) { - result.appendNull(); - continue position; + boolean allBlocksAreNulls = true; + if (!encodedBlock.isNull(p)) { + allBlocksAreNulls = false; } - if (encodedBlock.getValueCount(p) != 1) { - if (encodedBlock.getValueCount(p) > 1) { - warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); - } + if (allBlocksAreNulls) { result.appendNull(); continue position; } try { - result.appendBytesRef(StGeohash.fromFieldDocValuesAndLiteral(encodedBlock.getLong(encodedBlock.getFirstValueIndex(p)), this.precision)); - } catch (IllegalArgumentException e) { - warnings().registerException(e); - result.appendNull(); - } - } - return result.build(); - } - } - - public BytesRefBlock eval(int positionCount, LongVector encodedVector) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - position: for (int p = 0; p < positionCount; p++) { - try { - result.appendBytesRef(StGeohash.fromFieldDocValuesAndLiteral(encodedVector.getLong(p), this.precision)); + StGeohash.fromFieldDocValuesAndLiteral(result, p, encodedBlock, this.precision); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldAndLiteralEvaluator.java new file mode 100644 index 0000000000000..4d57666ce2cc1 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldAndLiteralEvaluator.java @@ -0,0 +1,148 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohash}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohashFromLiteralAndFieldAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final BytesRef in; + + private final EvalOperator.ExpressionEvaluator precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohashFromLiteralAndFieldAndLiteralEvaluator(Source source, BytesRef in, + EvalOperator.ExpressionEvaluator precision, Rectangle bounds, DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + IntVector precisionVector = precisionBlock.asVector(); + if (precisionVector == null) { + return eval(page.getPositionCount(), precisionBlock); + } + return eval(page.getPositionCount(), precisionVector); + } + } + + public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + try { + result.appendBytesRef(StGeohash.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds)); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + public BytesRefBlock eval(int positionCount, IntVector precisionVector) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + try { + result.appendBytesRef(StGeohash.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bounds)); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohashFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final BytesRef in; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + private final Rectangle bounds; + + public Factory(Source source, BytesRef in, EvalOperator.ExpressionEvaluator.Factory precision, + Rectangle bounds) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeohashFromLiteralAndFieldAndLiteralEvaluator get(DriverContext context) { + return new StGeohashFromLiteralAndFieldAndLiteralEvaluator(source, in, precision.get(context), bounds, context); + } + + @Override + public String toString() { + return "StGeohashFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java new file mode 100644 index 0000000000000..4dbca4a23343c --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java @@ -0,0 +1,122 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.expression.function.scalar.ScalarFunction; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.util.PlanStreamInput; +import org.elasticsearch.xpack.esql.expression.function.OptionalArgument; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * Spatial functions that take one spatial argument, one parameter and one optional bounds can inherit from this class. + * Obvious choices are: StGeohash, StGeotile and StGeohex. + */ +public abstract class SpatialGridFunction extends ScalarFunction implements OptionalArgument { + protected final Expression spatialField; + protected final Expression parameter; + protected final Expression bounds; + protected final boolean spatialDocsValues; + + protected SpatialGridFunction( + Source source, + Expression spatialField, + Expression parameter, + Expression bounds, + boolean spatialDocsValues + ) { + super(source, bounds == null ? Arrays.asList(spatialField, parameter) : Arrays.asList(spatialField, parameter, bounds)); + this.spatialField = spatialField; + this.parameter = parameter; + this.bounds = bounds; + this.spatialDocsValues = spatialDocsValues; + } + + protected SpatialGridFunction(StreamInput in, boolean spatialDocsValues) throws IOException { + this( + Source.readFrom((StreamInput & PlanStreamInput) in), + in.readNamedWriteable(Expression.class), + in.readNamedWriteable(Expression.class), + in.readOptionalNamedWriteable(Expression.class), + spatialDocsValues + ); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + source().writeTo(out); + out.writeNamedWriteable(spatialField); + out.writeNamedWriteable(parameter); + out.writeOptionalNamedWriteable(bounds); + } + + /** + * Mark the function as expecting the specified field to arrive as doc-values. + * This only applies to geo_point and cartesian_point types. + */ + public abstract SpatialGridFunction withDocValues(boolean useDocValues); + + @Override + public int hashCode() { + // NB: the hashcode is currently used for key generation so + // to avoid clashes between aggs with the same arguments, add the class name as variation + return Objects.hash(getClass(), children(), spatialDocsValues); + } + + @Override + public boolean equals(Object obj) { + if (super.equals(obj)) { + SpatialGridFunction other = (SpatialGridFunction) obj; + return Objects.equals(other.children(), children()) && Objects.equals(other.spatialDocsValues, spatialDocsValues); + } + return false; + } + + public boolean spatialDocsValues() { + return spatialDocsValues; + } + + @Override + public final SpatialGridFunction replaceChildren(List newChildren) { + Expression newSpatialField = newChildren.get(0); + Expression newParameter = newChildren.get(1); + Expression newBounds = newChildren.size() > 2 ? newChildren.get(2) : null; + + return spatialField.equals(newSpatialField) + && parameter.equals(newParameter) + && (bounds == null && newBounds == null || bounds != null && bounds.equals(newBounds)) + ? this + : replaceChildren(newSpatialField, newParameter, newBounds); + } + + protected abstract SpatialGridFunction replaceChildren(Expression newSpatialField, Expression newParameter, Expression newBounds); + + public Expression spatialField() { + return spatialField; + } + + public Expression parameter() { + return parameter; + } + + public Expression bounds() { + return bounds; + } + + @Override + public boolean foldable() { + return spatialField.foldable() && parameter.foldable() && (bounds == null || bounds.foldable()); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java index 1ac96e01cda34..864c62d1f3f3a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java @@ -12,12 +12,15 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; import org.elasticsearch.compute.ann.Fixed; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.geometry.utils.SpatialEnvelopeVisitor; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.FoldContext; -import org.elasticsearch.xpack.esql.core.expression.function.scalar.BinaryScalarFunction; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; @@ -27,19 +30,23 @@ import org.elasticsearch.xpack.esql.expression.function.Param; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.THIRD; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isType; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isWholeNumber; import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; /** * Calculates the geohash of geo_point geometries. */ -public class StGeohash extends UnarySpatialBinaryFunction implements EvaluatorMapper { +public class StGeohash extends SpatialGridFunction implements EvaluatorMapper { public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( Expression.class, "StGeohash", @@ -62,13 +69,19 @@ public StGeohash( name = "precision", type = { "integer" }, description = "Expression of type `integer`. If `null`, the function returns `null`." - ) Expression precision + ) Expression precision, + @Param( + name = "bounds", + type = { "geo_shape", "geo_point" }, + description = "Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points for top-left and bottom-right", + optional = true + ) Expression bounds ) { - this(source, field, precision, false); + this(source, field, precision, bounds, false); } - private StGeohash(Source source, Expression field, Expression precision, boolean spatialDocValues) { - super(source, field, precision, spatialDocValues); + private StGeohash(Source source, Expression field, Expression precision, Expression bounds, boolean spatialDocValues) { + super(source, field, precision, bounds, spatialDocValues); } private StGeohash(StreamInput in) throws IOException { @@ -76,10 +89,10 @@ private StGeohash(StreamInput in) throws IOException { } @Override - public UnarySpatialBinaryFunction withDocValues(boolean useDocValues) { + public SpatialGridFunction withDocValues(boolean useDocValues) { // Only update the docValues flags if the field is found in the attributes - boolean leftDV = this.spatialDocsValues || useDocValues; - return new StGeohash(source(), left(), right(), leftDV); + boolean docValues = this.spatialDocsValues || useDocValues; + return new StGeohash(source(), spatialField, parameter, bounds, docValues); } @Override @@ -93,13 +106,13 @@ public DataType dataType() { } @Override - protected BinaryScalarFunction replaceChildren(Expression newLeft, Expression newRight) { - return new StGeohash(source(), newLeft, newRight); + protected SpatialGridFunction replaceChildren(Expression newSpatialField, Expression newParameter, Expression newBounds) { + return new StGeohash(source(), newSpatialField, newParameter, newBounds); } @Override protected NodeInfo info() { - return NodeInfo.create(this, StGeohash::new, left(), right()); + return NodeInfo.create(this, StGeohash::new, spatialField, parameter, bounds, false); } @Override @@ -108,70 +121,142 @@ protected TypeResolution resolveType() { return new TypeResolution("Unresolved children"); } - TypeResolution resolution = isGeoPoint(left(), sourceText()); + TypeResolution resolution = isGeoPoint(spatialField(), sourceText()); if (resolution.unresolved()) { return resolution; } - resolution = isWholeNumber(right(), sourceText(), SECOND); + resolution = isWholeNumber(parameter(), sourceText(), SECOND); if (resolution.unresolved()) { return resolution; } + if (bounds() != null) { + resolution = isGeoShape(bounds(), sourceText()); + if (resolution.unresolved()) { + return resolution; + } + } + return TypeResolution.TYPE_RESOLVED; } protected static Expression.TypeResolution isGeoPoint(Expression e, String operationName) { - return isType(e, t -> t.equals(GEO_POINT), operationName, FIRST, GEO_POINT.typeName()); } + protected static Expression.TypeResolution isGeoShape(Expression e, String operationName) { + return isType(e, t -> t.equals(GEO_SHAPE), operationName, THIRD, GEO_SHAPE.typeName()); + } + + private static Rectangle asRectangle(BytesRef boundsBytesRef) { + var geometry = GEO.wkbToGeometry(boundsBytesRef); + if (geometry instanceof Rectangle rectangle) { + return rectangle; + } + var envelope = SpatialEnvelopeVisitor.visitGeo(geometry, SpatialEnvelopeVisitor.WrapLongitude.WRAP); + if (envelope.isPresent()) { + return envelope.get(); + } + throw new IllegalArgumentException("Cannot determine envelope of bounds geometry"); + } + @Override public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) { - // TODO: Implement - if (left().foldable()) { - // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() - var point = (BytesRef) left().fold(toEvaluator.foldCtx()); - return new StGeohashFromLiteralAndFieldEvaluator.Factory(source(), point, toEvaluator.apply(right())); - } else if (right().foldable()) { - // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() - int precision = (int) right().fold(toEvaluator.foldCtx()); - return spatialDocsValues - ? new StGeohashFromFieldDocValuesAndLiteralEvaluator.Factory(source(), toEvaluator.apply(left()), precision) - : new StGeohashFromFieldAndLiteralEvaluator.Factory(source(), toEvaluator.apply(left()), precision); + if (bounds != null) { + if (bounds.foldable() == false) { + throw new IllegalArgumentException("bounds must foldable"); + } + Rectangle bbox = asRectangle((BytesRef) bounds.fold(toEvaluator.foldCtx())); + if (spatialField().foldable()) { + // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() + var point = (BytesRef) spatialField.fold(toEvaluator.foldCtx()); + return new StGeohashFromLiteralAndFieldAndLiteralEvaluator.Factory(source(), point, toEvaluator.apply(parameter()), bbox); + } else if (parameter().foldable()) { + // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() + int precision = (int) parameter.fold(toEvaluator.foldCtx()); + return spatialDocsValues + ? new StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.Factory( + source(), + toEvaluator.apply(spatialField()), + precision, + bbox + ) + : new StGeohashFromFieldAndLiteralAndLiteralEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + precision, + bbox + ); + } else { + // Both arguments come from index fields + return spatialDocsValues + ? new StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + toEvaluator.apply(parameter), + bbox + ) + : new StGeohashFromFieldAndFieldAndLiteralEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + toEvaluator.apply(parameter), + bbox + ); + } } else { - // Both arguments come from index fields - return spatialDocsValues - ? new StGeohashFromFieldDocValuesAndFieldEvaluator.Factory(source(), toEvaluator.apply(left()), toEvaluator.apply(right())) - : new StGeohashFromFieldAndFieldEvaluator.Factory(source(), toEvaluator.apply(left()), toEvaluator.apply(right())); + if (spatialField().foldable()) { + // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() + var point = (BytesRef) spatialField.fold(toEvaluator.foldCtx()); + return new StGeohashFromLiteralAndFieldEvaluator.Factory(source(), point, toEvaluator.apply(parameter())); + } else if (parameter().foldable()) { + // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() + int precision = (int) parameter.fold(toEvaluator.foldCtx()); + return spatialDocsValues + ? new StGeohashFromFieldDocValuesAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField()), precision) + : new StGeohashFromFieldAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField), precision); + } else { + // Both arguments come from index fields + return spatialDocsValues + ? new StGeohashFromFieldDocValuesAndFieldEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + toEvaluator.apply(parameter) + ) + : new StGeohashFromFieldAndFieldEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + toEvaluator.apply(parameter) + ); + } } } @Override public Object fold(FoldContext ctx) { - var point = (BytesRef) left().fold(ctx); - int precision = (int) right().fold(ctx); + var point = (BytesRef) spatialField().fold(ctx); + int precision = (int) parameter().fold(ctx); return calculateGeohash(GEO.wkbAsPoint(point), precision); } @Evaluator(extraName = "FromFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static BytesRef fromFieldAndLiteral(BytesRef in, @Fixed int precision) { - return calculateGeohash(GEO.wkbAsPoint(in), precision); + static void fromFieldAndLiteral(BytesRefBlock.Builder results, int p, BytesRefBlock wkbBlock, @Fixed int precision) { + fromWKB(results, p, wkbBlock, precision); } @Evaluator(extraName = "FromFieldDocValuesAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static BytesRef fromFieldDocValuesAndLiteral(long encoded, @Fixed int precision) { - return calculateGeohash(GEO.longAsPoint(encoded), precision); + static void fromFieldDocValuesAndLiteral(BytesRefBlock.Builder results, int p, LongBlock encoded, @Fixed int precision) { + fromEncodedLong(results, p, encoded, precision); } @Evaluator(extraName = "FromFieldAndField", warnExceptions = { IllegalArgumentException.class }) - static BytesRef fromFieldAndField(BytesRef in, int precision) { - return calculateGeohash(GEO.wkbAsPoint(in), precision); + static void fromFieldAndField(BytesRefBlock.Builder results, int p, BytesRefBlock in, int precision) { + fromWKB(results, p, in, precision); } @Evaluator(extraName = "FromFieldDocValuesAndField", warnExceptions = { IllegalArgumentException.class }) - static BytesRef fromFieldDocValuesAndField(long encoded, int precision) { - return calculateGeohash(GEO.longAsPoint(encoded), precision); + static void fromFieldDocValuesAndField(BytesRefBlock.Builder results, int p, LongBlock encoded, int precision) { + fromEncodedLong(results, p, encoded, precision); } @Evaluator(extraName = "FromLiteralAndField", warnExceptions = { IllegalArgumentException.class }) @@ -182,4 +267,173 @@ static BytesRef fromLiteralAndField(@Fixed BytesRef in, int precision) { protected static BytesRef calculateGeohash(Point point, int precision) { return new BytesRef(Geohash.stringEncode(point.getX(), point.getY(), precision)); } + + @Evaluator(extraName = "FromFieldAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldAndLiteralAndLiteral( + BytesRefBlock.Builder results, + int p, + BytesRefBlock in, + @Fixed int precision, + @Fixed Rectangle bounds + ) { + fromWKB(results, p, in, precision, bounds); + } + + @Evaluator(extraName = "FromFieldDocValuesAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldDocValuesAndLiteralAndLiteral( + BytesRefBlock.Builder results, + int p, + LongBlock encoded, + @Fixed int precision, + @Fixed Rectangle bounds + ) { + fromEncodedLong(results, p, encoded, precision, bounds); + } + + @Evaluator(extraName = "FromFieldAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldAndFieldAndLiteral( + BytesRefBlock.Builder results, + int p, + BytesRefBlock in, + int precision, + @Fixed Rectangle bounds + ) { + fromWKB(results, p, in, precision, bounds); + } + + @Evaluator(extraName = "FromFieldDocValuesAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldDocValuesAndFieldAndLiteral( + BytesRefBlock.Builder results, + int p, + LongBlock encoded, + int precision, + @Fixed Rectangle bounds + ) { + fromEncodedLong(results, p, encoded, precision, bounds); + } + + @Evaluator(extraName = "FromLiteralAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static BytesRef fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed Rectangle bounds) { + return calculateGeohash(GEO.wkbAsPoint(in), precision, bounds); + } + + private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { + int valueCount = wkbBlock.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final BytesRef scratch = new BytesRef(); + final int firstValueIndex = wkbBlock.getFirstValueIndex(position); + if (valueCount == 1) { + results.appendBytesRef(calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision)); + } else { + results.beginPositionEntry(); + for (int i = 0; i < valueCount; i++) { + results.appendBytesRef(calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision)); + } + results.endPositionEntry(); + } + } + } + + private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, int precision) { + int valueCount = encoded.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final int firstValueIndex = encoded.getFirstValueIndex(position); + if (valueCount == 1) { + results.appendBytesRef(calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision)); + } else { + results.beginPositionEntry(); + for (int i = 0; i < valueCount; i++) { + results.appendBytesRef(calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision)); + } + results.endPositionEntry(); + } + } + } + + protected static BytesRef calculateGeohash(Point point, int precision, Rectangle bounds) { + // For points, filtering the point is as good as filtering the tile + if (inBounds(point, bounds)) { + return new BytesRef(Geohash.stringEncode(point.getX(), point.getY(), precision)); + } + return null; + } + + protected static boolean inBounds(Point point, Rectangle bounds) { + // TODO: consider bounds across the dateline + return point.getX() >= bounds.getMinX() + && point.getY() >= bounds.getMinY() + && point.getX() <= bounds.getMaxX() + && point.getY() <= bounds.getMaxY(); + } + + private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision, Rectangle bounds) { + int valueCount = wkbBlock.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final BytesRef scratch = new BytesRef(); + final int firstValueIndex = wkbBlock.getFirstValueIndex(position); + if (valueCount == 1) { + BytesRef grid = calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision, bounds); + if (grid == null) { + results.appendNull(); + } else { + results.appendBytesRef(grid); + } + } else { + var gridIds = new ArrayList(valueCount); + for (int i = 0; i < valueCount; i++) { + var grid = calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision, bounds); + if (grid != null) { + gridIds.add(grid); + } + } + addGrids(results, gridIds); + } + } + } + + private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, int precision, Rectangle bounds) { + int valueCount = encoded.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final int firstValueIndex = encoded.getFirstValueIndex(position); + if (valueCount == 1) { + BytesRef grid = calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision, bounds); + if (grid == null) { + results.appendNull(); + } else { + results.appendBytesRef(grid); + } + } else { + var gridIds = new ArrayList(valueCount); + for (int i = 0; i < valueCount; i++) { + var grid = calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision, bounds); + if (grid != null) { + gridIds.add(grid); + } + } + addGrids(results, gridIds); + } + } + } + + private static void addGrids(BytesRefBlock.Builder results, List gridIds) { + if (gridIds.isEmpty()) { + results.appendNull(); + } else if (gridIds.size() == 1) { + results.appendBytesRef(gridIds.getFirst()); + } else { + results.beginPositionEntry(); + for (BytesRef gridId : gridIds) { + results.appendBytesRef(gridId); + } + results.endPositionEntry(); + } + } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/UnarySpatialBinaryFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/UnarySpatialBinaryFunction.java deleted file mode 100644 index 0424c3219de55..0000000000000 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/UnarySpatialBinaryFunction.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; - -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.xpack.esql.core.expression.Expression; -import org.elasticsearch.xpack.esql.core.expression.function.scalar.BinaryScalarFunction; -import org.elasticsearch.xpack.esql.core.tree.Source; - -import java.io.IOException; -import java.util.Objects; - -/** - * Spatial functions that take one spatial argument can inherit from this class. - */ -public abstract class UnarySpatialBinaryFunction extends BinaryScalarFunction { - protected final boolean spatialDocsValues; - - protected UnarySpatialBinaryFunction(Source source, Expression left, Expression right, boolean spatialDocsValues) { - super(source, left, right); - this.spatialDocsValues = spatialDocsValues; - } - - protected UnarySpatialBinaryFunction(StreamInput in, boolean spatialDocsValues) throws IOException { - super(in); - this.spatialDocsValues = spatialDocsValues; - } - - /** - * Mark the function as expecting the specified fields to arrive as doc-values. - */ - public abstract UnarySpatialBinaryFunction withDocValues(boolean useDocValues); - - @Override - public int hashCode() { - // NB: the hashcode is currently used for key generation so - // to avoid clashes between aggs with the same arguments, add the class name as variation - return Objects.hash(getClass(), children(), spatialDocsValues); - } - - @Override - public boolean equals(Object obj) { - if (super.equals(obj)) { - UnarySpatialBinaryFunction other = (UnarySpatialBinaryFunction) obj; - return Objects.equals(other.children(), children()) && Objects.equals(other.spatialDocsValues, spatialDocsValues); - } - return false; - } - - public boolean spatialDocsValues() { - return spatialDocsValues; - } -} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/SpatialDocValuesExtraction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/SpatialDocValuesExtraction.java index 1018de02e06d3..6cbbb126ed690 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/SpatialDocValuesExtraction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/SpatialDocValuesExtraction.java @@ -17,7 +17,7 @@ import org.elasticsearch.xpack.esql.expression.function.aggregate.SpatialAggregateFunction; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.BinarySpatialFunction; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.SpatialRelatesFunction; -import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.UnarySpatialBinaryFunction; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.SpatialGridFunction; import org.elasticsearch.xpack.esql.optimizer.LocalPhysicalOptimizerContext; import org.elasticsearch.xpack.esql.optimizer.PhysicalOptimizerRules; import org.elasticsearch.xpack.esql.plan.physical.AggregateExec; @@ -113,7 +113,7 @@ && allowedForDocValues(fieldAttribute, ctx.searchStats(), agg, foundAttributes)) List changed = fields.stream() .map( f -> (Alias) f.transformDown(BinarySpatialFunction.class, s -> withDocValues(s, foundAttributes)) - .transformDown(UnarySpatialBinaryFunction.class, s -> withDocValues(s, foundAttributes)) + .transformDown(SpatialGridFunction.class, s -> withDocValues(s, foundAttributes)) ) .toList(); if (changed.equals(fields) == false) { @@ -125,7 +125,7 @@ && allowedForDocValues(fieldAttribute, ctx.searchStats(), agg, foundAttributes)) // to support shapes, we need to consider loading shape doc-values for both centroid and relates (ST_INTERSECTS) var condition = filterExec.condition() .transformDown(BinarySpatialFunction.class, s -> withDocValues(s, foundAttributes)) - .transformDown(UnarySpatialBinaryFunction.class, s -> withDocValues(s, foundAttributes)); + .transformDown(SpatialGridFunction.class, s -> withDocValues(s, foundAttributes)); if (filterExec.condition().equals(condition) == false) { exec = new FilterExec(filterExec.source(), filterExec.child(), condition); } @@ -155,9 +155,9 @@ private BinarySpatialFunction withDocValues(BinarySpatialFunction spatial, Set foundAttributes) { + private SpatialGridFunction withDocValues(SpatialGridFunction spatial, Set foundAttributes) { // Only update the docValues flags if the field is found in the attributes - boolean found = foundField(spatial.left(), foundAttributes); + boolean found = foundField(spatial.spatialField(), foundAttributes); return found ? spatial.withDocValues(found) : spatial; } From a4db2a3f04c4d8b30751d9da850a2698669edbd4 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 18 Mar 2025 18:57:07 +0100 Subject: [PATCH 04/34] Added geotile and geohex --- x-pack/plugin/esql/build.gradle | 1 + .../src/main/resources/spatial-grid.csv-spec | 349 ++++++++++++++++- ...xFromFieldAndFieldAndLiteralEvaluator.java | 139 +++++++ .../StGeohexFromFieldAndFieldEvaluator.java | 131 +++++++ ...romFieldAndLiteralAndLiteralEvaluator.java | 125 ++++++ .../StGeohexFromFieldAndLiteralEvaluator.java | 117 ++++++ ...dDocValuesAndFieldAndLiteralEvaluator.java | 140 +++++++ ...exFromFieldDocValuesAndFieldEvaluator.java | 133 +++++++ ...ocValuesAndLiteralAndLiteralEvaluator.java | 126 ++++++ ...FromFieldDocValuesAndLiteralEvaluator.java | 117 ++++++ ...romLiteralAndFieldAndLiteralEvaluator.java | 148 +++++++ .../StGeohexFromLiteralAndFieldEvaluator.java | 140 +++++++ ...eFromFieldAndFieldAndLiteralEvaluator.java | 139 +++++++ .../StGeotileFromFieldAndFieldEvaluator.java | 131 +++++++ ...romFieldAndLiteralAndLiteralEvaluator.java | 125 ++++++ ...StGeotileFromFieldAndLiteralEvaluator.java | 117 ++++++ ...dDocValuesAndFieldAndLiteralEvaluator.java | 140 +++++++ ...leFromFieldDocValuesAndFieldEvaluator.java | 133 +++++++ ...ocValuesAndLiteralAndLiteralEvaluator.java | 126 ++++++ ...FromFieldDocValuesAndLiteralEvaluator.java | 117 ++++++ ...romLiteralAndFieldAndLiteralEvaluator.java | 148 +++++++ ...StGeotileFromLiteralAndFieldEvaluator.java | 140 +++++++ .../esql/expression/ExpressionWritables.java | 6 +- .../function/EsqlFunctionRegistry.java | 6 +- .../scalar/spatial/SpatialGridFunction.java | 83 ++++ .../function/scalar/spatial/StGeohash.java | 79 +--- .../function/scalar/spatial/StGeohex.java | 358 +++++++++++++++++ .../function/scalar/spatial/StGeotile.java | 362 ++++++++++++++++++ .../local/SpatialDocValuesExtraction.java | 2 +- 29 files changed, 3785 insertions(+), 93 deletions(-) create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldAndLiteralEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java diff --git a/x-pack/plugin/esql/build.gradle b/x-pack/plugin/esql/build.gradle index 539da924e6504..03b32e3910216 100644 --- a/x-pack/plugin/esql/build.gradle +++ b/x-pack/plugin/esql/build.gradle @@ -40,6 +40,7 @@ dependencies { implementation project('compute:ann') implementation project(':libs:dissect') implementation project(':libs:grok') + implementation project(':libs:h3') implementation project('arrow') // Also contains a dummy processor to allow compilation with unused annotations. diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index 0eaadfd64ff5f..6e86646a83f65 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -1,14 +1,17 @@ ############################################### -# Tests for geo_grid functions: geohash, geotile, geohex +# Tests for geo_grid function: ST_GEOHASH ############################################### geohashLiteral ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") -| EVAL geohash = ST_GEOHASH(location, 4) +| EVAL geohash4 = ST_GEOHASH(location, 4), + geohash3 = ST_GEOHASH(location, 3), + geohash2 = ST_GEOHASH(location, 2), + geohash1 = ST_GEOHASH(location, 1) ; -location:geo_point | geohash:keyword -POINT(12.6493508684508 55.6285017221528) | u3bu +location:geo_point | geohash4:keyword | geohash3:keyword | geohash2:keyword | geohash1:keyword +POINT(12.6493508684508 55.6285017221528) | u3bu | u3b | u3 | u ; geohashLiteralMv @@ -44,6 +47,7 @@ FROM airports count = COUNT(*), centroid = ST_CENTROID_AGG(location) BY geohash +| WHERE count >= 10 | SORT count DESC, geohash ASC // end::st_geohash-grid[] ; @@ -67,14 +71,6 @@ count:long | centroid:geo_point | geohash:keyword 16 | POINT (147.40052131412085 21.054660080408212) | x 13 | POINT (63.64716878519035 54.37333276101317) | v 12 | POINT (-39.53510569408536 -11.72166372067295) | 7 -9 | POINT (-150.36503398790956 63.14222150482237) | b -7 | POINT (-167.3069146488394 -17.976190628084755) | 2 -6 | POINT (-157.0227657398209 17.60691551025957) | 8 -5 | POINT (114.40185610949993 48.99013584572822) | y -4 | POINT (-69.98911972157657 -52.170535867335275) | 4 -4 | POINT (51.48641954641789 -14.176777086686343) | m -1 | POINT (-109.43006442859769 -27.15877384878695) | 3 -1 | POINT (170.20002692006528 -45.92343100346625) | p // end::st_geohash-grid-result[] ; @@ -171,3 +167,332 @@ count:long | centroid:geo_point 14 | POINT (-2.5644131543646966 53.38093495994274) 3 | POINT (-2.7510103583335876 58.79020635969937) ; + +############################################### +# Tests for geo_grid function: ST_GEOTILE +############################################### + +geotileLiteral +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") +| EVAL geotile4 = ST_GEOTILE(location, 4), + geotile3 = ST_GEOTILE(location, 3), + geotile2 = ST_GEOTILE(location, 2), + geotile1 = ST_GEOTILE(location, 1) +; + +location:geo_point | geotile4:keyword | geotile3:keyword | geotile2:keyword | geotile1:keyword +POINT (12.6493508684508 55.6285017221528) | 4/8/5 | 3/4/2 | 2/2/1 | 1/1/0 +; + +geotileLiteralMv +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] +| MV_EXPAND precision +| EVAL geotile = ST_GEOTILE(location, precision) +; + +location:geo_point | precision:integer | geotile:keyword +POINT (12.6493508684508 55.6285017221528) | 1 | 1/1/0 +POINT (12.6493508684508 55.6285017221528) | 2 | 2/2/1 +POINT (12.6493508684508 55.6285017221528) | 3 | 3/4/2 +POINT (12.6493508684508 55.6285017221528) | 4 | 4/8/5 +POINT (12.6493508684508 55.6285017221528) | 5 | 5/17/10 +; + +geotileField +FROM airports +| WHERE abbrev == "CPH" +| EVAL geotile = ST_GEOTILE(location, 7) +| KEEP geotile, abbrev, name, location +; + +geotile:keyword | abbrev:keyword | name:text | location:geo_point +7/68/40 | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) +; + +gridGeotileStatsBy +// tag::st_geotile-grid[] +FROM airports +| EVAL geotile = ST_GEOTILE(location, 2) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geotile +| SORT count DESC, geotile ASC +// end::st_geotile-grid[] +; + +// tag::st_geotile-grid-result[] +count:long | centroid:geo_point | geotile:keyword +286 | POINT (39.31202001609169 35.149993664386415) | 2/2/1 +197 | POINT (-55.387361375756825 31.952955322292855) | 2/1/1 +136 | POINT (-110.97162496141048 36.87185255084734) | 2/0/1 +106 | POINT (119.35907618669827 25.46263281488791) | 2/3/1 +67 | POINT (-58.031108492373754 -22.624166105151065) | 2/1/2 +46 | POINT (142.95455511274707 -20.581492295427978) | 2/3/2 +34 | POINT (31.38476753634784 -14.64374022804858) | 2/2/2 +8 | POINT (-160.0723083713092 -19.124013530672528) | 2/0/2 +6 | POINT (23.95813101902604 70.17537698848173) | 2/2/0 +3 | POINT (-133.4001641627401 72.06833167467266) | 2/0/0 +2 | POINT (-68.47209956031293 66.77569948369637) | 2/1/0 +// end::st_geotile-grid-result[] +; + +gridGeotileStatsByBounds +FROM airports +| EVAL geotile = ST_GEOTILE(location, 3, TO_GEOSHAPE("BBOX(0, 12, 60, 30)")) +| WHERE geotile IS NOT NULL +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geotile +| SORT count DESC, geotile ASC +; + +count:long | centroid:geo_point | geotile:keyword +36 | POINT (6.52789649553597 48.36977661703713) | 3/4/2 +5 | POINT (6.707012789323926 37.031419202685356) | 3/4/3 +; + +gridGeotileStatsByWhereUK +FROM airports +| WHERE ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) +| EVAL geotile = ST_GEOTILE(location, 4) +| STATS + count = COUNT(location), + centroid = ST_CENTROID_AGG(location) + BY geotile +| SORT count DESC +; + +count:long | centroid:geo_point | geotile:keyword +12 | POINT (-2.342151787597686 52.9600293841213) | 4/7/5 +5 | POINT (-3.2097987569868565 57.63667118176818) | 4/7/4 +; + +gridGeotileStatsByBoundsUK +FROM airports +| EVAL bounds = ST_ENVELOPE(TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) +| EVAL geotile = ST_GEOTILE(location, 2, bounds) +| WHERE geotile IS NOT NULL +| STATS + count = COUNT(location), + centroid = ST_CENTROID_AGG(location) + BY geotile +| SORT count DESC +; + +count:long | centroid:geo_point | geotile:keyword +20 | POINT (-3.3905635555274785 54.08363554766402) | 2/1/1 +1 | POINT (0.15865350142121315 49.36166098807007) | 2/2/1 +; + +gridGeotileInStatsBy +FROM airports +| STATS + count = COUNT(location), + centroid = ST_CENTROID_AGG(location) + BY ST_GEOTILE(location, 1) +| SORT count DESC +| KEEP count, centroid +| LIMIT 10 +; + +count:long | centroid:geo_point +398 | POINT (60.39961956408642 33.09796363900383) +338 | POINT (-78.52247301001411 34.49426195088267) +80 | POINT (95.5373953927774 -18.057947666791733) +75 | POINT (-68.91550314612687 -22.25081649720669) +; + +gridGeotileInStatsByWhereUK +FROM airports +| WHERE ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) +| STATS + count = COUNT(location), + centroid = ST_CENTROID_AGG(location) + BY ST_GEOTILE(location, 3) +| KEEP count, centroid +| SORT count DESC +; + +count:long | centroid:geo_point +17 | POINT (-2.597342072712148 54.33551226578214) +; + +############################################### +# Tests for geo_grid function: ST_GEOHEX +############################################### + +geohexLiteral +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") +| EVAL geohex4 = ST_GEOHEX(location, 4), + geohex3 = ST_GEOHEX(location, 3), + geohex2 = ST_GEOHEX(location, 2), + geohex1 = ST_GEOHEX(location, 1) +; + +location:geo_point | geohex4:keyword | geohex3:keyword | geohex2:keyword | geohex1:keyword +POINT (12.6493508684508 55.6285017221528) | 841f059ffffffff | 831f05fffffffff | 821f07fffffffff | 811f3ffffffffff +; + +geohexLiteralMv +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] +| MV_EXPAND precision +| EVAL geohex = ST_GEOHEX(location, precision) +; + +location:geo_point | precision:integer | geohex:keyword +POINT (12.6493508684508 55.6285017221528) | 1 | 811f3ffffffffff +POINT (12.6493508684508 55.6285017221528) | 2 | 821f07fffffffff +POINT (12.6493508684508 55.6285017221528) | 3 | 831f05fffffffff +POINT (12.6493508684508 55.6285017221528) | 4 | 841f059ffffffff +POINT (12.6493508684508 55.6285017221528) | 5 | 851f0583fffffff +; + +geohexField +FROM airports +| WHERE abbrev == "CPH" +| EVAL geohex = ST_GEOHEX(location, 7) +| KEEP geohex, abbrev, name, location +; + +geohex:keyword | abbrev:keyword | name:text | location:geo_point +871f05818ffffff | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) +; + +gridGeohexStatsBy +// tag::st_geohex-grid[] +FROM airports +| EVAL geohex = ST_GEOHEX(location, 1) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geohex +| WHERE count >= 10 +| SORT count DESC, geohex ASC +// end::st_geohex-grid[] +; + +// tag::st_geohex-grid-result[] +count:long | centroid:geo_point | geohex:keyword +22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff +18 | POINT (-80.64959161449224 40.04119813675061) | 812abffffffffff +17 | POINT (-0.7606179875266903 52.86413913565304) | 81197ffffffffff +13 | POINT (22.53157936179867 41.98255742864254) | 811efffffffffff +13 | POINT (78.30096947387435 26.073904778951636) | 813dbffffffffff +12 | POINT (-76.39781514415517 45.16300531569868) | 812bbffffffffff +12 | POINT (-100.30120467301458 20.114154297625646) | 8149bffffffffff +11 | POINT (18.037187419831753 48.66540593306788) | 811e3ffffffffff +11 | POINT (-83.42379064553164 33.18388901439241) | 8144fffffffffff +11 | POINT (-99.4237939513881 27.100012352774765) | 8148bffffffffff +10 | POINT (128.01009018346667 35.8699960866943) | 8130fffffffffff +// end::st_geohex-grid-result[] +; + +gridGeohexStatsByBounds +FROM airports +| EVAL geohex = ST_GEOHEX(location, 1, TO_GEOSHAPE("BBOX(0, 12, 60, 30)")) +| WHERE geohex IS NOT NULL +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geohex +| SORT count DESC, geohex ASC +; + +count:long | centroid:geo_point | geohex:keyword +22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff +5 | POINT (3.6714368518441916 42.29731031600386) | 81397ffffffffff +4 | POINT (4.188777215313166 51.50470834574662) | 81197ffffffffff +3 | POINT (9.197671310976148 36.29719984252006) | 81387ffffffffff +2 | POINT (9.261639816686511 43.87209988664836) | 811ebffffffffff +2 | POINT (9.395754751749337 53.3421441167593) | 811f3ffffffffff +1 | POINT (5.629810290411115 58.88215648010373) | 8109bffffffffff +1 | POINT (0.15865350142121315 49.36166098807007) | 81187ffffffffff +1 | POINT (3.212073454633355 36.69972063973546) | 81383ffffffffff +; + +gridGeohexStatsByWhereUK +FROM airports +| WHERE ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) +| EVAL geohex = ST_GEOHEX(location, 1) +| STATS + count = COUNT(location), + centroid = ST_CENTROID_AGG(location) + BY geohex +| SORT count DESC, geohex ASC +; + +count:long | centroid:geo_point | geohex:keyword +13 | POINT (-2.283508819169723 53.28242553254733) | 81197ffffffffff +2 | POINT (-3.482485176064074 58.24696456314996) | 81193ffffffffff +1 | POINT (-1.2880607228726149 59.87668995279819) | 8109bffffffffff +1 | POINT (-6.216169511899352 54.66155751608312) | 81183ffffffffff +; + +gridGeohexStatsByBoundsUK +FROM airports +| EVAL bounds = ST_ENVELOPE(TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) +| EVAL geohex = ST_GEOHEX(location, 2, bounds) +| WHERE geohex IS NOT NULL +| STATS + count = COUNT(location), + centroid = ST_CENTROID_AGG(location) + BY geohex +| SORT count DESC, geohex ASC +; + +count:long | centroid:geo_point | geohex:keyword +5 | POINT (-1.7227098606526852 51.717823022045195) | 82195ffffffffff +4 | POINT (-3.9897833741270006 54.21732849790715) | 821957fffffffff +3 | POINT (-7.885485291481018 52.65633414499462) | 82182ffffffffff +2 | POINT (-4.2476349184289575 56.70184155693278) | 82190ffffffffff +2 | POINT (-2.5373152876272798 55.49281941493973) | 821977fffffffff +1 | POINT (-1.2880607228726149 59.87668995279819) | 8209a7fffffffff +1 | POINT (0.15865350142121315 49.36166098807007) | 821867fffffffff +1 | POINT (-2.9013785161077976 58.95442885346711) | 82192ffffffffff +1 | POINT (-1.6598310694098473 53.8690819311887) | 821947fffffffff +1 | POINT (-0.16296171583235264 51.1557567352429) | 82194ffffffffff +; + +gridGeohexInStatsBy +FROM airports +| STATS + count = COUNT(location), + centroid = ST_CENTROID_AGG(location) + BY ST_GEOHEX(location, 1) +| SORT count DESC +| KEEP count, centroid +| LIMIT 10 +; + +count:long | centroid:geo_point +22 | POINT (7.250850197689777 48.21363834643059) +18 | POINT (-80.64959161449224 40.04119813675061) +17 | POINT (-0.7606179875266903 52.86413913565304) +13 | POINT (22.53157936179867 41.98255742864254) +13 | POINT (78.30096947387435 26.073904778951636) +12 | POINT (-100.30120467301458 20.114154297625646) +12 | POINT (-76.39781514415517 45.16300531569868) +11 | POINT (-99.4237939513881 27.100012352774765) +11 | POINT (-83.42379064553164 33.18388901439241) +11 | POINT (18.037187419831753 48.66540593306788) +; + +gridGeohexInStatsByWhereUK +FROM airports +| WHERE ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) +| STATS + count = COUNT(location), + centroid = ST_CENTROID_AGG(location) + BY ST_GEOHEX(location, 1) +| KEEP count, centroid +| SORT count DESC +; + +count:long | centroid:geo_point +13 | POINT (-2.283508819169723 53.28242553254733) +2 | POINT (-3.482485176064074 58.24696456314996) +1 | POINT (-6.216169511899352 54.66155751608312) +1 | POINT (-1.2880607228726149 59.87668995279819) +; diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldAndLiteralEvaluator.java new file mode 100644 index 0000000000000..a33a359269f91 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldAndLiteralEvaluator.java @@ -0,0 +1,139 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohex}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohexFromFieldAndFieldAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator in; + + private final EvalOperator.ExpressionEvaluator precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohexFromFieldAndFieldAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator in, EvalOperator.ExpressionEvaluator precision, + Rectangle bounds, DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock inBlock = (BytesRefBlock) in.eval(page)) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + return eval(page.getPositionCount(), inBlock, precisionBlock); + } + } + } + + public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!inBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeohex.fromFieldAndFieldAndLiteral(result, p, inBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohexFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(in, precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory in; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + private final Rectangle bounds; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, + EvalOperator.ExpressionEvaluator.Factory precision, Rectangle bounds) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeohexFromFieldAndFieldAndLiteralEvaluator get(DriverContext context) { + return new StGeohexFromFieldAndFieldAndLiteralEvaluator(source, in.get(context), precision.get(context), bounds, context); + } + + @Override + public String toString() { + return "StGeohexFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldEvaluator.java new file mode 100644 index 0000000000000..d5fb297e66aa2 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldEvaluator.java @@ -0,0 +1,131 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohex}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohexFromFieldAndFieldEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator in; + + private final EvalOperator.ExpressionEvaluator precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohexFromFieldAndFieldEvaluator(Source source, EvalOperator.ExpressionEvaluator in, + EvalOperator.ExpressionEvaluator precision, DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock inBlock = (BytesRefBlock) in.eval(page)) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + return eval(page.getPositionCount(), inBlock, precisionBlock); + } + } + } + + public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!inBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeohex.fromFieldAndField(result, p, inBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohexFromFieldAndFieldEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(in, precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory in; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, + EvalOperator.ExpressionEvaluator.Factory precision) { + this.source = source; + this.in = in; + this.precision = precision; + } + + @Override + public StGeohexFromFieldAndFieldEvaluator get(DriverContext context) { + return new StGeohexFromFieldAndFieldEvaluator(source, in.get(context), precision.get(context), context); + } + + @Override + public String toString() { + return "StGeohexFromFieldAndFieldEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java new file mode 100644 index 0000000000000..cd12dc800a59e --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java @@ -0,0 +1,125 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohex}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohexFromFieldAndLiteralAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator in; + + private final int precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohexFromFieldAndLiteralAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator in, int precision, Rectangle bounds, + DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock inBlock = (BytesRefBlock) in.eval(page)) { + return eval(page.getPositionCount(), inBlock); + } + } + + public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!inBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeohex.fromFieldAndLiteralAndLiteral(result, p, inBlock, this.precision, this.bounds); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohexFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(in); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory in; + + private final int precision; + + private final Rectangle bounds; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, int precision, + Rectangle bounds) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeohexFromFieldAndLiteralAndLiteralEvaluator get(DriverContext context) { + return new StGeohexFromFieldAndLiteralAndLiteralEvaluator(source, in.get(context), precision, bounds, context); + } + + @Override + public String toString() { + return "StGeohexFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralEvaluator.java new file mode 100644 index 0000000000000..5a8304afab118 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralEvaluator.java @@ -0,0 +1,117 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohex}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohexFromFieldAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator wkbBlock; + + private final int precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohexFromFieldAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator wkbBlock, int precision, DriverContext driverContext) { + this.source = source; + this.wkbBlock = wkbBlock; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock wkbBlockBlock = (BytesRefBlock) wkbBlock.eval(page)) { + return eval(page.getPositionCount(), wkbBlockBlock); + } + } + + public BytesRefBlock eval(int positionCount, BytesRefBlock wkbBlockBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!wkbBlockBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeohex.fromFieldAndLiteral(result, p, wkbBlockBlock, this.precision); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohexFromFieldAndLiteralEvaluator[" + "wkbBlock=" + wkbBlock + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(wkbBlock); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory wkbBlock; + + private final int precision; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory wkbBlock, + int precision) { + this.source = source; + this.wkbBlock = wkbBlock; + this.precision = precision; + } + + @Override + public StGeohexFromFieldAndLiteralEvaluator get(DriverContext context) { + return new StGeohexFromFieldAndLiteralEvaluator(source, wkbBlock.get(context), precision, context); + } + + @Override + public String toString() { + return "StGeohexFromFieldAndLiteralEvaluator[" + "wkbBlock=" + wkbBlock + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator.java new file mode 100644 index 0000000000000..b31e82cab4549 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator.java @@ -0,0 +1,140 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohex}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encoded; + + private final EvalOperator.ExpressionEvaluator precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator encoded, EvalOperator.ExpressionEvaluator precision, + Rectangle bounds, DriverContext driverContext) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + return eval(page.getPositionCount(), encodedBlock, precisionBlock); + } + } + } + + public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeohex.fromFieldDocValuesAndFieldAndLiteral(result, p, encodedBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encoded, precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory encoded; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + private final Rectangle bounds; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, + EvalOperator.ExpressionEvaluator.Factory precision, Rectangle bounds) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator get(DriverContext context) { + return new StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator(source, encoded.get(context), precision.get(context), bounds, context); + } + + @Override + public String toString() { + return "StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldEvaluator.java new file mode 100644 index 0000000000000..79f794dcb52a5 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldEvaluator.java @@ -0,0 +1,133 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohex}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohexFromFieldDocValuesAndFieldEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encoded; + + private final EvalOperator.ExpressionEvaluator precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohexFromFieldDocValuesAndFieldEvaluator(Source source, + EvalOperator.ExpressionEvaluator encoded, EvalOperator.ExpressionEvaluator precision, + DriverContext driverContext) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + return eval(page.getPositionCount(), encodedBlock, precisionBlock); + } + } + } + + public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeohex.fromFieldDocValuesAndField(result, p, encodedBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohexFromFieldDocValuesAndFieldEvaluator[" + "encoded=" + encoded + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encoded, precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory encoded; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, + EvalOperator.ExpressionEvaluator.Factory precision) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + } + + @Override + public StGeohexFromFieldDocValuesAndFieldEvaluator get(DriverContext context) { + return new StGeohexFromFieldDocValuesAndFieldEvaluator(source, encoded.get(context), precision.get(context), context); + } + + @Override + public String toString() { + return "StGeohexFromFieldDocValuesAndFieldEvaluator[" + "encoded=" + encoded + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java new file mode 100644 index 0000000000000..f3d1401f9922e --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java @@ -0,0 +1,126 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohex}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encoded; + + private final int precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator encoded, int precision, Rectangle bounds, + DriverContext driverContext) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { + return eval(page.getPositionCount(), encodedBlock); + } + } + + public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeohex.fromFieldDocValuesAndLiteralAndLiteral(result, p, encodedBlock, this.precision, this.bounds); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encoded); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory encoded; + + private final int precision; + + private final Rectangle bounds; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, int precision, + Rectangle bounds) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator get(DriverContext context) { + return new StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator(source, encoded.get(context), precision, bounds, context); + } + + @Override + public String toString() { + return "StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralEvaluator.java new file mode 100644 index 0000000000000..7714f33ceaf7d --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralEvaluator.java @@ -0,0 +1,117 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohex}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohexFromFieldDocValuesAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encoded; + + private final int precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohexFromFieldDocValuesAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator encoded, int precision, DriverContext driverContext) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { + return eval(page.getPositionCount(), encodedBlock); + } + } + + public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeohex.fromFieldDocValuesAndLiteral(result, p, encodedBlock, this.precision); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohexFromFieldDocValuesAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encoded); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory encoded; + + private final int precision; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, int precision) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + } + + @Override + public StGeohexFromFieldDocValuesAndLiteralEvaluator get(DriverContext context) { + return new StGeohexFromFieldDocValuesAndLiteralEvaluator(source, encoded.get(context), precision, context); + } + + @Override + public String toString() { + return "StGeohexFromFieldDocValuesAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldAndLiteralEvaluator.java new file mode 100644 index 0000000000000..e7aa53d932bf9 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldAndLiteralEvaluator.java @@ -0,0 +1,148 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohex}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohexFromLiteralAndFieldAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final BytesRef in; + + private final EvalOperator.ExpressionEvaluator precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohexFromLiteralAndFieldAndLiteralEvaluator(Source source, BytesRef in, + EvalOperator.ExpressionEvaluator precision, Rectangle bounds, DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + IntVector precisionVector = precisionBlock.asVector(); + if (precisionVector == null) { + return eval(page.getPositionCount(), precisionBlock); + } + return eval(page.getPositionCount(), precisionVector); + } + } + + public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + try { + result.appendBytesRef(StGeohex.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds)); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + public BytesRefBlock eval(int positionCount, IntVector precisionVector) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + try { + result.appendBytesRef(StGeohex.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bounds)); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohexFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final BytesRef in; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + private final Rectangle bounds; + + public Factory(Source source, BytesRef in, EvalOperator.ExpressionEvaluator.Factory precision, + Rectangle bounds) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeohexFromLiteralAndFieldAndLiteralEvaluator get(DriverContext context) { + return new StGeohexFromLiteralAndFieldAndLiteralEvaluator(source, in, precision.get(context), bounds, context); + } + + @Override + public String toString() { + return "StGeohexFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldEvaluator.java new file mode 100644 index 0000000000000..4c2d6aa59b284 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldEvaluator.java @@ -0,0 +1,140 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohex}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeohexFromLiteralAndFieldEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final BytesRef in; + + private final EvalOperator.ExpressionEvaluator precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeohexFromLiteralAndFieldEvaluator(Source source, BytesRef in, + EvalOperator.ExpressionEvaluator precision, DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + IntVector precisionVector = precisionBlock.asVector(); + if (precisionVector == null) { + return eval(page.getPositionCount(), precisionBlock); + } + return eval(page.getPositionCount(), precisionVector); + } + } + + public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + try { + result.appendBytesRef(StGeohex.fromLiteralAndField(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + public BytesRefBlock eval(int positionCount, IntVector precisionVector) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + try { + result.appendBytesRef(StGeohex.fromLiteralAndField(this.in, precisionVector.getInt(p))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeohexFromLiteralAndFieldEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final BytesRef in; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + public Factory(Source source, BytesRef in, EvalOperator.ExpressionEvaluator.Factory precision) { + this.source = source; + this.in = in; + this.precision = precision; + } + + @Override + public StGeohexFromLiteralAndFieldEvaluator get(DriverContext context) { + return new StGeohexFromLiteralAndFieldEvaluator(source, in, precision.get(context), context); + } + + @Override + public String toString() { + return "StGeohexFromLiteralAndFieldEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldAndLiteralEvaluator.java new file mode 100644 index 0000000000000..ce115f873b047 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldAndLiteralEvaluator.java @@ -0,0 +1,139 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotile}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeotileFromFieldAndFieldAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator in; + + private final EvalOperator.ExpressionEvaluator precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeotileFromFieldAndFieldAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator in, EvalOperator.ExpressionEvaluator precision, + Rectangle bounds, DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock inBlock = (BytesRefBlock) in.eval(page)) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + return eval(page.getPositionCount(), inBlock, precisionBlock); + } + } + } + + public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!inBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeotile.fromFieldAndFieldAndLiteral(result, p, inBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeotileFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(in, precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory in; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + private final Rectangle bounds; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, + EvalOperator.ExpressionEvaluator.Factory precision, Rectangle bounds) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeotileFromFieldAndFieldAndLiteralEvaluator get(DriverContext context) { + return new StGeotileFromFieldAndFieldAndLiteralEvaluator(source, in.get(context), precision.get(context), bounds, context); + } + + @Override + public String toString() { + return "StGeotileFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldEvaluator.java new file mode 100644 index 0000000000000..c42279a3a977e --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldEvaluator.java @@ -0,0 +1,131 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotile}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeotileFromFieldAndFieldEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator in; + + private final EvalOperator.ExpressionEvaluator precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeotileFromFieldAndFieldEvaluator(Source source, EvalOperator.ExpressionEvaluator in, + EvalOperator.ExpressionEvaluator precision, DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock inBlock = (BytesRefBlock) in.eval(page)) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + return eval(page.getPositionCount(), inBlock, precisionBlock); + } + } + } + + public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!inBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeotile.fromFieldAndField(result, p, inBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeotileFromFieldAndFieldEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(in, precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory in; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, + EvalOperator.ExpressionEvaluator.Factory precision) { + this.source = source; + this.in = in; + this.precision = precision; + } + + @Override + public StGeotileFromFieldAndFieldEvaluator get(DriverContext context) { + return new StGeotileFromFieldAndFieldEvaluator(source, in.get(context), precision.get(context), context); + } + + @Override + public String toString() { + return "StGeotileFromFieldAndFieldEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java new file mode 100644 index 0000000000000..d1716cf51b03f --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java @@ -0,0 +1,125 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotile}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeotileFromFieldAndLiteralAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator in; + + private final int precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeotileFromFieldAndLiteralAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator in, int precision, Rectangle bounds, + DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock inBlock = (BytesRefBlock) in.eval(page)) { + return eval(page.getPositionCount(), inBlock); + } + } + + public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!inBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeotile.fromFieldAndLiteralAndLiteral(result, p, inBlock, this.precision, this.bounds); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeotileFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(in); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory in; + + private final int precision; + + private final Rectangle bounds; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, int precision, + Rectangle bounds) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeotileFromFieldAndLiteralAndLiteralEvaluator get(DriverContext context) { + return new StGeotileFromFieldAndLiteralAndLiteralEvaluator(source, in.get(context), precision, bounds, context); + } + + @Override + public String toString() { + return "StGeotileFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralEvaluator.java new file mode 100644 index 0000000000000..70fe6320362ca --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralEvaluator.java @@ -0,0 +1,117 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotile}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeotileFromFieldAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator wkbBlock; + + private final int precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeotileFromFieldAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator wkbBlock, int precision, DriverContext driverContext) { + this.source = source; + this.wkbBlock = wkbBlock; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock wkbBlockBlock = (BytesRefBlock) wkbBlock.eval(page)) { + return eval(page.getPositionCount(), wkbBlockBlock); + } + } + + public BytesRefBlock eval(int positionCount, BytesRefBlock wkbBlockBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!wkbBlockBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeotile.fromFieldAndLiteral(result, p, wkbBlockBlock, this.precision); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeotileFromFieldAndLiteralEvaluator[" + "wkbBlock=" + wkbBlock + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(wkbBlock); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory wkbBlock; + + private final int precision; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory wkbBlock, + int precision) { + this.source = source; + this.wkbBlock = wkbBlock; + this.precision = precision; + } + + @Override + public StGeotileFromFieldAndLiteralEvaluator get(DriverContext context) { + return new StGeotileFromFieldAndLiteralEvaluator(source, wkbBlock.get(context), precision, context); + } + + @Override + public String toString() { + return "StGeotileFromFieldAndLiteralEvaluator[" + "wkbBlock=" + wkbBlock + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator.java new file mode 100644 index 0000000000000..0ab5083efe77c --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator.java @@ -0,0 +1,140 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotile}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encoded; + + private final EvalOperator.ExpressionEvaluator precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator encoded, EvalOperator.ExpressionEvaluator precision, + Rectangle bounds, DriverContext driverContext) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + return eval(page.getPositionCount(), encodedBlock, precisionBlock); + } + } + } + + public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeotile.fromFieldDocValuesAndFieldAndLiteral(result, p, encodedBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encoded, precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory encoded; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + private final Rectangle bounds; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, + EvalOperator.ExpressionEvaluator.Factory precision, Rectangle bounds) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator get(DriverContext context) { + return new StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator(source, encoded.get(context), precision.get(context), bounds, context); + } + + @Override + public String toString() { + return "StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldEvaluator.java new file mode 100644 index 0000000000000..4769edf3750fd --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldEvaluator.java @@ -0,0 +1,133 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotile}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeotileFromFieldDocValuesAndFieldEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encoded; + + private final EvalOperator.ExpressionEvaluator precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeotileFromFieldDocValuesAndFieldEvaluator(Source source, + EvalOperator.ExpressionEvaluator encoded, EvalOperator.ExpressionEvaluator precision, + DriverContext driverContext) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + return eval(page.getPositionCount(), encodedBlock, precisionBlock); + } + } + } + + public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeotile.fromFieldDocValuesAndField(result, p, encodedBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeotileFromFieldDocValuesAndFieldEvaluator[" + "encoded=" + encoded + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encoded, precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory encoded; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, + EvalOperator.ExpressionEvaluator.Factory precision) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + } + + @Override + public StGeotileFromFieldDocValuesAndFieldEvaluator get(DriverContext context) { + return new StGeotileFromFieldDocValuesAndFieldEvaluator(source, encoded.get(context), precision.get(context), context); + } + + @Override + public String toString() { + return "StGeotileFromFieldDocValuesAndFieldEvaluator[" + "encoded=" + encoded + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java new file mode 100644 index 0000000000000..74cd0b7e6f7bd --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java @@ -0,0 +1,126 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotile}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encoded; + + private final int precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator encoded, int precision, Rectangle bounds, + DriverContext driverContext) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { + return eval(page.getPositionCount(), encodedBlock); + } + } + + public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeotile.fromFieldDocValuesAndLiteralAndLiteral(result, p, encodedBlock, this.precision, this.bounds); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encoded); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory encoded; + + private final int precision; + + private final Rectangle bounds; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, int precision, + Rectangle bounds) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator get(DriverContext context) { + return new StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator(source, encoded.get(context), precision, bounds, context); + } + + @Override + public String toString() { + return "StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralEvaluator.java new file mode 100644 index 0000000000000..277e709b25e7c --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralEvaluator.java @@ -0,0 +1,117 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotile}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeotileFromFieldDocValuesAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encoded; + + private final int precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeotileFromFieldDocValuesAndLiteralEvaluator(Source source, + EvalOperator.ExpressionEvaluator encoded, int precision, DriverContext driverContext) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedBlock = (LongBlock) encoded.eval(page)) { + return eval(page.getPositionCount(), encodedBlock); + } + } + + public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + StGeotile.fromFieldDocValuesAndLiteral(result, p, encodedBlock, this.precision); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeotileFromFieldDocValuesAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encoded); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory encoded; + + private final int precision; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, int precision) { + this.source = source; + this.encoded = encoded; + this.precision = precision; + } + + @Override + public StGeotileFromFieldDocValuesAndLiteralEvaluator get(DriverContext context) { + return new StGeotileFromFieldDocValuesAndLiteralEvaluator(source, encoded.get(context), precision, context); + } + + @Override + public String toString() { + return "StGeotileFromFieldDocValuesAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldAndLiteralEvaluator.java new file mode 100644 index 0000000000000..204769c813a75 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldAndLiteralEvaluator.java @@ -0,0 +1,148 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotile}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeotileFromLiteralAndFieldAndLiteralEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final BytesRef in; + + private final EvalOperator.ExpressionEvaluator precision; + + private final Rectangle bounds; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeotileFromLiteralAndFieldAndLiteralEvaluator(Source source, BytesRef in, + EvalOperator.ExpressionEvaluator precision, Rectangle bounds, DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + IntVector precisionVector = precisionBlock.asVector(); + if (precisionVector == null) { + return eval(page.getPositionCount(), precisionBlock); + } + return eval(page.getPositionCount(), precisionVector); + } + } + + public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + try { + result.appendBytesRef(StGeotile.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds)); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + public BytesRefBlock eval(int positionCount, IntVector precisionVector) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + try { + result.appendBytesRef(StGeotile.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bounds)); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeotileFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final BytesRef in; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + private final Rectangle bounds; + + public Factory(Source source, BytesRef in, EvalOperator.ExpressionEvaluator.Factory precision, + Rectangle bounds) { + this.source = source; + this.in = in; + this.precision = precision; + this.bounds = bounds; + } + + @Override + public StGeotileFromLiteralAndFieldAndLiteralEvaluator get(DriverContext context) { + return new StGeotileFromLiteralAndFieldAndLiteralEvaluator(source, in, precision.get(context), bounds, context); + } + + @Override + public String toString() { + return "StGeotileFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldEvaluator.java new file mode 100644 index 0000000000000..d4637db6ce838 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldEvaluator.java @@ -0,0 +1,140 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.Page; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.compute.operator.Warnings; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotile}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class StGeotileFromLiteralAndFieldEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final BytesRef in; + + private final EvalOperator.ExpressionEvaluator precision; + + private final DriverContext driverContext; + + private Warnings warnings; + + public StGeotileFromLiteralAndFieldEvaluator(Source source, BytesRef in, + EvalOperator.ExpressionEvaluator precision, DriverContext driverContext) { + this.source = source; + this.in = in; + this.precision = precision; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (IntBlock precisionBlock = (IntBlock) precision.eval(page)) { + IntVector precisionVector = precisionBlock.asVector(); + if (precisionVector == null) { + return eval(page.getPositionCount(), precisionBlock); + } + return eval(page.getPositionCount(), precisionVector); + } + } + + public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + if (precisionBlock.isNull(p)) { + result.appendNull(); + continue position; + } + if (precisionBlock.getValueCount(p) != 1) { + if (precisionBlock.getValueCount(p) > 1) { + warnings().registerException(new IllegalArgumentException("single-value function encountered multi-value")); + } + result.appendNull(); + continue position; + } + try { + result.appendBytesRef(StGeotile.fromLiteralAndField(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + public BytesRefBlock eval(int positionCount, IntVector precisionVector) { + try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + try { + result.appendBytesRef(StGeotile.fromLiteralAndField(this.in, precisionVector.getInt(p))); + } catch (IllegalArgumentException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "StGeotileFromLiteralAndFieldEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(precision); + } + + private Warnings warnings() { + if (warnings == null) { + this.warnings = Warnings.createWarnings( + driverContext.warningsMode(), + source.source().getLineNumber(), + source.source().getColumnNumber(), + source.text() + ); + } + return warnings; + } + + static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final BytesRef in; + + private final EvalOperator.ExpressionEvaluator.Factory precision; + + public Factory(Source source, BytesRef in, EvalOperator.ExpressionEvaluator.Factory precision) { + this.source = source; + this.in = in; + this.precision = precision; + } + + @Override + public StGeotileFromLiteralAndFieldEvaluator get(DriverContext context) { + return new StGeotileFromLiteralAndFieldEvaluator(source, in, precision.get(context), context); + } + + @Override + public String toString() { + return "StGeotileFromLiteralAndFieldEvaluator[" + "in=" + in + ", precision=" + precision + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java index 3cb062fb566df..dc991abb83615 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java @@ -59,6 +59,8 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StDistance; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StEnvelope; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohash; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohex; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotile; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StX; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMax; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMin; @@ -219,7 +221,9 @@ private static List spatials() { SpatialIntersects.ENTRY, SpatialWithin.ENTRY, StDistance.ENTRY, - StGeohash.ENTRY + StGeohash.ENTRY, + StGeotile.ENTRY, + StGeohex.ENTRY ); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index e8beaadf998ec..a2f8a40c2af0f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -129,6 +129,8 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StDistance; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StEnvelope; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohash; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohex; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotile; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StX; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMax; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMin; @@ -378,7 +380,9 @@ private static FunctionDefinition[][] functions() { def(StYMin.class, StYMin::new, "st_ymin"), def(StX.class, StX::new, "st_x"), def(StY.class, StY::new, "st_y"), - def(StGeohash.class, StGeohash::new, "st_geohash") }, + def(StGeohash.class, StGeohash::new, "st_geohash"), + def(StGeotile.class, StGeotile::new, "st_geotile"), + def(StGeohex.class, StGeohex::new, "st_geohex") }, // conditional new FunctionDefinition[] { def(Case.class, Case::new, "case") }, // null diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java index 4dbca4a23343c..c65eed8fda268 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java @@ -7,8 +7,13 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; +import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.geometry.utils.SpatialEnvelopeVisitor; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.function.scalar.ScalarFunction; import org.elasticsearch.xpack.esql.core.tree.Source; @@ -20,6 +25,15 @@ import java.util.List; import java.util.Objects; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.THIRD; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isType; +import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isWholeNumber; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; + /** * Spatial functions that take one spatial argument, one parameter and one optional bounds can inherit from this class. * Obvious choices are: StGeohash, StGeotile and StGeohex. @@ -68,6 +82,60 @@ public void writeTo(StreamOutput out) throws IOException { */ public abstract SpatialGridFunction withDocValues(boolean useDocValues); + @Override + protected TypeResolution resolveType() { + if (childrenResolved() == false) { + return new TypeResolution("Unresolved children"); + } + + TypeResolution resolution = isGeoPoint(spatialField(), sourceText()); + if (resolution.unresolved()) { + return resolution; + } + + resolution = isWholeNumber(parameter(), sourceText(), SECOND); + if (resolution.unresolved()) { + return resolution; + } + + if (bounds() != null) { + resolution = isGeoShape(bounds(), sourceText()); + if (resolution.unresolved()) { + return resolution; + } + } + + return TypeResolution.TYPE_RESOLVED; + } + + protected static Expression.TypeResolution isGeoPoint(Expression e, String operationName) { + return isType(e, t -> t.equals(GEO_POINT), operationName, FIRST, GEO_POINT.typeName()); + } + + protected static Expression.TypeResolution isGeoShape(Expression e, String operationName) { + return isType(e, t -> t.equals(GEO_SHAPE), operationName, THIRD, GEO_SHAPE.typeName()); + } + + protected static Rectangle asRectangle(BytesRef boundsBytesRef) { + var geometry = GEO.wkbToGeometry(boundsBytesRef); + if (geometry instanceof Rectangle rectangle) { + return rectangle; + } + var envelope = SpatialEnvelopeVisitor.visitGeo(geometry, SpatialEnvelopeVisitor.WrapLongitude.WRAP); + if (envelope.isPresent()) { + return envelope.get(); + } + throw new IllegalArgumentException("Cannot determine envelope of bounds geometry"); + } + + protected static boolean inBounds(Point point, Rectangle bounds) { + // TODO: consider bounds across the dateline + return point.getX() >= bounds.getMinX() + && point.getY() >= bounds.getMinY() + && point.getX() <= bounds.getMaxX() + && point.getY() <= bounds.getMaxY(); + } + @Override public int hashCode() { // NB: the hashcode is currently used for key generation so @@ -119,4 +187,19 @@ public Expression bounds() { public boolean foldable() { return spatialField.foldable() && parameter.foldable() && (bounds == null || bounds.foldable()); } + + protected static void addGrids(BytesRefBlock.Builder results, List gridIds) { + if (gridIds.isEmpty()) { + results.appendNull(); + } else if (gridIds.size() == 1) { + results.appendBytesRef(gridIds.getFirst()); + } else { + results.beginPositionEntry(); + for (BytesRef gridId : gridIds) { + results.appendBytesRef(gridId); + } + results.endPositionEntry(); + } + } + } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java index 864c62d1f3f3a..2f75fbb295908 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java @@ -18,7 +18,6 @@ import org.elasticsearch.geometry.Point; import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.geometry.utils.Geohash; -import org.elasticsearch.geometry.utils.SpatialEnvelopeVisitor; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.FoldContext; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -31,15 +30,7 @@ import java.io.IOException; import java.util.ArrayList; -import java.util.List; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.THIRD; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isType; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isWholeNumber; -import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT; -import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; @@ -73,7 +64,7 @@ public StGeohash( @Param( name = "bounds", type = { "geo_shape", "geo_point" }, - description = "Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points for top-left and bottom-right", + description = "Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points", optional = true ) Expression bounds ) { @@ -115,52 +106,6 @@ protected NodeInfo info() { return NodeInfo.create(this, StGeohash::new, spatialField, parameter, bounds, false); } - @Override - protected TypeResolution resolveType() { - if (childrenResolved() == false) { - return new TypeResolution("Unresolved children"); - } - - TypeResolution resolution = isGeoPoint(spatialField(), sourceText()); - if (resolution.unresolved()) { - return resolution; - } - - resolution = isWholeNumber(parameter(), sourceText(), SECOND); - if (resolution.unresolved()) { - return resolution; - } - - if (bounds() != null) { - resolution = isGeoShape(bounds(), sourceText()); - if (resolution.unresolved()) { - return resolution; - } - } - - return TypeResolution.TYPE_RESOLVED; - } - - protected static Expression.TypeResolution isGeoPoint(Expression e, String operationName) { - return isType(e, t -> t.equals(GEO_POINT), operationName, FIRST, GEO_POINT.typeName()); - } - - protected static Expression.TypeResolution isGeoShape(Expression e, String operationName) { - return isType(e, t -> t.equals(GEO_SHAPE), operationName, THIRD, GEO_SHAPE.typeName()); - } - - private static Rectangle asRectangle(BytesRef boundsBytesRef) { - var geometry = GEO.wkbToGeometry(boundsBytesRef); - if (geometry instanceof Rectangle rectangle) { - return rectangle; - } - var envelope = SpatialEnvelopeVisitor.visitGeo(geometry, SpatialEnvelopeVisitor.WrapLongitude.WRAP); - if (envelope.isPresent()) { - return envelope.get(); - } - throw new IllegalArgumentException("Cannot determine envelope of bounds geometry"); - } - @Override public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) { if (bounds != null) { @@ -362,14 +307,6 @@ protected static BytesRef calculateGeohash(Point point, int precision, Rectangle return null; } - protected static boolean inBounds(Point point, Rectangle bounds) { - // TODO: consider bounds across the dateline - return point.getX() >= bounds.getMinX() - && point.getY() >= bounds.getMinY() - && point.getX() <= bounds.getMaxX() - && point.getY() <= bounds.getMaxY(); - } - private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision, Rectangle bounds) { int valueCount = wkbBlock.getValueCount(position); if (valueCount < 1) { @@ -422,18 +359,4 @@ private static void fromEncodedLong(BytesRefBlock.Builder results, int position, } } } - - private static void addGrids(BytesRefBlock.Builder results, List gridIds) { - if (gridIds.isEmpty()) { - results.appendNull(); - } else if (gridIds.size() == 1) { - results.appendBytesRef(gridIds.getFirst()); - } else { - results.beginPositionEntry(); - for (BytesRef gridId : gridIds) { - results.appendBytesRef(gridId); - } - results.endPositionEntry(); - } - } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java new file mode 100644 index 0000000000000..26e28750647ce --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java @@ -0,0 +1,358 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.Evaluator; +import org.elasticsearch.compute.ann.Fixed; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.h3.H3; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.expression.FoldContext; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; + +import java.io.IOException; +import java.util.ArrayList; + +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; + +/** + * Calculates the geohex of geo_point geometries. + */ +public class StGeohex extends SpatialGridFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "StGeohex", StGeohex::new); + + @FunctionInfo( + returnType = "keyword", + description = "Calculates the `geohex` of the supplied geo_point at the specified precision.", + examples = @Example(file = "spatial-grid", tag = "st_geohex-grid") + ) + public StGeohex( + Source source, + @Param( + name = "point", + type = { "geo_point" }, + description = "Expression of type `geo_point`. If `null`, the function returns `null`." + ) Expression field, + @Param( + name = "precision", + type = { "integer" }, + description = "Expression of type `integer`. If `null`, the function returns `null`." + ) Expression precision, + @Param( + name = "bounds", + type = { "geo_shape", "geo_point" }, + description = "Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points", + optional = true + ) Expression bounds + ) { + this(source, field, precision, bounds, false); + } + + private StGeohex(Source source, Expression field, Expression precision, Expression bounds, boolean spatialDocValues) { + super(source, field, precision, bounds, spatialDocValues); + } + + private StGeohex(StreamInput in) throws IOException { + super(in, false); + } + + @Override + public SpatialGridFunction withDocValues(boolean useDocValues) { + // Only update the docValues flags if the field is found in the attributes + boolean docValues = this.spatialDocsValues || useDocValues; + return new StGeohex(source(), spatialField, parameter, bounds, docValues); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + public DataType dataType() { + return KEYWORD; + } + + @Override + protected SpatialGridFunction replaceChildren(Expression newSpatialField, Expression newParameter, Expression newBounds) { + return new StGeohex(source(), newSpatialField, newParameter, newBounds); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeohex::new, spatialField, parameter, bounds, false); + } + + @Override + public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) { + if (bounds != null) { + if (bounds.foldable() == false) { + throw new IllegalArgumentException("bounds must foldable"); + } + Rectangle bbox = asRectangle((BytesRef) bounds.fold(toEvaluator.foldCtx())); + if (spatialField().foldable()) { + // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() + var point = (BytesRef) spatialField.fold(toEvaluator.foldCtx()); + return new StGeohexFromLiteralAndFieldAndLiteralEvaluator.Factory(source(), point, toEvaluator.apply(parameter()), bbox); + } else if (parameter().foldable()) { + // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() + int precision = (int) parameter.fold(toEvaluator.foldCtx()); + return spatialDocsValues + ? new StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.Factory( + source(), + toEvaluator.apply(spatialField()), + precision, + bbox + ) + : new StGeohexFromFieldAndLiteralAndLiteralEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + precision, + bbox + ); + } else { + // Both arguments come from index fields + return spatialDocsValues + ? new StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + toEvaluator.apply(parameter), + bbox + ) + : new StGeohexFromFieldAndFieldAndLiteralEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + toEvaluator.apply(parameter), + bbox + ); + } + } else { + if (spatialField().foldable()) { + // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() + var point = (BytesRef) spatialField.fold(toEvaluator.foldCtx()); + return new StGeohexFromLiteralAndFieldEvaluator.Factory(source(), point, toEvaluator.apply(parameter())); + } else if (parameter().foldable()) { + // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() + int precision = (int) parameter.fold(toEvaluator.foldCtx()); + return spatialDocsValues + ? new StGeohexFromFieldDocValuesAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField()), precision) + : new StGeohexFromFieldAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField), precision); + } else { + // Both arguments come from index fields + return spatialDocsValues + ? new StGeohexFromFieldDocValuesAndFieldEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + toEvaluator.apply(parameter) + ) + : new StGeohexFromFieldAndFieldEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + toEvaluator.apply(parameter) + ); + } + } + } + + @Override + public Object fold(FoldContext ctx) { + var point = (BytesRef) spatialField().fold(ctx); + int precision = (int) parameter().fold(ctx); + return calculateGeohex(GEO.wkbAsPoint(point), precision); + } + + @Evaluator(extraName = "FromFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldAndLiteral(BytesRefBlock.Builder results, int p, BytesRefBlock wkbBlock, @Fixed int precision) { + fromWKB(results, p, wkbBlock, precision); + } + + @Evaluator(extraName = "FromFieldDocValuesAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldDocValuesAndLiteral(BytesRefBlock.Builder results, int p, LongBlock encoded, @Fixed int precision) { + fromEncodedLong(results, p, encoded, precision); + } + + @Evaluator(extraName = "FromFieldAndField", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldAndField(BytesRefBlock.Builder results, int p, BytesRefBlock in, int precision) { + fromWKB(results, p, in, precision); + } + + @Evaluator(extraName = "FromFieldDocValuesAndField", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldDocValuesAndField(BytesRefBlock.Builder results, int p, LongBlock encoded, int precision) { + fromEncodedLong(results, p, encoded, precision); + } + + @Evaluator(extraName = "FromLiteralAndField", warnExceptions = { IllegalArgumentException.class }) + static BytesRef fromLiteralAndField(@Fixed BytesRef in, int precision) { + return calculateGeohex(GEO.wkbAsPoint(in), precision); + } + + protected static BytesRef calculateGeohex(Point point, int precision) { + return new BytesRef(H3.geoToH3Address(point.getLat(), point.getLon(), precision)); + } + + @Evaluator(extraName = "FromFieldAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldAndLiteralAndLiteral( + BytesRefBlock.Builder results, + int p, + BytesRefBlock in, + @Fixed int precision, + @Fixed Rectangle bounds + ) { + fromWKB(results, p, in, precision, bounds); + } + + @Evaluator(extraName = "FromFieldDocValuesAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldDocValuesAndLiteralAndLiteral( + BytesRefBlock.Builder results, + int p, + LongBlock encoded, + @Fixed int precision, + @Fixed Rectangle bounds + ) { + fromEncodedLong(results, p, encoded, precision, bounds); + } + + @Evaluator(extraName = "FromFieldAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldAndFieldAndLiteral( + BytesRefBlock.Builder results, + int p, + BytesRefBlock in, + int precision, + @Fixed Rectangle bounds + ) { + fromWKB(results, p, in, precision, bounds); + } + + @Evaluator(extraName = "FromFieldDocValuesAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldDocValuesAndFieldAndLiteral( + BytesRefBlock.Builder results, + int p, + LongBlock encoded, + int precision, + @Fixed Rectangle bounds + ) { + fromEncodedLong(results, p, encoded, precision, bounds); + } + + @Evaluator(extraName = "FromLiteralAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static BytesRef fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed Rectangle bounds) { + return calculateGeohex(GEO.wkbAsPoint(in), precision, bounds); + } + + private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { + int valueCount = wkbBlock.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final BytesRef scratch = new BytesRef(); + final int firstValueIndex = wkbBlock.getFirstValueIndex(position); + if (valueCount == 1) { + results.appendBytesRef(calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision)); + } else { + results.beginPositionEntry(); + for (int i = 0; i < valueCount; i++) { + results.appendBytesRef(calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision)); + } + results.endPositionEntry(); + } + } + } + + private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, int precision) { + int valueCount = encoded.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final int firstValueIndex = encoded.getFirstValueIndex(position); + if (valueCount == 1) { + results.appendBytesRef(calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision)); + } else { + results.beginPositionEntry(); + for (int i = 0; i < valueCount; i++) { + results.appendBytesRef(calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision)); + } + results.endPositionEntry(); + } + } + } + + protected static BytesRef calculateGeohex(Point point, int precision, Rectangle bounds) { + // For points, filtering the point is as good as filtering the tile + if (inBounds(point, bounds)) { + return new BytesRef(H3.geoToH3Address(point.getLat(), point.getLon(), precision)); + } + return null; + } + + private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision, Rectangle bounds) { + int valueCount = wkbBlock.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final BytesRef scratch = new BytesRef(); + final int firstValueIndex = wkbBlock.getFirstValueIndex(position); + if (valueCount == 1) { + BytesRef grid = calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision, bounds); + if (grid == null) { + results.appendNull(); + } else { + results.appendBytesRef(grid); + } + } else { + var gridIds = new ArrayList(valueCount); + for (int i = 0; i < valueCount; i++) { + var grid = calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision, bounds); + if (grid != null) { + gridIds.add(grid); + } + } + addGrids(results, gridIds); + } + } + } + + private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, int precision, Rectangle bounds) { + int valueCount = encoded.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final int firstValueIndex = encoded.getFirstValueIndex(position); + if (valueCount == 1) { + BytesRef grid = calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision, bounds); + if (grid == null) { + results.appendNull(); + } else { + results.appendBytesRef(grid); + } + } else { + var gridIds = new ArrayList(valueCount); + for (int i = 0; i < valueCount; i++) { + var grid = calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision, bounds); + if (grid != null) { + gridIds.add(grid); + } + } + addGrids(results, gridIds); + } + } + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java new file mode 100644 index 0000000000000..bc197cf310fbb --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java @@ -0,0 +1,362 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.Evaluator; +import org.elasticsearch.compute.ann.Fixed; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.expression.FoldContext; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; + +import java.io.IOException; +import java.util.ArrayList; + +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; + +/** + * Calculates the geotile of geo_point geometries. + */ +public class StGeotile extends SpatialGridFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeotile", + StGeotile::new + ); + + @FunctionInfo( + returnType = "keyword", + description = "Calculates the `geotile` of the supplied geo_point at the specified precision.", + examples = @Example(file = "spatial-grid", tag = "st_geotile-grid") + ) + public StGeotile( + Source source, + @Param( + name = "point", + type = { "geo_point" }, + description = "Expression of type `geo_point`. If `null`, the function returns `null`." + ) Expression field, + @Param( + name = "precision", + type = { "integer" }, + description = "Expression of type `integer`. If `null`, the function returns `null`." + ) Expression precision, + @Param( + name = "bounds", + type = { "geo_shape", "geo_point" }, + description = "Bounds to filter the grid tiles, either a geo_shape BBOX or an array", + optional = true + ) Expression bounds + ) { + this(source, field, precision, bounds, false); + } + + private StGeotile(Source source, Expression field, Expression precision, Expression bounds, boolean spatialDocValues) { + super(source, field, precision, bounds, spatialDocValues); + } + + private StGeotile(StreamInput in) throws IOException { + super(in, false); + } + + @Override + public SpatialGridFunction withDocValues(boolean useDocValues) { + // Only update the docValues flags if the field is found in the attributes + boolean docValues = this.spatialDocsValues || useDocValues; + return new StGeotile(source(), spatialField, parameter, bounds, docValues); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + public DataType dataType() { + return KEYWORD; + } + + @Override + protected SpatialGridFunction replaceChildren(Expression newSpatialField, Expression newParameter, Expression newBounds) { + return new StGeotile(source(), newSpatialField, newParameter, newBounds); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeotile::new, spatialField, parameter, bounds, false); + } + + @Override + public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) { + if (bounds != null) { + if (bounds.foldable() == false) { + throw new IllegalArgumentException("bounds must foldable"); + } + Rectangle bbox = asRectangle((BytesRef) bounds.fold(toEvaluator.foldCtx())); + if (spatialField().foldable()) { + // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() + var point = (BytesRef) spatialField.fold(toEvaluator.foldCtx()); + return new StGeotileFromLiteralAndFieldAndLiteralEvaluator.Factory(source(), point, toEvaluator.apply(parameter()), bbox); + } else if (parameter().foldable()) { + // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() + int precision = (int) parameter.fold(toEvaluator.foldCtx()); + return spatialDocsValues + ? new StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.Factory( + source(), + toEvaluator.apply(spatialField()), + precision, + bbox + ) + : new StGeotileFromFieldAndLiteralAndLiteralEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + precision, + bbox + ); + } else { + // Both arguments come from index fields + return spatialDocsValues + ? new StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + toEvaluator.apply(parameter), + bbox + ) + : new StGeotileFromFieldAndFieldAndLiteralEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + toEvaluator.apply(parameter), + bbox + ); + } + } else { + if (spatialField().foldable()) { + // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() + var point = (BytesRef) spatialField.fold(toEvaluator.foldCtx()); + return new StGeotileFromLiteralAndFieldEvaluator.Factory(source(), point, toEvaluator.apply(parameter())); + } else if (parameter().foldable()) { + // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() + int precision = (int) parameter.fold(toEvaluator.foldCtx()); + return spatialDocsValues + ? new StGeotileFromFieldDocValuesAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField()), precision) + : new StGeotileFromFieldAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField), precision); + } else { + // Both arguments come from index fields + return spatialDocsValues + ? new StGeotileFromFieldDocValuesAndFieldEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + toEvaluator.apply(parameter) + ) + : new StGeotileFromFieldAndFieldEvaluator.Factory( + source(), + toEvaluator.apply(spatialField), + toEvaluator.apply(parameter) + ); + } + } + } + + @Override + public Object fold(FoldContext ctx) { + var point = (BytesRef) spatialField().fold(ctx); + int precision = (int) parameter().fold(ctx); + return calculateGeotile(GEO.wkbAsPoint(point), precision); + } + + @Evaluator(extraName = "FromFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldAndLiteral(BytesRefBlock.Builder results, int p, BytesRefBlock wkbBlock, @Fixed int precision) { + fromWKB(results, p, wkbBlock, precision); + } + + @Evaluator(extraName = "FromFieldDocValuesAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldDocValuesAndLiteral(BytesRefBlock.Builder results, int p, LongBlock encoded, @Fixed int precision) { + fromEncodedLong(results, p, encoded, precision); + } + + @Evaluator(extraName = "FromFieldAndField", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldAndField(BytesRefBlock.Builder results, int p, BytesRefBlock in, int precision) { + fromWKB(results, p, in, precision); + } + + @Evaluator(extraName = "FromFieldDocValuesAndField", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldDocValuesAndField(BytesRefBlock.Builder results, int p, LongBlock encoded, int precision) { + fromEncodedLong(results, p, encoded, precision); + } + + @Evaluator(extraName = "FromLiteralAndField", warnExceptions = { IllegalArgumentException.class }) + static BytesRef fromLiteralAndField(@Fixed BytesRef in, int precision) { + return calculateGeotile(GEO.wkbAsPoint(in), precision); + } + + protected static BytesRef calculateGeotile(Point point, int precision) { + return new BytesRef(GeoTileUtils.stringEncode(GeoTileUtils.longEncode(point.getX(), point.getY(), precision))); + } + + @Evaluator(extraName = "FromFieldAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldAndLiteralAndLiteral( + BytesRefBlock.Builder results, + int p, + BytesRefBlock in, + @Fixed int precision, + @Fixed Rectangle bounds + ) { + fromWKB(results, p, in, precision, bounds); + } + + @Evaluator(extraName = "FromFieldDocValuesAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldDocValuesAndLiteralAndLiteral( + BytesRefBlock.Builder results, + int p, + LongBlock encoded, + @Fixed int precision, + @Fixed Rectangle bounds + ) { + fromEncodedLong(results, p, encoded, precision, bounds); + } + + @Evaluator(extraName = "FromFieldAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldAndFieldAndLiteral( + BytesRefBlock.Builder results, + int p, + BytesRefBlock in, + int precision, + @Fixed Rectangle bounds + ) { + fromWKB(results, p, in, precision, bounds); + } + + @Evaluator(extraName = "FromFieldDocValuesAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static void fromFieldDocValuesAndFieldAndLiteral( + BytesRefBlock.Builder results, + int p, + LongBlock encoded, + int precision, + @Fixed Rectangle bounds + ) { + fromEncodedLong(results, p, encoded, precision, bounds); + } + + @Evaluator(extraName = "FromLiteralAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) + static BytesRef fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed Rectangle bounds) { + return calculateGeotile(GEO.wkbAsPoint(in), precision, bounds); + } + + private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { + int valueCount = wkbBlock.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final BytesRef scratch = new BytesRef(); + final int firstValueIndex = wkbBlock.getFirstValueIndex(position); + if (valueCount == 1) { + results.appendBytesRef(calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision)); + } else { + results.beginPositionEntry(); + for (int i = 0; i < valueCount; i++) { + results.appendBytesRef(calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision)); + } + results.endPositionEntry(); + } + } + } + + private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, int precision) { + int valueCount = encoded.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final int firstValueIndex = encoded.getFirstValueIndex(position); + if (valueCount == 1) { + results.appendBytesRef(calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision)); + } else { + results.beginPositionEntry(); + for (int i = 0; i < valueCount; i++) { + results.appendBytesRef(calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision)); + } + results.endPositionEntry(); + } + } + } + + protected static BytesRef calculateGeotile(Point point, int precision, Rectangle bounds) { + // For points, filtering the point is as good as filtering the tile + if (inBounds(point, bounds)) { + return new BytesRef(GeoTileUtils.stringEncode(GeoTileUtils.longEncode(point.getX(), point.getY(), precision))); + } + return null; + } + + private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision, Rectangle bounds) { + int valueCount = wkbBlock.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final BytesRef scratch = new BytesRef(); + final int firstValueIndex = wkbBlock.getFirstValueIndex(position); + if (valueCount == 1) { + BytesRef grid = calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision, bounds); + if (grid == null) { + results.appendNull(); + } else { + results.appendBytesRef(grid); + } + } else { + var gridIds = new ArrayList(valueCount); + for (int i = 0; i < valueCount; i++) { + var grid = calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision, bounds); + if (grid != null) { + gridIds.add(grid); + } + } + addGrids(results, gridIds); + } + } + } + + private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, int precision, Rectangle bounds) { + int valueCount = encoded.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final int firstValueIndex = encoded.getFirstValueIndex(position); + if (valueCount == 1) { + BytesRef grid = calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision, bounds); + if (grid == null) { + results.appendNull(); + } else { + results.appendBytesRef(grid); + } + } else { + var gridIds = new ArrayList(valueCount); + for (int i = 0; i < valueCount; i++) { + var grid = calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision, bounds); + if (grid != null) { + gridIds.add(grid); + } + } + addGrids(results, gridIds); + } + } + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/SpatialDocValuesExtraction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/SpatialDocValuesExtraction.java index 6cbbb126ed690..d55c0f9f17384 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/SpatialDocValuesExtraction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/SpatialDocValuesExtraction.java @@ -16,8 +16,8 @@ import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.expression.function.aggregate.SpatialAggregateFunction; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.BinarySpatialFunction; -import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.SpatialRelatesFunction; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.SpatialGridFunction; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.SpatialRelatesFunction; import org.elasticsearch.xpack.esql.optimizer.LocalPhysicalOptimizerContext; import org.elasticsearch.xpack.esql.optimizer.PhysicalOptimizerRules; import org.elasticsearch.xpack.esql.plan.physical.AggregateExec; From da13b47a7b7db01eb13c06c99f4d469f4d80c561 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Wed, 19 Mar 2025 11:18:10 +0100 Subject: [PATCH 05/34] Add ESQL Capability and reduce test flakiness --- .../src/main/resources/spatial-grid.csv-spec | 77 +++++++++++++++---- .../xpack/esql/action/EsqlCapabilities.java | 5 ++ .../rest-api-spec/test/esql/60_usage.yml | 6 +- 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index 6e86646a83f65..6b13c6454efe1 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -3,6 +3,8 @@ ############################################### geohashLiteral +required_capability: spatial_grid + ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") | EVAL geohash4 = ST_GEOHASH(location, 4), geohash3 = ST_GEOHASH(location, 3), @@ -15,6 +17,8 @@ POINT(12.6493508684508 55.6285017221528) | u3bu | u3b | u3 | u ; geohashLiteralMv +required_capability: spatial_grid + ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] | MV_EXPAND precision | EVAL geohash = ST_GEOHASH(location, precision) @@ -29,6 +33,8 @@ POINT (12.6493508684508 55.6285017221528) | 5 | u3bur ; geohashField +required_capability: spatial_grid + FROM airports | WHERE abbrev == "CPH" | EVAL geohash = ST_GEOHASH(location, 7) @@ -41,6 +47,8 @@ u3buryf | CPH | Copenhagen | POINT (12.6493508684508 55.62850 gridGeohashStatsBy // tag::st_geohash-grid[] +required_capability: spatial_grid + FROM airports | EVAL geohash = ST_GEOHASH(location, 1) | STATS @@ -75,6 +83,8 @@ count:long | centroid:geo_point | geohash:keyword ; gridGeohashStatsByBounds +required_capability: spatial_grid + FROM airports | EVAL geohash = ST_GEOHASH(location, 2, TO_GEOSHAPE("BBOX(0, 12, 60, 30)")) | WHERE geohash IS NOT NULL @@ -95,6 +105,8 @@ count:long | centroid:geo_point | geohash:keyword ; gridGeohashStatsByWhereUK +required_capability: spatial_grid + FROM airports | WHERE ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) | EVAL geohash = ST_GEOHASH(location, 2) @@ -111,6 +123,8 @@ count:long | centroid:geo_point | geohash:keyword ; gridGeohashStatsByBoundsUK +required_capability: spatial_grid + FROM airports | EVAL bounds = ST_ENVELOPE(TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) | EVAL geohash = ST_GEOHASH(location, 2, bounds) @@ -129,6 +143,8 @@ count:long | centroid:geo_point | geohash:keyword ; gridGeohashInStatsBy +required_capability: spatial_grid + FROM airports | STATS count = COUNT(location), @@ -153,6 +169,8 @@ count:long | centroid:geo_point ; gridGeohashInStatsByWhereUK +required_capability: spatial_grid + FROM airports | WHERE ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) | STATS @@ -173,6 +191,8 @@ count:long | centroid:geo_point ############################################### geotileLiteral +required_capability: spatial_grid + ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") | EVAL geotile4 = ST_GEOTILE(location, 4), geotile3 = ST_GEOTILE(location, 3), @@ -185,6 +205,8 @@ POINT (12.6493508684508 55.6285017221528) | 4/8/5 | 3/4/2 ; geotileLiteralMv +required_capability: spatial_grid + ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] | MV_EXPAND precision | EVAL geotile = ST_GEOTILE(location, precision) @@ -199,6 +221,8 @@ POINT (12.6493508684508 55.6285017221528) | 5 | 5/17/10 ; geotileField +required_capability: spatial_grid + FROM airports | WHERE abbrev == "CPH" | EVAL geotile = ST_GEOTILE(location, 7) @@ -211,6 +235,8 @@ geotile:keyword | abbrev:keyword | name:text | location:geo_point gridGeotileStatsBy // tag::st_geotile-grid[] +required_capability: spatial_grid + FROM airports | EVAL geotile = ST_GEOTILE(location, 2) | STATS @@ -238,6 +264,8 @@ count:long | centroid:geo_point | geotile:keyword ; gridGeotileStatsByBounds +required_capability: spatial_grid + FROM airports | EVAL geotile = ST_GEOTILE(location, 3, TO_GEOSHAPE("BBOX(0, 12, 60, 30)")) | WHERE geotile IS NOT NULL @@ -254,6 +282,8 @@ count:long | centroid:geo_point | geotile:keyword ; gridGeotileStatsByWhereUK +required_capability: spatial_grid + FROM airports | WHERE ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) | EVAL geotile = ST_GEOTILE(location, 4) @@ -270,6 +300,8 @@ count:long | centroid:geo_point | geotile:keyword ; gridGeotileStatsByBoundsUK +required_capability: spatial_grid + FROM airports | EVAL bounds = ST_ENVELOPE(TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) | EVAL geotile = ST_GEOTILE(location, 2, bounds) @@ -287,6 +319,8 @@ count:long | centroid:geo_point | geotile:keyword ; gridGeotileInStatsBy +required_capability: spatial_grid + FROM airports | STATS count = COUNT(location), @@ -305,6 +339,8 @@ count:long | centroid:geo_point ; gridGeotileInStatsByWhereUK +required_capability: spatial_grid + FROM airports | WHERE ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) | STATS @@ -324,6 +360,8 @@ count:long | centroid:geo_point ############################################### geohexLiteral +required_capability: spatial_grid + ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") | EVAL geohex4 = ST_GEOHEX(location, 4), geohex3 = ST_GEOHEX(location, 3), @@ -336,6 +374,8 @@ POINT (12.6493508684508 55.6285017221528) | 841f059ffffffff | 831f05fffffffff | ; geohexLiteralMv +required_capability: spatial_grid + ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] | MV_EXPAND precision | EVAL geohex = ST_GEOHEX(location, precision) @@ -350,6 +390,8 @@ POINT (12.6493508684508 55.6285017221528) | 5 | 851f0583fffffff ; geohexField +required_capability: spatial_grid + FROM airports | WHERE abbrev == "CPH" | EVAL geohex = ST_GEOHEX(location, 7) @@ -362,6 +404,8 @@ geohex:keyword | abbrev:keyword | name:text | location:geo_point gridGeohexStatsBy // tag::st_geohex-grid[] +required_capability: spatial_grid + FROM airports | EVAL geohex = ST_GEOHEX(location, 1) | STATS @@ -390,6 +434,8 @@ count:long | centroid:geo_point | geohex:keyword ; gridGeohexStatsByBounds +required_capability: spatial_grid + FROM airports | EVAL geohex = ST_GEOHEX(location, 1, TO_GEOSHAPE("BBOX(0, 12, 60, 30)")) | WHERE geohex IS NOT NULL @@ -413,6 +459,8 @@ count:long | centroid:geo_point | geohex:keyword ; gridGeohexStatsByWhereUK +required_capability: spatial_grid + FROM airports | WHERE ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) | EVAL geohex = ST_GEOHEX(location, 1) @@ -431,6 +479,8 @@ count:long | centroid:geo_point | geohex:keyword ; gridGeohexStatsByBoundsUK +required_capability: spatial_grid + FROM airports | EVAL bounds = ST_ENVELOPE(TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) | EVAL geohex = ST_GEOHEX(location, 2, bounds) @@ -455,37 +505,36 @@ count:long | centroid:geo_point | geohex:keyword 1 | POINT (-0.16296171583235264 51.1557567352429) | 82194ffffffffff ; -gridGeohexInStatsBy +gridGeohexInStatsByBounds +required_capability: spatial_grid + FROM airports | STATS count = COUNT(location), centroid = ST_CENTROID_AGG(location) - BY ST_GEOHEX(location, 1) + BY ST_GEOHEX(location, 2, TO_GEOSHAPE("BBOX(0, 12, 60, 30)")) +| WHERE count > 3 | SORT count DESC | KEEP count, centroid | LIMIT 10 ; -count:long | centroid:geo_point -22 | POINT (7.250850197689777 48.21363834643059) -18 | POINT (-80.64959161449224 40.04119813675061) -17 | POINT (-0.7606179875266903 52.86413913565304) -13 | POINT (22.53157936179867 41.98255742864254) -13 | POINT (78.30096947387435 26.073904778951636) -12 | POINT (-100.30120467301458 20.114154297625646) -12 | POINT (-76.39781514415517 45.16300531569868) -11 | POINT (-99.4237939513881 27.100012352774765) -11 | POINT (-83.42379064553164 33.18388901439241) -11 | POINT (18.037187419831753 48.66540593306788) +count:long | centroid:geo_point +850 | POINT (-0.347950274354833 23.284863485719132) +6 | POINT (5.582276992499828 50.72238312335685) +5 | POINT (8.6918301936239 45.19817395694554) ; gridGeohexInStatsByWhereUK +required_capability: spatial_grid + FROM airports | WHERE ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) | STATS count = COUNT(location), centroid = ST_CENTROID_AGG(location) BY ST_GEOHEX(location, 1) +| WHERE count > 1 | KEEP count, centroid | SORT count DESC ; @@ -493,6 +542,4 @@ FROM airports count:long | centroid:geo_point 13 | POINT (-2.283508819169723 53.28242553254733) 2 | POINT (-3.482485176064074 58.24696456314996) -1 | POINT (-6.216169511899352 54.66155751608312) -1 | POINT (-1.2880607228726149 59.87668995279819) ; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index 5a6d81cda1f02..16e2824ecb2dc 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java @@ -363,6 +363,11 @@ public enum Cap { */ ST_ENVELOPE, + /** + * Support ST_GEOHASH, ST_GEOTILE and ST_GEOHEX functions + */ + SPATIAL_GRID, + /** * Fix to GROK and DISSECT that allows extracting attributes with the same name as the input * https://github.com/elastic/elasticsearch/issues/110184 diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml index 40e93bafb8998..d6706e6bd9e32 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml @@ -120,8 +120,8 @@ setup: - gt: {esql.functions.to_long: $functions_to_long} - match: {esql.functions.coalesce: $functions_coalesce} - gt: {esql.functions.categorize: $functions_categorize} - # Testing for the entire function set isn't feasbile, so we just check that we return the correct count as an approximation. - - length: {esql.functions: 138} # check the "sister" test below for a likely update to the same esql.functions length check + # Testing for the entire function set isn't feasible, so we just check that we return the correct count as an approximation. + - length: {esql.functions: 140} # check the "sister" test below for a likely update to the same esql.functions length check --- "Basic ESQL usage output (telemetry) non-snapshot version": @@ -218,7 +218,7 @@ setup: - gt: {esql.functions.to_long: $functions_to_long} - match: {esql.functions.coalesce: $functions_coalesce} - gt: {esql.functions.categorize: $functions_categorize} - - length: {esql.functions: 131} # check the "sister" test above for a likely update to the same esql.functions length check + - length: {esql.functions: 133} # check the "sister" test above for a likely update to the same esql.functions length check --- took: From 9c83b64cdfac6d0e71a53f441369f2806a298b21 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Thu, 20 Mar 2025 11:52:17 +0100 Subject: [PATCH 06/34] Fix failing EsqlNodeSubclassTests from incorrect NodeInfo --- .../esql/expression/function/scalar/spatial/StGeohash.java | 2 +- .../xpack/esql/expression/function/scalar/spatial/StGeohex.java | 2 +- .../esql/expression/function/scalar/spatial/StGeotile.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java index 2f75fbb295908..a38fcf057ef13 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java @@ -103,7 +103,7 @@ protected SpatialGridFunction replaceChildren(Expression newSpatialField, Expres @Override protected NodeInfo info() { - return NodeInfo.create(this, StGeohash::new, spatialField, parameter, bounds, false); + return NodeInfo.create(this, StGeohash::new, spatialField, parameter, bounds); } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java index 26e28750647ce..0b6566bbc3791 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java @@ -99,7 +99,7 @@ protected SpatialGridFunction replaceChildren(Expression newSpatialField, Expres @Override protected NodeInfo info() { - return NodeInfo.create(this, StGeohex::new, spatialField, parameter, bounds, false); + return NodeInfo.create(this, StGeohex::new, spatialField, parameter, bounds); } @Override diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java index bc197cf310fbb..0b96cefb7dbd9 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java @@ -103,7 +103,7 @@ protected SpatialGridFunction replaceChildren(Expression newSpatialField, Expres @Override protected NodeInfo info() { - return NodeInfo.create(this, StGeotile::new, spatialField, parameter, bounds, false); + return NodeInfo.create(this, StGeotile::new, spatialField, parameter, bounds); } @Override From 04b2c8915978607f16ca110874aedac0bd820cf4 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Mon, 7 Apr 2025 14:43:52 +0200 Subject: [PATCH 07/34] Use GeoTileBoundedPredicate for geotile bounds filtering --- .../geogrid/GeoTileBoundedPredicate.java | 4 ++ .../src/main/resources/spatial-grid.csv-spec | 12 ++-- ...eFromFieldAndFieldAndLiteralEvaluator.java | 22 +++--- ...romFieldAndLiteralAndLiteralEvaluator.java | 26 +++---- ...dDocValuesAndFieldAndLiteralEvaluator.java | 22 +++--- ...ocValuesAndLiteralAndLiteralEvaluator.java | 26 +++---- ...romLiteralAndFieldAndLiteralEvaluator.java | 25 +++---- .../scalar/spatial/SpatialGridFunction.java | 13 ++++ .../function/scalar/spatial/StGeotile.java | 68 ++++++++++--------- 9 files changed, 114 insertions(+), 104 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoTileBoundedPredicate.java b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoTileBoundedPredicate.java index cc250b887b1bb..468d6b2401f6f 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoTileBoundedPredicate.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoTileBoundedPredicate.java @@ -56,6 +56,10 @@ public GeoTileBoundedPredicate(int precision, GeoBoundingBox bbox) { } } + public int precision() { + return precision; + } + /** Does the provided bounds crosses the dateline */ public boolean crossesDateline() { return crossesDateline; diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index 6b13c6454efe1..56ea1a4511b46 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -277,8 +277,8 @@ FROM airports ; count:long | centroid:geo_point | geotile:keyword -36 | POINT (6.52789649553597 48.36977661703713) | 3/4/2 -5 | POINT (6.707012789323926 37.031419202685356) | 3/4/3 +100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 +79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 ; gridGeotileStatsByWhereUK @@ -304,7 +304,7 @@ required_capability: spatial_grid FROM airports | EVAL bounds = ST_ENVELOPE(TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))")) -| EVAL geotile = ST_GEOTILE(location, 2, bounds) +| EVAL geotile = ST_GEOTILE(location, 4, bounds) | WHERE geotile IS NOT NULL | STATS count = COUNT(location), @@ -314,8 +314,10 @@ FROM airports ; count:long | centroid:geo_point | geotile:keyword -20 | POINT (-3.3905635555274785 54.08363554766402) | 2/1/1 -1 | POINT (0.15865350142121315 49.36166098807007) | 2/2/1 +56 | POINT (10.54233039047436 47.85997457644304) | 4/8/5 +18 | POINT (-3.5578574100509286 51.27018998377025) | 4/7/5 +11 | POINT (14.310833624648778 59.85619530801407) | 4/8/4 +7 | POINT (-6.466632609122565 59.19681839378817) | 4/7/4 ; gridGeotileInStatsBy diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldAndLiteralEvaluator.java index ce115f873b047..5e8d671795eae 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldAndLiteralEvaluator.java @@ -7,6 +7,7 @@ import java.lang.IllegalArgumentException; import java.lang.Override; import java.lang.String; +import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; @@ -15,7 +16,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -29,7 +29,7 @@ public final class StGeotileFromFieldAndFieldAndLiteralEvaluator implements Eval private final EvalOperator.ExpressionEvaluator precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; private final DriverContext driverContext; @@ -37,11 +37,11 @@ public final class StGeotileFromFieldAndFieldAndLiteralEvaluator implements Eval public StGeotileFromFieldAndFieldAndLiteralEvaluator(Source source, EvalOperator.ExpressionEvaluator in, EvalOperator.ExpressionEvaluator precision, - Rectangle bounds, DriverContext driverContext) { + GeoBoundingBox bbox, DriverContext driverContext) { this.source = source; this.in = in; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; this.driverContext = driverContext; } @@ -77,7 +77,7 @@ public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock pre continue position; } try { - StGeotile.fromFieldAndFieldAndLiteral(result, p, inBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds); + StGeotile.fromFieldAndFieldAndLiteral(result, p, inBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bbox); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -89,7 +89,7 @@ public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock pre @Override public String toString() { - return "StGeotileFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeotileFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bbox=" + bbox + "]"; } @Override @@ -116,24 +116,24 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, - EvalOperator.ExpressionEvaluator.Factory precision, Rectangle bounds) { + EvalOperator.ExpressionEvaluator.Factory precision, GeoBoundingBox bbox) { this.source = source; this.in = in; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; } @Override public StGeotileFromFieldAndFieldAndLiteralEvaluator get(DriverContext context) { - return new StGeotileFromFieldAndFieldAndLiteralEvaluator(source, in.get(context), precision.get(context), bounds, context); + return new StGeotileFromFieldAndFieldAndLiteralEvaluator(source, in.get(context), precision.get(context), bbox, context); } @Override public String toString() { - return "StGeotileFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeotileFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bbox=" + bbox + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java index d1716cf51b03f..dea9b3fa439a9 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java @@ -14,7 +14,7 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileBoundedPredicate; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -26,20 +26,17 @@ public final class StGeotileFromFieldAndLiteralAndLiteralEvaluator implements Ev private final EvalOperator.ExpressionEvaluator in; - private final int precision; - - private final Rectangle bounds; + private final GeoTileBoundedPredicate bounds; private final DriverContext driverContext; private Warnings warnings; public StGeotileFromFieldAndLiteralAndLiteralEvaluator(Source source, - EvalOperator.ExpressionEvaluator in, int precision, Rectangle bounds, + EvalOperator.ExpressionEvaluator in, GeoTileBoundedPredicate bounds, DriverContext driverContext) { this.source = source; this.in = in; - this.precision = precision; this.bounds = bounds; this.driverContext = driverContext; } @@ -63,7 +60,7 @@ public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock) { continue position; } try { - StGeotile.fromFieldAndLiteralAndLiteral(result, p, inBlock, this.precision, this.bounds); + StGeotile.fromFieldAndLiteralAndLiteral(result, p, inBlock, this.bounds); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -75,7 +72,7 @@ public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock) { @Override public String toString() { - return "StGeotileFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeotileFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", bounds=" + bounds + "]"; } @Override @@ -100,26 +97,23 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory in; - private final int precision; - - private final Rectangle bounds; + private final GeoTileBoundedPredicate bounds; - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, int precision, - Rectangle bounds) { + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, + GeoTileBoundedPredicate bounds) { this.source = source; this.in = in; - this.precision = precision; this.bounds = bounds; } @Override public StGeotileFromFieldAndLiteralAndLiteralEvaluator get(DriverContext context) { - return new StGeotileFromFieldAndLiteralAndLiteralEvaluator(source, in.get(context), precision, bounds, context); + return new StGeotileFromFieldAndLiteralAndLiteralEvaluator(source, in.get(context), bounds, context); } @Override public String toString() { - return "StGeotileFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeotileFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", bounds=" + bounds + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator.java index 0ab5083efe77c..3e0438f22e556 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator.java @@ -7,6 +7,7 @@ import java.lang.IllegalArgumentException; import java.lang.Override; import java.lang.String; +import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; @@ -16,7 +17,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -30,7 +30,7 @@ public final class StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator implem private final EvalOperator.ExpressionEvaluator precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; private final DriverContext driverContext; @@ -38,11 +38,11 @@ public final class StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator implem public StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator(Source source, EvalOperator.ExpressionEvaluator encoded, EvalOperator.ExpressionEvaluator precision, - Rectangle bounds, DriverContext driverContext) { + GeoBoundingBox bbox, DriverContext driverContext) { this.source = source; this.encoded = encoded; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; this.driverContext = driverContext; } @@ -78,7 +78,7 @@ public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock pr continue position; } try { - StGeotile.fromFieldDocValuesAndFieldAndLiteral(result, p, encodedBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds); + StGeotile.fromFieldDocValuesAndFieldAndLiteral(result, p, encodedBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bbox); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -90,7 +90,7 @@ public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock pr @Override public String toString() { - return "StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bbox=" + bbox + "]"; } @Override @@ -117,24 +117,24 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, - EvalOperator.ExpressionEvaluator.Factory precision, Rectangle bounds) { + EvalOperator.ExpressionEvaluator.Factory precision, GeoBoundingBox bbox) { this.source = source; this.encoded = encoded; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; } @Override public StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator get(DriverContext context) { - return new StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator(source, encoded.get(context), precision.get(context), bounds, context); + return new StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator(source, encoded.get(context), precision.get(context), bbox, context); } @Override public String toString() { - return "StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bbox=" + bbox + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java index 74cd0b7e6f7bd..7b8aa21624e2a 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java @@ -15,7 +15,7 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileBoundedPredicate; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -27,20 +27,17 @@ public final class StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator impl private final EvalOperator.ExpressionEvaluator encoded; - private final int precision; - - private final Rectangle bounds; + private final GeoTileBoundedPredicate bounds; private final DriverContext driverContext; private Warnings warnings; public StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator(Source source, - EvalOperator.ExpressionEvaluator encoded, int precision, Rectangle bounds, + EvalOperator.ExpressionEvaluator encoded, GeoTileBoundedPredicate bounds, DriverContext driverContext) { this.source = source; this.encoded = encoded; - this.precision = precision; this.bounds = bounds; this.driverContext = driverContext; } @@ -64,7 +61,7 @@ public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { continue position; } try { - StGeotile.fromFieldDocValuesAndLiteralAndLiteral(result, p, encodedBlock, this.precision, this.bounds); + StGeotile.fromFieldDocValuesAndLiteralAndLiteral(result, p, encodedBlock, this.bounds); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -76,7 +73,7 @@ public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { @Override public String toString() { - return "StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", bounds=" + bounds + "]"; } @Override @@ -101,26 +98,23 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory encoded; - private final int precision; - - private final Rectangle bounds; + private final GeoTileBoundedPredicate bounds; - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, int precision, - Rectangle bounds) { + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, + GeoTileBoundedPredicate bounds) { this.source = source; this.encoded = encoded; - this.precision = precision; this.bounds = bounds; } @Override public StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator get(DriverContext context) { - return new StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator(source, encoded.get(context), precision, bounds, context); + return new StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator(source, encoded.get(context), bounds, context); } @Override public String toString() { - return "StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", bounds=" + bounds + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldAndLiteralEvaluator.java index 204769c813a75..c606734c1616d 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldAndLiteralEvaluator.java @@ -8,6 +8,7 @@ import java.lang.Override; import java.lang.String; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; @@ -17,7 +18,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -31,18 +31,19 @@ public final class StGeotileFromLiteralAndFieldAndLiteralEvaluator implements Ev private final EvalOperator.ExpressionEvaluator precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; private final DriverContext driverContext; private Warnings warnings; public StGeotileFromLiteralAndFieldAndLiteralEvaluator(Source source, BytesRef in, - EvalOperator.ExpressionEvaluator precision, Rectangle bounds, DriverContext driverContext) { + EvalOperator.ExpressionEvaluator precision, GeoBoundingBox bbox, + DriverContext driverContext) { this.source = source; this.in = in; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; this.driverContext = driverContext; } @@ -72,7 +73,7 @@ public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { continue position; } try { - result.appendBytesRef(StGeotile.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds)); + result.appendBytesRef(StGeotile.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bbox)); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -86,7 +87,7 @@ public BytesRefBlock eval(int positionCount, IntVector precisionVector) { try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { try { - result.appendBytesRef(StGeotile.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bounds)); + result.appendBytesRef(StGeotile.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bbox)); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -98,7 +99,7 @@ public BytesRefBlock eval(int positionCount, IntVector precisionVector) { @Override public String toString() { - return "StGeotileFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeotileFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bbox=" + bbox + "]"; } @Override @@ -125,24 +126,24 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; public Factory(Source source, BytesRef in, EvalOperator.ExpressionEvaluator.Factory precision, - Rectangle bounds) { + GeoBoundingBox bbox) { this.source = source; this.in = in; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; } @Override public StGeotileFromLiteralAndFieldAndLiteralEvaluator get(DriverContext context) { - return new StGeotileFromLiteralAndFieldAndLiteralEvaluator(source, in, precision.get(context), bounds, context); + return new StGeotileFromLiteralAndFieldAndLiteralEvaluator(source, in, precision.get(context), bbox, context); } @Override public String toString() { - return "StGeotileFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeotileFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bbox=" + bbox + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java index c65eed8fda268..39c9c213d95b1 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.geo.GeoBoundingBox; +import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.compute.data.BytesRefBlock; @@ -128,6 +130,17 @@ protected static Rectangle asRectangle(BytesRef boundsBytesRef) { throw new IllegalArgumentException("Cannot determine envelope of bounds geometry"); } + protected static GeoBoundingBox asGeoBoundingBox(BytesRef boundsBytesRef) { + return asGeoBoundingBox(asRectangle(boundsBytesRef)); + } + + protected static GeoBoundingBox asGeoBoundingBox(Rectangle rectangle) { + return new GeoBoundingBox( + new GeoPoint(rectangle.getMaxLat(), rectangle.getMinLon()), + new GeoPoint(rectangle.getMinLat(), rectangle.getMaxLon()) + ); + } + protected static boolean inBounds(Point point, Rectangle bounds) { // TODO: consider bounds across the dateline return point.getX() >= bounds.getMinX() diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java index 0b96cefb7dbd9..4be0cbccb090c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java @@ -8,6 +8,7 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; @@ -16,7 +17,7 @@ import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.geometry.Point; -import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileBoundedPredicate; import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.FoldContext; @@ -110,9 +111,9 @@ protected NodeInfo info() { public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) { if (bounds != null) { if (bounds.foldable() == false) { - throw new IllegalArgumentException("bounds must foldable"); + throw new IllegalArgumentException("bounds must be foldable"); } - Rectangle bbox = asRectangle((BytesRef) bounds.fold(toEvaluator.foldCtx())); + GeoBoundingBox bbox = asGeoBoundingBox((BytesRef) bounds.fold(toEvaluator.foldCtx())); if (spatialField().foldable()) { // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() var point = (BytesRef) spatialField.fold(toEvaluator.foldCtx()); @@ -120,19 +121,14 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua } else if (parameter().foldable()) { // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() int precision = (int) parameter.fold(toEvaluator.foldCtx()); + GeoTileBoundedPredicate bounds = new GeoTileBoundedPredicate(precision, bbox); return spatialDocsValues ? new StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.Factory( source(), toEvaluator.apply(spatialField()), - precision, - bbox + bounds ) - : new StGeotileFromFieldAndLiteralAndLiteralEvaluator.Factory( - source(), - toEvaluator.apply(spatialField), - precision, - bbox - ); + : new StGeotileFromFieldAndLiteralAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField), bounds); } else { // Both arguments come from index fields return spatialDocsValues @@ -157,6 +153,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua } else if (parameter().foldable()) { // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() int precision = (int) parameter.fold(toEvaluator.foldCtx()); + // TODO: Use GeoTileBoundedPredicate return spatialDocsValues ? new StGeotileFromFieldDocValuesAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField()), precision) : new StGeotileFromFieldAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField), precision); @@ -181,6 +178,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua public Object fold(FoldContext ctx) { var point = (BytesRef) spatialField().fold(ctx); int precision = (int) parameter().fold(ctx); + // TODO: Use GeoTileBoundedPredicate return calculateGeotile(GEO.wkbAsPoint(point), precision); } @@ -218,10 +216,9 @@ static void fromFieldAndLiteralAndLiteral( BytesRefBlock.Builder results, int p, BytesRefBlock in, - @Fixed int precision, - @Fixed Rectangle bounds + @Fixed GeoTileBoundedPredicate bounds ) { - fromWKB(results, p, in, precision, bounds); + fromWKB(results, p, in, bounds); } @Evaluator(extraName = "FromFieldDocValuesAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) @@ -229,10 +226,9 @@ static void fromFieldDocValuesAndLiteralAndLiteral( BytesRefBlock.Builder results, int p, LongBlock encoded, - @Fixed int precision, - @Fixed Rectangle bounds + @Fixed GeoTileBoundedPredicate bounds ) { - fromEncodedLong(results, p, encoded, precision, bounds); + fromEncodedLong(results, p, encoded, bounds); } @Evaluator(extraName = "FromFieldAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) @@ -241,9 +237,10 @@ static void fromFieldAndFieldAndLiteral( int p, BytesRefBlock in, int precision, - @Fixed Rectangle bounds + @Fixed GeoBoundingBox bbox ) { - fromWKB(results, p, in, precision, bounds); + GeoTileBoundedPredicate bounds = new GeoTileBoundedPredicate(precision, bbox); + fromWKB(results, p, in, bounds); } @Evaluator(extraName = "FromFieldDocValuesAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) @@ -252,14 +249,16 @@ static void fromFieldDocValuesAndFieldAndLiteral( int p, LongBlock encoded, int precision, - @Fixed Rectangle bounds + @Fixed GeoBoundingBox bbox ) { - fromEncodedLong(results, p, encoded, precision, bounds); + GeoTileBoundedPredicate bounds = new GeoTileBoundedPredicate(precision, bbox); + fromEncodedLong(results, p, encoded, bounds); } @Evaluator(extraName = "FromLiteralAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static BytesRef fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed Rectangle bounds) { - return calculateGeotile(GEO.wkbAsPoint(in), precision, bounds); + static BytesRef fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed GeoBoundingBox bbox) { + GeoTileBoundedPredicate bounds = new GeoTileBoundedPredicate(precision, bbox); + return calculateGeotile(GEO.wkbAsPoint(in), bounds); } private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { @@ -299,15 +298,18 @@ private static void fromEncodedLong(BytesRefBlock.Builder results, int position, } } - protected static BytesRef calculateGeotile(Point point, int precision, Rectangle bounds) { - // For points, filtering the point is as good as filtering the tile - if (inBounds(point, bounds)) { - return new BytesRef(GeoTileUtils.stringEncode(GeoTileUtils.longEncode(point.getX(), point.getY(), precision))); + protected static BytesRef calculateGeotile(Point point, GeoTileBoundedPredicate bounds) { + final int tiles = 1 << GeoTileUtils.checkPrecisionRange(bounds.precision()); + final int x = GeoTileUtils.getXTile(point.getX(), tiles); + final int y = GeoTileUtils.getYTile(point.getY(), tiles); + if (bounds.validTile(x, y, bounds.precision())) { + final long encoded = GeoTileUtils.longEncodeTiles(bounds.precision(), x, y); + return new BytesRef(GeoTileUtils.stringEncode(encoded)); } return null; } - private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision, Rectangle bounds) { + private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, GeoTileBoundedPredicate bounds) { int valueCount = wkbBlock.getValueCount(position); if (valueCount < 1) { results.appendNull(); @@ -315,7 +317,7 @@ private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRe final BytesRef scratch = new BytesRef(); final int firstValueIndex = wkbBlock.getFirstValueIndex(position); if (valueCount == 1) { - BytesRef grid = calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision, bounds); + BytesRef grid = calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), bounds); if (grid == null) { results.appendNull(); } else { @@ -324,7 +326,7 @@ private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRe } else { var gridIds = new ArrayList(valueCount); for (int i = 0; i < valueCount; i++) { - var grid = calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision, bounds); + var grid = calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), bounds); if (grid != null) { gridIds.add(grid); } @@ -334,14 +336,14 @@ private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRe } } - private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, int precision, Rectangle bounds) { + private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, GeoTileBoundedPredicate bounds) { int valueCount = encoded.getValueCount(position); if (valueCount < 1) { results.appendNull(); } else { final int firstValueIndex = encoded.getFirstValueIndex(position); if (valueCount == 1) { - BytesRef grid = calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision, bounds); + BytesRef grid = calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex)), bounds); if (grid == null) { results.appendNull(); } else { @@ -350,7 +352,7 @@ private static void fromEncodedLong(BytesRefBlock.Builder results, int position, } else { var gridIds = new ArrayList(valueCount); for (int i = 0; i < valueCount; i++) { - var grid = calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision, bounds); + var grid = calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), bounds); if (grid != null) { gridIds.add(grid); } From c1003e1ef8b2ff31b82923456869055bbff8ce7c Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 8 Apr 2025 10:46:02 +0200 Subject: [PATCH 08/34] Added ST_GEOXXX_TO_LONG, _TO_STRING and _TO_GEOSHAPE functions This is because we want to move the ST_GEOXXX functions to produce longs only, for performance reasons, and need the convenience functions to display these either as strings or as actual shapes. This is both useful to the users, as well as easier to do manual tests where we visualize the results on a map. --- .../src/main/resources/spatial-grid.csv-spec | 70 ++++++++++ .../StGeohashToGeoShapeFromLongEvaluator.java | 124 +++++++++++++++++ ...tGeohashToGeoShapeFromStringEvaluator.java | 125 +++++++++++++++++ .../StGeohashToLongFromStringEvaluator.java | 126 ++++++++++++++++++ .../StGeohashToStringFromLongEvaluator.java | 124 +++++++++++++++++ .../StGeohexToGeoShapeFromLongEvaluator.java | 124 +++++++++++++++++ ...StGeohexToGeoShapeFromStringEvaluator.java | 125 +++++++++++++++++ .../StGeohexToLongFromStringEvaluator.java | 126 ++++++++++++++++++ .../StGeohexToStringFromLongEvaluator.java | 124 +++++++++++++++++ .../StGeotileToGeoShapeFromLongEvaluator.java | 124 +++++++++++++++++ ...tGeotileToGeoShapeFromStringEvaluator.java | 125 +++++++++++++++++ .../StGeotileToLongFromLongEvaluator.java | 126 ++++++++++++++++++ .../StGeotileToLongFromStringEvaluator.java | 126 ++++++++++++++++++ .../StGeotileToStringFromLongEvaluator.java | 124 +++++++++++++++++ .../function/EsqlFunctionRegistry.java | 20 ++- .../convert/AbstractConvertFunction.java | 2 +- .../scalar/spatial/StGeohashToGeoShape.java | 105 +++++++++++++++ .../scalar/spatial/StGeohashToLong.java | 93 +++++++++++++ .../scalar/spatial/StGeohashToString.java | 93 +++++++++++++ .../scalar/spatial/StGeohexToGeoShape.java | 121 +++++++++++++++++ .../scalar/spatial/StGeohexToLong.java | 93 +++++++++++++ .../scalar/spatial/StGeohexToString.java | 93 +++++++++++++ .../scalar/spatial/StGeotileToGeoShape.java | 105 +++++++++++++++ .../scalar/spatial/StGeotileToLong.java | 93 +++++++++++++ .../scalar/spatial/StGeotileToString.java | 93 +++++++++++++ 25 files changed, 2602 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromLongEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongFromStringEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringFromLongEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromLongEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongFromStringEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringFromLongEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromLongEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongFromLongEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongFromStringEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringFromLongEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLong.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToString.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLong.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLong.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToString.java diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index 56ea1a4511b46..cfbfa9c082eae 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -2,6 +2,50 @@ # Tests for geo_grid function: ST_GEOHASH ############################################### +geohashStringToLong +required_capability: spatial_grid + +ROW geohash = "u3bu" +| EVAL geohashLong = ST_GEOHASH_TO_LONG(geohash) +; + +geohash:keyword | geohashLong:long +u3bu | 13686180 +; + +geohashLongToString +required_capability: spatial_grid + +ROW geohash = TO_LONG(13686180) +| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +; + +geohash:long | geohashString:keyword +13686180 | u3bu +; + +geohashStringToGeoShape +required_capability: spatial_grid + +ROW geohash = "u3bu" +| EVAL boundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +; + +geohash:keyword | boundary:geo_shape +u3bu | BBOX (12.3046875, 12.65625, 55.72265625, 55.546875) +; + +geohashLongToGeoShape +required_capability: spatial_grid + +ROW geohash = TO_LONG(13686180) +| EVAL boundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +; + +geohash:long | boundary:geo_shape +13686180 | BBOX (12.3046875, 12.65625, 55.72265625, 55.546875) +; + geohashLiteral required_capability: spatial_grid @@ -190,6 +234,19 @@ count:long | centroid:geo_point # Tests for geo_grid function: ST_GEOTILE ############################################### +geotileStringToLong +required_capability: spatial_grid + +ROW geotile = "4/8/5" +| EVAL geotileLong = ST_GEOTILE_TO_LONG(geotile) +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotileLong) +| EVAL boundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +; + +geotile:keyword | geotileLong:long | geotileString:keyword | boundary:geo_shape +4/8/5 | 1152921508901814277 | 4/8/5 | BBOX (0.0, 22.5, 55.77657301866769, 40.979898069620134) +; + geotileLiteral required_capability: spatial_grid @@ -361,6 +418,19 @@ count:long | centroid:geo_point # Tests for geo_grid function: ST_GEOHEX ############################################### +geohexStringToLong +required_capability: spatial_grid + +ROW geohex = "841f059ffffffff" +| EVAL geohexLong = ST_GEOHEX_TO_LONG(geohex) +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohexLong) +| EVAL boundary = ST_GEOHEX_TO_GEOSHAPE(geohex) +; + +geohex:keyword | geohexLong:long | geohexString:keyword | boundary:geo_shape +841f059ffffffff | 595020895127339007 | 841f059ffffffff | POLYGON ((12.353546327258265 55.80335405461356, 12.2434612967008 55.60502874054935, 12.51733872608954 55.470800201545316, 12.901880149865134 55.53443156197633, 13.014270156228921 55.73262985778208, 12.739822958959069 55.8673267391136, 12.353546327258265 55.80335405461356)) +; + geohexLiteral required_capability: spatial_grid diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromLongEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromLongEvaluator.java new file mode 100644 index 0000000000000..3e95b8a55d7e9 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromLongEvaluator.java @@ -0,0 +1,124 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.LongVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohashToGeoShape}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeohashToGeoShapeFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeohashToGeoShapeFromLongEvaluator(Source source, + EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + LongVector vector = (LongVector) v; + int positionCount = v.getPositionCount(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p)); + } + return builder.build(); + } + } + + private BytesRef evalValue(LongVector container, int index) { + long value = container.getLong(index); + return StGeohashToGeoShape.fromLong(value); + } + + @Override + public Block evalBlock(Block b) { + LongBlock block = (LongBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(LongBlock container, int index) { + long value = container.getLong(index); + return StGeohashToGeoShape.fromLong(value); + } + + @Override + public String toString() { + return "StGeohashToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeohashToGeoShapeFromLongEvaluator get(DriverContext context) { + return new StGeohashToGeoShapeFromLongEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeohashToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java new file mode 100644 index 0000000000000..d0583a7dd000e --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java @@ -0,0 +1,125 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohashToGeoShape}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeohashToGeoShapeFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeohashToGeoShapeFromStringEvaluator(Source source, + EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + BytesRefVector vector = (BytesRefVector) v; + int positionCount = v.getPositionCount(); + BytesRef scratchPad = new BytesRef(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0, scratchPad), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p, scratchPad)); + } + return builder.build(); + } + } + + private BytesRef evalValue(BytesRefVector container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeohashToGeoShape.fromString(value); + } + + @Override + public Block evalBlock(Block b) { + BytesRefBlock block = (BytesRefBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + BytesRef scratchPad = new BytesRef(); + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i, scratchPad); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeohashToGeoShape.fromString(value); + } + + @Override + public String toString() { + return "StGeohashToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeohashToGeoShapeFromStringEvaluator get(DriverContext context) { + return new StGeohashToGeoShapeFromStringEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeohashToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongFromStringEvaluator.java new file mode 100644 index 0000000000000..640a77fe05fb9 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongFromStringEvaluator.java @@ -0,0 +1,126 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohashToLong}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeohashToLongFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeohashToLongFromStringEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, + DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + BytesRefVector vector = (BytesRefVector) v; + int positionCount = v.getPositionCount(); + BytesRef scratchPad = new BytesRef(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantLongBlockWith(evalValue(vector, 0, scratchPad), positionCount); + } + try (LongBlock.Builder builder = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendLong(evalValue(vector, p, scratchPad)); + } + return builder.build(); + } + } + + private long evalValue(BytesRefVector container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeohashToLong.fromString(value); + } + + @Override + public Block evalBlock(Block b) { + BytesRefBlock block = (BytesRefBlock) b; + int positionCount = block.getPositionCount(); + try (LongBlock.Builder builder = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { + BytesRef scratchPad = new BytesRef(); + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + long value = evalValue(block, i, scratchPad); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendLong(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private long evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeohashToLong.fromString(value); + } + + @Override + public String toString() { + return "StGeohashToLongFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeohashToLongFromStringEvaluator get(DriverContext context) { + return new StGeohashToLongFromStringEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeohashToLongFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringFromLongEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringFromLongEvaluator.java new file mode 100644 index 0000000000000..3e33f376e4e7e --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringFromLongEvaluator.java @@ -0,0 +1,124 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.LongVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohashToString}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeohashToStringFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeohashToStringFromLongEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, + DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + LongVector vector = (LongVector) v; + int positionCount = v.getPositionCount(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p)); + } + return builder.build(); + } + } + + private BytesRef evalValue(LongVector container, int index) { + long value = container.getLong(index); + return StGeohashToString.fromLong(value); + } + + @Override + public Block evalBlock(Block b) { + LongBlock block = (LongBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(LongBlock container, int index) { + long value = container.getLong(index); + return StGeohashToString.fromLong(value); + } + + @Override + public String toString() { + return "StGeohashToStringFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeohashToStringFromLongEvaluator get(DriverContext context) { + return new StGeohashToStringFromLongEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeohashToStringFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromLongEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromLongEvaluator.java new file mode 100644 index 0000000000000..250c2159e380b --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromLongEvaluator.java @@ -0,0 +1,124 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.LongVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohexToGeoShape}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeohexToGeoShapeFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeohexToGeoShapeFromLongEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, + DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + LongVector vector = (LongVector) v; + int positionCount = v.getPositionCount(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p)); + } + return builder.build(); + } + } + + private BytesRef evalValue(LongVector container, int index) { + long value = container.getLong(index); + return StGeohexToGeoShape.fromLong(value); + } + + @Override + public Block evalBlock(Block b) { + LongBlock block = (LongBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(LongBlock container, int index) { + long value = container.getLong(index); + return StGeohexToGeoShape.fromLong(value); + } + + @Override + public String toString() { + return "StGeohexToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeohexToGeoShapeFromLongEvaluator get(DriverContext context) { + return new StGeohexToGeoShapeFromLongEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeohexToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java new file mode 100644 index 0000000000000..1ca489f74f45d --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java @@ -0,0 +1,125 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohexToGeoShape}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeohexToGeoShapeFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeohexToGeoShapeFromStringEvaluator(Source source, + EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + BytesRefVector vector = (BytesRefVector) v; + int positionCount = v.getPositionCount(); + BytesRef scratchPad = new BytesRef(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0, scratchPad), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p, scratchPad)); + } + return builder.build(); + } + } + + private BytesRef evalValue(BytesRefVector container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeohexToGeoShape.fromString(value); + } + + @Override + public Block evalBlock(Block b) { + BytesRefBlock block = (BytesRefBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + BytesRef scratchPad = new BytesRef(); + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i, scratchPad); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeohexToGeoShape.fromString(value); + } + + @Override + public String toString() { + return "StGeohexToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeohexToGeoShapeFromStringEvaluator get(DriverContext context) { + return new StGeohexToGeoShapeFromStringEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeohexToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongFromStringEvaluator.java new file mode 100644 index 0000000000000..815b5c9cb9015 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongFromStringEvaluator.java @@ -0,0 +1,126 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohexToLong}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeohexToLongFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeohexToLongFromStringEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, + DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + BytesRefVector vector = (BytesRefVector) v; + int positionCount = v.getPositionCount(); + BytesRef scratchPad = new BytesRef(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantLongBlockWith(evalValue(vector, 0, scratchPad), positionCount); + } + try (LongBlock.Builder builder = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendLong(evalValue(vector, p, scratchPad)); + } + return builder.build(); + } + } + + private long evalValue(BytesRefVector container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeohexToLong.fromString(value); + } + + @Override + public Block evalBlock(Block b) { + BytesRefBlock block = (BytesRefBlock) b; + int positionCount = block.getPositionCount(); + try (LongBlock.Builder builder = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { + BytesRef scratchPad = new BytesRef(); + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + long value = evalValue(block, i, scratchPad); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendLong(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private long evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeohexToLong.fromString(value); + } + + @Override + public String toString() { + return "StGeohexToLongFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeohexToLongFromStringEvaluator get(DriverContext context) { + return new StGeohexToLongFromStringEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeohexToLongFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringFromLongEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringFromLongEvaluator.java new file mode 100644 index 0000000000000..9806e85ef6a48 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringFromLongEvaluator.java @@ -0,0 +1,124 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.LongVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohexToString}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeohexToStringFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeohexToStringFromLongEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, + DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + LongVector vector = (LongVector) v; + int positionCount = v.getPositionCount(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p)); + } + return builder.build(); + } + } + + private BytesRef evalValue(LongVector container, int index) { + long value = container.getLong(index); + return StGeohexToString.fromLong(value); + } + + @Override + public Block evalBlock(Block b) { + LongBlock block = (LongBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(LongBlock container, int index) { + long value = container.getLong(index); + return StGeohexToString.fromLong(value); + } + + @Override + public String toString() { + return "StGeohexToStringFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeohexToStringFromLongEvaluator get(DriverContext context) { + return new StGeohexToStringFromLongEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeohexToStringFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromLongEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromLongEvaluator.java new file mode 100644 index 0000000000000..e625fb7443aab --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromLongEvaluator.java @@ -0,0 +1,124 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.LongVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotileToGeoShape}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeotileToGeoShapeFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeotileToGeoShapeFromLongEvaluator(Source source, + EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + LongVector vector = (LongVector) v; + int positionCount = v.getPositionCount(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p)); + } + return builder.build(); + } + } + + private BytesRef evalValue(LongVector container, int index) { + long value = container.getLong(index); + return StGeotileToGeoShape.fromLong(value); + } + + @Override + public Block evalBlock(Block b) { + LongBlock block = (LongBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(LongBlock container, int index) { + long value = container.getLong(index); + return StGeotileToGeoShape.fromLong(value); + } + + @Override + public String toString() { + return "StGeotileToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeotileToGeoShapeFromLongEvaluator get(DriverContext context) { + return new StGeotileToGeoShapeFromLongEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeotileToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java new file mode 100644 index 0000000000000..196ec406da441 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java @@ -0,0 +1,125 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotileToGeoShape}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeotileToGeoShapeFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeotileToGeoShapeFromStringEvaluator(Source source, + EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + BytesRefVector vector = (BytesRefVector) v; + int positionCount = v.getPositionCount(); + BytesRef scratchPad = new BytesRef(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0, scratchPad), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p, scratchPad)); + } + return builder.build(); + } + } + + private BytesRef evalValue(BytesRefVector container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeotileToGeoShape.fromString(value); + } + + @Override + public Block evalBlock(Block b) { + BytesRefBlock block = (BytesRefBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + BytesRef scratchPad = new BytesRef(); + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i, scratchPad); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeotileToGeoShape.fromString(value); + } + + @Override + public String toString() { + return "StGeotileToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeotileToGeoShapeFromStringEvaluator get(DriverContext context) { + return new StGeotileToGeoShapeFromStringEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeotileToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongFromLongEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongFromLongEvaluator.java new file mode 100644 index 0000000000000..7fdf4159a9513 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongFromLongEvaluator.java @@ -0,0 +1,126 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotileToLong}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeotileToLongFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeotileToLongFromLongEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, + DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + BytesRefVector vector = (BytesRefVector) v; + int positionCount = v.getPositionCount(); + BytesRef scratchPad = new BytesRef(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantLongBlockWith(evalValue(vector, 0, scratchPad), positionCount); + } + try (LongBlock.Builder builder = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendLong(evalValue(vector, p, scratchPad)); + } + return builder.build(); + } + } + + private long evalValue(BytesRefVector container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeotileToLong.fromLong(value); + } + + @Override + public Block evalBlock(Block b) { + BytesRefBlock block = (BytesRefBlock) b; + int positionCount = block.getPositionCount(); + try (LongBlock.Builder builder = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { + BytesRef scratchPad = new BytesRef(); + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + long value = evalValue(block, i, scratchPad); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendLong(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private long evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeotileToLong.fromLong(value); + } + + @Override + public String toString() { + return "StGeotileToLongFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeotileToLongFromLongEvaluator get(DriverContext context) { + return new StGeotileToLongFromLongEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeotileToLongFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongFromStringEvaluator.java new file mode 100644 index 0000000000000..b99abc16e62f8 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongFromStringEvaluator.java @@ -0,0 +1,126 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotileToLong}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeotileToLongFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeotileToLongFromStringEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, + DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + BytesRefVector vector = (BytesRefVector) v; + int positionCount = v.getPositionCount(); + BytesRef scratchPad = new BytesRef(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantLongBlockWith(evalValue(vector, 0, scratchPad), positionCount); + } + try (LongBlock.Builder builder = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendLong(evalValue(vector, p, scratchPad)); + } + return builder.build(); + } + } + + private long evalValue(BytesRefVector container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeotileToLong.fromString(value); + } + + @Override + public Block evalBlock(Block b) { + BytesRefBlock block = (BytesRefBlock) b; + int positionCount = block.getPositionCount(); + try (LongBlock.Builder builder = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { + BytesRef scratchPad = new BytesRef(); + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + long value = evalValue(block, i, scratchPad); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendLong(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private long evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeotileToLong.fromString(value); + } + + @Override + public String toString() { + return "StGeotileToLongFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeotileToLongFromStringEvaluator get(DriverContext context) { + return new StGeotileToLongFromStringEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeotileToLongFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringFromLongEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringFromLongEvaluator.java new file mode 100644 index 0000000000000..aece0da62cd23 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringFromLongEvaluator.java @@ -0,0 +1,124 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.LongVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotileToString}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeotileToStringFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeotileToStringFromLongEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, + DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + LongVector vector = (LongVector) v; + int positionCount = v.getPositionCount(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p)); + } + return builder.build(); + } + } + + private BytesRef evalValue(LongVector container, int index) { + long value = container.getLong(index); + return StGeotileToString.fromLong(value); + } + + @Override + public Block evalBlock(Block b) { + LongBlock block = (LongBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(LongBlock container, int index) { + long value = container.getLong(index); + return StGeotileToString.fromLong(value); + } + + @Override + public String toString() { + return "StGeotileToStringFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeotileToStringFromLongEvaluator get(DriverContext context) { + return new StGeotileToStringFromLongEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeotileToStringFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index a2f8a40c2af0f..155fcea924e13 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -129,8 +129,17 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StDistance; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StEnvelope; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohash; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToGeoShape; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToLong; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohex; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToGeoShape; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToLong; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotile; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToGeoShape; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToLong; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StX; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMax; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMin; @@ -381,8 +390,17 @@ private static FunctionDefinition[][] functions() { def(StX.class, StX::new, "st_x"), def(StY.class, StY::new, "st_y"), def(StGeohash.class, StGeohash::new, "st_geohash"), + def(StGeohashToGeoShape.class, StGeohashToGeoShape::new, "st_geohash_to_geoshape"), + def(StGeohashToLong.class, StGeohashToLong::new, "st_geohash_to_long"), + def(StGeohashToString.class, StGeohashToString::new, "st_geohash_to_string"), def(StGeotile.class, StGeotile::new, "st_geotile"), - def(StGeohex.class, StGeohex::new, "st_geohex") }, + def(StGeotileToGeoShape.class, StGeotileToGeoShape::new, "st_geotile_to_geoshape"), + def(StGeotileToLong.class, StGeotileToLong::new, "st_geotile_to_long"), + def(StGeotileToString.class, StGeotileToString::new, "st_geotile_to_string"), + def(StGeohex.class, StGeohex::new, "st_geohex"), + def(StGeohexToGeoShape.class, StGeohexToGeoShape::new, "st_geohex_to_geoshape"), + def(StGeohexToLong.class, StGeohexToLong::new, "st_geohex_to_long"), + def(StGeohexToString.class, StGeohexToString::new, "st_geohex_to_string") }, // conditional new FunctionDefinition[] { def(Case.class, Case::new, "case") }, // null diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/AbstractConvertFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/AbstractConvertFunction.java index 3b869c0200cb9..cdd55ca24d86f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/AbstractConvertFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/AbstractConvertFunction.java @@ -100,7 +100,7 @@ static String supportedTypesNames(Set types) { } @FunctionalInterface - interface BuildFactory { + public interface BuildFactory { ExpressionEvaluator.Factory build(Source source, ExpressionEvaluator.Factory field); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java new file mode 100644 index 0000000000000..55065b8619451 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; + +public class StGeohashToGeoShape extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeohashToGeoShape", + StGeohashToGeoShape::new + ); + + private static final Map EVALUATORS = Map.ofEntries( + Map.entry(KEYWORD, StGeohashToGeoShapeFromStringEvaluator.Factory::new), + Map.entry(LONG, StGeohashToGeoShapeFromLongEvaluator.Factory::new) + ); + + @FunctionInfo( + returnType = "geo_shape", + description = """ + Converts an input value to a `geo_shape` value. + The input values are expected to be the grid-ids of geohash grids, in either long or string format.""", + examples = @Example(file = "spatial-grid", tag = "geohash_to_geoshape") + ) + public StGeohashToGeoShape( + Source source, + @Param( + name = "grid_id", + type = { "keyword", "long" }, + description = "Input geohash grid-id. The input can be a single- or multi-valued column or an expression." + ) Expression v + ) { + super(source, v); + } + + private StGeohashToGeoShape(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + protected Map factories() { + return EVALUATORS; + } + + @Override + public DataType dataType() { + return GEO_SHAPE; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new StGeohashToGeoShape(source(), newChildren.get(0)); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeohashToGeoShape::new, field()); + } + + @ConvertEvaluator(extraName = "FromString") + static BytesRef fromString(BytesRef gridId) { + Rectangle bbox = Geohash.toBoundingBox(gridId.utf8ToString()); + return SpatialCoordinateTypes.GEO.asWkb(bbox); + } + + @ConvertEvaluator(extraName = "FromLong") + static BytesRef fromLong(long gridId) { + Rectangle bbox = Geohash.toBoundingBox(Geohash.stringEncode(gridId)); + return SpatialCoordinateTypes.GEO.asWkb(bbox); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLong.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLong.java new file mode 100644 index 0000000000000..d9fa75fe69053 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLong.java @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; + +public class StGeohashToLong extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeohashToLong", + StGeohashToLong::new + ); + + private static final Map EVALUATORS = Map.ofEntries( + Map.entry(LONG, (source, fieldEval) -> fieldEval), + Map.entry(KEYWORD, StGeohashToLongFromStringEvaluator.Factory::new) + ); + + @FunctionInfo( + returnType = "long", + description = "Converts an input value representing a geohash grid-ID in string format into a long.", + examples = { @Example(file = "spatial-grid", tag = "geohash_to_long") } + ) + public StGeohashToLong( + Source source, + @Param( + name = "grid_id", + type = { "keyword", "long" }, + description = "Input geohash grid-id. The input can be a single- or multi-valued column or an expression." + ) Expression v + ) { + super(source, v); + } + + private StGeohashToLong(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + protected Map factories() { + return EVALUATORS; + } + + @Override + public DataType dataType() { + return LONG; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new StGeohashToLong(source(), newChildren.get(0)); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeohashToLong::new, field()); + } + + @ConvertEvaluator(extraName = "FromString") + static long fromString(BytesRef gridId) { + return Geohash.longEncode(gridId.utf8ToString()); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToString.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToString.java new file mode 100644 index 0000000000000..0a1e4d68cebf2 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToString.java @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; + +public class StGeohashToString extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeohashToString", + StGeohashToString::new + ); + + private static final Map EVALUATORS = Map.ofEntries( + Map.entry(KEYWORD, (source, fieldEval) -> fieldEval), + Map.entry(LONG, StGeohashToStringFromLongEvaluator.Factory::new) + ); + + @FunctionInfo( + returnType = "keyword", + description = "Converts an input value representing a geohash grid-ID in long format into a string.", + examples = { @Example(file = "spatial-grid", tag = "geohash_to_string") } + ) + public StGeohashToString( + Source source, + @Param( + name = "grid_id", + type = { "keyword", "long" }, + description = "Input geohash grid-id. The input can be a single- or multi-valued column or an expression." + ) Expression v + ) { + super(source, v); + } + + private StGeohashToString(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + protected Map factories() { + return EVALUATORS; + } + + @Override + public DataType dataType() { + return KEYWORD; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new StGeohashToString(source(), newChildren.get(0)); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeohashToString::new, field()); + } + + @ConvertEvaluator(extraName = "FromLong") + static BytesRef fromLong(long gridId) { + return new BytesRef(Geohash.stringEncode(gridId)); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java new file mode 100644 index 0000000000000..2470ad30690b5 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.geometry.LinearRing; +import org.elasticsearch.geometry.Polygon; +import org.elasticsearch.h3.CellBoundary; +import org.elasticsearch.h3.H3; +import org.elasticsearch.h3.LatLng; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; + +public class StGeohexToGeoShape extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeohexToGeoShape", + StGeohexToGeoShape::new + ); + + private static final Map EVALUATORS = Map.ofEntries( + Map.entry(KEYWORD, StGeohexToGeoShapeFromStringEvaluator.Factory::new), + Map.entry(LONG, StGeohexToGeoShapeFromLongEvaluator.Factory::new) + ); + + @FunctionInfo( + returnType = "geo_shape", + description = """ + Converts an input value to a `geo_shape` value. + The input values are expected to be the grid-ids of H3 grids, in either long or string format.""", + examples = @Example(file = "spatial-grid", tag = "geohex-to_geoshape") + ) + public StGeohexToGeoShape( + Source source, + @Param( + name = "grid_id", + type = { "keyword", "long" }, + description = "Input H3 grid-id. The input can be a single- or multi-valued column or an expression." + ) Expression v + ) { + super(source, v); + } + + private StGeohexToGeoShape(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + protected Map factories() { + return EVALUATORS; + } + + @Override + public DataType dataType() { + return GEO_SHAPE; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new StGeohexToGeoShape(source(), newChildren.get(0)); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeohexToGeoShape::new, field()); + } + + @ConvertEvaluator(extraName = "FromString") + static BytesRef fromString(BytesRef gridId) { + return fromCellBoundary(H3.h3ToGeoBoundary(gridId.utf8ToString())); + } + + @ConvertEvaluator(extraName = "FromLong") + static BytesRef fromLong(long gridId) { + return fromCellBoundary(H3.h3ToGeoBoundary(gridId)); + } + + private static BytesRef fromCellBoundary(CellBoundary cell) { + double[] x = new double[cell.numPoints() + 1]; + double[] y = new double[cell.numPoints() + 1]; + for (int i = 0; i < cell.numPoints(); i++) { + LatLng vertex = cell.getLatLon(i); + x[i] = vertex.getLonDeg(); + y[i] = vertex.getLatDeg(); + } + x[cell.numPoints()] = x[0]; + y[cell.numPoints()] = y[0]; + LinearRing ring = new LinearRing(x, y); + Polygon polygon = new Polygon(ring); + return SpatialCoordinateTypes.GEO.asWkb(polygon); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLong.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLong.java new file mode 100644 index 0000000000000..a410b9ebbbe0c --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLong.java @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.h3.H3; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; + +public class StGeohexToLong extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeohexToLong", + StGeohexToLong::new + ); + + private static final Map EVALUATORS = Map.ofEntries( + Map.entry(LONG, (source, fieldEval) -> fieldEval), + Map.entry(KEYWORD, StGeohexToLongFromStringEvaluator.Factory::new) + ); + + @FunctionInfo( + returnType = "long", + description = "Converts an input value representing a geohex grid-ID in string format into a long.", + examples = { @Example(file = "spatial-grid", tag = "geohex_to_long") } + ) + public StGeohexToLong( + Source source, + @Param( + name = "grid_id", + type = { "keyword", "long" }, + description = "Input geohex grid-id. The input can be a single- or multi-valued column or an expression." + ) Expression v + ) { + super(source, v); + } + + private StGeohexToLong(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + protected Map factories() { + return EVALUATORS; + } + + @Override + public DataType dataType() { + return LONG; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new StGeohexToLong(source(), newChildren.get(0)); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeohexToLong::new, field()); + } + + @ConvertEvaluator(extraName = "FromString") + static long fromString(BytesRef gridId) { + return H3.stringToH3(gridId.utf8ToString()); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java new file mode 100644 index 0000000000000..aafcbe4963a32 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.h3.H3; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; + +public class StGeohexToString extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeohexToString", + StGeohexToString::new + ); + + private static final Map EVALUATORS = Map.ofEntries( + Map.entry(KEYWORD, (source, fieldEval) -> fieldEval), + Map.entry(LONG, StGeohexToStringFromLongEvaluator.Factory::new) + ); + + @FunctionInfo( + returnType = "keyword", + description = "Converts an input value representing a Geohex grid-ID in long format into a string.", + examples = { @Example(file = "spatial-grid", tag = "Geohex_to_string") } + ) + public StGeohexToString( + Source source, + @Param( + name = "grid_id", + type = { "keyword", "long" }, + description = "Input Geohex grid-id. The input can be a single- or multi-valued column or an expression." + ) Expression v + ) { + super(source, v); + } + + private StGeohexToString(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + protected Map factories() { + return EVALUATORS; + } + + @Override + public DataType dataType() { + return KEYWORD; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new StGeohexToString(source(), newChildren.get(0)); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeohexToString::new, field()); + } + + @ConvertEvaluator(extraName = "FromLong") + static BytesRef fromLong(long gridId) { + return new BytesRef(H3.h3ToString(gridId)); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java new file mode 100644 index 0000000000000..bac4edc96e18f --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; + +public class StGeotileToGeoShape extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeotileToGeoShape", + StGeotileToGeoShape::new + ); + + private static final Map EVALUATORS = Map.ofEntries( + Map.entry(KEYWORD, StGeotileToGeoShapeFromStringEvaluator.Factory::new), + Map.entry(LONG, StGeotileToGeoShapeFromLongEvaluator.Factory::new) + ); + + @FunctionInfo( + returnType = "geo_shape", + description = """ + Converts an input value to a `geo_shape` value. + The input values are expected to be the grid-ids of geotile grids, in either long or string format.""", + examples = @Example(file = "spatial-grid", tag = "geotile-to_geoshape") + ) + public StGeotileToGeoShape( + Source source, + @Param( + name = "grid_id", + type = { "keyword", "long" }, + description = "Input geotile grid-id. The input can be a single- or multi-valued column or an expression." + ) Expression v + ) { + super(source, v); + } + + private StGeotileToGeoShape(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + protected Map factories() { + return EVALUATORS; + } + + @Override + public DataType dataType() { + return GEO_SHAPE; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new StGeotileToGeoShape(source(), newChildren.get(0)); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeotileToGeoShape::new, field()); + } + + @ConvertEvaluator(extraName = "FromString") + static BytesRef fromString(BytesRef gridId) { + Rectangle bbox = GeoTileUtils.toBoundingBox(gridId.utf8ToString()); + return SpatialCoordinateTypes.GEO.asWkb(bbox); + } + + @ConvertEvaluator(extraName = "FromLong") + static BytesRef fromLong(long gridId) { + Rectangle bbox = GeoTileUtils.toBoundingBox(gridId); + return SpatialCoordinateTypes.GEO.asWkb(bbox); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLong.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLong.java new file mode 100644 index 0000000000000..8189bac55b992 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLong.java @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; + +public class StGeotileToLong extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeotileToLong", + StGeotileToLong::new + ); + + private static final Map EVALUATORS = Map.ofEntries( + Map.entry(LONG, (source, fieldEval) -> fieldEval), + Map.entry(KEYWORD, StGeotileToLongFromStringEvaluator.Factory::new) + ); + + @FunctionInfo( + returnType = "long", + description = "Converts an input value representing a geotile grid-ID in string format into a long.", + examples = { @Example(file = "spatial-grid", tag = "geotile_to_long") } + ) + public StGeotileToLong( + Source source, + @Param( + name = "grid_id", + type = { "keyword", "long" }, + description = "Input geotile grid-id. The input can be a single- or multi-valued column or an expression." + ) Expression v + ) { + super(source, v); + } + + private StGeotileToLong(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + protected Map factories() { + return EVALUATORS; + } + + @Override + public DataType dataType() { + return LONG; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new StGeotileToLong(source(), newChildren.get(0)); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeotileToLong::new, field()); + } + + @ConvertEvaluator(extraName = "FromString") + static long fromString(BytesRef gridId) { + return GeoTileUtils.longEncode(gridId.utf8ToString()); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToString.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToString.java new file mode 100644 index 0000000000000..04b24d2874841 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToString.java @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; + +public class StGeotileToString extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeotileToString", + StGeotileToString::new + ); + + private static final Map EVALUATORS = Map.ofEntries( + Map.entry(KEYWORD, (source, fieldEval) -> fieldEval), + Map.entry(LONG, StGeotileToStringFromLongEvaluator.Factory::new) + ); + + @FunctionInfo( + returnType = "keyword", + description = "Converts an input value representing a geotile grid-ID in long format into a string.", + examples = { @Example(file = "spatial-grid", tag = "geotile_to_string") } + ) + public StGeotileToString( + Source source, + @Param( + name = "grid_id", + type = { "keyword", "long" }, + description = "Input geotile grid-id. The input can be a single- or multi-valued column or an expression." + ) Expression v + ) { + super(source, v); + } + + private StGeotileToString(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + protected Map factories() { + return EVALUATORS; + } + + @Override + public DataType dataType() { + return KEYWORD; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new StGeotileToString(source(), newChildren.get(0)); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeotileToString::new, field()); + } + + @ConvertEvaluator(extraName = "FromLong") + static BytesRef fromLong(long gridId) { + return new BytesRef(GeoTileUtils.stringEncode(gridId)); + } +} From 5ed543bf7cd0572023bcb36665e86bf321038aa2 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 8 Apr 2025 12:46:58 +0200 Subject: [PATCH 09/34] Convert geogrid functions to produce only long values --- .../src/main/resources/spatial-grid.csv-spec | 326 +++++++++++++----- ...hFromFieldAndFieldAndLiteralEvaluator.java | 5 +- .../StGeohashFromFieldAndFieldEvaluator.java | 5 +- ...romFieldAndLiteralAndLiteralEvaluator.java | 5 +- ...StGeohashFromFieldAndLiteralEvaluator.java | 5 +- ...dDocValuesAndFieldAndLiteralEvaluator.java | 5 +- ...shFromFieldDocValuesAndFieldEvaluator.java | 5 +- ...ocValuesAndLiteralAndLiteralEvaluator.java | 5 +- ...FromFieldDocValuesAndLiteralEvaluator.java | 5 +- ...romLiteralAndFieldAndLiteralEvaluator.java | 14 +- ...StGeohashFromLiteralAndFieldEvaluator.java | 14 +- ...xFromFieldAndFieldAndLiteralEvaluator.java | 5 +- .../StGeohexFromFieldAndFieldEvaluator.java | 5 +- ...romFieldAndLiteralAndLiteralEvaluator.java | 5 +- .../StGeohexFromFieldAndLiteralEvaluator.java | 5 +- ...dDocValuesAndFieldAndLiteralEvaluator.java | 5 +- ...exFromFieldDocValuesAndFieldEvaluator.java | 5 +- ...ocValuesAndLiteralAndLiteralEvaluator.java | 5 +- ...FromFieldDocValuesAndLiteralEvaluator.java | 5 +- ...romLiteralAndFieldAndLiteralEvaluator.java | 14 +- .../StGeohexFromLiteralAndFieldEvaluator.java | 14 +- ...eFromFieldAndFieldAndLiteralEvaluator.java | 5 +- .../StGeotileFromFieldAndFieldEvaluator.java | 5 +- ...romFieldAndLiteralAndLiteralEvaluator.java | 5 +- ...StGeotileFromFieldAndLiteralEvaluator.java | 5 +- ...dDocValuesAndFieldAndLiteralEvaluator.java | 5 +- ...leFromFieldDocValuesAndFieldEvaluator.java | 5 +- ...ocValuesAndLiteralAndLiteralEvaluator.java | 5 +- ...FromFieldDocValuesAndLiteralEvaluator.java | 5 +- ...romLiteralAndFieldAndLiteralEvaluator.java | 14 +- ...StGeotileFromLiteralAndFieldEvaluator.java | 14 +- .../esql/expression/ExpressionWritables.java | 20 +- .../scalar/spatial/SpatialGridFunction.java | 10 +- .../function/scalar/spatial/StGeohash.java | 84 +++-- .../function/scalar/spatial/StGeohex.java | 83 +++-- .../function/scalar/spatial/StGeotile.java | 89 +++-- 36 files changed, 482 insertions(+), 334 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index cfbfa9c082eae..ecb63e5484054 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -49,11 +49,29 @@ geohash:long | boundary:geo_shape geohashLiteral required_capability: spatial_grid +// tag::st_geohash-literal[] ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") | EVAL geohash4 = ST_GEOHASH(location, 4), geohash3 = ST_GEOHASH(location, 3), geohash2 = ST_GEOHASH(location, 2), geohash1 = ST_GEOHASH(location, 1) +// end::st_geohash-literal[] +; + +// tag::st_geohash-literal-result[] +location:geo_point | geohash4:long | geohash3:long | geohash2:long | geohash1:long +POINT (12.6493508684508 55.6285017221528) | 13686180 | 427683 | 13362 | 417 +// end::st_geohash-literal-result[] +; + +geohashLiteralString +required_capability: spatial_grid + +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") +| EVAL geohash4 = ST_GEOHASH_TO_STRING(ST_GEOHASH(location, 4)), + geohash3 = ST_GEOHASH_TO_STRING(ST_GEOHASH(location, 3)), + geohash2 = ST_GEOHASH_TO_STRING(ST_GEOHASH(location, 2)), + geohash1 = ST_GEOHASH_TO_STRING(ST_GEOHASH(location, 1)) ; location:geo_point | geohash4:keyword | geohash3:keyword | geohash2:keyword | geohash1:keyword @@ -66,14 +84,32 @@ required_capability: spatial_grid ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] | MV_EXPAND precision | EVAL geohash = ST_GEOHASH(location, precision) +| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +; + +location:geo_point | precision:integer | geohash:long | geohashString:keyword +POINT (12.6493508684508 55.6285017221528) | 1 | 417 | u +POINT (12.6493508684508 55.6285017221528) | 2 | 13362 | u3 +POINT (12.6493508684508 55.6285017221528) | 3 | 427683 | u3b +POINT (12.6493508684508 55.6285017221528) | 4 | 13686180 | u3bu +POINT (12.6493508684508 55.6285017221528) | 5 | 437958005 | u3bur +; + +geohashLiteralMvBoundary +required_capability: spatial_grid + +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] +| MV_EXPAND precision +| EVAL geohash = ST_GEOHASH_TO_STRING(ST_GEOHASH(location, precision)) +| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) ; -location:geo_point | precision:integer | geohash:keyword -POINT (12.6493508684508 55.6285017221528) | 1 | u -POINT (12.6493508684508 55.6285017221528) | 2 | u3 -POINT (12.6493508684508 55.6285017221528) | 3 | u3b -POINT (12.6493508684508 55.6285017221528) | 4 | u3bu -POINT (12.6493508684508 55.6285017221528) | 5 | u3bur +location:geo_point | precision:integer | geohash:keyword | cellBoundary:geo_shape +POINT (12.6493508684508 55.6285017221528) | 1 | u | BBOX (0.0, 45.0, 90.0, 45.0) +POINT (12.6493508684508 55.6285017221528) | 2 | u3 | BBOX (11.25, 22.5, 56.25, 50.625) +POINT (12.6493508684508 55.6285017221528) | 3 | u3b | BBOX (11.25, 12.65625, 56.25, 54.84375) +POINT (12.6493508684508 55.6285017221528) | 4 | u3bu | BBOX (12.3046875, 12.65625, 55.72265625, 55.546875) +POINT (12.6493508684508 55.6285017221528) | 5 | u3bur | BBOX (12.6123046875, 12.65625, 55.634765625, 55.5908203125) ; geohashField @@ -82,11 +118,12 @@ required_capability: spatial_grid FROM airports | WHERE abbrev == "CPH" | EVAL geohash = ST_GEOHASH(location, 7) -| KEEP geohash, abbrev, name, location +| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +| KEEP geohash, geohashString, abbrev, name, location ; -geohash:keyword | abbrev:keyword | name:text | location:geo_point -u3buryf | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) +geohash:long | geohashString:keyword | abbrev:keyword | name:text | location:geo_point +448469007591 | u3buryf | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) ; gridGeohashStatsBy @@ -100,12 +137,14 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohash | WHERE count >= 10 -| SORT count DESC, geohash ASC +| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +| KEEP count, centroid, geohashString +| SORT count DESC, geohashString ASC // end::st_geohash-grid[] ; // tag::st_geohash-grid-result[] -count:long | centroid:geo_point | geohash:keyword +count:long | centroid:geo_point | geohashString:keyword 118 | POINT (-77.41857436454018 26.96522968734409) | d 96 | POINT (23.181679135886952 27.295384635654045) | s 94 | POINT (70.94076107503807 25.691916451026547) | t @@ -136,16 +175,19 @@ FROM airports count = COUNT(*), centroid = ST_CENTROID_AGG(location) BY geohash -| SORT count DESC, geohash ASC +| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +| KEEP count, centroid, geohashString, cellBoundary +| SORT count DESC, geohashString ASC ; -count:long | centroid:geo_point | geohash:keyword -19 | POINT (6.360728044651057 47.94084087577894) | u0 -8 | POINT (6.351574736181647 51.8981519783847) | u1 -7 | POINT (5.268637698941997 42.747250193330856) | sp -4 | POINT (7.7012718468904495 36.39783004182391) | sn -2 | POINT (11.7787727387622 48.351816879585385) | u2 -1 | POINT (5.629810290411115 58.88215648010373) | u4 +count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape +19 | POINT (6.360728044651057 47.94084087577894) | u0 | BBOX (0.0, 11.25, 50.625, 45.0) +8 | POINT (6.351574736181647 51.8981519783847) | u1 | BBOX (0.0, 11.25, 56.25, 50.625) +7 | POINT (5.268637698941997 42.747250193330856) | sp | BBOX (0.0, 11.25, 45.0, 39.375) +4 | POINT (7.7012718468904495 36.39783004182391) | sn | BBOX (0.0, 11.25, 39.375, 33.75) +2 | POINT (11.7787727387622 48.351816879585385) | u2 | BBOX (11.25, 22.5, 50.625, 45.0) +1 | POINT (5.629810290411115 58.88215648010373) | u4 | BBOX (0.0, 11.25, 61.875, 56.25) ; gridGeohashStatsByWhereUK @@ -158,12 +200,15 @@ FROM airports count = COUNT(location), centroid = ST_CENTROID_AGG(location) BY geohash +| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +| KEEP count, centroid, geohashString, cellBoundary | SORT count DESC ; -count:long | centroid:geo_point | geohash:keyword -14 | POINT (-2.5644131543646966 53.38093495994274) | gc -3 | POINT (-2.7510103583335876 58.79020635969937) | gf +count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape +14 | POINT (-2.5644131543646966 53.38093495994274) | gc | BBOX (-11.25, 0.0, 56.25, 50.625) +3 | POINT (-2.7510103583335876 58.79020635969937) | gf | BBOX (-11.25, 0.0, 61.875, 56.25) ; gridGeohashStatsByBoundsUK @@ -177,13 +222,16 @@ FROM airports count = COUNT(location), centroid = ST_CENTROID_AGG(location) BY geohash +| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +| KEEP count, centroid, geohashString, cellBoundary | SORT count DESC ; -count:long | centroid:geo_point | geohash:keyword -17 | POINT (-3.5034258844440473 53.25306422789307) | gc -3 | POINT (-2.7510103583335876 58.79020635969937) | gf -1 | POINT (0.15865350142121315 49.36166098807007) | u0 +count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape +17 | POINT (-3.5034258844440473 53.25306422789307) | gc | BBOX (-11.25, 0.0, 56.25, 50.625) +3 | POINT (-2.7510103583335876 58.79020635969937) | gf | BBOX (-11.25, 0.0, 61.875, 56.25) +1 | POINT (0.15865350142121315 49.36166098807007) | u0 | BBOX (0.0, 11.25, 50.625, 45.0) ; gridGeohashInStatsBy @@ -250,11 +298,29 @@ geotile:keyword | geotileLong:long | geotileString:keyword | boundary:geo_sha geotileLiteral required_capability: spatial_grid +// tag::st_geotile-literal[] ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") | EVAL geotile4 = ST_GEOTILE(location, 4), geotile3 = ST_GEOTILE(location, 3), geotile2 = ST_GEOTILE(location, 2), geotile1 = ST_GEOTILE(location, 1) +// end::st_geotile-literal[] +; + +// tag::st_geotile-literal-result[] +location:geo_point | geotile4:long | geotile3:long | geotile2:long | geotile1:long +POINT (12.6493508684508 55.6285017221528) | 1152921508901814277 | 864691130602618882 | 576460753377165313 | 288230376688582656 +// end::st_geotile-literal-result[] +; + +geotileLiteralString +required_capability: spatial_grid + +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") +| EVAL geotile4 = ST_GEOTILE_TO_STRING(ST_GEOTILE(location, 4)), + geotile3 = ST_GEOTILE_TO_STRING(ST_GEOTILE(location, 3)), + geotile2 = ST_GEOTILE_TO_STRING(ST_GEOTILE(location, 2)), + geotile1 = ST_GEOTILE_TO_STRING(ST_GEOTILE(location, 1)) ; location:geo_point | geotile4:keyword | geotile3:keyword | geotile2:keyword | geotile1:keyword @@ -267,14 +333,32 @@ required_capability: spatial_grid ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] | MV_EXPAND precision | EVAL geotile = ST_GEOTILE(location, precision) +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) ; -location:geo_point | precision:integer | geotile:keyword -POINT (12.6493508684508 55.6285017221528) | 1 | 1/1/0 -POINT (12.6493508684508 55.6285017221528) | 2 | 2/2/1 -POINT (12.6493508684508 55.6285017221528) | 3 | 3/4/2 -POINT (12.6493508684508 55.6285017221528) | 4 | 4/8/5 -POINT (12.6493508684508 55.6285017221528) | 5 | 5/17/10 +location:geo_point | precision:integer | geotile:long | geotileString:keyword +POINT (12.6493508684508 55.6285017221528) | 1 | 288230376688582656 | 1/1/0 +POINT (12.6493508684508 55.6285017221528) | 2 | 576460753377165313 | 2/2/1 +POINT (12.6493508684508 55.6285017221528) | 3 | 864691130602618882 | 3/4/2 +POINT (12.6493508684508 55.6285017221528) | 4 | 1152921508901814277 | 4/8/5 +POINT (12.6493508684508 55.6285017221528) | 5 | 1441151889885364234 | 5/17/10 +; + +geotileLiteralMvBoundary +required_capability: spatial_grid + +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] +| MV_EXPAND precision +| EVAL geotile = ST_GEOTILE_TO_STRING(ST_GEOTILE(location, precision)) +| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +; + +location:geo_point | precision:integer | geotile:keyword | cellBoundary:geo_shape +POINT (12.6493508684508 55.6285017221528) | 1 | 1/1/0 | BBOX (0.0, 180.0, 85.0511287798066, 0.0) +POINT (12.6493508684508 55.6285017221528) | 2 | 2/2/1 | BBOX (0.0, 90.0, 66.51326044311186, 0.0) +POINT (12.6493508684508 55.6285017221528) | 3 | 3/4/2 | BBOX (0.0, 45.0, 66.51326044311186, 40.979898069620134) +POINT (12.6493508684508 55.6285017221528) | 4 | 4/8/5 | BBOX (0.0, 22.5, 55.77657301866769, 40.979898069620134) +POINT (12.6493508684508 55.6285017221528) | 5 | 5/17/10 | BBOX (11.25, 22.5, 55.77657301866769, 48.922499263758255) ; geotileField @@ -283,11 +367,12 @@ required_capability: spatial_grid FROM airports | WHERE abbrev == "CPH" | EVAL geotile = ST_GEOTILE(location, 7) -| KEEP geotile, abbrev, name, location +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| KEEP geotile, geotileString, abbrev, name, location ; -geotile:keyword | abbrev:keyword | name:text | location:geo_point -7/68/40 | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) +geotile:long | geotileString:keyword | abbrev:keyword | name:text | location:geo_point +2017612669569204264 | 7/68/40 | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) ; gridGeotileStatsBy @@ -300,12 +385,14 @@ FROM airports count = COUNT(*), centroid = ST_CENTROID_AGG(location) BY geotile -| SORT count DESC, geotile ASC +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| SORT count DESC, geotileString ASC +| KEEP count, centroid, geotileString // end::st_geotile-grid[] ; // tag::st_geotile-grid-result[] -count:long | centroid:geo_point | geotile:keyword +count:long | centroid:geo_point | geotileString:keyword 286 | POINT (39.31202001609169 35.149993664386415) | 2/2/1 197 | POINT (-55.387361375756825 31.952955322292855) | 2/1/1 136 | POINT (-110.97162496141048 36.87185255084734) | 2/0/1 @@ -330,12 +417,15 @@ FROM airports count = COUNT(*), centroid = ST_CENTROID_AGG(location) BY geotile -| SORT count DESC, geotile ASC +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +| SORT count DESC, geotileString ASC +| KEEP count, centroid, geotileString, cellBoundary ; -count:long | centroid:geo_point | geotile:keyword -100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 -79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 +count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape +100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 | BBOX (0.0, 45.0, 66.51326044311186, 40.979898069620134) +79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 | BBOX (0.0, 45.0, 40.979898069620134, 0.0) ; gridGeotileStatsByWhereUK @@ -348,12 +438,15 @@ FROM airports count = COUNT(location), centroid = ST_CENTROID_AGG(location) BY geotile +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +| KEEP count, centroid, geotileString, cellBoundary | SORT count DESC ; -count:long | centroid:geo_point | geotile:keyword -12 | POINT (-2.342151787597686 52.9600293841213) | 4/7/5 -5 | POINT (-3.2097987569868565 57.63667118176818) | 4/7/4 +count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape +12 | POINT (-2.342151787597686 52.9600293841213) | 4/7/5 | BBOX (-22.5, 0.0, 55.77657301866769, 40.979898069620134) +5 | POINT (-3.2097987569868565 57.63667118176818) | 4/7/4 | BBOX (-22.5, 0.0, 66.51326044311186, 55.77657301866769) ; gridGeotileStatsByBoundsUK @@ -367,14 +460,17 @@ FROM airports count = COUNT(location), centroid = ST_CENTROID_AGG(location) BY geotile +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +| KEEP count, centroid, geotileString, cellBoundary | SORT count DESC ; -count:long | centroid:geo_point | geotile:keyword -56 | POINT (10.54233039047436 47.85997457644304) | 4/8/5 -18 | POINT (-3.5578574100509286 51.27018998377025) | 4/7/5 -11 | POINT (14.310833624648778 59.85619530801407) | 4/8/4 -7 | POINT (-6.466632609122565 59.19681839378817) | 4/7/4 +count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape +56 | POINT (10.54233039047436 47.85997457644304) | 4/8/5 | BBOX (0.0, 22.5, 55.77657301866769, 40.979898069620134) +18 | POINT (-3.5578574100509286 51.27018998377025) | 4/7/5 | BBOX (-22.5, 0.0, 55.77657301866769, 40.979898069620134) +11 | POINT (14.310833624648778 59.85619530801407) | 4/8/4 | BBOX (0.0, 22.5, 66.51326044311186, 55.77657301866769) +7 | POINT (-6.466632609122565 59.19681839378817) | 4/7/4 | BBOX (-22.5, 0.0, 66.51326044311186, 55.77657301866769) ; gridGeotileInStatsBy @@ -434,11 +530,29 @@ geohex:keyword | geohexLong:long | geohexString:keyword | boundary:geo_shape geohexLiteral required_capability: spatial_grid +// tag::st_geohex-literal[] ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") | EVAL geohex4 = ST_GEOHEX(location, 4), geohex3 = ST_GEOHEX(location, 3), geohex2 = ST_GEOHEX(location, 2), geohex1 = ST_GEOHEX(location, 1) +// end::st_geohex-literal[] +; + +// tag::st_geohex-literal-result[] +location:geo_point | geohex4:long | geohex3:long | geohex2:long | geohex1:long +POINT (12.6493508684508 55.6285017221528) | 595020895127339007 | 590517321269772287 | 586013859081355263 | 581514107744681983 +// end::st_geohex-literal-result[] +; + +geohexLiteralString +required_capability: spatial_grid + +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") +| EVAL geohex4 = ST_GEOHEX_TO_STRING(ST_GEOHEX(location, 4)), + geohex3 = ST_GEOHEX_TO_STRING(ST_GEOHEX(location, 3)), + geohex2 = ST_GEOHEX_TO_STRING(ST_GEOHEX(location, 2)), + geohex1 = ST_GEOHEX_TO_STRING(ST_GEOHEX(location, 1)) ; location:geo_point | geohex4:keyword | geohex3:keyword | geohex2:keyword | geohex1:keyword @@ -451,14 +565,32 @@ required_capability: spatial_grid ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] | MV_EXPAND precision | EVAL geohex = ST_GEOHEX(location, precision) +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +; + +location:geo_point | precision:integer | geohex:long | geohexString:keyword +POINT (12.6493508684508 55.6285017221528) | 1 | 581514107744681983 | 811f3ffffffffff +POINT (12.6493508684508 55.6285017221528) | 2 | 586013859081355263 | 821f07fffffffff +POINT (12.6493508684508 55.6285017221528) | 3 | 590517321269772287 | 831f05fffffffff +POINT (12.6493508684508 55.6285017221528) | 4 | 595020895127339007 | 841f059ffffffff +POINT (12.6493508684508 55.6285017221528) | 5 | 599524487238516735 | 851f0583fffffff +; + +geohexLiteralMvBoundary +required_capability: spatial_grid + +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] +| MV_EXPAND precision +| EVAL geohex = ST_GEOHEX_TO_STRING(ST_GEOHEX(location, precision)) +| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) ; -location:geo_point | precision:integer | geohex:keyword -POINT (12.6493508684508 55.6285017221528) | 1 | 811f3ffffffffff -POINT (12.6493508684508 55.6285017221528) | 2 | 821f07fffffffff -POINT (12.6493508684508 55.6285017221528) | 3 | 831f05fffffffff -POINT (12.6493508684508 55.6285017221528) | 4 | 841f059ffffffff -POINT (12.6493508684508 55.6285017221528) | 5 | 851f0583fffffff +location:geo_point | precision:integer | geohex:keyword | cellBoundary:geo_shape +POINT (12.6493508684508 55.6285017221528) | 1 | 811f3ffffffffff | POLYGON ((5.523646549290313 55.70676846515226, 6.259687055981993 51.96477015603749, 12.345747364400065 50.55427508726938, 18.289963485942284 52.81905199947076, 18.2752359517578 56.63295271905082, 11.555977692900722 58.13053116585142, 5.523646549290313 55.70676846515226)) +POINT (12.6493508684508 55.6285017221528) | 2 | 821f07fffffffff | POLYGON ((10.06569233741819 55.3948787035456, 9.374530816292083 53.97551370235174, 11.245170492278875 53.03203973205439, 13.839528609232428 53.48724516123688, 14.640206584543728 54.90218190493179, 12.739822958959062 55.8673267391136, 10.06569233741819 55.3948787035456)) +POINT (12.6493508684508 55.6285017221528) | 3 | 831f05fffffffff | POLYGON ((11.860105203878488 55.53944935104936, 11.917786510985744 55.0057489060893, 12.839846498886947 54.79854371636354, 13.717124800902113 55.12308086302377, 13.674892957473272 55.65810153974231, 12.739822958959069 55.8673267391136, 11.860105203878488 55.53944935104936)) +POINT (12.6493508684508 55.6285017221528) | 4 | 841f059ffffffff | POLYGON ((12.353546327258265 55.80335405461356, 12.2434612967008 55.60502874054935, 12.51733872608954 55.470800201545316, 12.901880149865134 55.53443156197633, 13.014270156228921 55.73262985778208, 12.739822958959069 55.8673267391136, 12.353546327258265 55.80335405461356)) +POINT (12.6493508684508 55.6285017221528) | 5 | 851f0583fffffff | POLYGON ((12.494766876566144 55.69864155255122, 12.502309582573728 55.6227995792834, 12.635566668537882 55.59351730049433, 12.761550811198047 55.640035539252175, 12.754326292782508 55.71590456460875, 12.62079911077343 55.745228479933665, 12.494766876566144 55.69864155255122)) ; geohexField @@ -467,11 +599,12 @@ required_capability: spatial_grid FROM airports | WHERE abbrev == "CPH" | EVAL geohex = ST_GEOHEX(location, 7) -| KEEP geohex, abbrev, name, location +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| KEEP geohex, geohexString, abbrev, name, location ; -geohex:keyword | abbrev:keyword | name:text | location:geo_point -871f05818ffffff | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) +geohex:long | geohexString:keyword | abbrev:keyword | name:text | location:geo_point +608531685838946303 | 871f05818ffffff | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) ; gridGeohexStatsBy @@ -485,12 +618,14 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohex | WHERE count >= 10 -| SORT count DESC, geohex ASC +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| KEEP count, centroid, geohexString +| SORT count DESC, geohexString ASC // end::st_geohex-grid[] ; // tag::st_geohex-grid-result[] -count:long | centroid:geo_point | geohex:keyword +count:long | centroid:geo_point | geohexString:keyword 22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff 18 | POINT (-80.64959161449224 40.04119813675061) | 812abffffffffff 17 | POINT (-0.7606179875266903 52.86413913565304) | 81197ffffffffff @@ -515,19 +650,22 @@ FROM airports count = COUNT(*), centroid = ST_CENTROID_AGG(location) BY geohex -| SORT count DESC, geohex ASC +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) +| SORT count DESC, geohexString ASC +| KEEP count, centroid, geohexString, cellBoundary ; -count:long | centroid:geo_point | geohex:keyword -22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff -5 | POINT (3.6714368518441916 42.29731031600386) | 81397ffffffffff -4 | POINT (4.188777215313166 51.50470834574662) | 81197ffffffffff -3 | POINT (9.197671310976148 36.29719984252006) | 81387ffffffffff -2 | POINT (9.261639816686511 43.87209988664836) | 811ebffffffffff -2 | POINT (9.395754751749337 53.3421441167593) | 811f3ffffffffff -1 | POINT (5.629810290411115 58.88215648010373) | 8109bffffffffff -1 | POINT (0.15865350142121315 49.36166098807007) | 81187ffffffffff -1 | POINT (3.212073454633355 36.69972063973546) | 81383ffffffffff +count:long | centroid:geo_point | geohexString:keyword | cellBoundary:geo_shape +22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff | POLYGON ((1.1885095534434493 49.47027919866873, 2.026568965384636 45.18424868970643, 7.509948481928886 43.786609353945, 12.677317810359858 46.40695745798227, 12.345747364400065 50.55427508726938, 6.259687055981993 51.96477015603749, 3.6300086390995467 50.6104633125695, 1.1885095534434493 49.47027919866873)) +5 | POINT (3.6714368518441916 42.29731031600386) | 81397ffffffffff | POLYGON ((-2.4177958307002347 42.54047996565121, -1.416234262837718 38.1159967227654, 0.2387159546288331 37.58884624349159, 3.543589356987798 36.59789814478598, 8.045142114241353 39.40213636897177, 7.509948481928886 43.786609353945, 2.026568965384636 45.18424868970643, -2.4177958307002347 42.54047996565121)) +4 | POINT (4.188777215313166 51.50470834574662) | 81197ffffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -6.436337296790312 55.3773904155485, -4.889760342933795 51.22372845966177, 1.1885095534434493 49.47027919866873, 3.6300086390995365 50.610463312569514, 6.259687055981993 51.96477015603749, 5.523646549290304 55.70676846515228, -0.9315871635106163 57.689497374592854)) +3 | POINT (9.197671310976148 36.29719984252006) | 81387ffffffffff | POLYGON ((3.543589356987798 36.59789814478598, 4.204173995672654 32.11010693139568, 8.974635637589913 30.254840780701706, 13.488580338198277 32.87501547725471, 13.244313475659823 37.5237123657852, 8.045142114241353 39.40213636897177, 3.543589356987798 36.59789814478598)) +2 | POINT (9.261639816686511 43.87209988664836) | 811ebffffffffff | POLYGON ((7.509948481928886 43.786609353945, 8.045142114241353 39.40213636897177, 13.244313475659823 37.5237123657852, 18.325260281104846 39.988177963363235, 18.314740441319 44.47067958889503, 12.677317810359858 46.40695745798227, 7.509948481928886 43.786609353945)) +2 | POINT (9.395754751749337 53.3421441167593) | 811f3ffffffffff | POLYGON ((5.523646549290313 55.70676846515226, 6.259687055981993 51.96477015603749, 12.345747364400065 50.55427508726938, 18.289963485942284 52.81905199947076, 18.2752359517578 56.63295271905082, 11.555977692900722 58.13053116585142, 5.523646549290313 55.70676846515226)) +1 | POINT (5.629810290411115 58.88215648010373) | 8109bffffffffff | POLYGON ((4.012620898449951 63.32706132801842, -2.297526087621831 61.54550957788076, -0.9315871635106163 57.689497374592854, 5.523646549290304 55.70676846515228, 11.555977692900722 58.13053116585142, 11.080660058482376 61.54051460002519, 8.644221197607186 61.8908384753262, 4.012620898449951 63.32706132801842)) +1 | POINT (0.15865350142121315 49.36166098807007) | 81187ffffffffff | POLYGON ((-4.889760342933795 51.22372845966177, -9.724736207832692 48.43009421958323, -8.101589192291552 44.0506310521871, -2.4177958307002347 42.54047996565121, 2.026568965384605 45.18424868970644, 1.1885095534434493 49.47027919866873, -4.889760342933795 51.22372845966177)) +1 | POINT (3.212073454633355 36.69972063973546) | 81383ffffffffff | POLYGON ((-5.442348460730093 35.12442405176796, -4.341769247156951 30.69897412778907, -1.2408020165138167 29.828776159725596, 0.26094682603113584 29.300374659234986, 4.204173995672654 32.11010693139568, 3.543589356987798 36.59789814478598, 0.2387159546288331 37.58884624349159, -1.416234262837718 38.1159967227654, -5.442348460730093 35.12442405176796)) ; gridGeohexStatsByWhereUK @@ -540,14 +678,17 @@ FROM airports count = COUNT(location), centroid = ST_CENTROID_AGG(location) BY geohex -| SORT count DESC, geohex ASC +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) +| KEEP count, centroid, geohexString, cellBoundary +| SORT count DESC, geohexString ASC ; -count:long | centroid:geo_point | geohex:keyword -13 | POINT (-2.283508819169723 53.28242553254733) | 81197ffffffffff -2 | POINT (-3.482485176064074 58.24696456314996) | 81193ffffffffff -1 | POINT (-1.2880607228726149 59.87668995279819) | 8109bffffffffff -1 | POINT (-6.216169511899352 54.66155751608312) | 81183ffffffffff +count:long | centroid:geo_point | geohexString:keyword | cellBoundary:geo_shape +13 | POINT (-2.283508819169723 53.28242553254733) | 81197ffffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -6.436337296790312 55.3773904155485, -4.889760342933795 51.22372845966177, 1.1885095534434493 49.47027919866873, 3.6300086390995365 50.610463312569514, 6.259687055981993 51.96477015603749, 5.523646549290304 55.70676846515228, -0.9315871635106163 57.689497374592854)) +2 | POINT (-3.482485176064074 58.24696456314996) | 81193ffffffffff | POLYGON ((-10.44497754477833 63.09505407752544, -16.37196241724276 60.568693514800756, -13.79164665163863 56.73632442836386, -6.436337296790312 55.3773904155485, -0.9315871635106163 57.689497374592854, -2.297526087621831 61.54550957788076, -10.44497754477833 63.09505407752544)) +1 | POINT (-1.2880607228726149 59.87668995279819) | 8109bffffffffff | POLYGON ((4.012620898449951 63.32706132801842, -2.297526087621831 61.54550957788076, -0.9315871635106163 57.689497374592854, 5.523646549290304 55.70676846515228, 11.555977692900722 58.13053116585142, 11.080660058482376 61.54051460002519, 8.644221197607186 61.8908384753262, 4.012620898449951 63.32706132801842)) +1 | POINT (-6.216169511899352 54.66155751608312) | 81183ffffffffff | POLYGON ((-13.79164665163863 56.73632442836386, -18.841171686388584 53.74020675223833, -16.3823406256948 49.6092693973489, -9.724736207832692 48.43009421958323, -4.889760342933795 51.22372845966177, -6.436337296790312 55.3773904155485, -13.79164665163863 56.73632442836386)) ; gridGeohexStatsByBoundsUK @@ -561,20 +702,23 @@ FROM airports count = COUNT(location), centroid = ST_CENTROID_AGG(location) BY geohex -| SORT count DESC, geohex ASC -; - -count:long | centroid:geo_point | geohex:keyword -5 | POINT (-1.7227098606526852 51.717823022045195) | 82195ffffffffff -4 | POINT (-3.9897833741270006 54.21732849790715) | 821957fffffffff -3 | POINT (-7.885485291481018 52.65633414499462) | 82182ffffffffff -2 | POINT (-4.2476349184289575 56.70184155693278) | 82190ffffffffff -2 | POINT (-2.5373152876272798 55.49281941493973) | 821977fffffffff -1 | POINT (-1.2880607228726149 59.87668995279819) | 8209a7fffffffff -1 | POINT (0.15865350142121315 49.36166098807007) | 821867fffffffff -1 | POINT (-2.9013785161077976 58.95442885346711) | 82192ffffffffff -1 | POINT (-1.6598310694098473 53.8690819311887) | 821947fffffffff -1 | POINT (-0.16296171583235264 51.1557567352429) | 82194ffffffffff +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) +| KEEP count, centroid, geohexString, cellBoundary +| SORT count DESC, geohexString ASC +; + +count:long | centroid:geo_point | geohexString:keyword | cellBoundary:geo_shape +5 | POINT (-1.7227098606526852 51.717823022045195) | 82195ffffffffff | POLYGON ((-2.1788859209290505 53.251551050714795, -4.578382413982977 52.792439042763036, -4.889760342933795 51.22372845966177, -2.906527879284175 50.14229216995713, -0.6310947579755295 50.60191112048408, -0.21913743445926337 52.1416808182628, -2.1788859209290505 53.251551050714795)) +4 | POINT (-3.9897833741270006 54.21732849790715) | 821957fffffffff | POLYGON ((-3.9031812914854935 55.840605806464886, -6.436337296790312 55.3773904155485, -6.713499065102683 53.841053788108646, -4.578382413982977 52.792439042763036, -2.1788859209290505 53.251551050714795, -1.7855433613316123 54.76238836624054, -3.9031812914854935 55.840605806464886)) +3 | POINT (-7.885485291481018 52.65633414499462) | 82182ffffffffff | POLYGON ((-6.713499065102683 53.841053788108646, -9.16699332513357 53.28908444969493, -9.362891292036808 51.69686278886942, -7.224493860559402 50.67904691252102, -4.889760342933795 51.22372845966177, -4.578382413982977 52.792439042763036, -6.713499065102683 53.841053788108646)) +2 | POINT (-4.2476349184289575 56.70184155693278) | 82190ffffffffff | POLYGON ((-5.832270115239392 58.353838498476094, -8.508655388670189 57.8811306023458, -8.740899630542538 56.38258811071853, -6.436337296790312 55.3773904155485, -3.9031812914854935 55.840605806464886, -3.536381138969186 57.31728796714347, -5.832270115239392 58.353838498476094)) +2 | POINT (-2.5373152876272798 55.49281941493973) | 821977fffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -3.536381138969186 57.31728796714347, -3.9031812914854935 55.840605806464886, -1.7855433613316123 54.76238836624054, 0.6707588590220377 55.133805943055435, 1.1521975506221078 56.583354389307445, -0.9315871635106163 57.689497374592854)) +1 | POINT (-1.2880607228726149 59.87668995279819) | 8209a7fffffffff | POLYGON ((0.5480202135218006 61.82886471359379, -2.297526087621831 61.54550957788076, -2.7356231170279166 60.17050935552437, -0.4671324618104694 59.1035939329508, 2.198216040575142 59.383886486983954, 2.767527791540729 60.73321011494055, 0.5480202135218006 61.82886471359379)) +1 | POINT (0.15865350142121315 49.36166098807007) | 821867fffffffff | POLYGON ((-0.6310947579755295 50.60191112048408, -2.906527879284175 50.14229216995713, -3.2436562689082553 48.547301491418715, -1.3966081625912774 47.44351195977148, 0.7640259623867446 47.90745035042651, 1.1885095534434493 49.47027919866873, -0.6310947579755295 50.60191112048408)) +1 | POINT (-2.9013785161077976 58.95442885346711) | 82192ffffffffff | POLYGON ((-2.7356231170279166 60.17050935552437, -5.502334925300172 59.7918551703578, -5.832270115239392 58.353838498476094, -3.536381138969186 57.31728796714347, -0.9315871635106163 57.689497374592854, -0.4671324618104694 59.1035939329508, -2.7356231170279166 60.17050935552437)) +1 | POINT (-1.6598310694098473 53.8690819311887) | 821947fffffffff | POLYGON ((0.6707588590220377 55.133805943055435, -1.7855433613316123 54.76238836624054, -2.1788859209290505 53.251551050714795, -0.21913743445926337 52.1416808182628, 2.101313983947425 52.51713397842229, 2.592789031305367 53.99775155222293, 0.6707588590220377 55.133805943055435)) +1 | POINT (-0.16296171583235264 51.1557567352429) | 82194ffffffffff | POLYGON ((2.101313983947425 52.51713397842229, -0.21913743445926337 52.1416808182628, -0.6310947579755295 50.60191112048408, 1.1885095534434493 49.47027919866873, 3.384771510058846 49.85377035058955, 3.8811335596706074 51.360376195950145, 2.101313983947425 52.51713397842229)) ; gridGeohexInStatsByBounds diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldAndLiteralEvaluator.java index 3351b560df248..052e031de3461 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldAndLiteralEvaluator.java @@ -10,6 +10,7 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -54,8 +55,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!inBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldEvaluator.java index 443bcd333d33e..e97975b26aa44 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldEvaluator.java @@ -10,6 +10,7 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -49,8 +50,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!inBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java index 233eeb2ceaf08..c3148b57d8145 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java @@ -9,6 +9,7 @@ import java.lang.String; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -51,8 +52,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, BytesRefBlock inBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!inBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralEvaluator.java index 9e2a159106b12..c67d7e4855299 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralEvaluator.java @@ -9,6 +9,7 @@ import java.lang.String; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -46,8 +47,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, BytesRefBlock wkbBlockBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, BytesRefBlock wkbBlockBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!wkbBlockBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator.java index 84401fd376f94..9fe17446d565d 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator.java @@ -8,7 +8,6 @@ import java.lang.Override; import java.lang.String; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; @@ -55,8 +54,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!encodedBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldEvaluator.java index 7135a0b166196..ad24270bba186 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldEvaluator.java @@ -8,7 +8,6 @@ import java.lang.Override; import java.lang.String; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; @@ -51,8 +50,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!encodedBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java index 56a50ac8c6fed..561c14d6ec7b4 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java @@ -8,7 +8,6 @@ import java.lang.Override; import java.lang.String; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; @@ -52,8 +51,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, LongBlock encodedBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!encodedBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralEvaluator.java index da73fa0495145..a57c2559093bf 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralEvaluator.java @@ -8,7 +8,6 @@ import java.lang.Override; import java.lang.String; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; @@ -47,8 +46,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, LongBlock encodedBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!encodedBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldAndLiteralEvaluator.java index 4d57666ce2cc1..4518bc56d6ffb 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldAndLiteralEvaluator.java @@ -9,9 +9,9 @@ import java.lang.String; import org.apache.lucene.util.BytesRef; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -57,8 +57,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { if (precisionBlock.isNull(p)) { result.appendNull(); @@ -72,7 +72,7 @@ public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { continue position; } try { - result.appendBytesRef(StGeohash.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds)); + result.appendLong(StGeohash.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds)); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -82,11 +82,11 @@ public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { } } - public BytesRefBlock eval(int positionCount, IntVector precisionVector) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, IntVector precisionVector) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { try { - result.appendBytesRef(StGeohash.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bounds)); + result.appendLong(StGeohash.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bounds)); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldEvaluator.java index f4698177a88ae..8a60d2211ae4a 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldEvaluator.java @@ -9,9 +9,9 @@ import java.lang.String; import org.apache.lucene.util.BytesRef; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -53,8 +53,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { if (precisionBlock.isNull(p)) { result.appendNull(); @@ -68,7 +68,7 @@ public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { continue position; } try { - result.appendBytesRef(StGeohash.fromLiteralAndField(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)))); + result.appendLong(StGeohash.fromLiteralAndField(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)))); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -78,11 +78,11 @@ public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { } } - public BytesRefBlock eval(int positionCount, IntVector precisionVector) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, IntVector precisionVector) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { try { - result.appendBytesRef(StGeohash.fromLiteralAndField(this.in, precisionVector.getInt(p))); + result.appendLong(StGeohash.fromLiteralAndField(this.in, precisionVector.getInt(p))); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldAndLiteralEvaluator.java index a33a359269f91..712d08ef31c82 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldAndLiteralEvaluator.java @@ -10,6 +10,7 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -54,8 +55,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!inBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldEvaluator.java index d5fb297e66aa2..36d121396a086 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldEvaluator.java @@ -10,6 +10,7 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -49,8 +50,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!inBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java index cd12dc800a59e..cccd3a52ad9e2 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java @@ -9,6 +9,7 @@ import java.lang.String; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -51,8 +52,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, BytesRefBlock inBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!inBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralEvaluator.java index 5a8304afab118..5209d32caf308 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralEvaluator.java @@ -9,6 +9,7 @@ import java.lang.String; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -46,8 +47,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, BytesRefBlock wkbBlockBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, BytesRefBlock wkbBlockBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!wkbBlockBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator.java index b31e82cab4549..2b328aa303609 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator.java @@ -8,7 +8,6 @@ import java.lang.Override; import java.lang.String; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; @@ -55,8 +54,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!encodedBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldEvaluator.java index 79f794dcb52a5..947bc22e41136 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldEvaluator.java @@ -8,7 +8,6 @@ import java.lang.Override; import java.lang.String; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; @@ -51,8 +50,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!encodedBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java index f3d1401f9922e..41d0926b0069e 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java @@ -8,7 +8,6 @@ import java.lang.Override; import java.lang.String; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; @@ -52,8 +51,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, LongBlock encodedBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!encodedBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralEvaluator.java index 7714f33ceaf7d..2b7d48d5f159d 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralEvaluator.java @@ -8,7 +8,6 @@ import java.lang.Override; import java.lang.String; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; @@ -47,8 +46,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, LongBlock encodedBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!encodedBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldAndLiteralEvaluator.java index e7aa53d932bf9..d0af7080c784b 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldAndLiteralEvaluator.java @@ -9,9 +9,9 @@ import java.lang.String; import org.apache.lucene.util.BytesRef; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -57,8 +57,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { if (precisionBlock.isNull(p)) { result.appendNull(); @@ -72,7 +72,7 @@ public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { continue position; } try { - result.appendBytesRef(StGeohex.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds)); + result.appendLong(StGeohex.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds)); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -82,11 +82,11 @@ public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { } } - public BytesRefBlock eval(int positionCount, IntVector precisionVector) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, IntVector precisionVector) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { try { - result.appendBytesRef(StGeohex.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bounds)); + result.appendLong(StGeohex.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bounds)); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldEvaluator.java index 4c2d6aa59b284..d3daf1b6178da 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldEvaluator.java @@ -9,9 +9,9 @@ import java.lang.String; import org.apache.lucene.util.BytesRef; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -53,8 +53,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { if (precisionBlock.isNull(p)) { result.appendNull(); @@ -68,7 +68,7 @@ public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { continue position; } try { - result.appendBytesRef(StGeohex.fromLiteralAndField(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)))); + result.appendLong(StGeohex.fromLiteralAndField(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)))); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -78,11 +78,11 @@ public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { } } - public BytesRefBlock eval(int positionCount, IntVector precisionVector) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, IntVector precisionVector) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { try { - result.appendBytesRef(StGeohex.fromLiteralAndField(this.in, precisionVector.getInt(p))); + result.appendLong(StGeohex.fromLiteralAndField(this.in, precisionVector.getInt(p))); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldAndLiteralEvaluator.java index 5e8d671795eae..3644945c6600c 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldAndLiteralEvaluator.java @@ -11,6 +11,7 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -54,8 +55,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!inBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldEvaluator.java index c42279a3a977e..c0e9075742d58 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndFieldEvaluator.java @@ -10,6 +10,7 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -49,8 +50,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!inBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java index dea9b3fa439a9..16e36a4717665 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java @@ -9,6 +9,7 @@ import java.lang.String; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -48,8 +49,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, BytesRefBlock inBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, BytesRefBlock inBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!inBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralEvaluator.java index 70fe6320362ca..f5b6f4b503373 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralEvaluator.java @@ -9,6 +9,7 @@ import java.lang.String; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -46,8 +47,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, BytesRefBlock wkbBlockBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, BytesRefBlock wkbBlockBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!wkbBlockBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator.java index 3e0438f22e556..9c621960577ec 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldAndLiteralEvaluator.java @@ -9,7 +9,6 @@ import java.lang.String; import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; @@ -55,8 +54,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!encodedBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldEvaluator.java index 4769edf3750fd..0db8ced570f03 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndFieldEvaluator.java @@ -8,7 +8,6 @@ import java.lang.Override; import java.lang.String; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; @@ -51,8 +50,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!encodedBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java index 7b8aa21624e2a..2dbc49dd3777f 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java @@ -8,7 +8,6 @@ import java.lang.Override; import java.lang.String; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; @@ -49,8 +48,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, LongBlock encodedBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!encodedBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralEvaluator.java index 277e709b25e7c..93acf7bd2badc 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralEvaluator.java @@ -8,7 +8,6 @@ import java.lang.Override; import java.lang.String; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; @@ -47,8 +46,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, LongBlock encodedBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, LongBlock encodedBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { boolean allBlocksAreNulls = true; if (!encodedBlock.isNull(p)) { diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldAndLiteralEvaluator.java index c606734c1616d..f626323fdc4f9 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldAndLiteralEvaluator.java @@ -10,9 +10,9 @@ import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -58,8 +58,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { if (precisionBlock.isNull(p)) { result.appendNull(); @@ -73,7 +73,7 @@ public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { continue position; } try { - result.appendBytesRef(StGeotile.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bbox)); + result.appendLong(StGeotile.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bbox)); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -83,11 +83,11 @@ public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { } } - public BytesRefBlock eval(int positionCount, IntVector precisionVector) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, IntVector precisionVector) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { try { - result.appendBytesRef(StGeotile.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bbox)); + result.appendLong(StGeotile.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bbox)); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldEvaluator.java index d4637db6ce838..8a9534e8095d6 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromLiteralAndFieldEvaluator.java @@ -9,9 +9,9 @@ import java.lang.String; import org.apache.lucene.util.BytesRef; import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -53,8 +53,8 @@ public Block eval(Page page) { } } - public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, IntBlock precisionBlock) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { if (precisionBlock.isNull(p)) { result.appendNull(); @@ -68,7 +68,7 @@ public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { continue position; } try { - result.appendBytesRef(StGeotile.fromLiteralAndField(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)))); + result.appendLong(StGeotile.fromLiteralAndField(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)))); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -78,11 +78,11 @@ public BytesRefBlock eval(int positionCount, IntBlock precisionBlock) { } } - public BytesRefBlock eval(int positionCount, IntVector precisionVector) { - try(BytesRefBlock.Builder result = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + public LongBlock eval(int positionCount, IntVector precisionVector) { + try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { try { - result.appendBytesRef(StGeotile.fromLiteralAndField(this.in, precisionVector.getInt(p))); + result.appendLong(StGeotile.fromLiteralAndField(this.in, precisionVector.getInt(p))); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java index dc991abb83615..6b520ee4c034d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java @@ -59,8 +59,17 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StDistance; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StEnvelope; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohash; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToGeoShape; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToLong; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohex; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToGeoShape; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToLong; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotile; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToGeoShape; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToLong; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StX; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMax; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StXMin; @@ -222,8 +231,17 @@ private static List spatials() { SpatialWithin.ENTRY, StDistance.ENTRY, StGeohash.ENTRY, + StGeohashToString.ENTRY, + StGeohashToLong.ENTRY, + StGeohashToGeoShape.ENTRY, StGeotile.ENTRY, - StGeohex.ENTRY + StGeotileToString.ENTRY, + StGeotileToLong.ENTRY, + StGeotileToGeoShape.ENTRY, + StGeohex.ENTRY, + StGeohexToString.ENTRY, + StGeohexToLong.ENTRY, + StGeohexToGeoShape.ENTRY ); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java index 39c9c213d95b1..5399843c09771 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java @@ -12,7 +12,7 @@ import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.geometry.Point; import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.geometry.utils.SpatialEnvelopeVisitor; @@ -201,15 +201,15 @@ public boolean foldable() { return spatialField.foldable() && parameter.foldable() && (bounds == null || bounds.foldable()); } - protected static void addGrids(BytesRefBlock.Builder results, List gridIds) { + protected static void addGrids(LongBlock.Builder results, List gridIds) { if (gridIds.isEmpty()) { results.appendNull(); } else if (gridIds.size() == 1) { - results.appendBytesRef(gridIds.getFirst()); + results.appendLong(gridIds.getFirst()); } else { results.beginPositionEntry(); - for (BytesRef gridId : gridIds) { - results.appendBytesRef(gridId); + for (long gridId : gridIds) { + results.appendLong(gridId); } results.endPositionEntry(); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java index a38fcf057ef13..8ce0b1fe6c146 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java @@ -31,7 +31,7 @@ import java.io.IOException; import java.util.ArrayList; -import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; /** @@ -45,8 +45,11 @@ public class StGeohash extends SpatialGridFunction implements EvaluatorMapper { ); @FunctionInfo( - returnType = "keyword", - description = "Calculates the `geohash` of the supplied geo_point at the specified precision.", + returnType = "long", + description = """ + Calculates the `geohash` of the supplied geo_point at the specified precision. + The result is long encoded. Use ST_GEOHASH_TO_STRING to convert the result to a string. + Or use ST_GEOHASH_TO_GEOSHAPE to convert either the long or string geohash to a BBOX geo_shape.""", examples = @Example(file = "spatial-grid", tag = "st_geohash-grid") ) public StGeohash( @@ -93,7 +96,7 @@ public String getWriteableName() { @Override public DataType dataType() { - return KEYWORD; + return LONG; } @Override @@ -185,37 +188,37 @@ public Object fold(FoldContext ctx) { } @Evaluator(extraName = "FromFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndLiteral(BytesRefBlock.Builder results, int p, BytesRefBlock wkbBlock, @Fixed int precision) { + static void fromFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock wkbBlock, @Fixed int precision) { fromWKB(results, p, wkbBlock, precision); } @Evaluator(extraName = "FromFieldDocValuesAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldDocValuesAndLiteral(BytesRefBlock.Builder results, int p, LongBlock encoded, @Fixed int precision) { + static void fromFieldDocValuesAndLiteral(LongBlock.Builder results, int p, LongBlock encoded, @Fixed int precision) { fromEncodedLong(results, p, encoded, precision); } @Evaluator(extraName = "FromFieldAndField", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndField(BytesRefBlock.Builder results, int p, BytesRefBlock in, int precision) { + static void fromFieldAndField(LongBlock.Builder results, int p, BytesRefBlock in, int precision) { fromWKB(results, p, in, precision); } @Evaluator(extraName = "FromFieldDocValuesAndField", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldDocValuesAndField(BytesRefBlock.Builder results, int p, LongBlock encoded, int precision) { + static void fromFieldDocValuesAndField(LongBlock.Builder results, int p, LongBlock encoded, int precision) { fromEncodedLong(results, p, encoded, precision); } @Evaluator(extraName = "FromLiteralAndField", warnExceptions = { IllegalArgumentException.class }) - static BytesRef fromLiteralAndField(@Fixed BytesRef in, int precision) { + static long fromLiteralAndField(@Fixed BytesRef in, int precision) { return calculateGeohash(GEO.wkbAsPoint(in), precision); } - protected static BytesRef calculateGeohash(Point point, int precision) { - return new BytesRef(Geohash.stringEncode(point.getX(), point.getY(), precision)); + protected static long calculateGeohash(Point point, int precision) { + return Geohash.longEncode(point.getX(), point.getY(), precision); } @Evaluator(extraName = "FromFieldAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndLiteralAndLiteral( - BytesRefBlock.Builder results, + LongBlock.Builder results, int p, BytesRefBlock in, @Fixed int precision, @@ -226,7 +229,7 @@ static void fromFieldAndLiteralAndLiteral( @Evaluator(extraName = "FromFieldDocValuesAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndLiteralAndLiteral( - BytesRefBlock.Builder results, + LongBlock.Builder results, int p, LongBlock encoded, @Fixed int precision, @@ -236,19 +239,13 @@ static void fromFieldDocValuesAndLiteralAndLiteral( } @Evaluator(extraName = "FromFieldAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndFieldAndLiteral( - BytesRefBlock.Builder results, - int p, - BytesRefBlock in, - int precision, - @Fixed Rectangle bounds - ) { + static void fromFieldAndFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, int precision, @Fixed Rectangle bounds) { fromWKB(results, p, in, precision, bounds); } @Evaluator(extraName = "FromFieldDocValuesAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndFieldAndLiteral( - BytesRefBlock.Builder results, + LongBlock.Builder results, int p, LongBlock encoded, int precision, @@ -258,11 +255,11 @@ static void fromFieldDocValuesAndFieldAndLiteral( } @Evaluator(extraName = "FromLiteralAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static BytesRef fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed Rectangle bounds) { + static long fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed Rectangle bounds) { return calculateGeohash(GEO.wkbAsPoint(in), precision, bounds); } - private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { + private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { int valueCount = wkbBlock.getValueCount(position); if (valueCount < 1) { results.appendNull(); @@ -270,44 +267,45 @@ private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRe final BytesRef scratch = new BytesRef(); final int firstValueIndex = wkbBlock.getFirstValueIndex(position); if (valueCount == 1) { - results.appendBytesRef(calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision)); + results.appendLong(calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision)); } else { results.beginPositionEntry(); for (int i = 0; i < valueCount; i++) { - results.appendBytesRef(calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision)); + results.appendLong(calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision)); } results.endPositionEntry(); } } } - private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, int precision) { + private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, int precision) { int valueCount = encoded.getValueCount(position); if (valueCount < 1) { results.appendNull(); } else { final int firstValueIndex = encoded.getFirstValueIndex(position); if (valueCount == 1) { - results.appendBytesRef(calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision)); + results.appendLong(calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision)); } else { results.beginPositionEntry(); for (int i = 0; i < valueCount; i++) { - results.appendBytesRef(calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision)); + results.appendLong(calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision)); } results.endPositionEntry(); } } } - protected static BytesRef calculateGeohash(Point point, int precision, Rectangle bounds) { + protected static long calculateGeohash(Point point, int precision, Rectangle bounds) { // For points, filtering the point is as good as filtering the tile if (inBounds(point, bounds)) { - return new BytesRef(Geohash.stringEncode(point.getX(), point.getY(), precision)); + return Geohash.longEncode(point.getX(), point.getY(), precision); } - return null; + // TODO: When we move to GeohashBoundsPredicate we can hopefullly improve this condition + return -1; } - private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision, Rectangle bounds) { + private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision, Rectangle bounds) { int valueCount = wkbBlock.getValueCount(position); if (valueCount < 1) { results.appendNull(); @@ -315,17 +313,17 @@ private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRe final BytesRef scratch = new BytesRef(); final int firstValueIndex = wkbBlock.getFirstValueIndex(position); if (valueCount == 1) { - BytesRef grid = calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision, bounds); - if (grid == null) { + long grid = calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision, bounds); + if (grid < 0) { results.appendNull(); } else { - results.appendBytesRef(grid); + results.appendLong(grid); } } else { - var gridIds = new ArrayList(valueCount); + var gridIds = new ArrayList(valueCount); for (int i = 0; i < valueCount; i++) { var grid = calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision, bounds); - if (grid != null) { + if (grid >= 0) { gridIds.add(grid); } } @@ -334,24 +332,24 @@ private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRe } } - private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, int precision, Rectangle bounds) { + private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, int precision, Rectangle bounds) { int valueCount = encoded.getValueCount(position); if (valueCount < 1) { results.appendNull(); } else { final int firstValueIndex = encoded.getFirstValueIndex(position); if (valueCount == 1) { - BytesRef grid = calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision, bounds); - if (grid == null) { + long grid = calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision, bounds); + if (grid < 0) { results.appendNull(); } else { - results.appendBytesRef(grid); + results.appendLong(grid); } } else { - var gridIds = new ArrayList(valueCount); + var gridIds = new ArrayList(valueCount); for (int i = 0; i < valueCount; i++) { var grid = calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision, bounds); - if (grid != null) { + if (grid >= 0) { gridIds.add(grid); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java index 0b6566bbc3791..2bb1a763870ee 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java @@ -31,7 +31,7 @@ import java.io.IOException; import java.util.ArrayList; -import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; /** @@ -41,8 +41,11 @@ public class StGeohex extends SpatialGridFunction implements EvaluatorMapper { public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "StGeohex", StGeohex::new); @FunctionInfo( - returnType = "keyword", - description = "Calculates the `geohex` of the supplied geo_point at the specified precision.", + returnType = "long", + description = """ + Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision. + The result is long encoded. Use ST_GEOHEX_TO_STRING to convert the result to a string. + Or use ST_GEOHEX_TO_GEOSHAPE to convert either the long or string geohex to a POLYGON geo_shape.""", examples = @Example(file = "spatial-grid", tag = "st_geohex-grid") ) public StGeohex( @@ -89,7 +92,7 @@ public String getWriteableName() { @Override public DataType dataType() { - return KEYWORD; + return LONG; } @Override @@ -181,37 +184,37 @@ public Object fold(FoldContext ctx) { } @Evaluator(extraName = "FromFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndLiteral(BytesRefBlock.Builder results, int p, BytesRefBlock wkbBlock, @Fixed int precision) { + static void fromFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock wkbBlock, @Fixed int precision) { fromWKB(results, p, wkbBlock, precision); } @Evaluator(extraName = "FromFieldDocValuesAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldDocValuesAndLiteral(BytesRefBlock.Builder results, int p, LongBlock encoded, @Fixed int precision) { + static void fromFieldDocValuesAndLiteral(LongBlock.Builder results, int p, LongBlock encoded, @Fixed int precision) { fromEncodedLong(results, p, encoded, precision); } @Evaluator(extraName = "FromFieldAndField", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndField(BytesRefBlock.Builder results, int p, BytesRefBlock in, int precision) { + static void fromFieldAndField(LongBlock.Builder results, int p, BytesRefBlock in, int precision) { fromWKB(results, p, in, precision); } @Evaluator(extraName = "FromFieldDocValuesAndField", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldDocValuesAndField(BytesRefBlock.Builder results, int p, LongBlock encoded, int precision) { + static void fromFieldDocValuesAndField(LongBlock.Builder results, int p, LongBlock encoded, int precision) { fromEncodedLong(results, p, encoded, precision); } @Evaluator(extraName = "FromLiteralAndField", warnExceptions = { IllegalArgumentException.class }) - static BytesRef fromLiteralAndField(@Fixed BytesRef in, int precision) { + static long fromLiteralAndField(@Fixed BytesRef in, int precision) { return calculateGeohex(GEO.wkbAsPoint(in), precision); } - protected static BytesRef calculateGeohex(Point point, int precision) { - return new BytesRef(H3.geoToH3Address(point.getLat(), point.getLon(), precision)); + protected static long calculateGeohex(Point point, int precision) { + return H3.geoToH3(point.getLat(), point.getLon(), precision); } @Evaluator(extraName = "FromFieldAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndLiteralAndLiteral( - BytesRefBlock.Builder results, + LongBlock.Builder results, int p, BytesRefBlock in, @Fixed int precision, @@ -222,7 +225,7 @@ static void fromFieldAndLiteralAndLiteral( @Evaluator(extraName = "FromFieldDocValuesAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndLiteralAndLiteral( - BytesRefBlock.Builder results, + LongBlock.Builder results, int p, LongBlock encoded, @Fixed int precision, @@ -232,19 +235,13 @@ static void fromFieldDocValuesAndLiteralAndLiteral( } @Evaluator(extraName = "FromFieldAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndFieldAndLiteral( - BytesRefBlock.Builder results, - int p, - BytesRefBlock in, - int precision, - @Fixed Rectangle bounds - ) { + static void fromFieldAndFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, int precision, @Fixed Rectangle bounds) { fromWKB(results, p, in, precision, bounds); } @Evaluator(extraName = "FromFieldDocValuesAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndFieldAndLiteral( - BytesRefBlock.Builder results, + LongBlock.Builder results, int p, LongBlock encoded, int precision, @@ -254,11 +251,11 @@ static void fromFieldDocValuesAndFieldAndLiteral( } @Evaluator(extraName = "FromLiteralAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static BytesRef fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed Rectangle bounds) { + static long fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed Rectangle bounds) { return calculateGeohex(GEO.wkbAsPoint(in), precision, bounds); } - private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { + private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { int valueCount = wkbBlock.getValueCount(position); if (valueCount < 1) { results.appendNull(); @@ -266,44 +263,44 @@ private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRe final BytesRef scratch = new BytesRef(); final int firstValueIndex = wkbBlock.getFirstValueIndex(position); if (valueCount == 1) { - results.appendBytesRef(calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision)); + results.appendLong(calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision)); } else { results.beginPositionEntry(); for (int i = 0; i < valueCount; i++) { - results.appendBytesRef(calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision)); + results.appendLong(calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision)); } results.endPositionEntry(); } } } - private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, int precision) { + private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, int precision) { int valueCount = encoded.getValueCount(position); if (valueCount < 1) { results.appendNull(); } else { final int firstValueIndex = encoded.getFirstValueIndex(position); if (valueCount == 1) { - results.appendBytesRef(calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision)); + results.appendLong(calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision)); } else { results.beginPositionEntry(); for (int i = 0; i < valueCount; i++) { - results.appendBytesRef(calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision)); + results.appendLong(calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision)); } results.endPositionEntry(); } } } - protected static BytesRef calculateGeohex(Point point, int precision, Rectangle bounds) { + protected static long calculateGeohex(Point point, int precision, Rectangle bounds) { // For points, filtering the point is as good as filtering the tile if (inBounds(point, bounds)) { - return new BytesRef(H3.geoToH3Address(point.getLat(), point.getLon(), precision)); + return H3.geoToH3(point.getLat(), point.getLon(), precision); } - return null; + return -1L; } - private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision, Rectangle bounds) { + private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision, Rectangle bounds) { int valueCount = wkbBlock.getValueCount(position); if (valueCount < 1) { results.appendNull(); @@ -311,17 +308,17 @@ private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRe final BytesRef scratch = new BytesRef(); final int firstValueIndex = wkbBlock.getFirstValueIndex(position); if (valueCount == 1) { - BytesRef grid = calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision, bounds); - if (grid == null) { + long grid = calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision, bounds); + if (grid < 0) { results.appendNull(); } else { - results.appendBytesRef(grid); + results.appendLong(grid); } } else { - var gridIds = new ArrayList(valueCount); + var gridIds = new ArrayList(valueCount); for (int i = 0; i < valueCount; i++) { var grid = calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision, bounds); - if (grid != null) { + if (grid >= 0) { gridIds.add(grid); } } @@ -330,24 +327,24 @@ private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRe } } - private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, int precision, Rectangle bounds) { + private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, int precision, Rectangle bounds) { int valueCount = encoded.getValueCount(position); if (valueCount < 1) { results.appendNull(); } else { final int firstValueIndex = encoded.getFirstValueIndex(position); if (valueCount == 1) { - BytesRef grid = calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision, bounds); - if (grid == null) { + long grid = calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision, bounds); + if (grid < 0) { results.appendNull(); } else { - results.appendBytesRef(grid); + results.appendLong(grid); } } else { - var gridIds = new ArrayList(valueCount); + var gridIds = new ArrayList(valueCount); for (int i = 0; i < valueCount; i++) { var grid = calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision, bounds); - if (grid != null) { + if (grid >= 0) { gridIds.add(grid); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java index 4be0cbccb090c..64454629de782 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java @@ -32,7 +32,7 @@ import java.io.IOException; import java.util.ArrayList; -import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; /** @@ -46,8 +46,11 @@ public class StGeotile extends SpatialGridFunction implements EvaluatorMapper { ); @FunctionInfo( - returnType = "keyword", - description = "Calculates the `geotile` of the supplied geo_point at the specified precision.", + returnType = "long", + description = """ + Calculates the `geotile` of the supplied geo_point at the specified precision. + The result is long encoded. Use ST_GEOTILE_TO_STRING to convert the result to a string. + Or use ST_GEOTILE_TO_GEOSHAPE to convert either the long or string geotile to a BBOX geo_shape.""", examples = @Example(file = "spatial-grid", tag = "st_geotile-grid") ) public StGeotile( @@ -94,7 +97,7 @@ public String getWriteableName() { @Override public DataType dataType() { - return KEYWORD; + return LONG; } @Override @@ -183,47 +186,42 @@ public Object fold(FoldContext ctx) { } @Evaluator(extraName = "FromFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndLiteral(BytesRefBlock.Builder results, int p, BytesRefBlock wkbBlock, @Fixed int precision) { + static void fromFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock wkbBlock, @Fixed int precision) { fromWKB(results, p, wkbBlock, precision); } @Evaluator(extraName = "FromFieldDocValuesAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldDocValuesAndLiteral(BytesRefBlock.Builder results, int p, LongBlock encoded, @Fixed int precision) { + static void fromFieldDocValuesAndLiteral(LongBlock.Builder results, int p, LongBlock encoded, @Fixed int precision) { fromEncodedLong(results, p, encoded, precision); } @Evaluator(extraName = "FromFieldAndField", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndField(BytesRefBlock.Builder results, int p, BytesRefBlock in, int precision) { + static void fromFieldAndField(LongBlock.Builder results, int p, BytesRefBlock in, int precision) { fromWKB(results, p, in, precision); } @Evaluator(extraName = "FromFieldDocValuesAndField", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldDocValuesAndField(BytesRefBlock.Builder results, int p, LongBlock encoded, int precision) { + static void fromFieldDocValuesAndField(LongBlock.Builder results, int p, LongBlock encoded, int precision) { fromEncodedLong(results, p, encoded, precision); } @Evaluator(extraName = "FromLiteralAndField", warnExceptions = { IllegalArgumentException.class }) - static BytesRef fromLiteralAndField(@Fixed BytesRef in, int precision) { + static long fromLiteralAndField(@Fixed BytesRef in, int precision) { return calculateGeotile(GEO.wkbAsPoint(in), precision); } - protected static BytesRef calculateGeotile(Point point, int precision) { - return new BytesRef(GeoTileUtils.stringEncode(GeoTileUtils.longEncode(point.getX(), point.getY(), precision))); + protected static long calculateGeotile(Point point, int precision) { + return GeoTileUtils.longEncode(point.getX(), point.getY(), precision); } @Evaluator(extraName = "FromFieldAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndLiteralAndLiteral( - BytesRefBlock.Builder results, - int p, - BytesRefBlock in, - @Fixed GeoTileBoundedPredicate bounds - ) { + static void fromFieldAndLiteralAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, @Fixed GeoTileBoundedPredicate bounds) { fromWKB(results, p, in, bounds); } @Evaluator(extraName = "FromFieldDocValuesAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndLiteralAndLiteral( - BytesRefBlock.Builder results, + LongBlock.Builder results, int p, LongBlock encoded, @Fixed GeoTileBoundedPredicate bounds @@ -232,20 +230,14 @@ static void fromFieldDocValuesAndLiteralAndLiteral( } @Evaluator(extraName = "FromFieldAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndFieldAndLiteral( - BytesRefBlock.Builder results, - int p, - BytesRefBlock in, - int precision, - @Fixed GeoBoundingBox bbox - ) { + static void fromFieldAndFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, int precision, @Fixed GeoBoundingBox bbox) { GeoTileBoundedPredicate bounds = new GeoTileBoundedPredicate(precision, bbox); fromWKB(results, p, in, bounds); } @Evaluator(extraName = "FromFieldDocValuesAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndFieldAndLiteral( - BytesRefBlock.Builder results, + LongBlock.Builder results, int p, LongBlock encoded, int precision, @@ -256,12 +248,12 @@ static void fromFieldDocValuesAndFieldAndLiteral( } @Evaluator(extraName = "FromLiteralAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static BytesRef fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed GeoBoundingBox bbox) { + static long fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed GeoBoundingBox bbox) { GeoTileBoundedPredicate bounds = new GeoTileBoundedPredicate(precision, bbox); return calculateGeotile(GEO.wkbAsPoint(in), bounds); } - private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { + private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { int valueCount = wkbBlock.getValueCount(position); if (valueCount < 1) { results.appendNull(); @@ -269,47 +261,46 @@ private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRe final BytesRef scratch = new BytesRef(); final int firstValueIndex = wkbBlock.getFirstValueIndex(position); if (valueCount == 1) { - results.appendBytesRef(calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision)); + results.appendLong(calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision)); } else { results.beginPositionEntry(); for (int i = 0; i < valueCount; i++) { - results.appendBytesRef(calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision)); + results.appendLong(calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision)); } results.endPositionEntry(); } } } - private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, int precision) { + private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, int precision) { int valueCount = encoded.getValueCount(position); if (valueCount < 1) { results.appendNull(); } else { final int firstValueIndex = encoded.getFirstValueIndex(position); if (valueCount == 1) { - results.appendBytesRef(calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision)); + results.appendLong(calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision)); } else { results.beginPositionEntry(); for (int i = 0; i < valueCount; i++) { - results.appendBytesRef(calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision)); + results.appendLong(calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision)); } results.endPositionEntry(); } } } - protected static BytesRef calculateGeotile(Point point, GeoTileBoundedPredicate bounds) { + protected static long calculateGeotile(Point point, GeoTileBoundedPredicate bounds) { final int tiles = 1 << GeoTileUtils.checkPrecisionRange(bounds.precision()); final int x = GeoTileUtils.getXTile(point.getX(), tiles); final int y = GeoTileUtils.getYTile(point.getY(), tiles); if (bounds.validTile(x, y, bounds.precision())) { - final long encoded = GeoTileUtils.longEncodeTiles(bounds.precision(), x, y); - return new BytesRef(GeoTileUtils.stringEncode(encoded)); + return GeoTileUtils.longEncodeTiles(bounds.precision(), x, y); } - return null; + return -1; } - private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRefBlock wkbBlock, GeoTileBoundedPredicate bounds) { + private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, GeoTileBoundedPredicate bounds) { int valueCount = wkbBlock.getValueCount(position); if (valueCount < 1) { results.appendNull(); @@ -317,17 +308,17 @@ private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRe final BytesRef scratch = new BytesRef(); final int firstValueIndex = wkbBlock.getFirstValueIndex(position); if (valueCount == 1) { - BytesRef grid = calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), bounds); - if (grid == null) { + long grid = calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), bounds); + if (grid < 0) { results.appendNull(); } else { - results.appendBytesRef(grid); + results.appendLong(grid); } } else { - var gridIds = new ArrayList(valueCount); + var gridIds = new ArrayList(valueCount); for (int i = 0; i < valueCount; i++) { var grid = calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), bounds); - if (grid != null) { + if (grid >= 0) { gridIds.add(grid); } } @@ -336,24 +327,24 @@ private static void fromWKB(BytesRefBlock.Builder results, int position, BytesRe } } - private static void fromEncodedLong(BytesRefBlock.Builder results, int position, LongBlock encoded, GeoTileBoundedPredicate bounds) { + private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, GeoTileBoundedPredicate bounds) { int valueCount = encoded.getValueCount(position); if (valueCount < 1) { results.appendNull(); } else { final int firstValueIndex = encoded.getFirstValueIndex(position); if (valueCount == 1) { - BytesRef grid = calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex)), bounds); - if (grid == null) { + long grid = calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex)), bounds); + if (grid < 0) { results.appendNull(); } else { - results.appendBytesRef(grid); + results.appendLong(grid); } } else { - var gridIds = new ArrayList(valueCount); + var gridIds = new ArrayList(valueCount); for (int i = 0; i < valueCount; i++) { var grid = calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), bounds); - if (grid != null) { + if (grid >= 0) { gridIds.add(grid); } } From f3a19a008fbab38b654c08819867ad10d816f148 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 8 Apr 2025 14:46:18 +0200 Subject: [PATCH 10/34] Fixes after rebasing on main --- ...tGeohashToGeoShapeFromStringEvaluator.java | 19 +++++++++++++++++++ ...StGeohexToGeoShapeFromStringEvaluator.java | 19 +++++++++++++++++++ ...tGeotileToGeoShapeFromStringEvaluator.java | 19 +++++++++++++++++++ .../rest-api-spec/test/esql/60_usage.yml | 4 ++-- 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java index d0583a7dd000e..0e50257a50bed 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java @@ -10,6 +10,8 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.OrdinalBytesRefVector; import org.elasticsearch.compute.data.Vector; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -38,6 +40,10 @@ public EvalOperator.ExpressionEvaluator next() { @Override public Block evalVector(Vector v) { BytesRefVector vector = (BytesRefVector) v; + OrdinalBytesRefVector ordinals = vector.asOrdinals(); + if (ordinals != null) { + return evalOrdinals(ordinals); + } int positionCount = v.getPositionCount(); BytesRef scratchPad = new BytesRef(); if (vector.isConstant()) { @@ -92,6 +98,19 @@ private BytesRef evalValue(BytesRefBlock container, int index, BytesRef scratchP return StGeohashToGeoShape.fromString(value); } + private Block evalOrdinals(OrdinalBytesRefVector v) { + int positionCount = v.getDictionaryVector().getPositionCount(); + BytesRef scratchPad = new BytesRef(); + try (BytesRefVector.Builder builder = driverContext.blockFactory().newBytesRefVectorBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(v.getDictionaryVector(), p, scratchPad)); + } + IntVector ordinals = v.getOrdinalsVector(); + ordinals.incRef(); + return new OrdinalBytesRefVector(ordinals, builder.build()).asBlock(); + } + } + @Override public String toString() { return "StGeohashToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java index 1ca489f74f45d..94887bda9c960 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java @@ -10,6 +10,8 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.OrdinalBytesRefVector; import org.elasticsearch.compute.data.Vector; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -38,6 +40,10 @@ public EvalOperator.ExpressionEvaluator next() { @Override public Block evalVector(Vector v) { BytesRefVector vector = (BytesRefVector) v; + OrdinalBytesRefVector ordinals = vector.asOrdinals(); + if (ordinals != null) { + return evalOrdinals(ordinals); + } int positionCount = v.getPositionCount(); BytesRef scratchPad = new BytesRef(); if (vector.isConstant()) { @@ -92,6 +98,19 @@ private BytesRef evalValue(BytesRefBlock container, int index, BytesRef scratchP return StGeohexToGeoShape.fromString(value); } + private Block evalOrdinals(OrdinalBytesRefVector v) { + int positionCount = v.getDictionaryVector().getPositionCount(); + BytesRef scratchPad = new BytesRef(); + try (BytesRefVector.Builder builder = driverContext.blockFactory().newBytesRefVectorBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(v.getDictionaryVector(), p, scratchPad)); + } + IntVector ordinals = v.getOrdinalsVector(); + ordinals.incRef(); + return new OrdinalBytesRefVector(ordinals, builder.build()).asBlock(); + } + } + @Override public String toString() { return "StGeohexToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java index 196ec406da441..801bf228e6adf 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java @@ -10,6 +10,8 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.OrdinalBytesRefVector; import org.elasticsearch.compute.data.Vector; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; @@ -38,6 +40,10 @@ public EvalOperator.ExpressionEvaluator next() { @Override public Block evalVector(Vector v) { BytesRefVector vector = (BytesRefVector) v; + OrdinalBytesRefVector ordinals = vector.asOrdinals(); + if (ordinals != null) { + return evalOrdinals(ordinals); + } int positionCount = v.getPositionCount(); BytesRef scratchPad = new BytesRef(); if (vector.isConstant()) { @@ -92,6 +98,19 @@ private BytesRef evalValue(BytesRefBlock container, int index, BytesRef scratchP return StGeotileToGeoShape.fromString(value); } + private Block evalOrdinals(OrdinalBytesRefVector v) { + int positionCount = v.getDictionaryVector().getPositionCount(); + BytesRef scratchPad = new BytesRef(); + try (BytesRefVector.Builder builder = driverContext.blockFactory().newBytesRefVectorBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(v.getDictionaryVector(), p, scratchPad)); + } + IntVector ordinals = v.getOrdinalsVector(); + ordinals.incRef(); + return new OrdinalBytesRefVector(ordinals, builder.build()).asBlock(); + } + } + @Override public String toString() { return "StGeotileToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml index d6706e6bd9e32..d4aa4989d67a4 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml @@ -121,7 +121,7 @@ setup: - match: {esql.functions.coalesce: $functions_coalesce} - gt: {esql.functions.categorize: $functions_categorize} # Testing for the entire function set isn't feasible, so we just check that we return the correct count as an approximation. - - length: {esql.functions: 140} # check the "sister" test below for a likely update to the same esql.functions length check + - length: {esql.functions: 149} # check the "sister" test below for a likely update to the same esql.functions length check --- "Basic ESQL usage output (telemetry) non-snapshot version": @@ -218,7 +218,7 @@ setup: - gt: {esql.functions.to_long: $functions_to_long} - match: {esql.functions.coalesce: $functions_coalesce} - gt: {esql.functions.categorize: $functions_categorize} - - length: {esql.functions: 133} # check the "sister" test above for a likely update to the same esql.functions length check + - length: {esql.functions: 143} # check the "sister" test above for a likely update to the same esql.functions length check --- took: From 7e1989e06bcc933d48f1656f45c9aac5e24a9cc4 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 15 Apr 2025 13:06:28 +0200 Subject: [PATCH 11/34] Support geo-bounded-predicate for geohash and geohex This involved copying the H3 utils from spatial plugin to esql. We should rather find a common location or dependency for these. --- .../geogrid/GeoHashBoundedPredicate.java | 6 + x-pack/plugin/esql/build.gradle | 7 +- .../plugin/esql/licenses/lucene-LICENSE.txt | 475 ++++++++++++++++++ x-pack/plugin/esql/licenses/lucene-NOTICE.txt | 192 +++++++ .../elasticsearch/xpack/esql/CsvAssert.java | 2 +- .../src/main/resources/spatial-grid.csv-spec | 47 +- ...hFromFieldAndFieldAndLiteralEvaluator.java | 22 +- ...romFieldAndLiteralAndLiteralEvaluator.java | 26 +- ...dDocValuesAndFieldAndLiteralEvaluator.java | 22 +- ...ocValuesAndLiteralAndLiteralEvaluator.java | 26 +- ...romLiteralAndFieldAndLiteralEvaluator.java | 25 +- ...xFromFieldAndFieldAndLiteralEvaluator.java | 22 +- ...romFieldAndLiteralAndLiteralEvaluator.java | 25 +- ...dDocValuesAndFieldAndLiteralEvaluator.java | 22 +- ...ocValuesAndLiteralAndLiteralEvaluator.java | 25 +- ...romLiteralAndFieldAndLiteralEvaluator.java | 25 +- .../common/spatial/H3SphericalGeometry.java | 227 +++++++++ .../esql/common/spatial/H3SphericalUtil.java | 136 +++++ .../spatial/GeoHexBoundedPredicate.java | 53 ++ .../function/scalar/spatial/StGeohash.java | 71 ++- .../function/scalar/spatial/StGeohex.java | 69 ++- .../function/scalar/spatial/StGeotile.java | 5 +- .../spatial/H3SphericalGeometryTests.java | 96 ++++ .../common/spatial/H3SphericalUtilTests.java | 67 +++ 24 files changed, 1464 insertions(+), 229 deletions(-) create mode 100644 x-pack/plugin/esql/licenses/lucene-LICENSE.txt create mode 100644 x-pack/plugin/esql/licenses/lucene-NOTICE.txt create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalGeometry.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalUtil.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/GeoHexBoundedPredicate.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalGeometryTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalUtilTests.java diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoHashBoundedPredicate.java b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoHashBoundedPredicate.java index 7496697eb1161..42d1e7721db9b 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoHashBoundedPredicate.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoHashBoundedPredicate.java @@ -18,11 +18,13 @@ */ public class GeoHashBoundedPredicate { + private final int precision; private final boolean crossesDateline; private final long maxHashes; private final GeoBoundingBox bbox; public GeoHashBoundedPredicate(int precision, GeoBoundingBox bbox) { + this.precision = precision; this.crossesDateline = bbox.right() < bbox.left(); this.bbox = bbox; final long hashesY = (long) Math.ceil(((bbox.top() - bbox.bottom()) / Geohash.latHeightInDegrees(precision)) + 1); @@ -69,4 +71,8 @@ private boolean intersects(double minX, double maxX, double minY, double maxY) { public long getMaxHashes() { return maxHashes; } + + public int precision() { + return precision; + } } diff --git a/x-pack/plugin/esql/build.gradle b/x-pack/plugin/esql/build.gradle index 03b32e3910216..5e19b53f1ff19 100644 --- a/x-pack/plugin/esql/build.gradle +++ b/x-pack/plugin/esql/build.gradle @@ -40,7 +40,8 @@ dependencies { implementation project('compute:ann') implementation project(':libs:dissect') implementation project(':libs:grok') - implementation project(':libs:h3') + api "org.apache.lucene:lucene-spatial3d:${versions.lucene}" + api project(":libs:h3") implementation project('arrow') // Also contains a dummy processor to allow compilation with unused annotations. @@ -69,6 +70,10 @@ dependencies { internalClusterTestImplementation project(":modules:mapper-extras") } +tasks.named("dependencyLicenses").configure { + mapping from: /lucene-.*/, to: 'lucene' +} + def generatedPath = "src/main/generated" def projectDirectory = project.layout.projectDirectory def generatedSourceDir = projectDirectory.dir(generatedPath) diff --git a/x-pack/plugin/esql/licenses/lucene-LICENSE.txt b/x-pack/plugin/esql/licenses/lucene-LICENSE.txt new file mode 100644 index 0000000000000..28b134f5f8e4d --- /dev/null +++ b/x-pack/plugin/esql/licenses/lucene-LICENSE.txt @@ -0,0 +1,475 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +Some code in core/src/java/org/apache/lucene/util/UnicodeUtil.java was +derived from unicode conversion examples available at +http://www.unicode.org/Public/PROGRAMS/CVTUTF. Here is the copyright +from those sources: + +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + + +Some code in core/src/java/org/apache/lucene/util/ArrayUtil.java was +derived from Python 2.4.2 sources available at +http://www.python.org. Full license is here: + + http://www.python.org/download/releases/2.4.2/license/ + +Some code in core/src/java/org/apache/lucene/util/UnicodeUtil.java was +derived from Python 3.1.2 sources available at +http://www.python.org. Full license is here: + + http://www.python.org/download/releases/3.1.2/license/ + +Some code in core/src/java/org/apache/lucene/util/automaton was +derived from Brics automaton sources available at +www.brics.dk/automaton/. Here is the copyright from those sources: + +/* + * Copyright (c) 2001-2009 Anders Moeller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +The levenshtein automata tables in core/src/java/org/apache/lucene/util/automaton +were automatically generated with the moman/finenight FSA package. +Here is the copyright for those sources: + +# Copyright (c) 2010, Jean-Philippe Barrette-LaPierre, +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. + +Some code in core/src/java/org/apache/lucene/util/UnicodeUtil.java was +derived from ICU (http://www.icu-project.org) +The full license is available here: + http://source.icu-project.org/repos/icu/icu/trunk/license.html + +/* + * Copyright (C) 1999-2010, International Business Machines + * Corporation and others. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * provided that the above copyright notice(s) and this permission notice appear + * in all copies of the Software and that both the above copyright notice(s) and + * this permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE + * LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR + * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall not + * be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization of the + * copyright holder. + */ + +The following license applies to the Snowball stemmers: + +Copyright (c) 2001, Dr Martin Porter +Copyright (c) 2002, Richard Boulton +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holders nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The following license applies to the KStemmer: + +Copyright © 2003, +Center for Intelligent Information Retrieval, +University of Massachusetts, Amherst. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. The names "Center for Intelligent Information Retrieval" and +"University of Massachusetts" must not be used to endorse or promote products +derived from this software without prior written permission. To obtain +permission, contact info@ciir.cs.umass.edu. + +THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF MASSACHUSETTS AND OTHER CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +The following license applies to the Morfologik project: + +Copyright (c) 2006 Dawid Weiss +Copyright (c) 2007-2011 Dawid Weiss, Marcin Miłkowski +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Morfologik nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- + +The dictionary comes from Morfologik project. Morfologik uses data from +Polish ispell/myspell dictionary hosted at http://www.sjp.pl/slownik/en/ and +is licenced on the terms of (inter alia) LGPL and Creative Commons +ShareAlike. The part-of-speech tags were added in Morfologik project and +are not found in the data from sjp.pl. The tagset is similar to IPI PAN +tagset. + +--- + +The following license applies to the Morfeusz project, +used by org.apache.lucene.analysis.morfologik. + +BSD-licensed dictionary of Polish (SGJP) +http://sgjp.pl/morfeusz/ + +Copyright © 2011 Zygmunt Saloni, Włodzimierz Gruszczyński, + Marcin Woliński, Robert Wołosz + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS “AS IS” AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/x-pack/plugin/esql/licenses/lucene-NOTICE.txt b/x-pack/plugin/esql/licenses/lucene-NOTICE.txt new file mode 100644 index 0000000000000..1a1d51572432a --- /dev/null +++ b/x-pack/plugin/esql/licenses/lucene-NOTICE.txt @@ -0,0 +1,192 @@ +Apache Lucene +Copyright 2014 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +Includes software from other Apache Software Foundation projects, +including, but not limited to: + - Apache Ant + - Apache Jakarta Regexp + - Apache Commons + - Apache Xerces + +ICU4J, (under analysis/icu) is licensed under an MIT styles license +and Copyright (c) 1995-2008 International Business Machines Corporation and others + +Some data files (under analysis/icu/src/data) are derived from Unicode data such +as the Unicode Character Database. See http://unicode.org/copyright.html for more +details. + +Brics Automaton (under core/src/java/org/apache/lucene/util/automaton) is +BSD-licensed, created by Anders Møller. See http://www.brics.dk/automaton/ + +The levenshtein automata tables (under core/src/java/org/apache/lucene/util/automaton) were +automatically generated with the moman/finenight FSA library, created by +Jean-Philippe Barrette-LaPierre. This library is available under an MIT license, +see http://sites.google.com/site/rrettesite/moman and +http://bitbucket.org/jpbarrette/moman/overview/ + +The class org.apache.lucene.util.WeakIdentityMap was derived from +the Apache CXF project and is Apache License 2.0. + +The Google Code Prettify is Apache License 2.0. +See http://code.google.com/p/google-code-prettify/ + +JUnit (junit-4.10) is licensed under the Common Public License v. 1.0 +See http://junit.sourceforge.net/cpl-v10.html + +This product includes code (JaspellTernarySearchTrie) from Java Spelling Checkin +g Package (jaspell): http://jaspell.sourceforge.net/ +License: The BSD License (http://www.opensource.org/licenses/bsd-license.php) + +The snowball stemmers in + analysis/common/src/java/net/sf/snowball +were developed by Martin Porter and Richard Boulton. +The snowball stopword lists in + analysis/common/src/resources/org/apache/lucene/analysis/snowball +were developed by Martin Porter and Richard Boulton. +The full snowball package is available from + http://snowball.tartarus.org/ + +The KStem stemmer in + analysis/common/src/org/apache/lucene/analysis/en +was developed by Bob Krovetz and Sergio Guzman-Lara (CIIR-UMass Amherst) +under the BSD-license. + +The Arabic,Persian,Romanian,Bulgarian, Hindi and Bengali analyzers (common) come with a default +stopword list that is BSD-licensed created by Jacques Savoy. These files reside in: +analysis/common/src/resources/org/apache/lucene/analysis/ar/stopwords.txt, +analysis/common/src/resources/org/apache/lucene/analysis/fa/stopwords.txt, +analysis/common/src/resources/org/apache/lucene/analysis/ro/stopwords.txt, +analysis/common/src/resources/org/apache/lucene/analysis/bg/stopwords.txt, +analysis/common/src/resources/org/apache/lucene/analysis/hi/stopwords.txt, +analysis/common/src/resources/org/apache/lucene/analysis/bn/stopwords.txt +See http://members.unine.ch/jacques.savoy/clef/index.html. + +The German,Spanish,Finnish,French,Hungarian,Italian,Portuguese,Russian and Swedish light stemmers +(common) are based on BSD-licensed reference implementations created by Jacques Savoy and +Ljiljana Dolamic. These files reside in: +analysis/common/src/java/org/apache/lucene/analysis/de/GermanLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/de/GermanMinimalStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/es/SpanishLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/fi/FinnishLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/fr/FrenchLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/fr/FrenchMinimalStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/hu/HungarianLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/it/ItalianLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/pt/PortugueseLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/ru/RussianLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/sv/SwedishLightStemmer.java + +The Stempel analyzer (stempel) includes BSD-licensed software developed +by the Egothor project http://egothor.sf.net/, created by Leo Galambos, Martin Kvapil, +and Edmond Nolan. + +The Polish analyzer (stempel) comes with a default +stopword list that is BSD-licensed created by the Carrot2 project. The file resides +in stempel/src/resources/org/apache/lucene/analysis/pl/stopwords.txt. +See http://project.carrot2.org/license.html. + +The SmartChineseAnalyzer source code (smartcn) was +provided by Xiaoping Gao and copyright 2009 by www.imdict.net. + +WordBreakTestUnicode_*.java (under modules/analysis/common/src/test/) +is derived from Unicode data such as the Unicode Character Database. +See http://unicode.org/copyright.html for more details. + +The Morfologik analyzer (morfologik) includes BSD-licensed software +developed by Dawid Weiss and Marcin Miłkowski (http://morfologik.blogspot.com/). + +Morfologik uses data from Polish ispell/myspell dictionary +(http://www.sjp.pl/slownik/en/) licenced on the terms of (inter alia) +LGPL and Creative Commons ShareAlike. + +Morfologic includes data from BSD-licensed dictionary of Polish (SGJP) +(http://sgjp.pl/morfeusz/) + +Servlet-api.jar and javax.servlet-*.jar are under the CDDL license, the original +source code for this can be found at http://www.eclipse.org/jetty/downloads.php + +=========================================================================== +Kuromoji Japanese Morphological Analyzer - Apache Lucene Integration +=========================================================================== + +This software includes a binary and/or source version of data from + + mecab-ipadic-2.7.0-20070801 + +which can be obtained from + + http://atilika.com/releases/mecab-ipadic/mecab-ipadic-2.7.0-20070801.tar.gz + +or + + http://jaist.dl.sourceforge.net/project/mecab/mecab-ipadic/2.7.0-20070801/mecab-ipadic-2.7.0-20070801.tar.gz + +=========================================================================== +mecab-ipadic-2.7.0-20070801 Notice +=========================================================================== + +Nara Institute of Science and Technology (NAIST), +the copyright holders, disclaims all warranties with regard to this +software, including all implied warranties of merchantability and +fitness, in no event shall NAIST be liable for +any special, indirect or consequential damages or any damages +whatsoever resulting from loss of use, data or profits, whether in an +action of contract, negligence or other tortuous action, arising out +of or in connection with the use or performance of this software. + +A large portion of the dictionary entries +originate from ICOT Free Software. The following conditions for ICOT +Free Software applies to the current dictionary as well. + +Each User may also freely distribute the Program, whether in its +original form or modified, to any third party or parties, PROVIDED +that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear +on, or be attached to, the Program, which is distributed substantially +in the same form as set out herein and that such intended +distribution, if actually made, will neither violate or otherwise +contravene any of the laws and regulations of the countries having +jurisdiction over the User or the intended distribution itself. + +NO WARRANTY + +The program was produced on an experimental basis in the course of the +research and development conducted during the project and is provided +to users as so produced on an experimental basis. Accordingly, the +program is provided without any warranty whatsoever, whether express, +implied, statutory or otherwise. The term "warranty" used herein +includes, but is not limited to, any warranty of the quality, +performance, merchantability and fitness for a particular purpose of +the program and the nonexistence of any infringement or violation of +any right of any third party. + +Each user of the program will agree and understand, and be deemed to +have agreed and understood, that there is no warranty whatsoever for +the program and, accordingly, the entire risk arising from or +otherwise connected with the program is assumed by the user. + +Therefore, neither ICOT, the copyright holder, or any other +organization that participated in or was otherwise related to the +development of the program and their respective officials, directors, +officers and other employees shall be held liable for any and all +damages, including, without limitation, general, special, incidental +and consequential damages, arising out of or otherwise in connection +with the use or inability to use the program or any product, material +or result produced or otherwise obtained by using the program, +regardless of whether they have been advised of, or otherwise had +knowledge of, the possibility of such damages at any time during the +project or thereafter. Each user will be deemed to have agreed to the +foregoing by his or her commencement of use of the program. The term +"use" as used herein includes, but is not limited to, the use, +modification, copying and distribution of the program and the +production of secondary products from the program. + +In the case where the program, whether in its original form or +modified, was distributed or delivered to or received by a user from +any person, organization or entity other than ICOT, unless it makes or +grants independently of ICOT any specific warranty to the user in +writing, such person, organization or entity, will also be exempted +from and not be held liable to the user for any such damages as noted +above as far as the program is concerned. diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvAssert.java b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvAssert.java index 3f8478fe713a3..83276d006273a 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvAssert.java +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvAssert.java @@ -323,7 +323,7 @@ private static String pipeTable( if (values.size() > rows) { result.append("...").append(System.lineSeparator()); } - return result.toString(); + return result.toString().replaceAll("\\s+" + System.lineSeparator(), System.lineSeparator()); } private static String header(String name, Type type) { diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index ecb63e5484054..c4b865fc8878d 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -181,13 +181,18 @@ FROM airports | SORT count DESC, geohashString ASC ; -count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape -19 | POINT (6.360728044651057 47.94084087577894) | u0 | BBOX (0.0, 11.25, 50.625, 45.0) -8 | POINT (6.351574736181647 51.8981519783847) | u1 | BBOX (0.0, 11.25, 56.25, 50.625) -7 | POINT (5.268637698941997 42.747250193330856) | sp | BBOX (0.0, 11.25, 45.0, 39.375) -4 | POINT (7.7012718468904495 36.39783004182391) | sn | BBOX (0.0, 11.25, 39.375, 33.75) -2 | POINT (11.7787727387622 48.351816879585385) | u2 | BBOX (11.25, 22.5, 50.625, 45.0) -1 | POINT (5.629810290411115 58.88215648010373) | u4 | BBOX (0.0, 11.25, 61.875, 56.25) +count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape +19 | POINT (6.360728044651057 47.94084087577894) | u0 | BBOX (0.0, 11.25, 50.625, 45.0) +10 | POINT (15.350638423115015 47.80751353036612) | u2 | BBOX (11.25, 22.5, 50.625, 45.0) +9 | POINT (18.5217544157058 42.1394603792578) | sr | BBOX (11.25, 22.5, 45.0, 39.375) +8 | POINT (6.351574736181647 51.8981519783847) | u1 | BBOX (0.0, 11.25, 56.25, 50.625) +7 | POINT (5.268637698941997 42.747250193330856) | sp | BBOX (0.0, 11.25, 45.0, 39.375) +7 | POINT (17.092350951528974 53.365471504096476) | u3 | BBOX (11.25, 22.5, 56.25, 50.625) +5 | POINT (16.2651440910995 58.812188878655434) | u6 | BBOX (11.25, 22.5, 61.875, 56.25) +4 | POINT (7.7012718468904495 36.39783004182391) | sn | BBOX (0.0, 11.25, 39.375, 33.75) +3 | POINT (14.222751930356026 37.168446206487715) | sq | BBOX (11.25, 22.5, 39.375, 33.75) +3 | POINT (7.318722177296877 59.788265260867774) | u4 | BBOX (0.0, 11.25, 61.875, 56.25) +2 | POINT (16.706149326637387 32.37822346854955) | sm | BBOX (11.25, 22.5, 33.75, 28.125) ; gridGeohashStatsByWhereUK @@ -229,9 +234,11 @@ FROM airports ; count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape +19 | POINT (6.360728044651057 47.94084087577894) | u0 | BBOX (0.0, 11.25, 50.625, 45.0) 17 | POINT (-3.5034258844440473 53.25306422789307) | gc | BBOX (-11.25, 0.0, 56.25, 50.625) +8 | POINT (6.351574736181647 51.8981519783847) | u1 | BBOX (0.0, 11.25, 56.25, 50.625) +3 | POINT (7.318722177296877 59.788265260867774) | u4 | BBOX (0.0, 11.25, 61.875, 56.25) 3 | POINT (-2.7510103583335876 58.79020635969937) | gf | BBOX (-11.25, 0.0, 61.875, 56.25) -1 | POINT (0.15865350142121315 49.36166098807007) | u0 | BBOX (0.0, 11.25, 50.625, 45.0) ; gridGeohashInStatsBy @@ -658,14 +665,16 @@ FROM airports count:long | centroid:geo_point | geohexString:keyword | cellBoundary:geo_shape 22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff | POLYGON ((1.1885095534434493 49.47027919866873, 2.026568965384636 45.18424868970643, 7.509948481928886 43.786609353945, 12.677317810359858 46.40695745798227, 12.345747364400065 50.55427508726938, 6.259687055981993 51.96477015603749, 3.6300086390995467 50.6104633125695, 1.1885095534434493 49.47027919866873)) -5 | POINT (3.6714368518441916 42.29731031600386) | 81397ffffffffff | POLYGON ((-2.4177958307002347 42.54047996565121, -1.416234262837718 38.1159967227654, 0.2387159546288331 37.58884624349159, 3.543589356987798 36.59789814478598, 8.045142114241353 39.40213636897177, 7.509948481928886 43.786609353945, 2.026568965384636 45.18424868970643, -2.4177958307002347 42.54047996565121)) -4 | POINT (4.188777215313166 51.50470834574662) | 81197ffffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -6.436337296790312 55.3773904155485, -4.889760342933795 51.22372845966177, 1.1885095534434493 49.47027919866873, 3.6300086390995365 50.610463312569514, 6.259687055981993 51.96477015603749, 5.523646549290304 55.70676846515228, -0.9315871635106163 57.689497374592854)) +17 | POINT (-0.7606179875266903 52.86413913565304) | 81197ffffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -6.436337296790312 55.3773904155485, -4.889760342933795 51.22372845966177, 1.1885095534434493 49.47027919866873, 3.6300086390995365 50.610463312569514, 6.259687055981993 51.96477015603749, 5.523646549290304 55.70676846515228, -0.9315871635106163 57.689497374592854)) +7 | POINT (2.475211258445467 41.32352174592337) | 81397ffffffffff | POLYGON ((-2.4177958307002347 42.54047996565121, -1.416234262837718 38.1159967227654, 0.2387159546288331 37.58884624349159, 3.543589356987798 36.59789814478598, 8.045142114241353 39.40213636897177, 7.509948481928886 43.786609353945, 2.026568965384636 45.18424868970643, -2.4177958307002347 42.54047996565121)) +6 | POINT (11.75047050230205 42.351422344800085) | 811ebffffffffff | POLYGON ((7.509948481928886 43.786609353945, 8.045142114241353 39.40213636897177, 13.244313475659823 37.5237123657852, 18.325260281104846 39.988177963363235, 18.314740441319 44.47067958889503, 12.677317810359858 46.40695745798227, 7.509948481928886 43.786609353945)) +5 | POINT (18.766171680763364 59.15833930950612) | 8108bffffffffff | POLYGON ((11.080660058482376 61.54051460002519, 11.555977692900722 58.13053116585142, 18.2752359517578 56.63295271905082, 25.082722326707877 58.4015448703527, 24.517172437523495 62.47811345192472, 17.53544630840839 63.800792653212156, 15.771773841154092 62.88996835796253, 11.080660058482376 61.54051460002519)) +5 | POINT (11.404999259859324 54.510593589395285) | 811f3ffffffffff | POLYGON ((5.523646549290313 55.70676846515226, 6.259687055981993 51.96477015603749, 12.345747364400065 50.55427508726938, 18.289963485942284 52.81905199947076, 18.2752359517578 56.63295271905082, 11.555977692900722 58.13053116585142, 5.523646549290313 55.70676846515226)) +4 | POINT (5.167026452254504 59.81037143385038) | 8109bffffffffff | POLYGON ((4.012620898449951 63.32706132801842, -2.297526087621831 61.54550957788076, -0.9315871635106163 57.689497374592854, 5.523646549290304 55.70676846515228, 11.555977692900722 58.13053116585142, 11.080660058482376 61.54051460002519, 8.644221197607186 61.8908384753262, 4.012620898449951 63.32706132801842)) +4 | POINT (-1.1871178611181676 35.77457194332965) | 81383ffffffffff | POLYGON ((-5.442348460730093 35.12442405176796, -4.341769247156951 30.69897412778907, -1.2408020165138167 29.828776159725596, 0.26094682603113584 29.300374659234986, 4.204173995672654 32.11010693139568, 3.543589356987798 36.59789814478598, 0.2387159546288331 37.58884624349159, -1.416234262837718 38.1159967227654, -5.442348460730093 35.12442405176796)) +3 | POINT (-1.1497433669865131 45.83295159973204) | 81187ffffffffff | POLYGON ((-4.889760342933795 51.22372845966177, -9.724736207832692 48.43009421958323, -8.101589192291552 44.0506310521871, -2.4177958307002347 42.54047996565121, 2.026568965384605 45.18424868970644, 1.1885095534434493 49.47027919866873, -4.889760342933795 51.22372845966177)) 3 | POINT (9.197671310976148 36.29719984252006) | 81387ffffffffff | POLYGON ((3.543589356987798 36.59789814478598, 4.204173995672654 32.11010693139568, 8.974635637589913 30.254840780701706, 13.488580338198277 32.87501547725471, 13.244313475659823 37.5237123657852, 8.045142114241353 39.40213636897177, 3.543589356987798 36.59789814478598)) -2 | POINT (9.261639816686511 43.87209988664836) | 811ebffffffffff | POLYGON ((7.509948481928886 43.786609353945, 8.045142114241353 39.40213636897177, 13.244313475659823 37.5237123657852, 18.325260281104846 39.988177963363235, 18.314740441319 44.47067958889503, 12.677317810359858 46.40695745798227, 7.509948481928886 43.786609353945)) -2 | POINT (9.395754751749337 53.3421441167593) | 811f3ffffffffff | POLYGON ((5.523646549290313 55.70676846515226, 6.259687055981993 51.96477015603749, 12.345747364400065 50.55427508726938, 18.289963485942284 52.81905199947076, 18.2752359517578 56.63295271905082, 11.555977692900722 58.13053116585142, 5.523646549290313 55.70676846515226)) -1 | POINT (5.629810290411115 58.88215648010373) | 8109bffffffffff | POLYGON ((4.012620898449951 63.32706132801842, -2.297526087621831 61.54550957788076, -0.9315871635106163 57.689497374592854, 5.523646549290304 55.70676846515228, 11.555977692900722 58.13053116585142, 11.080660058482376 61.54051460002519, 8.644221197607186 61.8908384753262, 4.012620898449951 63.32706132801842)) -1 | POINT (0.15865350142121315 49.36166098807007) | 81187ffffffffff | POLYGON ((-4.889760342933795 51.22372845966177, -9.724736207832692 48.43009421958323, -8.101589192291552 44.0506310521871, -2.4177958307002347 42.54047996565121, 2.026568965384605 45.18424868970644, 1.1885095534434493 49.47027919866873, -4.889760342933795 51.22372845966177)) -1 | POINT (3.212073454633355 36.69972063973546) | 81383ffffffffff | POLYGON ((-5.442348460730093 35.12442405176796, -4.341769247156951 30.69897412778907, -1.2408020165138167 29.828776159725596, 0.26094682603113584 29.300374659234986, 4.204173995672654 32.11010693139568, 3.543589356987798 36.59789814478598, 0.2387159546288331 37.58884624349159, -1.416234262837718 38.1159967227654, -5.442348460730093 35.12442405176796)) +1 | POINT (13.144258903339505 32.66916951164603) | 813fbffffffffff | POLYGON ((8.974635637589913 30.254840780701706, 9.380676605201614 25.60370257696876, 13.915183885634578 23.45043771532035, 18.351304577591982 25.86678026136113, 18.343416368196834 30.62734805513404, 13.488580338198277 32.87501547725471, 8.974635637589913 30.254840780701706)) ; gridGeohexStatsByWhereUK @@ -712,13 +721,17 @@ count:long | centroid:geo_point | geohexString:keywo 5 | POINT (-1.7227098606526852 51.717823022045195) | 82195ffffffffff | POLYGON ((-2.1788859209290505 53.251551050714795, -4.578382413982977 52.792439042763036, -4.889760342933795 51.22372845966177, -2.906527879284175 50.14229216995713, -0.6310947579755295 50.60191112048408, -0.21913743445926337 52.1416808182628, -2.1788859209290505 53.251551050714795)) 4 | POINT (-3.9897833741270006 54.21732849790715) | 821957fffffffff | POLYGON ((-3.9031812914854935 55.840605806464886, -6.436337296790312 55.3773904155485, -6.713499065102683 53.841053788108646, -4.578382413982977 52.792439042763036, -2.1788859209290505 53.251551050714795, -1.7855433613316123 54.76238836624054, -3.9031812914854935 55.840605806464886)) 3 | POINT (-7.885485291481018 52.65633414499462) | 82182ffffffffff | POLYGON ((-6.713499065102683 53.841053788108646, -9.16699332513357 53.28908444969493, -9.362891292036808 51.69686278886942, -7.224493860559402 50.67904691252102, -4.889760342933795 51.22372845966177, -4.578382413982977 52.792439042763036, -6.713499065102683 53.841053788108646)) +3 | POINT (3.0334555450826883 48.842039234004915) | 821fb7fffffffff | POLYGON ((1.1885095534434493 49.47027919866873, 0.7640259623867446 47.90745035042651, 2.458901717447715 46.76373050573097, 4.652435425239358 47.393027403288, 5.163510941569062 48.943763955054884, 3.3847715100589153 49.85377035058955, 1.1885095534434493 49.47027919866873)) +2 | POINT (5.428531668148935 59.585608751513064) | 820987fffffffff | POLYGON ((5.479068693190393 60.92198553471913, 2.767527791540729 60.73321011494055, 2.198216040575142 59.383886486983954, 4.229785449235632 58.25202580757624, 6.766112799653718 58.44709614018101, 7.4384643434389535 59.76718020289119, 5.479068693190393 60.92198553471913)) 2 | POINT (-4.2476349184289575 56.70184155693278) | 82190ffffffffff | POLYGON ((-5.832270115239392 58.353838498476094, -8.508655388670189 57.8811306023458, -8.740899630542538 56.38258811071853, -6.436337296790312 55.3773904155485, -3.9031812914854935 55.840605806464886, -3.536381138969186 57.31728796714347, -5.832270115239392 58.353838498476094)) +2 | POINT (1.4715016074478626 50.863699545152485) | 82194ffffffffff | POLYGON ((2.101313983947425 52.51713397842229, -0.21913743445926337 52.1416808182628, -0.6310947579755295 50.60191112048408, 1.1885095534434493 49.47027919866873, 3.384771510058846 49.85377035058955, 3.8811335596706074 51.360376195950145, 2.101313983947425 52.51713397842229)) +2 | POINT (4.5991105819121 52.129031270742416) | 82196ffffffffff | POLYGON ((4.948742151508294 54.2882866932292, 2.592789031305367 53.99775155222293, 2.101313983947425 52.51713397842229, 3.8811335596706074 51.360376195950145, 6.259687055981993 51.96477015603749, 6.8482289070479005 53.43156035343158, 4.948742151508294 54.2882866932292)) 2 | POINT (-2.5373152876272798 55.49281941493973) | 821977fffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -3.536381138969186 57.31728796714347, -3.9031812914854935 55.840605806464886, -1.7855433613316123 54.76238836624054, 0.6707588590220377 55.133805943055435, 1.1521975506221078 56.583354389307445, -0.9315871635106163 57.689497374592854)) 1 | POINT (-1.2880607228726149 59.87668995279819) | 8209a7fffffffff | POLYGON ((0.5480202135218006 61.82886471359379, -2.297526087621831 61.54550957788076, -2.7356231170279166 60.17050935552437, -0.4671324618104694 59.1035939329508, 2.198216040575142 59.383886486983954, 2.767527791540729 60.73321011494055, 0.5480202135218006 61.82886471359379)) 1 | POINT (0.15865350142121315 49.36166098807007) | 821867fffffffff | POLYGON ((-0.6310947579755295 50.60191112048408, -2.906527879284175 50.14229216995713, -3.2436562689082553 48.547301491418715, -1.3966081625912774 47.44351195977148, 0.7640259623867446 47.90745035042651, 1.1885095534434493 49.47027919866873, -0.6310947579755295 50.60191112048408)) +1 | POINT (-7.270800014957786 62.06249998882413) | 821927fffffffff | POLYGON ((-4.777634484041529 62.56377272218282, -7.72004205669337 62.172198741500715, -7.999682127502827 60.77664727688846, -5.502334925300172 59.7918551703578, -2.7356231170279166 60.17050935552437, -2.297526087621831 61.54550957788076, -4.777634484041529 62.56377272218282)) 1 | POINT (-2.9013785161077976 58.95442885346711) | 82192ffffffffff | POLYGON ((-2.7356231170279166 60.17050935552437, -5.502334925300172 59.7918551703578, -5.832270115239392 58.353838498476094, -3.536381138969186 57.31728796714347, -0.9315871635106163 57.689497374592854, -0.4671324618104694 59.1035939329508, -2.7356231170279166 60.17050935552437)) 1 | POINT (-1.6598310694098473 53.8690819311887) | 821947fffffffff | POLYGON ((0.6707588590220377 55.133805943055435, -1.7855433613316123 54.76238836624054, -2.1788859209290505 53.251551050714795, -0.21913743445926337 52.1416808182628, 2.101313983947425 52.51713397842229, 2.592789031305367 53.99775155222293, 0.6707588590220377 55.133805943055435)) -1 | POINT (-0.16296171583235264 51.1557567352429) | 82194ffffffffff | POLYGON ((2.101313983947425 52.51713397842229, -0.21913743445926337 52.1416808182628, -0.6310947579755295 50.60191112048408, 1.1885095534434493 49.47027919866873, 3.384771510058846 49.85377035058955, 3.8811335596706074 51.360376195950145, 2.101313983947425 52.51713397842229)) ; gridGeohexInStatsByBounds @@ -736,7 +749,7 @@ FROM airports ; count:long | centroid:geo_point -850 | POINT (-0.347950274354833 23.284863485719132) +827 | POINT (-0.5615898292227913 22.56591850424922) 6 | POINT (5.582276992499828 50.72238312335685) 5 | POINT (8.6918301936239 45.19817395694554) ; diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldAndLiteralEvaluator.java index 052e031de3461..dafbf8836e46f 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndFieldAndLiteralEvaluator.java @@ -7,6 +7,7 @@ import java.lang.IllegalArgumentException; import java.lang.Override; import java.lang.String; +import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; @@ -16,7 +17,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -30,7 +30,7 @@ public final class StGeohashFromFieldAndFieldAndLiteralEvaluator implements Eval private final EvalOperator.ExpressionEvaluator precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; private final DriverContext driverContext; @@ -38,11 +38,11 @@ public final class StGeohashFromFieldAndFieldAndLiteralEvaluator implements Eval public StGeohashFromFieldAndFieldAndLiteralEvaluator(Source source, EvalOperator.ExpressionEvaluator in, EvalOperator.ExpressionEvaluator precision, - Rectangle bounds, DriverContext driverContext) { + GeoBoundingBox bbox, DriverContext driverContext) { this.source = source; this.in = in; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; this.driverContext = driverContext; } @@ -78,7 +78,7 @@ public LongBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisi continue position; } try { - StGeohash.fromFieldAndFieldAndLiteral(result, p, inBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds); + StGeohash.fromFieldAndFieldAndLiteral(result, p, inBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bbox); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -90,7 +90,7 @@ public LongBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisi @Override public String toString() { - return "StGeohashFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohashFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bbox=" + bbox + "]"; } @Override @@ -117,24 +117,24 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, - EvalOperator.ExpressionEvaluator.Factory precision, Rectangle bounds) { + EvalOperator.ExpressionEvaluator.Factory precision, GeoBoundingBox bbox) { this.source = source; this.in = in; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; } @Override public StGeohashFromFieldAndFieldAndLiteralEvaluator get(DriverContext context) { - return new StGeohashFromFieldAndFieldAndLiteralEvaluator(source, in.get(context), precision.get(context), bounds, context); + return new StGeohashFromFieldAndFieldAndLiteralEvaluator(source, in.get(context), precision.get(context), bbox, context); } @Override public String toString() { - return "StGeohashFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohashFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bbox=" + bbox + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java index c3148b57d8145..811d39e8cb36f 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java @@ -15,7 +15,7 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoHashBoundedPredicate; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -27,20 +27,17 @@ public final class StGeohashFromFieldAndLiteralAndLiteralEvaluator implements Ev private final EvalOperator.ExpressionEvaluator in; - private final int precision; - - private final Rectangle bounds; + private final GeoHashBoundedPredicate bounds; private final DriverContext driverContext; private Warnings warnings; public StGeohashFromFieldAndLiteralAndLiteralEvaluator(Source source, - EvalOperator.ExpressionEvaluator in, int precision, Rectangle bounds, + EvalOperator.ExpressionEvaluator in, GeoHashBoundedPredicate bounds, DriverContext driverContext) { this.source = source; this.in = in; - this.precision = precision; this.bounds = bounds; this.driverContext = driverContext; } @@ -64,7 +61,7 @@ public LongBlock eval(int positionCount, BytesRefBlock inBlock) { continue position; } try { - StGeohash.fromFieldAndLiteralAndLiteral(result, p, inBlock, this.precision, this.bounds); + StGeohash.fromFieldAndLiteralAndLiteral(result, p, inBlock, this.bounds); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -76,7 +73,7 @@ public LongBlock eval(int positionCount, BytesRefBlock inBlock) { @Override public String toString() { - return "StGeohashFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohashFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", bounds=" + bounds + "]"; } @Override @@ -101,26 +98,23 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory in; - private final int precision; - - private final Rectangle bounds; + private final GeoHashBoundedPredicate bounds; - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, int precision, - Rectangle bounds) { + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, + GeoHashBoundedPredicate bounds) { this.source = source; this.in = in; - this.precision = precision; this.bounds = bounds; } @Override public StGeohashFromFieldAndLiteralAndLiteralEvaluator get(DriverContext context) { - return new StGeohashFromFieldAndLiteralAndLiteralEvaluator(source, in.get(context), precision, bounds, context); + return new StGeohashFromFieldAndLiteralAndLiteralEvaluator(source, in.get(context), bounds, context); } @Override public String toString() { - return "StGeohashFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohashFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", bounds=" + bounds + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator.java index 9fe17446d565d..c5e2f6a651825 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator.java @@ -7,6 +7,7 @@ import java.lang.IllegalArgumentException; import java.lang.Override; import java.lang.String; +import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.LongBlock; @@ -15,7 +16,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -29,7 +29,7 @@ public final class StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator implem private final EvalOperator.ExpressionEvaluator precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; private final DriverContext driverContext; @@ -37,11 +37,11 @@ public final class StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator implem public StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator(Source source, EvalOperator.ExpressionEvaluator encoded, EvalOperator.ExpressionEvaluator precision, - Rectangle bounds, DriverContext driverContext) { + GeoBoundingBox bbox, DriverContext driverContext) { this.source = source; this.encoded = encoded; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; this.driverContext = driverContext; } @@ -77,7 +77,7 @@ public LongBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precis continue position; } try { - StGeohash.fromFieldDocValuesAndFieldAndLiteral(result, p, encodedBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds); + StGeohash.fromFieldDocValuesAndFieldAndLiteral(result, p, encodedBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bbox); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -89,7 +89,7 @@ public LongBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precis @Override public String toString() { - return "StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bbox=" + bbox + "]"; } @Override @@ -116,24 +116,24 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, - EvalOperator.ExpressionEvaluator.Factory precision, Rectangle bounds) { + EvalOperator.ExpressionEvaluator.Factory precision, GeoBoundingBox bbox) { this.source = source; this.encoded = encoded; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; } @Override public StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator get(DriverContext context) { - return new StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator(source, encoded.get(context), precision.get(context), bounds, context); + return new StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator(source, encoded.get(context), precision.get(context), bbox, context); } @Override public String toString() { - return "StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohashFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bbox=" + bbox + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java index 561c14d6ec7b4..e740f0948ba22 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java @@ -14,7 +14,7 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoHashBoundedPredicate; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -26,20 +26,17 @@ public final class StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator impl private final EvalOperator.ExpressionEvaluator encoded; - private final int precision; - - private final Rectangle bounds; + private final GeoHashBoundedPredicate bounds; private final DriverContext driverContext; private Warnings warnings; public StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator(Source source, - EvalOperator.ExpressionEvaluator encoded, int precision, Rectangle bounds, + EvalOperator.ExpressionEvaluator encoded, GeoHashBoundedPredicate bounds, DriverContext driverContext) { this.source = source; this.encoded = encoded; - this.precision = precision; this.bounds = bounds; this.driverContext = driverContext; } @@ -63,7 +60,7 @@ public LongBlock eval(int positionCount, LongBlock encodedBlock) { continue position; } try { - StGeohash.fromFieldDocValuesAndLiteralAndLiteral(result, p, encodedBlock, this.precision, this.bounds); + StGeohash.fromFieldDocValuesAndLiteralAndLiteral(result, p, encodedBlock, this.bounds); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -75,7 +72,7 @@ public LongBlock eval(int positionCount, LongBlock encodedBlock) { @Override public String toString() { - return "StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", bounds=" + bounds + "]"; } @Override @@ -100,26 +97,23 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory encoded; - private final int precision; - - private final Rectangle bounds; + private final GeoHashBoundedPredicate bounds; - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, int precision, - Rectangle bounds) { + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, + GeoHashBoundedPredicate bounds) { this.source = source; this.encoded = encoded; - this.precision = precision; this.bounds = bounds; } @Override public StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator get(DriverContext context) { - return new StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator(source, encoded.get(context), precision, bounds, context); + return new StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator(source, encoded.get(context), bounds, context); } @Override public String toString() { - return "StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", bounds=" + bounds + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldAndLiteralEvaluator.java index 4518bc56d6ffb..11b7e9d8e220c 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromLiteralAndFieldAndLiteralEvaluator.java @@ -8,6 +8,7 @@ import java.lang.Override; import java.lang.String; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.IntVector; @@ -17,7 +18,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -31,18 +31,19 @@ public final class StGeohashFromLiteralAndFieldAndLiteralEvaluator implements Ev private final EvalOperator.ExpressionEvaluator precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; private final DriverContext driverContext; private Warnings warnings; public StGeohashFromLiteralAndFieldAndLiteralEvaluator(Source source, BytesRef in, - EvalOperator.ExpressionEvaluator precision, Rectangle bounds, DriverContext driverContext) { + EvalOperator.ExpressionEvaluator precision, GeoBoundingBox bbox, + DriverContext driverContext) { this.source = source; this.in = in; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; this.driverContext = driverContext; } @@ -72,7 +73,7 @@ public LongBlock eval(int positionCount, IntBlock precisionBlock) { continue position; } try { - result.appendLong(StGeohash.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds)); + result.appendLong(StGeohash.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bbox)); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -86,7 +87,7 @@ public LongBlock eval(int positionCount, IntVector precisionVector) { try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { try { - result.appendLong(StGeohash.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bounds)); + result.appendLong(StGeohash.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bbox)); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -98,7 +99,7 @@ public LongBlock eval(int positionCount, IntVector precisionVector) { @Override public String toString() { - return "StGeohashFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohashFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bbox=" + bbox + "]"; } @Override @@ -125,24 +126,24 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; public Factory(Source source, BytesRef in, EvalOperator.ExpressionEvaluator.Factory precision, - Rectangle bounds) { + GeoBoundingBox bbox) { this.source = source; this.in = in; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; } @Override public StGeohashFromLiteralAndFieldAndLiteralEvaluator get(DriverContext context) { - return new StGeohashFromLiteralAndFieldAndLiteralEvaluator(source, in, precision.get(context), bounds, context); + return new StGeohashFromLiteralAndFieldAndLiteralEvaluator(source, in, precision.get(context), bbox, context); } @Override public String toString() { - return "StGeohashFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohashFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bbox=" + bbox + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldAndLiteralEvaluator.java index 712d08ef31c82..eb956fa8b37b1 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndFieldAndLiteralEvaluator.java @@ -7,6 +7,7 @@ import java.lang.IllegalArgumentException; import java.lang.Override; import java.lang.String; +import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.IntBlock; @@ -16,7 +17,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -30,7 +30,7 @@ public final class StGeohexFromFieldAndFieldAndLiteralEvaluator implements EvalO private final EvalOperator.ExpressionEvaluator precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; private final DriverContext driverContext; @@ -38,11 +38,11 @@ public final class StGeohexFromFieldAndFieldAndLiteralEvaluator implements EvalO public StGeohexFromFieldAndFieldAndLiteralEvaluator(Source source, EvalOperator.ExpressionEvaluator in, EvalOperator.ExpressionEvaluator precision, - Rectangle bounds, DriverContext driverContext) { + GeoBoundingBox bbox, DriverContext driverContext) { this.source = source; this.in = in; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; this.driverContext = driverContext; } @@ -78,7 +78,7 @@ public LongBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisi continue position; } try { - StGeohex.fromFieldAndFieldAndLiteral(result, p, inBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds); + StGeohex.fromFieldAndFieldAndLiteral(result, p, inBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bbox); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -90,7 +90,7 @@ public LongBlock eval(int positionCount, BytesRefBlock inBlock, IntBlock precisi @Override public String toString() { - return "StGeohexFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohexFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bbox=" + bbox + "]"; } @Override @@ -117,24 +117,24 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, - EvalOperator.ExpressionEvaluator.Factory precision, Rectangle bounds) { + EvalOperator.ExpressionEvaluator.Factory precision, GeoBoundingBox bbox) { this.source = source; this.in = in; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; } @Override public StGeohexFromFieldAndFieldAndLiteralEvaluator get(DriverContext context) { - return new StGeohexFromFieldAndFieldAndLiteralEvaluator(source, in.get(context), precision.get(context), bounds, context); + return new StGeohexFromFieldAndFieldAndLiteralEvaluator(source, in.get(context), precision.get(context), bbox, context); } @Override public String toString() { - return "StGeohexFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohexFromFieldAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bbox=" + bbox + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java index cccd3a52ad9e2..e5b9799d3856f 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java @@ -15,7 +15,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -27,20 +26,17 @@ public final class StGeohexFromFieldAndLiteralAndLiteralEvaluator implements Eva private final EvalOperator.ExpressionEvaluator in; - private final int precision; - - private final Rectangle bounds; + private final GeoHexBoundedPredicate bounds; private final DriverContext driverContext; private Warnings warnings; public StGeohexFromFieldAndLiteralAndLiteralEvaluator(Source source, - EvalOperator.ExpressionEvaluator in, int precision, Rectangle bounds, + EvalOperator.ExpressionEvaluator in, GeoHexBoundedPredicate bounds, DriverContext driverContext) { this.source = source; this.in = in; - this.precision = precision; this.bounds = bounds; this.driverContext = driverContext; } @@ -64,7 +60,7 @@ public LongBlock eval(int positionCount, BytesRefBlock inBlock) { continue position; } try { - StGeohex.fromFieldAndLiteralAndLiteral(result, p, inBlock, this.precision, this.bounds); + StGeohex.fromFieldAndLiteralAndLiteral(result, p, inBlock, this.bounds); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -76,7 +72,7 @@ public LongBlock eval(int positionCount, BytesRefBlock inBlock) { @Override public String toString() { - return "StGeohexFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohexFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", bounds=" + bounds + "]"; } @Override @@ -101,26 +97,23 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory in; - private final int precision; - - private final Rectangle bounds; + private final GeoHexBoundedPredicate bounds; - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, int precision, - Rectangle bounds) { + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, + GeoHexBoundedPredicate bounds) { this.source = source; this.in = in; - this.precision = precision; this.bounds = bounds; } @Override public StGeohexFromFieldAndLiteralAndLiteralEvaluator get(DriverContext context) { - return new StGeohexFromFieldAndLiteralAndLiteralEvaluator(source, in.get(context), precision, bounds, context); + return new StGeohexFromFieldAndLiteralAndLiteralEvaluator(source, in.get(context), bounds, context); } @Override public String toString() { - return "StGeohexFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohexFromFieldAndLiteralAndLiteralEvaluator[" + "in=" + in + ", bounds=" + bounds + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator.java index 2b328aa303609..c8b750048d141 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator.java @@ -7,6 +7,7 @@ import java.lang.IllegalArgumentException; import java.lang.Override; import java.lang.String; +import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.LongBlock; @@ -15,7 +16,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -29,7 +29,7 @@ public final class StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator impleme private final EvalOperator.ExpressionEvaluator precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; private final DriverContext driverContext; @@ -37,11 +37,11 @@ public final class StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator impleme public StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator(Source source, EvalOperator.ExpressionEvaluator encoded, EvalOperator.ExpressionEvaluator precision, - Rectangle bounds, DriverContext driverContext) { + GeoBoundingBox bbox, DriverContext driverContext) { this.source = source; this.encoded = encoded; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; this.driverContext = driverContext; } @@ -77,7 +77,7 @@ public LongBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precis continue position; } try { - StGeohex.fromFieldDocValuesAndFieldAndLiteral(result, p, encodedBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds); + StGeohex.fromFieldDocValuesAndFieldAndLiteral(result, p, encodedBlock, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bbox); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -89,7 +89,7 @@ public LongBlock eval(int positionCount, LongBlock encodedBlock, IntBlock precis @Override public String toString() { - return "StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bbox=" + bbox + "]"; } @Override @@ -116,24 +116,24 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, - EvalOperator.ExpressionEvaluator.Factory precision, Rectangle bounds) { + EvalOperator.ExpressionEvaluator.Factory precision, GeoBoundingBox bbox) { this.source = source; this.encoded = encoded; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; } @Override public StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator get(DriverContext context) { - return new StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator(source, encoded.get(context), precision.get(context), bounds, context); + return new StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator(source, encoded.get(context), precision.get(context), bbox, context); } @Override public String toString() { - return "StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohexFromFieldDocValuesAndFieldAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bbox=" + bbox + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java index 41d0926b0069e..6f95dfae7ab91 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java @@ -14,7 +14,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -26,20 +25,17 @@ public final class StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator imple private final EvalOperator.ExpressionEvaluator encoded; - private final int precision; - - private final Rectangle bounds; + private final GeoHexBoundedPredicate bounds; private final DriverContext driverContext; private Warnings warnings; public StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator(Source source, - EvalOperator.ExpressionEvaluator encoded, int precision, Rectangle bounds, + EvalOperator.ExpressionEvaluator encoded, GeoHexBoundedPredicate bounds, DriverContext driverContext) { this.source = source; this.encoded = encoded; - this.precision = precision; this.bounds = bounds; this.driverContext = driverContext; } @@ -63,7 +59,7 @@ public LongBlock eval(int positionCount, LongBlock encodedBlock) { continue position; } try { - StGeohex.fromFieldDocValuesAndLiteralAndLiteral(result, p, encodedBlock, this.precision, this.bounds); + StGeohex.fromFieldDocValuesAndLiteralAndLiteral(result, p, encodedBlock, this.bounds); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -75,7 +71,7 @@ public LongBlock eval(int positionCount, LongBlock encodedBlock) { @Override public String toString() { - return "StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", bounds=" + bounds + "]"; } @Override @@ -100,26 +96,23 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory encoded; - private final int precision; - - private final Rectangle bounds; + private final GeoHexBoundedPredicate bounds; - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, int precision, - Rectangle bounds) { + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, + GeoHexBoundedPredicate bounds) { this.source = source; this.encoded = encoded; - this.precision = precision; this.bounds = bounds; } @Override public StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator get(DriverContext context) { - return new StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator(source, encoded.get(context), precision, bounds, context); + return new StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator(source, encoded.get(context), bounds, context); } @Override public String toString() { - return "StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator[" + "encoded=" + encoded + ", bounds=" + bounds + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldAndLiteralEvaluator.java index d0af7080c784b..ff03bbf920760 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromLiteralAndFieldAndLiteralEvaluator.java @@ -8,6 +8,7 @@ import java.lang.Override; import java.lang.String; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.compute.data.IntVector; @@ -17,7 +18,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -31,18 +31,19 @@ public final class StGeohexFromLiteralAndFieldAndLiteralEvaluator implements Eva private final EvalOperator.ExpressionEvaluator precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; private final DriverContext driverContext; private Warnings warnings; public StGeohexFromLiteralAndFieldAndLiteralEvaluator(Source source, BytesRef in, - EvalOperator.ExpressionEvaluator precision, Rectangle bounds, DriverContext driverContext) { + EvalOperator.ExpressionEvaluator precision, GeoBoundingBox bbox, + DriverContext driverContext) { this.source = source; this.in = in; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; this.driverContext = driverContext; } @@ -72,7 +73,7 @@ public LongBlock eval(int positionCount, IntBlock precisionBlock) { continue position; } try { - result.appendLong(StGeohex.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bounds)); + result.appendLong(StGeohex.fromLiteralAndFieldAndLiteral(this.in, precisionBlock.getInt(precisionBlock.getFirstValueIndex(p)), this.bbox)); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -86,7 +87,7 @@ public LongBlock eval(int positionCount, IntVector precisionVector) { try(LongBlock.Builder result = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { position: for (int p = 0; p < positionCount; p++) { try { - result.appendLong(StGeohex.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bounds)); + result.appendLong(StGeohex.fromLiteralAndFieldAndLiteral(this.in, precisionVector.getInt(p), this.bbox)); } catch (IllegalArgumentException e) { warnings().registerException(e); result.appendNull(); @@ -98,7 +99,7 @@ public LongBlock eval(int positionCount, IntVector precisionVector) { @Override public String toString() { - return "StGeohexFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohexFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bbox=" + bbox + "]"; } @Override @@ -125,24 +126,24 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory precision; - private final Rectangle bounds; + private final GeoBoundingBox bbox; public Factory(Source source, BytesRef in, EvalOperator.ExpressionEvaluator.Factory precision, - Rectangle bounds) { + GeoBoundingBox bbox) { this.source = source; this.in = in; this.precision = precision; - this.bounds = bounds; + this.bbox = bbox; } @Override public StGeohexFromLiteralAndFieldAndLiteralEvaluator get(DriverContext context) { - return new StGeohexFromLiteralAndFieldAndLiteralEvaluator(source, in, precision.get(context), bounds, context); + return new StGeohexFromLiteralAndFieldAndLiteralEvaluator(source, in, precision.get(context), bbox, context); } @Override public String toString() { - return "StGeohexFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bounds=" + bounds + "]"; + return "StGeohexFromLiteralAndFieldAndLiteralEvaluator[" + "in=" + in + ", precision=" + precision + ", bbox=" + bbox + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalGeometry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalGeometry.java new file mode 100644 index 0000000000000..be43f576c7fdd --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalGeometry.java @@ -0,0 +1,227 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.common.spatial; + +import org.apache.lucene.geo.Component2D; +import org.apache.lucene.geo.GeoUtils; +import org.apache.lucene.geo.LatLonGeometry; +import org.apache.lucene.index.PointValues; +import org.apache.lucene.spatial3d.geom.GeoArea; +import org.apache.lucene.spatial3d.geom.GeoAreaFactory; +import org.apache.lucene.spatial3d.geom.GeoPolygon; +import org.apache.lucene.spatial3d.geom.LatLonBounds; +import org.apache.lucene.spatial3d.geom.PlanetModel; +import org.elasticsearch.h3.H3; + +/** + * Implementation of a lucene {@link LatLonGeometry} that covers the extent of a provided H3 bin. + * Note that H3 bin are polygons on the sphere. + * TODO: This class is a copy of the same class in org.elasticsearch.xpack.spatial.common, we should find a common location for it. + */ +class H3SphericalGeometry extends LatLonGeometry { + + private final long h3; + + H3SphericalGeometry(long h3) { + this.h3 = h3; + } + + @Override + protected Component2D toComponent2D() { + return new H3Polygon2D(h3); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o instanceof H3SphericalGeometry geom) { + return h3 == geom.h3; + } + return false; + } + + @Override + public int hashCode() { + return Long.hashCode(h3); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("H3 : "); + sb.append("\""); + sb.append(h3); + sb.append("\""); + return sb.toString(); + } + + private static class H3Polygon2D implements Component2D { + + // We want to make are edges a bit bigger because spatial3d and h3 edges do not fully agree in + // membership of points around he edges. + private static final double BBOX_EDGE_DELTA = 1e-4; + private final long h3; + private final int res; + private final GeoPolygon hexagon; + private final double minX, maxX, minY, maxY; + + private H3Polygon2D(long h3) { + this.h3 = h3; + this.res = H3.getResolution(h3); + this.hexagon = H3SphericalUtil.toGeoPolygon(h3); + final LatLonBounds bounds = new LatLonBounds(); + this.hexagon.getBounds(bounds); + final double minY = bounds.checkNoBottomLatitudeBound() ? GeoUtils.MIN_LAT_INCL : Math.toDegrees(bounds.getMinLatitude()); + final double maxY = bounds.checkNoTopLatitudeBound() ? GeoUtils.MAX_LAT_INCL : Math.toDegrees(bounds.getMaxLatitude()); + final double minX; + final double maxX; + if (bounds.checkNoLongitudeBound() || bounds.getLeftLongitude() > bounds.getRightLongitude()) { + minX = GeoUtils.MIN_LON_INCL; + maxX = GeoUtils.MAX_LON_INCL; + } else { + minX = Math.toDegrees(bounds.getLeftLongitude()); + maxX = Math.toDegrees(bounds.getRightLongitude()); + } + // Unfortunately, h3 bin edges are fuzzy and cannot be represented easily. We need to buffer + // the bounding boxes to make sure we don't reject valid points + this.minX = Math.max(GeoUtils.MIN_LON_INCL, minX - BBOX_EDGE_DELTA); + this.maxX = Math.min(GeoUtils.MAX_LON_INCL, maxX + BBOX_EDGE_DELTA); + this.minY = Math.max(GeoUtils.MIN_LAT_INCL, minY - BBOX_EDGE_DELTA); + this.maxY = Math.min(GeoUtils.MAX_LAT_INCL, maxY + BBOX_EDGE_DELTA); + + } + + @Override + public double getMinX() { + return minX; + } + + @Override + public double getMaxX() { + return maxX; + } + + @Override + public double getMinY() { + return minY; + } + + @Override + public double getMaxY() { + return maxY; + } + + @Override + public boolean contains(double x, double y) { + return h3 == H3.geoToH3(y, x, res); + } + + @Override + public PointValues.Relation relate(double minX, double maxX, double minY, double maxY) { + if (minX > this.maxX || maxX < this.minX || maxY < this.minY || minY > this.maxY) { + return PointValues.Relation.CELL_OUTSIDE_QUERY; + } + // h3 edges are fuzzy, therefore to avoid issues when bounding box are around the edges, + // we just buffer slightly the bounding box to check if it is inside the h3 bin, otherwise + // return crosses. + final GeoArea box = GeoAreaFactory.makeGeoArea( + PlanetModel.SPHERE, + Math.toRadians(Math.min(GeoUtils.MAX_LAT_INCL, maxY + BBOX_EDGE_DELTA)), + Math.toRadians(Math.max(GeoUtils.MIN_LAT_INCL, minY - BBOX_EDGE_DELTA)), + Math.toRadians(Math.max(GeoUtils.MIN_LON_INCL, minX - BBOX_EDGE_DELTA)), + Math.toRadians(Math.min(GeoUtils.MAX_LON_INCL, maxX + BBOX_EDGE_DELTA)) + ); + return switch (box.getRelationship(hexagon)) { + case GeoArea.CONTAINS -> PointValues.Relation.CELL_INSIDE_QUERY; + case GeoArea.DISJOINT -> PointValues.Relation.CELL_OUTSIDE_QUERY; + default -> PointValues.Relation.CELL_CROSSES_QUERY; + }; + } + + @Override + public boolean intersectsLine(double minX, double maxX, double minY, double maxY, double aX, double aY, double bX, double bY) { + throw new UnsupportedOperationException("intersectsLine not implemented in H3Polygon2D"); + } + + @Override + public boolean intersectsTriangle( + double minX, + double maxX, + double minY, + double maxY, + double aX, + double aY, + double bX, + double bY, + double cX, + double cY + ) { + throw new UnsupportedOperationException("intersectsTriangle not implemented in H3Polygon2D"); + } + + @Override + public boolean containsLine(double minX, double maxX, double minY, double maxY, double aX, double aY, double bX, double bY) { + throw new UnsupportedOperationException("containsLine not implemented in H3Polygon2D"); + } + + @Override + public boolean containsTriangle( + double minX, + double maxX, + double minY, + double maxY, + double aX, + double aY, + double bX, + double bY, + double cX, + double cY + ) { + throw new IllegalArgumentException(); + } + + @Override + public WithinRelation withinPoint(double x, double y) { + return contains(x, y) ? WithinRelation.NOTWITHIN : WithinRelation.DISJOINT; + } + + @Override + public WithinRelation withinLine( + double minX, + double maxX, + double minY, + double maxY, + double aX, + double aY, + boolean ab, + double bX, + double bY + ) { + throw new UnsupportedOperationException("withinLine not implemented in H3Polygon2D"); + } + + @Override + public WithinRelation withinTriangle( + double minX, + double maxX, + double minY, + double maxY, + double aX, + double aY, + boolean ab, + double bX, + double bY, + boolean bc, + double cX, + double cY, + boolean ca + ) { + throw new UnsupportedOperationException("withinTriangle not implemented in H3Polygon2D"); + } + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalUtil.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalUtil.java new file mode 100644 index 0000000000000..ee63b8cfb18d6 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalUtil.java @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.common.spatial; + +import org.apache.lucene.geo.LatLonGeometry; +import org.apache.lucene.spatial3d.geom.GeoPoint; +import org.apache.lucene.spatial3d.geom.GeoPolygon; +import org.apache.lucene.spatial3d.geom.GeoPolygonFactory; +import org.apache.lucene.spatial3d.geom.PlanetModel; +import org.elasticsearch.common.geo.GeoBoundingBox; +import org.elasticsearch.h3.CellBoundary; +import org.elasticsearch.h3.H3; +import org.elasticsearch.h3.LatLng; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiPredicate; + +/** + * Utility class for generating H3 spherical objects. + * TODO: This class is a copy of the same class in org.elasticsearch.xpack.spatial.common, we should find a common location for it. + */ +public final class H3SphericalUtil { + + private static final BiPredicate MIN_COMPARATOR = (e1, e2) -> e1.getLatRad() < e2.getLatRad(); + + private static final BiPredicate MAX_COMPARATOR = (e1, e2) -> e1.getLatRad() > e2.getLatRad(); + + /** + * Computes the bounding box of the provided h3 cell considering edges to be great circles and + * stores then in the provided {@link GeoBoundingBox}. + */ + public static void computeGeoBounds(long h3, GeoBoundingBox boundingBox) { + final CellBoundary boundary = H3.h3ToGeoBoundary(h3); + final int res = H3.getResolution(h3); + if (h3 == H3.northPolarH3(res)) { + // specialize north pole + computeNorthPoleBounds(boundary, boundingBox); + } else if (h3 == H3.southPolarH3(res)) { + // specialize south pole + computeSouthPoleBounds(boundary, boundingBox); + } else { + // generic case + computeBounds(boundary, boundingBox); + } + } + + private static void computeNorthPoleBounds(CellBoundary boundary, GeoBoundingBox boundingBox) { + double minLat = Double.POSITIVE_INFINITY; + for (int i = 0; i < boundary.numPoints(); i++) { + minLat = Math.min(minLat, boundary.getLatLon(i).getLatRad()); + } + boundingBox.topLeft().reset(90, -180d); + boundingBox.bottomRight().reset(Math.toDegrees(minLat), 180d); + } + + private static void computeSouthPoleBounds(CellBoundary boundary, GeoBoundingBox boundingBox) { + double maxLat = Double.NEGATIVE_INFINITY; + for (int i = 0; i < boundary.numPoints(); i++) { + maxLat = Math.max(maxLat, boundary.getLatLon(i).getLatRad()); + } + boundingBox.topLeft().reset(Math.toDegrees(maxLat), -180d); + boundingBox.bottomRight().reset(-90, 180d); + } + + private static void computeBounds(CellBoundary boundary, GeoBoundingBox boundingBox) { + // This algorithm is based on the bounding box for great circle edges in + // https://trs.jpl.nasa.gov/bitstream/handle/2014/41271/07-0286.pdf + double minLat = Double.POSITIVE_INFINITY; + int minLatPos = -1; + double minLon = Double.POSITIVE_INFINITY; + double maxLat = Double.NEGATIVE_INFINITY; + int maxLatPos = -1; + double maxLon = Double.NEGATIVE_INFINITY; + double maxNegLon = Double.NEGATIVE_INFINITY; + double minPosLon = Double.POSITIVE_INFINITY; + for (int i = 0; i < boundary.numPoints(); i++) { + final double lon = boundary.getLatLon(i).getLonRad(); + final double lat = boundary.getLatLon(i).getLatRad(); + if (lat < minLat) { + minLat = lat; + minLatPos = i; + } + if (lat > maxLat) { + maxLat = lat; + maxLatPos = i; + } + minLon = Math.min(minLon, lon); + maxLon = Math.max(maxLon, lon); + if (lon < 0) { + maxNegLon = Math.max(maxNegLon, lon); + } else { + minPosLon = Math.min(minPosLon, lon); + } + } + if (minLat < 0) { + // we only correct the min latitude if negative + minLat = boundary.getLatLon(minLatPos).greatCircleMinLatitude(computeEdge(boundary, minLatPos, MIN_COMPARATOR)); + } + if (maxLat > 0) { + // we only correct the max latitude if positive + maxLat = boundary.getLatLon(maxLatPos).greatCircleMaxLatitude(computeEdge(boundary, maxLatPos, MAX_COMPARATOR)); + } + // the min / max longitude is computed the same way as in cartesian, being careful with polygons crossing the dateline + final boolean crossesDateline = maxLon - minLon > Math.PI; + boundingBox.topLeft().reset(Math.toDegrees(maxLat), crossesDateline ? Math.toDegrees(minPosLon) : Math.toDegrees(minLon)); + boundingBox.bottomRight().reset(Math.toDegrees(minLat), crossesDateline ? Math.toDegrees(maxNegLon) : Math.toDegrees(maxLon)); + } + + private static LatLng computeEdge(CellBoundary boundary, int pos, BiPredicate comparator) { + final LatLng end1 = boundary.getLatLon((pos + 1) % boundary.numPoints()); + final LatLng end2 = boundary.getLatLon(pos == 0 ? boundary.numPoints() - 1 : pos - 1); + return comparator.test(end1, end2) ? end1 : end2; + } + + /** Return the {@link GeoPolygon} representing the provided H3 bin */ + public static GeoPolygon toGeoPolygon(long h3) { + final CellBoundary boundary = H3.h3ToGeoBoundary(h3); + List points = new ArrayList<>(boundary.numPoints()); + for (int i = 0; i < boundary.numPoints(); i++) { + LatLng latLng = boundary.getLatLon(i); + points.add(new GeoPoint(PlanetModel.SPHERE, latLng.getLatRad(), latLng.getLonRad())); + } + return GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points); + } + + /** Return the {@link LatLonGeometry} representing the provided H3 bin */ + public static LatLonGeometry getLatLonGeometry(long h3) { + return new H3SphericalGeometry(h3); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/GeoHexBoundedPredicate.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/GeoHexBoundedPredicate.java new file mode 100644 index 0000000000000..a94a83d7a2260 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/GeoHexBoundedPredicate.java @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.elasticsearch.common.geo.GeoBoundingBox; +import org.elasticsearch.xpack.esql.common.spatial.H3SphericalUtil; + +/** + * A class that checks if a hexagon intersects with a bounding box. + * TODO: This class is a copy of the inner class GeoHexPredicate inside GeoHexCellIdSource, we should find a common location for it. + */ +public class GeoHexBoundedPredicate { + + private final int precision; + private final boolean crossesDateline; + private final GeoBoundingBox bbox, scratch; + + GeoHexBoundedPredicate(int precision, GeoBoundingBox bbox) { + this.precision = precision; + this.crossesDateline = bbox.right() < bbox.left(); + this.bbox = bbox; + scratch = new GeoBoundingBox(new org.elasticsearch.common.geo.GeoPoint(), new org.elasticsearch.common.geo.GeoPoint()); + } + + public boolean validHex(long hex) { + H3SphericalUtil.computeGeoBounds(hex, scratch); + if (bbox.top() > scratch.bottom() && bbox.bottom() < scratch.top()) { + if (scratch.left() > scratch.right()) { + return intersects(-180, scratch.right()) || intersects(scratch.left(), 180); + } else { + return intersects(scratch.left(), scratch.right()); + } + } + return false; + } + + private boolean intersects(double minLon, double maxLon) { + if (crossesDateline) { + return bbox.left() < maxLon || bbox.right() > minLon; + } else { + return bbox.left() < maxLon && bbox.right() > minLon; + } + } + + public int precision() { + return precision; + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java index 8ce0b1fe6c146..217876e9f26af 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java @@ -8,6 +8,7 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; @@ -16,8 +17,8 @@ import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.geometry.Point; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoHashBoundedPredicate; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.FoldContext; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; @@ -113,9 +114,9 @@ protected NodeInfo info() { public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) { if (bounds != null) { if (bounds.foldable() == false) { - throw new IllegalArgumentException("bounds must foldable"); + throw new IllegalArgumentException("bounds must be foldable"); } - Rectangle bbox = asRectangle((BytesRef) bounds.fold(toEvaluator.foldCtx())); + GeoBoundingBox bbox = asGeoBoundingBox((BytesRef) bounds.fold(toEvaluator.foldCtx())); if (spatialField().foldable()) { // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() var point = (BytesRef) spatialField.fold(toEvaluator.foldCtx()); @@ -123,19 +124,14 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua } else if (parameter().foldable()) { // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() int precision = (int) parameter.fold(toEvaluator.foldCtx()); + GeoHashBoundedPredicate bounds = new GeoHashBoundedPredicate(precision, bbox); return spatialDocsValues ? new StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.Factory( source(), toEvaluator.apply(spatialField()), - precision, - bbox + bounds ) - : new StGeohashFromFieldAndLiteralAndLiteralEvaluator.Factory( - source(), - toEvaluator.apply(spatialField), - precision, - bbox - ); + : new StGeohashFromFieldAndLiteralAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField), bounds); } else { // Both arguments come from index fields return spatialDocsValues @@ -184,6 +180,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua public Object fold(FoldContext ctx) { var point = (BytesRef) spatialField().fold(ctx); int precision = (int) parameter().fold(ctx); + // TODO: Use GeoHashBoundedPredicate return calculateGeohash(GEO.wkbAsPoint(point), precision); } @@ -217,14 +214,8 @@ protected static long calculateGeohash(Point point, int precision) { } @Evaluator(extraName = "FromFieldAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndLiteralAndLiteral( - LongBlock.Builder results, - int p, - BytesRefBlock in, - @Fixed int precision, - @Fixed Rectangle bounds - ) { - fromWKB(results, p, in, precision, bounds); + static void fromFieldAndLiteralAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, @Fixed GeoHashBoundedPredicate bounds) { + fromWKB(results, p, in, bounds); } @Evaluator(extraName = "FromFieldDocValuesAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) @@ -232,15 +223,15 @@ static void fromFieldDocValuesAndLiteralAndLiteral( LongBlock.Builder results, int p, LongBlock encoded, - @Fixed int precision, - @Fixed Rectangle bounds + @Fixed GeoHashBoundedPredicate bounds ) { - fromEncodedLong(results, p, encoded, precision, bounds); + fromEncodedLong(results, p, encoded, bounds); } @Evaluator(extraName = "FromFieldAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, int precision, @Fixed Rectangle bounds) { - fromWKB(results, p, in, precision, bounds); + static void fromFieldAndFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, int precision, @Fixed GeoBoundingBox bbox) { + GeoHashBoundedPredicate bounds = new GeoHashBoundedPredicate(precision, bbox); + fromWKB(results, p, in, bounds); } @Evaluator(extraName = "FromFieldDocValuesAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) @@ -249,14 +240,16 @@ static void fromFieldDocValuesAndFieldAndLiteral( int p, LongBlock encoded, int precision, - @Fixed Rectangle bounds + @Fixed GeoBoundingBox bbox ) { - fromEncodedLong(results, p, encoded, precision, bounds); + GeoHashBoundedPredicate bounds = new GeoHashBoundedPredicate(precision, bbox); + fromEncodedLong(results, p, encoded, bounds); } @Evaluator(extraName = "FromLiteralAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static long fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed Rectangle bounds) { - return calculateGeohash(GEO.wkbAsPoint(in), precision, bounds); + static long fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed GeoBoundingBox bbox) { + GeoHashBoundedPredicate bounds = new GeoHashBoundedPredicate(precision, bbox); + return calculateGeohash(GEO.wkbAsPoint(in), bounds); } private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { @@ -296,16 +289,16 @@ private static void fromEncodedLong(LongBlock.Builder results, int position, Lon } } - protected static long calculateGeohash(Point point, int precision, Rectangle bounds) { - // For points, filtering the point is as good as filtering the tile - if (inBounds(point, bounds)) { - return Geohash.longEncode(point.getX(), point.getY(), precision); + protected static long calculateGeohash(Point point, GeoHashBoundedPredicate bounds) { + String geohash = Geohash.stringEncode(point.getX(), point.getY(), bounds.precision()); + if (bounds.validHash(geohash)) { + return Geohash.longEncode(geohash); } - // TODO: When we move to GeohashBoundsPredicate we can hopefullly improve this condition + // TODO: Are negative values allowed in geohash long encoding? return -1; } - private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision, Rectangle bounds) { + private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, GeoHashBoundedPredicate bounds) { int valueCount = wkbBlock.getValueCount(position); if (valueCount < 1) { results.appendNull(); @@ -313,7 +306,7 @@ private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlo final BytesRef scratch = new BytesRef(); final int firstValueIndex = wkbBlock.getFirstValueIndex(position); if (valueCount == 1) { - long grid = calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision, bounds); + long grid = calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), bounds); if (grid < 0) { results.appendNull(); } else { @@ -322,7 +315,7 @@ private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlo } else { var gridIds = new ArrayList(valueCount); for (int i = 0; i < valueCount; i++) { - var grid = calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision, bounds); + var grid = calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), bounds); if (grid >= 0) { gridIds.add(grid); } @@ -332,14 +325,14 @@ private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlo } } - private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, int precision, Rectangle bounds) { + private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, GeoHashBoundedPredicate bounds) { int valueCount = encoded.getValueCount(position); if (valueCount < 1) { results.appendNull(); } else { final int firstValueIndex = encoded.getFirstValueIndex(position); if (valueCount == 1) { - long grid = calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision, bounds); + long grid = calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex)), bounds); if (grid < 0) { results.appendNull(); } else { @@ -348,7 +341,7 @@ private static void fromEncodedLong(LongBlock.Builder results, int position, Lon } else { var gridIds = new ArrayList(valueCount); for (int i = 0; i < valueCount; i++) { - var grid = calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision, bounds); + var grid = calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), bounds); if (grid >= 0) { gridIds.add(grid); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java index 2bb1a763870ee..2f668fbc1ba80 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java @@ -8,6 +8,7 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.geo.GeoBoundingBox; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.Evaluator; @@ -16,7 +17,6 @@ import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.geometry.Point; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.h3.H3; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.FoldContext; @@ -109,9 +109,9 @@ protected NodeInfo info() { public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) { if (bounds != null) { if (bounds.foldable() == false) { - throw new IllegalArgumentException("bounds must foldable"); + throw new IllegalArgumentException("bounds must be foldable"); } - Rectangle bbox = asRectangle((BytesRef) bounds.fold(toEvaluator.foldCtx())); + GeoBoundingBox bbox = asGeoBoundingBox((BytesRef) bounds.fold(toEvaluator.foldCtx())); if (spatialField().foldable()) { // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() var point = (BytesRef) spatialField.fold(toEvaluator.foldCtx()); @@ -119,19 +119,14 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua } else if (parameter().foldable()) { // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() int precision = (int) parameter.fold(toEvaluator.foldCtx()); + GeoHexBoundedPredicate bounds = new GeoHexBoundedPredicate(precision, bbox); return spatialDocsValues ? new StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.Factory( source(), toEvaluator.apply(spatialField()), - precision, - bbox + bounds ) - : new StGeohexFromFieldAndLiteralAndLiteralEvaluator.Factory( - source(), - toEvaluator.apply(spatialField), - precision, - bbox - ); + : new StGeohexFromFieldAndLiteralAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField), bounds); } else { // Both arguments come from index fields return spatialDocsValues @@ -156,6 +151,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua } else if (parameter().foldable()) { // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() int precision = (int) parameter.fold(toEvaluator.foldCtx()); + // TODO: Use GeoHexBoundedPredicate return spatialDocsValues ? new StGeohexFromFieldDocValuesAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField()), precision) : new StGeohexFromFieldAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField), precision); @@ -180,6 +176,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua public Object fold(FoldContext ctx) { var point = (BytesRef) spatialField().fold(ctx); int precision = (int) parameter().fold(ctx); + // TODO: Use GeoHexBoundedPredicate return calculateGeohex(GEO.wkbAsPoint(point), precision); } @@ -213,14 +210,8 @@ protected static long calculateGeohex(Point point, int precision) { } @Evaluator(extraName = "FromFieldAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndLiteralAndLiteral( - LongBlock.Builder results, - int p, - BytesRefBlock in, - @Fixed int precision, - @Fixed Rectangle bounds - ) { - fromWKB(results, p, in, precision, bounds); + static void fromFieldAndLiteralAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, @Fixed GeoHexBoundedPredicate bounds) { + fromWKB(results, p, in, bounds); } @Evaluator(extraName = "FromFieldDocValuesAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) @@ -228,15 +219,15 @@ static void fromFieldDocValuesAndLiteralAndLiteral( LongBlock.Builder results, int p, LongBlock encoded, - @Fixed int precision, - @Fixed Rectangle bounds + @Fixed GeoHexBoundedPredicate bounds ) { - fromEncodedLong(results, p, encoded, precision, bounds); + fromEncodedLong(results, p, encoded, bounds); } @Evaluator(extraName = "FromFieldAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, int precision, @Fixed Rectangle bounds) { - fromWKB(results, p, in, precision, bounds); + static void fromFieldAndFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, int precision, @Fixed GeoBoundingBox bbox) { + GeoHexBoundedPredicate bounds = new GeoHexBoundedPredicate(precision, bbox); + fromWKB(results, p, in, bounds); } @Evaluator(extraName = "FromFieldDocValuesAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) @@ -245,14 +236,16 @@ static void fromFieldDocValuesAndFieldAndLiteral( int p, LongBlock encoded, int precision, - @Fixed Rectangle bounds + @Fixed GeoBoundingBox bbox ) { - fromEncodedLong(results, p, encoded, precision, bounds); + GeoHexBoundedPredicate bounds = new GeoHexBoundedPredicate(precision, bbox); + fromEncodedLong(results, p, encoded, bounds); } @Evaluator(extraName = "FromLiteralAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static long fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed Rectangle bounds) { - return calculateGeohex(GEO.wkbAsPoint(in), precision, bounds); + static long fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed GeoBoundingBox bbox) { + GeoHexBoundedPredicate bounds = new GeoHexBoundedPredicate(precision, bbox); + return calculateGeohex(GEO.wkbAsPoint(in), bounds); } private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { @@ -292,15 +285,17 @@ private static void fromEncodedLong(LongBlock.Builder results, int position, Lon } } - protected static long calculateGeohex(Point point, int precision, Rectangle bounds) { + protected static long calculateGeohex(Point point, GeoHexBoundedPredicate bounds) { // For points, filtering the point is as good as filtering the tile - if (inBounds(point, bounds)) { - return H3.geoToH3(point.getLat(), point.getLon(), precision); + long geohex = H3.geoToH3(point.getLat(), point.getLon(), bounds.precision()); + if (bounds.validHex(geohex)) { + return geohex; } + // TODO: Are we sure negative numbers are not valid return -1L; } - private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision, Rectangle bounds) { + private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, GeoHexBoundedPredicate bounds) { int valueCount = wkbBlock.getValueCount(position); if (valueCount < 1) { results.appendNull(); @@ -308,7 +303,7 @@ private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlo final BytesRef scratch = new BytesRef(); final int firstValueIndex = wkbBlock.getFirstValueIndex(position); if (valueCount == 1) { - long grid = calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision, bounds); + long grid = calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), bounds); if (grid < 0) { results.appendNull(); } else { @@ -317,7 +312,7 @@ private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlo } else { var gridIds = new ArrayList(valueCount); for (int i = 0; i < valueCount; i++) { - var grid = calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision, bounds); + var grid = calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), bounds); if (grid >= 0) { gridIds.add(grid); } @@ -327,14 +322,14 @@ private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlo } } - private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, int precision, Rectangle bounds) { + private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, GeoHexBoundedPredicate bounds) { int valueCount = encoded.getValueCount(position); if (valueCount < 1) { results.appendNull(); } else { final int firstValueIndex = encoded.getFirstValueIndex(position); if (valueCount == 1) { - long grid = calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision, bounds); + long grid = calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex)), bounds); if (grid < 0) { results.appendNull(); } else { @@ -343,7 +338,7 @@ private static void fromEncodedLong(LongBlock.Builder results, int position, Lon } else { var gridIds = new ArrayList(valueCount); for (int i = 0; i < valueCount; i++) { - var grid = calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision, bounds); + var grid = calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), bounds); if (grid >= 0) { gridIds.add(grid); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java index 64454629de782..773761673a575 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java @@ -68,7 +68,7 @@ public StGeotile( @Param( name = "bounds", type = { "geo_shape", "geo_point" }, - description = "Bounds to filter the grid tiles, either a geo_shape BBOX or an array", + description = "Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points", optional = true ) Expression bounds ) { @@ -297,7 +297,8 @@ protected static long calculateGeotile(Point point, GeoTileBoundedPredicate boun if (bounds.validTile(x, y, bounds.precision())) { return GeoTileUtils.longEncodeTiles(bounds.precision(), x, y); } - return -1; + // TODO: Are we sure negative numbers are not valid + return -1L; } private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, GeoTileBoundedPredicate bounds) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalGeometryTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalGeometryTests.java new file mode 100644 index 0000000000000..2431d61752345 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalGeometryTests.java @@ -0,0 +1,96 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.common.spatial; + +import org.apache.lucene.document.Document; +import org.apache.lucene.document.LatLonPoint; +import org.apache.lucene.document.ShapeField; +import org.apache.lucene.geo.GeoEncodingUtils; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.IndexWriterConfig; +import org.apache.lucene.index.SerialMergeScheduler; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.Query; +import org.apache.lucene.store.Directory; +import org.elasticsearch.core.IOUtils; +import org.elasticsearch.geo.GeometryTestUtils; +import org.elasticsearch.geometry.Point; +import org.elasticsearch.h3.CellBoundary; +import org.elasticsearch.h3.H3; +import org.elasticsearch.h3.LatLng; +import org.elasticsearch.test.ESTestCase; + +/** + * TODO: This class is a copy of the same class in org.elasticsearch.xpack.spatial.common, we should find a common location for it. + */ +public class H3SphericalGeometryTests extends ESTestCase { + + private static final String FIELD_NAME = "field"; + + public void testIndexPoints() throws Exception { + Point queryPoint = GeometryTestUtils.randomPoint(); + long[] hexes = new long[H3.MAX_H3_RES + 1]; + for (int res = 0; res < hexes.length; res++) { + hexes[res] = H3.geoToH3(queryPoint.getLat(), queryPoint.getLon(), res); + } + IndexWriterConfig iwc = newIndexWriterConfig(); + // Else seeds may not reproduce: + iwc.setMergeScheduler(new SerialMergeScheduler()); + // Else we can get O(N^2) merging: + iwc.setMaxBufferedDocs(10); + Directory dir = newDirectory(); + // RandomIndexWriter is too slow here: + int[] counts = new int[H3.MAX_H3_RES + 1]; + IndexWriter w = new IndexWriter(dir, iwc); + for (long hex : hexes) { + CellBoundary cellBoundary = H3.h3ToGeoBoundary(hex); + for (int i = 0; i < cellBoundary.numPoints(); i++) { + Document doc = new Document(); + LatLng latLng = cellBoundary.getLatLon(i); + doc.add(new LatLonPoint(FIELD_NAME, latLng.getLatDeg(), latLng.getLonDeg())); + w.addDocument(doc); + computeCounts(hexes, latLng.getLonDeg(), latLng.getLatDeg(), counts); + } + + } + final int numDocs = randomIntBetween(1000, 2000); + for (int id = 0; id < numDocs; id++) { + Document doc = new Document(); + Point point = GeometryTestUtils.randomPoint(); + doc.add(new LatLonPoint(FIELD_NAME, point.getLat(), point.getLon())); + w.addDocument(doc); + computeCounts(hexes, point.getLon(), point.getLat(), counts); + } + + if (random().nextBoolean()) { + w.forceMerge(1); + } + final IndexReader r = DirectoryReader.open(w); + w.close(); + + IndexSearcher s = newSearcher(r); + for (int i = 0; i < H3.MAX_H3_RES + 1; i++) { + H3SphericalGeometry geometry = new H3SphericalGeometry(hexes[i]); + Query indexQuery = LatLonPoint.newGeometryQuery(FIELD_NAME, ShapeField.QueryRelation.INTERSECTS, geometry); + assertEquals(counts[i], s.count(indexQuery)); + } + IOUtils.close(r, dir); + } + + private void computeCounts(long[] hexes, double lon, double lat, int[] counts) { + double qLat = GeoEncodingUtils.decodeLatitude(GeoEncodingUtils.encodeLatitude(lat)); + double qLon = GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(lon)); + for (int res = 0; res < hexes.length; res++) { + if (hexes[res] == H3.geoToH3(qLat, qLon, res)) { + counts[res]++; + } + } + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalUtilTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalUtilTests.java new file mode 100644 index 0000000000000..51537b11687e7 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/common/spatial/H3SphericalUtilTests.java @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.common.spatial; + +import org.apache.lucene.spatial3d.geom.GeoPolygon; +import org.apache.lucene.spatial3d.geom.LatLonBounds; +import org.apache.lucene.tests.geo.GeoTestUtil; +import org.elasticsearch.common.geo.GeoBoundingBox; +import org.elasticsearch.common.geo.GeoPoint; +import org.elasticsearch.h3.H3; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.spatial.common.H3SphericalUtil; + +/** + * TODO: This class is a copy of the same class in org.elasticsearch.xpack.spatial.common, we should find a common location for it. + */ +public class H3SphericalUtilTests extends ESTestCase { + + private static final double LAT_DELTA = 1e-7; + private static final double LON_DELTA = 1e-5; + + public void testRandomBounds() { + GeoBoundingBox boundingBox = new GeoBoundingBox(new GeoPoint(), new GeoPoint()); + for (int res = 0; res < H3.MAX_H3_RES; res++) { + final long h3 = H3.geoToH3(GeoTestUtil.nextLatitude(), GeoTestUtil.nextLongitude(), res); + assertBounds(h3, boundingBox); + } + } + + public void testBoundsLevel0() { + GeoBoundingBox boundingBox = new GeoBoundingBox(new GeoPoint(), new GeoPoint()); + for (long h3 : H3.getLongRes0Cells()) { + assertBounds(h3, boundingBox); + } + } + + private void assertBounds(long h3, GeoBoundingBox boundingBox) { + org.elasticsearch.xpack.spatial.common.H3SphericalUtil.computeGeoBounds(h3, boundingBox); + GeoPolygon polygon = H3SphericalUtil.toGeoPolygon(h3); + LatLonBounds bounds = new LatLonBounds(); + polygon.getBounds(bounds); + if (bounds.checkNoLongitudeBound()) { + assertEquals(-180d, boundingBox.left(), LON_DELTA); + assertEquals(180d, boundingBox.right(), LON_DELTA); + } else { + assertEquals(Math.toDegrees(bounds.getLeftLongitude()), boundingBox.left(), LON_DELTA); + assertEquals(Math.toDegrees(bounds.getRightLongitude()), boundingBox.right(), LON_DELTA); + } + + if (bounds.checkNoTopLatitudeBound()) { + assertEquals(90d, boundingBox.top(), LAT_DELTA); + } else { + assertEquals(Math.toDegrees(bounds.getMaxLatitude()), boundingBox.top(), LAT_DELTA); + } + + if (bounds.checkNoBottomLatitudeBound()) { + assertEquals(-90d, boundingBox.bottom(), LAT_DELTA); + } else { + assertEquals(Math.toDegrees(bounds.getMinLatitude()), boundingBox.bottom(), LAT_DELTA); + } + } +} From 6d115b4c9e682061b27418744ede39f77c1520ca Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 15 Apr 2025 17:55:15 +0200 Subject: [PATCH 12/34] Added unit tests for new functions and resulting docs --- .../functions/description/st_geohash.md | 6 ++ .../description/st_geohash_to_geoshape.md | 6 ++ .../description/st_geohash_to_long.md | 6 ++ .../description/st_geohash_to_string.md | 6 ++ .../functions/description/st_geohex.md | 6 ++ .../description/st_geohex_to_geoshape.md | 6 ++ .../description/st_geohex_to_long.md | 6 ++ .../description/st_geohex_to_string.md | 6 ++ .../functions/description/st_geotile.md | 6 ++ .../description/st_geotile_to_geoshape.md | 6 ++ .../description/st_geotile_to_long.md | 6 ++ .../description/st_geotile_to_string.md | 6 ++ .../functions/examples/st_geohash.md | 38 ++++++++ .../examples/st_geohash_to_geoshape.md | 14 +++ .../functions/examples/st_geohash_to_long.md | 14 +++ .../examples/st_geohash_to_string.md | 14 +++ .../_snippets/functions/examples/st_geohex.md | 32 +++++++ .../examples/st_geohex_to_geoshape.md | 14 +++ .../functions/examples/st_geohex_to_long.md | 14 +++ .../functions/examples/st_geohex_to_string.md | 14 +++ .../functions/examples/st_geotile.md | 31 ++++++ .../examples/st_geotile_to_geoshape.md | 14 +++ .../functions/examples/st_geotile_to_long.md | 14 +++ .../examples/st_geotile_to_string.md | 14 +++ .../_snippets/functions/layout/st_geohash.md | 23 +++++ .../layout/st_geohash_to_geoshape.md | 23 +++++ .../functions/layout/st_geohash_to_long.md | 23 +++++ .../functions/layout/st_geohash_to_string.md | 23 +++++ .../_snippets/functions/layout/st_geohex.md | 23 +++++ .../functions/layout/st_geohex_to_geoshape.md | 23 +++++ .../functions/layout/st_geohex_to_long.md | 23 +++++ .../functions/layout/st_geohex_to_string.md | 23 +++++ .../_snippets/functions/layout/st_geotile.md | 23 +++++ .../layout/st_geotile_to_geoshape.md | 23 +++++ .../functions/layout/st_geotile_to_long.md | 23 +++++ .../functions/layout/st_geotile_to_string.md | 23 +++++ .../functions/parameters/st_geohash.md | 13 +++ .../parameters/st_geohash_to_geoshape.md | 7 ++ .../parameters/st_geohash_to_long.md | 7 ++ .../parameters/st_geohash_to_string.md | 7 ++ .../functions/parameters/st_geohex.md | 13 +++ .../parameters/st_geohex_to_geoshape.md | 7 ++ .../functions/parameters/st_geohex_to_long.md | 7 ++ .../parameters/st_geohex_to_string.md | 7 ++ .../functions/parameters/st_geotile.md | 13 +++ .../parameters/st_geotile_to_geoshape.md | 7 ++ .../parameters/st_geotile_to_long.md | 7 ++ .../parameters/st_geotile_to_string.md | 7 ++ .../_snippets/functions/types/st_geohash.md | 8 ++ .../functions/types/st_geohash_to_geoshape.md | 9 ++ .../functions/types/st_geohash_to_long.md | 9 ++ .../functions/types/st_geohash_to_string.md | 9 ++ .../_snippets/functions/types/st_geohex.md | 8 ++ .../functions/types/st_geohex_to_geoshape.md | 9 ++ .../functions/types/st_geohex_to_long.md | 9 ++ .../functions/types/st_geohex_to_string.md | 9 ++ .../_snippets/functions/types/st_geotile.md | 8 ++ .../functions/types/st_geotile_to_geoshape.md | 9 ++ .../functions/types/st_geotile_to_long.md | 9 ++ .../functions/types/st_geotile_to_string.md | 9 ++ .../esql/_snippets/lists/spatial-functions.md | 12 +++ .../functions-operators/spatial-functions.md | 35 +++++++ .../esql/images/functions/st_geohash.svg | 1 + .../functions/st_geohash_to_geoshape.svg | 1 + .../images/functions/st_geohash_to_long.svg | 1 + .../images/functions/st_geohash_to_string.svg | 1 + .../esql/images/functions/st_geohex.svg | 1 + .../functions/st_geohex_to_geoshape.svg | 1 + .../images/functions/st_geohex_to_long.svg | 1 + .../images/functions/st_geohex_to_string.svg | 1 + .../esql/images/functions/st_geotile.svg | 1 + .../functions/st_geotile_to_geoshape.svg | 1 + .../images/functions/st_geotile_to_long.svg | 1 + .../images/functions/st_geotile_to_string.svg | 1 + .../definition/functions/st_geohash.json | 31 ++++++ .../functions/st_geohash_to_geoshape.json | 37 ++++++++ .../functions/st_geohash_to_long.json | 37 ++++++++ .../functions/st_geohash_to_string.json | 37 ++++++++ .../definition/functions/st_geohex.json | 31 ++++++ .../functions/st_geohex_to_geoshape.json | 37 ++++++++ .../functions/st_geohex_to_long.json | 37 ++++++++ .../functions/st_geohex_to_string.json | 37 ++++++++ .../definition/functions/st_geotile.json | 31 ++++++ .../functions/st_geotile_to_geoshape.json | 37 ++++++++ .../functions/st_geotile_to_long.json | 37 ++++++++ .../functions/st_geotile_to_string.json | 37 ++++++++ .../esql/kibana/docs/functions/st_geohash.md | 20 ++++ .../docs/functions/st_geohash_to_geoshape.md | 10 ++ .../docs/functions/st_geohash_to_long.md | 9 ++ .../docs/functions/st_geohash_to_string.md | 9 ++ .../esql/kibana/docs/functions/st_geohex.md | 20 ++++ .../docs/functions/st_geohex_to_geoshape.md | 10 ++ .../docs/functions/st_geohex_to_long.md | 9 ++ .../docs/functions/st_geohex_to_string.md | 9 ++ .../esql/kibana/docs/functions/st_geotile.md | 19 ++++ .../docs/functions/st_geotile_to_geoshape.md | 10 ++ .../docs/functions/st_geotile_to_long.md | 9 ++ .../docs/functions/st_geotile_to_string.md | 9 ++ .../src/main/resources/spatial-grid.csv-spec | 94 +++++++++++++++++-- .../function/scalar/spatial/StGeohash.java | 15 ++- .../function/scalar/spatial/StGeohex.java | 15 ++- .../scalar/spatial/StGeohexToGeoShape.java | 2 +- .../scalar/spatial/StGeohexToString.java | 2 +- .../function/scalar/spatial/StGeotile.java | 15 ++- .../scalar/spatial/StGeotileToGeoShape.java | 2 +- .../spatial/SpatialGridFunctionTestCase.java | 90 ++++++++++++++++++ .../SpatialGridTypeConversionTestCases.java | 54 +++++++++++ .../scalar/spatial/StGeohashTests.java | 46 +++++++++ .../spatial/StGeohashToGeoShapeTests.java | 64 +++++++++++++ .../scalar/spatial/StGeohashToLongTests.java | 63 +++++++++++++ .../spatial/StGeohashToStringTests.java | 64 +++++++++++++ .../scalar/spatial/StGeohexTests.java | 46 +++++++++ .../spatial/StGeohexToGeoShapeTests.java | 64 +++++++++++++ .../scalar/spatial/StGeohexToLongTests.java | 63 +++++++++++++ .../scalar/spatial/StGeohexToStringTests.java | 64 +++++++++++++ .../scalar/spatial/StGeotileTests.java | 46 +++++++++ .../spatial/StGeotileToGeoShapeTests.java | 64 +++++++++++++ .../scalar/spatial/StGeotileToLongTests.java | 63 +++++++++++++ .../spatial/StGeotileToStringTests.java | 64 +++++++++++++ 119 files changed, 2371 insertions(+), 39 deletions(-) create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/st_geohash.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/st_geohex.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/st_geotile.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/st_geohash.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/st_geohex.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_string.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/st_geotile.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_long.md create mode 100644 docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_string.md create mode 100644 docs/reference/query-languages/esql/images/functions/st_geohash.svg create mode 100644 docs/reference/query-languages/esql/images/functions/st_geohash_to_geoshape.svg create mode 100644 docs/reference/query-languages/esql/images/functions/st_geohash_to_long.svg create mode 100644 docs/reference/query-languages/esql/images/functions/st_geohash_to_string.svg create mode 100644 docs/reference/query-languages/esql/images/functions/st_geohex.svg create mode 100644 docs/reference/query-languages/esql/images/functions/st_geohex_to_geoshape.svg create mode 100644 docs/reference/query-languages/esql/images/functions/st_geohex_to_long.svg create mode 100644 docs/reference/query-languages/esql/images/functions/st_geohex_to_string.svg create mode 100644 docs/reference/query-languages/esql/images/functions/st_geotile.svg create mode 100644 docs/reference/query-languages/esql/images/functions/st_geotile_to_geoshape.svg create mode 100644 docs/reference/query-languages/esql/images/functions/st_geotile_to_long.svg create mode 100644 docs/reference/query-languages/esql/images/functions/st_geotile_to_string.svg create mode 100644 docs/reference/query-languages/esql/kibana/definition/functions/st_geohash.json create mode 100644 docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_geoshape.json create mode 100644 docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_long.json create mode 100644 docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_string.json create mode 100644 docs/reference/query-languages/esql/kibana/definition/functions/st_geohex.json create mode 100644 docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_geoshape.json create mode 100644 docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_long.json create mode 100644 docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_string.json create mode 100644 docs/reference/query-languages/esql/kibana/definition/functions/st_geotile.json create mode 100644 docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_geoshape.json create mode 100644 docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_long.json create mode 100644 docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_string.json create mode 100644 docs/reference/query-languages/esql/kibana/docs/functions/st_geohash.md create mode 100644 docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_long.md create mode 100644 docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_string.md create mode 100644 docs/reference/query-languages/esql/kibana/docs/functions/st_geohex.md create mode 100644 docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_long.md create mode 100644 docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_string.md create mode 100644 docs/reference/query-languages/esql/kibana/docs/functions/st_geotile.md create mode 100644 docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_geoshape.md create mode 100644 docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_long.md create mode 100644 docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_string.md create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunctionTestCase.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridTypeConversionTestCases.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringTests.java diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash.md new file mode 100644 index 0000000000000..ce9266350167f --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Description** + +Calculates the `geohash` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHASH_TO_STRING](#esql-st_geohash_to_string) to convert the result to a string. Or use [ST_GEOHASH_TO_GEOSHAPE](#esql-st_geohash_to_geoshape) to convert either the long or string `geohash` to a POLYGON geo_shape. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_geoshape.md new file mode 100644 index 0000000000000..98f834a5e8587 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_geoshape.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Description** + +Converts an input value to a `geo_shape` value. The input values are expected to be the grid-ids of geohash grids, in either long or string format. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_long.md new file mode 100644 index 0000000000000..2abb0c416addb --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_long.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Description** + +Converts an input value representing a geohash grid-ID in string format into a long. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_string.md new file mode 100644 index 0000000000000..5e1cc240c4731 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_string.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Description** + +Converts an input value representing a geohash grid-ID in long format into a string. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex.md new file mode 100644 index 0000000000000..a3bf1c1238544 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Description** + +Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHEX_TO_STRING](#esql-st_geohex_to_string) to convert the result to a string. Or use [ST_GEOHEX_TO_GEOSHAPE](#esql-st_geohex_to_geoshape) to convert either the long or string `geohex` to a POLYGON geo_shape. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_geoshape.md new file mode 100644 index 0000000000000..10547ae8c4bbc --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_geoshape.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Description** + +Converts an input value to a `geo_shape` value. The input values are expected to be the grid-ids of H3 grids, in either long or string format. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_long.md new file mode 100644 index 0000000000000..b391ae1d685eb --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_long.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Description** + +Converts an input value representing a geohex grid-ID in string format into a long. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_string.md new file mode 100644 index 0000000000000..7915ff0170e05 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_string.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Description** + +Converts an input value representing a Geohex grid-ID in long format into a string. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile.md new file mode 100644 index 0000000000000..631abd67eaa0f --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Description** + +Calculates the `geotile` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOTILE_TO_STRING](#esql-st_geotile_to_string) to convert the result to a string. Or use [ST_GEOTILE_TO_GEOSHAPE](#esql-st_geotile_to_geoshape) to convert either the long or string `geotile` to a POLYGON geo_shape. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_geoshape.md new file mode 100644 index 0000000000000..f8cbfa8878d15 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_geoshape.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Description** + +Converts an input value to a `geo_shape` value. The input values are expected to be the grid-ids of geotile grids, in either long or string format. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_long.md new file mode 100644 index 0000000000000..7ebe7a08d2a4d --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_long.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Description** + +Converts an input value representing a geotile grid-ID in string format into a long. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_string.md new file mode 100644 index 0000000000000..71fd355372975 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_string.md @@ -0,0 +1,6 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Description** + +Converts an input value representing a geotile grid-ID in long format into a string. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash.md new file mode 100644 index 0000000000000..f9fab4135d31f --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash.md @@ -0,0 +1,38 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Example** + +```esql +FROM airports +| EVAL geohash = ST_GEOHASH(location, 1) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geohash +| WHERE count >= 10 +| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +| KEEP count, centroid, geohashString +| SORT count DESC, geohashString ASC +``` + +| count:long | centroid:geo_point | geohashString:keyword | +| --- | --- | --- | +| 118 | POINT (-77.41857436454018 26.96522968734409) | d | +| 96 | POINT (23.181679135886952 27.295384635654045) | s | +| 94 | POINT (70.94076107503807 25.691916451026547) | t | +| 90 | POINT (-104.3941700803116 30.811849871650338) | 9 | +| 89 | POINT (18.71573683606942 53.165169130707305) | u | +| 85 | POINT (114.3722876966657 24.908398092505248) | w | +| 51 | POINT (-61.44522591713159 -22.87209844956284) | 6 | +| 38 | POINT (-9.429514887252529 25.497624435045413) | e | +| 34 | POINT (-111.8071846965262 52.464381378993174) | c | +| 30 | POINT (28.7045472683385 -14.706001980230212) | k | +| 28 | POINT (159.52750137208827 -25.555616633001982) | r | +| 22 | POINT (-4.410395708612421 54.90304926367985) | g | +| 21 | POINT (-69.40534970590046 50.93379438189523) | f | +| 17 | POINT (114.05526293222519 -10.898114638950895) | q | +| 16 | POINT (147.40052131412085 21.054660080408212) | x | +| 13 | POINT (63.64716878519035 54.37333276101317) | v | +| 12 | POINT (-39.53510569408536 -11.72166372067295) | 7 | + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_geoshape.md new file mode 100644 index 0000000000000..ed97120c270e3 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_geoshape.md @@ -0,0 +1,14 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Example** + +```esql +ROW geohash = "u3bu" +| EVAL boundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +``` + +| geohash:keyword | boundary:geo_shape | +| --- | --- | +| u3bu | BBOX (12.3046875, 12.65625, 55.72265625, 55.546875) | + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_long.md new file mode 100644 index 0000000000000..a5dd10b329f6f --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_long.md @@ -0,0 +1,14 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Example** + +```esql +ROW geohash = "u3bu" +| EVAL geohashLong = ST_GEOHASH_TO_LONG(geohash) +``` + +| geohash:keyword | geohashLong:long | +| --- | --- | +| u3bu | 13686180 | + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_string.md new file mode 100644 index 0000000000000..dd6327499254f --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_string.md @@ -0,0 +1,14 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Example** + +```esql +ROW geohash = TO_LONG(13686180) +| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +``` + +| geohash:long | geohashString:keyword | +| --- | --- | +| 13686180 | u3bu | + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex.md new file mode 100644 index 0000000000000..875add22968d6 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex.md @@ -0,0 +1,32 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Example** + +```esql +FROM airports +| EVAL geohex = ST_GEOHEX(location, 1) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geohex +| WHERE count >= 10 +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| KEEP count, centroid, geohexString +| SORT count DESC, geohexString ASC +``` + +| count:long | centroid:geo_point | geohexString:keyword | +| --- | --- | --- | +| 22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff | +| 18 | POINT (-80.64959161449224 40.04119813675061) | 812abffffffffff | +| 17 | POINT (-0.7606179875266903 52.86413913565304) | 81197ffffffffff | +| 13 | POINT (22.53157936179867 41.98255742864254) | 811efffffffffff | +| 13 | POINT (78.30096947387435 26.073904778951636) | 813dbffffffffff | +| 12 | POINT (-76.39781514415517 45.16300531569868) | 812bbffffffffff | +| 12 | POINT (-100.30120467301458 20.114154297625646) | 8149bffffffffff | +| 11 | POINT (18.037187419831753 48.66540593306788) | 811e3ffffffffff | +| 11 | POINT (-83.42379064553164 33.18388901439241) | 8144fffffffffff | +| 11 | POINT (-99.4237939513881 27.100012352774765) | 8148bffffffffff | +| 10 | POINT (128.01009018346667 35.8699960866943) | 8130fffffffffff | + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_geoshape.md new file mode 100644 index 0000000000000..544e9d4dfa39d --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_geoshape.md @@ -0,0 +1,14 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Example** + +```esql +ROW geohex = "841f059ffffffff" +| EVAL boundary = ST_GEOHEX_TO_GEOSHAPE(geohex) +``` + +| geohex:keyword | boundary:geo_shape | +| --- | --- | +| 841f059ffffffff | POLYGON ((12.353546327258265 55.80335405461356, 12.2434612967008 55.60502874054935, 12.51733872608954 55.470800201545316, 12.901880149865134 55.53443156197633, 13.014270156228921 55.73262985778208, 12.739822958959069 55.8673267391136, 12.353546327258265 55.80335405461356)) | + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_long.md new file mode 100644 index 0000000000000..be94b611917aa --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_long.md @@ -0,0 +1,14 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Example** + +```esql +ROW geohex = "841f059ffffffff" +| EVAL geohexLong = ST_GEOHEX_TO_LONG(geohex) +``` + +| geohex:keyword | geohexLong:long | +| --- | --- | +| 841f059ffffffff | 595020895127339007 | + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_string.md new file mode 100644 index 0000000000000..b3eabacd5ec14 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_string.md @@ -0,0 +1,14 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Example** + +```esql +ROW geohex = 595020895127339007 +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +``` + +| geohex:long | geohexString:keyword | +| --- | --- | +| 595020895127339007 | 841f059ffffffff | + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile.md new file mode 100644 index 0000000000000..0653f55c969c7 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile.md @@ -0,0 +1,31 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Example** + +```esql +FROM airports +| EVAL geotile = ST_GEOTILE(location, 2) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geotile +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| SORT count DESC, geotileString ASC +| KEEP count, centroid, geotileString +``` + +| count:long | centroid:geo_point | geotileString:keyword | +| --- | --- | --- | +| 286 | POINT (39.31202001609169 35.149993664386415) | 2/2/1 | +| 197 | POINT (-55.387361375756825 31.952955322292855) | 2/1/1 | +| 136 | POINT (-110.97162496141048 36.87185255084734) | 2/0/1 | +| 106 | POINT (119.35907618669827 25.46263281488791) | 2/3/1 | +| 67 | POINT (-58.031108492373754 -22.624166105151065) | 2/1/2 | +| 46 | POINT (142.95455511274707 -20.581492295427978) | 2/3/2 | +| 34 | POINT (31.38476753634784 -14.64374022804858) | 2/2/2 | +| 8 | POINT (-160.0723083713092 -19.124013530672528) | 2/0/2 | +| 6 | POINT (23.95813101902604 70.17537698848173) | 2/2/0 | +| 3 | POINT (-133.4001641627401 72.06833167467266) | 2/0/0 | +| 2 | POINT (-68.47209956031293 66.77569948369637) | 2/1/0 | + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_geoshape.md new file mode 100644 index 0000000000000..563f48797bd33 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_geoshape.md @@ -0,0 +1,14 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Example** + +```esql +ROW geotile = "4/8/5" +| EVAL boundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +``` + +| geotile:keyword | boundary:geo_shape | +| --- | --- | +| 4/8/5 | BBOX (0.0, 22.5, 55.77657301866769, 40.979898069620134) | + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_long.md new file mode 100644 index 0000000000000..995f04ee6f355 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_long.md @@ -0,0 +1,14 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Example** + +```esql +ROW geotile = "4/8/5" +| EVAL geotileLong = ST_GEOTILE_TO_LONG(geotile) +``` + +| geotile:keyword | geotileLong:long | +| --- | --- | +| 4/8/5 | 1152921508901814277 | + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_string.md new file mode 100644 index 0000000000000..6e7a95b6ff342 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_string.md @@ -0,0 +1,14 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Example** + +```esql +ROW geotile = 1152921508901814277 +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +``` + +| geotile:long | geotileString:keyword | +| --- | --- | +| 1152921508901814277 | 4/8/5 | + + diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash.md new file mode 100644 index 0000000000000..f84175b382f21 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash.md @@ -0,0 +1,23 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +## `ST_GEOHASH` [esql-st_geohash] + +**Syntax** + +:::{image} ../../../images/functions/st_geohash.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/st_geohash.md +::: + +:::{include} ../description/st_geohash.md +::: + +:::{include} ../types/st_geohash.md +::: + +:::{include} ../examples/st_geohash.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_geoshape.md new file mode 100644 index 0000000000000..b5c1403644c9c --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_geoshape.md @@ -0,0 +1,23 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +## `ST_GEOHASH_TO_GEOSHAPE` [esql-st_geohash_to_geoshape] + +**Syntax** + +:::{image} ../../../images/functions/st_geohash_to_geoshape.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/st_geohash_to_geoshape.md +::: + +:::{include} ../description/st_geohash_to_geoshape.md +::: + +:::{include} ../types/st_geohash_to_geoshape.md +::: + +:::{include} ../examples/st_geohash_to_geoshape.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_long.md new file mode 100644 index 0000000000000..73e09c2cbd83d --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_long.md @@ -0,0 +1,23 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +## `ST_GEOHASH_TO_LONG` [esql-st_geohash_to_long] + +**Syntax** + +:::{image} ../../../images/functions/st_geohash_to_long.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/st_geohash_to_long.md +::: + +:::{include} ../description/st_geohash_to_long.md +::: + +:::{include} ../types/st_geohash_to_long.md +::: + +:::{include} ../examples/st_geohash_to_long.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_string.md new file mode 100644 index 0000000000000..464d614c70638 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_string.md @@ -0,0 +1,23 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +## `ST_GEOHASH_TO_STRING` [esql-st_geohash_to_string] + +**Syntax** + +:::{image} ../../../images/functions/st_geohash_to_string.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/st_geohash_to_string.md +::: + +:::{include} ../description/st_geohash_to_string.md +::: + +:::{include} ../types/st_geohash_to_string.md +::: + +:::{include} ../examples/st_geohash_to_string.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex.md new file mode 100644 index 0000000000000..95c7c49ed50bc --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex.md @@ -0,0 +1,23 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +## `ST_GEOHEX` [esql-st_geohex] + +**Syntax** + +:::{image} ../../../images/functions/st_geohex.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/st_geohex.md +::: + +:::{include} ../description/st_geohex.md +::: + +:::{include} ../types/st_geohex.md +::: + +:::{include} ../examples/st_geohex.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_geoshape.md new file mode 100644 index 0000000000000..bbc02229ad139 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_geoshape.md @@ -0,0 +1,23 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +## `ST_GEOHEX_TO_GEOSHAPE` [esql-st_geohex_to_geoshape] + +**Syntax** + +:::{image} ../../../images/functions/st_geohex_to_geoshape.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/st_geohex_to_geoshape.md +::: + +:::{include} ../description/st_geohex_to_geoshape.md +::: + +:::{include} ../types/st_geohex_to_geoshape.md +::: + +:::{include} ../examples/st_geohex_to_geoshape.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_long.md new file mode 100644 index 0000000000000..cd1c1dd66910c --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_long.md @@ -0,0 +1,23 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +## `ST_GEOHEX_TO_LONG` [esql-st_geohex_to_long] + +**Syntax** + +:::{image} ../../../images/functions/st_geohex_to_long.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/st_geohex_to_long.md +::: + +:::{include} ../description/st_geohex_to_long.md +::: + +:::{include} ../types/st_geohex_to_long.md +::: + +:::{include} ../examples/st_geohex_to_long.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_string.md new file mode 100644 index 0000000000000..528d28ef6a3ca --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_string.md @@ -0,0 +1,23 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +## `ST_GEOHEX_TO_STRING` [esql-st_geohex_to_string] + +**Syntax** + +:::{image} ../../../images/functions/st_geohex_to_string.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/st_geohex_to_string.md +::: + +:::{include} ../description/st_geohex_to_string.md +::: + +:::{include} ../types/st_geohex_to_string.md +::: + +:::{include} ../examples/st_geohex_to_string.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile.md new file mode 100644 index 0000000000000..b6a8d1b70ffe8 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile.md @@ -0,0 +1,23 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +## `ST_GEOTILE` [esql-st_geotile] + +**Syntax** + +:::{image} ../../../images/functions/st_geotile.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/st_geotile.md +::: + +:::{include} ../description/st_geotile.md +::: + +:::{include} ../types/st_geotile.md +::: + +:::{include} ../examples/st_geotile.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_geoshape.md new file mode 100644 index 0000000000000..e0c608eeaea94 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_geoshape.md @@ -0,0 +1,23 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +## `ST_GEOTILE_TO_GEOSHAPE` [esql-st_geotile_to_geoshape] + +**Syntax** + +:::{image} ../../../images/functions/st_geotile_to_geoshape.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/st_geotile_to_geoshape.md +::: + +:::{include} ../description/st_geotile_to_geoshape.md +::: + +:::{include} ../types/st_geotile_to_geoshape.md +::: + +:::{include} ../examples/st_geotile_to_geoshape.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_long.md new file mode 100644 index 0000000000000..ce5c6151e990b --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_long.md @@ -0,0 +1,23 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +## `ST_GEOTILE_TO_LONG` [esql-st_geotile_to_long] + +**Syntax** + +:::{image} ../../../images/functions/st_geotile_to_long.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/st_geotile_to_long.md +::: + +:::{include} ../description/st_geotile_to_long.md +::: + +:::{include} ../types/st_geotile_to_long.md +::: + +:::{include} ../examples/st_geotile_to_long.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_string.md new file mode 100644 index 0000000000000..1b7d3af345fb1 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_string.md @@ -0,0 +1,23 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +## `ST_GEOTILE_TO_STRING` [esql-st_geotile_to_string] + +**Syntax** + +:::{image} ../../../images/functions/st_geotile_to_string.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/st_geotile_to_string.md +::: + +:::{include} ../description/st_geotile_to_string.md +::: + +:::{include} ../types/st_geotile_to_string.md +::: + +:::{include} ../examples/st_geotile_to_string.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash.md new file mode 100644 index 0000000000000..007af1d6c28f7 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash.md @@ -0,0 +1,13 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`geometry` +: Expression of type `geo_point`. If `null`, the function returns `null`. + +`precision` +: Expression of type `integer`. If `null`, the function returns `null`. + +`bounds` +: Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points + diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_geoshape.md new file mode 100644 index 0000000000000..5db5ddfdfcd2c --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_geoshape.md @@ -0,0 +1,7 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`grid_id` +: Input geohash grid-id. The input can be a single- or multi-valued column or an expression. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_long.md new file mode 100644 index 0000000000000..5db5ddfdfcd2c --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_long.md @@ -0,0 +1,7 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`grid_id` +: Input geohash grid-id. The input can be a single- or multi-valued column or an expression. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_string.md new file mode 100644 index 0000000000000..5db5ddfdfcd2c --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_string.md @@ -0,0 +1,7 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`grid_id` +: Input geohash grid-id. The input can be a single- or multi-valued column or an expression. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex.md new file mode 100644 index 0000000000000..007af1d6c28f7 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex.md @@ -0,0 +1,13 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`geometry` +: Expression of type `geo_point`. If `null`, the function returns `null`. + +`precision` +: Expression of type `integer`. If `null`, the function returns `null`. + +`bounds` +: Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points + diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_geoshape.md new file mode 100644 index 0000000000000..c929ae395f5fc --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_geoshape.md @@ -0,0 +1,7 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`grid_id` +: Input H3 grid-id. The input can be a single- or multi-valued column or an expression. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_long.md new file mode 100644 index 0000000000000..e86ac82e67003 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_long.md @@ -0,0 +1,7 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`grid_id` +: Input geohex grid-id. The input can be a single- or multi-valued column or an expression. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_string.md new file mode 100644 index 0000000000000..cb78878f500bf --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_string.md @@ -0,0 +1,7 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`grid_id` +: Input Geohex grid-id. The input can be a single- or multi-valued column or an expression. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile.md new file mode 100644 index 0000000000000..007af1d6c28f7 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile.md @@ -0,0 +1,13 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`geometry` +: Expression of type `geo_point`. If `null`, the function returns `null`. + +`precision` +: Expression of type `integer`. If `null`, the function returns `null`. + +`bounds` +: Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points + diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_geoshape.md new file mode 100644 index 0000000000000..4a16a5a87faad --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_geoshape.md @@ -0,0 +1,7 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`grid_id` +: Input geotile grid-id. The input can be a single- or multi-valued column or an expression. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_long.md new file mode 100644 index 0000000000000..4a16a5a87faad --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_long.md @@ -0,0 +1,7 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`grid_id` +: Input geotile grid-id. The input can be a single- or multi-valued column or an expression. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_string.md new file mode 100644 index 0000000000000..4a16a5a87faad --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_string.md @@ -0,0 +1,7 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Parameters** + +`grid_id` +: Input geotile grid-id. The input can be a single- or multi-valued column or an expression. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash.md b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash.md new file mode 100644 index 0000000000000..c7f908dd18458 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash.md @@ -0,0 +1,8 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| geometry | precision | bounds | result | +| --- | --- | --- | --- | +| geo_point | integer | | long | + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_geoshape.md new file mode 100644 index 0000000000000..5dec4762ba6ef --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_geoshape.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| grid_id | result | +| --- | --- | +| keyword | geo_shape | +| long | geo_shape | + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_long.md new file mode 100644 index 0000000000000..fb31bb5d9f657 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_long.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| grid_id | result | +| --- | --- | +| keyword | long | +| long | long | + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_string.md new file mode 100644 index 0000000000000..5d10b76e7bd09 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_string.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| grid_id | result | +| --- | --- | +| keyword | keyword | +| long | keyword | + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex.md b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex.md new file mode 100644 index 0000000000000..c7f908dd18458 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex.md @@ -0,0 +1,8 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| geometry | precision | bounds | result | +| --- | --- | --- | --- | +| geo_point | integer | | long | + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_geoshape.md new file mode 100644 index 0000000000000..5dec4762ba6ef --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_geoshape.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| grid_id | result | +| --- | --- | +| keyword | geo_shape | +| long | geo_shape | + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_long.md new file mode 100644 index 0000000000000..fb31bb5d9f657 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_long.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| grid_id | result | +| --- | --- | +| keyword | long | +| long | long | + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_string.md new file mode 100644 index 0000000000000..5d10b76e7bd09 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_string.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| grid_id | result | +| --- | --- | +| keyword | keyword | +| long | keyword | + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile.md b/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile.md new file mode 100644 index 0000000000000..c7f908dd18458 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile.md @@ -0,0 +1,8 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| geometry | precision | bounds | result | +| --- | --- | --- | --- | +| geo_point | integer | | long | + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_geoshape.md new file mode 100644 index 0000000000000..5dec4762ba6ef --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_geoshape.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| grid_id | result | +| --- | --- | +| keyword | geo_shape | +| long | geo_shape | + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_long.md new file mode 100644 index 0000000000000..fb31bb5d9f657 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_long.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| grid_id | result | +| --- | --- | +| keyword | long | +| long | long | + diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_string.md new file mode 100644 index 0000000000000..5d10b76e7bd09 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_string.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +**Supported types** + +| grid_id | result | +| --- | --- | +| keyword | keyword | +| long | keyword | + diff --git a/docs/reference/query-languages/esql/_snippets/lists/spatial-functions.md b/docs/reference/query-languages/esql/_snippets/lists/spatial-functions.md index 83cfdd4c60867..04562d1177602 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/spatial-functions.md +++ b/docs/reference/query-languages/esql/_snippets/lists/spatial-functions.md @@ -10,3 +10,15 @@ * [preview] [`ST_XMIN`](../../functions-operators/spatial-functions.md#esql-st_xmin) * [preview] [`ST_YMAX`](../../functions-operators/spatial-functions.md#esql-st_ymax) * [preview] [`ST_YMIN`](../../functions-operators/spatial-functions.md#esql-st_ymin) +* [preview] [`ST_GEOTILE`](../../functions-operators/spatial-functions.md#esql-st_geotile) +* [preview] [`ST_GEOHEX`](../../functions-operators/spatial-functions.md#esql-st_geohex) +* [preview] [`ST_GEOHASH`](../../functions-operators/spatial-functions.md#esql-st_geohash) +* [preview] [`ST_GEOTILE_TO_STRING`](../../functions-operators/spatial-functions.md#esql-st_geotile_to_string) +* [preview] [`ST_GEOHEX_TO_STRING`](../../functions-operators/spatial-functions.md#esql-st_geohex_to_string) +* [preview] [`ST_GEOHASH_TO_STRING`](../../functions-operators/spatial-functions.md#esql-st_geohash_to_string) +* [preview] [`ST_GEOTILE_TO_LONG`](../../functions-operators/spatial-functions.md#esql-st_geotile_to_long) +* [preview] [`ST_GEOHEX_TO_LONG`](../../functions-operators/spatial-functions.md#esql-st_geohex_to_long) +* [preview] [`ST_GEOHASH_TO_LONG`](../../functions-operators/spatial-functions.md#esql-st_geohash_to_long) +* [preview] [`ST_GEOTILE_TO_GEOSHAPE`](../../functions-operators/spatial-functions.md#esql-st_geotile_to_geoshape) +* [preview] [`ST_GEOHEX_TO_GEOSHAPE`](../../functions-operators/spatial-functions.md#esql-st_geohex_to_geoshape) +* [preview] [`ST_GEOHASH_TO_GEOSHAPE`](../../functions-operators/spatial-functions.md#esql-st_geohash_to_geoshape) diff --git a/docs/reference/query-languages/esql/functions-operators/spatial-functions.md b/docs/reference/query-languages/esql/functions-operators/spatial-functions.md index 806e5e8157a63..a6f50c809585e 100644 --- a/docs/reference/query-languages/esql/functions-operators/spatial-functions.md +++ b/docs/reference/query-languages/esql/functions-operators/spatial-functions.md @@ -48,3 +48,38 @@ mapped_pages: :::{include} ../_snippets/functions/layout/st_ymin.md ::: +:::{include} ../_snippets/functions/layout/st_geotile.md +::: + +:::{include} ../_snippets/functions/layout/st_geohex.md +::: + +:::{include} ../_snippets/functions/layout/st_geohash.md +::: + +:::{include} ../_snippets/functions/layout/st_geotile_to_string.md +::: + +:::{include} ../_snippets/functions/layout/st_geohex_to_string.md +::: + +:::{include} ../_snippets/functions/layout/st_geohash_to_string.md +::: + +:::{include} ../_snippets/functions/layout/st_geotile_to_long.md +::: + +:::{include} ../_snippets/functions/layout/st_geohex_to_long.md +::: + +:::{include} ../_snippets/functions/layout/st_geohash_to_long.md +::: + +:::{include} ../_snippets/functions/layout/st_geotile_to_geoshape.md +::: + +:::{include} ../_snippets/functions/layout/st_geohex_to_geoshape.md +::: + +:::{include} ../_snippets/functions/layout/st_geohash_to_geoshape.md +::: diff --git a/docs/reference/query-languages/esql/images/functions/st_geohash.svg b/docs/reference/query-languages/esql/images/functions/st_geohash.svg new file mode 100644 index 0000000000000..231866d25d521 --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/st_geohash.svg @@ -0,0 +1 @@ +ST_GEOHASH(geometry,precision,bounds) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/st_geohash_to_geoshape.svg b/docs/reference/query-languages/esql/images/functions/st_geohash_to_geoshape.svg new file mode 100644 index 0000000000000..bac257c45dd0b --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/st_geohash_to_geoshape.svg @@ -0,0 +1 @@ +ST_GEOHASH_TO_GEOSHAPE(grid_id) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/st_geohash_to_long.svg b/docs/reference/query-languages/esql/images/functions/st_geohash_to_long.svg new file mode 100644 index 0000000000000..869af17d522de --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/st_geohash_to_long.svg @@ -0,0 +1 @@ +ST_GEOHASH_TO_LONG(grid_id) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/st_geohash_to_string.svg b/docs/reference/query-languages/esql/images/functions/st_geohash_to_string.svg new file mode 100644 index 0000000000000..dcb7e909d81dd --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/st_geohash_to_string.svg @@ -0,0 +1 @@ +ST_GEOHASH_TO_STRING(grid_id) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/st_geohex.svg b/docs/reference/query-languages/esql/images/functions/st_geohex.svg new file mode 100644 index 0000000000000..588cb5374a617 --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/st_geohex.svg @@ -0,0 +1 @@ +ST_GEOHEX(geometry,precision,bounds) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/st_geohex_to_geoshape.svg b/docs/reference/query-languages/esql/images/functions/st_geohex_to_geoshape.svg new file mode 100644 index 0000000000000..0d814904e233f --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/st_geohex_to_geoshape.svg @@ -0,0 +1 @@ +ST_GEOHEX_TO_GEOSHAPE(grid_id) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/st_geohex_to_long.svg b/docs/reference/query-languages/esql/images/functions/st_geohex_to_long.svg new file mode 100644 index 0000000000000..39181484ebe7a --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/st_geohex_to_long.svg @@ -0,0 +1 @@ +ST_GEOHEX_TO_LONG(grid_id) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/st_geohex_to_string.svg b/docs/reference/query-languages/esql/images/functions/st_geohex_to_string.svg new file mode 100644 index 0000000000000..3d96677e1f87e --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/st_geohex_to_string.svg @@ -0,0 +1 @@ +ST_GEOHEX_TO_STRING(grid_id) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/st_geotile.svg b/docs/reference/query-languages/esql/images/functions/st_geotile.svg new file mode 100644 index 0000000000000..ee97511f568cc --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/st_geotile.svg @@ -0,0 +1 @@ +ST_GEOTILE(geometry,precision,bounds) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/st_geotile_to_geoshape.svg b/docs/reference/query-languages/esql/images/functions/st_geotile_to_geoshape.svg new file mode 100644 index 0000000000000..26d8d6c7a0778 --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/st_geotile_to_geoshape.svg @@ -0,0 +1 @@ +ST_GEOTILE_TO_GEOSHAPE(grid_id) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/st_geotile_to_long.svg b/docs/reference/query-languages/esql/images/functions/st_geotile_to_long.svg new file mode 100644 index 0000000000000..8ac85e2baa2d4 --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/st_geotile_to_long.svg @@ -0,0 +1 @@ +ST_GEOTILE_TO_LONG(grid_id) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/st_geotile_to_string.svg b/docs/reference/query-languages/esql/images/functions/st_geotile_to_string.svg new file mode 100644 index 0000000000000..cbe406dd19211 --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/st_geotile_to_string.svg @@ -0,0 +1 @@ +ST_GEOTILE_TO_STRING(grid_id) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash.json new file mode 100644 index 0000000000000..5a6e75496f253 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash.json @@ -0,0 +1,31 @@ +{ + "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "st_geohash", + "description" : "Calculates the `geohash` of the supplied geo_point at the specified precision.\nThe result is long encoded. Use ST_GEOHASH_TO_STRING to convert the result to a string.\nOr use ST_GEOHASH_TO_GEOSHAPE to convert either the long or string `geohash` to a\nPOLYGON geo_shape.", + "signatures" : [ + { + "params" : [ + { + "name" : "geometry", + "type" : "geo_point", + "optional" : false, + "description" : "Expression of type `geo_point`. If `null`, the function returns `null`." + }, + { + "name" : "precision", + "type" : "integer", + "optional" : false, + "description" : "Expression of type `integer`. If `null`, the function returns `null`." + } + ], + "variadic" : false, + "returnType" : "long" + } + ], + "examples" : [ + "FROM airports\n| EVAL geohash = ST_GEOHASH(location, 1)\n| STATS\n count = COUNT(*),\n centroid = ST_CENTROID_AGG(location)\n BY geohash\n| WHERE count >= 10\n| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash)\n| KEEP count, centroid, geohashString\n| SORT count DESC, geohashString ASC" + ], + "preview" : false, + "snapshot_only" : false +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_geoshape.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_geoshape.json new file mode 100644 index 0000000000000..9997c0f166d95 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_geoshape.json @@ -0,0 +1,37 @@ +{ + "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "st_geohash_to_geoshape", + "description" : "Converts an input value to a `geo_shape` value.\nThe input values are expected to be the grid-ids of geohash grids, in either long or string format.", + "signatures" : [ + { + "params" : [ + { + "name" : "grid_id", + "type" : "keyword", + "optional" : false, + "description" : "Input geohash grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geo_shape" + }, + { + "params" : [ + { + "name" : "grid_id", + "type" : "long", + "optional" : false, + "description" : "Input geohash grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geo_shape" + } + ], + "examples" : [ + "ROW geohash = \"u3bu\"\n| EVAL boundary = ST_GEOHASH_TO_GEOSHAPE(geohash)" + ], + "preview" : false, + "snapshot_only" : false +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_long.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_long.json new file mode 100644 index 0000000000000..f6b14f780e955 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_long.json @@ -0,0 +1,37 @@ +{ + "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "st_geohash_to_long", + "description" : "Converts an input value representing a geohash grid-ID in string format into a long.", + "signatures" : [ + { + "params" : [ + { + "name" : "grid_id", + "type" : "keyword", + "optional" : false, + "description" : "Input geohash grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "long" + }, + { + "params" : [ + { + "name" : "grid_id", + "type" : "long", + "optional" : false, + "description" : "Input geohash grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "long" + } + ], + "examples" : [ + "ROW geohash = \"u3bu\"\n| EVAL geohashLong = ST_GEOHASH_TO_LONG(geohash)" + ], + "preview" : false, + "snapshot_only" : false +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_string.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_string.json new file mode 100644 index 0000000000000..d6b55c483ced5 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_string.json @@ -0,0 +1,37 @@ +{ + "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "st_geohash_to_string", + "description" : "Converts an input value representing a geohash grid-ID in long format into a string.", + "signatures" : [ + { + "params" : [ + { + "name" : "grid_id", + "type" : "keyword", + "optional" : false, + "description" : "Input geohash grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "keyword" + }, + { + "params" : [ + { + "name" : "grid_id", + "type" : "long", + "optional" : false, + "description" : "Input geohash grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "keyword" + } + ], + "examples" : [ + "ROW geohash = TO_LONG(13686180)\n| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash)" + ], + "preview" : false, + "snapshot_only" : false +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex.json new file mode 100644 index 0000000000000..4d640329d8666 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex.json @@ -0,0 +1,31 @@ +{ + "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "st_geohex", + "description" : "Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision.\nThe result is long encoded. Use ST_GEOHEX_TO_STRING to convert the result to a string.\nOr use ST_GEOHEX_TO_GEOSHAPE to convert either the long or string `geohex` to a\nPOLYGON geo_shape.", + "signatures" : [ + { + "params" : [ + { + "name" : "geometry", + "type" : "geo_point", + "optional" : false, + "description" : "Expression of type `geo_point`. If `null`, the function returns `null`." + }, + { + "name" : "precision", + "type" : "integer", + "optional" : false, + "description" : "Expression of type `integer`. If `null`, the function returns `null`." + } + ], + "variadic" : false, + "returnType" : "long" + } + ], + "examples" : [ + "FROM airports\n| EVAL geohex = ST_GEOHEX(location, 1)\n| STATS\n count = COUNT(*),\n centroid = ST_CENTROID_AGG(location)\n BY geohex\n| WHERE count >= 10\n| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex)\n| KEEP count, centroid, geohexString\n| SORT count DESC, geohexString ASC" + ], + "preview" : false, + "snapshot_only" : false +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_geoshape.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_geoshape.json new file mode 100644 index 0000000000000..dde729a91ed2a --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_geoshape.json @@ -0,0 +1,37 @@ +{ + "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "st_geohex_to_geoshape", + "description" : "Converts an input value to a `geo_shape` value.\nThe input values are expected to be the grid-ids of H3 grids, in either long or string format.", + "signatures" : [ + { + "params" : [ + { + "name" : "grid_id", + "type" : "keyword", + "optional" : false, + "description" : "Input H3 grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geo_shape" + }, + { + "params" : [ + { + "name" : "grid_id", + "type" : "long", + "optional" : false, + "description" : "Input H3 grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geo_shape" + } + ], + "examples" : [ + "ROW geohex = \"841f059ffffffff\"\n| EVAL boundary = ST_GEOHEX_TO_GEOSHAPE(geohex)" + ], + "preview" : false, + "snapshot_only" : false +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_long.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_long.json new file mode 100644 index 0000000000000..474c4f63ea8a6 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_long.json @@ -0,0 +1,37 @@ +{ + "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "st_geohex_to_long", + "description" : "Converts an input value representing a geohex grid-ID in string format into a long.", + "signatures" : [ + { + "params" : [ + { + "name" : "grid_id", + "type" : "keyword", + "optional" : false, + "description" : "Input geohex grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "long" + }, + { + "params" : [ + { + "name" : "grid_id", + "type" : "long", + "optional" : false, + "description" : "Input geohex grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "long" + } + ], + "examples" : [ + "ROW geohex = \"841f059ffffffff\"\n| EVAL geohexLong = ST_GEOHEX_TO_LONG(geohex)" + ], + "preview" : false, + "snapshot_only" : false +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_string.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_string.json new file mode 100644 index 0000000000000..0d83038db609e --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_string.json @@ -0,0 +1,37 @@ +{ + "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "st_geohex_to_string", + "description" : "Converts an input value representing a Geohex grid-ID in long format into a string.", + "signatures" : [ + { + "params" : [ + { + "name" : "grid_id", + "type" : "keyword", + "optional" : false, + "description" : "Input Geohex grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "keyword" + }, + { + "params" : [ + { + "name" : "grid_id", + "type" : "long", + "optional" : false, + "description" : "Input Geohex grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "keyword" + } + ], + "examples" : [ + "ROW geohex = 595020895127339007\n| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex)" + ], + "preview" : false, + "snapshot_only" : false +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile.json new file mode 100644 index 0000000000000..68bac0f446f4f --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile.json @@ -0,0 +1,31 @@ +{ + "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "st_geotile", + "description" : "Calculates the `geotile` of the supplied geo_point at the specified precision.\nThe result is long encoded. Use ST_GEOTILE_TO_STRING to convert the result to a string.\nOr use ST_GEOTILE_TO_GEOSHAPE to convert either the long or string `geotile` to a\nPOLYGON geo_shape.", + "signatures" : [ + { + "params" : [ + { + "name" : "geometry", + "type" : "geo_point", + "optional" : false, + "description" : "Expression of type `geo_point`. If `null`, the function returns `null`." + }, + { + "name" : "precision", + "type" : "integer", + "optional" : false, + "description" : "Expression of type `integer`. If `null`, the function returns `null`." + } + ], + "variadic" : false, + "returnType" : "long" + } + ], + "examples" : [ + "FROM airports\n| EVAL geotile = ST_GEOTILE(location, 2)\n| STATS\n count = COUNT(*),\n centroid = ST_CENTROID_AGG(location)\n BY geotile\n| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile)\n| SORT count DESC, geotileString ASC\n| KEEP count, centroid, geotileString" + ], + "preview" : false, + "snapshot_only" : false +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_geoshape.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_geoshape.json new file mode 100644 index 0000000000000..1801f8d9735a3 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_geoshape.json @@ -0,0 +1,37 @@ +{ + "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "st_geotile_to_geoshape", + "description" : "Converts an input value to a `geo_shape` value.\nThe input values are expected to be the grid-ids of geotile grids, in either long or string format.", + "signatures" : [ + { + "params" : [ + { + "name" : "grid_id", + "type" : "keyword", + "optional" : false, + "description" : "Input geotile grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geo_shape" + }, + { + "params" : [ + { + "name" : "grid_id", + "type" : "long", + "optional" : false, + "description" : "Input geotile grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geo_shape" + } + ], + "examples" : [ + "ROW geotile = \"4/8/5\"\n| EVAL boundary = ST_GEOTILE_TO_GEOSHAPE(geotile)" + ], + "preview" : false, + "snapshot_only" : false +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_long.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_long.json new file mode 100644 index 0000000000000..e2aefafa33fdc --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_long.json @@ -0,0 +1,37 @@ +{ + "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "st_geotile_to_long", + "description" : "Converts an input value representing a geotile grid-ID in string format into a long.", + "signatures" : [ + { + "params" : [ + { + "name" : "grid_id", + "type" : "keyword", + "optional" : false, + "description" : "Input geotile grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "long" + }, + { + "params" : [ + { + "name" : "grid_id", + "type" : "long", + "optional" : false, + "description" : "Input geotile grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "long" + } + ], + "examples" : [ + "ROW geotile = \"4/8/5\"\n| EVAL geotileLong = ST_GEOTILE_TO_LONG(geotile)" + ], + "preview" : false, + "snapshot_only" : false +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_string.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_string.json new file mode 100644 index 0000000000000..effe374bab93c --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_string.json @@ -0,0 +1,37 @@ +{ + "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "st_geotile_to_string", + "description" : "Converts an input value representing a geotile grid-ID in long format into a string.", + "signatures" : [ + { + "params" : [ + { + "name" : "grid_id", + "type" : "keyword", + "optional" : false, + "description" : "Input geotile grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "keyword" + }, + { + "params" : [ + { + "name" : "grid_id", + "type" : "long", + "optional" : false, + "description" : "Input geotile grid-id. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "keyword" + } + ], + "examples" : [ + "ROW geotile = 1152921508901814277\n| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile)" + ], + "preview" : false, + "snapshot_only" : false +} diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash.md new file mode 100644 index 0000000000000..c16e1957f67eb --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash.md @@ -0,0 +1,20 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +### ST GEOHASH +Calculates the `geohash` of the supplied geo_point at the specified precision. +The result is long encoded. Use [ST_GEOHASH_TO_STRING](#esql-st_geohash_to_string) to convert the result to a string. +Or use [ST_GEOHASH_TO_GEOSHAPE](#esql-st_geohash_to_geoshape) to convert either the long or string `geohash` to a +POLYGON geo_shape. + +```esql +FROM airports +| EVAL geohash = ST_GEOHASH(location, 1) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geohash +| WHERE count >= 10 +| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +| KEEP count, centroid, geohashString +| SORT count DESC, geohashString ASC +``` diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_geoshape.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_geoshape.md new file mode 100644 index 0000000000000..debf86f9d1340 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_geoshape.md @@ -0,0 +1,10 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +### ST GEOHASH TO GEOSHAPE +Converts an input value to a `geo_shape` value. +The input values are expected to be the grid-ids of geohash grids, in either long or string format. + +```esql +ROW geohash = "u3bu" +| EVAL boundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +``` diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_long.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_long.md new file mode 100644 index 0000000000000..f949358288160 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_long.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +### ST GEOHASH TO LONG +Converts an input value representing a geohash grid-ID in string format into a long. + +```esql +ROW geohash = "u3bu" +| EVAL geohashLong = ST_GEOHASH_TO_LONG(geohash) +``` diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_string.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_string.md new file mode 100644 index 0000000000000..fbd7dbd3d4d0a --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_string.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +### ST GEOHASH TO STRING +Converts an input value representing a geohash grid-ID in long format into a string. + +```esql +ROW geohash = TO_LONG(13686180) +| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +``` diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex.md new file mode 100644 index 0000000000000..cca0ffe4c20bc --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex.md @@ -0,0 +1,20 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +### ST GEOHEX +Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision. +The result is long encoded. Use [ST_GEOHEX_TO_STRING](#esql-st_geohex_to_string) to convert the result to a string. +Or use [ST_GEOHEX_TO_GEOSHAPE](#esql-st_geohex_to_geoshape) to convert either the long or string `geohex` to a +POLYGON geo_shape. + +```esql +FROM airports +| EVAL geohex = ST_GEOHEX(location, 1) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geohex +| WHERE count >= 10 +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| KEEP count, centroid, geohexString +| SORT count DESC, geohexString ASC +``` diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_geoshape.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_geoshape.md new file mode 100644 index 0000000000000..85a2339792739 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_geoshape.md @@ -0,0 +1,10 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +### ST GEOHEX TO GEOSHAPE +Converts an input value to a `geo_shape` value. +The input values are expected to be the grid-ids of H3 grids, in either long or string format. + +```esql +ROW geohex = "841f059ffffffff" +| EVAL boundary = ST_GEOHEX_TO_GEOSHAPE(geohex) +``` diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_long.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_long.md new file mode 100644 index 0000000000000..393cde5be1e99 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_long.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +### ST GEOHEX TO LONG +Converts an input value representing a geohex grid-ID in string format into a long. + +```esql +ROW geohex = "841f059ffffffff" +| EVAL geohexLong = ST_GEOHEX_TO_LONG(geohex) +``` diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_string.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_string.md new file mode 100644 index 0000000000000..ba06c681d5af3 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_string.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +### ST GEOHEX TO STRING +Converts an input value representing a Geohex grid-ID in long format into a string. + +```esql +ROW geohex = 595020895127339007 +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +``` diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile.md new file mode 100644 index 0000000000000..603673dad4f54 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile.md @@ -0,0 +1,19 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +### ST GEOTILE +Calculates the `geotile` of the supplied geo_point at the specified precision. +The result is long encoded. Use [ST_GEOTILE_TO_STRING](#esql-st_geotile_to_string) to convert the result to a string. +Or use [ST_GEOTILE_TO_GEOSHAPE](#esql-st_geotile_to_geoshape) to convert either the long or string `geotile` to a +POLYGON geo_shape. + +```esql +FROM airports +| EVAL geotile = ST_GEOTILE(location, 2) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geotile +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| SORT count DESC, geotileString ASC +| KEEP count, centroid, geotileString +``` diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_geoshape.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_geoshape.md new file mode 100644 index 0000000000000..e03fbdd662c96 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_geoshape.md @@ -0,0 +1,10 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +### ST GEOTILE TO GEOSHAPE +Converts an input value to a `geo_shape` value. +The input values are expected to be the grid-ids of geotile grids, in either long or string format. + +```esql +ROW geotile = "4/8/5" +| EVAL boundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +``` diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_long.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_long.md new file mode 100644 index 0000000000000..75f42b84ae03e --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_long.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +### ST GEOTILE TO LONG +Converts an input value representing a geotile grid-ID in string format into a long. + +```esql +ROW geotile = "4/8/5" +| EVAL geotileLong = ST_GEOTILE_TO_LONG(geotile) +``` diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_string.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_string.md new file mode 100644 index 0000000000000..620047aa7ccc2 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_string.md @@ -0,0 +1,9 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +### ST GEOTILE TO STRING +Converts an input value representing a geotile grid-ID in long format into a string. + +```esql +ROW geotile = 1152921508901814277 +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +``` diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index c4b865fc8878d..bc03552fc1621 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -5,34 +5,46 @@ geohashStringToLong required_capability: spatial_grid +// tag::geohash_to_long[] ROW geohash = "u3bu" | EVAL geohashLong = ST_GEOHASH_TO_LONG(geohash) +// end::geohash_to_long[] ; +// tag::geohash_to_long-result[] geohash:keyword | geohashLong:long u3bu | 13686180 +// end::geohash_to_long-result[] ; geohashLongToString required_capability: spatial_grid +// tag::geohash_to_string[] ROW geohash = TO_LONG(13686180) | EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +// end::geohash_to_string[] ; +// tag::geohash_to_string-result[] geohash:long | geohashString:keyword 13686180 | u3bu +// end::geohash_to_string-result[] ; geohashStringToGeoShape required_capability: spatial_grid +// tag::geohash_to_geoshape[] ROW geohash = "u3bu" | EVAL boundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +// end::geohash_to_geoshape[] ; +// tag::geohash_to_geoshape-result[] geohash:keyword | boundary:geo_shape u3bu | BBOX (12.3046875, 12.65625, 55.72265625, 55.546875) +// end::geohash_to_geoshape-result[] ; geohashLongToGeoShape @@ -127,9 +139,9 @@ geohash:long | geohashString:keyword | abbrev:keyword | name:text | location:ge ; gridGeohashStatsBy -// tag::st_geohash-grid[] required_capability: spatial_grid +// tag::st_geohash-grid[] FROM airports | EVAL geohash = ST_GEOHASH(location, 1) | STATS @@ -292,14 +304,46 @@ count:long | centroid:geo_point geotileStringToLong required_capability: spatial_grid +// tag::geotile_to_long[] ROW geotile = "4/8/5" | EVAL geotileLong = ST_GEOTILE_TO_LONG(geotile) -| EVAL geotileString = ST_GEOTILE_TO_STRING(geotileLong) +// end::geotile_to_long[] +; + +// tag::geotile_to_long-result[] +geotile:keyword | geotileLong:long +4/8/5 | 1152921508901814277 +// end::geotile_to_long-result[] +; + +geotileLongToString +required_capability: spatial_grid + +// tag::geotile_to_string[] +ROW geotile = 1152921508901814277 +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +// end::geotile_to_string[] +; + +// tag::geotile_to_string-result[] +geotile:long | geotileString:keyword +1152921508901814277 | 4/8/5 +// end::geotile_to_string-result[] +; + +geotileStringToGeoshape +required_capability: spatial_grid + +// tag::geotile_to_geoshape[] +ROW geotile = "4/8/5" | EVAL boundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +// end::geotile_to_geoshape[] ; -geotile:keyword | geotileLong:long | geotileString:keyword | boundary:geo_shape -4/8/5 | 1152921508901814277 | 4/8/5 | BBOX (0.0, 22.5, 55.77657301866769, 40.979898069620134) +// tag::geotile_to_geoshape-result[] +geotile:keyword | boundary:geo_shape +4/8/5 | BBOX (0.0, 22.5, 55.77657301866769, 40.979898069620134) +// end::geotile_to_geoshape-result[] ; geotileLiteral @@ -383,9 +427,9 @@ geotile:long | geotileString:keyword | abbrev:keyword | name:text | loca ; gridGeotileStatsBy -// tag::st_geotile-grid[] required_capability: spatial_grid +// tag::st_geotile-grid[] FROM airports | EVAL geotile = ST_GEOTILE(location, 2) | STATS @@ -524,14 +568,46 @@ count:long | centroid:geo_point geohexStringToLong required_capability: spatial_grid +// tag::geohex_to_long[] ROW geohex = "841f059ffffffff" | EVAL geohexLong = ST_GEOHEX_TO_LONG(geohex) -| EVAL geohexString = ST_GEOHEX_TO_STRING(geohexLong) +// end::geohex_to_long[] +; + +// tag::geohex_to_long-result[] +geohex:keyword | geohexLong:long +841f059ffffffff | 595020895127339007 +// end::geohex_to_long-result[] +; + +geohexLongToString +required_capability: spatial_grid + +// tag::geohex_to_string[] +ROW geohex = 595020895127339007 +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +// end::geohex_to_string[] +; + +// tag::geohex_to_string-result[] +geohex:long | geohexString:keyword +595020895127339007 | 841f059ffffffff +// end::geohex_to_string-result[] +; + +geohexStringToGeoshape +required_capability: spatial_grid + +// tag::geohex_to_geoshape[] +ROW geohex = "841f059ffffffff" | EVAL boundary = ST_GEOHEX_TO_GEOSHAPE(geohex) +// end::geohex_to_geoshape[] ; -geohex:keyword | geohexLong:long | geohexString:keyword | boundary:geo_shape -841f059ffffffff | 595020895127339007 | 841f059ffffffff | POLYGON ((12.353546327258265 55.80335405461356, 12.2434612967008 55.60502874054935, 12.51733872608954 55.470800201545316, 12.901880149865134 55.53443156197633, 13.014270156228921 55.73262985778208, 12.739822958959069 55.8673267391136, 12.353546327258265 55.80335405461356)) +// tag::geohex_to_geoshape-result[] +geohex:keyword | boundary:geo_shape +841f059ffffffff | POLYGON ((12.353546327258265 55.80335405461356, 12.2434612967008 55.60502874054935, 12.51733872608954 55.470800201545316, 12.901880149865134 55.53443156197633, 13.014270156228921 55.73262985778208, 12.739822958959069 55.8673267391136, 12.353546327258265 55.80335405461356)) +// end::geohex_to_geoshape-result[] ; geohexLiteral @@ -615,9 +691,9 @@ geohex:long | geohexString:keyword | abbrev:keyword | name:text | locati ; gridGeohexStatsBy -// tag::st_geohex-grid[] required_capability: spatial_grid +// tag::st_geohex-grid[] FROM airports | EVAL geohex = ST_GEOHEX(location, 1) | STATS diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java index 217876e9f26af..93a4b2ed45d28 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java @@ -45,18 +45,15 @@ public class StGeohash extends SpatialGridFunction implements EvaluatorMapper { StGeohash::new ); - @FunctionInfo( - returnType = "long", - description = """ - Calculates the `geohash` of the supplied geo_point at the specified precision. - The result is long encoded. Use ST_GEOHASH_TO_STRING to convert the result to a string. - Or use ST_GEOHASH_TO_GEOSHAPE to convert either the long or string geohash to a BBOX geo_shape.""", - examples = @Example(file = "spatial-grid", tag = "st_geohash-grid") - ) + @FunctionInfo(returnType = "long", description = """ + Calculates the `geohash` of the supplied geo_point at the specified precision. + The result is long encoded. Use [ST_GEOHASH_TO_STRING](#esql-st_geohash_to_string) to convert the result to a string. + Or use [ST_GEOHASH_TO_GEOSHAPE](#esql-st_geohash_to_geoshape) to convert either the long or string `geohash` to a + POLYGON geo_shape.""", examples = @Example(file = "spatial-grid", tag = "st_geohash-grid")) public StGeohash( Source source, @Param( - name = "point", + name = "geometry", type = { "geo_point" }, description = "Expression of type `geo_point`. If `null`, the function returns `null`." ) Expression field, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java index 2f668fbc1ba80..4b8e26e897abf 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java @@ -40,18 +40,15 @@ public class StGeohex extends SpatialGridFunction implements EvaluatorMapper { public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "StGeohex", StGeohex::new); - @FunctionInfo( - returnType = "long", - description = """ - Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision. - The result is long encoded. Use ST_GEOHEX_TO_STRING to convert the result to a string. - Or use ST_GEOHEX_TO_GEOSHAPE to convert either the long or string geohex to a POLYGON geo_shape.""", - examples = @Example(file = "spatial-grid", tag = "st_geohex-grid") - ) + @FunctionInfo(returnType = "long", description = """ + Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision. + The result is long encoded. Use [ST_GEOHEX_TO_STRING](#esql-st_geohex_to_string) to convert the result to a string. + Or use [ST_GEOHEX_TO_GEOSHAPE](#esql-st_geohex_to_geoshape) to convert either the long or string `geohex` to a + POLYGON geo_shape.""", examples = @Example(file = "spatial-grid", tag = "st_geohex-grid")) public StGeohex( Source source, @Param( - name = "point", + name = "geometry", type = { "geo_point" }, description = "Expression of type `geo_point`. If `null`, the function returns `null`." ) Expression field, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java index 2470ad30690b5..b801d279d66c6 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java @@ -52,7 +52,7 @@ public class StGeohexToGeoShape extends AbstractConvertFunction implements Evalu description = """ Converts an input value to a `geo_shape` value. The input values are expected to be the grid-ids of H3 grids, in either long or string format.""", - examples = @Example(file = "spatial-grid", tag = "geohex-to_geoshape") + examples = @Example(file = "spatial-grid", tag = "geohex_to_geoshape") ) public StGeohexToGeoShape( Source source, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java index aafcbe4963a32..8e1fc18cfcefc 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java @@ -44,7 +44,7 @@ public class StGeohexToString extends AbstractConvertFunction implements Evaluat @FunctionInfo( returnType = "keyword", description = "Converts an input value representing a Geohex grid-ID in long format into a string.", - examples = { @Example(file = "spatial-grid", tag = "Geohex_to_string") } + examples = { @Example(file = "spatial-grid", tag = "geohex_to_string") } ) public StGeohexToString( Source source, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java index 773761673a575..f56980d674096 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java @@ -45,18 +45,15 @@ public class StGeotile extends SpatialGridFunction implements EvaluatorMapper { StGeotile::new ); - @FunctionInfo( - returnType = "long", - description = """ - Calculates the `geotile` of the supplied geo_point at the specified precision. - The result is long encoded. Use ST_GEOTILE_TO_STRING to convert the result to a string. - Or use ST_GEOTILE_TO_GEOSHAPE to convert either the long or string geotile to a BBOX geo_shape.""", - examples = @Example(file = "spatial-grid", tag = "st_geotile-grid") - ) + @FunctionInfo(returnType = "long", description = """ + Calculates the `geotile` of the supplied geo_point at the specified precision. + The result is long encoded. Use [ST_GEOTILE_TO_STRING](#esql-st_geotile_to_string) to convert the result to a string. + Or use [ST_GEOTILE_TO_GEOSHAPE](#esql-st_geotile_to_geoshape) to convert either the long or string `geotile` to a + POLYGON geo_shape.""", examples = @Example(file = "spatial-grid", tag = "st_geotile-grid")) public StGeotile( Source source, @Param( - name = "point", + name = "geometry", type = { "geo_point" }, description = "Expression of type `geo_point`. If `null`, the function returns `null`." ) Expression field, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java index bac4edc96e18f..55818a6f260e3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java @@ -49,7 +49,7 @@ public class StGeotileToGeoShape extends AbstractConvertFunction implements Eval description = """ Converts an input value to a `geo_shape` value. The input values are expected to be the grid-ids of geotile grids, in either long or string format.""", - examples = @Example(file = "spatial-grid", tag = "geotile-to_geoshape") + examples = @Example(file = "spatial-grid", tag = "geotile_to_geoshape") ) public StGeotileToGeoShape( Source source, diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunctionTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunctionTestCase.java new file mode 100644 index 0000000000000..3678ecd65df1f --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunctionTestCase.java @@ -0,0 +1,90 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.List; +import java.util.function.BiFunction; + +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; +import static org.elasticsearch.xpack.esql.core.type.DataType.isSpatialGeo; +import static org.hamcrest.Matchers.equalTo; + +public abstract class SpatialGridFunctionTestCase extends AbstractScalarFunctionTestCase { + + private static String getFunctionClassName() { + Class testClass = getTestClass(); + String testClassName = testClass.getSimpleName(); + return testClassName.replace("Tests", ""); + } + + protected static void addTestCaseSuppliers( + List suppliers, + DataType[] dataTypes, + BiFunction expectedValue + ) { + for (DataType spatialType : dataTypes) { + DataType shapeType = isSpatialGeo(spatialType) ? DataType.GEO_SHAPE : DataType.CARTESIAN_SHAPE; + TestCaseSupplier.TypedDataSupplier geometrySupplier = testCaseSupplier(spatialType, true); + suppliers.add(new TestCaseSupplier("with precision", List.of(spatialType, DataType.INTEGER), () -> { + TestCaseSupplier.TypedData geoTypedData = geometrySupplier.get(); + BytesRef geometry = (BytesRef) geoTypedData.data(); + int precision = between(1, 8); + TestCaseSupplier.TypedData precisionData = new TestCaseSupplier.TypedData(precision, DataType.INTEGER, "precision"); + return new TestCaseSupplier.TestCase( + List.of(geoTypedData, precisionData), + getFunctionClassName() + "FromFieldAndFieldEvaluator[in=Attribute[channel=0], precision=Attribute[channel=1]]", + LONG, + equalTo(expectedValue.apply(geometry, precision)) + ); + })); + /* + TODO: Implement non-foldable bounds + suppliers.add(new TestCaseSupplier("with precision and bounds", List.of(spatialType, DataType.INTEGER, shapeType), () -> { + TestCaseSupplier.TypedData geoTypedData = geometrySupplier.get(); + BytesRef geometry = (BytesRef) geoTypedData.data(); + int precision = between(1, 8); + TestCaseSupplier.TypedData precisionData = new TestCaseSupplier.TypedData(precision, DataType.INTEGER, "precision"); + Rectangle bounds = new Rectangle(-30, 30, 30, -30); + BytesRef boundsBytesRef = GEO.asWkb(bounds); + TestCaseSupplier.TypedData boundsData = new TestCaseSupplier.TypedData(boundsBytesRef, shapeType, "bounds"); + return new TestCaseSupplier.TestCase( + List.of(geoTypedData, precisionData, boundsData), + getFunctionClassName() + + "FromFieldAndFieldAndLiteralEvaluator[" + + "in=Attribute[channel=0], precision=Attribute[channel=1], bounds=Attribute[channel=2]]", + LONG, + equalTo(expectedValue.apply(geometry, precision)) + ); + })); + */ + } + } + + public static TestCaseSupplier.TypedDataSupplier testCaseSupplier(DataType dataType, boolean pointsOnly) { + if (pointsOnly) { + return switch (dataType.esType()) { + case "geo_point" -> TestCaseSupplier.geoPointCases(() -> false).get(0); + case "cartesian_point" -> TestCaseSupplier.cartesianPointCases(() -> false).get(0); + default -> throw new IllegalArgumentException("Unsupported datatype for " + functionName() + ": " + dataType); + }; + } else { + return switch (dataType.esType()) { + case "geo_point" -> TestCaseSupplier.geoPointCases(() -> false).get(0); + case "geo_shape" -> TestCaseSupplier.geoShapeCases(() -> false).get(0); + case "cartesian_point" -> TestCaseSupplier.cartesianPointCases(() -> false).get(0); + case "cartesian_shape" -> TestCaseSupplier.cartesianShapeCases(() -> false).get(0); + default -> throw new IllegalArgumentException("Unsupported datatype for " + functionName() + ": " + dataType); + }; + } + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridTypeConversionTestCases.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridTypeConversionTestCases.java new file mode 100644 index 0000000000000..c69269cbf7a83 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridTypeConversionTestCases.java @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.List; +import java.util.function.Function; + +import static org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier.geoPointCases; + +public abstract class SpatialGridTypeConversionTestCases extends AbstractScalarFunctionTestCase { + public static void forUnaryGeoPoint( + DataType type, + List suppliers, + String expectedEvaluatorToString, + DataType expectedType, + Function geometryToGeotile, + Function expectedValue + ) { + TestCaseSupplier.unary( + suppliers, + expectedEvaluatorToString, + geoPointAsGeotileCases(type, geometryToGeotile), + expectedType, + expectedValue::apply, + List.of() + ); + } + + public static List geoPointAsGeotileCases( + DataType type, + Function geometryToGeotile + ) { + return geoPointCases(ESTestCase::randomBoolean).stream() + .map( + t -> new TestCaseSupplier.TypedDataSupplier( + t.name() + " as " + type, + () -> geometryToGeotile.apply((BytesRef) t.supplier().get()), + type + ) + ) + .toList(); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java new file mode 100644 index 0000000000000..7acfc5a6c21ec --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +public class StGeohashTests extends SpatialGridFunctionTestCase { + public StGeohashTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + addTestCaseSuppliers(suppliers, new DataType[] { DataType.GEO_POINT }, StGeohashTests::valueOf); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static long valueOf(BytesRef wkb, int precision) { + return StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(wkb), precision); + } + + @Override + protected Expression build(Source source, List args) { + Expression bounds = args.size() > 2 ? args.get(2) : null; + return new StGeohash(source, args.get(0), args.get(1), bounds); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java new file mode 100644 index 0000000000000..07194782037b4 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.FunctionName; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +@FunctionName("st_geohash_to_geoshape") +public class StGeohashToGeoShapeTests extends SpatialGridTypeConversionTestCases { + public StGeohashToGeoShapeTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + forUnaryGeoPoint( + DataType.LONG, + suppliers, + "StGeohashToGeoShapeFromLongEvaluator[gridId=Attribute[channel=0]]", + GEO_SHAPE, + g -> StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(g), 2), + StGeohashToGeoShapeTests::valueOf + ); + forUnaryGeoPoint( + DataType.KEYWORD, + suppliers, + "StGeohashToGeoShapeFromStringEvaluator[gridId=Attribute[channel=0]]", + GEO_SHAPE, + g -> new BytesRef(Geohash.stringEncode(StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(g), 2))), + StGeohashToGeoShapeTests::valueOf + ); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static BytesRef valueOf(Object gridid) { + return (gridid instanceof Long hash) ? StGeohashToGeoShape.fromLong(hash) : StGeohashToGeoShape.fromString((BytesRef) gridid); + } + + @Override + protected Expression build(Source source, List args) { + return new StGeohashToGeoShape(source, args.get(0)); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongTests.java new file mode 100644 index 0000000000000..5a8787ede1303 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongTests.java @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.FunctionName; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +@FunctionName("st_geohash_to_long") +public class StGeohashToLongTests extends SpatialGridTypeConversionTestCases { + public StGeohashToLongTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + forUnaryGeoPoint( + DataType.LONG, + suppliers, + "Attribute[channel=0]", + DataType.LONG, + g -> StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(g), 2), + StGeohashToLongTests::valueOf + ); + forUnaryGeoPoint( + DataType.KEYWORD, + suppliers, + "StGeohashToLongFromStringEvaluator[gridId=Attribute[channel=0]]", + DataType.LONG, + g -> new BytesRef(Geohash.stringEncode(StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(g), 2))), + StGeohashToLongTests::valueOf + ); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static long valueOf(Object gridid) { + return (gridid instanceof Long hash) ? hash : Geohash.longEncode(((BytesRef) gridid).utf8ToString()); + } + + @Override + protected Expression build(Source source, List args) { + return new StGeohashToLong(source, args.get(0)); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.java new file mode 100644 index 0000000000000..75b7c9b2ba695 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.java @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.FunctionName; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +@FunctionName("st_geohash_to_string") +public class StGeohashToStringTests extends SpatialGridTypeConversionTestCases { + public StGeohashToStringTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + forUnaryGeoPoint( + DataType.LONG, + suppliers, + "StGeohashToStringFromLongEvaluator[gridId=Attribute[channel=0]]", + KEYWORD, + g -> StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(g), 2), + StGeohashToStringTests::valueOf + ); + forUnaryGeoPoint( + DataType.KEYWORD, + suppliers, + "Attribute[channel=0]", + KEYWORD, + g -> new BytesRef(Geohash.stringEncode(StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(g), 2))), + StGeohashToStringTests::valueOf + ); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static BytesRef valueOf(Object gridid) { + return (gridid instanceof Long hash) ? new BytesRef(Geohash.stringEncode(hash)) : (BytesRef) gridid; + } + + @Override + protected Expression build(Source source, List args) { + return new StGeohashToString(source, args.get(0)); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexTests.java new file mode 100644 index 0000000000000..56427a24daf53 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexTests.java @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +public class StGeohexTests extends SpatialGridFunctionTestCase { + public StGeohexTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + addTestCaseSuppliers(suppliers, new DataType[] { DataType.GEO_POINT }, StGeohexTests::valueOf); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static long valueOf(BytesRef wkb, int precision) { + return StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(wkb), precision); + } + + @Override + protected Expression build(Source source, List args) { + Expression bounds = args.size() > 2 ? args.get(2) : null; + return new StGeohex(source, args.get(0), args.get(1), bounds); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java new file mode 100644 index 0000000000000..5305eed10941b --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.h3.H3; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.FunctionName; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +@FunctionName("st_geohex_to_geoshape") +public class StGeohexToGeoShapeTests extends SpatialGridTypeConversionTestCases { + public StGeohexToGeoShapeTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + forUnaryGeoPoint( + DataType.LONG, + suppliers, + "StGeohexToGeoShapeFromLongEvaluator[gridId=Attribute[channel=0]]", + GEO_SHAPE, + g -> StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(g), 2), + StGeohexToGeoShapeTests::valueOf + ); + forUnaryGeoPoint( + DataType.KEYWORD, + suppliers, + "StGeohexToGeoShapeFromStringEvaluator[gridId=Attribute[channel=0]]", + GEO_SHAPE, + g -> new BytesRef(H3.h3ToString(StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(g), 2))), + StGeohexToGeoShapeTests::valueOf + ); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static BytesRef valueOf(Object gridid) { + return (gridid instanceof Long hex) ? StGeohexToGeoShape.fromLong(hex) : StGeohexToGeoShape.fromString((BytesRef) gridid); + } + + @Override + protected Expression build(Source source, List args) { + return new StGeohexToGeoShape(source, args.get(0)); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java new file mode 100644 index 0000000000000..356af77d56fa3 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.h3.H3; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.FunctionName; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +@FunctionName("st_geohex_to_long") +public class StGeohexToLongTests extends SpatialGridTypeConversionTestCases { + public StGeohexToLongTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + forUnaryGeoPoint( + DataType.LONG, + suppliers, + "Attribute[channel=0]", + DataType.LONG, + g -> StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(g), 2), + StGeohexToLongTests::valueOf + ); + forUnaryGeoPoint( + DataType.KEYWORD, + suppliers, + "StGeohexToLongFromStringEvaluator[gridId=Attribute[channel=0]]", + DataType.LONG, + g -> new BytesRef(H3.h3ToString(StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(g), 2))), + StGeohexToLongTests::valueOf + ); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static long valueOf(Object gridid) { + return (gridid instanceof Long hash) ? hash : H3.stringToH3(((BytesRef) gridid).utf8ToString()); + } + + @Override + protected Expression build(Source source, List args) { + return new StGeohexToLong(source, args.get(0)); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringTests.java new file mode 100644 index 0000000000000..826a7f9349895 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringTests.java @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.h3.H3; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.FunctionName; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +@FunctionName("st_geohex_to_string") +public class StGeohexToStringTests extends SpatialGridTypeConversionTestCases { + public StGeohexToStringTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + forUnaryGeoPoint( + DataType.LONG, + suppliers, + "StGeohexToStringFromLongEvaluator[gridId=Attribute[channel=0]]", + KEYWORD, + g -> StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(g), 2), + StGeohexToStringTests::valueOf + ); + forUnaryGeoPoint( + DataType.KEYWORD, + suppliers, + "Attribute[channel=0]", + KEYWORD, + g -> new BytesRef(H3.h3ToString(StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(g), 2))), + StGeohexToStringTests::valueOf + ); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static BytesRef valueOf(Object gridid) { + return (gridid instanceof Long hash) ? new BytesRef(H3.h3ToString(hash)) : (BytesRef) gridid; + } + + @Override + protected Expression build(Source source, List args) { + return new StGeohexToString(source, args.get(0)); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileTests.java new file mode 100644 index 0000000000000..a4f3c1844c1a5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileTests.java @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +public class StGeotileTests extends SpatialGridFunctionTestCase { + public StGeotileTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + addTestCaseSuppliers(suppliers, new DataType[] { DataType.GEO_POINT }, StGeotileTests::valueOf); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static long valueOf(BytesRef wkb, int precision) { + return StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(wkb), precision); + } + + @Override + protected Expression build(Source source, List args) { + Expression bounds = args.size() > 2 ? args.get(2) : null; + return new StGeotile(source, args.get(0), args.get(1), bounds); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java new file mode 100644 index 0000000000000..1f82c0a6c5e6d --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.FunctionName; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +@FunctionName("st_geotile_to_geoshape") +public class StGeotileToGeoShapeTests extends SpatialGridTypeConversionTestCases { + public StGeotileToGeoShapeTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + forUnaryGeoPoint( + DataType.LONG, + suppliers, + "StGeotileToGeoShapeFromLongEvaluator[gridId=Attribute[channel=0]]", + GEO_SHAPE, + g -> StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(g), 2), + StGeotileToGeoShapeTests::valueOf + ); + forUnaryGeoPoint( + DataType.KEYWORD, + suppliers, + "StGeotileToGeoShapeFromStringEvaluator[gridId=Attribute[channel=0]]", + GEO_SHAPE, + g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(g), 2))), + StGeotileToGeoShapeTests::valueOf + ); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static BytesRef valueOf(Object gridid) { + return (gridid instanceof Long hash) ? StGeotileToGeoShape.fromLong(hash) : StGeotileToGeoShape.fromString((BytesRef) gridid); + } + + @Override + protected Expression build(Source source, List args) { + return new StGeotileToGeoShape(source, args.get(0)); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongTests.java new file mode 100644 index 0000000000000..7e62effd9434e --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongTests.java @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.FunctionName; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +@FunctionName("st_geotile_to_long") +public class StGeotileToLongTests extends SpatialGridTypeConversionTestCases { + public StGeotileToLongTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + forUnaryGeoPoint( + DataType.LONG, + suppliers, + "Attribute[channel=0]", + DataType.LONG, + g -> StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(g), 2), + StGeotileToLongTests::valueOf + ); + forUnaryGeoPoint( + DataType.KEYWORD, + suppliers, + "StGeotileToLongFromStringEvaluator[gridId=Attribute[channel=0]]", + DataType.LONG, + g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(g), 2))), + StGeotileToLongTests::valueOf + ); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static long valueOf(Object gridid) { + return (gridid instanceof Long hash) ? hash : GeoTileUtils.longEncode(((BytesRef) gridid).utf8ToString()); + } + + @Override + protected Expression build(Source source, List args) { + return new StGeotileToLong(source, args.get(0)); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringTests.java new file mode 100644 index 0000000000000..e644f62abae89 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringTests.java @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.FunctionName; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +@FunctionName("st_geotile_to_string") +public class StGeotileToStringTests extends SpatialGridTypeConversionTestCases { + public StGeotileToStringTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + forUnaryGeoPoint( + DataType.LONG, + suppliers, + "StGeotileToStringFromLongEvaluator[gridId=Attribute[channel=0]]", + KEYWORD, + g -> StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(g), 2), + StGeotileToStringTests::valueOf + ); + forUnaryGeoPoint( + DataType.KEYWORD, + suppliers, + "Attribute[channel=0]", + KEYWORD, + g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(g), 2))), + StGeotileToStringTests::valueOf + ); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static BytesRef valueOf(Object gridid) { + return (gridid instanceof Long hash) ? new BytesRef(GeoTileUtils.stringEncode(hash)) : (BytesRef) gridid; + } + + @Override + protected Expression build(Source source, List args) { + return new StGeotileToString(source, args.get(0)); + } +} From 983b977f05bfdf4c11e86a5538fc482616932a30 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 15 Apr 2025 19:02:02 +0200 Subject: [PATCH 13/34] Output POLYGON instead of BBOX for TO_GEOSHAPE functions --- .../src/main/resources/spatial-grid.csv-spec | 86 +++++++++---------- .../scalar/spatial/StGeohashToGeoShape.java | 9 +- .../scalar/spatial/StGeotileToGeoShape.java | 16 +++- 3 files changed, 58 insertions(+), 53 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index bc03552fc1621..1299668e84442 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -43,7 +43,7 @@ ROW geohash = "u3bu" // tag::geohash_to_geoshape-result[] geohash:keyword | boundary:geo_shape -u3bu | BBOX (12.3046875, 12.65625, 55.72265625, 55.546875) +u3bu | POLYGON((12.3046875 55.546875, 12.65625 55.546875, 12.65625 55.72265625, 12.3046875 55.72265625, 12.3046875 55.546875)) // end::geohash_to_geoshape-result[] ; @@ -55,7 +55,7 @@ ROW geohash = TO_LONG(13686180) ; geohash:long | boundary:geo_shape -13686180 | BBOX (12.3046875, 12.65625, 55.72265625, 55.546875) +13686180 | POLYGON((12.3046875 55.546875, 12.65625 55.546875, 12.65625 55.72265625, 12.3046875 55.72265625, 12.3046875 55.546875)) ; geohashLiteral @@ -117,11 +117,11 @@ ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precisio ; location:geo_point | precision:integer | geohash:keyword | cellBoundary:geo_shape -POINT (12.6493508684508 55.6285017221528) | 1 | u | BBOX (0.0, 45.0, 90.0, 45.0) -POINT (12.6493508684508 55.6285017221528) | 2 | u3 | BBOX (11.25, 22.5, 56.25, 50.625) -POINT (12.6493508684508 55.6285017221528) | 3 | u3b | BBOX (11.25, 12.65625, 56.25, 54.84375) -POINT (12.6493508684508 55.6285017221528) | 4 | u3bu | BBOX (12.3046875, 12.65625, 55.72265625, 55.546875) -POINT (12.6493508684508 55.6285017221528) | 5 | u3bur | BBOX (12.6123046875, 12.65625, 55.634765625, 55.5908203125) +POINT (12.6493508684508 55.6285017221528) | 1 | u | POLYGON((0.0 45.0, 45.0 45.0, 45.0 90.0, 0.0 90.0, 0.0 45.0)) +POINT (12.6493508684508 55.6285017221528) | 2 | u3 | POLYGON((11.25 50.625, 22.5 50.625, 22.5 56.25, 11.25 56.25, 11.25 50.625)) +POINT (12.6493508684508 55.6285017221528) | 3 | u3b | POLYGON((11.25 54.84375, 12.65625 54.84375, 12.65625 56.25, 11.25 56.25, 11.25 54.84375)) +POINT (12.6493508684508 55.6285017221528) | 4 | u3bu | POLYGON((12.3046875 55.546875, 12.65625 55.546875, 12.65625 55.72265625, 12.3046875 55.72265625, 12.3046875 55.546875)) +POINT (12.6493508684508 55.6285017221528) | 5 | u3bur | POLYGON((12.6123046875 55.5908203125, 12.65625 55.5908203125, 12.65625 55.634765625, 12.6123046875 55.634765625, 12.6123046875 55.5908203125)) ; geohashField @@ -181,7 +181,7 @@ gridGeohashStatsByBounds required_capability: spatial_grid FROM airports -| EVAL geohash = ST_GEOHASH(location, 2, TO_GEOSHAPE("BBOX(0, 12, 60, 30)")) +| EVAL geohash = ST_GEOHASH(location, 2, TO_GEOSHAPE("POLYGON((0.0 30.0, 12.0 30.0, 12.0 60.0, 0.0 60.0, 0.0 30.0))")) | WHERE geohash IS NOT NULL | STATS count = COUNT(*), @@ -194,17 +194,17 @@ FROM airports ; count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape -19 | POINT (6.360728044651057 47.94084087577894) | u0 | BBOX (0.0, 11.25, 50.625, 45.0) -10 | POINT (15.350638423115015 47.80751353036612) | u2 | BBOX (11.25, 22.5, 50.625, 45.0) -9 | POINT (18.5217544157058 42.1394603792578) | sr | BBOX (11.25, 22.5, 45.0, 39.375) -8 | POINT (6.351574736181647 51.8981519783847) | u1 | BBOX (0.0, 11.25, 56.25, 50.625) -7 | POINT (5.268637698941997 42.747250193330856) | sp | BBOX (0.0, 11.25, 45.0, 39.375) -7 | POINT (17.092350951528974 53.365471504096476) | u3 | BBOX (11.25, 22.5, 56.25, 50.625) -5 | POINT (16.2651440910995 58.812188878655434) | u6 | BBOX (11.25, 22.5, 61.875, 56.25) -4 | POINT (7.7012718468904495 36.39783004182391) | sn | BBOX (0.0, 11.25, 39.375, 33.75) -3 | POINT (14.222751930356026 37.168446206487715) | sq | BBOX (11.25, 22.5, 39.375, 33.75) -3 | POINT (7.318722177296877 59.788265260867774) | u4 | BBOX (0.0, 11.25, 61.875, 56.25) -2 | POINT (16.706149326637387 32.37822346854955) | sm | BBOX (11.25, 22.5, 33.75, 28.125) +19 | POINT (6.360728044651057 47.94084087577894) | u0 | POLYGON((0.0 45.0, 11.25 45.0, 11.25 50.625, 0.0 50.625, 0.0 45.0)) +10 | POINT (15.350638423115015 47.80751353036612) | u2 | POLYGON((11.25 45.0, 22.5 45.0, 22.5 50.625, 11.25 50.625, 11.25 45.0)) +9 | POINT (18.5217544157058 42.1394603792578) | sr | POLYGON((11.25 39.375, 22.5 39.375, 22.5 45.0, 11.25 45.0, 11.25 39.375)) +8 | POINT (6.351574736181647 51.8981519783847) | u1 | POLYGON((0.0 50.625, 11.25 50.625, 11.25 56.25, 0.0 56.25, 0.0 50.625)) +7 | POINT (5.268637698941997 42.747250193330856) | sp | POLYGON((0.0 39.375, 11.25 39.375, 11.25 45.0, 0.0 45.0, 0.0 39.375)) +7 | POINT (17.092350951528974 53.365471504096476) | u3 | POLYGON((11.25 50.625, 22.5 50.625, 22.5 56.25, 11.25 56.25, 11.25 50.625)) +5 | POINT (16.2651440910995 58.812188878655434) | u6 | POLYGON((11.25 56.25, 22.5 56.25, 22.5 61.875, 11.25 61.875, 11.25 56.25)) +4 | POINT (7.7012718468904495 36.39783004182391) | sn | POLYGON((0.0 33.75, 11.25 33.75, 11.25 39.375, 0.0 39.375, 0.0 33.75)) +3 | POINT (14.222751930356026 37.168446206487715) | sq | POLYGON((11.25 33.75, 22.5 33.75, 22.5 39.375, 11.25 39.375, 11.25 33.75)) +3 | POINT (7.318722177296877 59.788265260867774) | u4 | POLYGON((0.0 56.25, 11.25 56.25, 11.25 61.875, 0.0 61.875, 0.0 56.25)) +2 | POINT (16.706149326637387 32.37822346854955) | sm | POLYGON((11.25 28.125, 22.5 28.125, 22.5 33.75, 11.25 33.75, 11.25 28.125)) ; gridGeohashStatsByWhereUK @@ -224,8 +224,8 @@ FROM airports ; count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape -14 | POINT (-2.5644131543646966 53.38093495994274) | gc | BBOX (-11.25, 0.0, 56.25, 50.625) -3 | POINT (-2.7510103583335876 58.79020635969937) | gf | BBOX (-11.25, 0.0, 61.875, 56.25) +14 | POINT (-2.5644131543646966 53.38093495994274) | gc | POLYGON((-11.25 50.625, 0.0 50.625, 0.0 56.25, -11.25 56.25, -11.25 50.625)) +3 | POINT (-2.7510103583335876 58.79020635969937) | gf | POLYGON((-11.25 56.25, 0.0 56.25, 0.0 61.875, -11.25 61.875, -11.25 56.25)) ; gridGeohashStatsByBoundsUK @@ -246,11 +246,11 @@ FROM airports ; count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape -19 | POINT (6.360728044651057 47.94084087577894) | u0 | BBOX (0.0, 11.25, 50.625, 45.0) -17 | POINT (-3.5034258844440473 53.25306422789307) | gc | BBOX (-11.25, 0.0, 56.25, 50.625) -8 | POINT (6.351574736181647 51.8981519783847) | u1 | BBOX (0.0, 11.25, 56.25, 50.625) -3 | POINT (7.318722177296877 59.788265260867774) | u4 | BBOX (0.0, 11.25, 61.875, 56.25) -3 | POINT (-2.7510103583335876 58.79020635969937) | gf | BBOX (-11.25, 0.0, 61.875, 56.25) +19 | POINT (6.360728044651057 47.94084087577894) | u0 | POLYGON((0.0 45.0, 11.25 45.0, 11.25 50.625, 0.0 50.625, 0.0 45.0)) +17 | POINT (-3.5034258844440473 53.25306422789307) | gc | POLYGON((-11.25 50.625, 0.0 50.625, 0.0 56.25, -11.25 56.25, -11.25 50.625)) +8 | POINT (6.351574736181647 51.8981519783847) | u1 | POLYGON((0.0 50.625, 11.25 50.625, 11.25 56.25, 0.0 56.25, 0.0 50.625)) +3 | POINT (7.318722177296877 59.788265260867774) | u4 | POLYGON((0.0 56.25, 11.25 56.25, 11.25 61.875, 0.0 61.875, 0.0 56.25)) +3 | POINT (-2.7510103583335876 58.79020635969937) | gf | POLYGON((-11.25 56.25, 0.0 56.25, 0.0 61.875, -11.25 61.875, -11.25 56.25)) ; gridGeohashInStatsBy @@ -342,7 +342,7 @@ ROW geotile = "4/8/5" // tag::geotile_to_geoshape-result[] geotile:keyword | boundary:geo_shape -4/8/5 | BBOX (0.0, 22.5, 55.77657301866769, 40.979898069620134) +4/8/5 | POLYGON((0.0 40.979898069620134, 22.5 40.979898069620134, 22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 40.979898069620134)) // end::geotile_to_geoshape-result[] ; @@ -405,11 +405,11 @@ ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precisio ; location:geo_point | precision:integer | geotile:keyword | cellBoundary:geo_shape -POINT (12.6493508684508 55.6285017221528) | 1 | 1/1/0 | BBOX (0.0, 180.0, 85.0511287798066, 0.0) -POINT (12.6493508684508 55.6285017221528) | 2 | 2/2/1 | BBOX (0.0, 90.0, 66.51326044311186, 0.0) -POINT (12.6493508684508 55.6285017221528) | 3 | 3/4/2 | BBOX (0.0, 45.0, 66.51326044311186, 40.979898069620134) -POINT (12.6493508684508 55.6285017221528) | 4 | 4/8/5 | BBOX (0.0, 22.5, 55.77657301866769, 40.979898069620134) -POINT (12.6493508684508 55.6285017221528) | 5 | 5/17/10 | BBOX (11.25, 22.5, 55.77657301866769, 48.922499263758255) +POINT (12.6493508684508 55.6285017221528) | 1 | 1/1/0 | POLYGON((0.0 0.0, 180.0 0.0, 180.0 85.0511287798066, 0.0 85.0511287798066, 0.0 0.0)) +POINT (12.6493508684508 55.6285017221528) | 2 | 2/2/1 | POLYGON((0.0 0.0, 90.0 0.0, 90.0 66.51326044311186, 0.0 66.51326044311186, 0.0 0.0)) +POINT (12.6493508684508 55.6285017221528) | 3 | 3/4/2 | POLYGON((0.0 40.979898069620134, 45.0 40.979898069620134, 45.0 66.51326044311186, 0.0 66.51326044311186, 0.0 40.979898069620134)) +POINT (12.6493508684508 55.6285017221528) | 4 | 4/8/5 | POLYGON((0.0 40.979898069620134, 22.5 40.979898069620134, 22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 40.979898069620134)) +POINT (12.6493508684508 55.6285017221528) | 5 | 5/17/10 | POLYGON((11.25 48.922499263758255, 22.5 48.922499263758255, 22.5 55.77657301866769, 11.25 55.77657301866769, 11.25 48.922499263758255)) ; geotileField @@ -462,7 +462,7 @@ gridGeotileStatsByBounds required_capability: spatial_grid FROM airports -| EVAL geotile = ST_GEOTILE(location, 3, TO_GEOSHAPE("BBOX(0, 12, 60, 30)")) +| EVAL geotile = ST_GEOTILE(location, 3, TO_GEOSHAPE("POLYGON((0.0 30.0, 12.0 30.0, 12.0 60.0, 0.0 60.0, 0.0 30.0))")) | WHERE geotile IS NOT NULL | STATS count = COUNT(*), @@ -475,8 +475,8 @@ FROM airports ; count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape -100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 | BBOX (0.0, 45.0, 66.51326044311186, 40.979898069620134) -79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 | BBOX (0.0, 45.0, 40.979898069620134, 0.0) +100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 | POLYGON((0.0 40.979898069620134, 45.0 40.979898069620134, 45.0 66.51326044311186, 0.0 66.51326044311186, 0.0 40.979898069620134)) +79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 | POLYGON((0.0 0.0, 45.0 0.0, 45.0 40.979898069620134, 0.0 40.979898069620134, 0.0 0.0)) ; gridGeotileStatsByWhereUK @@ -496,8 +496,8 @@ FROM airports ; count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape -12 | POINT (-2.342151787597686 52.9600293841213) | 4/7/5 | BBOX (-22.5, 0.0, 55.77657301866769, 40.979898069620134) -5 | POINT (-3.2097987569868565 57.63667118176818) | 4/7/4 | BBOX (-22.5, 0.0, 66.51326044311186, 55.77657301866769) +12 | POINT (-2.342151787597686 52.9600293841213) | 4/7/5 | POLYGON((-22.5 40.979898069620134, 0.0 40.979898069620134, 0.0 55.77657301866769, -22.5 55.77657301866769, -22.5 40.979898069620134)) +5 | POINT (-3.2097987569868565 57.63667118176818) | 4/7/4 | POLYGON((-22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 66.51326044311186, -22.5 66.51326044311186, -22.5 55.77657301866769)) ; gridGeotileStatsByBoundsUK @@ -518,10 +518,10 @@ FROM airports ; count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape -56 | POINT (10.54233039047436 47.85997457644304) | 4/8/5 | BBOX (0.0, 22.5, 55.77657301866769, 40.979898069620134) -18 | POINT (-3.5578574100509286 51.27018998377025) | 4/7/5 | BBOX (-22.5, 0.0, 55.77657301866769, 40.979898069620134) -11 | POINT (14.310833624648778 59.85619530801407) | 4/8/4 | BBOX (0.0, 22.5, 66.51326044311186, 55.77657301866769) -7 | POINT (-6.466632609122565 59.19681839378817) | 4/7/4 | BBOX (-22.5, 0.0, 66.51326044311186, 55.77657301866769) +56 | POINT (10.54233039047436 47.85997457644304) | 4/8/5 | POLYGON((0.0 40.979898069620134, 22.5 40.979898069620134, 22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 40.979898069620134)) +18 | POINT (-3.5578574100509286 51.27018998377025) | 4/7/5 | POLYGON((-22.5 40.979898069620134, 0.0 40.979898069620134, 0.0 55.77657301866769, -22.5 55.77657301866769, -22.5 40.979898069620134)) +11 | POINT (14.310833624648778 59.85619530801407) | 4/8/4 | POLYGON((0.0 55.77657301866769, 22.5 55.77657301866769, 22.5 66.51326044311186, 0.0 66.51326044311186, 0.0 55.77657301866769)) +7 | POINT (-6.466632609122565 59.19681839378817) | 4/7/4 | POLYGON((-22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 66.51326044311186, -22.5 66.51326044311186, -22.5 55.77657301866769)) ; gridGeotileInStatsBy @@ -727,7 +727,7 @@ gridGeohexStatsByBounds required_capability: spatial_grid FROM airports -| EVAL geohex = ST_GEOHEX(location, 1, TO_GEOSHAPE("BBOX(0, 12, 60, 30)")) +| EVAL geohex = ST_GEOHEX(location, 1, TO_GEOSHAPE("POLYGON((0.0 30.0, 12.0 30.0, 12.0 60.0, 0.0 60.0, 0.0 30.0))")) | WHERE geohex IS NOT NULL | STATS count = COUNT(*), @@ -817,7 +817,7 @@ FROM airports | STATS count = COUNT(location), centroid = ST_CENTROID_AGG(location) - BY ST_GEOHEX(location, 2, TO_GEOSHAPE("BBOX(0, 12, 60, 30)")) + BY ST_GEOHEX(location, 2, TO_GEOSHAPE("POLYGON((0.0 30.0, 12.0 30.0, 12.0 60.0, 0.0 60.0, 0.0 30.0))")) | WHERE count > 3 | SORT count DESC | KEEP count, centroid diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java index 55065b8619451..86487168bdfe7 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java @@ -11,13 +11,11 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; -import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.geometry.utils.Geohash; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes; import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; import org.elasticsearch.xpack.esql.expression.function.Example; import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; @@ -31,6 +29,7 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; +import static org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToGeoShape.fromRectangle; public class StGeohashToGeoShape extends AbstractConvertFunction implements EvaluatorMapper { public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( @@ -93,13 +92,11 @@ protected NodeInfo info() { @ConvertEvaluator(extraName = "FromString") static BytesRef fromString(BytesRef gridId) { - Rectangle bbox = Geohash.toBoundingBox(gridId.utf8ToString()); - return SpatialCoordinateTypes.GEO.asWkb(bbox); + return fromRectangle(Geohash.toBoundingBox(gridId.utf8ToString())); } @ConvertEvaluator(extraName = "FromLong") static BytesRef fromLong(long gridId) { - Rectangle bbox = Geohash.toBoundingBox(Geohash.stringEncode(gridId)); - return SpatialCoordinateTypes.GEO.asWkb(bbox); + return fromRectangle(Geohash.toBoundingBox(Geohash.stringEncode(gridId))); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java index 55818a6f260e3..65f2f0395bd2a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java @@ -11,6 +11,8 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.geometry.LinearRing; +import org.elasticsearch.geometry.Polygon; import org.elasticsearch.geometry.Rectangle; import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -93,13 +95,19 @@ protected NodeInfo info() { @ConvertEvaluator(extraName = "FromString") static BytesRef fromString(BytesRef gridId) { - Rectangle bbox = GeoTileUtils.toBoundingBox(gridId.utf8ToString()); - return SpatialCoordinateTypes.GEO.asWkb(bbox); + return fromRectangle(GeoTileUtils.toBoundingBox(gridId.utf8ToString())); } @ConvertEvaluator(extraName = "FromLong") static BytesRef fromLong(long gridId) { - Rectangle bbox = GeoTileUtils.toBoundingBox(gridId); - return SpatialCoordinateTypes.GEO.asWkb(bbox); + return fromRectangle(GeoTileUtils.toBoundingBox(gridId)); + } + + static BytesRef fromRectangle(Rectangle bbox) { + double[] x = new double[] { bbox.getMinX(), bbox.getMaxX(), bbox.getMaxX(), bbox.getMinX(), bbox.getMinX() }; + double[] y = new double[] { bbox.getMinY(), bbox.getMinY(), bbox.getMaxY(), bbox.getMaxY(), bbox.getMinY() }; + LinearRing ring = new LinearRing(x, y); + Polygon polygon = new Polygon(ring); + return SpatialCoordinateTypes.GEO.asWkb(polygon); } } From 0debf2e7ea74aa2c278f6dad43693aaa04a41f2b Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 15 Apr 2025 19:04:26 +0200 Subject: [PATCH 14/34] Make test less flaky --- .../qa/testFixtures/src/main/resources/spatial-grid.csv-spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index 1299668e84442..86e6ee8b14681 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -242,15 +242,15 @@ FROM airports | EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) | EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) | KEEP count, centroid, geohashString, cellBoundary -| SORT count DESC +| SORT count DESC, geohashString ASC ; count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape 19 | POINT (6.360728044651057 47.94084087577894) | u0 | POLYGON((0.0 45.0, 11.25 45.0, 11.25 50.625, 0.0 50.625, 0.0 45.0)) 17 | POINT (-3.5034258844440473 53.25306422789307) | gc | POLYGON((-11.25 50.625, 0.0 50.625, 0.0 56.25, -11.25 56.25, -11.25 50.625)) 8 | POINT (6.351574736181647 51.8981519783847) | u1 | POLYGON((0.0 50.625, 11.25 50.625, 11.25 56.25, 0.0 56.25, 0.0 50.625)) -3 | POINT (7.318722177296877 59.788265260867774) | u4 | POLYGON((0.0 56.25, 11.25 56.25, 11.25 61.875, 0.0 61.875, 0.0 56.25)) 3 | POINT (-2.7510103583335876 58.79020635969937) | gf | POLYGON((-11.25 56.25, 0.0 56.25, 0.0 61.875, -11.25 61.875, -11.25 56.25)) +3 | POINT (7.318722177296877 59.788265260867774) | u4 | POLYGON((0.0 56.25, 11.25 56.25, 11.25 61.875, 0.0 61.875, 0.0 56.25)) ; gridGeohashInStatsBy From a0c1e095cacbdc4a5e5f14e3ef62f28fc9b4f6e3 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Wed, 16 Apr 2025 12:36:45 +0200 Subject: [PATCH 15/34] Use wrapper classes on the bounded predicates to simplify and reduce duplicated code. --- .../examples/st_geohash_to_geoshape.md | 2 +- .../examples/st_geotile_to_geoshape.md | 2 +- .../geogrid/GeoHashBoundedPredicate.java | 6 - .../geogrid/GeoTileBoundedPredicate.java | 4 - ...romFieldAndLiteralAndLiteralEvaluator.java | 9 +- ...ocValuesAndLiteralAndLiteralEvaluator.java | 9 +- ...romFieldAndLiteralAndLiteralEvaluator.java | 8 +- ...ocValuesAndLiteralAndLiteralEvaluator.java | 8 +- ...romFieldAndLiteralAndLiteralEvaluator.java | 9 +- ...ocValuesAndLiteralAndLiteralEvaluator.java | 9 +- .../spatial/GeoHexBoundedPredicate.java | 8 +- .../scalar/spatial/SpatialGridFunction.java | 117 ++++++++++++ .../function/scalar/spatial/StGeohash.java | 169 +++++------------ .../function/scalar/spatial/StGeohex.java | 177 ++++++----------- .../function/scalar/spatial/StGeotile.java | 179 ++++++------------ .../scalar/spatial/StGeohashTests.java | 3 +- .../spatial/StGeohashToGeoShapeTests.java | 5 +- .../scalar/spatial/StGeohashToLongTests.java | 4 +- .../spatial/StGeohashToStringTests.java | 5 +- .../scalar/spatial/StGeohexTests.java | 2 +- .../spatial/StGeohexToGeoShapeTests.java | 4 +- .../scalar/spatial/StGeohexToLongTests.java | 5 +- .../scalar/spatial/StGeohexToStringTests.java | 4 +- .../scalar/spatial/StGeotileTests.java | 2 +- .../spatial/StGeotileToGeoShapeTests.java | 4 +- .../scalar/spatial/StGeotileToLongTests.java | 4 +- .../spatial/StGeotileToStringTests.java | 4 +- 27 files changed, 331 insertions(+), 431 deletions(-) diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_geoshape.md index ed97120c270e3..4990583a2f8c6 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_geoshape.md +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_geoshape.md @@ -9,6 +9,6 @@ ROW geohash = "u3bu" | geohash:keyword | boundary:geo_shape | | --- | --- | -| u3bu | BBOX (12.3046875, 12.65625, 55.72265625, 55.546875) | +| u3bu | POLYGON((12.3046875 55.546875, 12.65625 55.546875, 12.65625 55.72265625, 12.3046875 55.72265625, 12.3046875 55.546875)) | diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_geoshape.md index 563f48797bd33..9f0331fe632b8 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_geoshape.md +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_geoshape.md @@ -9,6 +9,6 @@ ROW geotile = "4/8/5" | geotile:keyword | boundary:geo_shape | | --- | --- | -| 4/8/5 | BBOX (0.0, 22.5, 55.77657301866769, 40.979898069620134) | +| 4/8/5 | POLYGON((0.0 40.979898069620134, 22.5 40.979898069620134, 22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 40.979898069620134)) | diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoHashBoundedPredicate.java b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoHashBoundedPredicate.java index 42d1e7721db9b..7496697eb1161 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoHashBoundedPredicate.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoHashBoundedPredicate.java @@ -18,13 +18,11 @@ */ public class GeoHashBoundedPredicate { - private final int precision; private final boolean crossesDateline; private final long maxHashes; private final GeoBoundingBox bbox; public GeoHashBoundedPredicate(int precision, GeoBoundingBox bbox) { - this.precision = precision; this.crossesDateline = bbox.right() < bbox.left(); this.bbox = bbox; final long hashesY = (long) Math.ceil(((bbox.top() - bbox.bottom()) / Geohash.latHeightInDegrees(precision)) + 1); @@ -71,8 +69,4 @@ private boolean intersects(double minX, double maxX, double minY, double maxY) { public long getMaxHashes() { return maxHashes; } - - public int precision() { - return precision; - } } diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoTileBoundedPredicate.java b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoTileBoundedPredicate.java index 468d6b2401f6f..cc250b887b1bb 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoTileBoundedPredicate.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/geogrid/GeoTileBoundedPredicate.java @@ -56,10 +56,6 @@ public GeoTileBoundedPredicate(int precision, GeoBoundingBox bbox) { } } - public int precision() { - return precision; - } - /** Does the provided bounds crosses the dateline */ public boolean crossesDateline() { return crossesDateline; diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java index 811d39e8cb36f..2e4b8e7d538d8 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldAndLiteralAndLiteralEvaluator.java @@ -15,7 +15,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.search.aggregations.bucket.geogrid.GeoHashBoundedPredicate; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -27,14 +26,14 @@ public final class StGeohashFromFieldAndLiteralAndLiteralEvaluator implements Ev private final EvalOperator.ExpressionEvaluator in; - private final GeoHashBoundedPredicate bounds; + private final StGeohash.GeoHashBoundedGrid bounds; private final DriverContext driverContext; private Warnings warnings; public StGeohashFromFieldAndLiteralAndLiteralEvaluator(Source source, - EvalOperator.ExpressionEvaluator in, GeoHashBoundedPredicate bounds, + EvalOperator.ExpressionEvaluator in, StGeohash.GeoHashBoundedGrid bounds, DriverContext driverContext) { this.source = source; this.in = in; @@ -98,10 +97,10 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory in; - private final GeoHashBoundedPredicate bounds; + private final StGeohash.GeoHashBoundedGrid bounds; public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, - GeoHashBoundedPredicate bounds) { + StGeohash.GeoHashBoundedGrid bounds) { this.source = source; this.in = in; this.bounds = bounds; diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java index e740f0948ba22..862b2b90c9b2d 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.java @@ -14,7 +14,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.search.aggregations.bucket.geogrid.GeoHashBoundedPredicate; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -26,14 +25,14 @@ public final class StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator impl private final EvalOperator.ExpressionEvaluator encoded; - private final GeoHashBoundedPredicate bounds; + private final StGeohash.GeoHashBoundedGrid bounds; private final DriverContext driverContext; private Warnings warnings; public StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator(Source source, - EvalOperator.ExpressionEvaluator encoded, GeoHashBoundedPredicate bounds, + EvalOperator.ExpressionEvaluator encoded, StGeohash.GeoHashBoundedGrid bounds, DriverContext driverContext) { this.source = source; this.encoded = encoded; @@ -97,10 +96,10 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory encoded; - private final GeoHashBoundedPredicate bounds; + private final StGeohash.GeoHashBoundedGrid bounds; public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, - GeoHashBoundedPredicate bounds) { + StGeohash.GeoHashBoundedGrid bounds) { this.source = source; this.encoded = encoded; this.bounds = bounds; diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java index e5b9799d3856f..24e070c46adda 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldAndLiteralAndLiteralEvaluator.java @@ -26,14 +26,14 @@ public final class StGeohexFromFieldAndLiteralAndLiteralEvaluator implements Eva private final EvalOperator.ExpressionEvaluator in; - private final GeoHexBoundedPredicate bounds; + private final StGeohex.GeoHexBoundedGrid bounds; private final DriverContext driverContext; private Warnings warnings; public StGeohexFromFieldAndLiteralAndLiteralEvaluator(Source source, - EvalOperator.ExpressionEvaluator in, GeoHexBoundedPredicate bounds, + EvalOperator.ExpressionEvaluator in, StGeohex.GeoHexBoundedGrid bounds, DriverContext driverContext) { this.source = source; this.in = in; @@ -97,10 +97,10 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory in; - private final GeoHexBoundedPredicate bounds; + private final StGeohex.GeoHexBoundedGrid bounds; public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, - GeoHexBoundedPredicate bounds) { + StGeohex.GeoHexBoundedGrid bounds) { this.source = source; this.in = in; this.bounds = bounds; diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java index 6f95dfae7ab91..0ac32cbdbedad 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.java @@ -25,14 +25,14 @@ public final class StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator imple private final EvalOperator.ExpressionEvaluator encoded; - private final GeoHexBoundedPredicate bounds; + private final StGeohex.GeoHexBoundedGrid bounds; private final DriverContext driverContext; private Warnings warnings; public StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator(Source source, - EvalOperator.ExpressionEvaluator encoded, GeoHexBoundedPredicate bounds, + EvalOperator.ExpressionEvaluator encoded, StGeohex.GeoHexBoundedGrid bounds, DriverContext driverContext) { this.source = source; this.encoded = encoded; @@ -96,10 +96,10 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory encoded; - private final GeoHexBoundedPredicate bounds; + private final StGeohex.GeoHexBoundedGrid bounds; public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, - GeoHexBoundedPredicate bounds) { + StGeohex.GeoHexBoundedGrid bounds) { this.source = source; this.encoded = encoded; this.bounds = bounds; diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java index 16e36a4717665..13a8da4ad0c9c 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldAndLiteralAndLiteralEvaluator.java @@ -15,7 +15,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileBoundedPredicate; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -27,14 +26,14 @@ public final class StGeotileFromFieldAndLiteralAndLiteralEvaluator implements Ev private final EvalOperator.ExpressionEvaluator in; - private final GeoTileBoundedPredicate bounds; + private final StGeotile.GeoTileBoundedGrid bounds; private final DriverContext driverContext; private Warnings warnings; public StGeotileFromFieldAndLiteralAndLiteralEvaluator(Source source, - EvalOperator.ExpressionEvaluator in, GeoTileBoundedPredicate bounds, + EvalOperator.ExpressionEvaluator in, StGeotile.GeoTileBoundedGrid bounds, DriverContext driverContext) { this.source = source; this.in = in; @@ -98,10 +97,10 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory in; - private final GeoTileBoundedPredicate bounds; + private final StGeotile.GeoTileBoundedGrid bounds; public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, - GeoTileBoundedPredicate bounds) { + StGeotile.GeoTileBoundedGrid bounds) { this.source = source; this.in = in; this.bounds = bounds; diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java index 2dbc49dd3777f..c6dc1d23b9f3d 100644 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.java @@ -14,7 +14,6 @@ import org.elasticsearch.compute.operator.EvalOperator; import org.elasticsearch.compute.operator.Warnings; import org.elasticsearch.core.Releasables; -import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileBoundedPredicate; import org.elasticsearch.xpack.esql.core.tree.Source; /** @@ -26,14 +25,14 @@ public final class StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator impl private final EvalOperator.ExpressionEvaluator encoded; - private final GeoTileBoundedPredicate bounds; + private final StGeotile.GeoTileBoundedGrid bounds; private final DriverContext driverContext; private Warnings warnings; public StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator(Source source, - EvalOperator.ExpressionEvaluator encoded, GeoTileBoundedPredicate bounds, + EvalOperator.ExpressionEvaluator encoded, StGeotile.GeoTileBoundedGrid bounds, DriverContext driverContext) { this.source = source; this.encoded = encoded; @@ -97,10 +96,10 @@ static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final EvalOperator.ExpressionEvaluator.Factory encoded; - private final GeoTileBoundedPredicate bounds; + private final StGeotile.GeoTileBoundedGrid bounds; public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encoded, - GeoTileBoundedPredicate bounds) { + StGeotile.GeoTileBoundedGrid bounds) { this.source = source; this.encoded = encoded; this.bounds = bounds; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/GeoHexBoundedPredicate.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/GeoHexBoundedPredicate.java index a94a83d7a2260..500a218e956f9 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/GeoHexBoundedPredicate.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/GeoHexBoundedPredicate.java @@ -16,12 +16,10 @@ */ public class GeoHexBoundedPredicate { - private final int precision; private final boolean crossesDateline; private final GeoBoundingBox bbox, scratch; - GeoHexBoundedPredicate(int precision, GeoBoundingBox bbox) { - this.precision = precision; + GeoHexBoundedPredicate(GeoBoundingBox bbox) { this.crossesDateline = bbox.right() < bbox.left(); this.bbox = bbox; scratch = new GeoBoundingBox(new org.elasticsearch.common.geo.GeoPoint(), new org.elasticsearch.common.geo.GeoPoint()); @@ -46,8 +44,4 @@ private boolean intersects(double minLon, double maxLon) { return bbox.left() < maxLon && bbox.right() > minLon; } } - - public int precision() { - return precision; - } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java index 5399843c09771..8df26af135d12 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java @@ -12,6 +12,7 @@ import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.compute.data.BytesRefBlock; import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.geometry.Point; import org.elasticsearch.geometry.Rectangle; @@ -23,6 +24,7 @@ import org.elasticsearch.xpack.esql.expression.function.OptionalArgument; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -215,4 +217,119 @@ protected static void addGrids(LongBlock.Builder results, List gridIds) { } } + protected interface UnboundedGrid { + long calculateGridId(Point point, int precision); + } + + protected interface BoundedGrid { + long calculateGridId(Point point); + + int precision(); + } + + protected static void fromWKB( + LongBlock.Builder results, + int position, + BytesRefBlock wkbBlock, + int precision, + UnboundedGrid unboundedGrid + ) { + int valueCount = wkbBlock.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final BytesRef scratch = new BytesRef(); + final int firstValueIndex = wkbBlock.getFirstValueIndex(position); + if (valueCount == 1) { + results.appendLong( + unboundedGrid.calculateGridId(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision) + ); + } else { + results.beginPositionEntry(); + for (int i = 0; i < valueCount; i++) { + results.appendLong( + unboundedGrid.calculateGridId(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision) + ); + } + results.endPositionEntry(); + } + } + } + + protected static void fromEncodedLong( + LongBlock.Builder results, + int position, + LongBlock encoded, + int precision, + UnboundedGrid unboundedGrid + ) { + int valueCount = encoded.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final int firstValueIndex = encoded.getFirstValueIndex(position); + if (valueCount == 1) { + results.appendLong(unboundedGrid.calculateGridId(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision)); + } else { + results.beginPositionEntry(); + for (int i = 0; i < valueCount; i++) { + results.appendLong(unboundedGrid.calculateGridId(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision)); + } + results.endPositionEntry(); + } + } + } + + protected static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, BoundedGrid bounds) { + int valueCount = wkbBlock.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final BytesRef scratch = new BytesRef(); + final int firstValueIndex = wkbBlock.getFirstValueIndex(position); + if (valueCount == 1) { + long grid = bounds.calculateGridId(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch))); + if (grid < 0) { + results.appendNull(); + } else { + results.appendLong(grid); + } + } else { + var gridIds = new ArrayList(valueCount); + for (int i = 0; i < valueCount; i++) { + var grid = bounds.calculateGridId(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch))); + if (grid >= 0) { + gridIds.add(grid); + } + } + addGrids(results, gridIds); + } + } + } + + protected static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, BoundedGrid bounds) { + int valueCount = encoded.getValueCount(position); + if (valueCount < 1) { + results.appendNull(); + } else { + final int firstValueIndex = encoded.getFirstValueIndex(position); + if (valueCount == 1) { + long grid = bounds.calculateGridId(GEO.longAsPoint(encoded.getLong(firstValueIndex))); + if (grid < 0) { + results.appendNull(); + } else { + results.appendLong(grid); + } + } else { + var gridIds = new ArrayList(valueCount); + for (int i = 0; i < valueCount; i++) { + var grid = bounds.calculateGridId(GEO.longAsPoint(encoded.getLong(firstValueIndex + i))); + if (grid >= 0) { + gridIds.add(grid); + } + } + addGrids(results, gridIds); + } + } + } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java index 93a4b2ed45d28..cff0aafc4daff 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java @@ -30,7 +30,6 @@ import org.elasticsearch.xpack.esql.expression.function.Param; import java.io.IOException; -import java.util.ArrayList; import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; @@ -45,6 +44,40 @@ public class StGeohash extends SpatialGridFunction implements EvaluatorMapper { StGeohash::new ); + /** + * When checking grid cells with bounds, we need to check if the cell is valid (intersects with the bounds). + * This uses GeoHashBoundedPredicate to check if the grid cell is valid. + */ + protected static class GeoHashBoundedGrid implements BoundedGrid { + private final GeoHashBoundedPredicate bounds; + private final int precision; + + public GeoHashBoundedGrid(int precision, GeoBoundingBox bbox) { + this.bounds = new GeoHashBoundedPredicate(precision, bbox); + this.precision = precision; + } + + public long calculateGridId(Point point) { + String geohash = Geohash.stringEncode(point.getX(), point.getY(), precision); + if (bounds.validHash(geohash)) { + return Geohash.longEncode(geohash); + } + // TODO: Are negative values allowed in geohash long encoding? + return -1; + } + + @Override + public int precision() { + return precision; + } + } + + /** + * For unbounded grids, we don't need to check if the grid cell is valid, + * just calculate the encoded long intersecting the point at that precision. + */ + protected static final UnboundedGrid unboundedGrid = (point, precision) -> Geohash.longEncode(point.getX(), point.getY(), precision); + @FunctionInfo(returnType = "long", description = """ Calculates the `geohash` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHASH_TO_STRING](#esql-st_geohash_to_string) to convert the result to a string. @@ -121,7 +154,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua } else if (parameter().foldable()) { // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() int precision = (int) parameter.fold(toEvaluator.foldCtx()); - GeoHashBoundedPredicate bounds = new GeoHashBoundedPredicate(precision, bbox); + GeoHashBoundedGrid bounds = new GeoHashBoundedGrid(precision, bbox); return spatialDocsValues ? new StGeohashFromFieldDocValuesAndLiteralAndLiteralEvaluator.Factory( source(), @@ -177,41 +210,40 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua public Object fold(FoldContext ctx) { var point = (BytesRef) spatialField().fold(ctx); int precision = (int) parameter().fold(ctx); - // TODO: Use GeoHashBoundedPredicate - return calculateGeohash(GEO.wkbAsPoint(point), precision); + if (bounds() == null) { + return fromLiteralAndField(point, precision); + } else { + return fromLiteralAndFieldAndLiteral(point, precision, asGeoBoundingBox((BytesRef) bounds().fold(ctx))); + } } @Evaluator(extraName = "FromFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock wkbBlock, @Fixed int precision) { - fromWKB(results, p, wkbBlock, precision); + fromWKB(results, p, wkbBlock, precision, unboundedGrid); } @Evaluator(extraName = "FromFieldDocValuesAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndLiteral(LongBlock.Builder results, int p, LongBlock encoded, @Fixed int precision) { - fromEncodedLong(results, p, encoded, precision); + fromEncodedLong(results, p, encoded, precision, unboundedGrid); } @Evaluator(extraName = "FromFieldAndField", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndField(LongBlock.Builder results, int p, BytesRefBlock in, int precision) { - fromWKB(results, p, in, precision); + fromWKB(results, p, in, precision, unboundedGrid); } @Evaluator(extraName = "FromFieldDocValuesAndField", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndField(LongBlock.Builder results, int p, LongBlock encoded, int precision) { - fromEncodedLong(results, p, encoded, precision); + fromEncodedLong(results, p, encoded, precision, unboundedGrid); } @Evaluator(extraName = "FromLiteralAndField", warnExceptions = { IllegalArgumentException.class }) static long fromLiteralAndField(@Fixed BytesRef in, int precision) { - return calculateGeohash(GEO.wkbAsPoint(in), precision); - } - - protected static long calculateGeohash(Point point, int precision) { - return Geohash.longEncode(point.getX(), point.getY(), precision); + return unboundedGrid.calculateGridId(GEO.wkbAsPoint(in), precision); } @Evaluator(extraName = "FromFieldAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndLiteralAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, @Fixed GeoHashBoundedPredicate bounds) { + static void fromFieldAndLiteralAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, @Fixed GeoHashBoundedGrid bounds) { fromWKB(results, p, in, bounds); } @@ -220,14 +252,14 @@ static void fromFieldDocValuesAndLiteralAndLiteral( LongBlock.Builder results, int p, LongBlock encoded, - @Fixed GeoHashBoundedPredicate bounds + @Fixed GeoHashBoundedGrid bounds ) { fromEncodedLong(results, p, encoded, bounds); } @Evaluator(extraName = "FromFieldAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, int precision, @Fixed GeoBoundingBox bbox) { - GeoHashBoundedPredicate bounds = new GeoHashBoundedPredicate(precision, bbox); + GeoHashBoundedGrid bounds = new GeoHashBoundedGrid(precision, bbox); fromWKB(results, p, in, bounds); } @@ -239,112 +271,13 @@ static void fromFieldDocValuesAndFieldAndLiteral( int precision, @Fixed GeoBoundingBox bbox ) { - GeoHashBoundedPredicate bounds = new GeoHashBoundedPredicate(precision, bbox); + GeoHashBoundedGrid bounds = new GeoHashBoundedGrid(precision, bbox); fromEncodedLong(results, p, encoded, bounds); } @Evaluator(extraName = "FromLiteralAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) static long fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed GeoBoundingBox bbox) { - GeoHashBoundedPredicate bounds = new GeoHashBoundedPredicate(precision, bbox); - return calculateGeohash(GEO.wkbAsPoint(in), bounds); - } - - private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { - int valueCount = wkbBlock.getValueCount(position); - if (valueCount < 1) { - results.appendNull(); - } else { - final BytesRef scratch = new BytesRef(); - final int firstValueIndex = wkbBlock.getFirstValueIndex(position); - if (valueCount == 1) { - results.appendLong(calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision)); - } else { - results.beginPositionEntry(); - for (int i = 0; i < valueCount; i++) { - results.appendLong(calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision)); - } - results.endPositionEntry(); - } - } - } - - private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, int precision) { - int valueCount = encoded.getValueCount(position); - if (valueCount < 1) { - results.appendNull(); - } else { - final int firstValueIndex = encoded.getFirstValueIndex(position); - if (valueCount == 1) { - results.appendLong(calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision)); - } else { - results.beginPositionEntry(); - for (int i = 0; i < valueCount; i++) { - results.appendLong(calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision)); - } - results.endPositionEntry(); - } - } - } - - protected static long calculateGeohash(Point point, GeoHashBoundedPredicate bounds) { - String geohash = Geohash.stringEncode(point.getX(), point.getY(), bounds.precision()); - if (bounds.validHash(geohash)) { - return Geohash.longEncode(geohash); - } - // TODO: Are negative values allowed in geohash long encoding? - return -1; - } - - private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, GeoHashBoundedPredicate bounds) { - int valueCount = wkbBlock.getValueCount(position); - if (valueCount < 1) { - results.appendNull(); - } else { - final BytesRef scratch = new BytesRef(); - final int firstValueIndex = wkbBlock.getFirstValueIndex(position); - if (valueCount == 1) { - long grid = calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), bounds); - if (grid < 0) { - results.appendNull(); - } else { - results.appendLong(grid); - } - } else { - var gridIds = new ArrayList(valueCount); - for (int i = 0; i < valueCount; i++) { - var grid = calculateGeohash(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), bounds); - if (grid >= 0) { - gridIds.add(grid); - } - } - addGrids(results, gridIds); - } - } - } - - private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, GeoHashBoundedPredicate bounds) { - int valueCount = encoded.getValueCount(position); - if (valueCount < 1) { - results.appendNull(); - } else { - final int firstValueIndex = encoded.getFirstValueIndex(position); - if (valueCount == 1) { - long grid = calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex)), bounds); - if (grid < 0) { - results.appendNull(); - } else { - results.appendLong(grid); - } - } else { - var gridIds = new ArrayList(valueCount); - for (int i = 0; i < valueCount; i++) { - var grid = calculateGeohash(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), bounds); - if (grid >= 0) { - gridIds.add(grid); - } - } - addGrids(results, gridIds); - } - } + GeoHashBoundedGrid bounds = new GeoHashBoundedGrid(precision, bbox); + return bounds.calculateGridId(GEO.wkbAsPoint(in)); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java index 4b8e26e897abf..750582520213e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java @@ -29,7 +29,6 @@ import org.elasticsearch.xpack.esql.expression.function.Param; import java.io.IOException; -import java.util.ArrayList; import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; @@ -40,6 +39,46 @@ public class StGeohex extends SpatialGridFunction implements EvaluatorMapper { public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "StGeohex", StGeohex::new); + /** + * When checking grid cells with bounds, we need to check if the cell is valid (intersects with the bounds). + * This uses GeoHexBoundedPredicate to check if the cell is valid. + */ + protected static class GeoHexBoundedGrid implements BoundedGrid { + private final GeoHexBoundedPredicate bounds; + private final int precision; + + public GeoHexBoundedGrid(int precision, GeoBoundingBox bbox) { + this.bounds = new GeoHexBoundedPredicate(bbox); + this.precision = precision; + } + + public long calculateGridId(Point point) { + // For points, filtering the point is as good as filtering the tile + long geohex = H3.geoToH3(point.getLat(), point.getLon(), precision); + if (bounds.validHex(geohex)) { + return geohex; + } + // TODO: Are we sure negative numbers are not valid + return -1L; + } + + @Override + public int precision() { + return precision; + } + } + + /** + * For unbounded grids, we don't need to check if the tile is valid, + * just calculate the encoded long intersecting the point at that precision. + */ + protected static final UnboundedGrid unboundedGrid = new UnboundedGrid() { + @Override + public long calculateGridId(Point point, int precision) { + return H3.geoToH3(point.getLat(), point.getLon(), precision); + } + }; + @FunctionInfo(returnType = "long", description = """ Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHEX_TO_STRING](#esql-st_geohex_to_string) to convert the result to a string. @@ -116,7 +155,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua } else if (parameter().foldable()) { // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() int precision = (int) parameter.fold(toEvaluator.foldCtx()); - GeoHexBoundedPredicate bounds = new GeoHexBoundedPredicate(precision, bbox); + GeoHexBoundedGrid bounds = new GeoHexBoundedGrid(precision, bbox); return spatialDocsValues ? new StGeohexFromFieldDocValuesAndLiteralAndLiteralEvaluator.Factory( source(), @@ -148,7 +187,6 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua } else if (parameter().foldable()) { // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() int precision = (int) parameter.fold(toEvaluator.foldCtx()); - // TODO: Use GeoHexBoundedPredicate return spatialDocsValues ? new StGeohexFromFieldDocValuesAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField()), precision) : new StGeohexFromFieldAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField), precision); @@ -173,41 +211,40 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua public Object fold(FoldContext ctx) { var point = (BytesRef) spatialField().fold(ctx); int precision = (int) parameter().fold(ctx); - // TODO: Use GeoHexBoundedPredicate - return calculateGeohex(GEO.wkbAsPoint(point), precision); + if (bounds() == null) { + return fromLiteralAndField(point, precision); + } else { + return fromLiteralAndFieldAndLiteral(point, precision, asGeoBoundingBox((BytesRef) bounds().fold(ctx))); + } } @Evaluator(extraName = "FromFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock wkbBlock, @Fixed int precision) { - fromWKB(results, p, wkbBlock, precision); + fromWKB(results, p, wkbBlock, precision, unboundedGrid); } @Evaluator(extraName = "FromFieldDocValuesAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndLiteral(LongBlock.Builder results, int p, LongBlock encoded, @Fixed int precision) { - fromEncodedLong(results, p, encoded, precision); + fromEncodedLong(results, p, encoded, precision, unboundedGrid); } @Evaluator(extraName = "FromFieldAndField", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndField(LongBlock.Builder results, int p, BytesRefBlock in, int precision) { - fromWKB(results, p, in, precision); + fromWKB(results, p, in, precision, unboundedGrid); } @Evaluator(extraName = "FromFieldDocValuesAndField", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndField(LongBlock.Builder results, int p, LongBlock encoded, int precision) { - fromEncodedLong(results, p, encoded, precision); + fromEncodedLong(results, p, encoded, precision, unboundedGrid); } @Evaluator(extraName = "FromLiteralAndField", warnExceptions = { IllegalArgumentException.class }) static long fromLiteralAndField(@Fixed BytesRef in, int precision) { - return calculateGeohex(GEO.wkbAsPoint(in), precision); - } - - protected static long calculateGeohex(Point point, int precision) { - return H3.geoToH3(point.getLat(), point.getLon(), precision); + return unboundedGrid.calculateGridId(GEO.wkbAsPoint(in), precision); } @Evaluator(extraName = "FromFieldAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndLiteralAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, @Fixed GeoHexBoundedPredicate bounds) { + static void fromFieldAndLiteralAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, @Fixed GeoHexBoundedGrid bounds) { fromWKB(results, p, in, bounds); } @@ -216,14 +253,14 @@ static void fromFieldDocValuesAndLiteralAndLiteral( LongBlock.Builder results, int p, LongBlock encoded, - @Fixed GeoHexBoundedPredicate bounds + @Fixed GeoHexBoundedGrid bounds ) { fromEncodedLong(results, p, encoded, bounds); } @Evaluator(extraName = "FromFieldAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, int precision, @Fixed GeoBoundingBox bbox) { - GeoHexBoundedPredicate bounds = new GeoHexBoundedPredicate(precision, bbox); + GeoHexBoundedGrid bounds = new GeoHexBoundedGrid(precision, bbox); fromWKB(results, p, in, bounds); } @@ -235,113 +272,13 @@ static void fromFieldDocValuesAndFieldAndLiteral( int precision, @Fixed GeoBoundingBox bbox ) { - GeoHexBoundedPredicate bounds = new GeoHexBoundedPredicate(precision, bbox); + GeoHexBoundedGrid bounds = new GeoHexBoundedGrid(precision, bbox); fromEncodedLong(results, p, encoded, bounds); } @Evaluator(extraName = "FromLiteralAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) static long fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed GeoBoundingBox bbox) { - GeoHexBoundedPredicate bounds = new GeoHexBoundedPredicate(precision, bbox); - return calculateGeohex(GEO.wkbAsPoint(in), bounds); - } - - private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { - int valueCount = wkbBlock.getValueCount(position); - if (valueCount < 1) { - results.appendNull(); - } else { - final BytesRef scratch = new BytesRef(); - final int firstValueIndex = wkbBlock.getFirstValueIndex(position); - if (valueCount == 1) { - results.appendLong(calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision)); - } else { - results.beginPositionEntry(); - for (int i = 0; i < valueCount; i++) { - results.appendLong(calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision)); - } - results.endPositionEntry(); - } - } - } - - private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, int precision) { - int valueCount = encoded.getValueCount(position); - if (valueCount < 1) { - results.appendNull(); - } else { - final int firstValueIndex = encoded.getFirstValueIndex(position); - if (valueCount == 1) { - results.appendLong(calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision)); - } else { - results.beginPositionEntry(); - for (int i = 0; i < valueCount; i++) { - results.appendLong(calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision)); - } - results.endPositionEntry(); - } - } - } - - protected static long calculateGeohex(Point point, GeoHexBoundedPredicate bounds) { - // For points, filtering the point is as good as filtering the tile - long geohex = H3.geoToH3(point.getLat(), point.getLon(), bounds.precision()); - if (bounds.validHex(geohex)) { - return geohex; - } - // TODO: Are we sure negative numbers are not valid - return -1L; - } - - private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, GeoHexBoundedPredicate bounds) { - int valueCount = wkbBlock.getValueCount(position); - if (valueCount < 1) { - results.appendNull(); - } else { - final BytesRef scratch = new BytesRef(); - final int firstValueIndex = wkbBlock.getFirstValueIndex(position); - if (valueCount == 1) { - long grid = calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), bounds); - if (grid < 0) { - results.appendNull(); - } else { - results.appendLong(grid); - } - } else { - var gridIds = new ArrayList(valueCount); - for (int i = 0; i < valueCount; i++) { - var grid = calculateGeohex(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), bounds); - if (grid >= 0) { - gridIds.add(grid); - } - } - addGrids(results, gridIds); - } - } - } - - private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, GeoHexBoundedPredicate bounds) { - int valueCount = encoded.getValueCount(position); - if (valueCount < 1) { - results.appendNull(); - } else { - final int firstValueIndex = encoded.getFirstValueIndex(position); - if (valueCount == 1) { - long grid = calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex)), bounds); - if (grid < 0) { - results.appendNull(); - } else { - results.appendLong(grid); - } - } else { - var gridIds = new ArrayList(valueCount); - for (int i = 0; i < valueCount; i++) { - var grid = calculateGeohex(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), bounds); - if (grid >= 0) { - gridIds.add(grid); - } - } - addGrids(results, gridIds); - } - } + GeoHexBoundedGrid bounds = new GeoHexBoundedGrid(precision, bbox); + return bounds.calculateGridId(GEO.wkbAsPoint(in)); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java index f56980d674096..f4c10bc59bdda 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java @@ -30,7 +30,6 @@ import org.elasticsearch.xpack.esql.expression.function.Param; import java.io.IOException; -import java.util.ArrayList; import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; @@ -45,6 +44,47 @@ public class StGeotile extends SpatialGridFunction implements EvaluatorMapper { StGeotile::new ); + /** + * When checking tiles with bounds, we need to check if the tile is valid (intersects with the bounds). + * This uses GeoTileBoundedPredicate to check if the tile is valid. + */ + protected static class GeoTileBoundedGrid implements BoundedGrid { + private final GeoTileBoundedPredicate bounds; + private final int precision; + + public GeoTileBoundedGrid(int precision, GeoBoundingBox bbox) { + this.bounds = new GeoTileBoundedPredicate(precision, bbox); + this.precision = precision; + } + + public long calculateGridId(Point point) { + final int tiles = 1 << GeoTileUtils.checkPrecisionRange(precision); + final int x = GeoTileUtils.getXTile(point.getX(), tiles); + final int y = GeoTileUtils.getYTile(point.getY(), tiles); + if (bounds.validTile(x, y, precision)) { + return GeoTileUtils.longEncodeTiles(precision, x, y); + } + // TODO: Are we sure negative numbers are not valid + return -1L; + } + + @Override + public int precision() { + return precision; + } + } + + /** + * For unbounded grids, we don't need to check if the tile is valid, + * just calculate the encoded long intersecting the point at that precision. + */ + protected static final UnboundedGrid unboundedGrid = new UnboundedGrid() { + @Override + public long calculateGridId(Point point, int precision) { + return GeoTileUtils.longEncode(point.getX(), point.getY(), precision); + } + }; + @FunctionInfo(returnType = "long", description = """ Calculates the `geotile` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOTILE_TO_STRING](#esql-st_geotile_to_string) to convert the result to a string. @@ -121,7 +161,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua } else if (parameter().foldable()) { // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() int precision = (int) parameter.fold(toEvaluator.foldCtx()); - GeoTileBoundedPredicate bounds = new GeoTileBoundedPredicate(precision, bbox); + GeoTileBoundedGrid bounds = new GeoTileBoundedGrid(precision, bbox); return spatialDocsValues ? new StGeotileFromFieldDocValuesAndLiteralAndLiteralEvaluator.Factory( source(), @@ -153,7 +193,6 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua } else if (parameter().foldable()) { // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() int precision = (int) parameter.fold(toEvaluator.foldCtx()); - // TODO: Use GeoTileBoundedPredicate return spatialDocsValues ? new StGeotileFromFieldDocValuesAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField()), precision) : new StGeotileFromFieldAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField), precision); @@ -178,41 +217,40 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua public Object fold(FoldContext ctx) { var point = (BytesRef) spatialField().fold(ctx); int precision = (int) parameter().fold(ctx); - // TODO: Use GeoTileBoundedPredicate - return calculateGeotile(GEO.wkbAsPoint(point), precision); + if (bounds() == null) { + return fromLiteralAndField(point, precision); + } else { + return fromLiteralAndFieldAndLiteral(point, precision, asGeoBoundingBox((BytesRef) bounds().fold(ctx))); + } } @Evaluator(extraName = "FromFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock wkbBlock, @Fixed int precision) { - fromWKB(results, p, wkbBlock, precision); + fromWKB(results, p, wkbBlock, precision, unboundedGrid); } @Evaluator(extraName = "FromFieldDocValuesAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndLiteral(LongBlock.Builder results, int p, LongBlock encoded, @Fixed int precision) { - fromEncodedLong(results, p, encoded, precision); + fromEncodedLong(results, p, encoded, precision, unboundedGrid); } @Evaluator(extraName = "FromFieldAndField", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndField(LongBlock.Builder results, int p, BytesRefBlock in, int precision) { - fromWKB(results, p, in, precision); + fromWKB(results, p, in, precision, unboundedGrid); } @Evaluator(extraName = "FromFieldDocValuesAndField", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndField(LongBlock.Builder results, int p, LongBlock encoded, int precision) { - fromEncodedLong(results, p, encoded, precision); + fromEncodedLong(results, p, encoded, precision, unboundedGrid); } @Evaluator(extraName = "FromLiteralAndField", warnExceptions = { IllegalArgumentException.class }) static long fromLiteralAndField(@Fixed BytesRef in, int precision) { - return calculateGeotile(GEO.wkbAsPoint(in), precision); - } - - protected static long calculateGeotile(Point point, int precision) { - return GeoTileUtils.longEncode(point.getX(), point.getY(), precision); + return unboundedGrid.calculateGridId(GEO.wkbAsPoint(in), precision); } @Evaluator(extraName = "FromFieldAndLiteralAndLiteral", warnExceptions = { IllegalArgumentException.class }) - static void fromFieldAndLiteralAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, @Fixed GeoTileBoundedPredicate bounds) { + static void fromFieldAndLiteralAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, @Fixed GeoTileBoundedGrid bounds) { fromWKB(results, p, in, bounds); } @@ -221,14 +259,14 @@ static void fromFieldDocValuesAndLiteralAndLiteral( LongBlock.Builder results, int p, LongBlock encoded, - @Fixed GeoTileBoundedPredicate bounds + @Fixed GeoTileBoundedGrid bounds ) { fromEncodedLong(results, p, encoded, bounds); } @Evaluator(extraName = "FromFieldAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndFieldAndLiteral(LongBlock.Builder results, int p, BytesRefBlock in, int precision, @Fixed GeoBoundingBox bbox) { - GeoTileBoundedPredicate bounds = new GeoTileBoundedPredicate(precision, bbox); + GeoTileBoundedGrid bounds = new GeoTileBoundedGrid(precision, bbox); fromWKB(results, p, in, bounds); } @@ -240,114 +278,13 @@ static void fromFieldDocValuesAndFieldAndLiteral( int precision, @Fixed GeoBoundingBox bbox ) { - GeoTileBoundedPredicate bounds = new GeoTileBoundedPredicate(precision, bbox); + GeoTileBoundedGrid bounds = new GeoTileBoundedGrid(precision, bbox); fromEncodedLong(results, p, encoded, bounds); } @Evaluator(extraName = "FromLiteralAndFieldAndLiteral", warnExceptions = { IllegalArgumentException.class }) static long fromLiteralAndFieldAndLiteral(@Fixed BytesRef in, int precision, @Fixed GeoBoundingBox bbox) { - GeoTileBoundedPredicate bounds = new GeoTileBoundedPredicate(precision, bbox); - return calculateGeotile(GEO.wkbAsPoint(in), bounds); - } - - private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, int precision) { - int valueCount = wkbBlock.getValueCount(position); - if (valueCount < 1) { - results.appendNull(); - } else { - final BytesRef scratch = new BytesRef(); - final int firstValueIndex = wkbBlock.getFirstValueIndex(position); - if (valueCount == 1) { - results.appendLong(calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), precision)); - } else { - results.beginPositionEntry(); - for (int i = 0; i < valueCount; i++) { - results.appendLong(calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), precision)); - } - results.endPositionEntry(); - } - } - } - - private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, int precision) { - int valueCount = encoded.getValueCount(position); - if (valueCount < 1) { - results.appendNull(); - } else { - final int firstValueIndex = encoded.getFirstValueIndex(position); - if (valueCount == 1) { - results.appendLong(calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex)), precision)); - } else { - results.beginPositionEntry(); - for (int i = 0; i < valueCount; i++) { - results.appendLong(calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), precision)); - } - results.endPositionEntry(); - } - } - } - - protected static long calculateGeotile(Point point, GeoTileBoundedPredicate bounds) { - final int tiles = 1 << GeoTileUtils.checkPrecisionRange(bounds.precision()); - final int x = GeoTileUtils.getXTile(point.getX(), tiles); - final int y = GeoTileUtils.getYTile(point.getY(), tiles); - if (bounds.validTile(x, y, bounds.precision())) { - return GeoTileUtils.longEncodeTiles(bounds.precision(), x, y); - } - // TODO: Are we sure negative numbers are not valid - return -1L; - } - - private static void fromWKB(LongBlock.Builder results, int position, BytesRefBlock wkbBlock, GeoTileBoundedPredicate bounds) { - int valueCount = wkbBlock.getValueCount(position); - if (valueCount < 1) { - results.appendNull(); - } else { - final BytesRef scratch = new BytesRef(); - final int firstValueIndex = wkbBlock.getFirstValueIndex(position); - if (valueCount == 1) { - long grid = calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex, scratch)), bounds); - if (grid < 0) { - results.appendNull(); - } else { - results.appendLong(grid); - } - } else { - var gridIds = new ArrayList(valueCount); - for (int i = 0; i < valueCount; i++) { - var grid = calculateGeotile(GEO.wkbAsPoint(wkbBlock.getBytesRef(firstValueIndex + i, scratch)), bounds); - if (grid >= 0) { - gridIds.add(grid); - } - } - addGrids(results, gridIds); - } - } - } - - private static void fromEncodedLong(LongBlock.Builder results, int position, LongBlock encoded, GeoTileBoundedPredicate bounds) { - int valueCount = encoded.getValueCount(position); - if (valueCount < 1) { - results.appendNull(); - } else { - final int firstValueIndex = encoded.getFirstValueIndex(position); - if (valueCount == 1) { - long grid = calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex)), bounds); - if (grid < 0) { - results.appendNull(); - } else { - results.appendLong(grid); - } - } else { - var gridIds = new ArrayList(valueCount); - for (int i = 0; i < valueCount; i++) { - var grid = calculateGeotile(GEO.longAsPoint(encoded.getLong(firstValueIndex + i)), bounds); - if (grid >= 0) { - gridIds.add(grid); - } - } - addGrids(results, gridIds); - } - } + GeoTileBoundedGrid bounds = new GeoTileBoundedGrid(precision, bbox); + return bounds.calculateGridId(GEO.wkbAsPoint(in)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java index 7acfc5a6c21ec..0a33a1fbf5096 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java @@ -9,7 +9,6 @@ import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - import org.apache.lucene.util.BytesRef; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; @@ -35,7 +34,7 @@ public static Iterable parameters() { } private static long valueOf(BytesRef wkb, int precision) { - return StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(wkb), precision); + return StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(wkb), precision); } @Override diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java index 07194782037b4..52bc62605271b 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java @@ -9,7 +9,6 @@ import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - import org.apache.lucene.util.BytesRef; import org.elasticsearch.geometry.utils.Geohash; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -39,7 +38,7 @@ public static Iterable parameters() { suppliers, "StGeohashToGeoShapeFromLongEvaluator[gridId=Attribute[channel=0]]", GEO_SHAPE, - g -> StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(g), 2), + g -> StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), StGeohashToGeoShapeTests::valueOf ); forUnaryGeoPoint( @@ -47,7 +46,7 @@ public static Iterable parameters() { suppliers, "StGeohashToGeoShapeFromStringEvaluator[gridId=Attribute[channel=0]]", GEO_SHAPE, - g -> new BytesRef(Geohash.stringEncode(StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(g), 2))), + g -> new BytesRef(Geohash.stringEncode(StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), StGeohashToGeoShapeTests::valueOf ); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongTests.java index 5a8787ede1303..fab3655677774 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongTests.java @@ -38,7 +38,7 @@ public static Iterable parameters() { suppliers, "Attribute[channel=0]", DataType.LONG, - g -> StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(g), 2), + g -> StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), StGeohashToLongTests::valueOf ); forUnaryGeoPoint( @@ -46,7 +46,7 @@ public static Iterable parameters() { suppliers, "StGeohashToLongFromStringEvaluator[gridId=Attribute[channel=0]]", DataType.LONG, - g -> new BytesRef(Geohash.stringEncode(StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(g), 2))), + g -> new BytesRef(Geohash.stringEncode(StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), StGeohashToLongTests::valueOf ); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.java index 75b7c9b2ba695..5da7da4786f21 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.java @@ -9,7 +9,6 @@ import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - import org.apache.lucene.util.BytesRef; import org.elasticsearch.geometry.utils.Geohash; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -39,7 +38,7 @@ public static Iterable parameters() { suppliers, "StGeohashToStringFromLongEvaluator[gridId=Attribute[channel=0]]", KEYWORD, - g -> StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(g), 2), + g -> StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), StGeohashToStringTests::valueOf ); forUnaryGeoPoint( @@ -47,7 +46,7 @@ public static Iterable parameters() { suppliers, "Attribute[channel=0]", KEYWORD, - g -> new BytesRef(Geohash.stringEncode(StGeohash.calculateGeohash(UNSPECIFIED.wkbAsPoint(g), 2))), + g -> new BytesRef(Geohash.stringEncode(StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), StGeohashToStringTests::valueOf ); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexTests.java index 56427a24daf53..595e2c4f15249 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexTests.java @@ -35,7 +35,7 @@ public static Iterable parameters() { } private static long valueOf(BytesRef wkb, int precision) { - return StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(wkb), precision); + return StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(wkb), precision); } @Override diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java index 5305eed10941b..acd08a82e672e 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java @@ -39,7 +39,7 @@ public static Iterable parameters() { suppliers, "StGeohexToGeoShapeFromLongEvaluator[gridId=Attribute[channel=0]]", GEO_SHAPE, - g -> StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(g), 2), + g -> StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), StGeohexToGeoShapeTests::valueOf ); forUnaryGeoPoint( @@ -47,7 +47,7 @@ public static Iterable parameters() { suppliers, "StGeohexToGeoShapeFromStringEvaluator[gridId=Attribute[channel=0]]", GEO_SHAPE, - g -> new BytesRef(H3.h3ToString(StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(g), 2))), + g -> new BytesRef(H3.h3ToString(StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), StGeohexToGeoShapeTests::valueOf ); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java index 356af77d56fa3..3eea1eadc78d8 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java @@ -9,7 +9,6 @@ import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - import org.apache.lucene.util.BytesRef; import org.elasticsearch.h3.H3; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -38,7 +37,7 @@ public static Iterable parameters() { suppliers, "Attribute[channel=0]", DataType.LONG, - g -> StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(g), 2), + g -> StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), StGeohexToLongTests::valueOf ); forUnaryGeoPoint( @@ -46,7 +45,7 @@ public static Iterable parameters() { suppliers, "StGeohexToLongFromStringEvaluator[gridId=Attribute[channel=0]]", DataType.LONG, - g -> new BytesRef(H3.h3ToString(StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(g), 2))), + g -> new BytesRef(H3.h3ToString(StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), StGeohexToLongTests::valueOf ); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringTests.java index 826a7f9349895..bf3c734869330 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringTests.java @@ -39,7 +39,7 @@ public static Iterable parameters() { suppliers, "StGeohexToStringFromLongEvaluator[gridId=Attribute[channel=0]]", KEYWORD, - g -> StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(g), 2), + g -> StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), StGeohexToStringTests::valueOf ); forUnaryGeoPoint( @@ -47,7 +47,7 @@ public static Iterable parameters() { suppliers, "Attribute[channel=0]", KEYWORD, - g -> new BytesRef(H3.h3ToString(StGeohex.calculateGeohex(UNSPECIFIED.wkbAsPoint(g), 2))), + g -> new BytesRef(H3.h3ToString(StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), StGeohexToStringTests::valueOf ); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileTests.java index a4f3c1844c1a5..5f7e8b0425a3f 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileTests.java @@ -35,7 +35,7 @@ public static Iterable parameters() { } private static long valueOf(BytesRef wkb, int precision) { - return StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(wkb), precision); + return StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(wkb), precision); } @Override diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java index 1f82c0a6c5e6d..afed423cccbbe 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java @@ -39,7 +39,7 @@ public static Iterable parameters() { suppliers, "StGeotileToGeoShapeFromLongEvaluator[gridId=Attribute[channel=0]]", GEO_SHAPE, - g -> StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(g), 2), + g -> StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), StGeotileToGeoShapeTests::valueOf ); forUnaryGeoPoint( @@ -47,7 +47,7 @@ public static Iterable parameters() { suppliers, "StGeotileToGeoShapeFromStringEvaluator[gridId=Attribute[channel=0]]", GEO_SHAPE, - g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(g), 2))), + g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), StGeotileToGeoShapeTests::valueOf ); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongTests.java index 7e62effd9434e..1f43536719fd8 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongTests.java @@ -38,7 +38,7 @@ public static Iterable parameters() { suppliers, "Attribute[channel=0]", DataType.LONG, - g -> StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(g), 2), + g -> StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), StGeotileToLongTests::valueOf ); forUnaryGeoPoint( @@ -46,7 +46,7 @@ public static Iterable parameters() { suppliers, "StGeotileToLongFromStringEvaluator[gridId=Attribute[channel=0]]", DataType.LONG, - g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(g), 2))), + g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), StGeotileToLongTests::valueOf ); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringTests.java index e644f62abae89..fd558887c0fda 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringTests.java @@ -39,7 +39,7 @@ public static Iterable parameters() { suppliers, "StGeotileToStringFromLongEvaluator[gridId=Attribute[channel=0]]", KEYWORD, - g -> StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(g), 2), + g -> StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), StGeotileToStringTests::valueOf ); forUnaryGeoPoint( @@ -47,7 +47,7 @@ public static Iterable parameters() { suppliers, "Attribute[channel=0]", KEYWORD, - g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.calculateGeotile(UNSPECIFIED.wkbAsPoint(g), 2))), + g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), StGeotileToStringTests::valueOf ); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); From 770b061442bb2b7d34bfa645fb3cc19d32c0f6df Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Wed, 16 Apr 2025 12:48:39 +0200 Subject: [PATCH 16/34] Spotless --- .../esql/expression/function/scalar/spatial/StGeohashTests.java | 1 + .../function/scalar/spatial/StGeohashToGeoShapeTests.java | 1 + .../function/scalar/spatial/StGeohashToStringTests.java | 1 + .../expression/function/scalar/spatial/StGeohexToLongTests.java | 1 + 4 files changed, 4 insertions(+) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java index 0a33a1fbf5096..51efa32c95833 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java @@ -9,6 +9,7 @@ import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + import org.apache.lucene.util.BytesRef; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java index 52bc62605271b..6c0eaac7a69a0 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java @@ -9,6 +9,7 @@ import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + import org.apache.lucene.util.BytesRef; import org.elasticsearch.geometry.utils.Geohash; import org.elasticsearch.xpack.esql.core.expression.Expression; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.java index 5da7da4786f21..58feda75a8ab9 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.java @@ -9,6 +9,7 @@ import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + import org.apache.lucene.util.BytesRef; import org.elasticsearch.geometry.utils.Geohash; import org.elasticsearch.xpack.esql.core.expression.Expression; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java index 3eea1eadc78d8..7c28fdb551079 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java @@ -9,6 +9,7 @@ import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + import org.apache.lucene.util.BytesRef; import org.elasticsearch.h3.H3; import org.elasticsearch.xpack.esql.core.expression.Expression; From 16435b1914037890f0e93edfe5a9a8c6ad784d6b Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Wed, 16 Apr 2025 17:27:06 +0200 Subject: [PATCH 17/34] Add precision validation as well as more examples, refined docs, and support for geo_point bounds --- .../functions/description/st_geohash.md | 2 +- .../functions/description/st_geohex.md | 2 +- .../functions/description/st_geotile.md | 2 +- .../functions/parameters/st_geohash.md | 4 +- .../functions/parameters/st_geohex.md | 4 +- .../functions/parameters/st_geotile.md | 4 +- .../definition/functions/st_geohash.json | 4 +- .../definition/functions/st_geohex.json | 4 +- .../definition/functions/st_geotile.json | 4 +- .../esql/kibana/docs/functions/st_geohash.md | 4 +- .../esql/kibana/docs/functions/st_geohex.md | 3 + .../esql/kibana/docs/functions/st_geotile.md | 3 + .../src/main/resources/spatial-grid.csv-spec | 127 ++++++++++++++++++ .../scalar/spatial/SpatialGridFunction.java | 28 +++- .../function/scalar/spatial/StGeohash.java | 60 +++++---- .../function/scalar/spatial/StGeohex.java | 66 +++++---- .../function/scalar/spatial/StGeotile.java | 62 ++++----- 17 files changed, 281 insertions(+), 102 deletions(-) diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash.md index ce9266350167f..2527a90db74e7 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash.md +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash.md @@ -2,5 +2,5 @@ **Description** -Calculates the `geohash` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHASH_TO_STRING](#esql-st_geohash_to_string) to convert the result to a string. Or use [ST_GEOHASH_TO_GEOSHAPE](#esql-st_geohash_to_geoshape) to convert either the long or string `geohash` to a POLYGON geo_shape. +Calculates the `geohash` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHASH_TO_STRING](#esql-st_geohash_to_string) to convert the result to a string. Or use [ST_GEOHASH_TO_GEOSHAPE](#esql-st_geohash_to_geoshape) to convert either the long or string `geohash` to a These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) and the [`geohash_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohashgrid-aggregation). diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex.md index a3bf1c1238544..2b31926bef047 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex.md +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex.md @@ -2,5 +2,5 @@ **Description** -Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHEX_TO_STRING](#esql-st_geohex_to_string) to convert the result to a string. Or use [ST_GEOHEX_TO_GEOSHAPE](#esql-st_geohex_to_geoshape) to convert either the long or string `geohex` to a POLYGON geo_shape. +Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHEX_TO_STRING](#esql-st_geohex_to_string) to convert the result to a string. Or use [ST_GEOHEX_TO_GEOSHAPE](#esql-st_geohex_to_geoshape) to convert either the long or string `geohex` to a POLYGON geo_shape. These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) and the [`geohex_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohexgrid-aggregation). diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile.md index 631abd67eaa0f..c473312687c7a 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile.md +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile.md @@ -2,5 +2,5 @@ **Description** -Calculates the `geotile` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOTILE_TO_STRING](#esql-st_geotile_to_string) to convert the result to a string. Or use [ST_GEOTILE_TO_GEOSHAPE](#esql-st_geotile_to_geoshape) to convert either the long or string `geotile` to a POLYGON geo_shape. +Calculates the `geotile` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOTILE_TO_STRING](#esql-st_geotile_to_string) to convert the result to a string. Or use [ST_GEOTILE_TO_GEOSHAPE](#esql-st_geotile_to_geoshape) to convert either the long or string `geotile` to a POLYGON geo_shape. These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) and the [`geotile_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geotilegrid-aggregation). diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash.md index 007af1d6c28f7..6980bf5442a1d 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash.md +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash.md @@ -6,8 +6,8 @@ : Expression of type `geo_point`. If `null`, the function returns `null`. `precision` -: Expression of type `integer`. If `null`, the function returns `null`. +: Expression of type `integer`. If `null`, the function returns `null`. Valid values are between [1 and 12](https://en.wikipedia.org/wiki/Geohash). `bounds` -: Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points +: Optional bounds to filter the grid tiles, either a `geo_shape` or an array of at least two `geo_point`s. The envelope of the `geo_shape` is used as bounds. diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex.md index 007af1d6c28f7..a9fecf05bb84a 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex.md +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex.md @@ -6,8 +6,8 @@ : Expression of type `geo_point`. If `null`, the function returns `null`. `precision` -: Expression of type `integer`. If `null`, the function returns `null`. +: Expression of type `integer`. If `null`, the function returns `null`. Valid values are between [0 and 15](https://h3geo.org/docs/core-library/restable/). `bounds` -: Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points +: Optional bounds to filter the grid tiles, either a `geo_shape` or an array of at least two `geo_point`s. The envelope of the `geo_shape` is used as bounds. diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile.md index 007af1d6c28f7..7f5e4e6f7c80c 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile.md +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile.md @@ -6,8 +6,8 @@ : Expression of type `geo_point`. If `null`, the function returns `null`. `precision` -: Expression of type `integer`. If `null`, the function returns `null`. +: Expression of type `integer`. If `null`, the function returns `null`. Valid values are between [0 and 29](https://wiki.openstreetmap.org/wiki/Zoom_levels). `bounds` -: Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points +: Optional bounds to filter the grid tiles, either a `geo_shape` or an array of at least two `geo_point`s. The envelope of the `geo_shape` is used as bounds. diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash.json index 5a6e75496f253..7b6c4ae3d92d0 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash.json @@ -2,7 +2,7 @@ "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", "type" : "scalar", "name" : "st_geohash", - "description" : "Calculates the `geohash` of the supplied geo_point at the specified precision.\nThe result is long encoded. Use ST_GEOHASH_TO_STRING to convert the result to a string.\nOr use ST_GEOHASH_TO_GEOSHAPE to convert either the long or string `geohash` to a\nPOLYGON geo_shape.", + "description" : "Calculates the `geohash` of the supplied geo_point at the specified precision.\nThe result is long encoded. Use ST_GEOHASH_TO_STRING to convert the result to a string.\nOr use ST_GEOHASH_TO_GEOSHAPE to convert either the long or string `geohash` to a\n\nThese functions are related to the `geo_grid` query\nand the `geohash_grid` aggregation.", "signatures" : [ { "params" : [ @@ -16,7 +16,7 @@ "name" : "precision", "type" : "integer", "optional" : false, - "description" : "Expression of type `integer`. If `null`, the function returns `null`." + "description" : "Expression of type `integer`. If `null`, the function returns `null`. Valid values are between [1 and 12](https://en.wikipedia.org/wiki/Geohash)." } ], "variadic" : false, diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex.json index 4d640329d8666..0f2faadd1da28 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex.json @@ -2,7 +2,7 @@ "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", "type" : "scalar", "name" : "st_geohex", - "description" : "Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision.\nThe result is long encoded. Use ST_GEOHEX_TO_STRING to convert the result to a string.\nOr use ST_GEOHEX_TO_GEOSHAPE to convert either the long or string `geohex` to a\nPOLYGON geo_shape.", + "description" : "Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision.\nThe result is long encoded. Use ST_GEOHEX_TO_STRING to convert the result to a string.\nOr use ST_GEOHEX_TO_GEOSHAPE to convert either the long or string `geohex` to a\nPOLYGON geo_shape.\n\nThese functions are related to the `geo_grid` query\nand the `geohex_grid` aggregation.", "signatures" : [ { "params" : [ @@ -16,7 +16,7 @@ "name" : "precision", "type" : "integer", "optional" : false, - "description" : "Expression of type `integer`. If `null`, the function returns `null`." + "description" : "Expression of type `integer`. If `null`, the function returns `null`. Valid values are between [0 and 15](https://h3geo.org/docs/core-library/restable/)." } ], "variadic" : false, diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile.json b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile.json index 68bac0f446f4f..e3e9dfcade0af 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile.json @@ -2,7 +2,7 @@ "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", "type" : "scalar", "name" : "st_geotile", - "description" : "Calculates the `geotile` of the supplied geo_point at the specified precision.\nThe result is long encoded. Use ST_GEOTILE_TO_STRING to convert the result to a string.\nOr use ST_GEOTILE_TO_GEOSHAPE to convert either the long or string `geotile` to a\nPOLYGON geo_shape.", + "description" : "Calculates the `geotile` of the supplied geo_point at the specified precision.\nThe result is long encoded. Use ST_GEOTILE_TO_STRING to convert the result to a string.\nOr use ST_GEOTILE_TO_GEOSHAPE to convert either the long or string `geotile` to a\nPOLYGON geo_shape.\n\nThese functions are related to the `geo_grid` query\nand the `geotile_grid` aggregation.", "signatures" : [ { "params" : [ @@ -16,7 +16,7 @@ "name" : "precision", "type" : "integer", "optional" : false, - "description" : "Expression of type `integer`. If `null`, the function returns `null`." + "description" : "Expression of type `integer`. If `null`, the function returns `null`. Valid values are between [0 and 29](https://wiki.openstreetmap.org/wiki/Zoom_levels)." } ], "variadic" : false, diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash.md index c16e1957f67eb..08b10e27a6d75 100644 --- a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash.md +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash.md @@ -4,7 +4,9 @@ Calculates the `geohash` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHASH_TO_STRING](#esql-st_geohash_to_string) to convert the result to a string. Or use [ST_GEOHASH_TO_GEOSHAPE](#esql-st_geohash_to_geoshape) to convert either the long or string `geohash` to a -POLYGON geo_shape. + +These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) +and the [`geohash_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohashgrid-aggregation). ```esql FROM airports diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex.md index cca0ffe4c20bc..604319938b6b1 100644 --- a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex.md +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex.md @@ -6,6 +6,9 @@ The result is long encoded. Use [ST_GEOHEX_TO_STRING](#esql-st_geohex_to_string) Or use [ST_GEOHEX_TO_GEOSHAPE](#esql-st_geohex_to_geoshape) to convert either the long or string `geohex` to a POLYGON geo_shape. +These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) +and the [`geohex_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohexgrid-aggregation). + ```esql FROM airports | EVAL geohex = ST_GEOHEX(location, 1) diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile.md index 603673dad4f54..aebc43fc14c4d 100644 --- a/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile.md +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile.md @@ -6,6 +6,9 @@ The result is long encoded. Use [ST_GEOTILE_TO_STRING](#esql-st_geotile_to_strin Or use [ST_GEOTILE_TO_GEOSHAPE](#esql-st_geotile_to_geoshape) to convert either the long or string `geotile` to a POLYGON geo_shape. +These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) +and the [`geotile_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geotilegrid-aggregation). + ```esql FROM airports | EVAL geotile = ST_GEOTILE(location, 2) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index 86e6ee8b14681..743a226ce6413 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -207,6 +207,51 @@ count:long | centroid:geo_point | geohashString:keywo 2 | POINT (16.706149326637387 32.37822346854955) | sm | POLYGON((11.25 28.125, 22.5 28.125, 22.5 33.75, 11.25 33.75, 11.25 28.125)) ; +gridGeohashStatsByPointsBounds +required_capability: spatial_grid + +FROM airports +| EVAL points = ["POINT(0.0 30.0)", "POINT(12.0 60.0)"] +| EVAL geohash = ST_GEOHASH(location, 2, TO_GEOPOINT(points)) +| WHERE geohash IS NOT NULL +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geohash +| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +| KEEP count, centroid, geohashString, cellBoundary +| SORT count DESC, geohashString ASC +; + +count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape +19 | POINT (6.360728044651057 47.94084087577894) | u0 | POLYGON((0.0 45.0, 11.25 45.0, 11.25 50.625, 0.0 50.625, 0.0 45.0)) +10 | POINT (15.350638423115015 47.80751353036612) | u2 | POLYGON((11.25 45.0, 22.5 45.0, 22.5 50.625, 11.25 50.625, 11.25 45.0)) +9 | POINT (18.5217544157058 42.1394603792578) | sr | POLYGON((11.25 39.375, 22.5 39.375, 22.5 45.0, 11.25 45.0, 11.25 39.375)) +8 | POINT (6.351574736181647 51.8981519783847) | u1 | POLYGON((0.0 50.625, 11.25 50.625, 11.25 56.25, 0.0 56.25, 0.0 50.625)) +7 | POINT (5.268637698941997 42.747250193330856) | sp | POLYGON((0.0 39.375, 11.25 39.375, 11.25 45.0, 0.0 45.0, 0.0 39.375)) +7 | POINT (17.092350951528974 53.365471504096476) | u3 | POLYGON((11.25 50.625, 22.5 50.625, 22.5 56.25, 11.25 56.25, 11.25 50.625)) +5 | POINT (16.2651440910995 58.812188878655434) | u6 | POLYGON((11.25 56.25, 22.5 56.25, 22.5 61.875, 11.25 61.875, 11.25 56.25)) +4 | POINT (7.7012718468904495 36.39783004182391) | sn | POLYGON((0.0 33.75, 11.25 33.75, 11.25 39.375, 0.0 39.375, 0.0 33.75)) +3 | POINT (14.222751930356026 37.168446206487715) | sq | POLYGON((11.25 33.75, 22.5 33.75, 22.5 39.375, 11.25 39.375, 11.25 33.75)) +3 | POINT (7.318722177296877 59.788265260867774) | u4 | POLYGON((0.0 56.25, 11.25 56.25, 11.25 61.875, 0.0 61.875, 0.0 56.25)) +2 | POINT (16.706149326637387 32.37822346854955) | sm | POLYGON((11.25 28.125, 22.5 28.125, 22.5 33.75, 11.25 33.75, 11.25 28.125)) +; + +gridGeohashDocsFromCell +required_capability: spatial_grid + +FROM airports +| WHERE ST_INTERSECTS(location, ST_GEOHASH_TO_GEOSHAPE("u1")) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) +; + +count:long | centroid:geo_point +8 | POINT (6.351574736181647 51.8981519783847) +; + gridGeohashStatsByWhereUK required_capability: spatial_grid @@ -479,6 +524,42 @@ count:long | centroid:geo_point | geotileString:keywor 79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 | POLYGON((0.0 0.0, 45.0 0.0, 45.0 40.979898069620134, 0.0 40.979898069620134, 0.0 0.0)) ; +gridGeotileStatsByPointsBounds +required_capability: spatial_grid + +FROM airports +| EVAL points = ["POINT(0.0 30.0)", "POINT(12.0 60.0)"] +| EVAL geotile = ST_GEOTILE(location, 3, TO_GEOPOINT(points)) +| WHERE geotile IS NOT NULL +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geotile +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +| KEEP count, centroid, geotileString, cellBoundary +| SORT count DESC, geotileString ASC +; + +count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape +100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 | POLYGON((0.0 40.979898069620134, 45.0 40.979898069620134, 45.0 66.51326044311186, 0.0 66.51326044311186, 0.0 40.979898069620134)) +79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 | POLYGON((0.0 0.0, 45.0 0.0, 45.0 40.979898069620134, 0.0 40.979898069620134, 0.0 0.0)) +; + +gridGeotileDocsFromCell +required_capability: spatial_grid + +FROM airports +| WHERE ST_INTERSECTS(location, ST_GEOTILE_TO_GEOSHAPE("3/4/3")) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) +; + +count:long | centroid:geo_point +79 | POINT (24.516750878736943 23.93036561181085) +; + gridGeotileStatsByWhereUK required_capability: spatial_grid @@ -753,6 +834,52 @@ count:long | centroid:geo_point | geohexString:keywor 1 | POINT (13.144258903339505 32.66916951164603) | 813fbffffffffff | POLYGON ((8.974635637589913 30.254840780701706, 9.380676605201614 25.60370257696876, 13.915183885634578 23.45043771532035, 18.351304577591982 25.86678026136113, 18.343416368196834 30.62734805513404, 13.488580338198277 32.87501547725471, 8.974635637589913 30.254840780701706)) ; +gridGeohexStatsByPointsBounds +required_capability: spatial_grid + +FROM airports +| EVAL points = ["POINT(0.0 30.0)", "POINT(12.0 60.0)"] +| EVAL geohex = ST_GEOHEX(location, 1, TO_GEOPOINT(points)) +| WHERE geohex IS NOT NULL +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geohex +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) +| KEEP count, centroid, geohexString, cellBoundary +| SORT count DESC, geohexString ASC +; + +count:long | centroid:geo_point | geohexString:keyword | cellBoundary:geo_shape +22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff | POLYGON ((1.1885095534434493 49.47027919866873, 2.026568965384636 45.18424868970643, 7.509948481928886 43.786609353945, 12.677317810359858 46.40695745798227, 12.345747364400065 50.55427508726938, 6.259687055981993 51.96477015603749, 3.6300086390995467 50.6104633125695, 1.1885095534434493 49.47027919866873)) +17 | POINT (-0.7606179875266903 52.86413913565304) | 81197ffffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -6.436337296790312 55.3773904155485, -4.889760342933795 51.22372845966177, 1.1885095534434493 49.47027919866873, 3.6300086390995365 50.610463312569514, 6.259687055981993 51.96477015603749, 5.523646549290304 55.70676846515228, -0.9315871635106163 57.689497374592854)) +7 | POINT (2.475211258445467 41.32352174592337) | 81397ffffffffff | POLYGON ((-2.4177958307002347 42.54047996565121, -1.416234262837718 38.1159967227654, 0.2387159546288331 37.58884624349159, 3.543589356987798 36.59789814478598, 8.045142114241353 39.40213636897177, 7.509948481928886 43.786609353945, 2.026568965384636 45.18424868970643, -2.4177958307002347 42.54047996565121)) +6 | POINT (11.75047050230205 42.351422344800085) | 811ebffffffffff | POLYGON ((7.509948481928886 43.786609353945, 8.045142114241353 39.40213636897177, 13.244313475659823 37.5237123657852, 18.325260281104846 39.988177963363235, 18.314740441319 44.47067958889503, 12.677317810359858 46.40695745798227, 7.509948481928886 43.786609353945)) +5 | POINT (18.766171680763364 59.15833930950612) | 8108bffffffffff | POLYGON ((11.080660058482376 61.54051460002519, 11.555977692900722 58.13053116585142, 18.2752359517578 56.63295271905082, 25.082722326707877 58.4015448703527, 24.517172437523495 62.47811345192472, 17.53544630840839 63.800792653212156, 15.771773841154092 62.88996835796253, 11.080660058482376 61.54051460002519)) +5 | POINT (11.404999259859324 54.510593589395285) | 811f3ffffffffff | POLYGON ((5.523646549290313 55.70676846515226, 6.259687055981993 51.96477015603749, 12.345747364400065 50.55427508726938, 18.289963485942284 52.81905199947076, 18.2752359517578 56.63295271905082, 11.555977692900722 58.13053116585142, 5.523646549290313 55.70676846515226)) +4 | POINT (5.167026452254504 59.81037143385038) | 8109bffffffffff | POLYGON ((4.012620898449951 63.32706132801842, -2.297526087621831 61.54550957788076, -0.9315871635106163 57.689497374592854, 5.523646549290304 55.70676846515228, 11.555977692900722 58.13053116585142, 11.080660058482376 61.54051460002519, 8.644221197607186 61.8908384753262, 4.012620898449951 63.32706132801842)) +4 | POINT (-1.1871178611181676 35.77457194332965) | 81383ffffffffff | POLYGON ((-5.442348460730093 35.12442405176796, -4.341769247156951 30.69897412778907, -1.2408020165138167 29.828776159725596, 0.26094682603113584 29.300374659234986, 4.204173995672654 32.11010693139568, 3.543589356987798 36.59789814478598, 0.2387159546288331 37.58884624349159, -1.416234262837718 38.1159967227654, -5.442348460730093 35.12442405176796)) +3 | POINT (-1.1497433669865131 45.83295159973204) | 81187ffffffffff | POLYGON ((-4.889760342933795 51.22372845966177, -9.724736207832692 48.43009421958323, -8.101589192291552 44.0506310521871, -2.4177958307002347 42.54047996565121, 2.026568965384605 45.18424868970644, 1.1885095534434493 49.47027919866873, -4.889760342933795 51.22372845966177)) +3 | POINT (9.197671310976148 36.29719984252006) | 81387ffffffffff | POLYGON ((3.543589356987798 36.59789814478598, 4.204173995672654 32.11010693139568, 8.974635637589913 30.254840780701706, 13.488580338198277 32.87501547725471, 13.244313475659823 37.5237123657852, 8.045142114241353 39.40213636897177, 3.543589356987798 36.59789814478598)) +1 | POINT (13.144258903339505 32.66916951164603) | 813fbffffffffff | POLYGON ((8.974635637589913 30.254840780701706, 9.380676605201614 25.60370257696876, 13.915183885634578 23.45043771532035, 18.351304577591982 25.86678026136113, 18.343416368196834 30.62734805513404, 13.488580338198277 32.87501547725471, 8.974635637589913 30.254840780701706)) +; + +// TODO: Fix this test +//gridGeohexDocsFromCell +//required_capability: spatial_grid +// +//FROM airports +//| WHERE ST_INTERSECTS(location, ST_GEOHEX_TO_GEOSHAPE("81397ffffffffff")) +//| STATS +// count = COUNT(*), +// centroid = ST_CENTROID_AGG(location) +//; +// +//count:long | centroid:geo_point +//7 | POINT (2.475211258445467 41.32352174592337) +//; + gridGeohexStatsByWhereUK required_capability: spatial_grid diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java index 8df26af135d12..a6b91599fcb99 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java @@ -103,7 +103,7 @@ protected TypeResolution resolveType() { } if (bounds() != null) { - resolution = isGeoShape(bounds(), sourceText()); + resolution = isGeo(bounds(), sourceText()); if (resolution.unresolved()) { return resolution; } @@ -116,8 +116,8 @@ protected static Expression.TypeResolution isGeoPoint(Expression e, String opera return isType(e, t -> t.equals(GEO_POINT), operationName, FIRST, GEO_POINT.typeName()); } - protected static Expression.TypeResolution isGeoShape(Expression e, String operationName) { - return isType(e, t -> t.equals(GEO_SHAPE), operationName, THIRD, GEO_SHAPE.typeName()); + protected static Expression.TypeResolution isGeo(Expression e, String operationName) { + return isType(e, t -> t.equals(GEO_SHAPE) || t.equals(GEO_POINT), operationName, THIRD, GEO_SHAPE.typeName(), GEO_POINT.typeName()); } protected static Rectangle asRectangle(BytesRef boundsBytesRef) { @@ -132,8 +132,26 @@ protected static Rectangle asRectangle(BytesRef boundsBytesRef) { throw new IllegalArgumentException("Cannot determine envelope of bounds geometry"); } - protected static GeoBoundingBox asGeoBoundingBox(BytesRef boundsBytesRef) { - return asGeoBoundingBox(asRectangle(boundsBytesRef)); + protected static Rectangle asRectangle(List list) { + var visitor = new SpatialEnvelopeVisitor(new SpatialEnvelopeVisitor.GeoPointVisitor(SpatialEnvelopeVisitor.WrapLongitude.WRAP)); + for (Object o : list) { + if (o instanceof BytesRef bytesRef) { + var geometry = GEO.wkbToGeometry(bytesRef); + geometry.visit(visitor); + } else { + throw new IllegalArgumentException("Cannot determine envelope of bounds geometry of type " + o.getClass().getSimpleName()); + } + } + return visitor.getResult(); + } + + protected static GeoBoundingBox asGeoBoundingBox(Object bounds) { + if (bounds instanceof BytesRef boundsBytesRef) { + return asGeoBoundingBox(asRectangle(boundsBytesRef)); + } else if (bounds instanceof List list) { + return asGeoBoundingBox(asRectangle(list)); + } + throw new IllegalArgumentException("Cannot determine envelope of bounds geometry of type " + bounds.getClass().getSimpleName()); } protected static GeoBoundingBox asGeoBoundingBox(Rectangle rectangle) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java index cff0aafc4daff..174f5f9b25207 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java @@ -49,12 +49,12 @@ public class StGeohash extends SpatialGridFunction implements EvaluatorMapper { * This uses GeoHashBoundedPredicate to check if the grid cell is valid. */ protected static class GeoHashBoundedGrid implements BoundedGrid { - private final GeoHashBoundedPredicate bounds; private final int precision; + private final GeoHashBoundedPredicate bounds; public GeoHashBoundedGrid(int precision, GeoBoundingBox bbox) { + this.precision = checkPrecisionRange(precision); this.bounds = new GeoHashBoundedPredicate(precision, bbox); - this.precision = precision; } public long calculateGridId(Point point) { @@ -76,13 +76,32 @@ public int precision() { * For unbounded grids, we don't need to check if the grid cell is valid, * just calculate the encoded long intersecting the point at that precision. */ - protected static final UnboundedGrid unboundedGrid = (point, precision) -> Geohash.longEncode(point.getX(), point.getY(), precision); + protected static final UnboundedGrid unboundedGrid = (point, precision) -> Geohash.longEncode( + point.getX(), + point.getY(), + checkPrecisionRange(precision) + ); + + private static int checkPrecisionRange(int precision) { + if (precision < 1 || precision > Geohash.PRECISION) { + throw new IllegalArgumentException( + "Invalid geohash precision of " + precision + ". Must be between 1 and " + Geohash.PRECISION + "." + ); + } + return precision; + } - @FunctionInfo(returnType = "long", description = """ - Calculates the `geohash` of the supplied geo_point at the specified precision. - The result is long encoded. Use [ST_GEOHASH_TO_STRING](#esql-st_geohash_to_string) to convert the result to a string. - Or use [ST_GEOHASH_TO_GEOSHAPE](#esql-st_geohash_to_geoshape) to convert either the long or string `geohash` to a - POLYGON geo_shape.""", examples = @Example(file = "spatial-grid", tag = "st_geohash-grid")) + @FunctionInfo( + returnType = "long", + description = """ + Calculates the `geohash` of the supplied geo_point at the specified precision. + The result is long encoded. Use [ST_GEOHASH_TO_STRING](#esql-st_geohash_to_string) to convert the result to a string. + Or use [ST_GEOHASH_TO_GEOSHAPE](#esql-st_geohash_to_geoshape) to convert either the long or string `geohash` to a + + These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) + and the [`geohash_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohashgrid-aggregation).""", + examples = @Example(file = "spatial-grid", tag = "st_geohash-grid") + ) public StGeohash( Source source, @Param( @@ -90,17 +109,12 @@ public StGeohash( type = { "geo_point" }, description = "Expression of type `geo_point`. If `null`, the function returns `null`." ) Expression field, - @Param( - name = "precision", - type = { "integer" }, - description = "Expression of type `integer`. If `null`, the function returns `null`." - ) Expression precision, - @Param( - name = "bounds", - type = { "geo_shape", "geo_point" }, - description = "Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points", - optional = true - ) Expression bounds + @Param(name = "precision", type = { "integer" }, description = """ + Expression of type `integer`. If `null`, the function returns `null`. + Valid values are between [1 and 12](https://en.wikipedia.org/wiki/Geohash).""") Expression precision, + @Param(name = "bounds", type = { "geo_shape", "geo_point" }, description = """ + Optional bounds to filter the grid tiles, either a `geo_shape` or an array of at least two `geo_point`s. + The envelope of the `geo_shape` is used as bounds.""", optional = true) Expression bounds ) { this(source, field, precision, bounds, false); } @@ -146,7 +160,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua if (bounds.foldable() == false) { throw new IllegalArgumentException("bounds must be foldable"); } - GeoBoundingBox bbox = asGeoBoundingBox((BytesRef) bounds.fold(toEvaluator.foldCtx())); + GeoBoundingBox bbox = asGeoBoundingBox(bounds.fold(toEvaluator.foldCtx())); if (spatialField().foldable()) { // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() var point = (BytesRef) spatialField.fold(toEvaluator.foldCtx()); @@ -185,7 +199,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua return new StGeohashFromLiteralAndFieldEvaluator.Factory(source(), point, toEvaluator.apply(parameter())); } else if (parameter().foldable()) { // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() - int precision = (int) parameter.fold(toEvaluator.foldCtx()); + int precision = checkPrecisionRange((int) parameter.fold(toEvaluator.foldCtx())); return spatialDocsValues ? new StGeohashFromFieldDocValuesAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField()), precision) : new StGeohashFromFieldAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField), precision); @@ -229,12 +243,12 @@ static void fromFieldDocValuesAndLiteral(LongBlock.Builder results, int p, LongB @Evaluator(extraName = "FromFieldAndField", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndField(LongBlock.Builder results, int p, BytesRefBlock in, int precision) { - fromWKB(results, p, in, precision, unboundedGrid); + fromWKB(results, p, in, checkPrecisionRange(precision), unboundedGrid); } @Evaluator(extraName = "FromFieldDocValuesAndField", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndField(LongBlock.Builder results, int p, LongBlock encoded, int precision) { - fromEncodedLong(results, p, encoded, precision, unboundedGrid); + fromEncodedLong(results, p, encoded, checkPrecisionRange(precision), unboundedGrid); } @Evaluator(extraName = "FromLiteralAndField", warnExceptions = { IllegalArgumentException.class }) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java index 750582520213e..cbd16c4c461aa 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java @@ -44,12 +44,12 @@ public class StGeohex extends SpatialGridFunction implements EvaluatorMapper { * This uses GeoHexBoundedPredicate to check if the cell is valid. */ protected static class GeoHexBoundedGrid implements BoundedGrid { - private final GeoHexBoundedPredicate bounds; private final int precision; + private final GeoHexBoundedPredicate bounds; public GeoHexBoundedGrid(int precision, GeoBoundingBox bbox) { + this.precision = checkPrecisionRange(precision); this.bounds = new GeoHexBoundedPredicate(bbox); - this.precision = precision; } public long calculateGridId(Point point) { @@ -72,18 +72,33 @@ public int precision() { * For unbounded grids, we don't need to check if the tile is valid, * just calculate the encoded long intersecting the point at that precision. */ - protected static final UnboundedGrid unboundedGrid = new UnboundedGrid() { - @Override - public long calculateGridId(Point point, int precision) { - return H3.geoToH3(point.getLat(), point.getLon(), precision); + protected static final UnboundedGrid unboundedGrid = (point, precision) -> H3.geoToH3( + point.getLat(), + point.getLon(), + checkPrecisionRange(precision) + ); + + private static int checkPrecisionRange(int precision) { + if (precision < 1 || precision > H3.MAX_H3_RES) { + throw new IllegalArgumentException( + "Invalid geohex precision of " + precision + ". Must be between 0 and " + H3.MAX_H3_RES + "." + ); } - }; + return precision; + } - @FunctionInfo(returnType = "long", description = """ - Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision. - The result is long encoded. Use [ST_GEOHEX_TO_STRING](#esql-st_geohex_to_string) to convert the result to a string. - Or use [ST_GEOHEX_TO_GEOSHAPE](#esql-st_geohex_to_geoshape) to convert either the long or string `geohex` to a - POLYGON geo_shape.""", examples = @Example(file = "spatial-grid", tag = "st_geohex-grid")) + @FunctionInfo( + returnType = "long", + description = """ + Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision. + The result is long encoded. Use [ST_GEOHEX_TO_STRING](#esql-st_geohex_to_string) to convert the result to a string. + Or use [ST_GEOHEX_TO_GEOSHAPE](#esql-st_geohex_to_geoshape) to convert either the long or string `geohex` to a + POLYGON geo_shape. + + These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) + and the [`geohex_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohexgrid-aggregation).""", + examples = @Example(file = "spatial-grid", tag = "st_geohex-grid") + ) public StGeohex( Source source, @Param( @@ -91,17 +106,12 @@ public StGeohex( type = { "geo_point" }, description = "Expression of type `geo_point`. If `null`, the function returns `null`." ) Expression field, - @Param( - name = "precision", - type = { "integer" }, - description = "Expression of type `integer`. If `null`, the function returns `null`." - ) Expression precision, - @Param( - name = "bounds", - type = { "geo_shape", "geo_point" }, - description = "Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points", - optional = true - ) Expression bounds + @Param(name = "precision", type = { "integer" }, description = """ + Expression of type `integer`. If `null`, the function returns `null`. + Valid values are between [0 and 15](https://h3geo.org/docs/core-library/restable/).""") Expression precision, + @Param(name = "bounds", type = { "geo_shape", "geo_point" }, description = """ + Optional bounds to filter the grid tiles, either a `geo_shape` or an array of at least two `geo_point`s. + The envelope of the `geo_shape` is used as bounds.""", optional = true) Expression bounds ) { this(source, field, precision, bounds, false); } @@ -147,7 +157,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua if (bounds.foldable() == false) { throw new IllegalArgumentException("bounds must be foldable"); } - GeoBoundingBox bbox = asGeoBoundingBox((BytesRef) bounds.fold(toEvaluator.foldCtx())); + GeoBoundingBox bbox = asGeoBoundingBox(bounds.fold(toEvaluator.foldCtx())); if (spatialField().foldable()) { // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() var point = (BytesRef) spatialField.fold(toEvaluator.foldCtx()); @@ -186,7 +196,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua return new StGeohexFromLiteralAndFieldEvaluator.Factory(source(), point, toEvaluator.apply(parameter())); } else if (parameter().foldable()) { // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() - int precision = (int) parameter.fold(toEvaluator.foldCtx()); + int precision = checkPrecisionRange((int) parameter.fold(toEvaluator.foldCtx())); return spatialDocsValues ? new StGeohexFromFieldDocValuesAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField()), precision) : new StGeohexFromFieldAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField), precision); @@ -210,7 +220,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua @Override public Object fold(FoldContext ctx) { var point = (BytesRef) spatialField().fold(ctx); - int precision = (int) parameter().fold(ctx); + int precision = checkPrecisionRange((int) parameter().fold(ctx)); if (bounds() == null) { return fromLiteralAndField(point, precision); } else { @@ -230,12 +240,12 @@ static void fromFieldDocValuesAndLiteral(LongBlock.Builder results, int p, LongB @Evaluator(extraName = "FromFieldAndField", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndField(LongBlock.Builder results, int p, BytesRefBlock in, int precision) { - fromWKB(results, p, in, precision, unboundedGrid); + fromWKB(results, p, in, checkPrecisionRange(precision), unboundedGrid); } @Evaluator(extraName = "FromFieldDocValuesAndField", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndField(LongBlock.Builder results, int p, LongBlock encoded, int precision) { - fromEncodedLong(results, p, encoded, precision, unboundedGrid); + fromEncodedLong(results, p, encoded, checkPrecisionRange(precision), unboundedGrid); } @Evaluator(extraName = "FromLiteralAndField", warnExceptions = { IllegalArgumentException.class }) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java index f4c10bc59bdda..231191d7485e2 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java @@ -31,6 +31,7 @@ import java.io.IOException; +import static org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils.checkPrecisionRange; import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; @@ -49,16 +50,16 @@ public class StGeotile extends SpatialGridFunction implements EvaluatorMapper { * This uses GeoTileBoundedPredicate to check if the tile is valid. */ protected static class GeoTileBoundedGrid implements BoundedGrid { - private final GeoTileBoundedPredicate bounds; private final int precision; + private final GeoTileBoundedPredicate bounds; public GeoTileBoundedGrid(int precision, GeoBoundingBox bbox) { + this.precision = checkPrecisionRange(precision); this.bounds = new GeoTileBoundedPredicate(precision, bbox); - this.precision = precision; } public long calculateGridId(Point point) { - final int tiles = 1 << GeoTileUtils.checkPrecisionRange(precision); + final int tiles = 1 << precision; final int x = GeoTileUtils.getXTile(point.getX(), tiles); final int y = GeoTileUtils.getYTile(point.getY(), tiles); if (bounds.validTile(x, y, precision)) { @@ -78,18 +79,24 @@ public int precision() { * For unbounded grids, we don't need to check if the tile is valid, * just calculate the encoded long intersecting the point at that precision. */ - protected static final UnboundedGrid unboundedGrid = new UnboundedGrid() { - @Override - public long calculateGridId(Point point, int precision) { - return GeoTileUtils.longEncode(point.getX(), point.getY(), precision); - } - }; + protected static final UnboundedGrid unboundedGrid = (point, precision) -> GeoTileUtils.longEncode( + point.getX(), + point.getY(), + checkPrecisionRange(precision) + ); - @FunctionInfo(returnType = "long", description = """ - Calculates the `geotile` of the supplied geo_point at the specified precision. - The result is long encoded. Use [ST_GEOTILE_TO_STRING](#esql-st_geotile_to_string) to convert the result to a string. - Or use [ST_GEOTILE_TO_GEOSHAPE](#esql-st_geotile_to_geoshape) to convert either the long or string `geotile` to a - POLYGON geo_shape.""", examples = @Example(file = "spatial-grid", tag = "st_geotile-grid")) + @FunctionInfo( + returnType = "long", + description = """ + Calculates the `geotile` of the supplied geo_point at the specified precision. + The result is long encoded. Use [ST_GEOTILE_TO_STRING](#esql-st_geotile_to_string) to convert the result to a string. + Or use [ST_GEOTILE_TO_GEOSHAPE](#esql-st_geotile_to_geoshape) to convert either the long or string `geotile` to a + POLYGON geo_shape. + + These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) + and the [`geotile_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geotilegrid-aggregation).""", + examples = @Example(file = "spatial-grid", tag = "st_geotile-grid") + ) public StGeotile( Source source, @Param( @@ -97,17 +104,12 @@ public StGeotile( type = { "geo_point" }, description = "Expression of type `geo_point`. If `null`, the function returns `null`." ) Expression field, - @Param( - name = "precision", - type = { "integer" }, - description = "Expression of type `integer`. If `null`, the function returns `null`." - ) Expression precision, - @Param( - name = "bounds", - type = { "geo_shape", "geo_point" }, - description = "Bounds to filter the grid tiles, either a geo_shape BBOX or an array of two points", - optional = true - ) Expression bounds + @Param(name = "precision", type = { "integer" }, description = """ + Expression of type `integer`. If `null`, the function returns `null`. + Valid values are between [0 and 29](https://wiki.openstreetmap.org/wiki/Zoom_levels).""") Expression precision, + @Param(name = "bounds", type = { "geo_shape", "geo_point" }, description = """ + Optional bounds to filter the grid tiles, either a `geo_shape` or an array of at least two `geo_point`s. + The envelope of the `geo_shape` is used as bounds.""", optional = true) Expression bounds ) { this(source, field, precision, bounds, false); } @@ -153,7 +155,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua if (bounds.foldable() == false) { throw new IllegalArgumentException("bounds must be foldable"); } - GeoBoundingBox bbox = asGeoBoundingBox((BytesRef) bounds.fold(toEvaluator.foldCtx())); + GeoBoundingBox bbox = asGeoBoundingBox(bounds.fold(toEvaluator.foldCtx())); if (spatialField().foldable()) { // Assume right is not foldable, since that would be dealt with in isFoldable() and fold() var point = (BytesRef) spatialField.fold(toEvaluator.foldCtx()); @@ -192,7 +194,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua return new StGeotileFromLiteralAndFieldEvaluator.Factory(source(), point, toEvaluator.apply(parameter())); } else if (parameter().foldable()) { // Assume left is not foldable, since that would be dealt with in isFoldable() and fold() - int precision = (int) parameter.fold(toEvaluator.foldCtx()); + int precision = checkPrecisionRange((int) parameter.fold(toEvaluator.foldCtx())); return spatialDocsValues ? new StGeotileFromFieldDocValuesAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField()), precision) : new StGeotileFromFieldAndLiteralEvaluator.Factory(source(), toEvaluator.apply(spatialField), precision); @@ -216,7 +218,7 @@ public EvalOperator.ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvalua @Override public Object fold(FoldContext ctx) { var point = (BytesRef) spatialField().fold(ctx); - int precision = (int) parameter().fold(ctx); + int precision = checkPrecisionRange((int) parameter().fold(ctx)); if (bounds() == null) { return fromLiteralAndField(point, precision); } else { @@ -236,12 +238,12 @@ static void fromFieldDocValuesAndLiteral(LongBlock.Builder results, int p, LongB @Evaluator(extraName = "FromFieldAndField", warnExceptions = { IllegalArgumentException.class }) static void fromFieldAndField(LongBlock.Builder results, int p, BytesRefBlock in, int precision) { - fromWKB(results, p, in, precision, unboundedGrid); + fromWKB(results, p, in, checkPrecisionRange(precision), unboundedGrid); } @Evaluator(extraName = "FromFieldDocValuesAndField", warnExceptions = { IllegalArgumentException.class }) static void fromFieldDocValuesAndField(LongBlock.Builder results, int p, LongBlock encoded, int precision) { - fromEncodedLong(results, p, encoded, precision, unboundedGrid); + fromEncodedLong(results, p, encoded, checkPrecisionRange(precision), unboundedGrid); } @Evaluator(extraName = "FromLiteralAndField", warnExceptions = { IllegalArgumentException.class }) From ea613d92ca75868491e55571e91acd3265451068 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Thu, 17 Apr 2025 11:03:57 +0200 Subject: [PATCH 18/34] Support depthOffset in MD docs headings for nesting functions --- .../esql/_snippets/lists/spatial-functions.md | 18 ++++++++--------- .../functions-operators/spatial-functions.md | 20 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/reference/query-languages/esql/_snippets/lists/spatial-functions.md b/docs/reference/query-languages/esql/_snippets/lists/spatial-functions.md index 04562d1177602..3621e44ac4f53 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/spatial-functions.md +++ b/docs/reference/query-languages/esql/_snippets/lists/spatial-functions.md @@ -11,14 +11,14 @@ * [preview] [`ST_YMAX`](../../functions-operators/spatial-functions.md#esql-st_ymax) * [preview] [`ST_YMIN`](../../functions-operators/spatial-functions.md#esql-st_ymin) * [preview] [`ST_GEOTILE`](../../functions-operators/spatial-functions.md#esql-st_geotile) + * [preview] [`ST_GEOTILE_TO_STRING`](../../functions-operators/spatial-functions.md#esql-st_geotile_to_string) + * [preview] [`ST_GEOTILE_TO_LONG`](../../functions-operators/spatial-functions.md#esql-st_geotile_to_long) + * [preview] [`ST_GEOTILE_TO_GEOSHAPE`](../../functions-operators/spatial-functions.md#esql-st_geotile_to_geoshape) * [preview] [`ST_GEOHEX`](../../functions-operators/spatial-functions.md#esql-st_geohex) + * [preview] [`ST_GEOHEX_TO_STRING`](../../functions-operators/spatial-functions.md#esql-st_geohex_to_string) + * [preview] [`ST_GEOHEX_TO_LONG`](../../functions-operators/spatial-functions.md#esql-st_geohex_to_long) + * [preview] [`ST_GEOHEX_TO_GEOSHAPE`](../../functions-operators/spatial-functions.md#esql-st_geohex_to_geoshape) * [preview] [`ST_GEOHASH`](../../functions-operators/spatial-functions.md#esql-st_geohash) -* [preview] [`ST_GEOTILE_TO_STRING`](../../functions-operators/spatial-functions.md#esql-st_geotile_to_string) -* [preview] [`ST_GEOHEX_TO_STRING`](../../functions-operators/spatial-functions.md#esql-st_geohex_to_string) -* [preview] [`ST_GEOHASH_TO_STRING`](../../functions-operators/spatial-functions.md#esql-st_geohash_to_string) -* [preview] [`ST_GEOTILE_TO_LONG`](../../functions-operators/spatial-functions.md#esql-st_geotile_to_long) -* [preview] [`ST_GEOHEX_TO_LONG`](../../functions-operators/spatial-functions.md#esql-st_geohex_to_long) -* [preview] [`ST_GEOHASH_TO_LONG`](../../functions-operators/spatial-functions.md#esql-st_geohash_to_long) -* [preview] [`ST_GEOTILE_TO_GEOSHAPE`](../../functions-operators/spatial-functions.md#esql-st_geotile_to_geoshape) -* [preview] [`ST_GEOHEX_TO_GEOSHAPE`](../../functions-operators/spatial-functions.md#esql-st_geohex_to_geoshape) -* [preview] [`ST_GEOHASH_TO_GEOSHAPE`](../../functions-operators/spatial-functions.md#esql-st_geohash_to_geoshape) + * [preview] [`ST_GEOHASH_TO_STRING`](../../functions-operators/spatial-functions.md#esql-st_geohash_to_string) + * [preview] [`ST_GEOHASH_TO_LONG`](../../functions-operators/spatial-functions.md#esql-st_geohash_to_long) + * [preview] [`ST_GEOHASH_TO_GEOSHAPE`](../../functions-operators/spatial-functions.md#esql-st_geohash_to_geoshape) diff --git a/docs/reference/query-languages/esql/functions-operators/spatial-functions.md b/docs/reference/query-languages/esql/functions-operators/spatial-functions.md index a6f50c809585e..c4441e12a14ae 100644 --- a/docs/reference/query-languages/esql/functions-operators/spatial-functions.md +++ b/docs/reference/query-languages/esql/functions-operators/spatial-functions.md @@ -51,34 +51,34 @@ mapped_pages: :::{include} ../_snippets/functions/layout/st_geotile.md ::: -:::{include} ../_snippets/functions/layout/st_geohex.md +:::{include} ../_snippets/functions/layout/st_geotile_to_string.md ::: -:::{include} ../_snippets/functions/layout/st_geohash.md +:::{include} ../_snippets/functions/layout/st_geotile_to_long.md ::: -:::{include} ../_snippets/functions/layout/st_geotile_to_string.md +:::{include} ../_snippets/functions/layout/st_geotile_to_geoshape.md ::: -:::{include} ../_snippets/functions/layout/st_geohex_to_string.md +:::{include} ../_snippets/functions/layout/st_geohex.md ::: -:::{include} ../_snippets/functions/layout/st_geohash_to_string.md +:::{include} ../_snippets/functions/layout/st_geohex_to_string.md ::: -:::{include} ../_snippets/functions/layout/st_geotile_to_long.md +:::{include} ../_snippets/functions/layout/st_geohex_to_long.md ::: -:::{include} ../_snippets/functions/layout/st_geohex_to_long.md +:::{include} ../_snippets/functions/layout/st_geohex_to_geoshape.md ::: -:::{include} ../_snippets/functions/layout/st_geohash_to_long.md +:::{include} ../_snippets/functions/layout/st_geohash.md ::: -:::{include} ../_snippets/functions/layout/st_geotile_to_geoshape.md +:::{include} ../_snippets/functions/layout/st_geohash_to_string.md ::: -:::{include} ../_snippets/functions/layout/st_geohex_to_geoshape.md +:::{include} ../_snippets/functions/layout/st_geohash_to_long.md ::: :::{include} ../_snippets/functions/layout/st_geohash_to_geoshape.md From 5dde316bac3b901b2708c488726eccad4a10290c Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Thu, 17 Apr 2025 11:04:31 +0200 Subject: [PATCH 19/34] Add depthOffset to geo grid functions --- .../esql/_snippets/functions/layout/st_geohash_to_geoshape.md | 2 +- .../esql/_snippets/functions/layout/st_geohash_to_long.md | 2 +- .../esql/_snippets/functions/layout/st_geohash_to_string.md | 2 +- .../esql/_snippets/functions/layout/st_geohex_to_geoshape.md | 2 +- .../esql/_snippets/functions/layout/st_geohex_to_long.md | 2 +- .../esql/_snippets/functions/layout/st_geohex_to_string.md | 2 +- .../esql/_snippets/functions/layout/st_geotile_to_geoshape.md | 2 +- .../esql/_snippets/functions/layout/st_geotile_to_long.md | 2 +- .../esql/_snippets/functions/layout/st_geotile_to_string.md | 2 +- .../function/scalar/spatial/StGeohashToGeoShape.java | 3 ++- .../expression/function/scalar/spatial/StGeohashToLong.java | 3 ++- .../expression/function/scalar/spatial/StGeohashToString.java | 3 ++- .../expression/function/scalar/spatial/StGeohexToGeoShape.java | 3 ++- .../expression/function/scalar/spatial/StGeohexToLong.java | 3 ++- .../expression/function/scalar/spatial/StGeohexToString.java | 3 ++- .../function/scalar/spatial/StGeotileToGeoShape.java | 3 ++- .../expression/function/scalar/spatial/StGeotileToLong.java | 3 ++- .../expression/function/scalar/spatial/StGeotileToString.java | 3 ++- 18 files changed, 27 insertions(+), 18 deletions(-) diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_geoshape.md index b5c1403644c9c..616208fab61ab 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_geoshape.md +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_geoshape.md @@ -1,6 +1,6 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. -## `ST_GEOHASH_TO_GEOSHAPE` [esql-st_geohash_to_geoshape] +### `ST_GEOHASH_TO_GEOSHAPE` [esql-st_geohash_to_geoshape] **Syntax** diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_long.md index 73e09c2cbd83d..e9f37660cedf9 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_long.md +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_long.md @@ -1,6 +1,6 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. -## `ST_GEOHASH_TO_LONG` [esql-st_geohash_to_long] +### `ST_GEOHASH_TO_LONG` [esql-st_geohash_to_long] **Syntax** diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_string.md index 464d614c70638..cfed286eeee68 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_string.md +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_string.md @@ -1,6 +1,6 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. -## `ST_GEOHASH_TO_STRING` [esql-st_geohash_to_string] +### `ST_GEOHASH_TO_STRING` [esql-st_geohash_to_string] **Syntax** diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_geoshape.md index bbc02229ad139..debfd69bc1af2 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_geoshape.md +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_geoshape.md @@ -1,6 +1,6 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. -## `ST_GEOHEX_TO_GEOSHAPE` [esql-st_geohex_to_geoshape] +### `ST_GEOHEX_TO_GEOSHAPE` [esql-st_geohex_to_geoshape] **Syntax** diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_long.md index cd1c1dd66910c..6fe48a030d188 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_long.md +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_long.md @@ -1,6 +1,6 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. -## `ST_GEOHEX_TO_LONG` [esql-st_geohex_to_long] +### `ST_GEOHEX_TO_LONG` [esql-st_geohex_to_long] **Syntax** diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_string.md index 528d28ef6a3ca..be1b882a50676 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_string.md +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_string.md @@ -1,6 +1,6 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. -## `ST_GEOHEX_TO_STRING` [esql-st_geohex_to_string] +### `ST_GEOHEX_TO_STRING` [esql-st_geohex_to_string] **Syntax** diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_geoshape.md index e0c608eeaea94..526c536c6c8b3 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_geoshape.md +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_geoshape.md @@ -1,6 +1,6 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. -## `ST_GEOTILE_TO_GEOSHAPE` [esql-st_geotile_to_geoshape] +### `ST_GEOTILE_TO_GEOSHAPE` [esql-st_geotile_to_geoshape] **Syntax** diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_long.md index ce5c6151e990b..eb5828218376d 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_long.md +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_long.md @@ -1,6 +1,6 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. -## `ST_GEOTILE_TO_LONG` [esql-st_geotile_to_long] +### `ST_GEOTILE_TO_LONG` [esql-st_geotile_to_long] **Syntax** diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_string.md index 1b7d3af345fb1..b1481b33788a4 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_string.md +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_string.md @@ -1,6 +1,6 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. -## `ST_GEOTILE_TO_STRING` [esql-st_geotile_to_string] +### `ST_GEOTILE_TO_STRING` [esql-st_geotile_to_string] **Syntax** diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java index 86487168bdfe7..b205ca194dbc9 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java @@ -48,7 +48,8 @@ public class StGeohashToGeoShape extends AbstractConvertFunction implements Eval description = """ Converts an input value to a `geo_shape` value. The input values are expected to be the grid-ids of geohash grids, in either long or string format.""", - examples = @Example(file = "spatial-grid", tag = "geohash_to_geoshape") + examples = @Example(file = "spatial-grid", tag = "geohash_to_geoshape"), + depthOffset = 1 // make it appear as a subsection of ST_GEOHASH ) public StGeohashToGeoShape( Source source, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLong.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLong.java index d9fa75fe69053..717dfea9724ec 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLong.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLong.java @@ -44,7 +44,8 @@ public class StGeohashToLong extends AbstractConvertFunction implements Evaluato @FunctionInfo( returnType = "long", description = "Converts an input value representing a geohash grid-ID in string format into a long.", - examples = { @Example(file = "spatial-grid", tag = "geohash_to_long") } + examples = { @Example(file = "spatial-grid", tag = "geohash_to_long") }, + depthOffset = 1 // make it appear as a subsection of ST_GEOHASH ) public StGeohashToLong( Source source, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToString.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToString.java index 0a1e4d68cebf2..d3c6f7697e0c9 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToString.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToString.java @@ -44,7 +44,8 @@ public class StGeohashToString extends AbstractConvertFunction implements Evalua @FunctionInfo( returnType = "keyword", description = "Converts an input value representing a geohash grid-ID in long format into a string.", - examples = { @Example(file = "spatial-grid", tag = "geohash_to_string") } + examples = { @Example(file = "spatial-grid", tag = "geohash_to_string") }, + depthOffset = 1 // make it appear as a subsection of ST_GEOHASH ) public StGeohashToString( Source source, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java index b801d279d66c6..816fadb6061c2 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java @@ -52,7 +52,8 @@ public class StGeohexToGeoShape extends AbstractConvertFunction implements Evalu description = """ Converts an input value to a `geo_shape` value. The input values are expected to be the grid-ids of H3 grids, in either long or string format.""", - examples = @Example(file = "spatial-grid", tag = "geohex_to_geoshape") + examples = @Example(file = "spatial-grid", tag = "geohex_to_geoshape"), + depthOffset = 1 // make it appear as a subsection of ST_GEOHEX ) public StGeohexToGeoShape( Source source, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLong.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLong.java index a410b9ebbbe0c..abb357a683109 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLong.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLong.java @@ -44,7 +44,8 @@ public class StGeohexToLong extends AbstractConvertFunction implements Evaluator @FunctionInfo( returnType = "long", description = "Converts an input value representing a geohex grid-ID in string format into a long.", - examples = { @Example(file = "spatial-grid", tag = "geohex_to_long") } + examples = { @Example(file = "spatial-grid", tag = "geohex_to_long") }, + depthOffset = 1 // make it appear as a subsection of ST_GEOHEX ) public StGeohexToLong( Source source, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java index 8e1fc18cfcefc..9632fe983a66b 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java @@ -44,7 +44,8 @@ public class StGeohexToString extends AbstractConvertFunction implements Evaluat @FunctionInfo( returnType = "keyword", description = "Converts an input value representing a Geohex grid-ID in long format into a string.", - examples = { @Example(file = "spatial-grid", tag = "geohex_to_string") } + examples = { @Example(file = "spatial-grid", tag = "geohex_to_string") }, + depthOffset = 1 // make it appear as a subsection of ST_GEOHEX ) public StGeohexToString( Source source, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java index 65f2f0395bd2a..862a33d82ad79 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java @@ -51,7 +51,8 @@ public class StGeotileToGeoShape extends AbstractConvertFunction implements Eval description = """ Converts an input value to a `geo_shape` value. The input values are expected to be the grid-ids of geotile grids, in either long or string format.""", - examples = @Example(file = "spatial-grid", tag = "geotile_to_geoshape") + examples = @Example(file = "spatial-grid", tag = "geotile_to_geoshape"), + depthOffset = 1 // make it appear as a subsection of ST_GEOTILE ) public StGeotileToGeoShape( Source source, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLong.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLong.java index 8189bac55b992..fd52f273a4f76 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLong.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLong.java @@ -44,7 +44,8 @@ public class StGeotileToLong extends AbstractConvertFunction implements Evaluato @FunctionInfo( returnType = "long", description = "Converts an input value representing a geotile grid-ID in string format into a long.", - examples = { @Example(file = "spatial-grid", tag = "geotile_to_long") } + examples = { @Example(file = "spatial-grid", tag = "geotile_to_long") }, + depthOffset = 1 // make it appear as a subsection of ST_GEOTILE ) public StGeotileToLong( Source source, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToString.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToString.java index 04b24d2874841..1a2d2b88afc52 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToString.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToString.java @@ -44,7 +44,8 @@ public class StGeotileToString extends AbstractConvertFunction implements Evalua @FunctionInfo( returnType = "keyword", description = "Converts an input value representing a geotile grid-ID in long format into a string.", - examples = { @Example(file = "spatial-grid", tag = "geotile_to_string") } + examples = { @Example(file = "spatial-grid", tag = "geotile_to_string") }, + depthOffset = 1 // make it appear as a subsection of ST_GEOTILE ) public StGeotileToString( Source source, From fdedf0ef2644a3cf8efcb291a27f2037b4892e94 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Mon, 19 May 2025 11:47:47 +0200 Subject: [PATCH 20/34] Added type error tests and reduced precision to only support integer --- .../scalar/spatial/SpatialGridFunction.java | 4 +- .../scalar/spatial/StGeohashErrorTests.java | 42 +++++++++++++++++++ .../scalar/spatial/StGeohexErrorTests.java | 42 +++++++++++++++++++ .../scalar/spatial/StGeotileErrorTests.java | 42 +++++++++++++++++++ 4 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashErrorTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexErrorTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileErrorTests.java diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java index a6b91599fcb99..ce29e92a88d35 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunction.java @@ -33,9 +33,9 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.THIRD; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isType; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isWholeNumber; import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT; import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.type.DataType.INTEGER; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; /** @@ -97,7 +97,7 @@ protected TypeResolution resolveType() { return resolution; } - resolution = isWholeNumber(parameter(), sourceText(), SECOND); + resolution = isType(parameter, t -> t.equals(INTEGER), sourceText(), SECOND, INTEGER.typeName()); if (resolution.unresolved()) { return resolution; } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashErrorTests.java new file mode 100644 index 0000000000000..c8f80421c5e03 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashErrorTests.java @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; +import org.hamcrest.Matcher; + +import java.util.List; +import java.util.Set; + +import static org.hamcrest.Matchers.equalTo; + +public class StGeohashErrorTests extends ErrorsForCasesWithoutExamplesTestCase { + @Override + protected List cases() { + return paramsToSuppliers(StGeohashTests.parameters()); + } + + @Override + protected Expression build(Source source, List args) { + return new StGeohash(source, args.get(0), args.get(1), args.size() > 2 ? args.get(2) : null); + } + + @Override + protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + return equalTo(typeErrorMessage(true, validPerPosition, signature, (v, p) -> switch (p) { + case 0 -> "geo_point"; + case 1 -> "integer"; + case 2 -> "geo_shape"; + default -> throw new IllegalStateException("Unexpected value: " + p); + })); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexErrorTests.java new file mode 100644 index 0000000000000..29110d015a6e0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexErrorTests.java @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; +import org.hamcrest.Matcher; + +import java.util.List; +import java.util.Set; + +import static org.hamcrest.Matchers.equalTo; + +public class StGeohexErrorTests extends ErrorsForCasesWithoutExamplesTestCase { + @Override + protected List cases() { + return paramsToSuppliers(StGeohexTests.parameters()); + } + + @Override + protected Expression build(Source source, List args) { + return new StGeohex(source, args.get(0), args.get(1), args.size() > 2 ? args.get(2) : null); + } + + @Override + protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + return equalTo(typeErrorMessage(true, validPerPosition, signature, (v, p) -> switch (p) { + case 0 -> "geo_point"; + case 1 -> "integer"; + case 2 -> "geo_shape"; + default -> throw new IllegalStateException("Unexpected value: " + p); + })); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileErrorTests.java new file mode 100644 index 0000000000000..c357b79636fd5 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileErrorTests.java @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; +import org.hamcrest.Matcher; + +import java.util.List; +import java.util.Set; + +import static org.hamcrest.Matchers.equalTo; + +public class StGeotileErrorTests extends ErrorsForCasesWithoutExamplesTestCase { + @Override + protected List cases() { + return paramsToSuppliers(StGeotileTests.parameters()); + } + + @Override + protected Expression build(Source source, List args) { + return new StGeotile(source, args.get(0), args.get(1), args.size() > 2 ? args.get(2) : null); + } + + @Override + protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + return equalTo(typeErrorMessage(true, validPerPosition, signature, (v, p) -> switch (p) { + case 0 -> "geo_point"; + case 1 -> "integer"; + case 2 -> "geo_shape"; + default -> throw new IllegalStateException("Unexpected value: " + p); + })); + } +} From 16072c8dd026129a456437249cc57bd0c38c905d Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Mon, 19 May 2025 15:19:19 +0200 Subject: [PATCH 21/34] Added geo_grid queries (no lucene pushdown) --- .../src/main/resources/spatial-grid.csv-spec | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index 743a226ce6413..48972efb9300f 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -177,6 +177,29 @@ count:long | centroid:geo_point | geohashString:keyw // end::st_geohash-grid-result[] ; +gridGeohashQuery +required_capability: spatial_grid + +FROM airports +| WHERE ST_GEOHASH(location, 1) == ST_GEOHASH_TO_LONG("7") +| EVAL geohash = ST_GEOHASH(location, 2) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geohash +| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +| KEEP count, centroid, geohashString +| SORT count DESC, geohashString ASC +; + +count:long | centroid:geo_point | geohashString:keyword +4 | POINT (-35.22712387377396 -7.672965489327908) | 7n +3 | POINT (-41.86607404612005 -3.8085224060341716) | 7p +2 | POINT (-42.66381660941988 -22.868987743277103) | 75 +2 | POINT (-42.12605922482908 -19.945099228061736) | 7h +1 | POINT (-38.3347990270704 -12.91436152998358) | 7j +; + gridGeohashStatsByBounds required_capability: spatial_grid @@ -503,6 +526,26 @@ count:long | centroid:geo_point | geotileString:key // end::st_geotile-grid-result[] ; +gridGeotileQuery +required_capability: spatial_grid + +FROM airports +| WHERE ST_GEOTILE(location, 2) == ST_GEOTILE_TO_LONG("2/0/2") +| EVAL geotile = ST_GEOTILE(location, 3) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geotile +| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| SORT count DESC, geotileString ASC +| KEEP count, centroid, geotileString +; + +count:long | centroid:geo_point | geotileString:keyword +7 | POINT (-167.3069146488394 -17.976190628084755) | 3/0/4 +1 | POINT (-109.43006442859769 -27.15877384878695) | 3/1/4 +; + gridGeotileStatsByBounds required_capability: spatial_grid @@ -804,6 +847,30 @@ count:long | centroid:geo_point | geohexString:keywo // end::st_geohex-grid-result[] ; +gridGeohexQuery +required_capability: spatial_grid + +FROM airports +| WHERE ST_GEOHEX(location, 1) == ST_GEOHEX_TO_LONG("812bbffffffffff") +| EVAL geohex = ST_GEOHEX(location, 2) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) + BY geohex +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| KEEP count, centroid, geohexString +| SORT count DESC, geohexString ASC +; + +count:long | centroid:geo_point | geohexString:keyword +3 | POINT (-74.35916994698346 43.44888433814049) | 822b8ffffffffff +2 | POINT (-74.84681587200612 45.50167993409559) | 822b87fffffffff +2 | POINT (-80.11034240014851 46.490730887744576) | 822b97fffffffff +2 | POINT (-78.6383319273591 43.40425574686378) | 822b9ffffffffff +2 | POINT (-72.56662221159786 46.1249598255381) | 822baffffffffff +1 | POINT (-81.37204706668854 48.56615798547864) | 820ecffffffffff +; + gridGeohexStatsByBounds required_capability: spatial_grid From e610b48cd4f34eb9a4ea482875351ba817254494 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Mon, 19 May 2025 17:33:09 +0200 Subject: [PATCH 22/34] Added tests for invalid precision --- .../function/scalar/spatial/StGeohash.java | 2 +- .../function/scalar/spatial/StGeohex.java | 2 +- .../spatial/SpatialGridFunctionTestCase.java | 23 +++++++++++++++++++ .../scalar/spatial/StGeohashTests.java | 9 ++++++++ .../scalar/spatial/StGeohexTests.java | 9 ++++++++ .../scalar/spatial/StGeotileTests.java | 9 ++++++++ 6 files changed, 52 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java index 174f5f9b25207..1dd4d70b318c1 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java @@ -85,7 +85,7 @@ public int precision() { private static int checkPrecisionRange(int precision) { if (precision < 1 || precision > Geohash.PRECISION) { throw new IllegalArgumentException( - "Invalid geohash precision of " + precision + ". Must be between 1 and " + Geohash.PRECISION + "." + "Invalid geohash_grid precision of " + precision + ". Must be between 1 and " + Geohash.PRECISION + "." ); } return precision; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java index cbd16c4c461aa..32fe9ea33ea8c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java @@ -81,7 +81,7 @@ public int precision() { private static int checkPrecisionRange(int precision) { if (precision < 1 || precision > H3.MAX_H3_RES) { throw new IllegalArgumentException( - "Invalid geohex precision of " + precision + ". Must be between 0 and " + H3.MAX_H3_RES + "." + "Invalid geohex_grid precision of " + precision + ". Must be between 0 and " + H3.MAX_H3_RES + "." ); } return precision; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunctionTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunctionTestCase.java index 3678ecd65df1f..fd1a01ad18493 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunctionTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunctionTestCase.java @@ -8,6 +8,10 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.xpack.esql.core.expression.Literal; +import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase; import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; @@ -18,6 +22,7 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; import static org.elasticsearch.xpack.esql.core.type.DataType.isSpatialGeo; import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assume.assumeNotNull; public abstract class SpatialGridFunctionTestCase extends AbstractScalarFunctionTestCase { @@ -87,4 +92,22 @@ public static TestCaseSupplier.TypedDataSupplier testCaseSupplier(DataType dataT }; } } + + protected Long process(int precision, BiFunction expectedValue) { + Object spatialObj = this.testCase.getDataValues().getFirst(); + assumeNotNull(spatialObj); + assumeTrue("Expected a BytesRef, but got " + spatialObj.getClass(), spatialObj instanceof BytesRef); + BytesRef wkb = (BytesRef) spatialObj; + try ( + EvalOperator.ExpressionEvaluator eval = evaluator( + build( + Source.EMPTY, + List.of(new Literal(Source.EMPTY, wkb, DataType.GEO_POINT), new Literal(Source.EMPTY, precision, DataType.INTEGER)) + ) + ).get(driverContext()); + Block block = eval.eval(row(List.of(wkb, precision))) + ) { + return block.isNull(0) ? null : expectedValue.apply(wkb, precision); + } + } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java index 51efa32c95833..3a62a8ec37eff 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java @@ -11,6 +11,7 @@ import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.geometry.utils.Geohash; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; @@ -21,6 +22,7 @@ import java.util.function.Supplier; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; +import static org.hamcrest.Matchers.containsString; public class StGeohashTests extends SpatialGridFunctionTestCase { public StGeohashTests(@Name("TestCase") Supplier testCaseSupplier) { @@ -43,4 +45,11 @@ protected Expression build(Source source, List args) { Expression bounds = args.size() > 2 ? args.get(2) : null; return new StGeohash(source, args.get(0), args.get(1), bounds); } + + public void testInvalidPrecision() { + IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> process(-1, StGeohashTests::valueOf)); + assertThat(ex.getMessage(), containsString("Invalid geohash_grid precision of -1. Must be between 1 and 12.")); + ex = expectThrows(IllegalArgumentException.class, () -> process(Geohash.PRECISION + 1, StGeohashTests::valueOf)); + assertThat(ex.getMessage(), containsString("Invalid geohash_grid precision of 13. Must be between 1 and 12.")); + } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexTests.java index 595e2c4f15249..e3763272771a2 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexTests.java @@ -11,6 +11,7 @@ import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.h3.H3; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; @@ -21,6 +22,7 @@ import java.util.function.Supplier; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; +import static org.hamcrest.Matchers.containsString; public class StGeohexTests extends SpatialGridFunctionTestCase { public StGeohexTests(@Name("TestCase") Supplier testCaseSupplier) { @@ -43,4 +45,11 @@ protected Expression build(Source source, List args) { Expression bounds = args.size() > 2 ? args.get(2) : null; return new StGeohex(source, args.get(0), args.get(1), bounds); } + + public void testInvalidPrecision() { + IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> process(-1, StGeohexTests::valueOf)); + assertThat(ex.getMessage(), containsString("Invalid geohex_grid precision of -1. Must be between 0 and 15.")); + ex = expectThrows(IllegalArgumentException.class, () -> process(H3.MAX_H3_RES + 1, StGeohexTests::valueOf)); + assertThat(ex.getMessage(), containsString("Invalid geohex_grid precision of 16. Must be between 0 and 15.")); + } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileTests.java index 5f7e8b0425a3f..7576912460907 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileTests.java @@ -11,6 +11,7 @@ import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; @@ -21,6 +22,7 @@ import java.util.function.Supplier; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; +import static org.hamcrest.Matchers.containsString; public class StGeotileTests extends SpatialGridFunctionTestCase { public StGeotileTests(@Name("TestCase") Supplier testCaseSupplier) { @@ -43,4 +45,11 @@ protected Expression build(Source source, List args) { Expression bounds = args.size() > 2 ? args.get(2) : null; return new StGeotile(source, args.get(0), args.get(1), bounds); } + + public void testInvalidPrecision() { + IllegalArgumentException ex = expectThrows(IllegalArgumentException.class, () -> process(-1, StGeotileTests::valueOf)); + assertThat(ex.getMessage(), containsString("Invalid geotile_grid precision of -1. Must be between 0 and 29.")); + ex = expectThrows(IllegalArgumentException.class, () -> process(GeoTileUtils.MAX_ZOOM + 1, StGeotileTests::valueOf)); + assertThat(ex.getMessage(), containsString("Invalid geotile_grid precision of 30. Must be between 0 and 29.")); + } } From 437a513227248efc9f1312f2324af0b427a2107e Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Mon, 19 May 2025 09:42:33 -0700 Subject: [PATCH 23/34] Update docs/changelog/125143.yaml --- docs/changelog/125143.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs/changelog/125143.yaml diff --git a/docs/changelog/125143.yaml b/docs/changelog/125143.yaml new file mode 100644 index 0000000000000..2f4ee63175bde --- /dev/null +++ b/docs/changelog/125143.yaml @@ -0,0 +1,5 @@ +pr: 125143 +summary: "ES|QL Support for ST_GEOHASH, ST_GEOTILE and ST_GEOHEX" +area: "ES|QL, Geo" +type: enhancement +issues: [] From 5cadb1471b00b584e3d7a3d5acabdee439fd0a9c Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Mon, 19 May 2025 18:47:54 +0200 Subject: [PATCH 24/34] Fix docs links --- .../esql/_snippets/functions/description/st_geohash.md | 2 +- .../esql/_snippets/functions/description/st_geohex.md | 2 +- .../esql/_snippets/functions/description/st_geotile.md | 2 +- .../query-languages/esql/kibana/docs/functions/st_geohash.md | 4 ++-- .../query-languages/esql/kibana/docs/functions/st_geohex.md | 4 ++-- .../query-languages/esql/kibana/docs/functions/st_geotile.md | 4 ++-- .../esql/expression/function/scalar/spatial/StGeohash.java | 4 ++-- .../esql/expression/function/scalar/spatial/StGeohex.java | 4 ++-- .../esql/expression/function/scalar/spatial/StGeotile.java | 4 ++-- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash.md index 2527a90db74e7..22b42697a6d4d 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash.md +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash.md @@ -2,5 +2,5 @@ **Description** -Calculates the `geohash` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHASH_TO_STRING](#esql-st_geohash_to_string) to convert the result to a string. Or use [ST_GEOHASH_TO_GEOSHAPE](#esql-st_geohash_to_geoshape) to convert either the long or string `geohash` to a These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) and the [`geohash_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohashgrid-aggregation). +Calculates the `geohash` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHASH_TO_STRING](#esql-st_geohash_to_string) to convert the result to a string. Or use [ST_GEOHASH_TO_GEOSHAPE](#esql-st_geohash_to_geoshape) to convert either the long or string `geohash` to a These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query.md) and the [`geohash_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohashgrid-aggregation.md). diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex.md index 2b31926bef047..92afbe3875e63 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex.md +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex.md @@ -2,5 +2,5 @@ **Description** -Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHEX_TO_STRING](#esql-st_geohex_to_string) to convert the result to a string. Or use [ST_GEOHEX_TO_GEOSHAPE](#esql-st_geohex_to_geoshape) to convert either the long or string `geohex` to a POLYGON geo_shape. These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) and the [`geohex_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohexgrid-aggregation). +Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHEX_TO_STRING](#esql-st_geohex_to_string) to convert the result to a string. Or use [ST_GEOHEX_TO_GEOSHAPE](#esql-st_geohex_to_geoshape) to convert either the long or string `geohex` to a POLYGON geo_shape. These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query.md) and the [`geohex_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohexgrid-aggregation.md). diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile.md index c473312687c7a..3ff5fa213ece9 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile.md +++ b/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile.md @@ -2,5 +2,5 @@ **Description** -Calculates the `geotile` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOTILE_TO_STRING](#esql-st_geotile_to_string) to convert the result to a string. Or use [ST_GEOTILE_TO_GEOSHAPE](#esql-st_geotile_to_geoshape) to convert either the long or string `geotile` to a POLYGON geo_shape. These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) and the [`geotile_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geotilegrid-aggregation). +Calculates the `geotile` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOTILE_TO_STRING](#esql-st_geotile_to_string) to convert the result to a string. Or use [ST_GEOTILE_TO_GEOSHAPE](#esql-st_geotile_to_geoshape) to convert either the long or string `geotile` to a POLYGON geo_shape. These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query.md) and the [`geotile_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geotilegrid-aggregation.md). diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash.md index 08b10e27a6d75..331e1d02d23e7 100644 --- a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash.md +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash.md @@ -5,8 +5,8 @@ Calculates the `geohash` of the supplied geo_point at the specified precision. The result is long encoded. Use [ST_GEOHASH_TO_STRING](#esql-st_geohash_to_string) to convert the result to a string. Or use [ST_GEOHASH_TO_GEOSHAPE](#esql-st_geohash_to_geoshape) to convert either the long or string `geohash` to a -These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) -and the [`geohash_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohashgrid-aggregation). +These functions are related to the [`geo_grid` query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-geo-grid-query) +and the [`geohash_grid` aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-geohashgrid-aggregation). ```esql FROM airports diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex.md index 604319938b6b1..d327cee735d96 100644 --- a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex.md +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex.md @@ -6,8 +6,8 @@ The result is long encoded. Use [ST_GEOHEX_TO_STRING](#esql-st_geohex_to_string) Or use [ST_GEOHEX_TO_GEOSHAPE](#esql-st_geohex_to_geoshape) to convert either the long or string `geohex` to a POLYGON geo_shape. -These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) -and the [`geohex_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohexgrid-aggregation). +These functions are related to the [`geo_grid` query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-geo-grid-query) +and the [`geohex_grid` aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-geohexgrid-aggregation). ```esql FROM airports diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile.md index aebc43fc14c4d..1aea5ea3b4e18 100644 --- a/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile.md +++ b/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile.md @@ -6,8 +6,8 @@ The result is long encoded. Use [ST_GEOTILE_TO_STRING](#esql-st_geotile_to_strin Or use [ST_GEOTILE_TO_GEOSHAPE](#esql-st_geotile_to_geoshape) to convert either the long or string `geotile` to a POLYGON geo_shape. -These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) -and the [`geotile_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geotilegrid-aggregation). +These functions are related to the [`geo_grid` query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-geo-grid-query) +and the [`geotile_grid` aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-geotilegrid-aggregation). ```esql FROM airports diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java index 1dd4d70b318c1..53fbb07a18942 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohash.java @@ -98,8 +98,8 @@ private static int checkPrecisionRange(int precision) { The result is long encoded. Use [ST_GEOHASH_TO_STRING](#esql-st_geohash_to_string) to convert the result to a string. Or use [ST_GEOHASH_TO_GEOSHAPE](#esql-st_geohash_to_geoshape) to convert either the long or string `geohash` to a - These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) - and the [`geohash_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohashgrid-aggregation).""", + These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query.md) + and the [`geohash_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohashgrid-aggregation.md).""", examples = @Example(file = "spatial-grid", tag = "st_geohash-grid") ) public StGeohash( diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java index 32fe9ea33ea8c..8ebb025dbee8c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java @@ -95,8 +95,8 @@ private static int checkPrecisionRange(int precision) { Or use [ST_GEOHEX_TO_GEOSHAPE](#esql-st_geohex_to_geoshape) to convert either the long or string `geohex` to a POLYGON geo_shape. - These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) - and the [`geohex_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohexgrid-aggregation).""", + These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query.md) + and the [`geohex_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geohexgrid-aggregation.md).""", examples = @Example(file = "spatial-grid", tag = "st_geohex-grid") ) public StGeohex( diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java index 231191d7485e2..33263596cbad5 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java @@ -93,8 +93,8 @@ public int precision() { Or use [ST_GEOTILE_TO_GEOSHAPE](#esql-st_geotile_to_geoshape) to convert either the long or string `geotile` to a POLYGON geo_shape. - These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query) - and the [`geotile_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geotilegrid-aggregation).""", + These functions are related to the [`geo_grid` query](/reference/query-languages/query-dsl/query-dsl-geo-grid-query.md) + and the [`geotile_grid` aggregation](/reference/aggregations/search-aggregations-bucket-geotilegrid-aggregation.md).""", examples = @Example(file = "spatial-grid", tag = "st_geotile-grid") ) public StGeotile( From a2326886b696081305785ab18d1395efcfd96e66 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Mon, 19 May 2025 09:50:34 -0700 Subject: [PATCH 25/34] Update docs/changelog/125143.yaml --- docs/changelog/125143.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/changelog/125143.yaml b/docs/changelog/125143.yaml index 2f4ee63175bde..b92990d4dd4d9 100644 --- a/docs/changelog/125143.yaml +++ b/docs/changelog/125143.yaml @@ -2,4 +2,5 @@ pr: 125143 summary: "ES|QL Support for ST_GEOHASH, ST_GEOTILE and ST_GEOHEX" area: "ES|QL, Geo" type: enhancement -issues: [] +issues: + - 123903 From dd2ec9a33de2274fff277cc105a9c897cee3e25e Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Mon, 19 May 2025 18:55:30 +0200 Subject: [PATCH 26/34] Fix invalid changelog --- docs/changelog/125143.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelog/125143.yaml b/docs/changelog/125143.yaml index b92990d4dd4d9..83e15973f9932 100644 --- a/docs/changelog/125143.yaml +++ b/docs/changelog/125143.yaml @@ -1,6 +1,6 @@ pr: 125143 summary: "ES|QL Support for ST_GEOHASH, ST_GEOTILE and ST_GEOHEX" -area: "ES|QL, Geo" +area: "ES|QL" type: enhancement issues: - 123903 From eaf9417791bb59e607b225a455c31b14c3612269 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 20 May 2025 11:44:50 +0200 Subject: [PATCH 27/34] Fix function count --- .../yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml index 39929f6bba8d7..bf8c3bcfdb3bc 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml @@ -123,7 +123,7 @@ setup: - match: {esql.functions.coalesce: $functions_coalesce} - gt: {esql.functions.categorize: $functions_categorize} # Testing for the entire function set isn't feasible, so we just check that we return the correct count as an approximation. - - length: {esql.functions: 152} # check the "sister" test below for a likely update to the same esql.functions length check + - length: {esql.functions: 153} # check the "sister" test below for a likely update to the same esql.functions length check --- "Basic ESQL usage output (telemetry) non-snapshot version": From ccd13f43138099979e2622c94d43f246dc18d960 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 20 May 2025 12:19:51 +0200 Subject: [PATCH 28/34] Some more specific tests to flush out bounds differences on serverless --- .../src/main/resources/spatial-grid.csv-spec | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index 48972efb9300f..1b3d6aa114d72 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -901,6 +901,40 @@ count:long | centroid:geo_point | geohexString:keywor 1 | POINT (13.144258903339505 32.66916951164603) | 813fbffffffffff | POLYGON ((8.974635637589913 30.254840780701706, 9.380676605201614 25.60370257696876, 13.915183885634578 23.45043771532035, 18.351304577591982 25.86678026136113, 18.343416368196834 30.62734805513404, 13.488580338198277 32.87501547725471, 8.974635637589913 30.254840780701706)) ; +gridGeohexQueryBounds +required_capability: spatial_grid + +FROM airports +| EVAL geohex = ST_GEOHEX(location, 1, TO_GEOSHAPE("POLYGON((0.0 30.0, 12.0 30.0, 12.0 60.0, 0.0 60.0, 0.0 30.0))")) +| WHERE ST_GEOHEX_TO_STRING(geohex) == "811f3ffffffffff" +| EVAL geohexString = ST_GEOHEX_TO_STRING(ST_GEOHEX(location, 1)) +| KEEP abbrev, location, geohexString +; + +abbrev:keyword | location:geo_point | geohexString:keyword +BRE | POINT (8.7858617703132 53.052287104156) | 811f3ffffffffff +GOT | POINT (12.2938269092573 57.6857493534879) | 811f3ffffffffff +CPH | POINT (12.6493508684508 55.6285017221528) | 811f3ffffffffff +HAM | POINT (10.005647830925 53.6320011640866) | 811f3ffffffffff +TXL | POINT (13.2903090925074 52.5544287044101) | 811f3ffffffffff +; + +gridGeohexByBounds +required_capability: spatial_grid + +FROM airports +| WHERE abbrev IN ("RTW", "TIP", "XMN") +| EVAL geohex = ST_GEOHEX(location, 1, TO_GEOSHAPE("POLYGON((0.0 30.0, 12.0 30.0, 12.0 60.0, 0.0 60.0, 0.0 30.0))")) +| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| KEEP abbrev, location, geohex, geohexString +; + +abbrev:keyword | location:geo_point | geohex:long | geohexString:keyword +RTW | POINT (46.035023249891 51.5606456508842) | null | null +XMN | POINT (118.12696884672 24.537192570557) | null | null +TIP | POINT (13.1442589810713 32.6691695504993) | 582085853791125503 | 813fbffffffffff +; + gridGeohexStatsByPointsBounds required_capability: spatial_grid From 71dc6a3c6864325e19412175b48647e9118cfc60 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 20 May 2025 14:55:22 +0200 Subject: [PATCH 29/34] Fix new tests for serverless --- .../src/main/resources/spatial-grid.csv-spec | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index 1b3d6aa114d72..2828c0273fba4 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -906,17 +906,18 @@ required_capability: spatial_grid FROM airports | EVAL geohex = ST_GEOHEX(location, 1, TO_GEOSHAPE("POLYGON((0.0 30.0, 12.0 30.0, 12.0 60.0, 0.0 60.0, 0.0 30.0))")) -| WHERE ST_GEOHEX_TO_STRING(geohex) == "811f3ffffffffff" +| WHERE ST_GEOHEX_TO_STRING(geohex) == "8108bffffffffff" | EVAL geohexString = ST_GEOHEX_TO_STRING(ST_GEOHEX(location, 1)) | KEEP abbrev, location, geohexString +| SORT abbrev ASC ; abbrev:keyword | location:geo_point | geohexString:keyword -BRE | POINT (8.7858617703132 53.052287104156) | 811f3ffffffffff -GOT | POINT (12.2938269092573 57.6857493534879) | 811f3ffffffffff -CPH | POINT (12.6493508684508 55.6285017221528) | 811f3ffffffffff -HAM | POINT (10.005647830925 53.6320011640866) | 811f3ffffffffff -TXL | POINT (13.2903090925074 52.5544287044101) | 811f3ffffffffff +ARN | POINT (17.9307299016916 59.6511203397372) | 8108bffffffffff +BMA | POINT (17.9456175406145 59.3555902065112) | 8108bffffffffff +NRK | POINT (16.2339407695814 58.5833805017541) | 8108bffffffffff +NYO | POINT (16.9216055584254 58.7851041303448) | 8108bffffffffff +TLL | POINT (24.798964869983 59.4165014697451) | 8108bffffffffff ; gridGeohexByBounds @@ -927,12 +928,13 @@ FROM airports | EVAL geohex = ST_GEOHEX(location, 1, TO_GEOSHAPE("POLYGON((0.0 30.0, 12.0 30.0, 12.0 60.0, 0.0 60.0, 0.0 30.0))")) | EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) | KEEP abbrev, location, geohex, geohexString +| SORT abbrev ASC ; abbrev:keyword | location:geo_point | geohex:long | geohexString:keyword RTW | POINT (46.035023249891 51.5606456508842) | null | null -XMN | POINT (118.12696884672 24.537192570557) | null | null TIP | POINT (13.1442589810713 32.6691695504993) | 582085853791125503 | 813fbffffffffff +XMN | POINT (118.12696884672 24.537192570557) | null | null ; gridGeohexStatsByPointsBounds From 481f5bbc4afd1a14ecdaebf0a94cc8f6bc3a05fb Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 20 May 2025 18:35:32 +0200 Subject: [PATCH 30/34] Another test for serverless --- .../src/main/resources/spatial-grid.csv-spec | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index 2828c0273fba4..8b77deda2b16d 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -937,6 +937,27 @@ TIP | POINT (13.1442589810713 32.6691695504993) | 582085853791125503 XMN | POINT (118.12696884672 24.537192570557) | null | null ; +literalGridGeohexByBounds +required_capability: spatial_grid + +ROW location = ["POINT (46.035023249891 51.5606456508842)", "POINT (13.1442589810713 32.6691695504993)", "POINT (118.12696884672 24.537192570557)"] +| MV_EXPAND location +| EVAL location = TO_GEOPOINT(location) +| EVAL geohex = ST_GEOHEX(location, 1) +| EVAL geohexBounded = ST_GEOHEX(location, 1, TO_GEOSHAPE("POLYGON((0.0 30.0, 12.0 30.0, 12.0 60.0, 0.0 60.0, 0.0 30.0))")) +| EVAL geohex = ST_GEOHEX_TO_STRING(geohex) +| EVAL geohexBounded = ST_GEOHEX_TO_STRING(geohexBounded) +| EVAL geohexShape = ST_GEOHEX_TO_GEOSHAPE(geohex) +| KEEP location, geohex, geohexBounded, geohexShape +| SORT geohex ASC +; + +location:geo_point | geohex:keyword | geohexBounded:keyword | geohexShape:geo_shape +POINT (46.035023249891 51.5606456508842) | 8110bffffffffff | null | POLYGON ((42.136829069634125 51.40943727610449, 47.038222832332735 48.33994165728296, 53.670493635625505 49.37211750883398, 56.286117998753014 53.74532256646542, 51.15131422930829 57.15637211465772, 43.547481617187756 55.820803924848654, 42.136829069634125 51.40943727610449)) +POINT (13.1442589810713 32.6691695504993) | 813fbffffffffff | 813fbffffffffff | POLYGON ((8.974635637589913 30.254840780701706, 9.380676605201614 25.60370257696876, 13.915183885634578 23.45043771532035, 18.351304577591982 25.86678026136113, 18.343416368196834 30.62734805513404, 13.488580338198277 32.87501547725471, 8.974635637589913 30.254840780701706)) +POINT (118.12696884672 24.537192570557) | 8141bffffffffff | null | POLYGON ((121.34751445935747 26.200276060455465, 120.50339385995798 29.892985338693542, 116.26130043917948 31.68090796798786, 112.74092235558841 29.367231998154967, 113.70376749169584 25.199133186716526, 117.99047716641066 23.5089519597363, 119.64146543031175 24.728661050965922, 121.34751445935747 26.200276060455465)) +; + gridGeohexStatsByPointsBounds required_capability: spatial_grid From 44eca39c85cb9a757fc144f44d8487188e4c2bf9 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Tue, 20 May 2025 18:38:23 +0200 Subject: [PATCH 31/34] Check if the issue is related to crossing the dateline --- .../function/scalar/spatial/GeoHexBoundedPredicate.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/GeoHexBoundedPredicate.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/GeoHexBoundedPredicate.java index 500a218e956f9..6731d0e7cf5c3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/GeoHexBoundedPredicate.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/GeoHexBoundedPredicate.java @@ -21,6 +21,8 @@ public class GeoHexBoundedPredicate { GeoHexBoundedPredicate(GeoBoundingBox bbox) { this.crossesDateline = bbox.right() < bbox.left(); + // TODO remove this once we get serverless flaky tests to pass + assert this.crossesDateline == false; this.bbox = bbox; scratch = new GeoBoundingBox(new org.elasticsearch.common.geo.GeoPoint(), new org.elasticsearch.common.geo.GeoPoint()); } From 742d46184e1c3d652026d9396f088d5b145f5b4d Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Wed, 21 May 2025 12:31:00 +0200 Subject: [PATCH 32/34] Remove support for grid TO_GEOSHAPE functions --- .../src/main/resources/spatial-grid.csv-spec | 381 +++++------------- .../StGeohashToGeoShapeFromLongEvaluator.java | 124 ------ ...tGeohashToGeoShapeFromStringEvaluator.java | 144 ------- .../StGeohexToGeoShapeFromLongEvaluator.java | 124 ------ ...StGeohexToGeoShapeFromStringEvaluator.java | 144 ------- .../StGeotileToGeoShapeFromLongEvaluator.java | 124 ------ ...tGeotileToGeoShapeFromStringEvaluator.java | 144 ------- .../esql/expression/ExpressionWritables.java | 8 +- .../function/EsqlFunctionRegistry.java | 6 - .../scalar/spatial/StGeohashToGeoShape.java | 103 ----- .../scalar/spatial/StGeohexToGeoShape.java | 122 ------ .../scalar/spatial/StGeotileToGeoShape.java | 114 ------ .../spatial/StGeohashToGeoShapeTests.java | 64 --- .../spatial/StGeohexToGeoShapeTests.java | 64 --- .../spatial/StGeotileToGeoShapeTests.java | 64 --- 15 files changed, 110 insertions(+), 1620 deletions(-) delete mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromLongEvaluator.java delete mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java delete mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromLongEvaluator.java delete mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java delete mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromLongEvaluator.java delete mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java delete mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java delete mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java delete mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java delete mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java delete mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java delete mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index 8b77deda2b16d..3558d1208a433 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -32,32 +32,6 @@ geohash:long | geohashString:keyword // end::geohash_to_string-result[] ; -geohashStringToGeoShape -required_capability: spatial_grid - -// tag::geohash_to_geoshape[] -ROW geohash = "u3bu" -| EVAL boundary = ST_GEOHASH_TO_GEOSHAPE(geohash) -// end::geohash_to_geoshape[] -; - -// tag::geohash_to_geoshape-result[] -geohash:keyword | boundary:geo_shape -u3bu | POLYGON((12.3046875 55.546875, 12.65625 55.546875, 12.65625 55.72265625, 12.3046875 55.72265625, 12.3046875 55.546875)) -// end::geohash_to_geoshape-result[] -; - -geohashLongToGeoShape -required_capability: spatial_grid - -ROW geohash = TO_LONG(13686180) -| EVAL boundary = ST_GEOHASH_TO_GEOSHAPE(geohash) -; - -geohash:long | boundary:geo_shape -13686180 | POLYGON((12.3046875 55.546875, 12.65625 55.546875, 12.65625 55.72265625, 12.3046875 55.72265625, 12.3046875 55.546875)) -; - geohashLiteral required_capability: spatial_grid @@ -107,23 +81,6 @@ POINT (12.6493508684508 55.6285017221528) | 4 | 13686180 | u POINT (12.6493508684508 55.6285017221528) | 5 | 437958005 | u3bur ; -geohashLiteralMvBoundary -required_capability: spatial_grid - -ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] -| MV_EXPAND precision -| EVAL geohash = ST_GEOHASH_TO_STRING(ST_GEOHASH(location, precision)) -| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) -; - -location:geo_point | precision:integer | geohash:keyword | cellBoundary:geo_shape -POINT (12.6493508684508 55.6285017221528) | 1 | u | POLYGON((0.0 45.0, 45.0 45.0, 45.0 90.0, 0.0 90.0, 0.0 45.0)) -POINT (12.6493508684508 55.6285017221528) | 2 | u3 | POLYGON((11.25 50.625, 22.5 50.625, 22.5 56.25, 11.25 56.25, 11.25 50.625)) -POINT (12.6493508684508 55.6285017221528) | 3 | u3b | POLYGON((11.25 54.84375, 12.65625 54.84375, 12.65625 56.25, 11.25 56.25, 11.25 54.84375)) -POINT (12.6493508684508 55.6285017221528) | 4 | u3bu | POLYGON((12.3046875 55.546875, 12.65625 55.546875, 12.65625 55.72265625, 12.3046875 55.72265625, 12.3046875 55.546875)) -POINT (12.6493508684508 55.6285017221528) | 5 | u3bur | POLYGON((12.6123046875 55.5908203125, 12.65625 55.5908203125, 12.65625 55.634765625, 12.6123046875 55.634765625, 12.6123046875 55.5908203125)) -; - geohashField required_capability: spatial_grid @@ -211,23 +168,22 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohash | EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) -| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) -| KEEP count, centroid, geohashString, cellBoundary +| KEEP count, centroid, geohashString | SORT count DESC, geohashString ASC ; -count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape -19 | POINT (6.360728044651057 47.94084087577894) | u0 | POLYGON((0.0 45.0, 11.25 45.0, 11.25 50.625, 0.0 50.625, 0.0 45.0)) -10 | POINT (15.350638423115015 47.80751353036612) | u2 | POLYGON((11.25 45.0, 22.5 45.0, 22.5 50.625, 11.25 50.625, 11.25 45.0)) -9 | POINT (18.5217544157058 42.1394603792578) | sr | POLYGON((11.25 39.375, 22.5 39.375, 22.5 45.0, 11.25 45.0, 11.25 39.375)) -8 | POINT (6.351574736181647 51.8981519783847) | u1 | POLYGON((0.0 50.625, 11.25 50.625, 11.25 56.25, 0.0 56.25, 0.0 50.625)) -7 | POINT (5.268637698941997 42.747250193330856) | sp | POLYGON((0.0 39.375, 11.25 39.375, 11.25 45.0, 0.0 45.0, 0.0 39.375)) -7 | POINT (17.092350951528974 53.365471504096476) | u3 | POLYGON((11.25 50.625, 22.5 50.625, 22.5 56.25, 11.25 56.25, 11.25 50.625)) -5 | POINT (16.2651440910995 58.812188878655434) | u6 | POLYGON((11.25 56.25, 22.5 56.25, 22.5 61.875, 11.25 61.875, 11.25 56.25)) -4 | POINT (7.7012718468904495 36.39783004182391) | sn | POLYGON((0.0 33.75, 11.25 33.75, 11.25 39.375, 0.0 39.375, 0.0 33.75)) -3 | POINT (14.222751930356026 37.168446206487715) | sq | POLYGON((11.25 33.75, 22.5 33.75, 22.5 39.375, 11.25 39.375, 11.25 33.75)) -3 | POINT (7.318722177296877 59.788265260867774) | u4 | POLYGON((0.0 56.25, 11.25 56.25, 11.25 61.875, 0.0 61.875, 0.0 56.25)) -2 | POINT (16.706149326637387 32.37822346854955) | sm | POLYGON((11.25 28.125, 22.5 28.125, 22.5 33.75, 11.25 33.75, 11.25 28.125)) +count:long | centroid:geo_point | geohashString:keyword +19 | POINT (6.360728044651057 47.94084087577894) | u0 +10 | POINT (15.350638423115015 47.80751353036612) | u2 +9 | POINT (18.5217544157058 42.1394603792578) | sr +8 | POINT (6.351574736181647 51.8981519783847) | u1 +7 | POINT (5.268637698941997 42.747250193330856) | sp +7 | POINT (17.092350951528974 53.365471504096476) | u3 +5 | POINT (16.2651440910995 58.812188878655434) | u6 +4 | POINT (7.7012718468904495 36.39783004182391) | sn +3 | POINT (14.222751930356026 37.168446206487715) | sq +3 | POINT (7.318722177296877 59.788265260867774) | u4 +2 | POINT (16.706149326637387 32.37822346854955) | sm ; gridGeohashStatsByPointsBounds @@ -242,37 +198,22 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohash | EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) -| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) -| KEEP count, centroid, geohashString, cellBoundary +| KEEP count, centroid, geohashString | SORT count DESC, geohashString ASC ; -count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape -19 | POINT (6.360728044651057 47.94084087577894) | u0 | POLYGON((0.0 45.0, 11.25 45.0, 11.25 50.625, 0.0 50.625, 0.0 45.0)) -10 | POINT (15.350638423115015 47.80751353036612) | u2 | POLYGON((11.25 45.0, 22.5 45.0, 22.5 50.625, 11.25 50.625, 11.25 45.0)) -9 | POINT (18.5217544157058 42.1394603792578) | sr | POLYGON((11.25 39.375, 22.5 39.375, 22.5 45.0, 11.25 45.0, 11.25 39.375)) -8 | POINT (6.351574736181647 51.8981519783847) | u1 | POLYGON((0.0 50.625, 11.25 50.625, 11.25 56.25, 0.0 56.25, 0.0 50.625)) -7 | POINT (5.268637698941997 42.747250193330856) | sp | POLYGON((0.0 39.375, 11.25 39.375, 11.25 45.0, 0.0 45.0, 0.0 39.375)) -7 | POINT (17.092350951528974 53.365471504096476) | u3 | POLYGON((11.25 50.625, 22.5 50.625, 22.5 56.25, 11.25 56.25, 11.25 50.625)) -5 | POINT (16.2651440910995 58.812188878655434) | u6 | POLYGON((11.25 56.25, 22.5 56.25, 22.5 61.875, 11.25 61.875, 11.25 56.25)) -4 | POINT (7.7012718468904495 36.39783004182391) | sn | POLYGON((0.0 33.75, 11.25 33.75, 11.25 39.375, 0.0 39.375, 0.0 33.75)) -3 | POINT (14.222751930356026 37.168446206487715) | sq | POLYGON((11.25 33.75, 22.5 33.75, 22.5 39.375, 11.25 39.375, 11.25 33.75)) -3 | POINT (7.318722177296877 59.788265260867774) | u4 | POLYGON((0.0 56.25, 11.25 56.25, 11.25 61.875, 0.0 61.875, 0.0 56.25)) -2 | POINT (16.706149326637387 32.37822346854955) | sm | POLYGON((11.25 28.125, 22.5 28.125, 22.5 33.75, 11.25 33.75, 11.25 28.125)) -; - -gridGeohashDocsFromCell -required_capability: spatial_grid - -FROM airports -| WHERE ST_INTERSECTS(location, ST_GEOHASH_TO_GEOSHAPE("u1")) -| STATS - count = COUNT(*), - centroid = ST_CENTROID_AGG(location) -; - -count:long | centroid:geo_point -8 | POINT (6.351574736181647 51.8981519783847) +count:long | centroid:geo_point | geohashString:keyword +19 | POINT (6.360728044651057 47.94084087577894) | u0 +10 | POINT (15.350638423115015 47.80751353036612) | u2 +9 | POINT (18.5217544157058 42.1394603792578) | sr +8 | POINT (6.351574736181647 51.8981519783847) | u1 +7 | POINT (5.268637698941997 42.747250193330856) | sp +7 | POINT (17.092350951528974 53.365471504096476) | u3 +5 | POINT (16.2651440910995 58.812188878655434) | u6 +4 | POINT (7.7012718468904495 36.39783004182391) | sn +3 | POINT (14.222751930356026 37.168446206487715) | sq +3 | POINT (7.318722177296877 59.788265260867774) | u4 +2 | POINT (16.706149326637387 32.37822346854955) | sm ; gridGeohashStatsByWhereUK @@ -286,14 +227,13 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohash | EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) -| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) -| KEEP count, centroid, geohashString, cellBoundary +| KEEP count, centroid, geohashString | SORT count DESC ; -count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape -14 | POINT (-2.5644131543646966 53.38093495994274) | gc | POLYGON((-11.25 50.625, 0.0 50.625, 0.0 56.25, -11.25 56.25, -11.25 50.625)) -3 | POINT (-2.7510103583335876 58.79020635969937) | gf | POLYGON((-11.25 56.25, 0.0 56.25, 0.0 61.875, -11.25 61.875, -11.25 56.25)) +count:long | centroid:geo_point | geohashString:keyword +14 | POINT (-2.5644131543646966 53.38093495994274) | gc +3 | POINT (-2.7510103583335876 58.79020635969937) | gf ; gridGeohashStatsByBoundsUK @@ -308,17 +248,16 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohash | EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) -| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) -| KEEP count, centroid, geohashString, cellBoundary +| KEEP count, centroid, geohashString | SORT count DESC, geohashString ASC ; -count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape -19 | POINT (6.360728044651057 47.94084087577894) | u0 | POLYGON((0.0 45.0, 11.25 45.0, 11.25 50.625, 0.0 50.625, 0.0 45.0)) -17 | POINT (-3.5034258844440473 53.25306422789307) | gc | POLYGON((-11.25 50.625, 0.0 50.625, 0.0 56.25, -11.25 56.25, -11.25 50.625)) -8 | POINT (6.351574736181647 51.8981519783847) | u1 | POLYGON((0.0 50.625, 11.25 50.625, 11.25 56.25, 0.0 56.25, 0.0 50.625)) -3 | POINT (-2.7510103583335876 58.79020635969937) | gf | POLYGON((-11.25 56.25, 0.0 56.25, 0.0 61.875, -11.25 61.875, -11.25 56.25)) -3 | POINT (7.318722177296877 59.788265260867774) | u4 | POLYGON((0.0 56.25, 11.25 56.25, 11.25 61.875, 0.0 61.875, 0.0 56.25)) +count:long | centroid:geo_point | geohashString:keyword +19 | POINT (6.360728044651057 47.94084087577894) | u0 +17 | POINT (-3.5034258844440473 53.25306422789307) | gc +8 | POINT (6.351574736181647 51.8981519783847) | u1 +3 | POINT (-2.7510103583335876 58.79020635969937) | gf +3 | POINT (7.318722177296877 59.788265260867774) | u4 ; gridGeohashInStatsBy @@ -399,21 +338,6 @@ geotile:long | geotileString:keyword // end::geotile_to_string-result[] ; -geotileStringToGeoshape -required_capability: spatial_grid - -// tag::geotile_to_geoshape[] -ROW geotile = "4/8/5" -| EVAL boundary = ST_GEOTILE_TO_GEOSHAPE(geotile) -// end::geotile_to_geoshape[] -; - -// tag::geotile_to_geoshape-result[] -geotile:keyword | boundary:geo_shape -4/8/5 | POLYGON((0.0 40.979898069620134, 22.5 40.979898069620134, 22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 40.979898069620134)) -// end::geotile_to_geoshape-result[] -; - geotileLiteral required_capability: spatial_grid @@ -463,23 +387,6 @@ POINT (12.6493508684508 55.6285017221528) | 4 | 1152921508901814 POINT (12.6493508684508 55.6285017221528) | 5 | 1441151889885364234 | 5/17/10 ; -geotileLiteralMvBoundary -required_capability: spatial_grid - -ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] -| MV_EXPAND precision -| EVAL geotile = ST_GEOTILE_TO_STRING(ST_GEOTILE(location, precision)) -| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) -; - -location:geo_point | precision:integer | geotile:keyword | cellBoundary:geo_shape -POINT (12.6493508684508 55.6285017221528) | 1 | 1/1/0 | POLYGON((0.0 0.0, 180.0 0.0, 180.0 85.0511287798066, 0.0 85.0511287798066, 0.0 0.0)) -POINT (12.6493508684508 55.6285017221528) | 2 | 2/2/1 | POLYGON((0.0 0.0, 90.0 0.0, 90.0 66.51326044311186, 0.0 66.51326044311186, 0.0 0.0)) -POINT (12.6493508684508 55.6285017221528) | 3 | 3/4/2 | POLYGON((0.0 40.979898069620134, 45.0 40.979898069620134, 45.0 66.51326044311186, 0.0 66.51326044311186, 0.0 40.979898069620134)) -POINT (12.6493508684508 55.6285017221528) | 4 | 4/8/5 | POLYGON((0.0 40.979898069620134, 22.5 40.979898069620134, 22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 40.979898069620134)) -POINT (12.6493508684508 55.6285017221528) | 5 | 5/17/10 | POLYGON((11.25 48.922499263758255, 22.5 48.922499263758255, 22.5 55.77657301866769, 11.25 55.77657301866769, 11.25 48.922499263758255)) -; - geotileField required_capability: spatial_grid @@ -557,14 +464,13 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geotile | EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) -| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) | SORT count DESC, geotileString ASC -| KEEP count, centroid, geotileString, cellBoundary +| KEEP count, centroid, geotileString ; -count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape -100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 | POLYGON((0.0 40.979898069620134, 45.0 40.979898069620134, 45.0 66.51326044311186, 0.0 66.51326044311186, 0.0 40.979898069620134)) -79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 | POLYGON((0.0 0.0, 45.0 0.0, 45.0 40.979898069620134, 0.0 40.979898069620134, 0.0 0.0)) +count:long | centroid:geo_point | geotileString:keyword +100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 +79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 ; gridGeotileStatsByPointsBounds @@ -579,28 +485,13 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geotile | EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) -| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) -| KEEP count, centroid, geotileString, cellBoundary +| KEEP count, centroid, geotileString | SORT count DESC, geotileString ASC ; -count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape -100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 | POLYGON((0.0 40.979898069620134, 45.0 40.979898069620134, 45.0 66.51326044311186, 0.0 66.51326044311186, 0.0 40.979898069620134)) -79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 | POLYGON((0.0 0.0, 45.0 0.0, 45.0 40.979898069620134, 0.0 40.979898069620134, 0.0 0.0)) -; - -gridGeotileDocsFromCell -required_capability: spatial_grid - -FROM airports -| WHERE ST_INTERSECTS(location, ST_GEOTILE_TO_GEOSHAPE("3/4/3")) -| STATS - count = COUNT(*), - centroid = ST_CENTROID_AGG(location) -; - -count:long | centroid:geo_point -79 | POINT (24.516750878736943 23.93036561181085) +count:long | centroid:geo_point | geotileString:keyword +100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 +79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 ; gridGeotileStatsByWhereUK @@ -614,14 +505,13 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geotile | EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) -| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) -| KEEP count, centroid, geotileString, cellBoundary +| KEEP count, centroid, geotileString | SORT count DESC ; -count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape -12 | POINT (-2.342151787597686 52.9600293841213) | 4/7/5 | POLYGON((-22.5 40.979898069620134, 0.0 40.979898069620134, 0.0 55.77657301866769, -22.5 55.77657301866769, -22.5 40.979898069620134)) -5 | POINT (-3.2097987569868565 57.63667118176818) | 4/7/4 | POLYGON((-22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 66.51326044311186, -22.5 66.51326044311186, -22.5 55.77657301866769)) +count:long | centroid:geo_point | geotileString:keyword +12 | POINT (-2.342151787597686 52.9600293841213) | 4/7/5 +5 | POINT (-3.2097987569868565 57.63667118176818) | 4/7/4 ; gridGeotileStatsByBoundsUK @@ -636,16 +526,15 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geotile | EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) -| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) -| KEEP count, centroid, geotileString, cellBoundary +| KEEP count, centroid, geotileString | SORT count DESC ; -count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape -56 | POINT (10.54233039047436 47.85997457644304) | 4/8/5 | POLYGON((0.0 40.979898069620134, 22.5 40.979898069620134, 22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 40.979898069620134)) -18 | POINT (-3.5578574100509286 51.27018998377025) | 4/7/5 | POLYGON((-22.5 40.979898069620134, 0.0 40.979898069620134, 0.0 55.77657301866769, -22.5 55.77657301866769, -22.5 40.979898069620134)) -11 | POINT (14.310833624648778 59.85619530801407) | 4/8/4 | POLYGON((0.0 55.77657301866769, 22.5 55.77657301866769, 22.5 66.51326044311186, 0.0 66.51326044311186, 0.0 55.77657301866769)) -7 | POINT (-6.466632609122565 59.19681839378817) | 4/7/4 | POLYGON((-22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 66.51326044311186, -22.5 66.51326044311186, -22.5 55.77657301866769)) +count:long | centroid:geo_point | geotileString:keyword +56 | POINT (10.54233039047436 47.85997457644304) | 4/8/5 +18 | POINT (-3.5578574100509286 51.27018998377025) | 4/7/5 +11 | POINT (14.310833624648778 59.85619530801407) | 4/8/4 +7 | POINT (-6.466632609122565 59.19681839378817) | 4/7/4 ; gridGeotileInStatsBy @@ -719,21 +608,6 @@ geohex:long | geohexString:keyword // end::geohex_to_string-result[] ; -geohexStringToGeoshape -required_capability: spatial_grid - -// tag::geohex_to_geoshape[] -ROW geohex = "841f059ffffffff" -| EVAL boundary = ST_GEOHEX_TO_GEOSHAPE(geohex) -// end::geohex_to_geoshape[] -; - -// tag::geohex_to_geoshape-result[] -geohex:keyword | boundary:geo_shape -841f059ffffffff | POLYGON ((12.353546327258265 55.80335405461356, 12.2434612967008 55.60502874054935, 12.51733872608954 55.470800201545316, 12.901880149865134 55.53443156197633, 13.014270156228921 55.73262985778208, 12.739822958959069 55.8673267391136, 12.353546327258265 55.80335405461356)) -// end::geohex_to_geoshape-result[] -; - geohexLiteral required_capability: spatial_grid @@ -783,23 +657,6 @@ POINT (12.6493508684508 55.6285017221528) | 4 | 5950208951273390 POINT (12.6493508684508 55.6285017221528) | 5 | 599524487238516735 | 851f0583fffffff ; -geohexLiteralMvBoundary -required_capability: spatial_grid - -ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] -| MV_EXPAND precision -| EVAL geohex = ST_GEOHEX_TO_STRING(ST_GEOHEX(location, precision)) -| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) -; - -location:geo_point | precision:integer | geohex:keyword | cellBoundary:geo_shape -POINT (12.6493508684508 55.6285017221528) | 1 | 811f3ffffffffff | POLYGON ((5.523646549290313 55.70676846515226, 6.259687055981993 51.96477015603749, 12.345747364400065 50.55427508726938, 18.289963485942284 52.81905199947076, 18.2752359517578 56.63295271905082, 11.555977692900722 58.13053116585142, 5.523646549290313 55.70676846515226)) -POINT (12.6493508684508 55.6285017221528) | 2 | 821f07fffffffff | POLYGON ((10.06569233741819 55.3948787035456, 9.374530816292083 53.97551370235174, 11.245170492278875 53.03203973205439, 13.839528609232428 53.48724516123688, 14.640206584543728 54.90218190493179, 12.739822958959062 55.8673267391136, 10.06569233741819 55.3948787035456)) -POINT (12.6493508684508 55.6285017221528) | 3 | 831f05fffffffff | POLYGON ((11.860105203878488 55.53944935104936, 11.917786510985744 55.0057489060893, 12.839846498886947 54.79854371636354, 13.717124800902113 55.12308086302377, 13.674892957473272 55.65810153974231, 12.739822958959069 55.8673267391136, 11.860105203878488 55.53944935104936)) -POINT (12.6493508684508 55.6285017221528) | 4 | 841f059ffffffff | POLYGON ((12.353546327258265 55.80335405461356, 12.2434612967008 55.60502874054935, 12.51733872608954 55.470800201545316, 12.901880149865134 55.53443156197633, 13.014270156228921 55.73262985778208, 12.739822958959069 55.8673267391136, 12.353546327258265 55.80335405461356)) -POINT (12.6493508684508 55.6285017221528) | 5 | 851f0583fffffff | POLYGON ((12.494766876566144 55.69864155255122, 12.502309582573728 55.6227995792834, 12.635566668537882 55.59351730049433, 12.761550811198047 55.640035539252175, 12.754326292782508 55.71590456460875, 12.62079911077343 55.745228479933665, 12.494766876566144 55.69864155255122)) -; - geohexField required_capability: spatial_grid @@ -882,23 +739,22 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohex | EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) -| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) | SORT count DESC, geohexString ASC -| KEEP count, centroid, geohexString, cellBoundary +| KEEP count, centroid, geohexString ; -count:long | centroid:geo_point | geohexString:keyword | cellBoundary:geo_shape -22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff | POLYGON ((1.1885095534434493 49.47027919866873, 2.026568965384636 45.18424868970643, 7.509948481928886 43.786609353945, 12.677317810359858 46.40695745798227, 12.345747364400065 50.55427508726938, 6.259687055981993 51.96477015603749, 3.6300086390995467 50.6104633125695, 1.1885095534434493 49.47027919866873)) -17 | POINT (-0.7606179875266903 52.86413913565304) | 81197ffffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -6.436337296790312 55.3773904155485, -4.889760342933795 51.22372845966177, 1.1885095534434493 49.47027919866873, 3.6300086390995365 50.610463312569514, 6.259687055981993 51.96477015603749, 5.523646549290304 55.70676846515228, -0.9315871635106163 57.689497374592854)) -7 | POINT (2.475211258445467 41.32352174592337) | 81397ffffffffff | POLYGON ((-2.4177958307002347 42.54047996565121, -1.416234262837718 38.1159967227654, 0.2387159546288331 37.58884624349159, 3.543589356987798 36.59789814478598, 8.045142114241353 39.40213636897177, 7.509948481928886 43.786609353945, 2.026568965384636 45.18424868970643, -2.4177958307002347 42.54047996565121)) -6 | POINT (11.75047050230205 42.351422344800085) | 811ebffffffffff | POLYGON ((7.509948481928886 43.786609353945, 8.045142114241353 39.40213636897177, 13.244313475659823 37.5237123657852, 18.325260281104846 39.988177963363235, 18.314740441319 44.47067958889503, 12.677317810359858 46.40695745798227, 7.509948481928886 43.786609353945)) -5 | POINT (18.766171680763364 59.15833930950612) | 8108bffffffffff | POLYGON ((11.080660058482376 61.54051460002519, 11.555977692900722 58.13053116585142, 18.2752359517578 56.63295271905082, 25.082722326707877 58.4015448703527, 24.517172437523495 62.47811345192472, 17.53544630840839 63.800792653212156, 15.771773841154092 62.88996835796253, 11.080660058482376 61.54051460002519)) -5 | POINT (11.404999259859324 54.510593589395285) | 811f3ffffffffff | POLYGON ((5.523646549290313 55.70676846515226, 6.259687055981993 51.96477015603749, 12.345747364400065 50.55427508726938, 18.289963485942284 52.81905199947076, 18.2752359517578 56.63295271905082, 11.555977692900722 58.13053116585142, 5.523646549290313 55.70676846515226)) -4 | POINT (5.167026452254504 59.81037143385038) | 8109bffffffffff | POLYGON ((4.012620898449951 63.32706132801842, -2.297526087621831 61.54550957788076, -0.9315871635106163 57.689497374592854, 5.523646549290304 55.70676846515228, 11.555977692900722 58.13053116585142, 11.080660058482376 61.54051460002519, 8.644221197607186 61.8908384753262, 4.012620898449951 63.32706132801842)) -4 | POINT (-1.1871178611181676 35.77457194332965) | 81383ffffffffff | POLYGON ((-5.442348460730093 35.12442405176796, -4.341769247156951 30.69897412778907, -1.2408020165138167 29.828776159725596, 0.26094682603113584 29.300374659234986, 4.204173995672654 32.11010693139568, 3.543589356987798 36.59789814478598, 0.2387159546288331 37.58884624349159, -1.416234262837718 38.1159967227654, -5.442348460730093 35.12442405176796)) -3 | POINT (-1.1497433669865131 45.83295159973204) | 81187ffffffffff | POLYGON ((-4.889760342933795 51.22372845966177, -9.724736207832692 48.43009421958323, -8.101589192291552 44.0506310521871, -2.4177958307002347 42.54047996565121, 2.026568965384605 45.18424868970644, 1.1885095534434493 49.47027919866873, -4.889760342933795 51.22372845966177)) -3 | POINT (9.197671310976148 36.29719984252006) | 81387ffffffffff | POLYGON ((3.543589356987798 36.59789814478598, 4.204173995672654 32.11010693139568, 8.974635637589913 30.254840780701706, 13.488580338198277 32.87501547725471, 13.244313475659823 37.5237123657852, 8.045142114241353 39.40213636897177, 3.543589356987798 36.59789814478598)) -1 | POINT (13.144258903339505 32.66916951164603) | 813fbffffffffff | POLYGON ((8.974635637589913 30.254840780701706, 9.380676605201614 25.60370257696876, 13.915183885634578 23.45043771532035, 18.351304577591982 25.86678026136113, 18.343416368196834 30.62734805513404, 13.488580338198277 32.87501547725471, 8.974635637589913 30.254840780701706)) +count:long | centroid:geo_point | geohexString:keyword +22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff +17 | POINT (-0.7606179875266903 52.86413913565304) | 81197ffffffffff +7 | POINT (2.475211258445467 41.32352174592337) | 81397ffffffffff +6 | POINT (11.75047050230205 42.351422344800085) | 811ebffffffffff +5 | POINT (18.766171680763364 59.15833930950612) | 8108bffffffffff +5 | POINT (11.404999259859324 54.510593589395285) | 811f3ffffffffff +4 | POINT (5.167026452254504 59.81037143385038) | 8109bffffffffff +4 | POINT (-1.1871178611181676 35.77457194332965) | 81383ffffffffff +3 | POINT (-1.1497433669865131 45.83295159973204) | 81187ffffffffff +3 | POINT (9.197671310976148 36.29719984252006) | 81387ffffffffff +1 | POINT (13.144258903339505 32.66916951164603) | 813fbffffffffff ; gridGeohexQueryBounds @@ -947,15 +803,14 @@ ROW location = ["POINT (46.035023249891 51.5606456508842)", "POINT (13.144258981 | EVAL geohexBounded = ST_GEOHEX(location, 1, TO_GEOSHAPE("POLYGON((0.0 30.0, 12.0 30.0, 12.0 60.0, 0.0 60.0, 0.0 30.0))")) | EVAL geohex = ST_GEOHEX_TO_STRING(geohex) | EVAL geohexBounded = ST_GEOHEX_TO_STRING(geohexBounded) -| EVAL geohexShape = ST_GEOHEX_TO_GEOSHAPE(geohex) -| KEEP location, geohex, geohexBounded, geohexShape +| KEEP location, geohex, geohexBounded | SORT geohex ASC ; -location:geo_point | geohex:keyword | geohexBounded:keyword | geohexShape:geo_shape -POINT (46.035023249891 51.5606456508842) | 8110bffffffffff | null | POLYGON ((42.136829069634125 51.40943727610449, 47.038222832332735 48.33994165728296, 53.670493635625505 49.37211750883398, 56.286117998753014 53.74532256646542, 51.15131422930829 57.15637211465772, 43.547481617187756 55.820803924848654, 42.136829069634125 51.40943727610449)) -POINT (13.1442589810713 32.6691695504993) | 813fbffffffffff | 813fbffffffffff | POLYGON ((8.974635637589913 30.254840780701706, 9.380676605201614 25.60370257696876, 13.915183885634578 23.45043771532035, 18.351304577591982 25.86678026136113, 18.343416368196834 30.62734805513404, 13.488580338198277 32.87501547725471, 8.974635637589913 30.254840780701706)) -POINT (118.12696884672 24.537192570557) | 8141bffffffffff | null | POLYGON ((121.34751445935747 26.200276060455465, 120.50339385995798 29.892985338693542, 116.26130043917948 31.68090796798786, 112.74092235558841 29.367231998154967, 113.70376749169584 25.199133186716526, 117.99047716641066 23.5089519597363, 119.64146543031175 24.728661050965922, 121.34751445935747 26.200276060455465)) +location:geo_point | geohex:keyword | geohexBounded:keyword +POINT (46.035023249891 51.5606456508842) | 8110bffffffffff | null +POINT (13.1442589810713 32.6691695504993) | 813fbffffffffff | 813fbffffffffff +POINT (118.12696884672 24.537192570557) | 8141bffffffffff | null ; gridGeohexStatsByPointsBounds @@ -970,39 +825,23 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohex | EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) -| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) -| KEEP count, centroid, geohexString, cellBoundary +| KEEP count, centroid, geohexString | SORT count DESC, geohexString ASC ; -count:long | centroid:geo_point | geohexString:keyword | cellBoundary:geo_shape -22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff | POLYGON ((1.1885095534434493 49.47027919866873, 2.026568965384636 45.18424868970643, 7.509948481928886 43.786609353945, 12.677317810359858 46.40695745798227, 12.345747364400065 50.55427508726938, 6.259687055981993 51.96477015603749, 3.6300086390995467 50.6104633125695, 1.1885095534434493 49.47027919866873)) -17 | POINT (-0.7606179875266903 52.86413913565304) | 81197ffffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -6.436337296790312 55.3773904155485, -4.889760342933795 51.22372845966177, 1.1885095534434493 49.47027919866873, 3.6300086390995365 50.610463312569514, 6.259687055981993 51.96477015603749, 5.523646549290304 55.70676846515228, -0.9315871635106163 57.689497374592854)) -7 | POINT (2.475211258445467 41.32352174592337) | 81397ffffffffff | POLYGON ((-2.4177958307002347 42.54047996565121, -1.416234262837718 38.1159967227654, 0.2387159546288331 37.58884624349159, 3.543589356987798 36.59789814478598, 8.045142114241353 39.40213636897177, 7.509948481928886 43.786609353945, 2.026568965384636 45.18424868970643, -2.4177958307002347 42.54047996565121)) -6 | POINT (11.75047050230205 42.351422344800085) | 811ebffffffffff | POLYGON ((7.509948481928886 43.786609353945, 8.045142114241353 39.40213636897177, 13.244313475659823 37.5237123657852, 18.325260281104846 39.988177963363235, 18.314740441319 44.47067958889503, 12.677317810359858 46.40695745798227, 7.509948481928886 43.786609353945)) -5 | POINT (18.766171680763364 59.15833930950612) | 8108bffffffffff | POLYGON ((11.080660058482376 61.54051460002519, 11.555977692900722 58.13053116585142, 18.2752359517578 56.63295271905082, 25.082722326707877 58.4015448703527, 24.517172437523495 62.47811345192472, 17.53544630840839 63.800792653212156, 15.771773841154092 62.88996835796253, 11.080660058482376 61.54051460002519)) -5 | POINT (11.404999259859324 54.510593589395285) | 811f3ffffffffff | POLYGON ((5.523646549290313 55.70676846515226, 6.259687055981993 51.96477015603749, 12.345747364400065 50.55427508726938, 18.289963485942284 52.81905199947076, 18.2752359517578 56.63295271905082, 11.555977692900722 58.13053116585142, 5.523646549290313 55.70676846515226)) -4 | POINT (5.167026452254504 59.81037143385038) | 8109bffffffffff | POLYGON ((4.012620898449951 63.32706132801842, -2.297526087621831 61.54550957788076, -0.9315871635106163 57.689497374592854, 5.523646549290304 55.70676846515228, 11.555977692900722 58.13053116585142, 11.080660058482376 61.54051460002519, 8.644221197607186 61.8908384753262, 4.012620898449951 63.32706132801842)) -4 | POINT (-1.1871178611181676 35.77457194332965) | 81383ffffffffff | POLYGON ((-5.442348460730093 35.12442405176796, -4.341769247156951 30.69897412778907, -1.2408020165138167 29.828776159725596, 0.26094682603113584 29.300374659234986, 4.204173995672654 32.11010693139568, 3.543589356987798 36.59789814478598, 0.2387159546288331 37.58884624349159, -1.416234262837718 38.1159967227654, -5.442348460730093 35.12442405176796)) -3 | POINT (-1.1497433669865131 45.83295159973204) | 81187ffffffffff | POLYGON ((-4.889760342933795 51.22372845966177, -9.724736207832692 48.43009421958323, -8.101589192291552 44.0506310521871, -2.4177958307002347 42.54047996565121, 2.026568965384605 45.18424868970644, 1.1885095534434493 49.47027919866873, -4.889760342933795 51.22372845966177)) -3 | POINT (9.197671310976148 36.29719984252006) | 81387ffffffffff | POLYGON ((3.543589356987798 36.59789814478598, 4.204173995672654 32.11010693139568, 8.974635637589913 30.254840780701706, 13.488580338198277 32.87501547725471, 13.244313475659823 37.5237123657852, 8.045142114241353 39.40213636897177, 3.543589356987798 36.59789814478598)) -1 | POINT (13.144258903339505 32.66916951164603) | 813fbffffffffff | POLYGON ((8.974635637589913 30.254840780701706, 9.380676605201614 25.60370257696876, 13.915183885634578 23.45043771532035, 18.351304577591982 25.86678026136113, 18.343416368196834 30.62734805513404, 13.488580338198277 32.87501547725471, 8.974635637589913 30.254840780701706)) -; - -// TODO: Fix this test -//gridGeohexDocsFromCell -//required_capability: spatial_grid -// -//FROM airports -//| WHERE ST_INTERSECTS(location, ST_GEOHEX_TO_GEOSHAPE("81397ffffffffff")) -//| STATS -// count = COUNT(*), -// centroid = ST_CENTROID_AGG(location) -//; -// -//count:long | centroid:geo_point -//7 | POINT (2.475211258445467 41.32352174592337) -//; +count:long | centroid:geo_point | geohexString:keyword +22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff +17 | POINT (-0.7606179875266903 52.86413913565304) | 81197ffffffffff +7 | POINT (2.475211258445467 41.32352174592337) | 81397ffffffffff +6 | POINT (11.75047050230205 42.351422344800085) | 811ebffffffffff +5 | POINT (18.766171680763364 59.15833930950612) | 8108bffffffffff +5 | POINT (11.404999259859324 54.510593589395285) | 811f3ffffffffff +4 | POINT (5.167026452254504 59.81037143385038) | 8109bffffffffff +4 | POINT (-1.1871178611181676 35.77457194332965) | 81383ffffffffff +3 | POINT (-1.1497433669865131 45.83295159973204) | 81187ffffffffff +3 | POINT (9.197671310976148 36.29719984252006) | 81387ffffffffff +1 | POINT (13.144258903339505 32.66916951164603) | 813fbffffffffff +; gridGeohexStatsByWhereUK required_capability: spatial_grid @@ -1015,16 +854,15 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohex | EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) -| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) -| KEEP count, centroid, geohexString, cellBoundary +| KEEP count, centroid, geohexString | SORT count DESC, geohexString ASC ; -count:long | centroid:geo_point | geohexString:keyword | cellBoundary:geo_shape -13 | POINT (-2.283508819169723 53.28242553254733) | 81197ffffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -6.436337296790312 55.3773904155485, -4.889760342933795 51.22372845966177, 1.1885095534434493 49.47027919866873, 3.6300086390995365 50.610463312569514, 6.259687055981993 51.96477015603749, 5.523646549290304 55.70676846515228, -0.9315871635106163 57.689497374592854)) -2 | POINT (-3.482485176064074 58.24696456314996) | 81193ffffffffff | POLYGON ((-10.44497754477833 63.09505407752544, -16.37196241724276 60.568693514800756, -13.79164665163863 56.73632442836386, -6.436337296790312 55.3773904155485, -0.9315871635106163 57.689497374592854, -2.297526087621831 61.54550957788076, -10.44497754477833 63.09505407752544)) -1 | POINT (-1.2880607228726149 59.87668995279819) | 8109bffffffffff | POLYGON ((4.012620898449951 63.32706132801842, -2.297526087621831 61.54550957788076, -0.9315871635106163 57.689497374592854, 5.523646549290304 55.70676846515228, 11.555977692900722 58.13053116585142, 11.080660058482376 61.54051460002519, 8.644221197607186 61.8908384753262, 4.012620898449951 63.32706132801842)) -1 | POINT (-6.216169511899352 54.66155751608312) | 81183ffffffffff | POLYGON ((-13.79164665163863 56.73632442836386, -18.841171686388584 53.74020675223833, -16.3823406256948 49.6092693973489, -9.724736207832692 48.43009421958323, -4.889760342933795 51.22372845966177, -6.436337296790312 55.3773904155485, -13.79164665163863 56.73632442836386)) +count:long | centroid:geo_point | geohexString:keyword +13 | POINT (-2.283508819169723 53.28242553254733) | 81197ffffffffff +2 | POINT (-3.482485176064074 58.24696456314996) | 81193ffffffffff +1 | POINT (-1.2880607228726149 59.87668995279819) | 8109bffffffffff +1 | POINT (-6.216169511899352 54.66155751608312) | 81183ffffffffff ; gridGeohexStatsByBoundsUK @@ -1039,26 +877,25 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohex | EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) -| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) -| KEEP count, centroid, geohexString, cellBoundary +| KEEP count, centroid, geohexString | SORT count DESC, geohexString ASC ; -count:long | centroid:geo_point | geohexString:keyword | cellBoundary:geo_shape -5 | POINT (-1.7227098606526852 51.717823022045195) | 82195ffffffffff | POLYGON ((-2.1788859209290505 53.251551050714795, -4.578382413982977 52.792439042763036, -4.889760342933795 51.22372845966177, -2.906527879284175 50.14229216995713, -0.6310947579755295 50.60191112048408, -0.21913743445926337 52.1416808182628, -2.1788859209290505 53.251551050714795)) -4 | POINT (-3.9897833741270006 54.21732849790715) | 821957fffffffff | POLYGON ((-3.9031812914854935 55.840605806464886, -6.436337296790312 55.3773904155485, -6.713499065102683 53.841053788108646, -4.578382413982977 52.792439042763036, -2.1788859209290505 53.251551050714795, -1.7855433613316123 54.76238836624054, -3.9031812914854935 55.840605806464886)) -3 | POINT (-7.885485291481018 52.65633414499462) | 82182ffffffffff | POLYGON ((-6.713499065102683 53.841053788108646, -9.16699332513357 53.28908444969493, -9.362891292036808 51.69686278886942, -7.224493860559402 50.67904691252102, -4.889760342933795 51.22372845966177, -4.578382413982977 52.792439042763036, -6.713499065102683 53.841053788108646)) -3 | POINT (3.0334555450826883 48.842039234004915) | 821fb7fffffffff | POLYGON ((1.1885095534434493 49.47027919866873, 0.7640259623867446 47.90745035042651, 2.458901717447715 46.76373050573097, 4.652435425239358 47.393027403288, 5.163510941569062 48.943763955054884, 3.3847715100589153 49.85377035058955, 1.1885095534434493 49.47027919866873)) -2 | POINT (5.428531668148935 59.585608751513064) | 820987fffffffff | POLYGON ((5.479068693190393 60.92198553471913, 2.767527791540729 60.73321011494055, 2.198216040575142 59.383886486983954, 4.229785449235632 58.25202580757624, 6.766112799653718 58.44709614018101, 7.4384643434389535 59.76718020289119, 5.479068693190393 60.92198553471913)) -2 | POINT (-4.2476349184289575 56.70184155693278) | 82190ffffffffff | POLYGON ((-5.832270115239392 58.353838498476094, -8.508655388670189 57.8811306023458, -8.740899630542538 56.38258811071853, -6.436337296790312 55.3773904155485, -3.9031812914854935 55.840605806464886, -3.536381138969186 57.31728796714347, -5.832270115239392 58.353838498476094)) -2 | POINT (1.4715016074478626 50.863699545152485) | 82194ffffffffff | POLYGON ((2.101313983947425 52.51713397842229, -0.21913743445926337 52.1416808182628, -0.6310947579755295 50.60191112048408, 1.1885095534434493 49.47027919866873, 3.384771510058846 49.85377035058955, 3.8811335596706074 51.360376195950145, 2.101313983947425 52.51713397842229)) -2 | POINT (4.5991105819121 52.129031270742416) | 82196ffffffffff | POLYGON ((4.948742151508294 54.2882866932292, 2.592789031305367 53.99775155222293, 2.101313983947425 52.51713397842229, 3.8811335596706074 51.360376195950145, 6.259687055981993 51.96477015603749, 6.8482289070479005 53.43156035343158, 4.948742151508294 54.2882866932292)) -2 | POINT (-2.5373152876272798 55.49281941493973) | 821977fffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -3.536381138969186 57.31728796714347, -3.9031812914854935 55.840605806464886, -1.7855433613316123 54.76238836624054, 0.6707588590220377 55.133805943055435, 1.1521975506221078 56.583354389307445, -0.9315871635106163 57.689497374592854)) -1 | POINT (-1.2880607228726149 59.87668995279819) | 8209a7fffffffff | POLYGON ((0.5480202135218006 61.82886471359379, -2.297526087621831 61.54550957788076, -2.7356231170279166 60.17050935552437, -0.4671324618104694 59.1035939329508, 2.198216040575142 59.383886486983954, 2.767527791540729 60.73321011494055, 0.5480202135218006 61.82886471359379)) -1 | POINT (0.15865350142121315 49.36166098807007) | 821867fffffffff | POLYGON ((-0.6310947579755295 50.60191112048408, -2.906527879284175 50.14229216995713, -3.2436562689082553 48.547301491418715, -1.3966081625912774 47.44351195977148, 0.7640259623867446 47.90745035042651, 1.1885095534434493 49.47027919866873, -0.6310947579755295 50.60191112048408)) -1 | POINT (-7.270800014957786 62.06249998882413) | 821927fffffffff | POLYGON ((-4.777634484041529 62.56377272218282, -7.72004205669337 62.172198741500715, -7.999682127502827 60.77664727688846, -5.502334925300172 59.7918551703578, -2.7356231170279166 60.17050935552437, -2.297526087621831 61.54550957788076, -4.777634484041529 62.56377272218282)) -1 | POINT (-2.9013785161077976 58.95442885346711) | 82192ffffffffff | POLYGON ((-2.7356231170279166 60.17050935552437, -5.502334925300172 59.7918551703578, -5.832270115239392 58.353838498476094, -3.536381138969186 57.31728796714347, -0.9315871635106163 57.689497374592854, -0.4671324618104694 59.1035939329508, -2.7356231170279166 60.17050935552437)) -1 | POINT (-1.6598310694098473 53.8690819311887) | 821947fffffffff | POLYGON ((0.6707588590220377 55.133805943055435, -1.7855433613316123 54.76238836624054, -2.1788859209290505 53.251551050714795, -0.21913743445926337 52.1416808182628, 2.101313983947425 52.51713397842229, 2.592789031305367 53.99775155222293, 0.6707588590220377 55.133805943055435)) +count:long | centroid:geo_point | geohexString:keyword +5 | POINT (-1.7227098606526852 51.717823022045195) | 82195ffffffffff +4 | POINT (-3.9897833741270006 54.21732849790715) | 821957fffffffff +3 | POINT (-7.885485291481018 52.65633414499462) | 82182ffffffffff +3 | POINT (3.0334555450826883 48.842039234004915) | 821fb7fffffffff +2 | POINT (5.428531668148935 59.585608751513064) | 820987fffffffff +2 | POINT (-4.2476349184289575 56.70184155693278) | 82190ffffffffff +2 | POINT (1.4715016074478626 50.863699545152485) | 82194ffffffffff +2 | POINT (4.5991105819121 52.129031270742416) | 82196ffffffffff +2 | POINT (-2.5373152876272798 55.49281941493973) | 821977fffffffff +1 | POINT (-1.2880607228726149 59.87668995279819) | 8209a7fffffffff +1 | POINT (0.15865350142121315 49.36166098807007) | 821867fffffffff +1 | POINT (-7.270800014957786 62.06249998882413) | 821927fffffffff +1 | POINT (-2.9013785161077976 58.95442885346711) | 82192ffffffffff +1 | POINT (-1.6598310694098473 53.8690819311887) | 821947fffffffff ; gridGeohexInStatsByBounds diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromLongEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromLongEvaluator.java deleted file mode 100644 index 3e95b8a55d7e9..0000000000000 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromLongEvaluator.java +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License -// 2.0; you may not use this file except in compliance with the Elastic License -// 2.0. -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; - -import java.lang.Override; -import java.lang.String; -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; -import org.elasticsearch.compute.data.LongBlock; -import org.elasticsearch.compute.data.LongVector; -import org.elasticsearch.compute.data.Vector; -import org.elasticsearch.compute.operator.DriverContext; -import org.elasticsearch.compute.operator.EvalOperator; -import org.elasticsearch.core.Releasables; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; - -/** - * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohashToGeoShape}. - * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. - */ -public final class StGeohashToGeoShapeFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { - private final EvalOperator.ExpressionEvaluator gridId; - - public StGeohashToGeoShapeFromLongEvaluator(Source source, - EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { - super(driverContext, source); - this.gridId = gridId; - } - - @Override - public EvalOperator.ExpressionEvaluator next() { - return gridId; - } - - @Override - public Block evalVector(Vector v) { - LongVector vector = (LongVector) v; - int positionCount = v.getPositionCount(); - if (vector.isConstant()) { - return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0), positionCount); - } - try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - for (int p = 0; p < positionCount; p++) { - builder.appendBytesRef(evalValue(vector, p)); - } - return builder.build(); - } - } - - private BytesRef evalValue(LongVector container, int index) { - long value = container.getLong(index); - return StGeohashToGeoShape.fromLong(value); - } - - @Override - public Block evalBlock(Block b) { - LongBlock block = (LongBlock) b; - int positionCount = block.getPositionCount(); - try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - for (int p = 0; p < positionCount; p++) { - int valueCount = block.getValueCount(p); - int start = block.getFirstValueIndex(p); - int end = start + valueCount; - boolean positionOpened = false; - boolean valuesAppended = false; - for (int i = start; i < end; i++) { - BytesRef value = evalValue(block, i); - if (positionOpened == false && valueCount > 1) { - builder.beginPositionEntry(); - positionOpened = true; - } - builder.appendBytesRef(value); - valuesAppended = true; - } - if (valuesAppended == false) { - builder.appendNull(); - } else if (positionOpened) { - builder.endPositionEntry(); - } - } - return builder.build(); - } - } - - private BytesRef evalValue(LongBlock container, int index) { - long value = container.getLong(index); - return StGeohashToGeoShape.fromLong(value); - } - - @Override - public String toString() { - return "StGeohashToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; - } - - @Override - public void close() { - Releasables.closeExpectNoException(gridId); - } - - public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { - private final Source source; - - private final EvalOperator.ExpressionEvaluator.Factory gridId; - - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { - this.source = source; - this.gridId = gridId; - } - - @Override - public StGeohashToGeoShapeFromLongEvaluator get(DriverContext context) { - return new StGeohashToGeoShapeFromLongEvaluator(source, gridId.get(context), context); - } - - @Override - public String toString() { - return "StGeohashToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; - } - } -} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java deleted file mode 100644 index 0e50257a50bed..0000000000000 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License -// 2.0; you may not use this file except in compliance with the Elastic License -// 2.0. -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; - -import java.lang.Override; -import java.lang.String; -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; -import org.elasticsearch.compute.data.BytesRefVector; -import org.elasticsearch.compute.data.IntVector; -import org.elasticsearch.compute.data.OrdinalBytesRefVector; -import org.elasticsearch.compute.data.Vector; -import org.elasticsearch.compute.operator.DriverContext; -import org.elasticsearch.compute.operator.EvalOperator; -import org.elasticsearch.core.Releasables; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; - -/** - * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohashToGeoShape}. - * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. - */ -public final class StGeohashToGeoShapeFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { - private final EvalOperator.ExpressionEvaluator gridId; - - public StGeohashToGeoShapeFromStringEvaluator(Source source, - EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { - super(driverContext, source); - this.gridId = gridId; - } - - @Override - public EvalOperator.ExpressionEvaluator next() { - return gridId; - } - - @Override - public Block evalVector(Vector v) { - BytesRefVector vector = (BytesRefVector) v; - OrdinalBytesRefVector ordinals = vector.asOrdinals(); - if (ordinals != null) { - return evalOrdinals(ordinals); - } - int positionCount = v.getPositionCount(); - BytesRef scratchPad = new BytesRef(); - if (vector.isConstant()) { - return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0, scratchPad), positionCount); - } - try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - for (int p = 0; p < positionCount; p++) { - builder.appendBytesRef(evalValue(vector, p, scratchPad)); - } - return builder.build(); - } - } - - private BytesRef evalValue(BytesRefVector container, int index, BytesRef scratchPad) { - BytesRef value = container.getBytesRef(index, scratchPad); - return StGeohashToGeoShape.fromString(value); - } - - @Override - public Block evalBlock(Block b) { - BytesRefBlock block = (BytesRefBlock) b; - int positionCount = block.getPositionCount(); - try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - BytesRef scratchPad = new BytesRef(); - for (int p = 0; p < positionCount; p++) { - int valueCount = block.getValueCount(p); - int start = block.getFirstValueIndex(p); - int end = start + valueCount; - boolean positionOpened = false; - boolean valuesAppended = false; - for (int i = start; i < end; i++) { - BytesRef value = evalValue(block, i, scratchPad); - if (positionOpened == false && valueCount > 1) { - builder.beginPositionEntry(); - positionOpened = true; - } - builder.appendBytesRef(value); - valuesAppended = true; - } - if (valuesAppended == false) { - builder.appendNull(); - } else if (positionOpened) { - builder.endPositionEntry(); - } - } - return builder.build(); - } - } - - private BytesRef evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { - BytesRef value = container.getBytesRef(index, scratchPad); - return StGeohashToGeoShape.fromString(value); - } - - private Block evalOrdinals(OrdinalBytesRefVector v) { - int positionCount = v.getDictionaryVector().getPositionCount(); - BytesRef scratchPad = new BytesRef(); - try (BytesRefVector.Builder builder = driverContext.blockFactory().newBytesRefVectorBuilder(positionCount)) { - for (int p = 0; p < positionCount; p++) { - builder.appendBytesRef(evalValue(v.getDictionaryVector(), p, scratchPad)); - } - IntVector ordinals = v.getOrdinalsVector(); - ordinals.incRef(); - return new OrdinalBytesRefVector(ordinals, builder.build()).asBlock(); - } - } - - @Override - public String toString() { - return "StGeohashToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; - } - - @Override - public void close() { - Releasables.closeExpectNoException(gridId); - } - - public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { - private final Source source; - - private final EvalOperator.ExpressionEvaluator.Factory gridId; - - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { - this.source = source; - this.gridId = gridId; - } - - @Override - public StGeohashToGeoShapeFromStringEvaluator get(DriverContext context) { - return new StGeohashToGeoShapeFromStringEvaluator(source, gridId.get(context), context); - } - - @Override - public String toString() { - return "StGeohashToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; - } - } -} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromLongEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromLongEvaluator.java deleted file mode 100644 index 250c2159e380b..0000000000000 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromLongEvaluator.java +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License -// 2.0; you may not use this file except in compliance with the Elastic License -// 2.0. -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; - -import java.lang.Override; -import java.lang.String; -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; -import org.elasticsearch.compute.data.LongBlock; -import org.elasticsearch.compute.data.LongVector; -import org.elasticsearch.compute.data.Vector; -import org.elasticsearch.compute.operator.DriverContext; -import org.elasticsearch.compute.operator.EvalOperator; -import org.elasticsearch.core.Releasables; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; - -/** - * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohexToGeoShape}. - * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. - */ -public final class StGeohexToGeoShapeFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { - private final EvalOperator.ExpressionEvaluator gridId; - - public StGeohexToGeoShapeFromLongEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, - DriverContext driverContext) { - super(driverContext, source); - this.gridId = gridId; - } - - @Override - public EvalOperator.ExpressionEvaluator next() { - return gridId; - } - - @Override - public Block evalVector(Vector v) { - LongVector vector = (LongVector) v; - int positionCount = v.getPositionCount(); - if (vector.isConstant()) { - return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0), positionCount); - } - try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - for (int p = 0; p < positionCount; p++) { - builder.appendBytesRef(evalValue(vector, p)); - } - return builder.build(); - } - } - - private BytesRef evalValue(LongVector container, int index) { - long value = container.getLong(index); - return StGeohexToGeoShape.fromLong(value); - } - - @Override - public Block evalBlock(Block b) { - LongBlock block = (LongBlock) b; - int positionCount = block.getPositionCount(); - try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - for (int p = 0; p < positionCount; p++) { - int valueCount = block.getValueCount(p); - int start = block.getFirstValueIndex(p); - int end = start + valueCount; - boolean positionOpened = false; - boolean valuesAppended = false; - for (int i = start; i < end; i++) { - BytesRef value = evalValue(block, i); - if (positionOpened == false && valueCount > 1) { - builder.beginPositionEntry(); - positionOpened = true; - } - builder.appendBytesRef(value); - valuesAppended = true; - } - if (valuesAppended == false) { - builder.appendNull(); - } else if (positionOpened) { - builder.endPositionEntry(); - } - } - return builder.build(); - } - } - - private BytesRef evalValue(LongBlock container, int index) { - long value = container.getLong(index); - return StGeohexToGeoShape.fromLong(value); - } - - @Override - public String toString() { - return "StGeohexToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; - } - - @Override - public void close() { - Releasables.closeExpectNoException(gridId); - } - - public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { - private final Source source; - - private final EvalOperator.ExpressionEvaluator.Factory gridId; - - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { - this.source = source; - this.gridId = gridId; - } - - @Override - public StGeohexToGeoShapeFromLongEvaluator get(DriverContext context) { - return new StGeohexToGeoShapeFromLongEvaluator(source, gridId.get(context), context); - } - - @Override - public String toString() { - return "StGeohexToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; - } - } -} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java deleted file mode 100644 index 94887bda9c960..0000000000000 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License -// 2.0; you may not use this file except in compliance with the Elastic License -// 2.0. -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; - -import java.lang.Override; -import java.lang.String; -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; -import org.elasticsearch.compute.data.BytesRefVector; -import org.elasticsearch.compute.data.IntVector; -import org.elasticsearch.compute.data.OrdinalBytesRefVector; -import org.elasticsearch.compute.data.Vector; -import org.elasticsearch.compute.operator.DriverContext; -import org.elasticsearch.compute.operator.EvalOperator; -import org.elasticsearch.core.Releasables; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; - -/** - * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohexToGeoShape}. - * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. - */ -public final class StGeohexToGeoShapeFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { - private final EvalOperator.ExpressionEvaluator gridId; - - public StGeohexToGeoShapeFromStringEvaluator(Source source, - EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { - super(driverContext, source); - this.gridId = gridId; - } - - @Override - public EvalOperator.ExpressionEvaluator next() { - return gridId; - } - - @Override - public Block evalVector(Vector v) { - BytesRefVector vector = (BytesRefVector) v; - OrdinalBytesRefVector ordinals = vector.asOrdinals(); - if (ordinals != null) { - return evalOrdinals(ordinals); - } - int positionCount = v.getPositionCount(); - BytesRef scratchPad = new BytesRef(); - if (vector.isConstant()) { - return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0, scratchPad), positionCount); - } - try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - for (int p = 0; p < positionCount; p++) { - builder.appendBytesRef(evalValue(vector, p, scratchPad)); - } - return builder.build(); - } - } - - private BytesRef evalValue(BytesRefVector container, int index, BytesRef scratchPad) { - BytesRef value = container.getBytesRef(index, scratchPad); - return StGeohexToGeoShape.fromString(value); - } - - @Override - public Block evalBlock(Block b) { - BytesRefBlock block = (BytesRefBlock) b; - int positionCount = block.getPositionCount(); - try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - BytesRef scratchPad = new BytesRef(); - for (int p = 0; p < positionCount; p++) { - int valueCount = block.getValueCount(p); - int start = block.getFirstValueIndex(p); - int end = start + valueCount; - boolean positionOpened = false; - boolean valuesAppended = false; - for (int i = start; i < end; i++) { - BytesRef value = evalValue(block, i, scratchPad); - if (positionOpened == false && valueCount > 1) { - builder.beginPositionEntry(); - positionOpened = true; - } - builder.appendBytesRef(value); - valuesAppended = true; - } - if (valuesAppended == false) { - builder.appendNull(); - } else if (positionOpened) { - builder.endPositionEntry(); - } - } - return builder.build(); - } - } - - private BytesRef evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { - BytesRef value = container.getBytesRef(index, scratchPad); - return StGeohexToGeoShape.fromString(value); - } - - private Block evalOrdinals(OrdinalBytesRefVector v) { - int positionCount = v.getDictionaryVector().getPositionCount(); - BytesRef scratchPad = new BytesRef(); - try (BytesRefVector.Builder builder = driverContext.blockFactory().newBytesRefVectorBuilder(positionCount)) { - for (int p = 0; p < positionCount; p++) { - builder.appendBytesRef(evalValue(v.getDictionaryVector(), p, scratchPad)); - } - IntVector ordinals = v.getOrdinalsVector(); - ordinals.incRef(); - return new OrdinalBytesRefVector(ordinals, builder.build()).asBlock(); - } - } - - @Override - public String toString() { - return "StGeohexToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; - } - - @Override - public void close() { - Releasables.closeExpectNoException(gridId); - } - - public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { - private final Source source; - - private final EvalOperator.ExpressionEvaluator.Factory gridId; - - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { - this.source = source; - this.gridId = gridId; - } - - @Override - public StGeohexToGeoShapeFromStringEvaluator get(DriverContext context) { - return new StGeohexToGeoShapeFromStringEvaluator(source, gridId.get(context), context); - } - - @Override - public String toString() { - return "StGeohexToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; - } - } -} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromLongEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromLongEvaluator.java deleted file mode 100644 index e625fb7443aab..0000000000000 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromLongEvaluator.java +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License -// 2.0; you may not use this file except in compliance with the Elastic License -// 2.0. -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; - -import java.lang.Override; -import java.lang.String; -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; -import org.elasticsearch.compute.data.LongBlock; -import org.elasticsearch.compute.data.LongVector; -import org.elasticsearch.compute.data.Vector; -import org.elasticsearch.compute.operator.DriverContext; -import org.elasticsearch.compute.operator.EvalOperator; -import org.elasticsearch.core.Releasables; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; - -/** - * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotileToGeoShape}. - * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. - */ -public final class StGeotileToGeoShapeFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { - private final EvalOperator.ExpressionEvaluator gridId; - - public StGeotileToGeoShapeFromLongEvaluator(Source source, - EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { - super(driverContext, source); - this.gridId = gridId; - } - - @Override - public EvalOperator.ExpressionEvaluator next() { - return gridId; - } - - @Override - public Block evalVector(Vector v) { - LongVector vector = (LongVector) v; - int positionCount = v.getPositionCount(); - if (vector.isConstant()) { - return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0), positionCount); - } - try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - for (int p = 0; p < positionCount; p++) { - builder.appendBytesRef(evalValue(vector, p)); - } - return builder.build(); - } - } - - private BytesRef evalValue(LongVector container, int index) { - long value = container.getLong(index); - return StGeotileToGeoShape.fromLong(value); - } - - @Override - public Block evalBlock(Block b) { - LongBlock block = (LongBlock) b; - int positionCount = block.getPositionCount(); - try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - for (int p = 0; p < positionCount; p++) { - int valueCount = block.getValueCount(p); - int start = block.getFirstValueIndex(p); - int end = start + valueCount; - boolean positionOpened = false; - boolean valuesAppended = false; - for (int i = start; i < end; i++) { - BytesRef value = evalValue(block, i); - if (positionOpened == false && valueCount > 1) { - builder.beginPositionEntry(); - positionOpened = true; - } - builder.appendBytesRef(value); - valuesAppended = true; - } - if (valuesAppended == false) { - builder.appendNull(); - } else if (positionOpened) { - builder.endPositionEntry(); - } - } - return builder.build(); - } - } - - private BytesRef evalValue(LongBlock container, int index) { - long value = container.getLong(index); - return StGeotileToGeoShape.fromLong(value); - } - - @Override - public String toString() { - return "StGeotileToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; - } - - @Override - public void close() { - Releasables.closeExpectNoException(gridId); - } - - public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { - private final Source source; - - private final EvalOperator.ExpressionEvaluator.Factory gridId; - - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { - this.source = source; - this.gridId = gridId; - } - - @Override - public StGeotileToGeoShapeFromLongEvaluator get(DriverContext context) { - return new StGeotileToGeoShapeFromLongEvaluator(source, gridId.get(context), context); - } - - @Override - public String toString() { - return "StGeotileToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; - } - } -} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java deleted file mode 100644 index 801bf228e6adf..0000000000000 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one -// or more contributor license agreements. Licensed under the Elastic License -// 2.0; you may not use this file except in compliance with the Elastic License -// 2.0. -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; - -import java.lang.Override; -import java.lang.String; -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.compute.data.Block; -import org.elasticsearch.compute.data.BytesRefBlock; -import org.elasticsearch.compute.data.BytesRefVector; -import org.elasticsearch.compute.data.IntVector; -import org.elasticsearch.compute.data.OrdinalBytesRefVector; -import org.elasticsearch.compute.data.Vector; -import org.elasticsearch.compute.operator.DriverContext; -import org.elasticsearch.compute.operator.EvalOperator; -import org.elasticsearch.core.Releasables; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; - -/** - * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotileToGeoShape}. - * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. - */ -public final class StGeotileToGeoShapeFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { - private final EvalOperator.ExpressionEvaluator gridId; - - public StGeotileToGeoShapeFromStringEvaluator(Source source, - EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { - super(driverContext, source); - this.gridId = gridId; - } - - @Override - public EvalOperator.ExpressionEvaluator next() { - return gridId; - } - - @Override - public Block evalVector(Vector v) { - BytesRefVector vector = (BytesRefVector) v; - OrdinalBytesRefVector ordinals = vector.asOrdinals(); - if (ordinals != null) { - return evalOrdinals(ordinals); - } - int positionCount = v.getPositionCount(); - BytesRef scratchPad = new BytesRef(); - if (vector.isConstant()) { - return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0, scratchPad), positionCount); - } - try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - for (int p = 0; p < positionCount; p++) { - builder.appendBytesRef(evalValue(vector, p, scratchPad)); - } - return builder.build(); - } - } - - private BytesRef evalValue(BytesRefVector container, int index, BytesRef scratchPad) { - BytesRef value = container.getBytesRef(index, scratchPad); - return StGeotileToGeoShape.fromString(value); - } - - @Override - public Block evalBlock(Block b) { - BytesRefBlock block = (BytesRefBlock) b; - int positionCount = block.getPositionCount(); - try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { - BytesRef scratchPad = new BytesRef(); - for (int p = 0; p < positionCount; p++) { - int valueCount = block.getValueCount(p); - int start = block.getFirstValueIndex(p); - int end = start + valueCount; - boolean positionOpened = false; - boolean valuesAppended = false; - for (int i = start; i < end; i++) { - BytesRef value = evalValue(block, i, scratchPad); - if (positionOpened == false && valueCount > 1) { - builder.beginPositionEntry(); - positionOpened = true; - } - builder.appendBytesRef(value); - valuesAppended = true; - } - if (valuesAppended == false) { - builder.appendNull(); - } else if (positionOpened) { - builder.endPositionEntry(); - } - } - return builder.build(); - } - } - - private BytesRef evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { - BytesRef value = container.getBytesRef(index, scratchPad); - return StGeotileToGeoShape.fromString(value); - } - - private Block evalOrdinals(OrdinalBytesRefVector v) { - int positionCount = v.getDictionaryVector().getPositionCount(); - BytesRef scratchPad = new BytesRef(); - try (BytesRefVector.Builder builder = driverContext.blockFactory().newBytesRefVectorBuilder(positionCount)) { - for (int p = 0; p < positionCount; p++) { - builder.appendBytesRef(evalValue(v.getDictionaryVector(), p, scratchPad)); - } - IntVector ordinals = v.getOrdinalsVector(); - ordinals.incRef(); - return new OrdinalBytesRefVector(ordinals, builder.build()).asBlock(); - } - } - - @Override - public String toString() { - return "StGeotileToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; - } - - @Override - public void close() { - Releasables.closeExpectNoException(gridId); - } - - public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { - private final Source source; - - private final EvalOperator.ExpressionEvaluator.Factory gridId; - - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { - this.source = source; - this.gridId = gridId; - } - - @Override - public StGeotileToGeoShapeFromStringEvaluator get(DriverContext context) { - return new StGeotileToGeoShapeFromStringEvaluator(source, gridId.get(context), context); - } - - @Override - public String toString() { - return "StGeotileToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; - } - } -} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java index 6b520ee4c034d..ffb566b59f894 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java @@ -59,15 +59,12 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StDistance; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StEnvelope; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohash; -import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToGeoShape; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToLong; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohex; -import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToGeoShape; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToLong; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotile; -import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToGeoShape; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToLong; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StX; @@ -233,15 +230,12 @@ private static List spatials() { StGeohash.ENTRY, StGeohashToString.ENTRY, StGeohashToLong.ENTRY, - StGeohashToGeoShape.ENTRY, StGeotile.ENTRY, StGeotileToString.ENTRY, StGeotileToLong.ENTRY, - StGeotileToGeoShape.ENTRY, StGeohex.ENTRY, StGeohexToString.ENTRY, - StGeohexToLong.ENTRY, - StGeohexToGeoShape.ENTRY + StGeohexToLong.ENTRY ); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index 95d2b284152df..4851259f3fd10 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -132,15 +132,12 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StDistance; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StEnvelope; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohash; -import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToGeoShape; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToLong; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohex; -import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToGeoShape; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToLong; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotile; -import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToGeoShape; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToLong; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StX; @@ -394,15 +391,12 @@ private static FunctionDefinition[][] functions() { def(StX.class, StX::new, "st_x"), def(StY.class, StY::new, "st_y"), def(StGeohash.class, StGeohash::new, "st_geohash"), - def(StGeohashToGeoShape.class, StGeohashToGeoShape::new, "st_geohash_to_geoshape"), def(StGeohashToLong.class, StGeohashToLong::new, "st_geohash_to_long"), def(StGeohashToString.class, StGeohashToString::new, "st_geohash_to_string"), def(StGeotile.class, StGeotile::new, "st_geotile"), - def(StGeotileToGeoShape.class, StGeotileToGeoShape::new, "st_geotile_to_geoshape"), def(StGeotileToLong.class, StGeotileToLong::new, "st_geotile_to_long"), def(StGeotileToString.class, StGeotileToString::new, "st_geotile_to_string"), def(StGeohex.class, StGeohex::new, "st_geohex"), - def(StGeohexToGeoShape.class, StGeohexToGeoShape::new, "st_geohex_to_geoshape"), def(StGeohexToLong.class, StGeohexToLong::new, "st_geohex_to_long"), def(StGeohexToString.class, StGeohexToString::new, "st_geohex_to_string") }, // conditional diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java deleted file mode 100644 index b205ca194dbc9..0000000000000 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; - -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.common.io.stream.NamedWriteableRegistry; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.compute.ann.ConvertEvaluator; -import org.elasticsearch.geometry.utils.Geohash; -import org.elasticsearch.xpack.esql.core.expression.Expression; -import org.elasticsearch.xpack.esql.core.tree.NodeInfo; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; -import org.elasticsearch.xpack.esql.expression.function.Example; -import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; -import org.elasticsearch.xpack.esql.expression.function.Param; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; -import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; -import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; -import static org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToGeoShape.fromRectangle; - -public class StGeohashToGeoShape extends AbstractConvertFunction implements EvaluatorMapper { - public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( - Expression.class, - "StGeohashToGeoShape", - StGeohashToGeoShape::new - ); - - private static final Map EVALUATORS = Map.ofEntries( - Map.entry(KEYWORD, StGeohashToGeoShapeFromStringEvaluator.Factory::new), - Map.entry(LONG, StGeohashToGeoShapeFromLongEvaluator.Factory::new) - ); - - @FunctionInfo( - returnType = "geo_shape", - description = """ - Converts an input value to a `geo_shape` value. - The input values are expected to be the grid-ids of geohash grids, in either long or string format.""", - examples = @Example(file = "spatial-grid", tag = "geohash_to_geoshape"), - depthOffset = 1 // make it appear as a subsection of ST_GEOHASH - ) - public StGeohashToGeoShape( - Source source, - @Param( - name = "grid_id", - type = { "keyword", "long" }, - description = "Input geohash grid-id. The input can be a single- or multi-valued column or an expression." - ) Expression v - ) { - super(source, v); - } - - private StGeohashToGeoShape(StreamInput in) throws IOException { - super(in); - } - - @Override - public String getWriteableName() { - return ENTRY.name; - } - - @Override - protected Map factories() { - return EVALUATORS; - } - - @Override - public DataType dataType() { - return GEO_SHAPE; - } - - @Override - public Expression replaceChildren(List newChildren) { - return new StGeohashToGeoShape(source(), newChildren.get(0)); - } - - @Override - protected NodeInfo info() { - return NodeInfo.create(this, StGeohashToGeoShape::new, field()); - } - - @ConvertEvaluator(extraName = "FromString") - static BytesRef fromString(BytesRef gridId) { - return fromRectangle(Geohash.toBoundingBox(gridId.utf8ToString())); - } - - @ConvertEvaluator(extraName = "FromLong") - static BytesRef fromLong(long gridId) { - return fromRectangle(Geohash.toBoundingBox(Geohash.stringEncode(gridId))); - } -} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java deleted file mode 100644 index 816fadb6061c2..0000000000000 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; - -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.common.io.stream.NamedWriteableRegistry; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.compute.ann.ConvertEvaluator; -import org.elasticsearch.geometry.LinearRing; -import org.elasticsearch.geometry.Polygon; -import org.elasticsearch.h3.CellBoundary; -import org.elasticsearch.h3.H3; -import org.elasticsearch.h3.LatLng; -import org.elasticsearch.xpack.esql.core.expression.Expression; -import org.elasticsearch.xpack.esql.core.tree.NodeInfo; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes; -import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; -import org.elasticsearch.xpack.esql.expression.function.Example; -import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; -import org.elasticsearch.xpack.esql.expression.function.Param; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; -import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; -import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; - -public class StGeohexToGeoShape extends AbstractConvertFunction implements EvaluatorMapper { - public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( - Expression.class, - "StGeohexToGeoShape", - StGeohexToGeoShape::new - ); - - private static final Map EVALUATORS = Map.ofEntries( - Map.entry(KEYWORD, StGeohexToGeoShapeFromStringEvaluator.Factory::new), - Map.entry(LONG, StGeohexToGeoShapeFromLongEvaluator.Factory::new) - ); - - @FunctionInfo( - returnType = "geo_shape", - description = """ - Converts an input value to a `geo_shape` value. - The input values are expected to be the grid-ids of H3 grids, in either long or string format.""", - examples = @Example(file = "spatial-grid", tag = "geohex_to_geoshape"), - depthOffset = 1 // make it appear as a subsection of ST_GEOHEX - ) - public StGeohexToGeoShape( - Source source, - @Param( - name = "grid_id", - type = { "keyword", "long" }, - description = "Input H3 grid-id. The input can be a single- or multi-valued column or an expression." - ) Expression v - ) { - super(source, v); - } - - private StGeohexToGeoShape(StreamInput in) throws IOException { - super(in); - } - - @Override - public String getWriteableName() { - return ENTRY.name; - } - - @Override - protected Map factories() { - return EVALUATORS; - } - - @Override - public DataType dataType() { - return GEO_SHAPE; - } - - @Override - public Expression replaceChildren(List newChildren) { - return new StGeohexToGeoShape(source(), newChildren.get(0)); - } - - @Override - protected NodeInfo info() { - return NodeInfo.create(this, StGeohexToGeoShape::new, field()); - } - - @ConvertEvaluator(extraName = "FromString") - static BytesRef fromString(BytesRef gridId) { - return fromCellBoundary(H3.h3ToGeoBoundary(gridId.utf8ToString())); - } - - @ConvertEvaluator(extraName = "FromLong") - static BytesRef fromLong(long gridId) { - return fromCellBoundary(H3.h3ToGeoBoundary(gridId)); - } - - private static BytesRef fromCellBoundary(CellBoundary cell) { - double[] x = new double[cell.numPoints() + 1]; - double[] y = new double[cell.numPoints() + 1]; - for (int i = 0; i < cell.numPoints(); i++) { - LatLng vertex = cell.getLatLon(i); - x[i] = vertex.getLonDeg(); - y[i] = vertex.getLatDeg(); - } - x[cell.numPoints()] = x[0]; - y[cell.numPoints()] = y[0]; - LinearRing ring = new LinearRing(x, y); - Polygon polygon = new Polygon(ring); - return SpatialCoordinateTypes.GEO.asWkb(polygon); - } -} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java deleted file mode 100644 index 862a33d82ad79..0000000000000 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; - -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.common.io.stream.NamedWriteableRegistry; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.compute.ann.ConvertEvaluator; -import org.elasticsearch.geometry.LinearRing; -import org.elasticsearch.geometry.Polygon; -import org.elasticsearch.geometry.Rectangle; -import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; -import org.elasticsearch.xpack.esql.core.expression.Expression; -import org.elasticsearch.xpack.esql.core.tree.NodeInfo; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes; -import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; -import org.elasticsearch.xpack.esql.expression.function.Example; -import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; -import org.elasticsearch.xpack.esql.expression.function.Param; -import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; -import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; -import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; - -public class StGeotileToGeoShape extends AbstractConvertFunction implements EvaluatorMapper { - public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( - Expression.class, - "StGeotileToGeoShape", - StGeotileToGeoShape::new - ); - - private static final Map EVALUATORS = Map.ofEntries( - Map.entry(KEYWORD, StGeotileToGeoShapeFromStringEvaluator.Factory::new), - Map.entry(LONG, StGeotileToGeoShapeFromLongEvaluator.Factory::new) - ); - - @FunctionInfo( - returnType = "geo_shape", - description = """ - Converts an input value to a `geo_shape` value. - The input values are expected to be the grid-ids of geotile grids, in either long or string format.""", - examples = @Example(file = "spatial-grid", tag = "geotile_to_geoshape"), - depthOffset = 1 // make it appear as a subsection of ST_GEOTILE - ) - public StGeotileToGeoShape( - Source source, - @Param( - name = "grid_id", - type = { "keyword", "long" }, - description = "Input geotile grid-id. The input can be a single- or multi-valued column or an expression." - ) Expression v - ) { - super(source, v); - } - - private StGeotileToGeoShape(StreamInput in) throws IOException { - super(in); - } - - @Override - public String getWriteableName() { - return ENTRY.name; - } - - @Override - protected Map factories() { - return EVALUATORS; - } - - @Override - public DataType dataType() { - return GEO_SHAPE; - } - - @Override - public Expression replaceChildren(List newChildren) { - return new StGeotileToGeoShape(source(), newChildren.get(0)); - } - - @Override - protected NodeInfo info() { - return NodeInfo.create(this, StGeotileToGeoShape::new, field()); - } - - @ConvertEvaluator(extraName = "FromString") - static BytesRef fromString(BytesRef gridId) { - return fromRectangle(GeoTileUtils.toBoundingBox(gridId.utf8ToString())); - } - - @ConvertEvaluator(extraName = "FromLong") - static BytesRef fromLong(long gridId) { - return fromRectangle(GeoTileUtils.toBoundingBox(gridId)); - } - - static BytesRef fromRectangle(Rectangle bbox) { - double[] x = new double[] { bbox.getMinX(), bbox.getMaxX(), bbox.getMaxX(), bbox.getMinX(), bbox.getMinX() }; - double[] y = new double[] { bbox.getMinY(), bbox.getMinY(), bbox.getMaxY(), bbox.getMaxY(), bbox.getMinY() }; - LinearRing ring = new LinearRing(x, y); - Polygon polygon = new Polygon(ring); - return SpatialCoordinateTypes.GEO.asWkb(polygon); - } -} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java deleted file mode 100644 index 6c0eaac7a69a0..0000000000000 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; - -import com.carrotsearch.randomizedtesting.annotations.Name; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.geometry.utils.Geohash; -import org.elasticsearch.xpack.esql.core.expression.Expression; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.expression.function.FunctionName; -import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - -import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; -import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; - -@FunctionName("st_geohash_to_geoshape") -public class StGeohashToGeoShapeTests extends SpatialGridTypeConversionTestCases { - public StGeohashToGeoShapeTests(@Name("TestCase") Supplier testCaseSupplier) { - this.testCase = testCaseSupplier.get(); - } - - @ParametersFactory - public static Iterable parameters() { - final List suppliers = new ArrayList<>(); - forUnaryGeoPoint( - DataType.LONG, - suppliers, - "StGeohashToGeoShapeFromLongEvaluator[gridId=Attribute[channel=0]]", - GEO_SHAPE, - g -> StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeohashToGeoShapeTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "StGeohashToGeoShapeFromStringEvaluator[gridId=Attribute[channel=0]]", - GEO_SHAPE, - g -> new BytesRef(Geohash.stringEncode(StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), - StGeohashToGeoShapeTests::valueOf - ); - return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); - } - - private static BytesRef valueOf(Object gridid) { - return (gridid instanceof Long hash) ? StGeohashToGeoShape.fromLong(hash) : StGeohashToGeoShape.fromString((BytesRef) gridid); - } - - @Override - protected Expression build(Source source, List args) { - return new StGeohashToGeoShape(source, args.get(0)); - } -} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java deleted file mode 100644 index acd08a82e672e..0000000000000 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; - -import com.carrotsearch.randomizedtesting.annotations.Name; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.h3.H3; -import org.elasticsearch.xpack.esql.core.expression.Expression; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.expression.function.FunctionName; -import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - -import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; -import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; - -@FunctionName("st_geohex_to_geoshape") -public class StGeohexToGeoShapeTests extends SpatialGridTypeConversionTestCases { - public StGeohexToGeoShapeTests(@Name("TestCase") Supplier testCaseSupplier) { - this.testCase = testCaseSupplier.get(); - } - - @ParametersFactory - public static Iterable parameters() { - final List suppliers = new ArrayList<>(); - forUnaryGeoPoint( - DataType.LONG, - suppliers, - "StGeohexToGeoShapeFromLongEvaluator[gridId=Attribute[channel=0]]", - GEO_SHAPE, - g -> StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeohexToGeoShapeTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "StGeohexToGeoShapeFromStringEvaluator[gridId=Attribute[channel=0]]", - GEO_SHAPE, - g -> new BytesRef(H3.h3ToString(StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), - StGeohexToGeoShapeTests::valueOf - ); - return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); - } - - private static BytesRef valueOf(Object gridid) { - return (gridid instanceof Long hex) ? StGeohexToGeoShape.fromLong(hex) : StGeohexToGeoShape.fromString((BytesRef) gridid); - } - - @Override - protected Expression build(Source source, List args) { - return new StGeohexToGeoShape(source, args.get(0)); - } -} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java deleted file mode 100644 index afed423cccbbe..0000000000000 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; - -import com.carrotsearch.randomizedtesting.annotations.Name; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; -import org.elasticsearch.xpack.esql.core.expression.Expression; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.expression.function.FunctionName; -import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - -import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; -import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; - -@FunctionName("st_geotile_to_geoshape") -public class StGeotileToGeoShapeTests extends SpatialGridTypeConversionTestCases { - public StGeotileToGeoShapeTests(@Name("TestCase") Supplier testCaseSupplier) { - this.testCase = testCaseSupplier.get(); - } - - @ParametersFactory - public static Iterable parameters() { - final List suppliers = new ArrayList<>(); - forUnaryGeoPoint( - DataType.LONG, - suppliers, - "StGeotileToGeoShapeFromLongEvaluator[gridId=Attribute[channel=0]]", - GEO_SHAPE, - g -> StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeotileToGeoShapeTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "StGeotileToGeoShapeFromStringEvaluator[gridId=Attribute[channel=0]]", - GEO_SHAPE, - g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), - StGeotileToGeoShapeTests::valueOf - ); - return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); - } - - private static BytesRef valueOf(Object gridid) { - return (gridid instanceof Long hash) ? StGeotileToGeoShape.fromLong(hash) : StGeotileToGeoShape.fromString((BytesRef) gridid); - } - - @Override - protected Expression build(Source source, List args) { - return new StGeotileToGeoShape(source, args.get(0)); - } -} From f949e9e89a39fc06d7f0e7cab657dcb1389dde1d Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Wed, 21 May 2025 12:31:26 +0200 Subject: [PATCH 33/34] Revert "Remove support for grid TO_GEOSHAPE functions" This reverts commit 742d46184e1c3d652026d9396f088d5b145f5b4d. --- .../src/main/resources/spatial-grid.csv-spec | 381 +++++++++++++----- .../StGeohashToGeoShapeFromLongEvaluator.java | 124 ++++++ ...tGeohashToGeoShapeFromStringEvaluator.java | 144 +++++++ .../StGeohexToGeoShapeFromLongEvaluator.java | 124 ++++++ ...StGeohexToGeoShapeFromStringEvaluator.java | 144 +++++++ .../StGeotileToGeoShapeFromLongEvaluator.java | 124 ++++++ ...tGeotileToGeoShapeFromStringEvaluator.java | 144 +++++++ .../esql/expression/ExpressionWritables.java | 8 +- .../function/EsqlFunctionRegistry.java | 6 + .../scalar/spatial/StGeohashToGeoShape.java | 103 +++++ .../scalar/spatial/StGeohexToGeoShape.java | 122 ++++++ .../scalar/spatial/StGeotileToGeoShape.java | 114 ++++++ .../spatial/StGeohashToGeoShapeTests.java | 64 +++ .../spatial/StGeohexToGeoShapeTests.java | 64 +++ .../spatial/StGeotileToGeoShapeTests.java | 64 +++ 15 files changed, 1620 insertions(+), 110 deletions(-) create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromLongEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromLongEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromLongEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec index 3558d1208a433..8b77deda2b16d 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/spatial-grid.csv-spec @@ -32,6 +32,32 @@ geohash:long | geohashString:keyword // end::geohash_to_string-result[] ; +geohashStringToGeoShape +required_capability: spatial_grid + +// tag::geohash_to_geoshape[] +ROW geohash = "u3bu" +| EVAL boundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +// end::geohash_to_geoshape[] +; + +// tag::geohash_to_geoshape-result[] +geohash:keyword | boundary:geo_shape +u3bu | POLYGON((12.3046875 55.546875, 12.65625 55.546875, 12.65625 55.72265625, 12.3046875 55.72265625, 12.3046875 55.546875)) +// end::geohash_to_geoshape-result[] +; + +geohashLongToGeoShape +required_capability: spatial_grid + +ROW geohash = TO_LONG(13686180) +| EVAL boundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +; + +geohash:long | boundary:geo_shape +13686180 | POLYGON((12.3046875 55.546875, 12.65625 55.546875, 12.65625 55.72265625, 12.3046875 55.72265625, 12.3046875 55.546875)) +; + geohashLiteral required_capability: spatial_grid @@ -81,6 +107,23 @@ POINT (12.6493508684508 55.6285017221528) | 4 | 13686180 | u POINT (12.6493508684508 55.6285017221528) | 5 | 437958005 | u3bur ; +geohashLiteralMvBoundary +required_capability: spatial_grid + +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] +| MV_EXPAND precision +| EVAL geohash = ST_GEOHASH_TO_STRING(ST_GEOHASH(location, precision)) +| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +; + +location:geo_point | precision:integer | geohash:keyword | cellBoundary:geo_shape +POINT (12.6493508684508 55.6285017221528) | 1 | u | POLYGON((0.0 45.0, 45.0 45.0, 45.0 90.0, 0.0 90.0, 0.0 45.0)) +POINT (12.6493508684508 55.6285017221528) | 2 | u3 | POLYGON((11.25 50.625, 22.5 50.625, 22.5 56.25, 11.25 56.25, 11.25 50.625)) +POINT (12.6493508684508 55.6285017221528) | 3 | u3b | POLYGON((11.25 54.84375, 12.65625 54.84375, 12.65625 56.25, 11.25 56.25, 11.25 54.84375)) +POINT (12.6493508684508 55.6285017221528) | 4 | u3bu | POLYGON((12.3046875 55.546875, 12.65625 55.546875, 12.65625 55.72265625, 12.3046875 55.72265625, 12.3046875 55.546875)) +POINT (12.6493508684508 55.6285017221528) | 5 | u3bur | POLYGON((12.6123046875 55.5908203125, 12.65625 55.5908203125, 12.65625 55.634765625, 12.6123046875 55.634765625, 12.6123046875 55.5908203125)) +; + geohashField required_capability: spatial_grid @@ -168,22 +211,23 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohash | EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) -| KEEP count, centroid, geohashString +| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +| KEEP count, centroid, geohashString, cellBoundary | SORT count DESC, geohashString ASC ; -count:long | centroid:geo_point | geohashString:keyword -19 | POINT (6.360728044651057 47.94084087577894) | u0 -10 | POINT (15.350638423115015 47.80751353036612) | u2 -9 | POINT (18.5217544157058 42.1394603792578) | sr -8 | POINT (6.351574736181647 51.8981519783847) | u1 -7 | POINT (5.268637698941997 42.747250193330856) | sp -7 | POINT (17.092350951528974 53.365471504096476) | u3 -5 | POINT (16.2651440910995 58.812188878655434) | u6 -4 | POINT (7.7012718468904495 36.39783004182391) | sn -3 | POINT (14.222751930356026 37.168446206487715) | sq -3 | POINT (7.318722177296877 59.788265260867774) | u4 -2 | POINT (16.706149326637387 32.37822346854955) | sm +count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape +19 | POINT (6.360728044651057 47.94084087577894) | u0 | POLYGON((0.0 45.0, 11.25 45.0, 11.25 50.625, 0.0 50.625, 0.0 45.0)) +10 | POINT (15.350638423115015 47.80751353036612) | u2 | POLYGON((11.25 45.0, 22.5 45.0, 22.5 50.625, 11.25 50.625, 11.25 45.0)) +9 | POINT (18.5217544157058 42.1394603792578) | sr | POLYGON((11.25 39.375, 22.5 39.375, 22.5 45.0, 11.25 45.0, 11.25 39.375)) +8 | POINT (6.351574736181647 51.8981519783847) | u1 | POLYGON((0.0 50.625, 11.25 50.625, 11.25 56.25, 0.0 56.25, 0.0 50.625)) +7 | POINT (5.268637698941997 42.747250193330856) | sp | POLYGON((0.0 39.375, 11.25 39.375, 11.25 45.0, 0.0 45.0, 0.0 39.375)) +7 | POINT (17.092350951528974 53.365471504096476) | u3 | POLYGON((11.25 50.625, 22.5 50.625, 22.5 56.25, 11.25 56.25, 11.25 50.625)) +5 | POINT (16.2651440910995 58.812188878655434) | u6 | POLYGON((11.25 56.25, 22.5 56.25, 22.5 61.875, 11.25 61.875, 11.25 56.25)) +4 | POINT (7.7012718468904495 36.39783004182391) | sn | POLYGON((0.0 33.75, 11.25 33.75, 11.25 39.375, 0.0 39.375, 0.0 33.75)) +3 | POINT (14.222751930356026 37.168446206487715) | sq | POLYGON((11.25 33.75, 22.5 33.75, 22.5 39.375, 11.25 39.375, 11.25 33.75)) +3 | POINT (7.318722177296877 59.788265260867774) | u4 | POLYGON((0.0 56.25, 11.25 56.25, 11.25 61.875, 0.0 61.875, 0.0 56.25)) +2 | POINT (16.706149326637387 32.37822346854955) | sm | POLYGON((11.25 28.125, 22.5 28.125, 22.5 33.75, 11.25 33.75, 11.25 28.125)) ; gridGeohashStatsByPointsBounds @@ -198,22 +242,37 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohash | EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) -| KEEP count, centroid, geohashString +| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +| KEEP count, centroid, geohashString, cellBoundary | SORT count DESC, geohashString ASC ; -count:long | centroid:geo_point | geohashString:keyword -19 | POINT (6.360728044651057 47.94084087577894) | u0 -10 | POINT (15.350638423115015 47.80751353036612) | u2 -9 | POINT (18.5217544157058 42.1394603792578) | sr -8 | POINT (6.351574736181647 51.8981519783847) | u1 -7 | POINT (5.268637698941997 42.747250193330856) | sp -7 | POINT (17.092350951528974 53.365471504096476) | u3 -5 | POINT (16.2651440910995 58.812188878655434) | u6 -4 | POINT (7.7012718468904495 36.39783004182391) | sn -3 | POINT (14.222751930356026 37.168446206487715) | sq -3 | POINT (7.318722177296877 59.788265260867774) | u4 -2 | POINT (16.706149326637387 32.37822346854955) | sm +count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape +19 | POINT (6.360728044651057 47.94084087577894) | u0 | POLYGON((0.0 45.0, 11.25 45.0, 11.25 50.625, 0.0 50.625, 0.0 45.0)) +10 | POINT (15.350638423115015 47.80751353036612) | u2 | POLYGON((11.25 45.0, 22.5 45.0, 22.5 50.625, 11.25 50.625, 11.25 45.0)) +9 | POINT (18.5217544157058 42.1394603792578) | sr | POLYGON((11.25 39.375, 22.5 39.375, 22.5 45.0, 11.25 45.0, 11.25 39.375)) +8 | POINT (6.351574736181647 51.8981519783847) | u1 | POLYGON((0.0 50.625, 11.25 50.625, 11.25 56.25, 0.0 56.25, 0.0 50.625)) +7 | POINT (5.268637698941997 42.747250193330856) | sp | POLYGON((0.0 39.375, 11.25 39.375, 11.25 45.0, 0.0 45.0, 0.0 39.375)) +7 | POINT (17.092350951528974 53.365471504096476) | u3 | POLYGON((11.25 50.625, 22.5 50.625, 22.5 56.25, 11.25 56.25, 11.25 50.625)) +5 | POINT (16.2651440910995 58.812188878655434) | u6 | POLYGON((11.25 56.25, 22.5 56.25, 22.5 61.875, 11.25 61.875, 11.25 56.25)) +4 | POINT (7.7012718468904495 36.39783004182391) | sn | POLYGON((0.0 33.75, 11.25 33.75, 11.25 39.375, 0.0 39.375, 0.0 33.75)) +3 | POINT (14.222751930356026 37.168446206487715) | sq | POLYGON((11.25 33.75, 22.5 33.75, 22.5 39.375, 11.25 39.375, 11.25 33.75)) +3 | POINT (7.318722177296877 59.788265260867774) | u4 | POLYGON((0.0 56.25, 11.25 56.25, 11.25 61.875, 0.0 61.875, 0.0 56.25)) +2 | POINT (16.706149326637387 32.37822346854955) | sm | POLYGON((11.25 28.125, 22.5 28.125, 22.5 33.75, 11.25 33.75, 11.25 28.125)) +; + +gridGeohashDocsFromCell +required_capability: spatial_grid + +FROM airports +| WHERE ST_INTERSECTS(location, ST_GEOHASH_TO_GEOSHAPE("u1")) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) +; + +count:long | centroid:geo_point +8 | POINT (6.351574736181647 51.8981519783847) ; gridGeohashStatsByWhereUK @@ -227,13 +286,14 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohash | EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) -| KEEP count, centroid, geohashString +| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +| KEEP count, centroid, geohashString, cellBoundary | SORT count DESC ; -count:long | centroid:geo_point | geohashString:keyword -14 | POINT (-2.5644131543646966 53.38093495994274) | gc -3 | POINT (-2.7510103583335876 58.79020635969937) | gf +count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape +14 | POINT (-2.5644131543646966 53.38093495994274) | gc | POLYGON((-11.25 50.625, 0.0 50.625, 0.0 56.25, -11.25 56.25, -11.25 50.625)) +3 | POINT (-2.7510103583335876 58.79020635969937) | gf | POLYGON((-11.25 56.25, 0.0 56.25, 0.0 61.875, -11.25 61.875, -11.25 56.25)) ; gridGeohashStatsByBoundsUK @@ -248,16 +308,17 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohash | EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) -| KEEP count, centroid, geohashString +| EVAL cellBoundary = ST_GEOHASH_TO_GEOSHAPE(geohash) +| KEEP count, centroid, geohashString, cellBoundary | SORT count DESC, geohashString ASC ; -count:long | centroid:geo_point | geohashString:keyword -19 | POINT (6.360728044651057 47.94084087577894) | u0 -17 | POINT (-3.5034258844440473 53.25306422789307) | gc -8 | POINT (6.351574736181647 51.8981519783847) | u1 -3 | POINT (-2.7510103583335876 58.79020635969937) | gf -3 | POINT (7.318722177296877 59.788265260867774) | u4 +count:long | centroid:geo_point | geohashString:keyword | cellBoundary:geo_shape +19 | POINT (6.360728044651057 47.94084087577894) | u0 | POLYGON((0.0 45.0, 11.25 45.0, 11.25 50.625, 0.0 50.625, 0.0 45.0)) +17 | POINT (-3.5034258844440473 53.25306422789307) | gc | POLYGON((-11.25 50.625, 0.0 50.625, 0.0 56.25, -11.25 56.25, -11.25 50.625)) +8 | POINT (6.351574736181647 51.8981519783847) | u1 | POLYGON((0.0 50.625, 11.25 50.625, 11.25 56.25, 0.0 56.25, 0.0 50.625)) +3 | POINT (-2.7510103583335876 58.79020635969937) | gf | POLYGON((-11.25 56.25, 0.0 56.25, 0.0 61.875, -11.25 61.875, -11.25 56.25)) +3 | POINT (7.318722177296877 59.788265260867774) | u4 | POLYGON((0.0 56.25, 11.25 56.25, 11.25 61.875, 0.0 61.875, 0.0 56.25)) ; gridGeohashInStatsBy @@ -338,6 +399,21 @@ geotile:long | geotileString:keyword // end::geotile_to_string-result[] ; +geotileStringToGeoshape +required_capability: spatial_grid + +// tag::geotile_to_geoshape[] +ROW geotile = "4/8/5" +| EVAL boundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +// end::geotile_to_geoshape[] +; + +// tag::geotile_to_geoshape-result[] +geotile:keyword | boundary:geo_shape +4/8/5 | POLYGON((0.0 40.979898069620134, 22.5 40.979898069620134, 22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 40.979898069620134)) +// end::geotile_to_geoshape-result[] +; + geotileLiteral required_capability: spatial_grid @@ -387,6 +463,23 @@ POINT (12.6493508684508 55.6285017221528) | 4 | 1152921508901814 POINT (12.6493508684508 55.6285017221528) | 5 | 1441151889885364234 | 5/17/10 ; +geotileLiteralMvBoundary +required_capability: spatial_grid + +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] +| MV_EXPAND precision +| EVAL geotile = ST_GEOTILE_TO_STRING(ST_GEOTILE(location, precision)) +| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +; + +location:geo_point | precision:integer | geotile:keyword | cellBoundary:geo_shape +POINT (12.6493508684508 55.6285017221528) | 1 | 1/1/0 | POLYGON((0.0 0.0, 180.0 0.0, 180.0 85.0511287798066, 0.0 85.0511287798066, 0.0 0.0)) +POINT (12.6493508684508 55.6285017221528) | 2 | 2/2/1 | POLYGON((0.0 0.0, 90.0 0.0, 90.0 66.51326044311186, 0.0 66.51326044311186, 0.0 0.0)) +POINT (12.6493508684508 55.6285017221528) | 3 | 3/4/2 | POLYGON((0.0 40.979898069620134, 45.0 40.979898069620134, 45.0 66.51326044311186, 0.0 66.51326044311186, 0.0 40.979898069620134)) +POINT (12.6493508684508 55.6285017221528) | 4 | 4/8/5 | POLYGON((0.0 40.979898069620134, 22.5 40.979898069620134, 22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 40.979898069620134)) +POINT (12.6493508684508 55.6285017221528) | 5 | 5/17/10 | POLYGON((11.25 48.922499263758255, 22.5 48.922499263758255, 22.5 55.77657301866769, 11.25 55.77657301866769, 11.25 48.922499263758255)) +; + geotileField required_capability: spatial_grid @@ -464,13 +557,14 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geotile | EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) | SORT count DESC, geotileString ASC -| KEEP count, centroid, geotileString +| KEEP count, centroid, geotileString, cellBoundary ; -count:long | centroid:geo_point | geotileString:keyword -100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 -79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 +count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape +100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 | POLYGON((0.0 40.979898069620134, 45.0 40.979898069620134, 45.0 66.51326044311186, 0.0 66.51326044311186, 0.0 40.979898069620134)) +79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 | POLYGON((0.0 0.0, 45.0 0.0, 45.0 40.979898069620134, 0.0 40.979898069620134, 0.0 0.0)) ; gridGeotileStatsByPointsBounds @@ -485,13 +579,28 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geotile | EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) -| KEEP count, centroid, geotileString +| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +| KEEP count, centroid, geotileString, cellBoundary | SORT count DESC, geotileString ASC ; -count:long | centroid:geo_point | geotileString:keyword -100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 -79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 +count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape +100 | POINT (18.10569669920951 50.40505832391791) | 3/4/2 | POLYGON((0.0 40.979898069620134, 45.0 40.979898069620134, 45.0 66.51326044311186, 0.0 66.51326044311186, 0.0 40.979898069620134)) +79 | POINT (24.516750878736943 23.93036561181085) | 3/4/3 | POLYGON((0.0 0.0, 45.0 0.0, 45.0 40.979898069620134, 0.0 40.979898069620134, 0.0 0.0)) +; + +gridGeotileDocsFromCell +required_capability: spatial_grid + +FROM airports +| WHERE ST_INTERSECTS(location, ST_GEOTILE_TO_GEOSHAPE("3/4/3")) +| STATS + count = COUNT(*), + centroid = ST_CENTROID_AGG(location) +; + +count:long | centroid:geo_point +79 | POINT (24.516750878736943 23.93036561181085) ; gridGeotileStatsByWhereUK @@ -505,13 +614,14 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geotile | EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) -| KEEP count, centroid, geotileString +| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +| KEEP count, centroid, geotileString, cellBoundary | SORT count DESC ; -count:long | centroid:geo_point | geotileString:keyword -12 | POINT (-2.342151787597686 52.9600293841213) | 4/7/5 -5 | POINT (-3.2097987569868565 57.63667118176818) | 4/7/4 +count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape +12 | POINT (-2.342151787597686 52.9600293841213) | 4/7/5 | POLYGON((-22.5 40.979898069620134, 0.0 40.979898069620134, 0.0 55.77657301866769, -22.5 55.77657301866769, -22.5 40.979898069620134)) +5 | POINT (-3.2097987569868565 57.63667118176818) | 4/7/4 | POLYGON((-22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 66.51326044311186, -22.5 66.51326044311186, -22.5 55.77657301866769)) ; gridGeotileStatsByBoundsUK @@ -526,15 +636,16 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geotile | EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) -| KEEP count, centroid, geotileString +| EVAL cellBoundary = ST_GEOTILE_TO_GEOSHAPE(geotile) +| KEEP count, centroid, geotileString, cellBoundary | SORT count DESC ; -count:long | centroid:geo_point | geotileString:keyword -56 | POINT (10.54233039047436 47.85997457644304) | 4/8/5 -18 | POINT (-3.5578574100509286 51.27018998377025) | 4/7/5 -11 | POINT (14.310833624648778 59.85619530801407) | 4/8/4 -7 | POINT (-6.466632609122565 59.19681839378817) | 4/7/4 +count:long | centroid:geo_point | geotileString:keyword | cellBoundary:geo_shape +56 | POINT (10.54233039047436 47.85997457644304) | 4/8/5 | POLYGON((0.0 40.979898069620134, 22.5 40.979898069620134, 22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 40.979898069620134)) +18 | POINT (-3.5578574100509286 51.27018998377025) | 4/7/5 | POLYGON((-22.5 40.979898069620134, 0.0 40.979898069620134, 0.0 55.77657301866769, -22.5 55.77657301866769, -22.5 40.979898069620134)) +11 | POINT (14.310833624648778 59.85619530801407) | 4/8/4 | POLYGON((0.0 55.77657301866769, 22.5 55.77657301866769, 22.5 66.51326044311186, 0.0 66.51326044311186, 0.0 55.77657301866769)) +7 | POINT (-6.466632609122565 59.19681839378817) | 4/7/4 | POLYGON((-22.5 55.77657301866769, 0.0 55.77657301866769, 0.0 66.51326044311186, -22.5 66.51326044311186, -22.5 55.77657301866769)) ; gridGeotileInStatsBy @@ -608,6 +719,21 @@ geohex:long | geohexString:keyword // end::geohex_to_string-result[] ; +geohexStringToGeoshape +required_capability: spatial_grid + +// tag::geohex_to_geoshape[] +ROW geohex = "841f059ffffffff" +| EVAL boundary = ST_GEOHEX_TO_GEOSHAPE(geohex) +// end::geohex_to_geoshape[] +; + +// tag::geohex_to_geoshape-result[] +geohex:keyword | boundary:geo_shape +841f059ffffffff | POLYGON ((12.353546327258265 55.80335405461356, 12.2434612967008 55.60502874054935, 12.51733872608954 55.470800201545316, 12.901880149865134 55.53443156197633, 13.014270156228921 55.73262985778208, 12.739822958959069 55.8673267391136, 12.353546327258265 55.80335405461356)) +// end::geohex_to_geoshape-result[] +; + geohexLiteral required_capability: spatial_grid @@ -657,6 +783,23 @@ POINT (12.6493508684508 55.6285017221528) | 4 | 5950208951273390 POINT (12.6493508684508 55.6285017221528) | 5 | 599524487238516735 | 851f0583fffffff ; +geohexLiteralMvBoundary +required_capability: spatial_grid + +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)"), precision = [1,2,3,4,5] +| MV_EXPAND precision +| EVAL geohex = ST_GEOHEX_TO_STRING(ST_GEOHEX(location, precision)) +| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) +; + +location:geo_point | precision:integer | geohex:keyword | cellBoundary:geo_shape +POINT (12.6493508684508 55.6285017221528) | 1 | 811f3ffffffffff | POLYGON ((5.523646549290313 55.70676846515226, 6.259687055981993 51.96477015603749, 12.345747364400065 50.55427508726938, 18.289963485942284 52.81905199947076, 18.2752359517578 56.63295271905082, 11.555977692900722 58.13053116585142, 5.523646549290313 55.70676846515226)) +POINT (12.6493508684508 55.6285017221528) | 2 | 821f07fffffffff | POLYGON ((10.06569233741819 55.3948787035456, 9.374530816292083 53.97551370235174, 11.245170492278875 53.03203973205439, 13.839528609232428 53.48724516123688, 14.640206584543728 54.90218190493179, 12.739822958959062 55.8673267391136, 10.06569233741819 55.3948787035456)) +POINT (12.6493508684508 55.6285017221528) | 3 | 831f05fffffffff | POLYGON ((11.860105203878488 55.53944935104936, 11.917786510985744 55.0057489060893, 12.839846498886947 54.79854371636354, 13.717124800902113 55.12308086302377, 13.674892957473272 55.65810153974231, 12.739822958959069 55.8673267391136, 11.860105203878488 55.53944935104936)) +POINT (12.6493508684508 55.6285017221528) | 4 | 841f059ffffffff | POLYGON ((12.353546327258265 55.80335405461356, 12.2434612967008 55.60502874054935, 12.51733872608954 55.470800201545316, 12.901880149865134 55.53443156197633, 13.014270156228921 55.73262985778208, 12.739822958959069 55.8673267391136, 12.353546327258265 55.80335405461356)) +POINT (12.6493508684508 55.6285017221528) | 5 | 851f0583fffffff | POLYGON ((12.494766876566144 55.69864155255122, 12.502309582573728 55.6227995792834, 12.635566668537882 55.59351730049433, 12.761550811198047 55.640035539252175, 12.754326292782508 55.71590456460875, 12.62079911077343 55.745228479933665, 12.494766876566144 55.69864155255122)) +; + geohexField required_capability: spatial_grid @@ -739,22 +882,23 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohex | EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) | SORT count DESC, geohexString ASC -| KEEP count, centroid, geohexString +| KEEP count, centroid, geohexString, cellBoundary ; -count:long | centroid:geo_point | geohexString:keyword -22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff -17 | POINT (-0.7606179875266903 52.86413913565304) | 81197ffffffffff -7 | POINT (2.475211258445467 41.32352174592337) | 81397ffffffffff -6 | POINT (11.75047050230205 42.351422344800085) | 811ebffffffffff -5 | POINT (18.766171680763364 59.15833930950612) | 8108bffffffffff -5 | POINT (11.404999259859324 54.510593589395285) | 811f3ffffffffff -4 | POINT (5.167026452254504 59.81037143385038) | 8109bffffffffff -4 | POINT (-1.1871178611181676 35.77457194332965) | 81383ffffffffff -3 | POINT (-1.1497433669865131 45.83295159973204) | 81187ffffffffff -3 | POINT (9.197671310976148 36.29719984252006) | 81387ffffffffff -1 | POINT (13.144258903339505 32.66916951164603) | 813fbffffffffff +count:long | centroid:geo_point | geohexString:keyword | cellBoundary:geo_shape +22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff | POLYGON ((1.1885095534434493 49.47027919866873, 2.026568965384636 45.18424868970643, 7.509948481928886 43.786609353945, 12.677317810359858 46.40695745798227, 12.345747364400065 50.55427508726938, 6.259687055981993 51.96477015603749, 3.6300086390995467 50.6104633125695, 1.1885095534434493 49.47027919866873)) +17 | POINT (-0.7606179875266903 52.86413913565304) | 81197ffffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -6.436337296790312 55.3773904155485, -4.889760342933795 51.22372845966177, 1.1885095534434493 49.47027919866873, 3.6300086390995365 50.610463312569514, 6.259687055981993 51.96477015603749, 5.523646549290304 55.70676846515228, -0.9315871635106163 57.689497374592854)) +7 | POINT (2.475211258445467 41.32352174592337) | 81397ffffffffff | POLYGON ((-2.4177958307002347 42.54047996565121, -1.416234262837718 38.1159967227654, 0.2387159546288331 37.58884624349159, 3.543589356987798 36.59789814478598, 8.045142114241353 39.40213636897177, 7.509948481928886 43.786609353945, 2.026568965384636 45.18424868970643, -2.4177958307002347 42.54047996565121)) +6 | POINT (11.75047050230205 42.351422344800085) | 811ebffffffffff | POLYGON ((7.509948481928886 43.786609353945, 8.045142114241353 39.40213636897177, 13.244313475659823 37.5237123657852, 18.325260281104846 39.988177963363235, 18.314740441319 44.47067958889503, 12.677317810359858 46.40695745798227, 7.509948481928886 43.786609353945)) +5 | POINT (18.766171680763364 59.15833930950612) | 8108bffffffffff | POLYGON ((11.080660058482376 61.54051460002519, 11.555977692900722 58.13053116585142, 18.2752359517578 56.63295271905082, 25.082722326707877 58.4015448703527, 24.517172437523495 62.47811345192472, 17.53544630840839 63.800792653212156, 15.771773841154092 62.88996835796253, 11.080660058482376 61.54051460002519)) +5 | POINT (11.404999259859324 54.510593589395285) | 811f3ffffffffff | POLYGON ((5.523646549290313 55.70676846515226, 6.259687055981993 51.96477015603749, 12.345747364400065 50.55427508726938, 18.289963485942284 52.81905199947076, 18.2752359517578 56.63295271905082, 11.555977692900722 58.13053116585142, 5.523646549290313 55.70676846515226)) +4 | POINT (5.167026452254504 59.81037143385038) | 8109bffffffffff | POLYGON ((4.012620898449951 63.32706132801842, -2.297526087621831 61.54550957788076, -0.9315871635106163 57.689497374592854, 5.523646549290304 55.70676846515228, 11.555977692900722 58.13053116585142, 11.080660058482376 61.54051460002519, 8.644221197607186 61.8908384753262, 4.012620898449951 63.32706132801842)) +4 | POINT (-1.1871178611181676 35.77457194332965) | 81383ffffffffff | POLYGON ((-5.442348460730093 35.12442405176796, -4.341769247156951 30.69897412778907, -1.2408020165138167 29.828776159725596, 0.26094682603113584 29.300374659234986, 4.204173995672654 32.11010693139568, 3.543589356987798 36.59789814478598, 0.2387159546288331 37.58884624349159, -1.416234262837718 38.1159967227654, -5.442348460730093 35.12442405176796)) +3 | POINT (-1.1497433669865131 45.83295159973204) | 81187ffffffffff | POLYGON ((-4.889760342933795 51.22372845966177, -9.724736207832692 48.43009421958323, -8.101589192291552 44.0506310521871, -2.4177958307002347 42.54047996565121, 2.026568965384605 45.18424868970644, 1.1885095534434493 49.47027919866873, -4.889760342933795 51.22372845966177)) +3 | POINT (9.197671310976148 36.29719984252006) | 81387ffffffffff | POLYGON ((3.543589356987798 36.59789814478598, 4.204173995672654 32.11010693139568, 8.974635637589913 30.254840780701706, 13.488580338198277 32.87501547725471, 13.244313475659823 37.5237123657852, 8.045142114241353 39.40213636897177, 3.543589356987798 36.59789814478598)) +1 | POINT (13.144258903339505 32.66916951164603) | 813fbffffffffff | POLYGON ((8.974635637589913 30.254840780701706, 9.380676605201614 25.60370257696876, 13.915183885634578 23.45043771532035, 18.351304577591982 25.86678026136113, 18.343416368196834 30.62734805513404, 13.488580338198277 32.87501547725471, 8.974635637589913 30.254840780701706)) ; gridGeohexQueryBounds @@ -803,14 +947,15 @@ ROW location = ["POINT (46.035023249891 51.5606456508842)", "POINT (13.144258981 | EVAL geohexBounded = ST_GEOHEX(location, 1, TO_GEOSHAPE("POLYGON((0.0 30.0, 12.0 30.0, 12.0 60.0, 0.0 60.0, 0.0 30.0))")) | EVAL geohex = ST_GEOHEX_TO_STRING(geohex) | EVAL geohexBounded = ST_GEOHEX_TO_STRING(geohexBounded) -| KEEP location, geohex, geohexBounded +| EVAL geohexShape = ST_GEOHEX_TO_GEOSHAPE(geohex) +| KEEP location, geohex, geohexBounded, geohexShape | SORT geohex ASC ; -location:geo_point | geohex:keyword | geohexBounded:keyword -POINT (46.035023249891 51.5606456508842) | 8110bffffffffff | null -POINT (13.1442589810713 32.6691695504993) | 813fbffffffffff | 813fbffffffffff -POINT (118.12696884672 24.537192570557) | 8141bffffffffff | null +location:geo_point | geohex:keyword | geohexBounded:keyword | geohexShape:geo_shape +POINT (46.035023249891 51.5606456508842) | 8110bffffffffff | null | POLYGON ((42.136829069634125 51.40943727610449, 47.038222832332735 48.33994165728296, 53.670493635625505 49.37211750883398, 56.286117998753014 53.74532256646542, 51.15131422930829 57.15637211465772, 43.547481617187756 55.820803924848654, 42.136829069634125 51.40943727610449)) +POINT (13.1442589810713 32.6691695504993) | 813fbffffffffff | 813fbffffffffff | POLYGON ((8.974635637589913 30.254840780701706, 9.380676605201614 25.60370257696876, 13.915183885634578 23.45043771532035, 18.351304577591982 25.86678026136113, 18.343416368196834 30.62734805513404, 13.488580338198277 32.87501547725471, 8.974635637589913 30.254840780701706)) +POINT (118.12696884672 24.537192570557) | 8141bffffffffff | null | POLYGON ((121.34751445935747 26.200276060455465, 120.50339385995798 29.892985338693542, 116.26130043917948 31.68090796798786, 112.74092235558841 29.367231998154967, 113.70376749169584 25.199133186716526, 117.99047716641066 23.5089519597363, 119.64146543031175 24.728661050965922, 121.34751445935747 26.200276060455465)) ; gridGeohexStatsByPointsBounds @@ -825,23 +970,39 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohex | EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) -| KEEP count, centroid, geohexString +| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) +| KEEP count, centroid, geohexString, cellBoundary | SORT count DESC, geohexString ASC ; -count:long | centroid:geo_point | geohexString:keyword -22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff -17 | POINT (-0.7606179875266903 52.86413913565304) | 81197ffffffffff -7 | POINT (2.475211258445467 41.32352174592337) | 81397ffffffffff -6 | POINT (11.75047050230205 42.351422344800085) | 811ebffffffffff -5 | POINT (18.766171680763364 59.15833930950612) | 8108bffffffffff -5 | POINT (11.404999259859324 54.510593589395285) | 811f3ffffffffff -4 | POINT (5.167026452254504 59.81037143385038) | 8109bffffffffff -4 | POINT (-1.1871178611181676 35.77457194332965) | 81383ffffffffff -3 | POINT (-1.1497433669865131 45.83295159973204) | 81187ffffffffff -3 | POINT (9.197671310976148 36.29719984252006) | 81387ffffffffff -1 | POINT (13.144258903339505 32.66916951164603) | 813fbffffffffff -; +count:long | centroid:geo_point | geohexString:keyword | cellBoundary:geo_shape +22 | POINT (7.250850197689777 48.21363834643059) | 811fbffffffffff | POLYGON ((1.1885095534434493 49.47027919866873, 2.026568965384636 45.18424868970643, 7.509948481928886 43.786609353945, 12.677317810359858 46.40695745798227, 12.345747364400065 50.55427508726938, 6.259687055981993 51.96477015603749, 3.6300086390995467 50.6104633125695, 1.1885095534434493 49.47027919866873)) +17 | POINT (-0.7606179875266903 52.86413913565304) | 81197ffffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -6.436337296790312 55.3773904155485, -4.889760342933795 51.22372845966177, 1.1885095534434493 49.47027919866873, 3.6300086390995365 50.610463312569514, 6.259687055981993 51.96477015603749, 5.523646549290304 55.70676846515228, -0.9315871635106163 57.689497374592854)) +7 | POINT (2.475211258445467 41.32352174592337) | 81397ffffffffff | POLYGON ((-2.4177958307002347 42.54047996565121, -1.416234262837718 38.1159967227654, 0.2387159546288331 37.58884624349159, 3.543589356987798 36.59789814478598, 8.045142114241353 39.40213636897177, 7.509948481928886 43.786609353945, 2.026568965384636 45.18424868970643, -2.4177958307002347 42.54047996565121)) +6 | POINT (11.75047050230205 42.351422344800085) | 811ebffffffffff | POLYGON ((7.509948481928886 43.786609353945, 8.045142114241353 39.40213636897177, 13.244313475659823 37.5237123657852, 18.325260281104846 39.988177963363235, 18.314740441319 44.47067958889503, 12.677317810359858 46.40695745798227, 7.509948481928886 43.786609353945)) +5 | POINT (18.766171680763364 59.15833930950612) | 8108bffffffffff | POLYGON ((11.080660058482376 61.54051460002519, 11.555977692900722 58.13053116585142, 18.2752359517578 56.63295271905082, 25.082722326707877 58.4015448703527, 24.517172437523495 62.47811345192472, 17.53544630840839 63.800792653212156, 15.771773841154092 62.88996835796253, 11.080660058482376 61.54051460002519)) +5 | POINT (11.404999259859324 54.510593589395285) | 811f3ffffffffff | POLYGON ((5.523646549290313 55.70676846515226, 6.259687055981993 51.96477015603749, 12.345747364400065 50.55427508726938, 18.289963485942284 52.81905199947076, 18.2752359517578 56.63295271905082, 11.555977692900722 58.13053116585142, 5.523646549290313 55.70676846515226)) +4 | POINT (5.167026452254504 59.81037143385038) | 8109bffffffffff | POLYGON ((4.012620898449951 63.32706132801842, -2.297526087621831 61.54550957788076, -0.9315871635106163 57.689497374592854, 5.523646549290304 55.70676846515228, 11.555977692900722 58.13053116585142, 11.080660058482376 61.54051460002519, 8.644221197607186 61.8908384753262, 4.012620898449951 63.32706132801842)) +4 | POINT (-1.1871178611181676 35.77457194332965) | 81383ffffffffff | POLYGON ((-5.442348460730093 35.12442405176796, -4.341769247156951 30.69897412778907, -1.2408020165138167 29.828776159725596, 0.26094682603113584 29.300374659234986, 4.204173995672654 32.11010693139568, 3.543589356987798 36.59789814478598, 0.2387159546288331 37.58884624349159, -1.416234262837718 38.1159967227654, -5.442348460730093 35.12442405176796)) +3 | POINT (-1.1497433669865131 45.83295159973204) | 81187ffffffffff | POLYGON ((-4.889760342933795 51.22372845966177, -9.724736207832692 48.43009421958323, -8.101589192291552 44.0506310521871, -2.4177958307002347 42.54047996565121, 2.026568965384605 45.18424868970644, 1.1885095534434493 49.47027919866873, -4.889760342933795 51.22372845966177)) +3 | POINT (9.197671310976148 36.29719984252006) | 81387ffffffffff | POLYGON ((3.543589356987798 36.59789814478598, 4.204173995672654 32.11010693139568, 8.974635637589913 30.254840780701706, 13.488580338198277 32.87501547725471, 13.244313475659823 37.5237123657852, 8.045142114241353 39.40213636897177, 3.543589356987798 36.59789814478598)) +1 | POINT (13.144258903339505 32.66916951164603) | 813fbffffffffff | POLYGON ((8.974635637589913 30.254840780701706, 9.380676605201614 25.60370257696876, 13.915183885634578 23.45043771532035, 18.351304577591982 25.86678026136113, 18.343416368196834 30.62734805513404, 13.488580338198277 32.87501547725471, 8.974635637589913 30.254840780701706)) +; + +// TODO: Fix this test +//gridGeohexDocsFromCell +//required_capability: spatial_grid +// +//FROM airports +//| WHERE ST_INTERSECTS(location, ST_GEOHEX_TO_GEOSHAPE("81397ffffffffff")) +//| STATS +// count = COUNT(*), +// centroid = ST_CENTROID_AGG(location) +//; +// +//count:long | centroid:geo_point +//7 | POINT (2.475211258445467 41.32352174592337) +//; gridGeohexStatsByWhereUK required_capability: spatial_grid @@ -854,15 +1015,16 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohex | EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) -| KEEP count, centroid, geohexString +| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) +| KEEP count, centroid, geohexString, cellBoundary | SORT count DESC, geohexString ASC ; -count:long | centroid:geo_point | geohexString:keyword -13 | POINT (-2.283508819169723 53.28242553254733) | 81197ffffffffff -2 | POINT (-3.482485176064074 58.24696456314996) | 81193ffffffffff -1 | POINT (-1.2880607228726149 59.87668995279819) | 8109bffffffffff -1 | POINT (-6.216169511899352 54.66155751608312) | 81183ffffffffff +count:long | centroid:geo_point | geohexString:keyword | cellBoundary:geo_shape +13 | POINT (-2.283508819169723 53.28242553254733) | 81197ffffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -6.436337296790312 55.3773904155485, -4.889760342933795 51.22372845966177, 1.1885095534434493 49.47027919866873, 3.6300086390995365 50.610463312569514, 6.259687055981993 51.96477015603749, 5.523646549290304 55.70676846515228, -0.9315871635106163 57.689497374592854)) +2 | POINT (-3.482485176064074 58.24696456314996) | 81193ffffffffff | POLYGON ((-10.44497754477833 63.09505407752544, -16.37196241724276 60.568693514800756, -13.79164665163863 56.73632442836386, -6.436337296790312 55.3773904155485, -0.9315871635106163 57.689497374592854, -2.297526087621831 61.54550957788076, -10.44497754477833 63.09505407752544)) +1 | POINT (-1.2880607228726149 59.87668995279819) | 8109bffffffffff | POLYGON ((4.012620898449951 63.32706132801842, -2.297526087621831 61.54550957788076, -0.9315871635106163 57.689497374592854, 5.523646549290304 55.70676846515228, 11.555977692900722 58.13053116585142, 11.080660058482376 61.54051460002519, 8.644221197607186 61.8908384753262, 4.012620898449951 63.32706132801842)) +1 | POINT (-6.216169511899352 54.66155751608312) | 81183ffffffffff | POLYGON ((-13.79164665163863 56.73632442836386, -18.841171686388584 53.74020675223833, -16.3823406256948 49.6092693973489, -9.724736207832692 48.43009421958323, -4.889760342933795 51.22372845966177, -6.436337296790312 55.3773904155485, -13.79164665163863 56.73632442836386)) ; gridGeohexStatsByBoundsUK @@ -877,25 +1039,26 @@ FROM airports centroid = ST_CENTROID_AGG(location) BY geohex | EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) -| KEEP count, centroid, geohexString +| EVAL cellBoundary = ST_GEOHEX_TO_GEOSHAPE(geohex) +| KEEP count, centroid, geohexString, cellBoundary | SORT count DESC, geohexString ASC ; -count:long | centroid:geo_point | geohexString:keyword -5 | POINT (-1.7227098606526852 51.717823022045195) | 82195ffffffffff -4 | POINT (-3.9897833741270006 54.21732849790715) | 821957fffffffff -3 | POINT (-7.885485291481018 52.65633414499462) | 82182ffffffffff -3 | POINT (3.0334555450826883 48.842039234004915) | 821fb7fffffffff -2 | POINT (5.428531668148935 59.585608751513064) | 820987fffffffff -2 | POINT (-4.2476349184289575 56.70184155693278) | 82190ffffffffff -2 | POINT (1.4715016074478626 50.863699545152485) | 82194ffffffffff -2 | POINT (4.5991105819121 52.129031270742416) | 82196ffffffffff -2 | POINT (-2.5373152876272798 55.49281941493973) | 821977fffffffff -1 | POINT (-1.2880607228726149 59.87668995279819) | 8209a7fffffffff -1 | POINT (0.15865350142121315 49.36166098807007) | 821867fffffffff -1 | POINT (-7.270800014957786 62.06249998882413) | 821927fffffffff -1 | POINT (-2.9013785161077976 58.95442885346711) | 82192ffffffffff -1 | POINT (-1.6598310694098473 53.8690819311887) | 821947fffffffff +count:long | centroid:geo_point | geohexString:keyword | cellBoundary:geo_shape +5 | POINT (-1.7227098606526852 51.717823022045195) | 82195ffffffffff | POLYGON ((-2.1788859209290505 53.251551050714795, -4.578382413982977 52.792439042763036, -4.889760342933795 51.22372845966177, -2.906527879284175 50.14229216995713, -0.6310947579755295 50.60191112048408, -0.21913743445926337 52.1416808182628, -2.1788859209290505 53.251551050714795)) +4 | POINT (-3.9897833741270006 54.21732849790715) | 821957fffffffff | POLYGON ((-3.9031812914854935 55.840605806464886, -6.436337296790312 55.3773904155485, -6.713499065102683 53.841053788108646, -4.578382413982977 52.792439042763036, -2.1788859209290505 53.251551050714795, -1.7855433613316123 54.76238836624054, -3.9031812914854935 55.840605806464886)) +3 | POINT (-7.885485291481018 52.65633414499462) | 82182ffffffffff | POLYGON ((-6.713499065102683 53.841053788108646, -9.16699332513357 53.28908444969493, -9.362891292036808 51.69686278886942, -7.224493860559402 50.67904691252102, -4.889760342933795 51.22372845966177, -4.578382413982977 52.792439042763036, -6.713499065102683 53.841053788108646)) +3 | POINT (3.0334555450826883 48.842039234004915) | 821fb7fffffffff | POLYGON ((1.1885095534434493 49.47027919866873, 0.7640259623867446 47.90745035042651, 2.458901717447715 46.76373050573097, 4.652435425239358 47.393027403288, 5.163510941569062 48.943763955054884, 3.3847715100589153 49.85377035058955, 1.1885095534434493 49.47027919866873)) +2 | POINT (5.428531668148935 59.585608751513064) | 820987fffffffff | POLYGON ((5.479068693190393 60.92198553471913, 2.767527791540729 60.73321011494055, 2.198216040575142 59.383886486983954, 4.229785449235632 58.25202580757624, 6.766112799653718 58.44709614018101, 7.4384643434389535 59.76718020289119, 5.479068693190393 60.92198553471913)) +2 | POINT (-4.2476349184289575 56.70184155693278) | 82190ffffffffff | POLYGON ((-5.832270115239392 58.353838498476094, -8.508655388670189 57.8811306023458, -8.740899630542538 56.38258811071853, -6.436337296790312 55.3773904155485, -3.9031812914854935 55.840605806464886, -3.536381138969186 57.31728796714347, -5.832270115239392 58.353838498476094)) +2 | POINT (1.4715016074478626 50.863699545152485) | 82194ffffffffff | POLYGON ((2.101313983947425 52.51713397842229, -0.21913743445926337 52.1416808182628, -0.6310947579755295 50.60191112048408, 1.1885095534434493 49.47027919866873, 3.384771510058846 49.85377035058955, 3.8811335596706074 51.360376195950145, 2.101313983947425 52.51713397842229)) +2 | POINT (4.5991105819121 52.129031270742416) | 82196ffffffffff | POLYGON ((4.948742151508294 54.2882866932292, 2.592789031305367 53.99775155222293, 2.101313983947425 52.51713397842229, 3.8811335596706074 51.360376195950145, 6.259687055981993 51.96477015603749, 6.8482289070479005 53.43156035343158, 4.948742151508294 54.2882866932292)) +2 | POINT (-2.5373152876272798 55.49281941493973) | 821977fffffffff | POLYGON ((-0.9315871635106163 57.689497374592854, -3.536381138969186 57.31728796714347, -3.9031812914854935 55.840605806464886, -1.7855433613316123 54.76238836624054, 0.6707588590220377 55.133805943055435, 1.1521975506221078 56.583354389307445, -0.9315871635106163 57.689497374592854)) +1 | POINT (-1.2880607228726149 59.87668995279819) | 8209a7fffffffff | POLYGON ((0.5480202135218006 61.82886471359379, -2.297526087621831 61.54550957788076, -2.7356231170279166 60.17050935552437, -0.4671324618104694 59.1035939329508, 2.198216040575142 59.383886486983954, 2.767527791540729 60.73321011494055, 0.5480202135218006 61.82886471359379)) +1 | POINT (0.15865350142121315 49.36166098807007) | 821867fffffffff | POLYGON ((-0.6310947579755295 50.60191112048408, -2.906527879284175 50.14229216995713, -3.2436562689082553 48.547301491418715, -1.3966081625912774 47.44351195977148, 0.7640259623867446 47.90745035042651, 1.1885095534434493 49.47027919866873, -0.6310947579755295 50.60191112048408)) +1 | POINT (-7.270800014957786 62.06249998882413) | 821927fffffffff | POLYGON ((-4.777634484041529 62.56377272218282, -7.72004205669337 62.172198741500715, -7.999682127502827 60.77664727688846, -5.502334925300172 59.7918551703578, -2.7356231170279166 60.17050935552437, -2.297526087621831 61.54550957788076, -4.777634484041529 62.56377272218282)) +1 | POINT (-2.9013785161077976 58.95442885346711) | 82192ffffffffff | POLYGON ((-2.7356231170279166 60.17050935552437, -5.502334925300172 59.7918551703578, -5.832270115239392 58.353838498476094, -3.536381138969186 57.31728796714347, -0.9315871635106163 57.689497374592854, -0.4671324618104694 59.1035939329508, -2.7356231170279166 60.17050935552437)) +1 | POINT (-1.6598310694098473 53.8690819311887) | 821947fffffffff | POLYGON ((0.6707588590220377 55.133805943055435, -1.7855433613316123 54.76238836624054, -2.1788859209290505 53.251551050714795, -0.21913743445926337 52.1416808182628, 2.101313983947425 52.51713397842229, 2.592789031305367 53.99775155222293, 0.6707588590220377 55.133805943055435)) ; gridGeohexInStatsByBounds diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromLongEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromLongEvaluator.java new file mode 100644 index 0000000000000..3e95b8a55d7e9 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromLongEvaluator.java @@ -0,0 +1,124 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.LongVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohashToGeoShape}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeohashToGeoShapeFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeohashToGeoShapeFromLongEvaluator(Source source, + EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + LongVector vector = (LongVector) v; + int positionCount = v.getPositionCount(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p)); + } + return builder.build(); + } + } + + private BytesRef evalValue(LongVector container, int index) { + long value = container.getLong(index); + return StGeohashToGeoShape.fromLong(value); + } + + @Override + public Block evalBlock(Block b) { + LongBlock block = (LongBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(LongBlock container, int index) { + long value = container.getLong(index); + return StGeohashToGeoShape.fromLong(value); + } + + @Override + public String toString() { + return "StGeohashToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeohashToGeoShapeFromLongEvaluator get(DriverContext context) { + return new StGeohashToGeoShapeFromLongEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeohashToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java new file mode 100644 index 0000000000000..0e50257a50bed --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeFromStringEvaluator.java @@ -0,0 +1,144 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.OrdinalBytesRefVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohashToGeoShape}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeohashToGeoShapeFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeohashToGeoShapeFromStringEvaluator(Source source, + EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + BytesRefVector vector = (BytesRefVector) v; + OrdinalBytesRefVector ordinals = vector.asOrdinals(); + if (ordinals != null) { + return evalOrdinals(ordinals); + } + int positionCount = v.getPositionCount(); + BytesRef scratchPad = new BytesRef(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0, scratchPad), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p, scratchPad)); + } + return builder.build(); + } + } + + private BytesRef evalValue(BytesRefVector container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeohashToGeoShape.fromString(value); + } + + @Override + public Block evalBlock(Block b) { + BytesRefBlock block = (BytesRefBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + BytesRef scratchPad = new BytesRef(); + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i, scratchPad); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeohashToGeoShape.fromString(value); + } + + private Block evalOrdinals(OrdinalBytesRefVector v) { + int positionCount = v.getDictionaryVector().getPositionCount(); + BytesRef scratchPad = new BytesRef(); + try (BytesRefVector.Builder builder = driverContext.blockFactory().newBytesRefVectorBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(v.getDictionaryVector(), p, scratchPad)); + } + IntVector ordinals = v.getOrdinalsVector(); + ordinals.incRef(); + return new OrdinalBytesRefVector(ordinals, builder.build()).asBlock(); + } + } + + @Override + public String toString() { + return "StGeohashToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeohashToGeoShapeFromStringEvaluator get(DriverContext context) { + return new StGeohashToGeoShapeFromStringEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeohashToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromLongEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromLongEvaluator.java new file mode 100644 index 0000000000000..250c2159e380b --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromLongEvaluator.java @@ -0,0 +1,124 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.LongVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohexToGeoShape}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeohexToGeoShapeFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeohexToGeoShapeFromLongEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, + DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + LongVector vector = (LongVector) v; + int positionCount = v.getPositionCount(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p)); + } + return builder.build(); + } + } + + private BytesRef evalValue(LongVector container, int index) { + long value = container.getLong(index); + return StGeohexToGeoShape.fromLong(value); + } + + @Override + public Block evalBlock(Block b) { + LongBlock block = (LongBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(LongBlock container, int index) { + long value = container.getLong(index); + return StGeohexToGeoShape.fromLong(value); + } + + @Override + public String toString() { + return "StGeohexToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeohexToGeoShapeFromLongEvaluator get(DriverContext context) { + return new StGeohexToGeoShapeFromLongEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeohexToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java new file mode 100644 index 0000000000000..94887bda9c960 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeFromStringEvaluator.java @@ -0,0 +1,144 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.OrdinalBytesRefVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohexToGeoShape}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeohexToGeoShapeFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeohexToGeoShapeFromStringEvaluator(Source source, + EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + BytesRefVector vector = (BytesRefVector) v; + OrdinalBytesRefVector ordinals = vector.asOrdinals(); + if (ordinals != null) { + return evalOrdinals(ordinals); + } + int positionCount = v.getPositionCount(); + BytesRef scratchPad = new BytesRef(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0, scratchPad), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p, scratchPad)); + } + return builder.build(); + } + } + + private BytesRef evalValue(BytesRefVector container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeohexToGeoShape.fromString(value); + } + + @Override + public Block evalBlock(Block b) { + BytesRefBlock block = (BytesRefBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + BytesRef scratchPad = new BytesRef(); + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i, scratchPad); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeohexToGeoShape.fromString(value); + } + + private Block evalOrdinals(OrdinalBytesRefVector v) { + int positionCount = v.getDictionaryVector().getPositionCount(); + BytesRef scratchPad = new BytesRef(); + try (BytesRefVector.Builder builder = driverContext.blockFactory().newBytesRefVectorBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(v.getDictionaryVector(), p, scratchPad)); + } + IntVector ordinals = v.getOrdinalsVector(); + ordinals.incRef(); + return new OrdinalBytesRefVector(ordinals, builder.build()).asBlock(); + } + } + + @Override + public String toString() { + return "StGeohexToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeohexToGeoShapeFromStringEvaluator get(DriverContext context) { + return new StGeohexToGeoShapeFromStringEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeohexToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromLongEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromLongEvaluator.java new file mode 100644 index 0000000000000..e625fb7443aab --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromLongEvaluator.java @@ -0,0 +1,124 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.LongBlock; +import org.elasticsearch.compute.data.LongVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotileToGeoShape}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeotileToGeoShapeFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeotileToGeoShapeFromLongEvaluator(Source source, + EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + LongVector vector = (LongVector) v; + int positionCount = v.getPositionCount(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p)); + } + return builder.build(); + } + } + + private BytesRef evalValue(LongVector container, int index) { + long value = container.getLong(index); + return StGeotileToGeoShape.fromLong(value); + } + + @Override + public Block evalBlock(Block b) { + LongBlock block = (LongBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(LongBlock container, int index) { + long value = container.getLong(index); + return StGeotileToGeoShape.fromLong(value); + } + + @Override + public String toString() { + return "StGeotileToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeotileToGeoShapeFromLongEvaluator get(DriverContext context) { + return new StGeotileToGeoShapeFromLongEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeotileToGeoShapeFromLongEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java new file mode 100644 index 0000000000000..801bf228e6adf --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeFromStringEvaluator.java @@ -0,0 +1,144 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License +// 2.0; you may not use this file except in compliance with the Elastic License +// 2.0. +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import java.lang.Override; +import java.lang.String; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.BytesRefVector; +import org.elasticsearch.compute.data.IntVector; +import org.elasticsearch.compute.data.OrdinalBytesRefVector; +import org.elasticsearch.compute.data.Vector; +import org.elasticsearch.compute.operator.DriverContext; +import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.core.Releasables; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotileToGeoShape}. + * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. + */ +public final class StGeotileToGeoShapeFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private final EvalOperator.ExpressionEvaluator gridId; + + public StGeotileToGeoShapeFromStringEvaluator(Source source, + EvalOperator.ExpressionEvaluator gridId, DriverContext driverContext) { + super(driverContext, source); + this.gridId = gridId; + } + + @Override + public EvalOperator.ExpressionEvaluator next() { + return gridId; + } + + @Override + public Block evalVector(Vector v) { + BytesRefVector vector = (BytesRefVector) v; + OrdinalBytesRefVector ordinals = vector.asOrdinals(); + if (ordinals != null) { + return evalOrdinals(ordinals); + } + int positionCount = v.getPositionCount(); + BytesRef scratchPad = new BytesRef(); + if (vector.isConstant()) { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0, scratchPad), positionCount); + } + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(vector, p, scratchPad)); + } + return builder.build(); + } + } + + private BytesRef evalValue(BytesRefVector container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeotileToGeoShape.fromString(value); + } + + @Override + public Block evalBlock(Block b) { + BytesRefBlock block = (BytesRefBlock) b; + int positionCount = block.getPositionCount(); + try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { + BytesRef scratchPad = new BytesRef(); + for (int p = 0; p < positionCount; p++) { + int valueCount = block.getValueCount(p); + int start = block.getFirstValueIndex(p); + int end = start + valueCount; + boolean positionOpened = false; + boolean valuesAppended = false; + for (int i = start; i < end; i++) { + BytesRef value = evalValue(block, i, scratchPad); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } + if (valuesAppended == false) { + builder.appendNull(); + } else if (positionOpened) { + builder.endPositionEntry(); + } + } + return builder.build(); + } + } + + private BytesRef evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { + BytesRef value = container.getBytesRef(index, scratchPad); + return StGeotileToGeoShape.fromString(value); + } + + private Block evalOrdinals(OrdinalBytesRefVector v) { + int positionCount = v.getDictionaryVector().getPositionCount(); + BytesRef scratchPad = new BytesRef(); + try (BytesRefVector.Builder builder = driverContext.blockFactory().newBytesRefVectorBuilder(positionCount)) { + for (int p = 0; p < positionCount; p++) { + builder.appendBytesRef(evalValue(v.getDictionaryVector(), p, scratchPad)); + } + IntVector ordinals = v.getOrdinalsVector(); + ordinals.incRef(); + return new OrdinalBytesRefVector(ordinals, builder.build()).asBlock(); + } + } + + @Override + public String toString() { + return "StGeotileToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(gridId); + } + + public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { + private final Source source; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + this.source = source; + this.gridId = gridId; + } + + @Override + public StGeotileToGeoShapeFromStringEvaluator get(DriverContext context) { + return new StGeotileToGeoShapeFromStringEvaluator(source, gridId.get(context), context); + } + + @Override + public String toString() { + return "StGeotileToGeoShapeFromStringEvaluator[" + "gridId=" + gridId + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java index ffb566b59f894..6b520ee4c034d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/ExpressionWritables.java @@ -59,12 +59,15 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StDistance; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StEnvelope; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohash; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToGeoShape; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToLong; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohex; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToGeoShape; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToLong; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotile; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToGeoShape; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToLong; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StX; @@ -230,12 +233,15 @@ private static List spatials() { StGeohash.ENTRY, StGeohashToString.ENTRY, StGeohashToLong.ENTRY, + StGeohashToGeoShape.ENTRY, StGeotile.ENTRY, StGeotileToString.ENTRY, StGeotileToLong.ENTRY, + StGeotileToGeoShape.ENTRY, StGeohex.ENTRY, StGeohexToString.ENTRY, - StGeohexToLong.ENTRY + StGeohexToLong.ENTRY, + StGeohexToGeoShape.ENTRY ); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index 4851259f3fd10..95d2b284152df 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -132,12 +132,15 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StDistance; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StEnvelope; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohash; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToGeoShape; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToLong; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohashToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohex; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToGeoShape; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToLong; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohexToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotile; +import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToGeoShape; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToLong; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToString; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StX; @@ -391,12 +394,15 @@ private static FunctionDefinition[][] functions() { def(StX.class, StX::new, "st_x"), def(StY.class, StY::new, "st_y"), def(StGeohash.class, StGeohash::new, "st_geohash"), + def(StGeohashToGeoShape.class, StGeohashToGeoShape::new, "st_geohash_to_geoshape"), def(StGeohashToLong.class, StGeohashToLong::new, "st_geohash_to_long"), def(StGeohashToString.class, StGeohashToString::new, "st_geohash_to_string"), def(StGeotile.class, StGeotile::new, "st_geotile"), + def(StGeotileToGeoShape.class, StGeotileToGeoShape::new, "st_geotile_to_geoshape"), def(StGeotileToLong.class, StGeotileToLong::new, "st_geotile_to_long"), def(StGeotileToString.class, StGeotileToString::new, "st_geotile_to_string"), def(StGeohex.class, StGeohex::new, "st_geohex"), + def(StGeohexToGeoShape.class, StGeohexToGeoShape::new, "st_geohex_to_geoshape"), def(StGeohexToLong.class, StGeohexToLong::new, "st_geohex_to_long"), def(StGeohexToString.class, StGeohexToString::new, "st_geohex_to_string") }, // conditional diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java new file mode 100644 index 0000000000000..b205ca194dbc9 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShape.java @@ -0,0 +1,103 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; +import static org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotileToGeoShape.fromRectangle; + +public class StGeohashToGeoShape extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeohashToGeoShape", + StGeohashToGeoShape::new + ); + + private static final Map EVALUATORS = Map.ofEntries( + Map.entry(KEYWORD, StGeohashToGeoShapeFromStringEvaluator.Factory::new), + Map.entry(LONG, StGeohashToGeoShapeFromLongEvaluator.Factory::new) + ); + + @FunctionInfo( + returnType = "geo_shape", + description = """ + Converts an input value to a `geo_shape` value. + The input values are expected to be the grid-ids of geohash grids, in either long or string format.""", + examples = @Example(file = "spatial-grid", tag = "geohash_to_geoshape"), + depthOffset = 1 // make it appear as a subsection of ST_GEOHASH + ) + public StGeohashToGeoShape( + Source source, + @Param( + name = "grid_id", + type = { "keyword", "long" }, + description = "Input geohash grid-id. The input can be a single- or multi-valued column or an expression." + ) Expression v + ) { + super(source, v); + } + + private StGeohashToGeoShape(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + protected Map factories() { + return EVALUATORS; + } + + @Override + public DataType dataType() { + return GEO_SHAPE; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new StGeohashToGeoShape(source(), newChildren.get(0)); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeohashToGeoShape::new, field()); + } + + @ConvertEvaluator(extraName = "FromString") + static BytesRef fromString(BytesRef gridId) { + return fromRectangle(Geohash.toBoundingBox(gridId.utf8ToString())); + } + + @ConvertEvaluator(extraName = "FromLong") + static BytesRef fromLong(long gridId) { + return fromRectangle(Geohash.toBoundingBox(Geohash.stringEncode(gridId))); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java new file mode 100644 index 0000000000000..816fadb6061c2 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShape.java @@ -0,0 +1,122 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.geometry.LinearRing; +import org.elasticsearch.geometry.Polygon; +import org.elasticsearch.h3.CellBoundary; +import org.elasticsearch.h3.H3; +import org.elasticsearch.h3.LatLng; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; + +public class StGeohexToGeoShape extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeohexToGeoShape", + StGeohexToGeoShape::new + ); + + private static final Map EVALUATORS = Map.ofEntries( + Map.entry(KEYWORD, StGeohexToGeoShapeFromStringEvaluator.Factory::new), + Map.entry(LONG, StGeohexToGeoShapeFromLongEvaluator.Factory::new) + ); + + @FunctionInfo( + returnType = "geo_shape", + description = """ + Converts an input value to a `geo_shape` value. + The input values are expected to be the grid-ids of H3 grids, in either long or string format.""", + examples = @Example(file = "spatial-grid", tag = "geohex_to_geoshape"), + depthOffset = 1 // make it appear as a subsection of ST_GEOHEX + ) + public StGeohexToGeoShape( + Source source, + @Param( + name = "grid_id", + type = { "keyword", "long" }, + description = "Input H3 grid-id. The input can be a single- or multi-valued column or an expression." + ) Expression v + ) { + super(source, v); + } + + private StGeohexToGeoShape(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + protected Map factories() { + return EVALUATORS; + } + + @Override + public DataType dataType() { + return GEO_SHAPE; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new StGeohexToGeoShape(source(), newChildren.get(0)); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeohexToGeoShape::new, field()); + } + + @ConvertEvaluator(extraName = "FromString") + static BytesRef fromString(BytesRef gridId) { + return fromCellBoundary(H3.h3ToGeoBoundary(gridId.utf8ToString())); + } + + @ConvertEvaluator(extraName = "FromLong") + static BytesRef fromLong(long gridId) { + return fromCellBoundary(H3.h3ToGeoBoundary(gridId)); + } + + private static BytesRef fromCellBoundary(CellBoundary cell) { + double[] x = new double[cell.numPoints() + 1]; + double[] y = new double[cell.numPoints() + 1]; + for (int i = 0; i < cell.numPoints(); i++) { + LatLng vertex = cell.getLatLon(i); + x[i] = vertex.getLonDeg(); + y[i] = vertex.getLatDeg(); + } + x[cell.numPoints()] = x[0]; + y[cell.numPoints()] = y[0]; + LinearRing ring = new LinearRing(x, y); + Polygon polygon = new Polygon(ring); + return SpatialCoordinateTypes.GEO.asWkb(polygon); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java new file mode 100644 index 0000000000000..862a33d82ad79 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShape.java @@ -0,0 +1,114 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.geometry.LinearRing; +import org.elasticsearch.geometry.Polygon; +import org.elasticsearch.geometry.Rectangle; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes; +import org.elasticsearch.xpack.esql.evaluator.mapper.EvaluatorMapper; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; + +public class StGeotileToGeoShape extends AbstractConvertFunction implements EvaluatorMapper { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( + Expression.class, + "StGeotileToGeoShape", + StGeotileToGeoShape::new + ); + + private static final Map EVALUATORS = Map.ofEntries( + Map.entry(KEYWORD, StGeotileToGeoShapeFromStringEvaluator.Factory::new), + Map.entry(LONG, StGeotileToGeoShapeFromLongEvaluator.Factory::new) + ); + + @FunctionInfo( + returnType = "geo_shape", + description = """ + Converts an input value to a `geo_shape` value. + The input values are expected to be the grid-ids of geotile grids, in either long or string format.""", + examples = @Example(file = "spatial-grid", tag = "geotile_to_geoshape"), + depthOffset = 1 // make it appear as a subsection of ST_GEOTILE + ) + public StGeotileToGeoShape( + Source source, + @Param( + name = "grid_id", + type = { "keyword", "long" }, + description = "Input geotile grid-id. The input can be a single- or multi-valued column or an expression." + ) Expression v + ) { + super(source, v); + } + + private StGeotileToGeoShape(StreamInput in) throws IOException { + super(in); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + protected Map factories() { + return EVALUATORS; + } + + @Override + public DataType dataType() { + return GEO_SHAPE; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new StGeotileToGeoShape(source(), newChildren.get(0)); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, StGeotileToGeoShape::new, field()); + } + + @ConvertEvaluator(extraName = "FromString") + static BytesRef fromString(BytesRef gridId) { + return fromRectangle(GeoTileUtils.toBoundingBox(gridId.utf8ToString())); + } + + @ConvertEvaluator(extraName = "FromLong") + static BytesRef fromLong(long gridId) { + return fromRectangle(GeoTileUtils.toBoundingBox(gridId)); + } + + static BytesRef fromRectangle(Rectangle bbox) { + double[] x = new double[] { bbox.getMinX(), bbox.getMaxX(), bbox.getMaxX(), bbox.getMinX(), bbox.getMinX() }; + double[] y = new double[] { bbox.getMinY(), bbox.getMinY(), bbox.getMaxY(), bbox.getMaxY(), bbox.getMinY() }; + LinearRing ring = new LinearRing(x, y); + Polygon polygon = new Polygon(ring); + return SpatialCoordinateTypes.GEO.asWkb(polygon); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java new file mode 100644 index 0000000000000..6c0eaac7a69a0 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToGeoShapeTests.java @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.FunctionName; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +@FunctionName("st_geohash_to_geoshape") +public class StGeohashToGeoShapeTests extends SpatialGridTypeConversionTestCases { + public StGeohashToGeoShapeTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + forUnaryGeoPoint( + DataType.LONG, + suppliers, + "StGeohashToGeoShapeFromLongEvaluator[gridId=Attribute[channel=0]]", + GEO_SHAPE, + g -> StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), + StGeohashToGeoShapeTests::valueOf + ); + forUnaryGeoPoint( + DataType.KEYWORD, + suppliers, + "StGeohashToGeoShapeFromStringEvaluator[gridId=Attribute[channel=0]]", + GEO_SHAPE, + g -> new BytesRef(Geohash.stringEncode(StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), + StGeohashToGeoShapeTests::valueOf + ); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static BytesRef valueOf(Object gridid) { + return (gridid instanceof Long hash) ? StGeohashToGeoShape.fromLong(hash) : StGeohashToGeoShape.fromString((BytesRef) gridid); + } + + @Override + protected Expression build(Source source, List args) { + return new StGeohashToGeoShape(source, args.get(0)); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java new file mode 100644 index 0000000000000..acd08a82e672e --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToGeoShapeTests.java @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.h3.H3; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.FunctionName; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +@FunctionName("st_geohex_to_geoshape") +public class StGeohexToGeoShapeTests extends SpatialGridTypeConversionTestCases { + public StGeohexToGeoShapeTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + forUnaryGeoPoint( + DataType.LONG, + suppliers, + "StGeohexToGeoShapeFromLongEvaluator[gridId=Attribute[channel=0]]", + GEO_SHAPE, + g -> StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), + StGeohexToGeoShapeTests::valueOf + ); + forUnaryGeoPoint( + DataType.KEYWORD, + suppliers, + "StGeohexToGeoShapeFromStringEvaluator[gridId=Attribute[channel=0]]", + GEO_SHAPE, + g -> new BytesRef(H3.h3ToString(StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), + StGeohexToGeoShapeTests::valueOf + ); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static BytesRef valueOf(Object gridid) { + return (gridid instanceof Long hex) ? StGeohexToGeoShape.fromLong(hex) : StGeohexToGeoShape.fromString((BytesRef) gridid); + } + + @Override + protected Expression build(Source source, List args) { + return new StGeohexToGeoShape(source, args.get(0)); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java new file mode 100644 index 0000000000000..afed423cccbbe --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToGeoShapeTests.java @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.FunctionName; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; +import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; + +@FunctionName("st_geotile_to_geoshape") +public class StGeotileToGeoShapeTests extends SpatialGridTypeConversionTestCases { + public StGeotileToGeoShapeTests(@Name("TestCase") Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + @ParametersFactory + public static Iterable parameters() { + final List suppliers = new ArrayList<>(); + forUnaryGeoPoint( + DataType.LONG, + suppliers, + "StGeotileToGeoShapeFromLongEvaluator[gridId=Attribute[channel=0]]", + GEO_SHAPE, + g -> StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), + StGeotileToGeoShapeTests::valueOf + ); + forUnaryGeoPoint( + DataType.KEYWORD, + suppliers, + "StGeotileToGeoShapeFromStringEvaluator[gridId=Attribute[channel=0]]", + GEO_SHAPE, + g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), + StGeotileToGeoShapeTests::valueOf + ); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); + } + + private static BytesRef valueOf(Object gridid) { + return (gridid instanceof Long hash) ? StGeotileToGeoShape.fromLong(hash) : StGeotileToGeoShape.fromString((BytesRef) gridid); + } + + @Override + protected Expression build(Source source, List args) { + return new StGeotileToGeoShape(source, args.get(0)); + } +} From e0a64b203268c15325ea4cd90c974973492a7305 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Wed, 21 May 2025 12:39:55 +0200 Subject: [PATCH 34/34] Update docs/changelog/128239.yaml --- docs/changelog/128239.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs/changelog/128239.yaml diff --git a/docs/changelog/128239.yaml b/docs/changelog/128239.yaml new file mode 100644 index 0000000000000..0d35f5a506b8a --- /dev/null +++ b/docs/changelog/128239.yaml @@ -0,0 +1,5 @@ +pr: 128239 +summary: Esql grid to geoshape +area: "ES|QL, Geo" +type: enhancement +issues: []