This is an automated email from the ASF dual-hosted git repository. jackie pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push: new 8df722a22f Add some missing geospatial scalar functions to support use in intermediate stages with the v2 query engine (#13457) 8df722a22f is described below commit 8df722a22f089d088bfb03e2b8aa49549bc4c38c Author: Yash Mayya <yash.ma...@gmail.com> AuthorDate: Sun Jun 23 04:39:00 2024 +0530 Add some missing geospatial scalar functions to support use in intermediate stages with the v2 query engine (#13457) --- .../transform/function/ScalarFunctions.java | 36 ++++++++++++++++++++++ .../integration/tests/custom/GeoSpatialTest.java | 33 ++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/pinot-core/src/main/java/org/apache/pinot/core/geospatial/transform/function/ScalarFunctions.java b/pinot-core/src/main/java/org/apache/pinot/core/geospatial/transform/function/ScalarFunctions.java index d8c37c3bd7..2d259c03a7 100644 --- a/pinot-core/src/main/java/org/apache/pinot/core/geospatial/transform/function/ScalarFunctions.java +++ b/pinot-core/src/main/java/org/apache/pinot/core/geospatial/transform/function/ScalarFunctions.java @@ -188,4 +188,40 @@ public class ScalarFunctions { return firstGeometry.isEmpty() || secondGeometry.isEmpty() ? Double.NaN : firstGeometry.distance(secondGeometry); } } + + @ScalarFunction(names = {"stContains", "st_contains"}) + public static int stContains(byte[] first, byte[] second) { + Geometry firstGeometry = GeometrySerializer.deserialize(first); + Geometry secondGeometry = GeometrySerializer.deserialize(second); + if (GeometryUtils.isGeography(firstGeometry) != GeometryUtils.isGeography(secondGeometry)) { + throw new RuntimeException("The first and second arguments should either both be geometry or both be geography"); + } + // TODO: to fully support Geography contains operation. + return firstGeometry.contains(secondGeometry) ? 1 : 0; + } + + @ScalarFunction(names = {"stEquals", "st_equals"}) + public static int stEquals(byte[] first, byte[] second) { + Geometry firstGeometry = GeometrySerializer.deserialize(first); + Geometry secondGeometry = GeometrySerializer.deserialize(second); + + return firstGeometry.equals(secondGeometry) ? 1 : 0; + } + + @ScalarFunction(names = {"stGeometryType", "st_geometry_type"}) + public static String stGeometryType(byte[] bytes) { + Geometry geometry = GeometrySerializer.deserialize(bytes); + return geometry.getGeometryType(); + } + + @ScalarFunction(names = {"stWithin", "st_within"}) + public static int stWithin(byte[] first, byte[] second) { + Geometry firstGeometry = GeometrySerializer.deserialize(first); + Geometry secondGeometry = GeometrySerializer.deserialize(second); + if (GeometryUtils.isGeography(firstGeometry) != GeometryUtils.isGeography(secondGeometry)) { + throw new RuntimeException("The first and second arguments should either both be geometry or both be geography"); + } + // TODO: to fully support Geography within operation. + return firstGeometry.within(secondGeometry) ? 1 : 0; + } } diff --git a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/custom/GeoSpatialTest.java b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/custom/GeoSpatialTest.java index ff41c76b13..b5cf20019b 100644 --- a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/custom/GeoSpatialTest.java +++ b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/custom/GeoSpatialTest.java @@ -404,6 +404,39 @@ public class GeoSpatialTest extends CustomDataQueryClusterIntegrationTest { } } + @Test(dataProvider = "useBothQueryEngines") + public void testStContainsQuery(boolean useMultiStageQueryEngine) throws Exception { + setUseMultiStageQueryEngine(useMultiStageQueryEngine); + // contains is the converse of within + String query = + String.format("Select ST_Contains(ST_GeomFromText(%s), ST_GeomFromText(%s)), %s from %s", + WKT_2_NAME, WKT_1_NAME, ST_WITHIN_RESULT_NAME, getTableName()); + JsonNode pinotResponse = postQuery(query); + JsonNode rows = pinotResponse.get("resultTable").get("rows"); + for (int i = 0; i < rows.size(); i++) { + JsonNode row = rows.get(i); + boolean actualResult = row.get(0).intValue() == 1; + boolean expectedResult = row.get(1).booleanValue(); + Assert.assertEquals(actualResult, expectedResult); + } + } + + @Test(dataProvider = "useV2QueryEngine") + public void testStContainsQueryWithV2(boolean useMultiStageQueryEngine) throws Exception { + setUseMultiStageQueryEngine(useMultiStageQueryEngine); + + String query = String.format("Select ST_Contains(ST_GeomFromText('MULTIPOINT (20 20, 25 25)'), " + + "ST_GeomFromText('POINT (25 25)')) from %s a CROSS JOIN %s b LIMIT 5", getTableName(), getTableName()); + + JsonNode pinotResponse = postQuery(query); + JsonNode rows = pinotResponse.get("resultTable").get("rows"); + for (int i = 0; i < rows.size(); i++) { + JsonNode row = rows.get(i); + boolean actualResult = row.get(0).intValue() == 1; + Assert.assertTrue(actualResult); + } + } + @Test(dataProvider = "useV2QueryEngine") public void testStWithinLiteral(boolean useMultiStageQueryEngine) throws Exception { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org