-
Notifications
You must be signed in to change notification settings - Fork 24.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add two new OGC functions ST_X and ST_Y (#105768)
* Add two new OGC functions ST_X and ST_Y Recently Nik did work that involved extracting the X and Y coordinates from geo_point data using `to_string(field)` followed by a DISSECT command to re-parse the string to get the X and Y coordinates. This is much more efficiently achieved using existing known OGC functions `ST_X` and `ST_Y`. * Update docs/changelog/105768.yaml * Fixed invalid changelog yaml * Fixed mixed cluster tests * Fixed tests and added docs * Removed false impression that these functions were different for geo/cartesian With the use of WKB as the core type in the compute engine, many spatial functions are actually the same between these two types, so we should not give the impression they are different. * Code review comments and reduced object creation. * Revert temporary StringUtils hack, and fix bug in x/y extraction from WKB * Revert object creation reduction * Fixed mistakes in documentation
- Loading branch information
1 parent
882b92a
commit 8d93a93
Showing
21 changed files
with
683 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
pr: 105768 | ||
summary: Add two new OGC functions ST_X and ST_Y | ||
area: "ES|QL" | ||
type: enhancement | ||
issues: [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
[[esql-spatial-functions]] | ||
==== {esql} spatial functions | ||
|
||
++++ | ||
<titleabbrev>Spatial functions</titleabbrev> | ||
++++ | ||
|
||
{esql} supports these spatial functions: | ||
|
||
// tag::spatial_list[] | ||
* <<esql-st_x>> | ||
* <<esql-st_y>> | ||
// end::spatial_list[] | ||
|
||
include::st_x.asciidoc[] | ||
include::st_y.asciidoc[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
[discrete] | ||
[[esql-st_x]] | ||
=== `ST_X` | ||
|
||
*Syntax* | ||
|
||
[.text-center] | ||
image::esql/functions/signature/st_x.svg[Embedded,opts=inline] | ||
|
||
*Parameters* | ||
|
||
`point`:: | ||
Expression of type `geo_point` or `cartesian_point`. If `null`, the function returns `null`. | ||
|
||
*Description* | ||
|
||
Extracts the `x` coordinate from the supplied point. | ||
If the points is of type `geo_point` this is equivalent to extracting the `longitude` value. | ||
|
||
*Supported types* | ||
|
||
include::types/st_x.asciidoc[] | ||
|
||
*Example* | ||
|
||
[source.merge.styled,esql] | ||
---- | ||
include::{esql-specs}/spatial.csv-spec[tag=st_x_y] | ||
---- | ||
[%header.monospaced.styled,format=dsv,separator=|] | ||
|=== | ||
include::{esql-specs}/spatial.csv-spec[tag=st_x_y-result] | ||
|=== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
[discrete] | ||
[[esql-st_y]] | ||
=== `ST_Y` | ||
|
||
*Syntax* | ||
|
||
[.text-center] | ||
image::esql/functions/signature/st_y.svg[Embedded,opts=inline] | ||
|
||
*Parameters* | ||
|
||
`point`:: | ||
Expression of type `geo_point` or `cartesian_point`. If `null`, the function returns `null`. | ||
|
||
*Description* | ||
|
||
Extracts the `y` coordinate from the supplied point. | ||
If the points is of type `geo_point` this is equivalent to extracting the `latitude` value. | ||
|
||
*Supported types* | ||
|
||
include::types/st_y.asciidoc[] | ||
|
||
*Example* | ||
|
||
[source.merge.styled,esql] | ||
---- | ||
include::{esql-specs}/spatial.csv-spec[tag=st_x_y] | ||
---- | ||
[%header.monospaced.styled,format=dsv,separator=|] | ||
|=== | ||
include::{esql-specs}/spatial.csv-spec[tag=st_x_y-result] | ||
|=== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[%header.monospaced.styled,format=dsv,separator=|] | ||
|=== | ||
point | result | ||
cartesian_point | double | ||
geo_point | double | ||
|=== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[%header.monospaced.styled,format=dsv,separator=|] | ||
|=== | ||
point | result | ||
cartesian_point | double | ||
geo_point | double | ||
|=== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
127 changes: 127 additions & 0 deletions
127
.../org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StXFromWKBEvaluator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
// 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.DoubleBlock; | ||
import org.elasticsearch.compute.data.Vector; | ||
import org.elasticsearch.compute.operator.DriverContext; | ||
import org.elasticsearch.compute.operator.EvalOperator; | ||
import org.elasticsearch.xpack.esql.expression.function.scalar.convert.AbstractConvertFunction; | ||
import org.elasticsearch.xpack.ql.tree.Source; | ||
|
||
/** | ||
* {@link EvalOperator.ExpressionEvaluator} implementation for {@link StX}. | ||
* This class is generated. Do not edit it. | ||
*/ | ||
public final class StXFromWKBEvaluator extends AbstractConvertFunction.AbstractEvaluator { | ||
public StXFromWKBEvaluator(EvalOperator.ExpressionEvaluator field, Source source, | ||
DriverContext driverContext) { | ||
super(driverContext, field, source); | ||
} | ||
|
||
@Override | ||
public String name() { | ||
return "StXFromWKB"; | ||
} | ||
|
||
@Override | ||
public Block evalVector(Vector v) { | ||
BytesRefVector vector = (BytesRefVector) v; | ||
int positionCount = v.getPositionCount(); | ||
BytesRef scratchPad = new BytesRef(); | ||
if (vector.isConstant()) { | ||
try { | ||
return driverContext.blockFactory().newConstantDoubleBlockWith(evalValue(vector, 0, scratchPad), positionCount); | ||
} catch (IllegalArgumentException e) { | ||
registerException(e); | ||
return driverContext.blockFactory().newConstantNullBlock(positionCount); | ||
} | ||
} | ||
try (DoubleBlock.Builder builder = driverContext.blockFactory().newDoubleBlockBuilder(positionCount)) { | ||
for (int p = 0; p < positionCount; p++) { | ||
try { | ||
builder.appendDouble(evalValue(vector, p, scratchPad)); | ||
} catch (IllegalArgumentException e) { | ||
registerException(e); | ||
builder.appendNull(); | ||
} | ||
} | ||
return builder.build(); | ||
} | ||
} | ||
|
||
private static double evalValue(BytesRefVector container, int index, BytesRef scratchPad) { | ||
BytesRef value = container.getBytesRef(index, scratchPad); | ||
return StX.fromWellKnownBinary(value); | ||
} | ||
|
||
@Override | ||
public Block evalBlock(Block b) { | ||
BytesRefBlock block = (BytesRefBlock) b; | ||
int positionCount = block.getPositionCount(); | ||
try (DoubleBlock.Builder builder = driverContext.blockFactory().newDoubleBlockBuilder(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++) { | ||
try { | ||
double value = evalValue(block, i, scratchPad); | ||
if (positionOpened == false && valueCount > 1) { | ||
builder.beginPositionEntry(); | ||
positionOpened = true; | ||
} | ||
builder.appendDouble(value); | ||
valuesAppended = true; | ||
} catch (IllegalArgumentException e) { | ||
registerException(e); | ||
} | ||
} | ||
if (valuesAppended == false) { | ||
builder.appendNull(); | ||
} else if (positionOpened) { | ||
builder.endPositionEntry(); | ||
} | ||
} | ||
return builder.build(); | ||
} | ||
} | ||
|
||
private static double evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { | ||
BytesRef value = container.getBytesRef(index, scratchPad); | ||
return StX.fromWellKnownBinary(value); | ||
} | ||
|
||
public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { | ||
private final Source source; | ||
|
||
private final EvalOperator.ExpressionEvaluator.Factory field; | ||
|
||
public Factory(EvalOperator.ExpressionEvaluator.Factory field, Source source) { | ||
this.field = field; | ||
this.source = source; | ||
} | ||
|
||
@Override | ||
public StXFromWKBEvaluator get(DriverContext context) { | ||
return new StXFromWKBEvaluator(field.get(context), source, context); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "StXFromWKBEvaluator[field=" + field + "]"; | ||
} | ||
} | ||
} |
Oops, something went wrong.