diff --git a/docs/changelog/129581.yaml b/docs/changelog/129581.yaml new file mode 100644 index 0000000000000..a7fd38838836d --- /dev/null +++ b/docs/changelog/129581.yaml @@ -0,0 +1,5 @@ +pr: 129581 +summary: "Support geohash, geotile and geohex grid types" +area: "ES|QL" +type: enhancement +issues: [] diff --git a/docs/redirects.yml b/docs/redirects.yml index 93546f93f0139..60b18ccc8ec78 100644 --- a/docs/redirects.yml +++ b/docs/redirects.yml @@ -1,7 +1,7 @@ redirects: # Related to https://github.com/elastic/elasticsearch/pull/130716/ 'reference/query-languages/eql/eql-ex-threat-detection.md': 'docs-content://explore-analyze/query-filter/languages/example-detect-threats-with-eql.md' - + # https://github.com/elastic/elasticsearch/pull/131385 'reference/elasticsearch/rest-apis/retrievers.md': to: 'reference/elasticsearch/rest-apis/retrievers.md' @@ -23,7 +23,7 @@ redirects: anchors: {'rule-retriever'} - to: 'reference/elasticsearch/rest-apis/retrievers/pinned-retriever.md' anchors: {'pinned-retriever'} - + # ESQL command redirects - split from aggregate pages to individual pages 'reference/query-languages/esql/commands/source-commands.md': to: 'reference/query-languages/esql/commands/source-commands.md' @@ -35,7 +35,7 @@ redirects: anchors: {'esql-row'} - to: 'reference/query-languages/esql/commands/show.md' anchors: {'esql-show'} - + # Handle old anchor references to esql-commands.md 'reference/query-languages/esql/esql-commands.md': to: 'reference/query-languages/esql/esql-commands.md' @@ -45,7 +45,7 @@ redirects: anchors: {'esql-source-commands'} - to: 'reference/query-languages/esql/commands/processing-commands.md' anchors: {'esql-processing-commands'} - + 'reference/query-languages/esql/commands/processing-commands.md': to: 'reference/query-languages/esql/commands/processing-commands.md' anchors: {} # pass-through unlisted anchors in the `many` ruleset @@ -98,3 +98,53 @@ redirects: anchors: {'query-rescorer'} - to: 'reference/elasticsearch/rest-apis/rescore-search-results.md' anchors: {'multiple-rescores'} + + # Dummy redirects for deleted snippets to get round a bug in redirects validation + 'docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/images/functions/st_geohash_to_string.svg': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/images/functions/st_geotile_to_string.svg': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/images/functions/st_geohex_to_string.svg': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/images/functions/st_geohash_to_long.svg': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/images/functions/st_geotile_to_long.svg': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/images/functions/st_geohex_to_long.svg': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_string.json': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_string.json': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_string.json': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_long.json': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_long.json': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_long.json': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_string.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' + 'docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_long.md': 'reference/query-languages/esql/esql-functions-operators.md' 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 758afcfbfb745..9531779bca629 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. 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). +Calculates the `geohash` of the supplied geo_point at the specified precision. The result is long encoded. Use [TO_STRING](#esql-to_string) to convert the result to a string, [TO_LONG](#esql-to_long) to convert it to a `long`, or [TO_GEOSHAPE](esql-to_geoshape.md) to calculate the `geo_shape` bounding geometry. 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 6c46af65812a3..e240d28f6d0b0 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. 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). +Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision. The result is long encoded. Use [TO_STRING](#esql-to_string) to convert the result to a string, [TO_LONG](#esql-to_long) to convert it to a `long`, or [TO_GEOSHAPE](esql-to_geoshape.md) to calculate the `geo_shape` bounding geometry. 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_geohex_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_string.md deleted file mode 100644 index 91fc4c723f399..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_string.md +++ /dev/null @@ -1,6 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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 index 7b0a3aaf57466..36c1875196b2f 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. 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). +Calculates the `geotile` of the supplied geo_point at the specified precision. The result is long encoded. Use [TO_STRING](#esql-to_string) to convert the result to a string, [TO_LONG](#esql-to_long) to convert it to a `long`, or [TO_GEOSHAPE](esql-to_geoshape.md) to calculate the `geo_shape` bounding geometry. 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/_snippets/functions/description/st_geotile_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_long.md deleted file mode 100644 index 66478347cb984..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_long.md +++ /dev/null @@ -1,6 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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 deleted file mode 100644 index c82f653ec100e..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/description/st_geotile_to_string.md +++ /dev/null @@ -1,6 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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/description/st_geohash_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/description/to_geohash.md similarity index 51% rename from docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_string.md rename to docs/reference/query-languages/esql/_snippets/functions/description/to_geohash.md index f19c6d1c2b67c..0c588cfc2a876 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_string.md +++ b/docs/reference/query-languages/esql/_snippets/functions/description/to_geohash.md @@ -2,5 +2,5 @@ **Description** -Converts an input value representing a geohash grid-ID in long format into a string. +Converts an input value to a `geohash` value. A string will only be successfully converted if it respects the `geohash` 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/to_geohex.md similarity index 51% rename from docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_long.md rename to docs/reference/query-languages/esql/_snippets/functions/description/to_geohex.md index 73b48261cf975..78eaa369454ca 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohash_to_long.md +++ b/docs/reference/query-languages/esql/_snippets/functions/description/to_geohex.md @@ -2,5 +2,5 @@ **Description** -Converts an input value representing a geohash grid-ID in string format into a long. +Converts an input value to a `geohex` value. A string will only be successfully converted if it respects the `geohex` 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/to_geotile.md similarity index 51% rename from docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_long.md rename to docs/reference/query-languages/esql/_snippets/functions/description/to_geotile.md index 2dcc3114dd514..b5a2c3812e254 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/description/st_geohex_to_long.md +++ b/docs/reference/query-languages/esql/_snippets/functions/description/to_geotile.md @@ -2,5 +2,5 @@ **Description** -Converts an input value representing a geohex grid-ID in string format into a long. +Converts an input value to a `geotile` value. A string will only be successfully converted if it respects the `geotile` format. 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 index 681d2a738879c..144bf0ec09cef 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash.md +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash.md @@ -6,11 +6,11 @@ FROM airports | EVAL geohash = ST_GEOHASH(location, 1) | STATS - count = COUNT(*), + count = COUNT(geohash), centroid = ST_CENTROID_AGG(location) BY geohash | WHERE count >= 10 -| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +| EVAL geohashString = TO_STRING(geohash) | KEEP count, centroid, geohashString | SORT count DESC, geohashString ASC ``` 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 index a43ddc5081e34..3f194d065cb1a 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex.md +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex.md @@ -6,11 +6,11 @@ FROM airports | EVAL geohex = ST_GEOHEX(location, 1) | STATS - count = COUNT(*), + count = COUNT(geohex), centroid = ST_CENTROID_AGG(location) BY geohex | WHERE count >= 10 -| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| EVAL geohexString = TO_STRING(geohex) | KEEP count, centroid, geohexString | SORT count DESC, geohexString ASC ``` 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 deleted file mode 100644 index 2a4b85b5131ad..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_long.md +++ /dev/null @@ -1,14 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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 deleted file mode 100644 index 652a2e23fcb4d..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohex_to_string.md +++ /dev/null @@ -1,14 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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 index 432bdd085cdf1..eb7aa2de95c96 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile.md +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile.md @@ -6,10 +6,10 @@ FROM airports | EVAL geotile = ST_GEOTILE(location, 2) | STATS - count = COUNT(*), + count = COUNT(geotile), centroid = ST_CENTROID_AGG(location) BY geotile -| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| EVAL geotileString = TO_STRING(geotile) | SORT count DESC, geotileString ASC | KEEP count, centroid, geotileString ``` 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 deleted file mode 100644 index 1ce40569cdd12..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_string.md +++ /dev/null @@ -1,14 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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/examples/st_geohash_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/examples/to_geohash.md similarity index 55% rename from docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_long.md rename to docs/reference/query-languages/esql/_snippets/functions/examples/to_geohash.md index a85135ea32f2e..1e48d726698d6 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_long.md +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/to_geohash.md @@ -3,12 +3,12 @@ **Example** ```esql -ROW geohash = "u3bu" -| EVAL geohashLong = ST_GEOHASH_TO_LONG(geohash) +ROW string = "u3bu" +| EVAL geohash = TO_GEOHASH(string) ``` -| geohash:keyword | geohashLong:long | +| string:keyword | geohash:geohash | | --- | --- | -| u3bu | 13686180 | +| u3bu | u3bu | 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/to_geohex.md similarity index 52% rename from docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_long.md rename to docs/reference/query-languages/esql/_snippets/functions/examples/to_geohex.md index fe1266db86aca..32543f3c3f415 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geotile_to_long.md +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/to_geohex.md @@ -3,12 +3,12 @@ **Example** ```esql -ROW geotile = "4/8/5" -| EVAL geotileLong = ST_GEOTILE_TO_LONG(geotile) +ROW string = "841f059ffffffff" +| EVAL geohex = TO_GEOHEX(string) ``` -| geotile:keyword | geotileLong:long | +| string:keyword | geohex:geohex | | --- | --- | -| 4/8/5 | 1152921508901814277 | +| 841f059ffffffff | 841f059ffffffff | 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/to_geotile.md similarity index 51% rename from docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_string.md rename to docs/reference/query-languages/esql/_snippets/functions/examples/to_geotile.md index ee6854edfbda3..a47072cd3a1e8 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/st_geohash_to_string.md +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/to_geotile.md @@ -3,12 +3,12 @@ **Example** ```esql -ROW geohash = TO_LONG(13686180) -| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +ROW string = "4/8/5" +| EVAL geotile = TO_GEOTILE(string) ``` -| geohash:long | geohashString:keyword | +| string:keyword | geotile:geotile | | --- | --- | -| 13686180 | u3bu | +| 4/8/5 | 4/8/5 | 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 deleted file mode 100644 index 03f251812bd02..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_long.md +++ /dev/null @@ -1,27 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. - -### `ST_GEOHASH_TO_LONG` [esql-st_geohash_to_long] -```{applies_to} -stack: preview -serverless: preview -``` - -**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 deleted file mode 100644 index b85283545a533..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohash_to_string.md +++ /dev/null @@ -1,27 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. - -### `ST_GEOHASH_TO_STRING` [esql-st_geohash_to_string] -```{applies_to} -stack: preview -serverless: preview -``` - -**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_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_long.md deleted file mode 100644 index 732fa68504391..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_long.md +++ /dev/null @@ -1,27 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. - -### `ST_GEOHEX_TO_LONG` [esql-st_geohex_to_long] -```{applies_to} -stack: preview -serverless: preview -``` - -**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 deleted file mode 100644 index 689484e97a8a3..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geohex_to_string.md +++ /dev/null @@ -1,27 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. - -### `ST_GEOHEX_TO_STRING` [esql-st_geohex_to_string] -```{applies_to} -stack: preview -serverless: preview -``` - -**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_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_long.md deleted file mode 100644 index ea3e8f76775df..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_long.md +++ /dev/null @@ -1,27 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. - -### `ST_GEOTILE_TO_LONG` [esql-st_geotile_to_long] -```{applies_to} -stack: preview -serverless: preview -``` - -**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 deleted file mode 100644 index 4cea1dd5225f1..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/layout/st_geotile_to_string.md +++ /dev/null @@ -1,27 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. - -### `ST_GEOTILE_TO_STRING` [esql-st_geotile_to_string] -```{applies_to} -stack: preview -serverless: preview -``` - -**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/layout/to_geohash.md b/docs/reference/query-languages/esql/_snippets/functions/layout/to_geohash.md new file mode 100644 index 0000000000000..92fad1c051bb0 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/to_geohash.md @@ -0,0 +1,27 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +## `TO_GEOHASH` [esql-to_geohash] +```{applies_to} +stack: preview +serverless: preview +``` + +**Syntax** + +:::{image} ../../../images/functions/to_geohash.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/to_geohash.md +::: + +:::{include} ../description/to_geohash.md +::: + +:::{include} ../types/to_geohash.md +::: + +:::{include} ../examples/to_geohash.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/to_geohex.md b/docs/reference/query-languages/esql/_snippets/functions/layout/to_geohex.md new file mode 100644 index 0000000000000..7177922df3120 --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/to_geohex.md @@ -0,0 +1,27 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +## `TO_GEOHEX` [esql-to_geohex] +```{applies_to} +stack: preview +serverless: preview +``` + +**Syntax** + +:::{image} ../../../images/functions/to_geohex.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/to_geohex.md +::: + +:::{include} ../description/to_geohex.md +::: + +:::{include} ../types/to_geohex.md +::: + +:::{include} ../examples/to_geohex.md +::: diff --git a/docs/reference/query-languages/esql/_snippets/functions/layout/to_geotile.md b/docs/reference/query-languages/esql/_snippets/functions/layout/to_geotile.md new file mode 100644 index 0000000000000..4208d0b61d12a --- /dev/null +++ b/docs/reference/query-languages/esql/_snippets/functions/layout/to_geotile.md @@ -0,0 +1,27 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +## `TO_GEOTILE` [esql-to_geotile] +```{applies_to} +stack: preview +serverless: preview +``` + +**Syntax** + +:::{image} ../../../images/functions/to_geotile.svg +:alt: Embedded +:class: text-center +::: + + +:::{include} ../parameters/to_geotile.md +::: + +:::{include} ../description/to_geotile.md +::: + +:::{include} ../types/to_geotile.md +::: + +:::{include} ../examples/to_geotile.md +::: 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 deleted file mode 100644 index c86fbc960a049..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_string.md +++ /dev/null @@ -1,7 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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_geotile_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_long.md deleted file mode 100644 index 3367072950615..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_long.md +++ /dev/null @@ -1,7 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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 deleted file mode 100644 index 3367072950615..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geotile_to_string.md +++ /dev/null @@ -1,7 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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_geohex_to_long.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/to_geohash.md similarity index 56% rename from docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_long.md rename to docs/reference/query-languages/esql/_snippets/functions/parameters/to_geohash.md index c3386d276f821..b218f4be18a25 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_long.md +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/to_geohash.md @@ -2,6 +2,6 @@ **Parameters** -`grid_id` -: Input geohex grid-id. The input can be a single- or multi-valued column or an expression. +`field` +: Input value. 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/to_geohex.md similarity index 56% rename from docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_string.md rename to docs/reference/query-languages/esql/_snippets/functions/parameters/to_geohex.md index 4304a3458a0d2..b218f4be18a25 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohex_to_string.md +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/to_geohex.md @@ -2,6 +2,6 @@ **Parameters** -`grid_id` -: Input Geohex grid-id. The input can be a single- or multi-valued column or an expression. +`field` +: Input value. 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/to_geotile.md similarity index 55% rename from docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_long.md rename to docs/reference/query-languages/esql/_snippets/functions/parameters/to_geotile.md index c86fbc960a049..b218f4be18a25 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/st_geohash_to_long.md +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/to_geotile.md @@ -2,6 +2,6 @@ **Parameters** -`grid_id` -: Input geohash grid-id. The input can be a single- or multi-valued column or an expression. +`field` +: Input value. The input can be a single- or multi-valued column or an expression. diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/case.md b/docs/reference/query-languages/esql/_snippets/functions/types/case.md index 37546fd964d34..bb20353ebe7c7 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/case.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/case.md @@ -20,6 +20,12 @@ | boolean | geo_point | | geo_point | | boolean | geo_shape | geo_shape | geo_shape | | boolean | geo_shape | | geo_shape | +| boolean | geohash | geohash | geohash | +| boolean | geohash | | geohash | +| boolean | geohex | geohex | geohex | +| boolean | geohex | | geohex | +| boolean | geotile | geotile | geotile | +| boolean | geotile | | geotile | | boolean | integer | integer | integer | | boolean | integer | | integer | | boolean | ip | ip | ip | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/coalesce.md b/docs/reference/query-languages/esql/_snippets/functions/types/coalesce.md index e38b4d261cf84..8fb034b63a6a3 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/coalesce.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/coalesce.md @@ -12,6 +12,9 @@ | date_nanos | date_nanos | date_nanos | | geo_point | geo_point | geo_point | | geo_shape | geo_shape | geo_shape | +| geohash | geohash | geohash | +| geohex | geohex | geohex | +| geotile | geotile | geotile | | integer | integer | integer | | integer | | integer | | ip | ip | ip | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/count.md b/docs/reference/query-languages/esql/_snippets/functions/types/count.md index 364b0c0353491..175336bd98374 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/count.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/count.md @@ -12,6 +12,9 @@ | double | long | | geo_point | long | | geo_shape | long | +| geohash | long | +| geohex | long | +| geotile | long | | integer | long | | ip | long | | keyword | long | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/count_over_time.md b/docs/reference/query-languages/esql/_snippets/functions/types/count_over_time.md index 364b0c0353491..175336bd98374 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/count_over_time.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/count_over_time.md @@ -12,6 +12,9 @@ | double | long | | geo_point | long | | geo_shape | long | +| geohash | long | +| geohex | long | +| geotile | long | | integer | long | | ip | long | | keyword | long | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/mv_append.md b/docs/reference/query-languages/esql/_snippets/functions/types/mv_append.md index 112ac6fca3be3..64515ccdcbab1 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/mv_append.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/mv_append.md @@ -12,6 +12,9 @@ | double | double | double | | geo_point | geo_point | geo_point | | geo_shape | geo_shape | geo_shape | +| geohash | geohash | geohash | +| geohex | geohex | geohex | +| geotile | geotile | geotile | | integer | integer | integer | | ip | ip | ip | | keyword | keyword | keyword | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/mv_contains.md b/docs/reference/query-languages/esql/_snippets/functions/types/mv_contains.md index fe4b46ac5b280..a965866eaae38 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/mv_contains.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/mv_contains.md @@ -12,6 +12,9 @@ | double | double | boolean | | geo_point | geo_point | boolean | | geo_shape | geo_shape | boolean | +| geohash | geohash | boolean | +| geohex | geohex | boolean | +| geotile | geotile | boolean | | integer | integer | boolean | | ip | ip | boolean | | keyword | keyword | boolean | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/mv_count.md b/docs/reference/query-languages/esql/_snippets/functions/types/mv_count.md index a4b51f2bf3d05..083f80ede9d30 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/mv_count.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/mv_count.md @@ -12,6 +12,9 @@ | double | integer | | geo_point | integer | | geo_shape | integer | +| geohash | integer | +| geohex | integer | +| geotile | integer | | integer | integer | | ip | integer | | keyword | integer | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/mv_dedupe.md b/docs/reference/query-languages/esql/_snippets/functions/types/mv_dedupe.md index a287b900efccf..fd0419ffba8db 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/mv_dedupe.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/mv_dedupe.md @@ -12,6 +12,9 @@ | double | double | | geo_point | geo_point | | geo_shape | geo_shape | +| geohash | geohash | +| geohex | geohex | +| geotile | geotile | | integer | integer | | ip | ip | | keyword | keyword | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/mv_first.md b/docs/reference/query-languages/esql/_snippets/functions/types/mv_first.md index a287b900efccf..fd0419ffba8db 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/mv_first.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/mv_first.md @@ -12,6 +12,9 @@ | double | double | | geo_point | geo_point | | geo_shape | geo_shape | +| geohash | geohash | +| geohex | geohex | +| geotile | geotile | | integer | integer | | ip | ip | | keyword | keyword | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/mv_last.md b/docs/reference/query-languages/esql/_snippets/functions/types/mv_last.md index a287b900efccf..fd0419ffba8db 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/mv_last.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/mv_last.md @@ -12,6 +12,9 @@ | double | double | | geo_point | geo_point | | geo_shape | geo_shape | +| geohash | geohash | +| geohex | geohex | +| geotile | geotile | | integer | integer | | ip | ip | | keyword | keyword | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/mv_slice.md b/docs/reference/query-languages/esql/_snippets/functions/types/mv_slice.md index 8f1150b408504..2b405206d7248 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/mv_slice.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/mv_slice.md @@ -12,6 +12,9 @@ | double | integer | integer | double | | geo_point | integer | integer | geo_point | | geo_shape | integer | integer | geo_shape | +| geohash | integer | integer | geohash | +| geohex | integer | integer | geohex | +| geotile | integer | integer | geotile | | integer | integer | integer | integer | | ip | integer | integer | ip | | keyword | integer | integer | keyword | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/sample.md b/docs/reference/query-languages/esql/_snippets/functions/types/sample.md index 8e9d0114da060..ca03db0f978f5 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/sample.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/sample.md @@ -12,6 +12,9 @@ | double | integer | double | | geo_point | integer | geo_point | | geo_shape | integer | geo_shape | +| geohash | integer | geohash | +| geohex | integer | geohex | +| geotile | integer | geotile | | integer | integer | integer | | ip | integer | ip | | keyword | integer | keyword | 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 index 91e1685421f74..add2b59eac83c 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash.md @@ -4,6 +4,6 @@ | geometry | precision | bounds | result | | --- | --- | --- | --- | -| geo_point | integer | geo_shape | long | -| geo_point | integer | | long | +| geo_point | integer | geo_shape | geohash | +| geo_point | integer | | geohash | 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 index 91e1685421f74..c4ca71b60d9b6 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex.md @@ -4,6 +4,6 @@ | geometry | precision | bounds | result | | --- | --- | --- | --- | -| geo_point | integer | geo_shape | long | -| geo_point | integer | | long | +| geo_point | integer | geo_shape | geohex | +| geo_point | integer | | geohex | 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 deleted file mode 100644 index 64168998bfddc..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_string.md +++ /dev/null @@ -1,9 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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 index 91e1685421f74..5fe82d0062943 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile.md @@ -4,6 +4,6 @@ | geometry | precision | bounds | result | | --- | --- | --- | --- | -| geo_point | integer | geo_shape | long | -| geo_point | integer | | long | +| geo_point | integer | geo_shape | geotile | +| geo_point | integer | | geotile | 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 deleted file mode 100644 index c005d6c7ec33a..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_long.md +++ /dev/null @@ -1,9 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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 deleted file mode 100644 index 64168998bfddc..0000000000000 --- a/docs/reference/query-languages/esql/_snippets/functions/types/st_geotile_to_string.md +++ /dev/null @@ -1,9 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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_geohash_to_string.md b/docs/reference/query-languages/esql/_snippets/functions/types/to_geohash.md similarity index 60% rename from docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_string.md rename to docs/reference/query-languages/esql/_snippets/functions/types/to_geohash.md index 64168998bfddc..6d33be50ce1ad 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_string.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/to_geohash.md @@ -2,8 +2,10 @@ **Supported types** -| grid_id | result | +| field | result | | --- | --- | -| keyword | keyword | -| long | keyword | +| geohash | geohash | +| keyword | geohash | +| long | geohash | +| text | geohash | 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/to_geohex.md similarity index 61% rename from docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_long.md rename to docs/reference/query-languages/esql/_snippets/functions/types/to_geohex.md index c005d6c7ec33a..aafc34a5ef106 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohash_to_long.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/to_geohex.md @@ -2,8 +2,10 @@ **Supported types** -| grid_id | result | +| field | result | | --- | --- | -| keyword | long | -| long | long | +| geohex | geohex | +| keyword | geohex | +| long | geohex | +| text | geohex | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/to_geoshape.md b/docs/reference/query-languages/esql/_snippets/functions/types/to_geoshape.md index 6949cef79ca51..63667d4ad85c3 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/to_geoshape.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/to_geoshape.md @@ -6,6 +6,9 @@ | --- | --- | | geo_point | geo_shape | | geo_shape | geo_shape | +| geohash | geo_shape | +| geohex | geo_shape | +| geotile | geo_shape | | keyword | geo_shape | | text | 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/to_geotile.md similarity index 60% rename from docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_long.md rename to docs/reference/query-languages/esql/_snippets/functions/types/to_geotile.md index c005d6c7ec33a..832f77b5563f9 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/st_geohex_to_long.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/to_geotile.md @@ -2,8 +2,10 @@ **Supported types** -| grid_id | result | +| field | result | | --- | --- | -| keyword | long | -| long | long | +| geotile | geotile | +| keyword | geotile | +| long | geotile | +| text | geotile | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/to_long.md b/docs/reference/query-languages/esql/_snippets/functions/types/to_long.md index f4445c6b359de..bec3d7987ccc2 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/to_long.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/to_long.md @@ -10,6 +10,9 @@ | date | long | | date_nanos | long | | double | long | +| geohash | long | +| geohex | long | +| geotile | long | | integer | long | | keyword | long | | long | long | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/to_string.md b/docs/reference/query-languages/esql/_snippets/functions/types/to_string.md index 81476ec26c36e..77fd3adaf8c56 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/to_string.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/to_string.md @@ -12,6 +12,9 @@ | double | keyword | | geo_point | keyword | | geo_shape | keyword | +| geohash | keyword | +| geohex | keyword | +| geotile | keyword | | integer | keyword | | ip | keyword | | keyword | keyword | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/values.md b/docs/reference/query-languages/esql/_snippets/functions/types/values.md index a287b900efccf..fd0419ffba8db 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/values.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/values.md @@ -12,6 +12,9 @@ | double | double | | geo_point | geo_point | | geo_shape | geo_shape | +| geohash | geohash | +| geohex | geohex | +| geotile | geotile | | integer | integer | | ip | ip | | keyword | keyword | diff --git a/docs/reference/query-languages/esql/_snippets/operators/types/equals.md b/docs/reference/query-languages/esql/_snippets/operators/types/equals.md index 904aaba5ef11b..938d9fca47661 100644 --- a/docs/reference/query-languages/esql/_snippets/operators/types/equals.md +++ b/docs/reference/query-languages/esql/_snippets/operators/types/equals.md @@ -16,6 +16,9 @@ | double | long | boolean | | geo_point | geo_point | boolean | | geo_shape | geo_shape | boolean | +| geohash | geohash | boolean | +| geohex | geohex | boolean | +| geotile | geotile | boolean | | integer | double | boolean | | integer | integer | boolean | | integer | long | boolean | diff --git a/docs/reference/query-languages/esql/_snippets/operators/types/is_not_null.md b/docs/reference/query-languages/esql/_snippets/operators/types/is_not_null.md index f2b65a11de81e..0a1179d8b1218 100644 --- a/docs/reference/query-languages/esql/_snippets/operators/types/is_not_null.md +++ b/docs/reference/query-languages/esql/_snippets/operators/types/is_not_null.md @@ -15,6 +15,9 @@ | double | boolean | | geo_point | boolean | | geo_shape | boolean | +| geohash | boolean | +| geohex | boolean | +| geotile | boolean | | integer | boolean | | ip | boolean | | keyword | boolean | diff --git a/docs/reference/query-languages/esql/_snippets/operators/types/is_null.md b/docs/reference/query-languages/esql/_snippets/operators/types/is_null.md index f2b65a11de81e..0a1179d8b1218 100644 --- a/docs/reference/query-languages/esql/_snippets/operators/types/is_null.md +++ b/docs/reference/query-languages/esql/_snippets/operators/types/is_null.md @@ -15,6 +15,9 @@ | double | boolean | | geo_point | boolean | | geo_shape | boolean | +| geohash | boolean | +| geohex | boolean | +| geotile | boolean | | integer | boolean | | ip | boolean | | keyword | boolean | diff --git a/docs/reference/query-languages/esql/_snippets/operators/types/not_equals.md b/docs/reference/query-languages/esql/_snippets/operators/types/not_equals.md index 904aaba5ef11b..938d9fca47661 100644 --- a/docs/reference/query-languages/esql/_snippets/operators/types/not_equals.md +++ b/docs/reference/query-languages/esql/_snippets/operators/types/not_equals.md @@ -16,6 +16,9 @@ | double | long | boolean | | geo_point | geo_point | boolean | | geo_shape | geo_shape | boolean | +| geohash | geohash | boolean | +| geohex | geohex | boolean | +| geotile | geotile | boolean | | integer | double | boolean | | integer | integer | boolean | | integer | long | boolean | diff --git a/docs/reference/query-languages/esql/images/functions/st_geohash.svg b/docs/reference/query-languages/esql/images/functions/st_geohash.svg index 231866d25d521..2867f072e1a8e 100644 --- a/docs/reference/query-languages/esql/images/functions/st_geohash.svg +++ b/docs/reference/query-languages/esql/images/functions/st_geohash.svg @@ -1 +1 @@ -ST_GEOHASH(geometry,precision,bounds) \ No newline at end of file +ST_GEOHASH(geometry,precision,bounds) \ 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 deleted file mode 100644 index 869af17d522de..0000000000000 --- a/docs/reference/query-languages/esql/images/functions/st_geohash_to_long.svg +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index dcb7e909d81dd..0000000000000 --- a/docs/reference/query-languages/esql/images/functions/st_geohash_to_string.svg +++ /dev/null @@ -1 +0,0 @@ -ST_GEOHASH_TO_STRING(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 deleted file mode 100644 index 39181484ebe7a..0000000000000 --- a/docs/reference/query-languages/esql/images/functions/st_geohex_to_long.svg +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 3d96677e1f87e..0000000000000 --- a/docs/reference/query-languages/esql/images/functions/st_geohex_to_string.svg +++ /dev/null @@ -1 +0,0 @@ -ST_GEOHEX_TO_STRING(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 deleted file mode 100644 index 8ac85e2baa2d4..0000000000000 --- a/docs/reference/query-languages/esql/images/functions/st_geotile_to_long.svg +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index cbe406dd19211..0000000000000 --- a/docs/reference/query-languages/esql/images/functions/st_geotile_to_string.svg +++ /dev/null @@ -1 +0,0 @@ -ST_GEOTILE_TO_STRING(grid_id) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/to_geohash.svg b/docs/reference/query-languages/esql/images/functions/to_geohash.svg new file mode 100644 index 0000000000000..09238c61d1fa4 --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/to_geohash.svg @@ -0,0 +1 @@ +TO_GEOHASH(field) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/to_geohex.svg b/docs/reference/query-languages/esql/images/functions/to_geohex.svg new file mode 100644 index 0000000000000..a97e160058e78 --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/to_geohex.svg @@ -0,0 +1 @@ +TO_GEOHEX(field) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/to_geotile.svg b/docs/reference/query-languages/esql/images/functions/to_geotile.svg new file mode 100644 index 0000000000000..3afd3b77f8b80 --- /dev/null +++ b/docs/reference/query-languages/esql/images/functions/to_geotile.svg @@ -0,0 +1 @@ +TO_GEOTILE(field) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/case.json b/docs/reference/query-languages/esql/kibana/definition/functions/case.json index 21dfaa2c9b7cf..96a3089e7f63c 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/case.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/case.json @@ -340,6 +340,132 @@ "variadic" : true, "returnType" : "geo_shape" }, + { + "params" : [ + { + "name" : "condition", + "type" : "boolean", + "optional" : false, + "description" : "A condition." + }, + { + "name" : "trueValue", + "type" : "geohash", + "optional" : false, + "description" : "The value that’s returned when the corresponding condition is the first to evaluate to `true`. The default value is returned when no condition matches." + } + ], + "variadic" : true, + "returnType" : "geohash" + }, + { + "params" : [ + { + "name" : "condition", + "type" : "boolean", + "optional" : false, + "description" : "A condition." + }, + { + "name" : "trueValue", + "type" : "geohash", + "optional" : false, + "description" : "The value that’s returned when the corresponding condition is the first to evaluate to `true`. The default value is returned when no condition matches." + }, + { + "name" : "elseValue", + "type" : "geohash", + "optional" : true, + "description" : "The value that’s returned when no condition evaluates to `true`." + } + ], + "variadic" : true, + "returnType" : "geohash" + }, + { + "params" : [ + { + "name" : "condition", + "type" : "boolean", + "optional" : false, + "description" : "A condition." + }, + { + "name" : "trueValue", + "type" : "geohex", + "optional" : false, + "description" : "The value that’s returned when the corresponding condition is the first to evaluate to `true`. The default value is returned when no condition matches." + } + ], + "variadic" : true, + "returnType" : "geohex" + }, + { + "params" : [ + { + "name" : "condition", + "type" : "boolean", + "optional" : false, + "description" : "A condition." + }, + { + "name" : "trueValue", + "type" : "geohex", + "optional" : false, + "description" : "The value that’s returned when the corresponding condition is the first to evaluate to `true`. The default value is returned when no condition matches." + }, + { + "name" : "elseValue", + "type" : "geohex", + "optional" : true, + "description" : "The value that’s returned when no condition evaluates to `true`." + } + ], + "variadic" : true, + "returnType" : "geohex" + }, + { + "params" : [ + { + "name" : "condition", + "type" : "boolean", + "optional" : false, + "description" : "A condition." + }, + { + "name" : "trueValue", + "type" : "geotile", + "optional" : false, + "description" : "The value that’s returned when the corresponding condition is the first to evaluate to `true`. The default value is returned when no condition matches." + } + ], + "variadic" : true, + "returnType" : "geotile" + }, + { + "params" : [ + { + "name" : "condition", + "type" : "boolean", + "optional" : false, + "description" : "A condition." + }, + { + "name" : "trueValue", + "type" : "geotile", + "optional" : false, + "description" : "The value that’s returned when the corresponding condition is the first to evaluate to `true`. The default value is returned when no condition matches." + }, + { + "name" : "elseValue", + "type" : "geotile", + "optional" : true, + "description" : "The value that’s returned when no condition evaluates to `true`." + } + ], + "variadic" : true, + "returnType" : "geotile" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/coalesce.json b/docs/reference/query-languages/esql/kibana/definition/functions/coalesce.json index 644fec38ff385..eca399992b3c3 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/coalesce.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/coalesce.json @@ -142,6 +142,60 @@ "variadic" : true, "returnType" : "geo_shape" }, + { + "params" : [ + { + "name" : "first", + "type" : "geohash", + "optional" : false, + "description" : "Expression to evaluate." + }, + { + "name" : "rest", + "type" : "geohash", + "optional" : true, + "description" : "Other expression to evaluate." + } + ], + "variadic" : true, + "returnType" : "geohash" + }, + { + "params" : [ + { + "name" : "first", + "type" : "geohex", + "optional" : false, + "description" : "Expression to evaluate." + }, + { + "name" : "rest", + "type" : "geohex", + "optional" : true, + "description" : "Other expression to evaluate." + } + ], + "variadic" : true, + "returnType" : "geohex" + }, + { + "params" : [ + { + "name" : "first", + "type" : "geotile", + "optional" : false, + "description" : "Expression to evaluate." + }, + { + "name" : "rest", + "type" : "geotile", + "optional" : true, + "description" : "Other expression to evaluate." + } + ], + "variadic" : true, + "returnType" : "geotile" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/count.json b/docs/reference/query-languages/esql/kibana/definition/functions/count.json index 09da0ee7dbb28..4510ef427fbda 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/count.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/count.json @@ -100,6 +100,42 @@ "variadic" : false, "returnType" : "long" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : true, + "description" : "Expression that outputs values to be counted. If omitted, equivalent to `COUNT(*)` (the number of rows)." + } + ], + "variadic" : false, + "returnType" : "long" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : true, + "description" : "Expression that outputs values to be counted. If omitted, equivalent to `COUNT(*)` (the number of rows)." + } + ], + "variadic" : false, + "returnType" : "long" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : true, + "description" : "Expression that outputs values to be counted. If omitted, equivalent to `COUNT(*)` (the number of rows)." + } + ], + "variadic" : false, + "returnType" : "long" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/count_over_time.json b/docs/reference/query-languages/esql/kibana/definition/functions/count_over_time.json index 724bd3abd6b99..c8c1527b6f2a7 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/count_over_time.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/count_over_time.json @@ -101,6 +101,42 @@ "variadic" : false, "returnType" : "long" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "long" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "long" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "long" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/mv_append.json b/docs/reference/query-languages/esql/kibana/definition/functions/mv_append.json index eb38bc0c66837..e47c655b661c4 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/mv_append.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/mv_append.json @@ -148,6 +148,60 @@ "variadic" : false, "returnType" : "geo_shape" }, + { + "params" : [ + { + "name" : "field1", + "type" : "geohash", + "optional" : false, + "description" : "" + }, + { + "name" : "field2", + "type" : "geohash", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "geohash" + }, + { + "params" : [ + { + "name" : "field1", + "type" : "geohex", + "optional" : false, + "description" : "" + }, + { + "name" : "field2", + "type" : "geohex", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "geohex" + }, + { + "params" : [ + { + "name" : "field1", + "type" : "geotile", + "optional" : false, + "description" : "" + }, + { + "name" : "field2", + "type" : "geotile", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "geotile" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/mv_contains.json b/docs/reference/query-languages/esql/kibana/definition/functions/mv_contains.json index 0116939ba4f59..da091144b0be8 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/mv_contains.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/mv_contains.json @@ -148,6 +148,60 @@ "variadic" : false, "returnType" : "boolean" }, + { + "params" : [ + { + "name" : "superset", + "type" : "geohash", + "optional" : false, + "description" : "Multivalue expression." + }, + { + "name" : "subset", + "type" : "geohash", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "superset", + "type" : "geohex", + "optional" : false, + "description" : "Multivalue expression." + }, + { + "name" : "subset", + "type" : "geohex", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "superset", + "type" : "geotile", + "optional" : false, + "description" : "Multivalue expression." + }, + { + "name" : "subset", + "type" : "geotile", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/mv_count.json b/docs/reference/query-languages/esql/kibana/definition/functions/mv_count.json index 69e707dd45d0c..b699d691acba5 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/mv_count.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/mv_count.json @@ -100,6 +100,42 @@ "variadic" : false, "returnType" : "integer" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "integer" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "integer" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "integer" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/mv_dedupe.json b/docs/reference/query-languages/esql/kibana/definition/functions/mv_dedupe.json index 3318672deb329..af0016a8c6d1f 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/mv_dedupe.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/mv_dedupe.json @@ -101,6 +101,42 @@ "variadic" : false, "returnType" : "geo_shape" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "geohash" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "geohex" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "geotile" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/mv_first.json b/docs/reference/query-languages/esql/kibana/definition/functions/mv_first.json index 67d9996423701..34222aeed43e7 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/mv_first.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/mv_first.json @@ -100,6 +100,42 @@ "variadic" : false, "returnType" : "geo_shape" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "geohash" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "geohex" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "geotile" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/mv_last.json b/docs/reference/query-languages/esql/kibana/definition/functions/mv_last.json index b6bcf15722014..e098d37ee7eee 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/mv_last.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/mv_last.json @@ -100,6 +100,42 @@ "variadic" : false, "returnType" : "geo_shape" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "geohash" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "geohex" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "Multivalue expression." + } + ], + "variadic" : false, + "returnType" : "geotile" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/mv_slice.json b/docs/reference/query-languages/esql/kibana/definition/functions/mv_slice.json index 25b8abc50db61..73a9eea542d5c 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/mv_slice.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/mv_slice.json @@ -196,6 +196,78 @@ "variadic" : false, "returnType" : "geo_shape" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "Multivalue expression. If `null`, the function returns `null`." + }, + { + "name" : "start", + "type" : "integer", + "optional" : false, + "description" : "Start position. If `null`, the function returns `null`. The start argument can be negative. An index of -1 is used to specify the last value in the list." + }, + { + "name" : "end", + "type" : "integer", + "optional" : true, + "description" : "End position(included). Optional; if omitted, the position at `start` is returned. The end argument can be negative. An index of -1 is used to specify the last value in the list." + } + ], + "variadic" : false, + "returnType" : "geohash" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "Multivalue expression. If `null`, the function returns `null`." + }, + { + "name" : "start", + "type" : "integer", + "optional" : false, + "description" : "Start position. If `null`, the function returns `null`. The start argument can be negative. An index of -1 is used to specify the last value in the list." + }, + { + "name" : "end", + "type" : "integer", + "optional" : true, + "description" : "End position(included). Optional; if omitted, the position at `start` is returned. The end argument can be negative. An index of -1 is used to specify the last value in the list." + } + ], + "variadic" : false, + "returnType" : "geohex" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "Multivalue expression. If `null`, the function returns `null`." + }, + { + "name" : "start", + "type" : "integer", + "optional" : false, + "description" : "Start position. If `null`, the function returns `null`. The start argument can be negative. An index of -1 is used to specify the last value in the list." + }, + { + "name" : "end", + "type" : "integer", + "optional" : true, + "description" : "End position(included). Optional; if omitted, the position at `start` is returned. The end argument can be negative. An index of -1 is used to specify the last value in the list." + } + ], + "variadic" : false, + "returnType" : "geotile" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/sample.json b/docs/reference/query-languages/esql/kibana/definition/functions/sample.json index 65af7520c2d96..28487b604e15b 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/sample.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/sample.json @@ -148,6 +148,60 @@ "variadic" : false, "returnType" : "geo_shape" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "The field to collect sample values for." + }, + { + "name" : "limit", + "type" : "integer", + "optional" : false, + "description" : "The maximum number of values to collect." + } + ], + "variadic" : false, + "returnType" : "geohash" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "The field to collect sample values for." + }, + { + "name" : "limit", + "type" : "integer", + "optional" : false, + "description" : "The maximum number of values to collect." + } + ], + "variadic" : false, + "returnType" : "geohex" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "The field to collect sample values for." + }, + { + "name" : "limit", + "type" : "integer", + "optional" : false, + "description" : "The maximum number of values to collect." + } + ], + "variadic" : false, + "returnType" : "geotile" + }, { "params" : [ { 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 43633b336453a..fced160121589 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 not 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.\n\nThese functions are related to the `geo_grid` query\nand the `geohash_grid` aggregation.", + "description" : "Calculates the `geohash` of the supplied geo_point at the specified precision.\nThe result is long encoded. Use TO_STRING to convert the result to a string,\nTO_LONG to convert it to a `long`, or TO_GEOSHAPE to calculate\nthe `geo_shape` bounding geometry.\n\nThese functions are related to the `geo_grid` query\nand the `geohash_grid` aggregation.", "signatures" : [ { "params" : [ @@ -15,12 +15,12 @@ { "name" : "precision", "type" : "integer", - "optional" : false, + "optional" : true, "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, - "returnType" : "long" + "returnType" : "geohash" }, { "params" : [ @@ -33,7 +33,7 @@ { "name" : "precision", "type" : "integer", - "optional" : false, + "optional" : true, "description" : "Expression of type `integer`. If `null`, the function returns `null`. Valid values are between [1 and 12](https://en.wikipedia.org/wiki/Geohash)." }, { @@ -44,11 +44,11 @@ } ], "variadic" : false, - "returnType" : "long" + "returnType" : "geohash" } ], "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" + "FROM airports\n| EVAL geohash = ST_GEOHASH(location, 1)\n| STATS\n count = COUNT(geohash),\n centroid = ST_CENTROID_AGG(location)\n BY geohash\n| WHERE count >= 10\n| EVAL geohashString = TO_STRING(geohash)\n| KEEP count, centroid, geohashString\n| SORT count DESC, geohashString ASC" ], "preview" : true, "snapshot_only" : true 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 deleted file mode 100644 index 6bbda7aa19d85..0000000000000 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_long.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do not 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" : true, - "snapshot_only" : true -} 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 deleted file mode 100644 index 76131683932db..0000000000000 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohash_to_string.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do not 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" : true, - "snapshot_only" : true -} 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 f29db14ed50e7..019fe27405f51 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 @@ -3,7 +3,7 @@ "type" : "scalar", "name" : "st_geohex", "license" : "PLATINUM", - "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.\n\nThese functions are related to the `geo_grid` query\nand the `geohex_grid` aggregation.", + "description" : "Calculates the `geohex`, the H3 cell-id, of the supplied geo_point at the specified precision.\nThe result is long encoded. Use TO_STRING to convert the result to a string,\nTO_LONG to convert it to a `long`, or TO_GEOSHAPE to calculate\nthe `geo_shape` bounding geometry.\n\nThese functions are related to the `geo_grid` query\nand the `geohex_grid` aggregation.", "signatures" : [ { "params" : [ @@ -22,7 +22,7 @@ ], "license" : "PLATINUM", "variadic" : false, - "returnType" : "long" + "returnType" : "geohex" }, { "params" : [ @@ -47,11 +47,11 @@ ], "license" : "PLATINUM", "variadic" : false, - "returnType" : "long" + "returnType" : "geohex" } ], "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" + "FROM airports\n| EVAL geohex = ST_GEOHEX(location, 1)\n| STATS\n count = COUNT(geohex),\n centroid = ST_CENTROID_AGG(location)\n BY geohex\n| WHERE count >= 10\n| EVAL geohexString = TO_STRING(geohex)\n| KEEP count, centroid, geohexString\n| SORT count DESC, geohexString ASC" ], "preview" : true, "snapshot_only" : true 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 deleted file mode 100644 index d582739620024..0000000000000 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_long.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do not 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" : true, - "snapshot_only" : true -} 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 deleted file mode 100644 index a1abce7c75adb..0000000000000 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geohex_to_string.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do not 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" : true, - "snapshot_only" : true -} 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 d728f186fc5ae..bd5fb4ede8cc4 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 not 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.\n\nThese functions are related to the `geo_grid` query\nand the `geotile_grid` aggregation.", + "description" : "Calculates the `geotile` of the supplied geo_point at the specified precision.\nThe result is long encoded. Use TO_STRING to convert the result to a string,\nTO_LONG to convert it to a `long`, or TO_GEOSHAPE to calculate\nthe `geo_shape` bounding geometry.\n\nThese functions are related to the `geo_grid` query\nand the `geotile_grid` aggregation.", "signatures" : [ { "params" : [ @@ -20,7 +20,7 @@ } ], "variadic" : false, - "returnType" : "long" + "returnType" : "geotile" }, { "params" : [ @@ -44,11 +44,11 @@ } ], "variadic" : false, - "returnType" : "long" + "returnType" : "geotile" } ], "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" + "FROM airports\n| EVAL geotile = ST_GEOTILE(location, 2)\n| STATS\n count = COUNT(geotile),\n centroid = ST_CENTROID_AGG(location)\n BY geotile\n| EVAL geotileString = TO_STRING(geotile)\n| SORT count DESC, geotileString ASC\n| KEEP count, centroid, geotileString" ], "preview" : true, "snapshot_only" : true 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 deleted file mode 100644 index b2c7c01aea606..0000000000000 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_long.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do not 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" : true, - "snapshot_only" : true -} 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 deleted file mode 100644 index 5a327c2c50976..0000000000000 --- a/docs/reference/query-languages/esql/kibana/definition/functions/st_geotile_to_string.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do not 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" : true, - "snapshot_only" : true -} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/to_geohash.json b/docs/reference/query-languages/esql/kibana/definition/functions/to_geohash.json new file mode 100644 index 0000000000000..9c6645f19f2eb --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/to_geohash.json @@ -0,0 +1,61 @@ +{ + "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "to_geohash", + "description" : "Converts an input value to a `geohash` value.\nA string will only be successfully converted if it respects the\n`geohash` format.", + "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geohash" + }, + { + "params" : [ + { + "name" : "field", + "type" : "keyword", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geohash" + }, + { + "params" : [ + { + "name" : "field", + "type" : "long", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geohash" + }, + { + "params" : [ + { + "name" : "field", + "type" : "text", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geohash" + } + ], + "examples" : [ + "ROW string = \"u3bu\"\n| EVAL geohash = TO_GEOHASH(string)" + ], + "preview" : true, + "snapshot_only" : true +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/to_geohex.json b/docs/reference/query-languages/esql/kibana/definition/functions/to_geohex.json new file mode 100644 index 0000000000000..9d75a0d5db755 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/to_geohex.json @@ -0,0 +1,61 @@ +{ + "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "to_geohex", + "description" : "Converts an input value to a `geohex` value.\nA string will only be successfully converted if it respects the\n`geohex` format.", + "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geohex" + }, + { + "params" : [ + { + "name" : "field", + "type" : "keyword", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geohex" + }, + { + "params" : [ + { + "name" : "field", + "type" : "long", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geohex" + }, + { + "params" : [ + { + "name" : "field", + "type" : "text", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geohex" + } + ], + "examples" : [ + "ROW string = \"841f059ffffffff\"\n| EVAL geohex = TO_GEOHEX(string)" + ], + "preview" : true, + "snapshot_only" : true +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/to_geoshape.json b/docs/reference/query-languages/esql/kibana/definition/functions/to_geoshape.json index e960989de94c5..ac995833cf258 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/to_geoshape.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/to_geoshape.json @@ -28,6 +28,42 @@ "variadic" : false, "returnType" : "geo_shape" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geo_shape" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geo_shape" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geo_shape" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/to_geotile.json b/docs/reference/query-languages/esql/kibana/definition/functions/to_geotile.json new file mode 100644 index 0000000000000..85879c996dad7 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/definition/functions/to_geotile.json @@ -0,0 +1,61 @@ +{ + "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it.", + "type" : "scalar", + "name" : "to_geotile", + "description" : "Converts an input value to a `geotile` value.\nA string will only be successfully converted if it respects the\n`geotile` format.", + "signatures" : [ + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geotile" + }, + { + "params" : [ + { + "name" : "field", + "type" : "keyword", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geotile" + }, + { + "params" : [ + { + "name" : "field", + "type" : "long", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geotile" + }, + { + "params" : [ + { + "name" : "field", + "type" : "text", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "geotile" + } + ], + "examples" : [ + "ROW string = \"4/8/5\"\n| EVAL geotile = TO_GEOTILE(string)" + ], + "preview" : true, + "snapshot_only" : true +} diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/to_long.json b/docs/reference/query-languages/esql/kibana/definition/functions/to_long.json index 39e5879fbc29b..345f6f8c68337 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/to_long.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/to_long.json @@ -76,6 +76,42 @@ "variadic" : false, "returnType" : "long" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "long" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "long" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "long" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/to_string.json b/docs/reference/query-languages/esql/kibana/definition/functions/to_string.json index a93c18bbb3325..7e81f967db12e 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/to_string.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/to_string.json @@ -100,6 +100,42 @@ "variadic" : false, "returnType" : "keyword" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "keyword" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "keyword" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "Input value. The input can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "keyword" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/values.json b/docs/reference/query-languages/esql/kibana/definition/functions/values.json index 8212384822c11..cf7de6974eaf1 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/values.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/values.json @@ -100,6 +100,42 @@ "variadic" : false, "returnType" : "geo_shape" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "geohash" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "geohex" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "" + } + ], + "variadic" : false, + "returnType" : "geotile" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/operators/equals.json b/docs/reference/query-languages/esql/kibana/definition/operators/equals.json index a0237be6df498..b9dcab10f71d6 100644 --- a/docs/reference/query-languages/esql/kibana/definition/operators/equals.json +++ b/docs/reference/query-languages/esql/kibana/definition/operators/equals.json @@ -222,6 +222,60 @@ "variadic" : false, "returnType" : "boolean" }, + { + "params" : [ + { + "name" : "lhs", + "type" : "geohash", + "optional" : false, + "description" : "An expression." + }, + { + "name" : "rhs", + "type" : "geohash", + "optional" : false, + "description" : "An expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "lhs", + "type" : "geohex", + "optional" : false, + "description" : "An expression." + }, + { + "name" : "rhs", + "type" : "geohex", + "optional" : false, + "description" : "An expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "lhs", + "type" : "geotile", + "optional" : false, + "description" : "An expression." + }, + { + "name" : "rhs", + "type" : "geotile", + "optional" : false, + "description" : "An expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/operators/is_not_null.json b/docs/reference/query-languages/esql/kibana/definition/operators/is_not_null.json index f184165c249d4..c3cc8fae2a14e 100644 --- a/docs/reference/query-languages/esql/kibana/definition/operators/is_not_null.json +++ b/docs/reference/query-languages/esql/kibana/definition/operators/is_not_null.json @@ -138,6 +138,42 @@ "variadic" : false, "returnType" : "boolean" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/operators/is_null.json b/docs/reference/query-languages/esql/kibana/definition/operators/is_null.json index dd8c9b4e3d4e7..08c98810ddede 100644 --- a/docs/reference/query-languages/esql/kibana/definition/operators/is_null.json +++ b/docs/reference/query-languages/esql/kibana/definition/operators/is_null.json @@ -138,6 +138,42 @@ "variadic" : false, "returnType" : "boolean" }, + { + "params" : [ + { + "name" : "field", + "type" : "geohash", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geohex", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "field", + "type" : "geotile", + "optional" : false, + "description" : "Value to check. It can be a single- or multi-valued column or an expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, { "params" : [ { diff --git a/docs/reference/query-languages/esql/kibana/definition/operators/not_equals.json b/docs/reference/query-languages/esql/kibana/definition/operators/not_equals.json index d127125928a97..ac16b232da3a5 100644 --- a/docs/reference/query-languages/esql/kibana/definition/operators/not_equals.json +++ b/docs/reference/query-languages/esql/kibana/definition/operators/not_equals.json @@ -222,6 +222,60 @@ "variadic" : false, "returnType" : "boolean" }, + { + "params" : [ + { + "name" : "lhs", + "type" : "geohash", + "optional" : false, + "description" : "An expression." + }, + { + "name" : "rhs", + "type" : "geohash", + "optional" : false, + "description" : "An expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "lhs", + "type" : "geohex", + "optional" : false, + "description" : "An expression." + }, + { + "name" : "rhs", + "type" : "geohex", + "optional" : false, + "description" : "An expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "lhs", + "type" : "geotile", + "optional" : false, + "description" : "An expression." + }, + { + "name" : "rhs", + "type" : "geotile", + "optional" : false, + "description" : "An expression." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, { "params" : [ { 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 16eebd9d4fa07..17d0c71f274b2 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 @@ -2,7 +2,9 @@ ### 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. +The result is long encoded. Use [TO_STRING](#esql-to_string) to convert the result to a string, +[TO_LONG](#esql-to_long) to convert it to a `long`, or [TO_GEOSHAPE](esql-to_geoshape.md) to calculate +the `geo_shape` bounding geometry. 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). @@ -11,11 +13,11 @@ and the [`geohash_grid` aggregation](https://www.elastic.co/docs/reference/aggre FROM airports | EVAL geohash = ST_GEOHASH(location, 1) | STATS - count = COUNT(*), + count = COUNT(geohash), centroid = ST_CENTROID_AGG(location) BY geohash | WHERE count >= 10 -| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +| EVAL geohashString = 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_long.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_long.md deleted file mode 100644 index 21377587a19f3..0000000000000 --- a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_long.md +++ /dev/null @@ -1,9 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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 deleted file mode 100644 index d87b13e384487..0000000000000 --- a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohash_to_string.md +++ /dev/null @@ -1,9 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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 index 254838a789bd0..02143698b7b6c 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 @@ -2,7 +2,9 @@ ### 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. +The result is long encoded. Use [TO_STRING](#esql-to_string) to convert the result to a string, +[TO_LONG](#esql-to_long) to convert it to a `long`, or [TO_GEOSHAPE](esql-to_geoshape.md) to calculate +the `geo_shape` bounding geometry. 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). @@ -11,11 +13,11 @@ and the [`geohex_grid` aggregation](https://www.elastic.co/docs/reference/aggreg FROM airports | EVAL geohex = ST_GEOHEX(location, 1) | STATS - count = COUNT(*), + count = COUNT(geohex), centroid = ST_CENTROID_AGG(location) BY geohex | WHERE count >= 10 -| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| EVAL geohexString = 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_long.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_long.md deleted file mode 100644 index f3e9310af6c45..0000000000000 --- a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_long.md +++ /dev/null @@ -1,9 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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 deleted file mode 100644 index 8db5903868d68..0000000000000 --- a/docs/reference/query-languages/esql/kibana/docs/functions/st_geohex_to_string.md +++ /dev/null @@ -1,9 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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 index 840632eb826bc..236a68e66d374 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 @@ -2,7 +2,9 @@ ### 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. +The result is long encoded. Use [TO_STRING](#esql-to_string) to convert the result to a string, +[TO_LONG](#esql-to_long) to convert it to a `long`, or [TO_GEOSHAPE](esql-to_geoshape.md) to calculate +the `geo_shape` bounding geometry. 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). @@ -11,10 +13,10 @@ and the [`geotile_grid` aggregation](https://www.elastic.co/docs/reference/aggre FROM airports | EVAL geotile = ST_GEOTILE(location, 2) | STATS - count = COUNT(*), + count = COUNT(geotile), centroid = ST_CENTROID_AGG(location) BY geotile -| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| EVAL geotileString = 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_long.md b/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_long.md deleted file mode 100644 index 6e5b75ba4617d..0000000000000 --- a/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_long.md +++ /dev/null @@ -1,9 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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 deleted file mode 100644 index 7d3d5ca2606f5..0000000000000 --- a/docs/reference/query-languages/esql/kibana/docs/functions/st_geotile_to_string.md +++ /dev/null @@ -1,9 +0,0 @@ -% This is generated by ESQL's AbstractFunctionTestCase. Do not 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/docs/reference/query-languages/esql/kibana/docs/functions/to_geohash.md b/docs/reference/query-languages/esql/kibana/docs/functions/to_geohash.md new file mode 100644 index 0000000000000..59277639cf6f3 --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/to_geohash.md @@ -0,0 +1,11 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +### TO GEOHASH +Converts an input value to a `geohash` value. +A string will only be successfully converted if it respects the +`geohash` format. + +```esql +ROW string = "u3bu" +| EVAL geohash = TO_GEOHASH(string) +``` diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/to_geohex.md b/docs/reference/query-languages/esql/kibana/docs/functions/to_geohex.md new file mode 100644 index 0000000000000..1d6e3b968995e --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/to_geohex.md @@ -0,0 +1,11 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +### TO GEOHEX +Converts an input value to a `geohex` value. +A string will only be successfully converted if it respects the +`geohex` format. + +```esql +ROW string = "841f059ffffffff" +| EVAL geohex = TO_GEOHEX(string) +``` diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/to_geotile.md b/docs/reference/query-languages/esql/kibana/docs/functions/to_geotile.md new file mode 100644 index 0000000000000..a123797d01d7b --- /dev/null +++ b/docs/reference/query-languages/esql/kibana/docs/functions/to_geotile.md @@ -0,0 +1,11 @@ +% This is generated by ESQL's AbstractFunctionTestCase. Do not edit it. See ../README.md for how to regenerate it. + +### TO GEOTILE +Converts an input value to a `geotile` value. +A string will only be successfully converted if it respects the +`geotile` format. + +```esql +ROW string = "4/8/5" +| EVAL geotile = TO_GEOTILE(string) +``` diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/TypeResolutions.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/TypeResolutions.java index 814adfde50e74..c0ca5d18dc63d 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/TypeResolutions.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/TypeResolutions.java @@ -22,7 +22,7 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME; import static org.elasticsearch.xpack.esql.core.type.DataType.IP; import static org.elasticsearch.xpack.esql.core.type.DataType.NULL; -import static org.elasticsearch.xpack.esql.core.type.DataType.isSpatial; +import static org.elasticsearch.xpack.esql.core.type.DataType.isSpatialOrGrid; public final class TypeResolutions { @@ -82,7 +82,7 @@ public static TypeResolution isRepresentableExceptCounters(Expression e, String public static TypeResolution isRepresentableExceptCountersAndSpatial(Expression e, String operationName, ParamOrdinal paramOrd) { return isType( e, - (t) -> isSpatial(t) == false && DataType.isRepresentable(t), + (t) -> isSpatialOrGrid(t) == false && DataType.isRepresentable(t), operationName, paramOrd, "any type except counter and spatial types" diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java index bde8af3c4e6d1..b3f7acfe2eac4 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/type/DataType.java @@ -276,6 +276,9 @@ public enum DataType { // wild estimate for size, based on some test data (airport_city_boundaries) CARTESIAN_SHAPE(builder().esType("cartesian_shape").estimatedSize(200).docValues()), GEO_SHAPE(builder().esType("geo_shape").estimatedSize(200).docValues()), + GEOHASH(builder().esType("geohash").typeName("GEOHASH").estimatedSize(Long.BYTES)), + GEOTILE(builder().esType("geotile").typeName("GEOTILE").estimatedSize(Long.BYTES)), + GEOHEX(builder().esType("geohex").typeName("GEOHEX").estimatedSize(Long.BYTES)), /** * Fields with this type represent a Lucene doc id. This field is a bit magic in that: @@ -567,19 +570,27 @@ public static boolean isSpatialPoint(DataType t) { } public static boolean isSpatialShape(DataType t) { - return t == GEO_SHAPE || t == CARTESIAN_SHAPE; + return t == GEO_SHAPE || t == CARTESIAN_SHAPE || t == GEOHASH || t == GEOTILE || t == GEOHEX; } public static boolean isSpatialGeo(DataType t) { - return t == GEO_POINT || t == GEO_SHAPE; + return t == GEO_POINT || t == GEO_SHAPE || t == GEOHASH || t == GEOTILE || t == GEOHEX; } public static boolean isSpatial(DataType t) { return t == GEO_POINT || t == CARTESIAN_POINT || t == GEO_SHAPE || t == CARTESIAN_SHAPE; } + public static boolean isSpatialOrGrid(DataType t) { + return isSpatial(t) || isGeoGrid(t); + } + + public static boolean isGeoGrid(DataType t) { + return t == GEOHASH || t == GEOTILE || t == GEOHEX; + } + public static boolean isSortable(DataType t) { - return false == (t == SOURCE || isCounter(t) || isSpatial(t) || t == AGGREGATE_METRIC_DOUBLE); + return false == (t == SOURCE || isCounter(t) || isSpatialOrGrid(t) || t == AGGREGATE_METRIC_DOUBLE); } public String nameUpper() { diff --git a/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/RestEsqlIT.java b/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/RestEsqlIT.java index e8153673adb89..b2142037de5b1 100644 --- a/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/RestEsqlIT.java +++ b/x-pack/plugin/esql/qa/server/single-node/src/javaRestTest/java/org/elasticsearch/xpack/esql/qa/single_node/RestEsqlIT.java @@ -663,6 +663,9 @@ public void testSuggestedCast() throws IOException { Set shouldBeSupported = Stream.of(DataType.values()).filter(DataType::isRepresentable).collect(Collectors.toSet()); shouldBeSupported.remove(DataType.CARTESIAN_POINT); shouldBeSupported.remove(DataType.CARTESIAN_SHAPE); + shouldBeSupported.remove(DataType.GEOHASH); + shouldBeSupported.remove(DataType.GEOTILE); + shouldBeSupported.remove(DataType.GEOHEX); shouldBeSupported.remove(DataType.NULL); shouldBeSupported.remove(DataType.DOC_DATA_TYPE); shouldBeSupported.remove(DataType.TSID_DATA_TYPE); @@ -671,7 +674,7 @@ public void testSuggestedCast() throws IOException { shouldBeSupported.remove(DataType.AGGREGATE_METRIC_DOUBLE); } for (DataType type : shouldBeSupported) { - assertTrue(typesAndValues.containsKey(type)); + assertTrue(type.typeName(), typesAndValues.containsKey(type)); } assertThat(typesAndValues.size(), equalTo(shouldBeSupported.size())); 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 cac61d9acd434..05d6b08b61ff2 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 @@ -12,8 +12,11 @@ import org.elasticsearch.common.time.DateFormatter; import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder; import org.elasticsearch.compute.data.Page; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.h3.H3; import org.elasticsearch.logging.Logger; import org.elasticsearch.search.DocValueFormat; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; import org.elasticsearch.test.ListMatcher; import org.elasticsearch.xpack.esql.CsvTestUtils.ActualResults; import org.elasticsearch.xpack.versionfield.Version; @@ -135,6 +138,9 @@ private static void assertMetadata( || expectedType == Type.DATE_NANOS || expectedType == Type.GEO_POINT || expectedType == Type.CARTESIAN_POINT + || expectedType == Type.GEOHASH + || expectedType == Type.GEOTILE + || expectedType == Type.GEOHEX || expectedType == UNSIGNED_LONG)) { continue; } @@ -412,6 +418,9 @@ private static Object convertExpectedValue(Type expectedType, Object expectedVal BytesRef.class, x -> CARTESIAN.wkbToWkt((BytesRef) x) ); + case Type.GEOHASH -> rebuildExpected(expectedValue, Long.class, x -> Geohash.stringEncode((long) x)); + case Type.GEOTILE -> rebuildExpected(expectedValue, Long.class, x -> GeoTileUtils.stringEncode((long) x)); + case Type.GEOHEX -> rebuildExpected(expectedValue, Long.class, x -> H3.h3ToString((long) x)); case Type.IP -> // convert BytesRef-packed IP to String, allowing subsequent comparison with what's expected rebuildExpected(expectedValue, BytesRef.class, x -> DocValueFormat.IP.format((BytesRef) x)); case Type.VERSION -> // convert BytesRef-packed Version to String diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestUtils.java b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestUtils.java index 3a6f623c6dec1..0c4a38a933bed 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestUtils.java +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestUtils.java @@ -27,7 +27,10 @@ import org.elasticsearch.core.Releasables; import org.elasticsearch.core.Strings; import org.elasticsearch.core.Tuple; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.h3.H3; import org.elasticsearch.logging.Logger; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; import org.elasticsearch.test.VersionUtils; import org.elasticsearch.xpack.esql.action.ResponseValueUtils; import org.elasticsearch.xpack.esql.core.type.DataType; @@ -487,6 +490,9 @@ public enum Type { CARTESIAN_POINT(x -> x == null ? null : CARTESIAN.wktToWkb(x), BytesRef.class), GEO_SHAPE(x -> x == null ? null : GEO.wktToWkb(x), BytesRef.class), CARTESIAN_SHAPE(x -> x == null ? null : CARTESIAN.wktToWkb(x), BytesRef.class), + GEOHASH(x -> x == null ? null : Geohash.longEncode(x), Long.class), + GEOTILE(x -> x == null ? null : GeoTileUtils.longEncode(x), Long.class), + GEOHEX(x -> x == null ? null : H3.stringToH3(x), Long.class), AGGREGATE_METRIC_DOUBLE( x -> x == null ? null : stringToAggregateMetricDoubleLiteral(x), AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral.class diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/EsqlTestUtils.java b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/EsqlTestUtils.java index 3551a75c65faf..ff47fc4121b0f 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/EsqlTestUtils.java +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/EsqlTestUtils.java @@ -39,9 +39,12 @@ import org.elasticsearch.core.Tuple; import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.ShapeTestUtils; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.h3.H3; import org.elasticsearch.index.IndexMode; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.search.SearchService; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; import org.elasticsearch.tasks.TaskCancelledException; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.threadpool.ThreadPool; @@ -67,6 +70,9 @@ import org.elasticsearch.xpack.esql.core.util.DateUtils; import org.elasticsearch.xpack.esql.core.util.StringUtils; import org.elasticsearch.xpack.esql.expression.function.EsqlFunctionRegistry; +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.string.regex.RLike; import org.elasticsearch.xpack.esql.expression.function.scalar.string.regex.WildcardLike; import org.elasticsearch.xpack.esql.expression.predicate.Range; @@ -854,6 +860,15 @@ public static Literal randomLiteral(DataType type) { case CARTESIAN_POINT -> CARTESIAN.asWkb(ShapeTestUtils.randomPoint()); case GEO_SHAPE -> GEO.asWkb(GeometryTestUtils.randomGeometry(randomBoolean())); case CARTESIAN_SHAPE -> CARTESIAN.asWkb(ShapeTestUtils.randomGeometry(randomBoolean())); + case GEOHASH -> StGeohash.unboundedGrid.calculateGridId( + GeometryTestUtils.randomPoint(), + randomIntBetween(1, Geohash.PRECISION) + ); + case GEOTILE -> StGeotile.unboundedGrid.calculateGridId( + GeometryTestUtils.randomPoint(), + randomIntBetween(0, GeoTileUtils.MAX_ZOOM) + ); + case GEOHEX -> StGeohex.unboundedGrid.calculateGridId(GeometryTestUtils.randomPoint(), randomIntBetween(0, H3.MAX_H3_RES)); case AGGREGATE_METRIC_DOUBLE -> new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral( randomDouble(), randomDouble(), 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 a694f0ca48afe..f0dc76e4c8e87 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,27 +2,44 @@ # Tests for geo_grid function: ST_GEOHASH ############################################### -geohashStringToLong -required_capability: spatial_grid +toGeohash +required_capability: spatial_grid_types -// tag::geohash_to_long[] -ROW geohash = "u3bu" -| EVAL geohashLong = ST_GEOHASH_TO_LONG(geohash) -// end::geohash_to_long[] +// tag::to_geohash[] +ROW string = "u3bu" +| EVAL geohash = TO_GEOHASH(string) +// end::to_geohash[] ; -// tag::geohash_to_long-result[] -geohash:keyword | geohashLong:long -u3bu | 13686180 -// end::geohash_to_long-result[] +// tag::to_geohash-result[] +string:keyword | geohash:geohash +u3bu | u3bu +// end::to_geohash-result[] +; + +toGeohashToLong +required_capability: spatial_grid_types + +// tag::to_geohash_to_long[] +ROW string = "u3bu" +| EVAL geohash = TO_GEOHASH(string) +| EVAL geohashLong = TO_LONG(geohash) +| EVAL geohash2 = TO_GEOHASH(geohash) +// end::to_geohash_to_long[] +; + +// tag::to_geohash_to_long-result[] +string:keyword | geohash:geohash | geohashLong:long | geohash2:geohash +u3bu | u3bu | 13686180 | u3bu +// end::to_geohash_to_long-result[] ; geohashLongToString -required_capability: spatial_grid +required_capability: spatial_grid_types // tag::geohash_to_string[] -ROW geohash = TO_LONG(13686180) -| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +ROW geohash = 13686180::long +| EVAL geohashString = TO_STRING(TO_GEOHASH(geohash)) // end::geohash_to_string[] ; @@ -32,64 +49,126 @@ geohash:long | geohashString:keyword // end::geohash_to_string-result[] ; +geohashStringToGeoShape +required_capability: spatial_grid_types + +// tag::geohash_to_geoshape[] +ROW hash = "u3bu" +| EVAL boundary = TO_GEOSHAPE(TO_GEOHASH(hash)) +// end::geohash_to_geoshape[] +; + +// tag::geohash_to_geoshape-result[] +hash: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_types + +ROW hash = TO_LONG(13686180) +| EVAL boundary = TO_GEOSHAPE(TO_GEOHASH(hash)) +; + +hash: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 +required_capability: spatial_grid_types -// tag::st_geohash-literal[] +// tag::to_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[] +// end::to_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[] +// tag::to_geohash_literal-result[] +location:geo_point | geohash4:geohash | geohash3:geohash | geohash2:geohash | geohash1:geohash +POINT(12.6493508684508 55.6285017221528) | u3bu | u3b | u3 | u +// end::to_geohash_literal-result[] ; geohashLiteralString -required_capability: spatial_grid +required_capability: spatial_grid_types 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)) +| EVAL geohash4 = TO_STRING(ST_GEOHASH(location, 4)), + geohash3 = TO_STRING(ST_GEOHASH(location, 3)), + geohash2 = TO_STRING(ST_GEOHASH(location, 2)), + geohash1 = TO_STRING(ST_GEOHASH(location, 1)) ; location:geo_point | geohash4:keyword | geohash3:keyword | geohash2:keyword | geohash1:keyword POINT(12.6493508684508 55.6285017221528) | u3bu | u3b | u3 | u ; +geohashLiteralLong +required_capability: spatial_grid_types + +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") +| EVAL geohash4 = TO_LONG(ST_GEOHASH(location, 4)), + geohash3 = TO_LONG(ST_GEOHASH(location, 3)), + geohash2 = TO_LONG(ST_GEOHASH(location, 2)), + geohash1 = TO_LONG(ST_GEOHASH(location, 1)) +; + +location:geo_point | geohash4:long | geohash3:long | geohash2:long | geohash1:long +POINT (12.6493508684508 55.6285017221528) | 13686180 | 427683 | 13362 | 417 +; + +geohashLiteralMv +required_capability: spatial_grid_types +required_capability: fn_mv_contains + +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) +| EVAL chain = MV_APPEND(geohash4, MV_APPEND(geohash3, MV_APPEND(geohash2, geohash1))) +| EVAL description = MV_CONCAT(chain::keyword, " --> ") +| EVAL top = MV_LAST(chain) +| EVAL bottom = MV_FIRST(chain) +| EVAL top = COALESCE(top, null, bottom) +| EVAL bottom = COALESCE(bottom, null, top) +| WHERE MV_CONTAINS(chain, top) AND MV_CONTAINS(chain, bottom) +| KEEP location, top, bottom, chain, description +; + +location:geo_point | top:geohash | bottom:geohash | chain:geohash | description:keyword +POINT(12.6493508684508 55.6285017221528) | u | u3bu | [u3bu, u3b, u3, u] | u3bu --> u3b --> u3 --> u +; + geohashField -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | WHERE abbrev == "CPH" | EVAL geohash = ST_GEOHASH(location, 7) -| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) -| KEEP geohash, geohashString, abbrev, name, location +| KEEP geohash, abbrev, name, location ; -geohash:long | geohashString:keyword | abbrev:keyword | name:text | location:geo_point -448469007591 | u3buryf | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) +geohash:geohash | abbrev:keyword | name:text | location:geo_point +u3buryf | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) ; gridGeohashStatsBy -required_capability: spatial_grid +required_capability: spatial_grid_types // tag::st_geohash-grid[] FROM airports | EVAL geohash = ST_GEOHASH(location, 1) | STATS - count = COUNT(*), + count = COUNT(geohash), centroid = ST_CENTROID_AGG(location) BY geohash | WHERE count >= 10 -| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +| EVAL geohashString = TO_STRING(geohash) | KEEP count, centroid, geohashString | SORT count DESC, geohashString ASC // end::st_geohash-grid[] @@ -117,17 +196,58 @@ count:long | centroid:geo_point | geohashString:keyw // end::st_geohash-grid-result[] ; +gridGeohashCase +required_capability: spatial_grid_types + +// tag::st_geohash-case[] +FROM airports +| EVAL geohash = ST_GEOHASH(location, 2) +| STATS + count = COUNT(geohash), + centroid = ST_CENTROID_AGG(location) + BY geohash +| WHERE count >= 10 +| EVAL parent = ST_GEOHASH(centroid, 1) +| EVAL level = CASE( + parent == "u"::geohash, "high", + parent == "d"::geohash, "medium", + parent == "9"::geohash, "low", + "other" + ) +| EVAL geohashString = TO_STRING(geohash) +| KEEP count, centroid, geohashString, parent, level +| SORT count DESC, geohashString ASC +// end::st_geohash-case[] +; + +// tag::st_geohash-case-result[] +count:long | centroid:geo_point | geohashString:keyword | parent:geohash | level:keyword +19 | POINT (6.360728044651057 47.94084087577894) | u0 | u | high +17 | POINT (-3.5034258844440473 53.25306422789307) | gc | g | other +16 | POINT (-84.3847085541347 41.85195600060979) | dp | d | medium +13 | POINT (-74.08679279498756 42.10354745746232) | dr | d | medium +12 | POINT (-83.732457049191 36.367889943066984) | dn | d | medium +12 | POINT (74.7963257250376 31.238017017021775) | tt | t | other +12 | POINT (84.32237566681579 24.78583392337896) | tu | t | other +11 | POINT (-94.80821384032342 31.166376347060908) | 9v | 9 | low +10 | POINT (-49.814146178774536 -24.70176063431427) | 6g | 6 | other +10 | POINT (-97.22507307864726 19.70557357929647) | 9g | 9 | low +10 | POINT (15.350638423115015 47.80751353036612) | u2 | u | high +10 | POINT (128.12597772292793 36.5161985848099) | wy | w | other +// end::st_geohash-case-result[] +; + gridGeohashQuery -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports -| WHERE ST_GEOHASH(location, 1) == ST_GEOHASH_TO_LONG("7") +| WHERE ST_GEOHASH(location, 1) == TO_GEOHASH("7") | EVAL geohash = ST_GEOHASH(location, 2) | STATS - count = COUNT(*), + count = COUNT(geohash), centroid = ST_CENTROID_AGG(location) BY geohash -| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) +| EVAL geohashString = TO_STRING(geohash) | KEEP count, centroid, geohashString | SORT count DESC, geohashString ASC ; @@ -141,65 +261,67 @@ count:long | centroid:geo_point | geohashString:keyw ; gridGeohashStatsByBounds -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | EVAL geohash = ST_GEOHASH(location, 2, TO_GEOSHAPE("BBOX(0.0, 12.0, 60.0, 30.0)")) | WHERE geohash IS NOT NULL | STATS - count = COUNT(*), + count = COUNT(geohash), centroid = ST_CENTROID_AGG(location) BY geohash -| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) -| KEEP count, centroid, geohashString +| EVAL geohashString = TO_STRING(geohash) +| EVAL cellBoundary = 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)) ; gridGeohashStatsByBoundsEnvelope -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | EVAL geohash = ST_GEOHASH(location, 2, ST_ENVELOPE(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(*), + count = COUNT(geohash), centroid = ST_CENTROID_AGG(location) BY geohash -| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) -| KEEP count, centroid, geohashString +| EVAL geohashString = TO_STRING(geohash) +| EVAL cellBoundary = 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)) ; gridGeohashStatsByWhereUK -required_capability: spatial_grid +required_capability: spatial_grid_types 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))")) @@ -208,18 +330,19 @@ FROM airports count = COUNT(location), centroid = ST_CENTROID_AGG(location) BY geohash -| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) -| KEEP count, centroid, geohashString +| EVAL geohashString = TO_STRING(geohash) +| EVAL cellBoundary = 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 -required_capability: spatial_grid +required_capability: spatial_grid_types 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))")) @@ -229,21 +352,22 @@ FROM airports count = COUNT(location), centroid = ST_CENTROID_AGG(location) BY geohash -| EVAL geohashString = ST_GEOHASH_TO_STRING(geohash) -| KEEP count, centroid, geohashString +| EVAL geohashString = TO_STRING(geohash) +| EVAL cellBoundary = 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 -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | STATS @@ -269,7 +393,7 @@ count:long | centroid:geo_point ; gridGeohashInStatsByWhereUK -required_capability: spatial_grid +required_capability: spatial_grid_types 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))")) @@ -290,27 +414,44 @@ count:long | centroid:geo_point # Tests for geo_grid function: ST_GEOTILE ############################################### -geotileStringToLong -required_capability: spatial_grid +toGeotile +required_capability: spatial_grid_types -// tag::geotile_to_long[] -ROW geotile = "4/8/5" -| EVAL geotileLong = ST_GEOTILE_TO_LONG(geotile) -// end::geotile_to_long[] +// tag::to_geotile[] +ROW string = "4/8/5" +| EVAL geotile = TO_GEOTILE(string) +// end::to_geotile[] ; -// tag::geotile_to_long-result[] -geotile:keyword | geotileLong:long -4/8/5 | 1152921508901814277 -// end::geotile_to_long-result[] +// tag::to_geotile-result[] +string:keyword | geotile:geotile +4/8/5 | 4/8/5 +// end::to_geotile-result[] +; + +toGeotileToLong +required_capability: spatial_grid_types + +// tag::to_geotile_to_long[] +ROW string = "4/8/5" +| EVAL geotile = TO_GEOTILE(string) +| EVAL geotileLong = TO_LONG(geotile) +| EVAL geotile2 = TO_GEOTILE(geotile) +// end::to_geotile_to_long[] +; + +// tag::to_geotile_to_long-result[] +string:keyword | geotile:geotile | geotileLong:long | geotile2:geotile +4/8/5 | 4/8/5 | 1152921508901814277 | 4/8/5 +// end::to_geotile_to_long-result[] ; geotileLongToString -required_capability: spatial_grid +required_capability: spatial_grid_types // tag::geotile_to_string[] ROW geotile = 1152921508901814277 -| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| EVAL geotileString = TO_STRING(TO_GEOTILE(geotile)) // end::geotile_to_string[] ; @@ -320,63 +461,114 @@ geotile:long | geotileString:keyword // end::geotile_to_string-result[] ; +geotileStringToGeoshape +required_capability: spatial_grid_types + +// tag::geotile_to_geoshape[] +ROW tile = "4/8/5" +| EVAL boundary = TO_GEOSHAPE(TO_GEOTILE(tile)) +// end::geotile_to_geoshape[] +; + +// tag::geotile_to_geoshape-result[] +tile: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 +required_capability: spatial_grid_types -// tag::st_geotile-literal[] +// 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[] +// 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[] +// tag::st_geotile_literal-result[] +location:geo_point | geotile4:geotile | geotile3:geotile | geotile2:geotile | geotile1:geotile +POINT (12.6493508684508 55.6285017221528) | 4/8/5 | 3/4/2 | 2/2/1 | 1/1/0 +// end::st_geotile_literal-result[] ; geotileLiteralString -required_capability: spatial_grid +required_capability: spatial_grid_types 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)) +| EVAL geotile4 = TO_STRING(ST_GEOTILE(location, 4)), + geotile3 = TO_STRING(ST_GEOTILE(location, 3)), + geotile2 = TO_STRING(ST_GEOTILE(location, 2)), + geotile1 = TO_STRING(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 ; +geotileLiteralLong +required_capability: spatial_grid_types + +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") +| EVAL geotile4 = TO_LONG(ST_GEOTILE(location, 4)), + geotile3 = TO_LONG(ST_GEOTILE(location, 3)), + geotile2 = TO_LONG(ST_GEOTILE(location, 2)), + geotile1 = TO_LONG(ST_GEOTILE(location, 1)) +; + +location:geo_point | geotile4:long | geotile3:long | geotile2:long | geotile1:long +POINT (12.6493508684508 55.6285017221528) | 1152921508901814277 | 864691130602618882 | 576460753377165313 | 288230376688582656 +; + +geotileLiteralMv +required_capability: spatial_grid_types +required_capability: fn_mv_contains + +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) +| EVAL chain = MV_APPEND(geotile4, MV_APPEND(geotile3, MV_APPEND(geotile2, geotile1))) +| EVAL description = MV_CONCAT(chain::keyword, " --> ") +| EVAL top = MV_LAST(chain) +| EVAL bottom = MV_FIRST(chain) +| EVAL top = COALESCE(top, null, bottom) +| EVAL bottom = COALESCE(bottom, null, top) +| WHERE MV_CONTAINS(chain, top) AND MV_CONTAINS(chain, bottom) +| KEEP location, top, bottom, chain, description +; + +location:geo_point | top:geotile | bottom:geotile | chain:geotile | description:keyword +POINT (12.6493508684508 55.6285017221528) | 1/1/0 | 4/8/5 | [4/8/5, 3/4/2, 2/2/1, 1/1/0] | 4/8/5 --> 3/4/2 --> 2/2/1 --> 1/1/0 +; + geotileField -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | WHERE abbrev == "CPH" | EVAL geotile = ST_GEOTILE(location, 7) -| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) -| KEEP geotile, geotileString, abbrev, name, location +| KEEP geotile, abbrev, name, location ; -geotile:long | geotileString:keyword | abbrev:keyword | name:text | location:geo_point -2017612669569204264 | 7/68/40 | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) +geotile:geotile | abbrev:keyword | name:text | location:geo_point +7/68/40 | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) ; gridGeotileStatsBy -required_capability: spatial_grid +required_capability: spatial_grid_types // tag::st_geotile-grid[] FROM airports | EVAL geotile = ST_GEOTILE(location, 2) | STATS - count = COUNT(*), + count = COUNT(geotile), centroid = ST_CENTROID_AGG(location) BY geotile -| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| EVAL geotileString = TO_STRING(geotile) | SORT count DESC, geotileString ASC | KEEP count, centroid, geotileString // end::st_geotile-grid[] @@ -398,17 +590,53 @@ count:long | centroid:geo_point | geotileString:key // end::st_geotile-grid-result[] ; +gridGeotileCase +required_capability: spatial_grid_types + +// tag::st_geotile-case[] +FROM airports +| EVAL geotile = ST_GEOTILE(location, 2) +| STATS + count = COUNT(geotile), + centroid = ST_CENTROID_AGG(location) + BY geotile +| WHERE count >= 10 +| EVAL parent = ST_GEOTILE(centroid, 1) +| EVAL level = CASE( + parent == "1/0/0"::geotile, "high", + parent == "1/1/0"::geotile, "medium", + parent == "1/1/1"::geotile, "low", + "other" + ) +| EVAL geotileString = TO_STRING(geotile) +| KEEP count, centroid, geotileString, parent, level +| SORT count DESC, geotileString ASC +// end::st_geotile-case[] +; + +// tag::st_geotile-case-result[] +count:long | centroid:geo_point | geotileString:keyword | parent:geotile | level:keyword +286 | POINT (39.31202001609169 35.149993664386415) | 2/2/1 | 1/1/0 | medium +197 | POINT (-55.387361375756825 31.952955322292855) | 2/1/1 | 1/0/0 | high +136 | POINT (-110.97162496141048 36.87185255084734) | 2/0/1 | 1/0/0 | high +106 | POINT (119.35907618669827 25.46263281488791) | 2/3/1 | 1/1/0 | medium +67 | POINT (-58.031108492373754 -22.624166105151065) | 2/1/2 | 1/0/1 | other +46 | POINT (142.95455511274707 -20.581492295427978) | 2/3/2 | 1/1/1 | low +34 | POINT (31.38476753634784 -14.64374022804858) | 2/2/2 | 1/1/1 | low +// end::st_geotile-case-result[] +; + gridGeotileQuery -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports -| WHERE ST_GEOTILE(location, 2) == ST_GEOTILE_TO_LONG("2/0/2") +| WHERE ST_GEOTILE(location, 2) == TO_GEOTILE("2/0/2") | EVAL geotile = ST_GEOTILE(location, 3) | STATS - count = COUNT(*), + count = COUNT(geotile), centroid = ST_CENTROID_AGG(location) BY geotile -| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| EVAL geotileString = TO_STRING(geotile) | SORT count DESC, geotileString ASC | KEEP count, centroid, geotileString ; @@ -419,47 +647,49 @@ count:long | centroid:geo_point | geotileString:keyw ; gridGeotileStatsByBounds -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | EVAL geotile = ST_GEOTILE(location, 3, TO_GEOSHAPE("BBOX(0.0, 12.0, 60.0, 30.0)")) | WHERE geotile IS NOT NULL | STATS - count = COUNT(*), + count = COUNT(geotile), centroid = ST_CENTROID_AGG(location) BY geotile -| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| EVAL geotileString = TO_STRING(geotile) +| EVAL cellBoundary = 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)) ; gridGeotileStatsByBoundsEnvelope -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | EVAL geotile = ST_GEOTILE(location, 3, ST_ENVELOPE(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(*), + count = COUNT(geotile), centroid = ST_CENTROID_AGG(location) BY geotile -| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) +| EVAL geotileString = TO_STRING(geotile) +| EVAL cellBoundary = TO_GEOSHAPE(geotile) +| KEEP count, centroid, geotileString, cellBoundary | SORT count DESC, geotileString ASC -| KEEP count, centroid, geotileString ; -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)) ; gridGeotileStatsByWhereUK -required_capability: spatial_grid +required_capability: spatial_grid_types 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))")) @@ -468,18 +698,19 @@ FROM airports count = COUNT(location), centroid = ST_CENTROID_AGG(location) BY geotile -| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) -| KEEP count, centroid, geotileString +| EVAL geotileString = TO_STRING(geotile) +| EVAL cellBoundary = 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 -required_capability: spatial_grid +required_capability: spatial_grid_types 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))")) @@ -489,20 +720,21 @@ FROM airports count = COUNT(location), centroid = ST_CENTROID_AGG(location) BY geotile -| EVAL geotileString = ST_GEOTILE_TO_STRING(geotile) -| KEEP count, centroid, geotileString +| EVAL geotileString = TO_STRING(geotile) +| EVAL cellBoundary = 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 -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | STATS @@ -522,7 +754,7 @@ count:long | centroid:geo_point ; gridGeotileInStatsByWhereUK -required_capability: spatial_grid +required_capability: spatial_grid_types 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))")) @@ -542,94 +774,162 @@ count:long | centroid:geo_point # Tests for geo_grid function: ST_GEOHEX ############################################### -geohexStringToLong -required_capability: spatial_grid +toGeohex +required_capability: spatial_grid_types -// tag::geohex_to_long[] -ROW geohex = "841f059ffffffff" -| EVAL geohexLong = ST_GEOHEX_TO_LONG(geohex) -// end::geohex_to_long[] +// tag::to_geohex[] +ROW string = "841f059ffffffff" +| EVAL geohex = TO_GEOHEX(string) +// end::to_geohex[] ; -// tag::geohex_to_long-result[] -geohex:keyword | geohexLong:long -841f059ffffffff | 595020895127339007 -// end::geohex_to_long-result[] +// tag::to_geohex-result[] +string:keyword | geohex:geohex +841f059ffffffff | 841f059ffffffff +// end::to_geohex-result[] ; -geohexLongToString -required_capability: spatial_grid +toGeohexToLong +required_capability: spatial_grid_types -// tag::geohex_to_string[] -ROW geohex = 595020895127339007 -| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) -// end::geohex_to_string[] +// tag::to_geohex_to_long[] +ROW string = "841f059ffffffff" +| EVAL geohex = TO_GEOHEX(string) +| EVAL geohexLong = TO_LONG(geohex) +| EVAL geohex2 = TO_GEOHEX(geohex) +// end::to_geohex_to_long[] ; -// tag::geohex_to_string-result[] -geohex:long | geohexString:keyword +// tag::to_geohex_to_long-result[] +string:keyword | geohex:geohex | geohexLong:long | geohex2:geohex +841f059ffffffff | 841f059ffffffff | 595020895127339007 | 841f059ffffffff +// end::to_geohex_to_long-result[] +; + +geohexLongToGeoHex +required_capability: spatial_grid_types + +// tag::long_to_geohex[] +ROW gridId = 595020895127339007 +| EVAL geohex = TO_GEOHEX(gridId) +// end::long_to_geohex[] +; + +// tag::long_to_geohex-result[] +gridId:long | geohex:geohex 595020895127339007 | 841f059ffffffff -// end::geohex_to_string-result[] +// end::long_to_geohex-result[] +; + +geohexStringToGeoshape +required_capability: spatial_grid_types + +// tag::geohex_to_geoshape[] +ROW hex = "841f059ffffffff" +| EVAL boundary = TO_GEOSHAPE(TO_GEOHEX(hex)) +// end::geohex_to_geoshape[] +; + +// tag::geohex_to_geoshape-result[] +hex: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 +required_capability: spatial_grid_types -// tag::st_geohex-literal[] +// 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[] +// 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[] +// tag::st_geohex_literal-result[] +location:geo_point | geohex4:geohex | geohex3:geohex | geohex2:geohex | geohex1:geohex +POINT (12.6493508684508 55.6285017221528) | 841f059ffffffff | 831f05fffffffff | 821f07fffffffff | 811f3ffffffffff +// end::st_geohex_literal-result[] ; geohexLiteralString -required_capability: spatial_grid +required_capability: spatial_grid_types 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)) +| EVAL geohex4 = TO_STRING(ST_GEOHEX(location, 4)), + geohex3 = TO_STRING(ST_GEOHEX(location, 3)), + geohex2 = TO_STRING(ST_GEOHEX(location, 2)), + geohex1 = TO_STRING(ST_GEOHEX(location, 1)) ; location:geo_point | geohex4:keyword | geohex3:keyword | geohex2:keyword | geohex1:keyword POINT (12.6493508684508 55.6285017221528) | 841f059ffffffff | 831f05fffffffff | 821f07fffffffff | 811f3ffffffffff ; +geohexLiteralLong +required_capability: spatial_grid_types + +ROW location = TO_GEOPOINT("POINT(12.6493508684508 55.6285017221528)") +| EVAL geohex4 = TO_LONG(ST_GEOHEX(location, 4)), + geohex3 = TO_LONG(ST_GEOHEX(location, 3)), + geohex2 = TO_LONG(ST_GEOHEX(location, 2)), + geohex1 = TO_LONG(ST_GEOHEX(location, 1)) +; + +location:geo_point | geohex4:long | geohex3:long | geohex2:long | geohex1:long +POINT (12.6493508684508 55.6285017221528) | 595020895127339007 | 590517321269772287 | 586013859081355263 | 581514107744681983 +; + +geohexLiteralMv +required_capability: spatial_grid_types +required_capability: fn_mv_contains + +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) +| EVAL chain = MV_APPEND(geohex4, MV_APPEND(geohex3, MV_APPEND(geohex2, geohex1))) +| EVAL description = MV_CONCAT(chain::keyword, " --> ") +| EVAL top = MV_LAST(chain) +| EVAL bottom = MV_FIRST(chain) +| EVAL top = COALESCE(top, null, bottom) +| EVAL bottom = COALESCE(bottom, null, top) +| WHERE MV_CONTAINS(chain, top) AND MV_CONTAINS(chain, bottom) +| KEEP location, top, bottom, chain, description +; + +location:geo_point | top:geohex | bottom:geohex | chain:geohex | description:keyword +POINT (12.6493508684508 55.6285017221528) | 811f3ffffffffff | 841f059ffffffff | [841f059ffffffff, 831f05fffffffff, 821f07fffffffff, 811f3ffffffffff] | 841f059ffffffff --> 831f05fffffffff --> 821f07fffffffff --> 811f3ffffffffff +; + geohexField -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | WHERE abbrev == "CPH" | EVAL geohex = ST_GEOHEX(location, 7) -| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) -| KEEP geohex, geohexString, abbrev, name, location +| KEEP geohex, abbrev, name, location ; -geohex:long | geohexString:keyword | abbrev:keyword | name:text | location:geo_point -608531685838946303 | 871f05818ffffff | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) +geohex:geohex | abbrev:keyword | name:text | location:geo_point +871f05818ffffff | CPH | Copenhagen | POINT (12.6493508684508 55.6285017221528) ; gridGeohexStatsBy -required_capability: spatial_grid +required_capability: spatial_grid_types // tag::st_geohex-grid[] FROM airports | EVAL geohex = ST_GEOHEX(location, 1) | STATS - count = COUNT(*), + count = COUNT(geohex), centroid = ST_CENTROID_AGG(location) BY geohex | WHERE count >= 10 -| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| EVAL geohexString = TO_STRING(geohex) | KEEP count, centroid, geohexString | SORT count DESC, geohexString ASC // end::st_geohex-grid[] @@ -651,17 +951,51 @@ count:long | centroid:geo_point | geohexString:keywo // end::st_geohex-grid-result[] ; +gridGeohexCase +required_capability: spatial_grid_types + +// tag::st_geohex-case[] +FROM airports +| EVAL geohex = ST_GEOHEX(location, 2) +| STATS + count = COUNT(geohex), + centroid = ST_CENTROID_AGG(location) + BY geohex +| WHERE count >= 5 +| EVAL parent = ST_GEOHEX(centroid, 1) +| EVAL level = CASE( + parent == "811fbffffffffff"::geohex, "high", + parent == "81197ffffffffff"::geohex, "medium", + parent == "8129bffffffffff"::geohex, "low", + "other" + ) +| EVAL geohexString = TO_STRING(geohex) +| KEEP count, centroid, geohexString, parent, level +| SORT count DESC, geohexString ASC +// end::st_geohex-case[] +; + +// tag::st_geohex-case-result[] +count:long | centroid:geo_point | geohexString:keyword | parent:geohex | level:keyword +6 | POINT (5.582276992499828 50.72238312335685) | 821fa7fffffffff | 811fbffffffffff | high +5 | POINT (-1.7227098606526852 51.717823022045195) | 82195ffffffffff | 81197ffffffffff | medium +5 | POINT (8.6918301936239 45.19817395694554) | 821f9ffffffffff | 811fbffffffffff | high +5 | POINT (-117.60585453920066 33.392433090135455) | 8229a7fffffffff | 8129bffffffffff | low +5 | POINT (-82.21536266617477 42.29504897072911) | 822ab7fffffffff | 812abffffffffff | other +// end::st_geohex-case-result[] +; + gridGeohexQuery -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports -| WHERE ST_GEOHEX(location, 1) == ST_GEOHEX_TO_LONG("812bbffffffffff") +| WHERE ST_GEOHEX(location, 1) == TO_GEOHEX("812bbffffffffff") | EVAL geohex = ST_GEOHEX(location, 2) | STATS - count = COUNT(*), + count = COUNT(geohex), centroid = ST_CENTROID_AGG(location) BY geohex -| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| EVAL geohexString = TO_STRING(geohex) | KEEP count, centroid, geohexString | SORT count DESC, geohexString ASC ; @@ -676,45 +1010,46 @@ count:long | centroid:geo_point | geohexString:keywor ; gridGeohexStatsByBounds -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | EVAL geohex = ST_GEOHEX(location, 1, TO_GEOSHAPE("BBOX(0.0, 12.0, 60.0, 30.0)")) | WHERE geohex IS NOT NULL | STATS - count = COUNT(*), + count = COUNT(geohex), centroid = ST_CENTROID_AGG(location) BY geohex -| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| EVAL geohexString = TO_STRING(geohex) +| EVAL cellBoundary = 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)) ; gridGeohexStatsByBoundsEnvelope -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | EVAL geohex = ST_GEOHEX(location, 1, ST_ENVELOPE(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(*), + count = COUNT(geohex), centroid = ST_CENTROID_AGG(location) BY geohex -| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) +| EVAL geohexString = TO_STRING(geohex) | SORT count DESC, geohexString ASC | KEEP count, centroid, geohexString ; @@ -734,12 +1069,12 @@ count:long | centroid:geo_point | geohexString:keywor ; gridGeohexQueryBounds -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | EVAL geohex = ST_GEOHEX(location, 1, TO_GEOSHAPE("BBOX(0.0, 12.0, 60.0, 30.0)")) -| WHERE ST_GEOHEX_TO_STRING(geohex) == "8108bffffffffff" -| EVAL geohexString = ST_GEOHEX_TO_STRING(ST_GEOHEX(location, 1)) +| WHERE TO_STRING(geohex) == "8108bffffffffff" +| EVAL geohexString = TO_STRING(ST_GEOHEX(location, 1)) | KEEP abbrev, location, geohexString | SORT abbrev ASC ; @@ -753,44 +1088,43 @@ TLL | POINT (24.798964869983 59.4165014697451) | 8108bffffffffff ; gridGeohexByBounds -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | WHERE abbrev IN ("RTW", "TIP", "XMN") | EVAL geohex = ST_GEOHEX(location, 1, TO_GEOSHAPE("BBOX(0.0, 12.0, 60.0, 30.0)")) -| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) -| KEEP abbrev, location, geohex, geohexString +| KEEP abbrev, location, geohex | SORT abbrev ASC ; -abbrev:keyword | location:geo_point | geohex:long | geohexString:keyword -RTW | POINT (46.035023249891 51.5606456508842) | null | null -TIP | POINT (13.1442589810713 32.6691695504993) | 582085853791125503 | 813fbffffffffff -XMN | POINT (118.12696884672 24.537192570557) | null | null +abbrev:keyword | location:geo_point | geohex:geohex +RTW | POINT (46.035023249891 51.5606456508842) | null +TIP | POINT (13.1442589810713 32.6691695504993) | 813fbffffffffff +XMN | POINT (118.12696884672 24.537192570557) | null ; literalGridGeohexByBounds -required_capability: spatial_grid +required_capability: spatial_grid_types 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("BBOX(0.0, 12.0, 60.0, 30.0)")) -| EVAL geohex = ST_GEOHEX_TO_STRING(geohex) -| EVAL geohexBounded = ST_GEOHEX_TO_STRING(geohexBounded) -| KEEP location, geohex, geohexBounded +| EVAL geohexShape = TO_GEOSHAPE(geohex) +| EVAL geohex = TO_STRING(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:geohex | 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)) ; gridGeohexStatsByWhereUK -required_capability: spatial_grid +required_capability: spatial_grid_types 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))")) @@ -799,20 +1133,21 @@ FROM airports count = COUNT(location), centroid = ST_CENTROID_AGG(location) BY geohex -| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) -| KEEP count, centroid, geohexString +| EVAL geohexString = TO_STRING(geohex) +| EVAL cellBoundary = 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 -required_capability: spatial_grid +required_capability: spatial_grid_types 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))")) @@ -822,30 +1157,31 @@ FROM airports count = COUNT(location), centroid = ST_CENTROID_AGG(location) BY geohex -| EVAL geohexString = ST_GEOHEX_TO_STRING(geohex) -| KEEP count, centroid, geohexString +| EVAL geohexString = TO_STRING(geohex) +| EVAL cellBoundary = 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 -required_capability: spatial_grid +required_capability: spatial_grid_types FROM airports | STATS @@ -865,7 +1201,7 @@ count:long | centroid:geo_point ; gridGeohexInStatsByWhereUK -required_capability: spatial_grid +required_capability: spatial_grid_types 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))")) diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/LookupJoinTypesIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/LookupJoinTypesIT.java index bc4053584fc77..c305938c09b0b 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/LookupJoinTypesIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/LookupJoinTypesIT.java @@ -52,6 +52,9 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.DOC_DATA_TYPE; import static org.elasticsearch.xpack.esql.core.type.DataType.DOUBLE; import static org.elasticsearch.xpack.esql.core.type.DataType.FLOAT; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; import static org.elasticsearch.xpack.esql.core.type.DataType.HALF_FLOAT; import static org.elasticsearch.xpack.esql.core.type.DataType.INTEGER; import static org.elasticsearch.xpack.esql.core.type.DataType.IP; @@ -180,6 +183,9 @@ protected Collection> nodePlugins() { || type == DOC_DATA_TYPE || type == TSID_DATA_TYPE || type == AGGREGATE_METRIC_DOUBLE + || type == GEOHASH + || type == GEOTILE + || type == GEOHEX || type.esType() == null || type.isCounter() || DataType.isRepresentable(type) == false) { diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/SpatialGridLicenseTestCase.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/SpatialGridLicenseTestCase.java index 421bea9c0d69c..e7297f49f0cea 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/SpatialGridLicenseTestCase.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/SpatialGridLicenseTestCase.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.esql.spatial; +import org.elasticsearch.Build; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.index.IndexRequest; @@ -15,9 +16,12 @@ import org.elasticsearch.xpack.esql.VerificationException; import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; import org.elasticsearch.xpack.esql.action.EsqlCapabilities; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter; import org.junit.Before; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; @@ -32,7 +36,6 @@ public abstract class SpatialGridLicenseTestCase extends AbstractEsqlIntegTestCa @Before public void setupIndex() throws Exception { - assumeTrue("requires SPATIAL_GRID capability", EsqlCapabilities.Cap.SPATIAL_GRID.isEnabled()); createAndPopulateIndexes(10); } @@ -40,12 +43,30 @@ public void setupIndex() throws Exception { protected abstract String gridFunction(); - protected abstract Map expectedValues(); + protected abstract DataType gridType(); + + protected abstract long pointToGridId(Point point); + + protected Map expectedValues() { + Map expected = new HashMap<>(); + for (Point point : testData) { + long gridId = pointToGridId(point); + expected.compute(EsqlDataTypeConverter.geoGridToString(gridId, gridType()), (k, v) -> v == null ? 1 : v + 1); + } + return expected; + } protected int precision() { return 1; // Default precision for grid function tests, can be overridden in subclasses } + /** + * Test that the geo_grid functions are disabled outside of SNAPSHOT. + */ + public void testGeoGridDisabled() { + assertGeoGridDisabledWith("index_geo_point"); + } + /** * This test will fail without a platinum license */ @@ -60,6 +81,7 @@ public void testGeoGridWithPoints() { } protected void assertGeoGridFromIndex(String index) { + assumeTrue("requires SPATIAL_GRID_TYPES capability", EsqlCapabilities.Cap.SPATIAL_GRID_TYPES.isEnabled()); assumeTrue("geo_shape capability not yet implemented", index.equals("index_geo_point")); var query = String.format(Locale.ROOT, """ FROM %s @@ -69,11 +91,11 @@ protected void assertGeoGridFromIndex(String index) { """, index, gridFunction(), precision()); try (var resp = run(query)) { assertColumnNames(resp.columns(), List.of("gridId", "count")); - assertColumnTypes(resp.columns(), List.of("long", "long")); - Map values = getValuesMap(resp.values()); - Map expected = expectedValues(); + assertColumnTypes(resp.columns(), List.of(gridType().typeName(), "long")); + Map values = getValuesMap(resp.values()); + Map expected = expectedValues(); assertThat(values.size(), equalTo(expected.size())); - for (Long gridId : expected.keySet()) { + for (String gridId : expected.keySet()) { assertThat("Missing grid-id: " + gridId, values.containsKey(gridId), equalTo(true)); assertThat("Unexpected count for grid-id: " + gridId, values.get(gridId), equalTo(expected.get(gridId))); } @@ -81,6 +103,7 @@ protected void assertGeoGridFromIndex(String index) { } protected void assertGeoGridFailsWith(String index) { + assumeTrue("requires SPATIAL_GRID_TYPES capability", EsqlCapabilities.Cap.SPATIAL_GRID_TYPES.isEnabled()); assumeTrue("geo_shape capability not yet implemented", index.equals("index_geo_point")); var query = String.format(Locale.ROOT, """ FROM %s @@ -97,9 +120,21 @@ protected void assertGeoGridFailsWith(String index) { assertThat(e.getMessage(), containsString(expectedError)); } - public static Map getValuesMap(Iterator> values) { - var valuesMap = new LinkedHashMap(); - values.forEachRemaining(row -> { valuesMap.put(((Number) row.next()).longValue(), ((Number) row.next()).longValue()); }); + protected void assertGeoGridDisabledWith(String index) { + assumeFalse("testing feature is disabled in non-snapshot builds", Build.current().isSnapshot()); + var query = String.format(Locale.ROOT, """ + FROM %s + | EVAL gridId = %s(location, %d) + | STATS count=COUNT() BY gridId + """, index, gridFunction(), precision()); + var expectedError = String.format(Locale.ROOT, "Unknown function [%s]", gridFunction()); + ElasticsearchException e = expectThrows(VerificationException.class, () -> run(query)); + assertThat(e.getMessage(), containsString(expectedError)); + } + + public static Map getValuesMap(Iterator> values) { + var valuesMap = new LinkedHashMap(); + values.forEachRemaining(row -> { valuesMap.put(row.next().toString(), ((Number) row.next()).longValue()); }); return valuesMap; } diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/StGeohashLicenseIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/StGeohashLicenseIT.java index c3e50b9b87b5d..ade5753087a49 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/StGeohashLicenseIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/StGeohashLicenseIT.java @@ -10,13 +10,12 @@ import org.elasticsearch.geometry.Point; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.xpack.esql.action.EsqlPluginWithEnterpriseOrTrialLicense; +import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohash; import org.elasticsearch.xpack.spatial.SpatialPlugin; import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class StGeohashLicenseIT extends SpatialGridLicenseTestCase { @Override @@ -30,13 +29,13 @@ protected String gridFunction() { } @Override - protected Map expectedValues() { - Map expected = new HashMap<>(); - for (Point point : testData) { - long gridId = StGeohash.unboundedGrid.calculateGridId(point, precision()); - expected.compute(gridId, (k, v) -> v == null ? 1 : v + 1); - } - return expected; + protected DataType gridType() { + return DataType.GEOHASH; + } + + @Override + protected long pointToGridId(Point point) { + return StGeohash.unboundedGrid.calculateGridId(point, precision()); } public void testGeoGridWithShapes() { diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/StGeohexLicenseIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/StGeohexLicenseIT.java index 5bc4eef4e78a7..55e2002b997c0 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/StGeohexLicenseIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/StGeohexLicenseIT.java @@ -10,13 +10,12 @@ import org.elasticsearch.geometry.Point; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.xpack.esql.action.EsqlPluginWithEnterpriseOrTrialLicense; +import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeohex; import org.elasticsearch.xpack.spatial.SpatialPlugin; import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class StGeohexLicenseIT extends SpatialGridLicenseTestCase { @Override @@ -30,13 +29,13 @@ protected String gridFunction() { } @Override - protected Map expectedValues() { - Map expected = new HashMap<>(); - for (Point point : testData) { - long gridId = StGeohex.unboundedGrid.calculateGridId(point, precision()); - expected.compute(gridId, (k, v) -> v == null ? 1 : v + 1); - } - return expected; + protected DataType gridType() { + return DataType.GEOHEX; + } + + @Override + protected long pointToGridId(Point point) { + return StGeohex.unboundedGrid.calculateGridId(point, precision()); } public void testGeoGridWithShapes() { diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/StGeotileLicenseIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/StGeotileLicenseIT.java index d5f42c43587e2..ad0200bd32ce5 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/StGeotileLicenseIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/spatial/StGeotileLicenseIT.java @@ -10,13 +10,12 @@ import org.elasticsearch.geometry.Point; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.xpack.esql.action.EsqlPluginWithEnterpriseOrTrialLicense; +import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotile; import org.elasticsearch.xpack.spatial.SpatialPlugin; import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class StGeotileLicenseIT extends SpatialGridLicenseTestCase { @Override @@ -30,13 +29,13 @@ protected String gridFunction() { } @Override - protected Map expectedValues() { - Map expected = new HashMap<>(); - for (Point point : testData) { - long gridId = StGeotile.unboundedGrid.calculateGridId(point, precision()); - expected.compute(gridId, (k, v) -> v == null ? 1 : v + 1); - } - return expected; + protected DataType gridType() { + return DataType.GEOTILE; + } + + @Override + protected long pointToGridId(Point point) { + return StGeotile.unboundedGrid.calculateGridId(point, precision()); } public void testGeoGridWithShapes() { 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/convert/ToGeoShapeFromGeoGridEvaluator.java similarity index 58% rename from x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringFromLongEvaluator.java rename to x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeFromGeoGridEvaluator.java index 440a2a6456d17..c87b99790f7f4 100644 --- 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/convert/ToGeoShapeFromGeoGridEvaluator.java @@ -2,8 +2,9 @@ // 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; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; +import java.lang.IllegalArgumentException; import java.lang.Override; import java.lang.String; import org.apache.lucene.util.BytesRef; @@ -17,26 +18,29 @@ 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; +import org.elasticsearch.xpack.esql.core.type.DataType; /** - * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeohashToString}. + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link ToGeoShape}. * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. */ -public final class StGeohashToStringFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { - private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(StGeohashToStringFromLongEvaluator.class); +public final class ToGeoShapeFromGeoGridEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(ToGeoShapeFromGeoGridEvaluator.class); - private final EvalOperator.ExpressionEvaluator gridId; + private final EvalOperator.ExpressionEvaluator in; - public StGeohashToStringFromLongEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, - DriverContext driverContext) { + private final DataType dataType; + + public ToGeoShapeFromGeoGridEvaluator(Source source, EvalOperator.ExpressionEvaluator in, + DataType dataType, DriverContext driverContext) { super(driverContext, source); - this.gridId = gridId; + this.in = in; + this.dataType = dataType; } @Override public EvalOperator.ExpressionEvaluator next() { - return gridId; + return in; } @Override @@ -44,11 +48,21 @@ 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 { + return driverContext.blockFactory().newConstantBytesRefBlockWith(evalValue(vector, 0), positionCount); + } catch (IllegalArgumentException e) { + registerException(e); + return driverContext.blockFactory().newConstantNullBlock(positionCount); + } } try (BytesRefBlock.Builder builder = driverContext.blockFactory().newBytesRefBlockBuilder(positionCount)) { for (int p = 0; p < positionCount; p++) { - builder.appendBytesRef(evalValue(vector, p)); + try { + builder.appendBytesRef(evalValue(vector, p)); + } catch (IllegalArgumentException e) { + registerException(e); + builder.appendNull(); + } } return builder.build(); } @@ -56,7 +70,7 @@ public Block evalVector(Vector v) { private BytesRef evalValue(LongVector container, int index) { long value = container.getLong(index); - return StGeohashToString.fromLong(value); + return ToGeoShape.fromGeoGrid(value, this.dataType); } @Override @@ -71,13 +85,17 @@ public Block evalBlock(Block b) { 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; + try { + BytesRef value = evalValue(block, i); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendBytesRef(value); + valuesAppended = true; + } catch (IllegalArgumentException e) { + registerException(e); } - builder.appendBytesRef(value); - valuesAppended = true; } if (valuesAppended == false) { builder.appendNull(); @@ -91,44 +109,47 @@ public Block evalBlock(Block b) { private BytesRef evalValue(LongBlock container, int index) { long value = container.getLong(index); - return StGeohashToString.fromLong(value); + return ToGeoShape.fromGeoGrid(value, this.dataType); } @Override public String toString() { - return "StGeohashToStringFromLongEvaluator[" + "gridId=" + gridId + "]"; + return "ToGeoShapeFromGeoGridEvaluator[" + "in=" + in + ", dataType=" + dataType + "]"; } @Override public void close() { - Releasables.closeExpectNoException(gridId); + Releasables.closeExpectNoException(in); } @Override public long baseRamBytesUsed() { long baseRamBytesUsed = BASE_RAM_BYTES_USED; - baseRamBytesUsed += gridId.baseRamBytesUsed(); + baseRamBytesUsed += in.baseRamBytesUsed(); return baseRamBytesUsed; } public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final Source source; - private final EvalOperator.ExpressionEvaluator.Factory gridId; + private final EvalOperator.ExpressionEvaluator.Factory in; + + private final DataType dataType; - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in, DataType dataType) { this.source = source; - this.gridId = gridId; + this.in = in; + this.dataType = dataType; } @Override - public StGeohashToStringFromLongEvaluator get(DriverContext context) { - return new StGeohashToStringFromLongEvaluator(source, gridId.get(context), context); + public ToGeoShapeFromGeoGridEvaluator get(DriverContext context) { + return new ToGeoShapeFromGeoGridEvaluator(source, in.get(context), dataType, context); } @Override public String toString() { - return "StGeohashToStringFromLongEvaluator[" + "gridId=" + gridId + "]"; + return "ToGeoShapeFromGeoGridEvaluator[" + "in=" + in + ", dataType=" + dataType + "]"; } } } 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/convert/ToGeohashFromStringEvaluator.java similarity index 64% rename from x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongFromStringEvaluator.java rename to x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashFromStringEvaluator.java index 04ea23fdfbc64..5eeca08465d34 100644 --- 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/convert/ToGeohashFromStringEvaluator.java @@ -2,8 +2,9 @@ // 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; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; +import java.lang.IllegalArgumentException; import java.lang.Override; import java.lang.String; import org.apache.lucene.util.BytesRef; @@ -17,26 +18,25 @@ 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}. + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link ToGeohash}. * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. */ -public final class StGeotileToLongFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { - private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(StGeotileToLongFromStringEvaluator.class); +public final class ToGeohashFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(ToGeohashFromStringEvaluator.class); - private final EvalOperator.ExpressionEvaluator gridId; + private final EvalOperator.ExpressionEvaluator in; - public StGeotileToLongFromStringEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, + public ToGeohashFromStringEvaluator(Source source, EvalOperator.ExpressionEvaluator in, DriverContext driverContext) { super(driverContext, source); - this.gridId = gridId; + this.in = in; } @Override public EvalOperator.ExpressionEvaluator next() { - return gridId; + return in; } @Override @@ -45,11 +45,21 @@ public Block evalVector(Vector v) { int positionCount = v.getPositionCount(); BytesRef scratchPad = new BytesRef(); if (vector.isConstant()) { - return driverContext.blockFactory().newConstantLongBlockWith(evalValue(vector, 0, scratchPad), positionCount); + try { + return driverContext.blockFactory().newConstantLongBlockWith(evalValue(vector, 0, scratchPad), positionCount); + } catch (IllegalArgumentException e) { + registerException(e); + return driverContext.blockFactory().newConstantNullBlock(positionCount); + } } try (LongBlock.Builder builder = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { for (int p = 0; p < positionCount; p++) { - builder.appendLong(evalValue(vector, p, scratchPad)); + try { + builder.appendLong(evalValue(vector, p, scratchPad)); + } catch (IllegalArgumentException e) { + registerException(e); + builder.appendNull(); + } } return builder.build(); } @@ -57,7 +67,7 @@ public Block evalVector(Vector v) { private long evalValue(BytesRefVector container, int index, BytesRef scratchPad) { BytesRef value = container.getBytesRef(index, scratchPad); - return StGeotileToLong.fromString(value); + return ToGeohash.fromString(value); } @Override @@ -73,13 +83,17 @@ public Block evalBlock(Block b) { 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; + try { + long value = evalValue(block, i, scratchPad); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendLong(value); + valuesAppended = true; + } catch (IllegalArgumentException e) { + registerException(e); } - builder.appendLong(value); - valuesAppended = true; } if (valuesAppended == false) { builder.appendNull(); @@ -93,44 +107,44 @@ public Block evalBlock(Block b) { private long evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { BytesRef value = container.getBytesRef(index, scratchPad); - return StGeotileToLong.fromString(value); + return ToGeohash.fromString(value); } @Override public String toString() { - return "StGeotileToLongFromStringEvaluator[" + "gridId=" + gridId + "]"; + return "ToGeohashFromStringEvaluator[" + "in=" + in + "]"; } @Override public void close() { - Releasables.closeExpectNoException(gridId); + Releasables.closeExpectNoException(in); } @Override public long baseRamBytesUsed() { long baseRamBytesUsed = BASE_RAM_BYTES_USED; - baseRamBytesUsed += gridId.baseRamBytesUsed(); + baseRamBytesUsed += in.baseRamBytesUsed(); return baseRamBytesUsed; } public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final Source source; - private final EvalOperator.ExpressionEvaluator.Factory gridId; + private final EvalOperator.ExpressionEvaluator.Factory in; - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in) { this.source = source; - this.gridId = gridId; + this.in = in; } @Override - public StGeotileToLongFromStringEvaluator get(DriverContext context) { - return new StGeotileToLongFromStringEvaluator(source, gridId.get(context), context); + public ToGeohashFromStringEvaluator get(DriverContext context) { + return new ToGeohashFromStringEvaluator(source, in.get(context), context); } @Override public String toString() { - return "StGeotileToLongFromStringEvaluator[" + "gridId=" + gridId + "]"; + return "ToGeohashFromStringEvaluator[" + "in=" + in + "]"; } } } 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/convert/ToGeohexFromStringEvaluator.java similarity index 64% rename from x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongFromStringEvaluator.java rename to x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexFromStringEvaluator.java index 61f82764e525d..f3bc3f3aec410 100644 --- 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/convert/ToGeohexFromStringEvaluator.java @@ -2,8 +2,9 @@ // 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; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; +import java.lang.IllegalArgumentException; import java.lang.Override; import java.lang.String; import org.apache.lucene.util.BytesRef; @@ -17,26 +18,25 @@ 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}. + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link ToGeohex}. * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. */ -public final class StGeohashToLongFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { - private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(StGeohashToLongFromStringEvaluator.class); +public final class ToGeohexFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(ToGeohexFromStringEvaluator.class); - private final EvalOperator.ExpressionEvaluator gridId; + private final EvalOperator.ExpressionEvaluator in; - public StGeohashToLongFromStringEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, + public ToGeohexFromStringEvaluator(Source source, EvalOperator.ExpressionEvaluator in, DriverContext driverContext) { super(driverContext, source); - this.gridId = gridId; + this.in = in; } @Override public EvalOperator.ExpressionEvaluator next() { - return gridId; + return in; } @Override @@ -45,11 +45,21 @@ public Block evalVector(Vector v) { int positionCount = v.getPositionCount(); BytesRef scratchPad = new BytesRef(); if (vector.isConstant()) { - return driverContext.blockFactory().newConstantLongBlockWith(evalValue(vector, 0, scratchPad), positionCount); + try { + return driverContext.blockFactory().newConstantLongBlockWith(evalValue(vector, 0, scratchPad), positionCount); + } catch (IllegalArgumentException e) { + registerException(e); + return driverContext.blockFactory().newConstantNullBlock(positionCount); + } } try (LongBlock.Builder builder = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { for (int p = 0; p < positionCount; p++) { - builder.appendLong(evalValue(vector, p, scratchPad)); + try { + builder.appendLong(evalValue(vector, p, scratchPad)); + } catch (IllegalArgumentException e) { + registerException(e); + builder.appendNull(); + } } return builder.build(); } @@ -57,7 +67,7 @@ public Block evalVector(Vector v) { private long evalValue(BytesRefVector container, int index, BytesRef scratchPad) { BytesRef value = container.getBytesRef(index, scratchPad); - return StGeohashToLong.fromString(value); + return ToGeohex.fromString(value); } @Override @@ -73,13 +83,17 @@ public Block evalBlock(Block b) { 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; + try { + long value = evalValue(block, i, scratchPad); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendLong(value); + valuesAppended = true; + } catch (IllegalArgumentException e) { + registerException(e); } - builder.appendLong(value); - valuesAppended = true; } if (valuesAppended == false) { builder.appendNull(); @@ -93,44 +107,44 @@ public Block evalBlock(Block b) { private long evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { BytesRef value = container.getBytesRef(index, scratchPad); - return StGeohashToLong.fromString(value); + return ToGeohex.fromString(value); } @Override public String toString() { - return "StGeohashToLongFromStringEvaluator[" + "gridId=" + gridId + "]"; + return "ToGeohexFromStringEvaluator[" + "in=" + in + "]"; } @Override public void close() { - Releasables.closeExpectNoException(gridId); + Releasables.closeExpectNoException(in); } @Override public long baseRamBytesUsed() { long baseRamBytesUsed = BASE_RAM_BYTES_USED; - baseRamBytesUsed += gridId.baseRamBytesUsed(); + baseRamBytesUsed += in.baseRamBytesUsed(); return baseRamBytesUsed; } public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final Source source; - private final EvalOperator.ExpressionEvaluator.Factory gridId; + private final EvalOperator.ExpressionEvaluator.Factory in; - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in) { this.source = source; - this.gridId = gridId; + this.in = in; } @Override - public StGeohashToLongFromStringEvaluator get(DriverContext context) { - return new StGeohashToLongFromStringEvaluator(source, gridId.get(context), context); + public ToGeohexFromStringEvaluator get(DriverContext context) { + return new ToGeohexFromStringEvaluator(source, in.get(context), context); } @Override public String toString() { - return "StGeohashToLongFromStringEvaluator[" + "gridId=" + gridId + "]"; + return "ToGeohexFromStringEvaluator[" + "in=" + in + "]"; } } } 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/convert/ToGeotileFromStringEvaluator.java similarity index 64% rename from x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongFromStringEvaluator.java rename to x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileFromStringEvaluator.java index b04e0bdceef4e..a77c85d7415fe 100644 --- 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/convert/ToGeotileFromStringEvaluator.java @@ -2,8 +2,9 @@ // 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; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; +import java.lang.IllegalArgumentException; import java.lang.Override; import java.lang.String; import org.apache.lucene.util.BytesRef; @@ -17,26 +18,25 @@ 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}. + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link ToGeotile}. * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. */ -public final class StGeohexToLongFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { - private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(StGeohexToLongFromStringEvaluator.class); +public final class ToGeotileFromStringEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(ToGeotileFromStringEvaluator.class); - private final EvalOperator.ExpressionEvaluator gridId; + private final EvalOperator.ExpressionEvaluator in; - public StGeohexToLongFromStringEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, + public ToGeotileFromStringEvaluator(Source source, EvalOperator.ExpressionEvaluator in, DriverContext driverContext) { super(driverContext, source); - this.gridId = gridId; + this.in = in; } @Override public EvalOperator.ExpressionEvaluator next() { - return gridId; + return in; } @Override @@ -45,11 +45,21 @@ public Block evalVector(Vector v) { int positionCount = v.getPositionCount(); BytesRef scratchPad = new BytesRef(); if (vector.isConstant()) { - return driverContext.blockFactory().newConstantLongBlockWith(evalValue(vector, 0, scratchPad), positionCount); + try { + return driverContext.blockFactory().newConstantLongBlockWith(evalValue(vector, 0, scratchPad), positionCount); + } catch (IllegalArgumentException e) { + registerException(e); + return driverContext.blockFactory().newConstantNullBlock(positionCount); + } } try (LongBlock.Builder builder = driverContext.blockFactory().newLongBlockBuilder(positionCount)) { for (int p = 0; p < positionCount; p++) { - builder.appendLong(evalValue(vector, p, scratchPad)); + try { + builder.appendLong(evalValue(vector, p, scratchPad)); + } catch (IllegalArgumentException e) { + registerException(e); + builder.appendNull(); + } } return builder.build(); } @@ -57,7 +67,7 @@ public Block evalVector(Vector v) { private long evalValue(BytesRefVector container, int index, BytesRef scratchPad) { BytesRef value = container.getBytesRef(index, scratchPad); - return StGeohexToLong.fromString(value); + return ToGeotile.fromString(value); } @Override @@ -73,13 +83,17 @@ public Block evalBlock(Block b) { 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; + try { + long value = evalValue(block, i, scratchPad); + if (positionOpened == false && valueCount > 1) { + builder.beginPositionEntry(); + positionOpened = true; + } + builder.appendLong(value); + valuesAppended = true; + } catch (IllegalArgumentException e) { + registerException(e); } - builder.appendLong(value); - valuesAppended = true; } if (valuesAppended == false) { builder.appendNull(); @@ -93,44 +107,44 @@ public Block evalBlock(Block b) { private long evalValue(BytesRefBlock container, int index, BytesRef scratchPad) { BytesRef value = container.getBytesRef(index, scratchPad); - return StGeohexToLong.fromString(value); + return ToGeotile.fromString(value); } @Override public String toString() { - return "StGeohexToLongFromStringEvaluator[" + "gridId=" + gridId + "]"; + return "ToGeotileFromStringEvaluator[" + "in=" + in + "]"; } @Override public void close() { - Releasables.closeExpectNoException(gridId); + Releasables.closeExpectNoException(in); } @Override public long baseRamBytesUsed() { long baseRamBytesUsed = BASE_RAM_BYTES_USED; - baseRamBytesUsed += gridId.baseRamBytesUsed(); + baseRamBytesUsed += in.baseRamBytesUsed(); return baseRamBytesUsed; } public static class Factory implements EvalOperator.ExpressionEvaluator.Factory { private final Source source; - private final EvalOperator.ExpressionEvaluator.Factory gridId; + private final EvalOperator.ExpressionEvaluator.Factory in; - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory in) { this.source = source; - this.gridId = gridId; + this.in = in; } @Override - public StGeohexToLongFromStringEvaluator get(DriverContext context) { - return new StGeohexToLongFromStringEvaluator(source, gridId.get(context), context); + public ToGeotileFromStringEvaluator get(DriverContext context) { + return new ToGeotileFromStringEvaluator(source, in.get(context), context); } @Override public String toString() { - return "StGeohexToLongFromStringEvaluator[" + "gridId=" + gridId + "]"; + return "ToGeotileFromStringEvaluator[" + "in=" + in + "]"; } } } 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/convert/ToStringFromGeoGridEvaluator.java similarity index 78% rename from x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringFromLongEvaluator.java rename to x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringFromGeoGridEvaluator.java index 6f45f7aea646a..c40334282c9bf 100644 --- 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/convert/ToStringFromGeoGridEvaluator.java @@ -2,7 +2,7 @@ // 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; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import java.lang.Override; import java.lang.String; @@ -17,21 +17,24 @@ 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; +import org.elasticsearch.xpack.esql.core.type.DataType; /** - * {@link EvalOperator.ExpressionEvaluator} implementation for {@link StGeotileToString}. + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link ToString}. * This class is generated. Edit {@code ConvertEvaluatorImplementer} instead. */ -public final class StGeotileToStringFromLongEvaluator extends AbstractConvertFunction.AbstractEvaluator { - private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(StGeotileToStringFromLongEvaluator.class); +public final class ToStringFromGeoGridEvaluator extends AbstractConvertFunction.AbstractEvaluator { + private static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(ToStringFromGeoGridEvaluator.class); private final EvalOperator.ExpressionEvaluator gridId; - public StGeotileToStringFromLongEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, - DriverContext driverContext) { + private final DataType dataType; + + public ToStringFromGeoGridEvaluator(Source source, EvalOperator.ExpressionEvaluator gridId, + DataType dataType, DriverContext driverContext) { super(driverContext, source); this.gridId = gridId; + this.dataType = dataType; } @Override @@ -56,7 +59,7 @@ public Block evalVector(Vector v) { private BytesRef evalValue(LongVector container, int index) { long value = container.getLong(index); - return StGeotileToString.fromLong(value); + return ToString.fromGeoGrid(value, this.dataType); } @Override @@ -91,12 +94,12 @@ public Block evalBlock(Block b) { private BytesRef evalValue(LongBlock container, int index) { long value = container.getLong(index); - return StGeotileToString.fromLong(value); + return ToString.fromGeoGrid(value, this.dataType); } @Override public String toString() { - return "StGeotileToStringFromLongEvaluator[" + "gridId=" + gridId + "]"; + return "ToStringFromGeoGridEvaluator[" + "gridId=" + gridId + ", dataType=" + dataType + "]"; } @Override @@ -116,19 +119,23 @@ public static class Factory implements EvalOperator.ExpressionEvaluator.Factory private final EvalOperator.ExpressionEvaluator.Factory gridId; - public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId) { + private final DataType dataType; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory gridId, + DataType dataType) { this.source = source; this.gridId = gridId; + this.dataType = dataType; } @Override - public StGeotileToStringFromLongEvaluator get(DriverContext context) { - return new StGeotileToStringFromLongEvaluator(source, gridId.get(context), context); + public ToStringFromGeoGridEvaluator get(DriverContext context) { + return new ToStringFromGeoGridEvaluator(source, gridId.get(context), dataType, context); } @Override public String toString() { - return "StGeotileToStringFromLongEvaluator[" + "gridId=" + gridId + "]"; + return "ToStringFromGeoGridEvaluator[" + "gridId=" + gridId + ", dataType=" + dataType + "]"; } } } diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialDisjointGeoPointDocValuesAndConstantGridEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialDisjointGeoPointDocValuesAndConstantGridEvaluator.java new file mode 100644 index 0000000000000..9464495a05178 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialDisjointGeoPointDocValuesAndConstantGridEvaluator.java @@ -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.io.IOException; +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BooleanBlock; +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; +import org.elasticsearch.xpack.esql.core.type.DataType; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link SpatialDisjoint}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class SpatialDisjointGeoPointDocValuesAndConstantGridEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encodedPoints; + + private final long gridId; + + private final DataType gridType; + + private final DriverContext driverContext; + + private Warnings warnings; + + public SpatialDisjointGeoPointDocValuesAndConstantGridEvaluator(Source source, + EvalOperator.ExpressionEvaluator encodedPoints, long gridId, DataType gridType, + DriverContext driverContext) { + this.source = source; + this.encodedPoints = encodedPoints; + this.gridId = gridId; + this.gridType = gridType; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedPointsBlock = (LongBlock) encodedPoints.eval(page)) { + return eval(page.getPositionCount(), encodedPointsBlock); + } + } + + public BooleanBlock eval(int positionCount, LongBlock encodedPointsBlock) { + try(BooleanBlock.Builder result = driverContext.blockFactory().newBooleanBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedPointsBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + SpatialDisjoint.processGeoPointDocValuesAndConstantGrid(result, p, encodedPointsBlock, this.gridId, this.gridType); + } catch (IllegalArgumentException | IOException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "SpatialDisjointGeoPointDocValuesAndConstantGridEvaluator[" + "encodedPoints=" + encodedPoints + ", gridId=" + gridId + ", gridType=" + gridType + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encodedPoints); + } + + 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 encodedPoints; + + private final long gridId; + + private final DataType gridType; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encodedPoints, + long gridId, DataType gridType) { + this.source = source; + this.encodedPoints = encodedPoints; + this.gridId = gridId; + this.gridType = gridType; + } + + @Override + public SpatialDisjointGeoPointDocValuesAndConstantGridEvaluator get(DriverContext context) { + return new SpatialDisjointGeoPointDocValuesAndConstantGridEvaluator(source, encodedPoints.get(context), gridId, gridType, context); + } + + @Override + public String toString() { + return "SpatialDisjointGeoPointDocValuesAndConstantGridEvaluator[" + "encodedPoints=" + encodedPoints + ", gridId=" + gridId + ", gridType=" + gridType + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialDisjointGeoPointDocValuesAndSourceGridEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialDisjointGeoPointDocValuesAndSourceGridEvaluator.java new file mode 100644 index 0000000000000..23a6a0016867b --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialDisjointGeoPointDocValuesAndSourceGridEvaluator.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.io.IOException; +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BooleanBlock; +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; +import org.elasticsearch.xpack.esql.core.type.DataType; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link SpatialDisjoint}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class SpatialDisjointGeoPointDocValuesAndSourceGridEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encodedPoints; + + private final EvalOperator.ExpressionEvaluator gridIds; + + private final DataType gridType; + + private final DriverContext driverContext; + + private Warnings warnings; + + public SpatialDisjointGeoPointDocValuesAndSourceGridEvaluator(Source source, + EvalOperator.ExpressionEvaluator encodedPoints, EvalOperator.ExpressionEvaluator gridIds, + DataType gridType, DriverContext driverContext) { + this.source = source; + this.encodedPoints = encodedPoints; + this.gridIds = gridIds; + this.gridType = gridType; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedPointsBlock = (LongBlock) encodedPoints.eval(page)) { + try (LongBlock gridIdsBlock = (LongBlock) gridIds.eval(page)) { + return eval(page.getPositionCount(), encodedPointsBlock, gridIdsBlock); + } + } + } + + public BooleanBlock eval(int positionCount, LongBlock encodedPointsBlock, + LongBlock gridIdsBlock) { + try(BooleanBlock.Builder result = driverContext.blockFactory().newBooleanBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedPointsBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (!gridIdsBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + SpatialDisjoint.processGeoPointDocValuesAndSourceGrid(result, p, encodedPointsBlock, gridIdsBlock, this.gridType); + } catch (IllegalArgumentException | IOException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "SpatialDisjointGeoPointDocValuesAndSourceGridEvaluator[" + "encodedPoints=" + encodedPoints + ", gridIds=" + gridIds + ", gridType=" + gridType + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encodedPoints, gridIds); + } + + 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 encodedPoints; + + private final EvalOperator.ExpressionEvaluator.Factory gridIds; + + private final DataType gridType; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encodedPoints, + EvalOperator.ExpressionEvaluator.Factory gridIds, DataType gridType) { + this.source = source; + this.encodedPoints = encodedPoints; + this.gridIds = gridIds; + this.gridType = gridType; + } + + @Override + public SpatialDisjointGeoPointDocValuesAndSourceGridEvaluator get(DriverContext context) { + return new SpatialDisjointGeoPointDocValuesAndSourceGridEvaluator(source, encodedPoints.get(context), gridIds.get(context), gridType, context); + } + + @Override + public String toString() { + return "SpatialDisjointGeoPointDocValuesAndSourceGridEvaluator[" + "encodedPoints=" + encodedPoints + ", gridIds=" + gridIds + ", gridType=" + gridType + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialDisjointGeoSourceAndConstantGridEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialDisjointGeoSourceAndConstantGridEvaluator.java new file mode 100644 index 0000000000000..aa8b09b9e8420 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialDisjointGeoSourceAndConstantGridEvaluator.java @@ -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.io.IOException; +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BooleanBlock; +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; +import org.elasticsearch.xpack.esql.core.type.DataType; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link SpatialDisjoint}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class SpatialDisjointGeoSourceAndConstantGridEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator wkb; + + private final long gridId; + + private final DataType gridType; + + private final DriverContext driverContext; + + private Warnings warnings; + + public SpatialDisjointGeoSourceAndConstantGridEvaluator(Source source, + EvalOperator.ExpressionEvaluator wkb, long gridId, DataType gridType, + DriverContext driverContext) { + this.source = source; + this.wkb = wkb; + this.gridId = gridId; + this.gridType = gridType; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock wkbBlock = (BytesRefBlock) wkb.eval(page)) { + return eval(page.getPositionCount(), wkbBlock); + } + } + + public BooleanBlock eval(int positionCount, BytesRefBlock wkbBlock) { + try(BooleanBlock.Builder result = driverContext.blockFactory().newBooleanBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!wkbBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + SpatialDisjoint.processGeoSourceAndConstantGrid(result, p, wkbBlock, this.gridId, this.gridType); + } catch (IllegalArgumentException | IOException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "SpatialDisjointGeoSourceAndConstantGridEvaluator[" + "wkb=" + wkb + ", gridId=" + gridId + ", gridType=" + gridType + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(wkb); + } + + 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 wkb; + + private final long gridId; + + private final DataType gridType; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory wkb, long gridId, + DataType gridType) { + this.source = source; + this.wkb = wkb; + this.gridId = gridId; + this.gridType = gridType; + } + + @Override + public SpatialDisjointGeoSourceAndConstantGridEvaluator get(DriverContext context) { + return new SpatialDisjointGeoSourceAndConstantGridEvaluator(source, wkb.get(context), gridId, gridType, context); + } + + @Override + public String toString() { + return "SpatialDisjointGeoSourceAndConstantGridEvaluator[" + "wkb=" + wkb + ", gridId=" + gridId + ", gridType=" + gridType + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialDisjointGeoSourceAndSourceGridEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialDisjointGeoSourceAndSourceGridEvaluator.java new file mode 100644 index 0000000000000..556c647edb695 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialDisjointGeoSourceAndSourceGridEvaluator.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.io.IOException; +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BooleanBlock; +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; +import org.elasticsearch.xpack.esql.core.type.DataType; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link SpatialDisjoint}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class SpatialDisjointGeoSourceAndSourceGridEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator wkb; + + private final EvalOperator.ExpressionEvaluator gridId; + + private final DataType gridType; + + private final DriverContext driverContext; + + private Warnings warnings; + + public SpatialDisjointGeoSourceAndSourceGridEvaluator(Source source, + EvalOperator.ExpressionEvaluator wkb, EvalOperator.ExpressionEvaluator gridId, + DataType gridType, DriverContext driverContext) { + this.source = source; + this.wkb = wkb; + this.gridId = gridId; + this.gridType = gridType; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock wkbBlock = (BytesRefBlock) wkb.eval(page)) { + try (LongBlock gridIdBlock = (LongBlock) gridId.eval(page)) { + return eval(page.getPositionCount(), wkbBlock, gridIdBlock); + } + } + } + + public BooleanBlock eval(int positionCount, BytesRefBlock wkbBlock, LongBlock gridIdBlock) { + try(BooleanBlock.Builder result = driverContext.blockFactory().newBooleanBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!wkbBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (!gridIdBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + SpatialDisjoint.processGeoSourceAndSourceGrid(result, p, wkbBlock, gridIdBlock, this.gridType); + } catch (IllegalArgumentException | IOException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "SpatialDisjointGeoSourceAndSourceGridEvaluator[" + "wkb=" + wkb + ", gridId=" + gridId + ", gridType=" + gridType + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(wkb, gridId); + } + + 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 wkb; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + private final DataType gridType; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory wkb, + EvalOperator.ExpressionEvaluator.Factory gridId, DataType gridType) { + this.source = source; + this.wkb = wkb; + this.gridId = gridId; + this.gridType = gridType; + } + + @Override + public SpatialDisjointGeoSourceAndSourceGridEvaluator get(DriverContext context) { + return new SpatialDisjointGeoSourceAndSourceGridEvaluator(source, wkb.get(context), gridId.get(context), gridType, context); + } + + @Override + public String toString() { + return "SpatialDisjointGeoSourceAndSourceGridEvaluator[" + "wkb=" + wkb + ", gridId=" + gridId + ", gridType=" + gridType + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialIntersectsGeoPointDocValuesAndConstantGridEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialIntersectsGeoPointDocValuesAndConstantGridEvaluator.java new file mode 100644 index 0000000000000..e134546b8e35c --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialIntersectsGeoPointDocValuesAndConstantGridEvaluator.java @@ -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.io.IOException; +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BooleanBlock; +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; +import org.elasticsearch.xpack.esql.core.type.DataType; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link SpatialIntersects}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class SpatialIntersectsGeoPointDocValuesAndConstantGridEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encodedPoints; + + private final long gridId; + + private final DataType gridType; + + private final DriverContext driverContext; + + private Warnings warnings; + + public SpatialIntersectsGeoPointDocValuesAndConstantGridEvaluator(Source source, + EvalOperator.ExpressionEvaluator encodedPoints, long gridId, DataType gridType, + DriverContext driverContext) { + this.source = source; + this.encodedPoints = encodedPoints; + this.gridId = gridId; + this.gridType = gridType; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedPointsBlock = (LongBlock) encodedPoints.eval(page)) { + return eval(page.getPositionCount(), encodedPointsBlock); + } + } + + public BooleanBlock eval(int positionCount, LongBlock encodedPointsBlock) { + try(BooleanBlock.Builder result = driverContext.blockFactory().newBooleanBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedPointsBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + SpatialIntersects.processGeoPointDocValuesAndConstantGrid(result, p, encodedPointsBlock, this.gridId, this.gridType); + } catch (IllegalArgumentException | IOException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "SpatialIntersectsGeoPointDocValuesAndConstantGridEvaluator[" + "encodedPoints=" + encodedPoints + ", gridId=" + gridId + ", gridType=" + gridType + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encodedPoints); + } + + 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 encodedPoints; + + private final long gridId; + + private final DataType gridType; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encodedPoints, + long gridId, DataType gridType) { + this.source = source; + this.encodedPoints = encodedPoints; + this.gridId = gridId; + this.gridType = gridType; + } + + @Override + public SpatialIntersectsGeoPointDocValuesAndConstantGridEvaluator get(DriverContext context) { + return new SpatialIntersectsGeoPointDocValuesAndConstantGridEvaluator(source, encodedPoints.get(context), gridId, gridType, context); + } + + @Override + public String toString() { + return "SpatialIntersectsGeoPointDocValuesAndConstantGridEvaluator[" + "encodedPoints=" + encodedPoints + ", gridId=" + gridId + ", gridType=" + gridType + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialIntersectsGeoPointDocValuesAndSourceGridEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialIntersectsGeoPointDocValuesAndSourceGridEvaluator.java new file mode 100644 index 0000000000000..df4058bca87b4 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialIntersectsGeoPointDocValuesAndSourceGridEvaluator.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.io.IOException; +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BooleanBlock; +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; +import org.elasticsearch.xpack.esql.core.type.DataType; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link SpatialIntersects}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class SpatialIntersectsGeoPointDocValuesAndSourceGridEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator encodedPoints; + + private final EvalOperator.ExpressionEvaluator gridIds; + + private final DataType gridType; + + private final DriverContext driverContext; + + private Warnings warnings; + + public SpatialIntersectsGeoPointDocValuesAndSourceGridEvaluator(Source source, + EvalOperator.ExpressionEvaluator encodedPoints, EvalOperator.ExpressionEvaluator gridIds, + DataType gridType, DriverContext driverContext) { + this.source = source; + this.encodedPoints = encodedPoints; + this.gridIds = gridIds; + this.gridType = gridType; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (LongBlock encodedPointsBlock = (LongBlock) encodedPoints.eval(page)) { + try (LongBlock gridIdsBlock = (LongBlock) gridIds.eval(page)) { + return eval(page.getPositionCount(), encodedPointsBlock, gridIdsBlock); + } + } + } + + public BooleanBlock eval(int positionCount, LongBlock encodedPointsBlock, + LongBlock gridIdsBlock) { + try(BooleanBlock.Builder result = driverContext.blockFactory().newBooleanBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!encodedPointsBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (!gridIdsBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + SpatialIntersects.processGeoPointDocValuesAndSourceGrid(result, p, encodedPointsBlock, gridIdsBlock, this.gridType); + } catch (IllegalArgumentException | IOException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "SpatialIntersectsGeoPointDocValuesAndSourceGridEvaluator[" + "encodedPoints=" + encodedPoints + ", gridIds=" + gridIds + ", gridType=" + gridType + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(encodedPoints, gridIds); + } + + 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 encodedPoints; + + private final EvalOperator.ExpressionEvaluator.Factory gridIds; + + private final DataType gridType; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory encodedPoints, + EvalOperator.ExpressionEvaluator.Factory gridIds, DataType gridType) { + this.source = source; + this.encodedPoints = encodedPoints; + this.gridIds = gridIds; + this.gridType = gridType; + } + + @Override + public SpatialIntersectsGeoPointDocValuesAndSourceGridEvaluator get(DriverContext context) { + return new SpatialIntersectsGeoPointDocValuesAndSourceGridEvaluator(source, encodedPoints.get(context), gridIds.get(context), gridType, context); + } + + @Override + public String toString() { + return "SpatialIntersectsGeoPointDocValuesAndSourceGridEvaluator[" + "encodedPoints=" + encodedPoints + ", gridIds=" + gridIds + ", gridType=" + gridType + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialIntersectsGeoSourceAndConstantGridEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialIntersectsGeoSourceAndConstantGridEvaluator.java new file mode 100644 index 0000000000000..23a6fb1cda3be --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialIntersectsGeoSourceAndConstantGridEvaluator.java @@ -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.io.IOException; +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BooleanBlock; +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; +import org.elasticsearch.xpack.esql.core.type.DataType; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link SpatialIntersects}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class SpatialIntersectsGeoSourceAndConstantGridEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator wkb; + + private final long gridId; + + private final DataType gridType; + + private final DriverContext driverContext; + + private Warnings warnings; + + public SpatialIntersectsGeoSourceAndConstantGridEvaluator(Source source, + EvalOperator.ExpressionEvaluator wkb, long gridId, DataType gridType, + DriverContext driverContext) { + this.source = source; + this.wkb = wkb; + this.gridId = gridId; + this.gridType = gridType; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock wkbBlock = (BytesRefBlock) wkb.eval(page)) { + return eval(page.getPositionCount(), wkbBlock); + } + } + + public BooleanBlock eval(int positionCount, BytesRefBlock wkbBlock) { + try(BooleanBlock.Builder result = driverContext.blockFactory().newBooleanBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!wkbBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + SpatialIntersects.processGeoSourceAndConstantGrid(result, p, wkbBlock, this.gridId, this.gridType); + } catch (IllegalArgumentException | IOException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "SpatialIntersectsGeoSourceAndConstantGridEvaluator[" + "wkb=" + wkb + ", gridId=" + gridId + ", gridType=" + gridType + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(wkb); + } + + 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 wkb; + + private final long gridId; + + private final DataType gridType; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory wkb, long gridId, + DataType gridType) { + this.source = source; + this.wkb = wkb; + this.gridId = gridId; + this.gridType = gridType; + } + + @Override + public SpatialIntersectsGeoSourceAndConstantGridEvaluator get(DriverContext context) { + return new SpatialIntersectsGeoSourceAndConstantGridEvaluator(source, wkb.get(context), gridId, gridType, context); + } + + @Override + public String toString() { + return "SpatialIntersectsGeoSourceAndConstantGridEvaluator[" + "wkb=" + wkb + ", gridId=" + gridId + ", gridType=" + gridType + "]"; + } + } +} diff --git a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialIntersectsGeoSourceAndSourceGridEvaluator.java b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialIntersectsGeoSourceAndSourceGridEvaluator.java new file mode 100644 index 0000000000000..8d2c55a82cec6 --- /dev/null +++ b/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialIntersectsGeoSourceAndSourceGridEvaluator.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.io.IOException; +import java.lang.IllegalArgumentException; +import java.lang.Override; +import java.lang.String; +import org.elasticsearch.compute.data.Block; +import org.elasticsearch.compute.data.BooleanBlock; +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; +import org.elasticsearch.xpack.esql.core.type.DataType; + +/** + * {@link EvalOperator.ExpressionEvaluator} implementation for {@link SpatialIntersects}. + * This class is generated. Edit {@code EvaluatorImplementer} instead. + */ +public final class SpatialIntersectsGeoSourceAndSourceGridEvaluator implements EvalOperator.ExpressionEvaluator { + private final Source source; + + private final EvalOperator.ExpressionEvaluator wkb; + + private final EvalOperator.ExpressionEvaluator gridId; + + private final DataType gridType; + + private final DriverContext driverContext; + + private Warnings warnings; + + public SpatialIntersectsGeoSourceAndSourceGridEvaluator(Source source, + EvalOperator.ExpressionEvaluator wkb, EvalOperator.ExpressionEvaluator gridId, + DataType gridType, DriverContext driverContext) { + this.source = source; + this.wkb = wkb; + this.gridId = gridId; + this.gridType = gridType; + this.driverContext = driverContext; + } + + @Override + public Block eval(Page page) { + try (BytesRefBlock wkbBlock = (BytesRefBlock) wkb.eval(page)) { + try (LongBlock gridIdBlock = (LongBlock) gridId.eval(page)) { + return eval(page.getPositionCount(), wkbBlock, gridIdBlock); + } + } + } + + public BooleanBlock eval(int positionCount, BytesRefBlock wkbBlock, LongBlock gridIdBlock) { + try(BooleanBlock.Builder result = driverContext.blockFactory().newBooleanBlockBuilder(positionCount)) { + position: for (int p = 0; p < positionCount; p++) { + boolean allBlocksAreNulls = true; + if (!wkbBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (!gridIdBlock.isNull(p)) { + allBlocksAreNulls = false; + } + if (allBlocksAreNulls) { + result.appendNull(); + continue position; + } + try { + SpatialIntersects.processGeoSourceAndSourceGrid(result, p, wkbBlock, gridIdBlock, this.gridType); + } catch (IllegalArgumentException | IOException e) { + warnings().registerException(e); + result.appendNull(); + } + } + return result.build(); + } + } + + @Override + public String toString() { + return "SpatialIntersectsGeoSourceAndSourceGridEvaluator[" + "wkb=" + wkb + ", gridId=" + gridId + ", gridType=" + gridType + "]"; + } + + @Override + public void close() { + Releasables.closeExpectNoException(wkb, gridId); + } + + 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 wkb; + + private final EvalOperator.ExpressionEvaluator.Factory gridId; + + private final DataType gridType; + + public Factory(Source source, EvalOperator.ExpressionEvaluator.Factory wkb, + EvalOperator.ExpressionEvaluator.Factory gridId, DataType gridType) { + this.source = source; + this.wkb = wkb; + this.gridId = gridId; + this.gridType = gridType; + } + + @Override + public SpatialIntersectsGeoSourceAndSourceGridEvaluator get(DriverContext context) { + return new SpatialIntersectsGeoSourceAndSourceGridEvaluator(source, wkb.get(context), gridId.get(context), gridType, context); + } + + @Override + public String toString() { + return "SpatialIntersectsGeoSourceAndSourceGridEvaluator[" + "wkb=" + wkb + ", gridId=" + gridId + ", gridType=" + gridType + "]"; + } + } +} 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 deleted file mode 100644 index ad5094b0de795..0000000000000 --- a/x-pack/plugin/esql/src/main/generated/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringFromLongEvaluator.java +++ /dev/null @@ -1,134 +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.apache.lucene.util.RamUsageEstimator; -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 static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(StGeohexToStringFromLongEvaluator.class); - - 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); - } - - @Override - public long baseRamBytesUsed() { - long baseRamBytesUsed = BASE_RAM_BYTES_USED; - baseRamBytesUsed += gridId.baseRamBytesUsed(); - return baseRamBytesUsed; - } - - 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/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index f5b86af3c64f8..dc9f6f3b3978d 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 @@ -416,6 +416,11 @@ public enum Cap { */ SPATIAL_GRID(Build.current().isSnapshot()), + /** + * Support geohash, geotile and geohex data types. Done in #129581 + */ + SPATIAL_GRID_TYPES(Build.current().isSnapshot()), + /** * 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/esql/src/main/java/org/elasticsearch/xpack/esql/action/PositionToXContent.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/PositionToXContent.java index 00f297efd0e53..965c9571f7547 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/PositionToXContent.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/PositionToXContent.java @@ -29,6 +29,7 @@ import static org.elasticsearch.xpack.esql.core.util.NumericUtils.unsignedLongAsNumber; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.aggregateMetricDoubleBlockToString; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.dateTimeToString; +import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.geoGridToString; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.ipToString; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.nanoTimeToString; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.spatialToString; @@ -136,6 +137,14 @@ protected XContentBuilder valueToXContent(XContentBuilder builder, ToXContent.Pa return builder.value(spatialToString(((BytesRefBlock) block).getBytesRef(valueIndex, scratch))); } }; + case GEOHASH, GEOTILE, GEOHEX -> new PositionToXContent(block) { + @Override + protected XContentBuilder valueToXContent(XContentBuilder builder, ToXContent.Params params, int valueIndex) + throws IOException { + long longVal = ((LongBlock) block).getLong(valueIndex); + return builder.value(geoGridToString(longVal, columnInfo.type())); + } + }; case BOOLEAN -> new PositionToXContent(block) { @Override protected XContentBuilder valueToXContent(XContentBuilder builder, ToXContent.Params params, int valueIndex) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/ResponseValueUtils.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/ResponseValueUtils.java index 3a406de60ace7..5d0b60c138710 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/ResponseValueUtils.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/ResponseValueUtils.java @@ -34,6 +34,7 @@ import static org.elasticsearch.xpack.esql.core.util.NumericUtils.unsignedLongAsNumber; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.aggregateMetricDoubleBlockToString; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.dateTimeToString; +import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.geoGridToString; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.ipToString; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.nanoTimeToString; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.spatialToString; @@ -135,6 +136,7 @@ private static Object valueAt(DataType dataType, Block block, int offset, BytesR case GEO_POINT, GEO_SHAPE, CARTESIAN_POINT, CARTESIAN_SHAPE -> spatialToString( ((BytesRefBlock) block).getBytesRef(offset, scratch) ); + case GEOHEX, GEOHASH, GEOTILE -> geoGridToString(((LongBlock) block).getLong(offset), dataType); case AGGREGATE_METRIC_DOUBLE -> aggregateMetricDoubleBlockToString((AggregateMetricDoubleBlock) block, offset); case UNSUPPORTED -> (String) null; case SOURCE -> { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Verifier.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Verifier.java index 30fa9e8609b3c..11dcf79248f65 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Verifier.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Verifier.java @@ -313,6 +313,9 @@ public static Failure validateBinaryComparison(BinaryComparison bc) { allowed.add(DataType.GEO_SHAPE); allowed.add(DataType.CARTESIAN_POINT); allowed.add(DataType.CARTESIAN_SHAPE); + allowed.add(DataType.GEOHASH); + allowed.add(DataType.GEOTILE); + allowed.add(DataType.GEOHEX); if (bc instanceof Equals || bc instanceof NotEquals) { allowed.add(DataType.BOOLEAN); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/EsqlTypeResolutions.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/EsqlTypeResolutions.java index 23f875e4a0595..befeedb01cc9c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/EsqlTypeResolutions.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/EsqlTypeResolutions.java @@ -20,6 +20,9 @@ import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isType; import static org.elasticsearch.xpack.esql.core.type.DataType.CARTESIAN_POINT; import static org.elasticsearch.xpack.esql.core.type.DataType.CARTESIAN_SHAPE; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT; import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_SHAPE; @@ -62,6 +65,14 @@ public static Expression.TypeResolution isExact(Expression e, String operationNa CARTESIAN_POINT.typeName(), GEO_SHAPE.typeName(), CARTESIAN_SHAPE.typeName() }; + private static final String[] SPATIAL_AND_GRID_TYPE_NAMES = new String[] { + GEO_POINT.typeName(), + CARTESIAN_POINT.typeName(), + GEO_SHAPE.typeName(), + CARTESIAN_SHAPE.typeName(), + GEOHASH.typeName(), + GEOTILE.typeName(), + GEOHEX.typeName() }; private static final String[] POINT_TYPE_NAMES = new String[] { GEO_POINT.typeName(), CARTESIAN_POINT.typeName() }; public static Expression.TypeResolution isSpatialPoint(Expression e, String operationName, TypeResolutions.ParamOrdinal paramOrd) { @@ -71,4 +82,8 @@ public static Expression.TypeResolution isSpatialPoint(Expression e, String oper public static Expression.TypeResolution isSpatial(Expression e, String operationName, TypeResolutions.ParamOrdinal paramOrd) { return isType(e, DataType::isSpatial, operationName, paramOrd, SPATIAL_TYPE_NAMES); } + + public static Expression.TypeResolution isSpatialOrGrid(Expression e, String operationName, TypeResolutions.ParamOrdinal paramOrd) { + return isType(e, DataType::isSpatialOrGrid, operationName, paramOrd, SPATIAL_AND_GRID_TYPE_NAMES); + } } 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 25d131b23f623..8866337e8f15c 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 @@ -25,6 +25,9 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDouble; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeoPoint; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeoShape; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeohash; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeohex; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeotile; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToInteger; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToIpLeadingZerosDecimal; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToIpLeadingZerosOctal; @@ -61,14 +64,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.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.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.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; @@ -211,6 +208,9 @@ public static List unaryScalars() { entries.add(ToGeoShape.ENTRY); entries.add(ToCartesianShape.ENTRY); entries.add(ToGeoPoint.ENTRY); + entries.add(ToGeohash.ENTRY); + entries.add(ToGeotile.ENTRY); + entries.add(ToGeohex.ENTRY); entries.add(ToIpLeadingZerosDecimal.ENTRY); entries.add(ToIpLeadingZerosOctal.ENTRY); entries.add(ToIpLeadingZerosRejected.ENTRY); @@ -238,14 +238,8 @@ private static List spatials() { SpatialWithin.ENTRY, StDistance.ENTRY, StGeohash.ENTRY, - StGeohashToString.ENTRY, - StGeohashToLong.ENTRY, StGeotile.ENTRY, - StGeotileToString.ENTRY, - StGeotileToLong.ENTRY, - StGeohex.ENTRY, - StGeohexToString.ENTRY, - StGeohexToLong.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 bb98f4b2fbb20..0df4b4c035918 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 @@ -72,6 +72,9 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDouble; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeoPoint; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeoShape; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeohash; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeohex; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeotile; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToInteger; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToIp; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToIpLeadingZerosDecimal; @@ -148,14 +151,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.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.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.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; @@ -217,6 +214,9 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME; import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_PERIOD; import static org.elasticsearch.xpack.esql.core.type.DataType.DOUBLE; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; 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; @@ -246,6 +246,9 @@ public class EsqlFunctionRegistry { GEO_SHAPE, CARTESIAN_POINT, CARTESIAN_SHAPE, + GEOHASH, + GEOHEX, + GEOTILE, BOOLEAN, UNSIGNED_LONG, UNSUPPORTED @@ -502,15 +505,12 @@ private static FunctionDefinition[][] snapshotFunctions() { def(Score.class, uni(Score::new), Score.NAME), def(Term.class, bi(Term::new), "term"), def(Knn.class, quad(Knn::new), "knn"), + def(ToGeohash.class, ToGeohash::new, "to_geohash"), + def(ToGeotile.class, ToGeotile::new, "to_geotile"), + def(ToGeohex.class, ToGeohex::new, "to_geohex"), def(StGeohash.class, StGeohash::new, "st_geohash"), - 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(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(StGeohexToLong.class, StGeohexToLong::new, "st_geohex_to_long"), - def(StGeohexToString.class, StGeohexToString::new, "st_geohex_to_string"), def(CosineSimilarity.class, CosineSimilarity::new, "v_cosine"), def(DotProduct.class, DotProduct::new, "v_dot_product"), def(L1Norm.class, L1Norm::new, "v_l1_norm"), diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Count.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Count.java index 9c6e4145759ca..cbf281f1bc86b 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Count.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Count.java @@ -83,6 +83,9 @@ public Count( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountOverTime.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountOverTime.java index 6da92bc2ec3b5..8bd46d6d52d10 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountOverTime.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountOverTime.java @@ -58,6 +58,9 @@ public CountOverTime( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java index 50cb44b186045..1ed7e439a9f06 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Sample.java @@ -59,6 +59,9 @@ public class Sample extends AggregateFunction implements ToAggregator, PostOptim "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -84,6 +87,9 @@ public Sample( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Values.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Values.java index cbf82bb005974..863a9d2d2d58d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Values.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Values.java @@ -56,6 +56,9 @@ public class Values extends AggregateFunction implements ToAggregator { Map.entry(DataType.CARTESIAN_POINT, ValuesBytesRefAggregatorFunctionSupplier::new), Map.entry(DataType.GEO_SHAPE, ValuesBytesRefAggregatorFunctionSupplier::new), Map.entry(DataType.CARTESIAN_SHAPE, ValuesBytesRefAggregatorFunctionSupplier::new), + Map.entry(DataType.GEOHASH, ValuesLongAggregatorFunctionSupplier::new), + Map.entry(DataType.GEOTILE, ValuesLongAggregatorFunctionSupplier::new), + Map.entry(DataType.GEOHEX, ValuesLongAggregatorFunctionSupplier::new), Map.entry(DataType.BOOLEAN, ValuesBooleanAggregatorFunctionSupplier::new) ); @@ -69,6 +72,9 @@ public class Values extends AggregateFunction implements ToAggregator { "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -109,6 +115,9 @@ public Values( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/Case.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/Case.java index 64c176abd9c2c..3f5cfea2e7443 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/Case.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/Case.java @@ -71,6 +71,9 @@ ConditionEvaluatorSupplier toEvaluator(ToEvaluator toEvaluator) { "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -111,6 +114,9 @@ public Case( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShape.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShape.java index f3a7ef8ca1481..b8852804e0242 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShape.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShape.java @@ -11,6 +11,7 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.compute.ann.Fixed; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; import org.elasticsearch.xpack.esql.core.tree.Source; @@ -23,10 +24,14 @@ import java.util.List; import java.util.Map; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; 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.type.DataType.TEXT; +import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.geoGridToShape; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToGeo; public class ToGeoShape extends AbstractConvertFunction { @@ -39,6 +44,9 @@ public class ToGeoShape extends AbstractConvertFunction { private static final Map EVALUATORS = Map.ofEntries( Map.entry(GEO_POINT, (source, fieldEval) -> fieldEval), Map.entry(GEO_SHAPE, (source, fieldEval) -> fieldEval), + Map.entry(GEOHASH, (source, fieldEval) -> new ToGeoShapeFromGeoGridEvaluator.Factory(source, fieldEval, GEOHASH)), + Map.entry(GEOTILE, (source, fieldEval) -> new ToGeoShapeFromGeoGridEvaluator.Factory(source, fieldEval, GEOTILE)), + Map.entry(GEOHEX, (source, fieldEval) -> new ToGeoShapeFromGeoGridEvaluator.Factory(source, fieldEval, GEOHEX)), Map.entry(KEYWORD, ToGeoShapeFromStringEvaluator.Factory::new), Map.entry(TEXT, ToGeoShapeFromStringEvaluator.Factory::new) ); @@ -55,7 +63,7 @@ public ToGeoShape( Source source, @Param( name = "field", - type = { "geo_point", "geo_shape", "keyword", "text" }, + type = { "geo_point", "geo_shape", "geohash", "geohex", "geotile", "keyword", "text" }, description = "Input value. The input can be a single- or multi-valued column or an expression." ) Expression field ) { @@ -95,4 +103,9 @@ protected NodeInfo extends Expression> info() { static BytesRef fromKeyword(BytesRef in) { return stringToGeo(in.utf8ToString()); } + + @ConvertEvaluator(extraName = "FromGeoGrid", warnExceptions = { IllegalArgumentException.class }) + static BytesRef fromGeoGrid(long in, @Fixed DataType dataType) { + return geoGridToShape(in, dataType); + } } 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/convert/ToGeohash.java similarity index 61% rename from x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLong.java rename to x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohash.java index 5b2a4fdb2175c..0ea490098ca6f 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/convert/ToGeohash.java @@ -5,7 +5,7 @@ * 2.0. */ -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; @@ -16,53 +16,57 @@ 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.FunctionAppliesTo; import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle; 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.GEOHASH; 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.type.DataType.TEXT; -public class StGeohashToLong extends AbstractConvertFunction implements EvaluatorMapper { +public class ToGeohash extends AbstractConvertFunction { public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( Expression.class, - "StGeohashToLong", - StGeohashToLong::new + "ToGeohash", + ToGeohash::new ); private static final Map EVALUATORS = Map.ofEntries( + Map.entry(GEOHASH, (source, fieldEval) -> fieldEval), Map.entry(LONG, (source, fieldEval) -> fieldEval), - Map.entry(KEYWORD, StGeohashToLongFromStringEvaluator.Factory::new) + Map.entry(KEYWORD, ToGeohashFromStringEvaluator.Factory::new), + Map.entry(TEXT, ToGeohashFromStringEvaluator.Factory::new) ); @FunctionInfo( - returnType = "long", + returnType = "geohash", preview = true, appliesTo = { @FunctionAppliesTo(lifeCycle = FunctionAppliesToLifecycle.PREVIEW) }, - 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") }, - depthOffset = 1 // make it appear as a subsection of ST_GEOHASH + description = """ + Converts an input value to a `geohash` value. + A string will only be successfully converted if it respects the + `geohash` format.""", + examples = @Example(file = "spatial-grid", tag = "to_geohash") ) - public StGeohashToLong( + public ToGeohash( 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 + name = "field", + type = { "geohash", "long", "keyword", "text" }, + description = "Input value. The input can be a single- or multi-valued column or an expression." + ) Expression field ) { - super(source, v); + super(source, field); } - private StGeohashToLong(StreamInput in) throws IOException { + private ToGeohash(StreamInput in) throws IOException { super(in); } @@ -78,21 +82,21 @@ protected Map factories() { @Override public DataType dataType() { - return LONG; + return GEOHASH; } @Override public Expression replaceChildren(List newChildren) { - return new StGeohashToLong(source(), newChildren.get(0)); + return new ToGeohash(source(), newChildren.get(0)); } @Override protected NodeInfo extends Expression> info() { - return NodeInfo.create(this, StGeohashToLong::new, field()); + return NodeInfo.create(this, ToGeohash::new, field()); } - @ConvertEvaluator(extraName = "FromString") - static long fromString(BytesRef gridId) { - return Geohash.longEncode(gridId.utf8ToString()); + @ConvertEvaluator(extraName = "FromString", warnExceptions = { IllegalArgumentException.class }) + static long fromString(BytesRef in) { + return Geohash.longEncode(in.utf8ToString()); } } 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/convert/ToGeohex.java similarity index 60% rename from x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLong.java rename to x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohex.java index 4be2f51659a90..4ccda5cea66f8 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/convert/ToGeohex.java @@ -5,7 +5,7 @@ * 2.0. */ -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; @@ -16,53 +16,53 @@ 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.FunctionAppliesTo; import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle; 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.GEOHEX; 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.type.DataType.TEXT; -public class StGeohexToLong extends AbstractConvertFunction implements EvaluatorMapper { - public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( - Expression.class, - "StGeohexToLong", - StGeohexToLong::new - ); +public class ToGeohex extends AbstractConvertFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "ToGeohex", ToGeohex::new); private static final Map EVALUATORS = Map.ofEntries( + Map.entry(GEOHEX, (source, fieldEval) -> fieldEval), Map.entry(LONG, (source, fieldEval) -> fieldEval), - Map.entry(KEYWORD, StGeohexToLongFromStringEvaluator.Factory::new) + Map.entry(KEYWORD, ToGeohexFromStringEvaluator.Factory::new), + Map.entry(TEXT, ToGeohexFromStringEvaluator.Factory::new) ); @FunctionInfo( - returnType = "long", + returnType = "geohex", preview = true, appliesTo = { @FunctionAppliesTo(lifeCycle = FunctionAppliesToLifecycle.PREVIEW) }, - 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") }, - depthOffset = 1 // make it appear as a subsection of ST_GEOHEX + description = """ + Converts an input value to a `geohex` value. + A string will only be successfully converted if it respects the + `geohex` format.""", + examples = @Example(file = "spatial-grid", tag = "to_geohex") ) - public StGeohexToLong( + public ToGeohex( 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 + name = "field", + type = { "geohex", "long", "keyword", "text" }, + description = "Input value. The input can be a single- or multi-valued column or an expression." + ) Expression field ) { - super(source, v); + super(source, field); } - private StGeohexToLong(StreamInput in) throws IOException { + private ToGeohex(StreamInput in) throws IOException { super(in); } @@ -78,21 +78,21 @@ protected Map factories() { @Override public DataType dataType() { - return LONG; + return GEOHEX; } @Override public Expression replaceChildren(List newChildren) { - return new StGeohexToLong(source(), newChildren.get(0)); + return new ToGeohex(source(), newChildren.get(0)); } @Override protected NodeInfo extends Expression> info() { - return NodeInfo.create(this, StGeohexToLong::new, field()); + return NodeInfo.create(this, ToGeohex::new, field()); } - @ConvertEvaluator(extraName = "FromString") - static long fromString(BytesRef gridId) { - return H3.stringToH3(gridId.utf8ToString()); + @ConvertEvaluator(extraName = "FromString", warnExceptions = { IllegalArgumentException.class }) + static long fromString(BytesRef in) { + return H3.stringToH3(in.utf8ToString()); } } 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/convert/ToGeotile.java similarity index 61% rename from x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLong.java rename to x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotile.java index 64950c77e56aa..ea2c3075a9303 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/convert/ToGeotile.java @@ -5,7 +5,7 @@ * 2.0. */ -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; @@ -16,53 +16,57 @@ 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.FunctionAppliesTo; import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle; 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.GEOTILE; 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.type.DataType.TEXT; -public class StGeotileToLong extends AbstractConvertFunction implements EvaluatorMapper { +public class ToGeotile extends AbstractConvertFunction { public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( Expression.class, - "StGeotileToLong", - StGeotileToLong::new + "ToGeotile", + ToGeotile::new ); private static final Map EVALUATORS = Map.ofEntries( + Map.entry(GEOTILE, (source, fieldEval) -> fieldEval), Map.entry(LONG, (source, fieldEval) -> fieldEval), - Map.entry(KEYWORD, StGeotileToLongFromStringEvaluator.Factory::new) + Map.entry(KEYWORD, ToGeotileFromStringEvaluator.Factory::new), + Map.entry(TEXT, ToGeotileFromStringEvaluator.Factory::new) ); @FunctionInfo( - returnType = "long", + returnType = "geotile", preview = true, appliesTo = { @FunctionAppliesTo(lifeCycle = FunctionAppliesToLifecycle.PREVIEW) }, - 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") }, - depthOffset = 1 // make it appear as a subsection of ST_GEOTILE + description = """ + Converts an input value to a `geotile` value. + A string will only be successfully converted if it respects the + `geotile` format.""", + examples = @Example(file = "spatial-grid", tag = "to_geotile") ) - public StGeotileToLong( + public ToGeotile( 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 + name = "field", + type = { "geotile", "long", "keyword", "text" }, + description = "Input value. The input can be a single- or multi-valued column or an expression." + ) Expression field ) { - super(source, v); + super(source, field); } - private StGeotileToLong(StreamInput in) throws IOException { + private ToGeotile(StreamInput in) throws IOException { super(in); } @@ -78,21 +82,21 @@ protected Map factories() { @Override public DataType dataType() { - return LONG; + return GEOTILE; } @Override public Expression replaceChildren(List newChildren) { - return new StGeotileToLong(source(), newChildren.get(0)); + return new ToGeotile(source(), newChildren.get(0)); } @Override protected NodeInfo extends Expression> info() { - return NodeInfo.create(this, StGeotileToLong::new, field()); + return NodeInfo.create(this, ToGeotile::new, field()); } - @ConvertEvaluator(extraName = "FromString") - static long fromString(BytesRef gridId) { - return GeoTileUtils.longEncode(gridId.utf8ToString()); + @ConvertEvaluator(extraName = "FromString", warnExceptions = { IllegalArgumentException.class }) + static long fromString(BytesRef in) { + return GeoTileUtils.longEncode(in.utf8ToString()); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLong.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLong.java index 51bb3936060c1..6983437e8ac5a 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLong.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLong.java @@ -28,6 +28,9 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME; import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_NANOS; import static org.elasticsearch.xpack.esql.core.type.DataType.DOUBLE; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; import static org.elasticsearch.xpack.esql.core.type.DataType.INTEGER; import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; @@ -51,7 +54,10 @@ public class ToLong extends AbstractConvertFunction { Map.entry(UNSIGNED_LONG, ToLongFromUnsignedLongEvaluator.Factory::new), Map.entry(INTEGER, ToLongFromIntEvaluator.Factory::new), // CastIntToLongEvaluator would be a candidate, but not MV'd Map.entry(DataType.COUNTER_LONG, (source, field) -> field), - Map.entry(DataType.COUNTER_INTEGER, ToLongFromIntEvaluator.Factory::new) + Map.entry(DataType.COUNTER_INTEGER, ToLongFromIntEvaluator.Factory::new), + Map.entry(GEOHASH, (source, fieldEval) -> fieldEval), + Map.entry(GEOTILE, (source, fieldEval) -> fieldEval), + Map.entry(GEOHEX, (source, fieldEval) -> fieldEval) ); @FunctionInfo( @@ -86,7 +92,10 @@ public ToLong( "unsigned_long", "integer", "counter_integer", - "counter_long" }, + "counter_long", + "geohash", + "geotile", + "geohex" }, description = "Input value. The input can be a single- or multi-valued column or an expression." ) Expression field ) { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToString.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToString.java index e3221f374375e..9cf14aea6b643 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToString.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToString.java @@ -11,6 +11,7 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.compute.ann.ConvertEvaluator; +import org.elasticsearch.compute.ann.Fixed; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.NodeInfo; import org.elasticsearch.xpack.esql.core.tree.Source; @@ -31,6 +32,9 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME; import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_NANOS; import static org.elasticsearch.xpack.esql.core.type.DataType.DOUBLE; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; 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; @@ -41,6 +45,7 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG; import static org.elasticsearch.xpack.esql.core.type.DataType.VERSION; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.dateTimeToString; +import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.geoGridToString; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.ipToString; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.nanoTimeToString; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.numericBooleanToString; @@ -67,6 +72,9 @@ public class ToString extends AbstractConvertFunction implements EvaluatorMapper Map.entry(CARTESIAN_POINT, ToStringFromCartesianPointEvaluator.Factory::new), Map.entry(CARTESIAN_SHAPE, ToStringFromCartesianShapeEvaluator.Factory::new), Map.entry(GEO_SHAPE, ToStringFromGeoShapeEvaluator.Factory::new), + Map.entry(GEOHASH, (source, fieldEval) -> new ToStringFromGeoGridEvaluator.Factory(source, fieldEval, GEOHASH)), + Map.entry(GEOTILE, (source, fieldEval) -> new ToStringFromGeoGridEvaluator.Factory(source, fieldEval, GEOTILE)), + Map.entry(GEOHEX, (source, fieldEval) -> new ToStringFromGeoGridEvaluator.Factory(source, fieldEval, GEOHEX)), Map.entry(AGGREGATE_METRIC_DOUBLE, ToStringFromAggregateMetricDoubleEvaluator.Factory::new) ); @@ -91,6 +99,9 @@ public ToString( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -197,4 +208,9 @@ static BytesRef fromCartesianShape(BytesRef wkb) { static BytesRef fromGeoShape(BytesRef wkb) { return new BytesRef(spatialToString(wkb)); } + + @ConvertEvaluator(extraName = "FromGeoGrid") + static BytesRef fromGeoGrid(long gridId, @Fixed DataType dataType) { + return new BytesRef(geoGridToString(gridId, dataType)); + } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppend.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppend.java index d2043c6530503..10966f99fb902 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppend.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppend.java @@ -61,6 +61,9 @@ public class MvAppend extends EsqlScalarFunction implements EvaluatorMapper { "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -83,6 +86,9 @@ public MvAppend( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -102,6 +108,9 @@ public MvAppend( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContains.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContains.java index dfdec763e330a..052dac0d68b1c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContains.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContains.java @@ -93,6 +93,9 @@ public MvContains( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -113,6 +116,9 @@ public MvContains( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCount.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCount.java index afb3075d1921c..aa6049207fa05 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCount.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCount.java @@ -52,6 +52,9 @@ public MvCount( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupe.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupe.java index 228395a60aad0..c7b7ea0523a45 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupe.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupe.java @@ -42,6 +42,9 @@ public class MvDedupe extends AbstractMultivalueFunction { "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -65,6 +68,9 @@ public MvDedupe( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirst.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirst.java index 2325c3c10b47f..7afcf0a1641cc 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirst.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirst.java @@ -49,6 +49,9 @@ public class MvFirst extends AbstractMultivalueFunction { "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -80,6 +83,9 @@ public MvFirst( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLast.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLast.java index 610f76eb6f65b..bbcc6367784d4 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLast.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLast.java @@ -49,6 +49,9 @@ public class MvLast extends AbstractMultivalueFunction { "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -80,6 +83,9 @@ public MvLast( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSlice.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSlice.java index 8e33d759ea9e8..cdefb4db19d76 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSlice.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSlice.java @@ -63,6 +63,9 @@ public class MvSlice extends EsqlScalarFunction implements OptionalArgument, Eva "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -92,6 +95,9 @@ public MvSlice( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/nulls/Coalesce.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/nulls/Coalesce.java index c8005506be627..642eb27f7fb63 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/nulls/Coalesce.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/nulls/Coalesce.java @@ -31,20 +31,7 @@ import java.util.List; import java.util.stream.Stream; -import static org.elasticsearch.xpack.esql.core.type.DataType.BOOLEAN; -import static org.elasticsearch.xpack.esql.core.type.DataType.CARTESIAN_POINT; -import static org.elasticsearch.xpack.esql.core.type.DataType.CARTESIAN_SHAPE; -import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME; -import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_NANOS; -import static org.elasticsearch.xpack.esql.core.type.DataType.DOUBLE; -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.type.DataType.IP; -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.type.DataType.NULL; -import static org.elasticsearch.xpack.esql.core.type.DataType.VERSION; /** * Function returning the first non-null value. {@code COALESCE} runs as though @@ -64,6 +51,9 @@ public class Coalesce extends EsqlScalarFunction implements OptionalArgument { "date", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -84,6 +74,9 @@ public Coalesce( "date", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -102,6 +95,9 @@ public Coalesce( "date", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", @@ -205,7 +201,10 @@ public ExpressionEvaluator.Factory toEvaluator(ToEvaluator toEvaluator) { case BOOLEAN -> CoalesceBooleanEvaluator.toEvaluator(toEvaluator, children()); case DOUBLE, COUNTER_DOUBLE -> CoalesceDoubleEvaluator.toEvaluator(toEvaluator, children()); case INTEGER, COUNTER_INTEGER -> CoalesceIntEvaluator.toEvaluator(toEvaluator, children()); - case LONG, DATE_NANOS, DATETIME, COUNTER_LONG, UNSIGNED_LONG -> CoalesceLongEvaluator.toEvaluator(toEvaluator, children()); + case LONG, DATE_NANOS, DATETIME, COUNTER_LONG, UNSIGNED_LONG, GEOHASH, GEOTILE, GEOHEX -> CoalesceLongEvaluator.toEvaluator( + toEvaluator, + children() + ); case KEYWORD, TEXT, CARTESIAN_POINT, CARTESIAN_SHAPE, GEO_POINT, GEO_SHAPE, IP, VERSION -> CoalesceBytesRefEvaluator .toEvaluator(toEvaluator, children()); case NULL -> EvalOperator.CONSTANT_NULL_FACTORY; 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 c152108c67649..594327f083423 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 @@ -35,8 +35,9 @@ import java.io.IOException; import static org.elasticsearch.compute.ann.Fixed.Scope.THREAD_LOCAL; -import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; +import static org.elasticsearch.xpack.esql.expression.function.scalar.spatial.StGeotile.fromRectangle; /** * Calculates the geohash of geo_point geometries. @@ -111,12 +112,14 @@ private static int checkPrecisionRange(int precision) { } @FunctionInfo( - returnType = "long", + returnType = "geohash", preview = true, appliesTo = { @FunctionAppliesTo(lifeCycle = FunctionAppliesToLifecycle.PREVIEW) }, 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. + The result is long encoded. Use [TO_STRING](#esql-to_string) to convert the result to a string, + [TO_LONG](#esql-to_long) to convert it to a `long`, or [TO_GEOSHAPE](esql-to_geoshape.md) to calculate + the `geo_shape` bounding geometry. 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).""", @@ -131,7 +134,7 @@ public StGeohash( ) Expression field, @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, + Valid values are between [1 and 12](https://en.wikipedia.org/wiki/Geohash).""", optional = true) Expression precision, @Param(name = "bounds", type = { "geo_shape" }, description = """ Optional bounds to filter the grid tiles, a `geo_shape` of type `BBOX`. Use [`ST_ENVELOPE`](#esql-st_envelope) if the `geo_shape` is of any other type.""", optional = true) Expression bounds @@ -161,7 +164,7 @@ public String getWriteableName() { @Override public DataType dataType() { - return LONG; + return GEOHASH; } @Override @@ -244,4 +247,8 @@ static void fromFieldDocValuesAndLiteralAndLiteral( ) { fromEncodedLong(results, p, encoded, bounds); } + + public static BytesRef toBounds(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/StGeohashToString.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToString.java deleted file mode 100644 index fa3362b28b1df..0000000000000 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToString.java +++ /dev/null @@ -1,98 +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.FunctionAppliesTo; -import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle; -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", - preview = true, - appliesTo = { @FunctionAppliesTo(lifeCycle = FunctionAppliesToLifecycle.PREVIEW) }, - 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") }, - depthOffset = 1 // make it appear as a subsection of ST_GEOHASH - ) - 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 extends Expression> 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/StGeohex.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohex.java index 936b22ba03ccf..b595d92007ef1 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 @@ -17,8 +17,12 @@ import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.geometry.LinearRing; import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.Polygon; +import org.elasticsearch.h3.CellBoundary; import org.elasticsearch.h3.H3; +import org.elasticsearch.h3.LatLng; import org.elasticsearch.license.License; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -26,6 +30,7 @@ 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.FunctionAppliesTo; @@ -36,7 +41,7 @@ import java.io.IOException; import static org.elasticsearch.compute.ann.Fixed.Scope.THREAD_LOCAL; -import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; /** @@ -99,7 +104,7 @@ public GeoHexBoundedGrid get(DriverContext context) { ); private static int checkPrecisionRange(int precision) { - if (precision < 1 || precision > H3.MAX_H3_RES) { + if (precision < 0 || precision > H3.MAX_H3_RES) { throw new IllegalArgumentException( "Invalid geohex_grid precision of " + precision + ". Must be between 0 and " + H3.MAX_H3_RES + "." ); @@ -108,12 +113,14 @@ private static int checkPrecisionRange(int precision) { } @FunctionInfo( - returnType = "long", + returnType = "geohex", preview = true, appliesTo = { @FunctionAppliesTo(lifeCycle = FunctionAppliesToLifecycle.PREVIEW) }, 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. + The result is long encoded. Use [TO_STRING](#esql-to_string) to convert the result to a string, + [TO_LONG](#esql-to_long) to convert it to a `long`, or [TO_GEOSHAPE](esql-to_geoshape.md) to calculate + the `geo_shape` bounding geometry. 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).""", @@ -163,7 +170,7 @@ public String getWriteableName() { @Override public DataType dataType() { - return LONG; + return GEOHEX; } @Override @@ -246,4 +253,23 @@ static void fromFieldDocValuesAndLiteralAndLiteral( ) { fromEncodedLong(results, p, encoded, bounds); } + + public static BytesRef toBounds(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/StGeohexToString.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java deleted file mode 100644 index d82dc3f61dbf2..0000000000000 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToString.java +++ /dev/null @@ -1,98 +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.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.FunctionAppliesTo; -import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle; -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", - preview = true, - appliesTo = { @FunctionAppliesTo(lifeCycle = FunctionAppliesToLifecycle.PREVIEW) }, - 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") }, - depthOffset = 1 // make it appear as a subsection of ST_GEOHEX - ) - 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 extends Expression> 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/StGeotile.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotile.java index 86a9e2bbc6030..b86d121c0c961 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 @@ -17,7 +17,10 @@ import org.elasticsearch.compute.data.LongBlock; import org.elasticsearch.compute.operator.DriverContext; import org.elasticsearch.compute.operator.EvalOperator; +import org.elasticsearch.geometry.LinearRing; import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.Polygon; +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; @@ -25,6 +28,7 @@ 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.FunctionAppliesTo; @@ -36,7 +40,7 @@ import static org.elasticsearch.compute.ann.Fixed.Scope.THREAD_LOCAL; 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.type.DataType.GEOTILE; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; /** @@ -105,12 +109,14 @@ public GeoTileBoundedGrid get(DriverContext context) { ); @FunctionInfo( - returnType = "long", + returnType = "geotile", preview = true, appliesTo = { @FunctionAppliesTo(lifeCycle = FunctionAppliesToLifecycle.PREVIEW) }, 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. + The result is long encoded. Use [TO_STRING](#esql-to_string) to convert the result to a string, + [TO_LONG](#esql-to_long) to convert it to a `long`, or [TO_GEOSHAPE](esql-to_geoshape.md) to calculate + the `geo_shape` bounding geometry. 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).""", @@ -155,7 +161,7 @@ public String getWriteableName() { @Override public DataType dataType() { - return LONG; + return GEOTILE; } @Override @@ -238,4 +244,16 @@ static void fromFieldDocValuesAndLiteralAndLiteral( ) { fromEncodedLong(results, p, encoded, bounds); } + + public static BytesRef toBounds(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/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 deleted file mode 100644 index 115ebbe270a3a..0000000000000 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToString.java +++ /dev/null @@ -1,98 +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.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.FunctionAppliesTo; -import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle; -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", - preview = true, - appliesTo = { @FunctionAppliesTo(lifeCycle = FunctionAppliesToLifecycle.PREVIEW) }, - 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") }, - depthOffset = 1 // make it appear as a subsection of ST_GEOTILE - ) - 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 extends Expression> info() { - return NodeInfo.create(this, StGeotileToString::new, field()); - } - - @ConvertEvaluator(extraName = "FromLong") - static BytesRef fromLong(long gridId) { - return new BytesRef(GeoTileUtils.stringEncode(gridId)); - } -} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/Equals.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/Equals.java index 01f57342da1f0..63cda52368eb8 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/Equals.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/Equals.java @@ -48,6 +48,9 @@ public class Equals extends EsqlBinaryComparison implements Negatable TopNEncoder.DEFAULT_SORTABLE; case GEO_POINT, CARTESIAN_POINT, GEO_SHAPE, CARTESIAN_SHAPE, COUNTER_LONG, COUNTER_INTEGER, COUNTER_DOUBLE, SOURCE, - AGGREGATE_METRIC_DOUBLE, DENSE_VECTOR -> TopNEncoder.DEFAULT_UNSORTABLE; + AGGREGATE_METRIC_DOUBLE, DENSE_VECTOR, GEOHASH, GEOTILE, GEOHEX -> TopNEncoder.DEFAULT_UNSORTABLE; // unsupported fields are encoded as BytesRef, we'll use the same encoder; all values should be null at this point case PARTIAL_AGG, UNSUPPORTED -> TopNEncoder.UNSUPPORTED; }; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java index f956bdf34089f..6c7162ada2e7f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/PlannerUtils.java @@ -305,7 +305,7 @@ && translatable(exp, ctx).finish() == TranslationAware.FinishedTranslatable.YES) * This specifically excludes spatial data types, which are not themselves sortable. */ public static ElementType toSortableElementType(DataType dataType) { - if (DataType.isSpatial(dataType)) { + if (DataType.isSpatialOrGrid(dataType)) { return ElementType.UNKNOWN; } return toElementType(dataType); @@ -326,7 +326,7 @@ public static ElementType toElementType(DataType dataType) { public static ElementType toElementType(DataType dataType, MappedFieldType.FieldExtractPreference fieldExtractPreference) { return switch (dataType) { - case LONG, DATETIME, DATE_NANOS, UNSIGNED_LONG, COUNTER_LONG -> ElementType.LONG; + case LONG, DATETIME, DATE_NANOS, UNSIGNED_LONG, COUNTER_LONG, GEOHASH, GEOTILE, GEOHEX -> ElementType.LONG; case INTEGER, COUNTER_INTEGER -> ElementType.INT; case DOUBLE, COUNTER_DOUBLE -> ElementType.DOUBLE; // unsupported fields are passed through as a BytesRef diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/telemetry/PlanTelemetry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/telemetry/PlanTelemetry.java index 10b48c243d3b1..aa6b8d4873832 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/telemetry/PlanTelemetry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/telemetry/PlanTelemetry.java @@ -46,7 +46,7 @@ public void function(String name) { } public void function(Class extends Function> clazz) { - add(functions, functionRegistry.functionName(clazz)); + add(functions, functionRegistry.snapshotRegistry().functionName(clazz)); } public Map commands() { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/type/EsqlDataTypeConverter.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/type/EsqlDataTypeConverter.java index fe9e7d77c9078..e3a6b08cac1fd 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/type/EsqlDataTypeConverter.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/type/EsqlDataTypeConverter.java @@ -22,7 +22,10 @@ import org.elasticsearch.compute.data.DoubleBlock; import org.elasticsearch.compute.data.IntBlock; import org.elasticsearch.core.Booleans; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.h3.H3; import org.elasticsearch.search.DocValueFormat; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; import org.elasticsearch.xcontent.XContentBuilder; import org.elasticsearch.xcontent.json.JsonXContent; import org.elasticsearch.xpack.esql.core.InvalidArgumentException; @@ -47,6 +50,9 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDouble; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeoPoint; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeoShape; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeohash; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeohex; +import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToGeotile; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToInteger; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToIpLeadingZerosRejected; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToLong; @@ -54,6 +60,9 @@ import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToTimeDuration; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToUnsignedLong; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToVersion; +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.parser.ParsingException; import org.elasticsearch.xpack.versionfield.Version; @@ -80,6 +89,9 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_NANOS; import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_PERIOD; import static org.elasticsearch.xpack.esql.core.type.DataType.DOUBLE; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; 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; @@ -126,6 +138,9 @@ public class EsqlDataTypeConverter { entry(DOUBLE, ToDouble::new), entry(GEO_POINT, ToGeoPoint::new), entry(GEO_SHAPE, ToGeoShape::new), + entry(GEOHASH, ToGeohash::new), + entry(GEOTILE, ToGeotile::new), + entry(GEOHEX, ToGeohex::new), entry(INTEGER, ToInteger::new), entry(IP, ToIpLeadingZerosRejected::new), entry(LONG, ToLong::new), @@ -242,6 +257,15 @@ public static Converter converterFor(DataType from, DataType to) { if (DataType.isSpatial(to)) { return EsqlConverter.STRING_TO_SPATIAL; } + if (to == DataType.GEOHASH) { + return EsqlConverter.STRING_TO_GEOHASH; + } + if (to == DataType.GEOTILE) { + return EsqlConverter.STRING_TO_GEOTILE; + } + if (to == DataType.GEOHEX) { + return EsqlConverter.STRING_TO_GEOHEX; + } if (to == DataType.TIME_DURATION) { return EsqlConverter.STRING_TO_TIME_DURATION; } @@ -545,6 +569,24 @@ public static String spatialToString(BytesRef field) { return UNSPECIFIED.wkbToWkt(field); } + public static String geoGridToString(long field, DataType dataType) { + return switch (dataType) { + case GEOHASH -> Geohash.stringEncode(field); + case GEOTILE -> GeoTileUtils.stringEncode(field); + case GEOHEX -> H3.h3ToString(field); + default -> throw new IllegalArgumentException("Unsupported data type for geo grid: " + dataType); + }; + } + + public static BytesRef geoGridToShape(long field, DataType dataType) { + return switch (dataType) { + case GEOHASH -> StGeohash.toBounds(field); + case GEOTILE -> StGeotile.toBounds(field); + case GEOHEX -> StGeohex.toBounds(field); + default -> throw new IllegalArgumentException("Unsupported data type for geo grid: " + dataType); + }; + } + public static BytesRef stringToGeo(String field) { return GEO.wktToWkb(field); } @@ -782,7 +824,10 @@ public enum EsqlConverter implements Converter { STRING_TO_INT(x -> EsqlDataTypeConverter.stringToInt(BytesRefs.toString(x))), STRING_TO_BOOLEAN(x -> EsqlDataTypeConverter.stringToBoolean(BytesRefs.toString(x))), STRING_TO_GEO(x -> EsqlDataTypeConverter.stringToGeo(BytesRefs.toString(x))), - STRING_TO_SPATIAL(x -> EsqlDataTypeConverter.stringToSpatial(BytesRefs.toString(x))); + STRING_TO_SPATIAL(x -> EsqlDataTypeConverter.stringToSpatial(BytesRefs.toString(x))), + STRING_TO_GEOHASH(x -> Geohash.longEncode(BytesRefs.toString(x))), + STRING_TO_GEOTILE(x -> GeoTileUtils.longEncode(BytesRefs.toString(x))), + STRING_TO_GEOHEX(x -> H3.stringToH3(BytesRefs.toString(x))); private static final String NAME = "esql-converter"; private final Function converter; diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseTests.java index 981384ca70a10..5621e10f5f205 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseTests.java @@ -40,8 +40,12 @@ import org.elasticsearch.core.TimeValue; import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.ShapeTestUtils; +import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.h3.H3; import org.elasticsearch.index.mapper.BlockLoader; import org.elasticsearch.rest.action.RestActions; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; import org.elasticsearch.test.AbstractChunkedSerializingTestCase; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.transport.RemoteClusterAware; @@ -232,6 +236,22 @@ private Page randomPage(List columns) { case CARTESIAN_SHAPE -> ((BytesRefBlock.Builder) builder).appendBytesRef( CARTESIAN.asWkb(ShapeTestUtils.randomGeometry(randomBoolean())) ); + case GEOHASH -> { + Point p = GeometryTestUtils.randomPoint(); + ((LongBlock.Builder) builder).appendLong( + Geohash.longEncode(p.getX(), p.getY(), randomIntBetween(1, Geohash.PRECISION)) + ); + } + case GEOTILE -> { + Point p = GeometryTestUtils.randomPoint(); + ((LongBlock.Builder) builder).appendLong( + GeoTileUtils.longEncode(p.getX(), p.getY(), randomIntBetween(0, GeoTileUtils.MAX_ZOOM)) + ); + } + case GEOHEX -> { + Point p = GeometryTestUtils.randomPoint(); + ((LongBlock.Builder) builder).appendLong(H3.geoToH3(p.getLat(), p.getLon(), randomIntBetween(1, H3.MAX_H3_RES))); + } case AGGREGATE_METRIC_DOUBLE -> { BlockLoader.AggregateMetricDoubleBuilder aggBuilder = (BlockLoader.AggregateMetricDoubleBuilder) builder; aggBuilder.min().appendDouble(randomDouble()); @@ -1206,6 +1226,9 @@ static Page valuesToPage(BlockFactory blockFactory, List columns BytesRef wkb = stringToSpatial(value.toString()); ((BytesRefBlock.Builder) builder).appendBytesRef(wkb); } + case GEOHASH -> ((LongBlock.Builder) builder).appendLong(Geohash.longEncode(value.toString())); + case GEOTILE -> ((LongBlock.Builder) builder).appendLong(GeoTileUtils.longEncode(value.toString())); + case GEOHEX -> ((LongBlock.Builder) builder).appendLong(H3.stringToH3(value.toString())); case AGGREGATE_METRIC_DOUBLE -> { BlockLoader.AggregateMetricDoubleBuilder aggBuilder = (BlockLoader.AggregateMetricDoubleBuilder) builder; aggBuilder.min().appendDouble(((Number) value).doubleValue()); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java index 4367851c8caae..f26c14db41604 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java @@ -1635,7 +1635,7 @@ public void testRegexOnInt() { public void testUnsupportedTypesWithToString() { // DATE_PERIOD and TIME_DURATION types have been added, but not really patched through the engine; i.e. supported. final String supportedTypes = "aggregate_metric_double or boolean or cartesian_point or cartesian_shape or date_nanos or datetime " - + "or geo_point or geo_shape or ip or numeric or string or version"; + + "or geo_point or geo_shape or geohash or geohex or geotile or ip or numeric or string or version"; verifyUnsupported( "row period = 1 year | eval to_string(period)", "line 1:28: argument of [to_string(period)] must be [" + supportedTypes + "], found value [period] type [date_period]" diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/ParsingTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/ParsingTests.java index 01242b19e3074..35bcb75714d4b 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/ParsingTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/ParsingTests.java @@ -104,7 +104,7 @@ public void testInlineCast() throws IOException { assertThat(row.fields(), hasSize(1)); Function functionCall = (Function) row.fields().get(0).child(); assertThat(functionCall.dataType(), equalTo(expectedType)); - report.field(nameOrAlias, registry.functionName(functionCall.getClass())); + report.field(nameOrAlias, registry.snapshotRegistry().functionName(functionCall.getClass())); } report.endObject(); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java index 594148826b432..919db367115cf 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java @@ -52,6 +52,9 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_NANOS; import static org.elasticsearch.xpack.esql.core.type.DataType.DOUBLE; import static org.elasticsearch.xpack.esql.core.type.DataType.FLOAT; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; 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; @@ -1055,6 +1058,9 @@ public void testSpatialSort() { "1:136: cannot sort on cartesian_shape", error(prefix + "| EVAL shape = TO_CARTESIANSHAPE(wkt) | limit 5 | sort shape") ); + assertEquals("1:143: cannot sort on geohash", error(prefix + "| EVAL grid = ST_GEOHASH(TO_GEOPOINT(wkt),1) | limit 5 | sort grid")); + assertEquals("1:143: cannot sort on geotile", error(prefix + "| EVAL grid = ST_GEOTILE(TO_GEOPOINT(wkt),1) | limit 5 | sort grid")); + assertEquals("1:142: cannot sort on geohex", error(prefix + "| EVAL grid = ST_GEOHEX(TO_GEOPOINT(wkt),1) | limit 5 | sort grid")); var airports = AnalyzerTestUtils.analyzer(loadMapping("mapping-airports.json", "airports")); var airportsWeb = AnalyzerTestUtils.analyzer(loadMapping("mapping-airports_web.json", "airports_web")); var countriesBbox = AnalyzerTestUtils.analyzer(loadMapping("mapping-countries_bbox.json", "countries_bbox")); @@ -1063,6 +1069,15 @@ public void testSpatialSort() { assertEquals("1:36: cannot sort on cartesian_point", error("FROM airports_web | LIMIT 5 | sort location", airportsWeb)); assertEquals("1:38: cannot sort on geo_shape", error("FROM countries_bbox | LIMIT 5 | sort shape", countriesBbox)); assertEquals("1:42: cannot sort on cartesian_shape", error("FROM countries_bbox_web | LIMIT 5 | sort shape", countriesBboxWeb)); + assertEquals( + "1:67: cannot sort on geohash", + error("FROM airports | LIMIT 5 | EVAL g = ST_GEOHASH(location, 1) | sort g", airports) + ); + assertEquals( + "1:67: cannot sort on geotile", + error("FROM airports | LIMIT 5 | EVAL g = ST_GEOTILE(location, 1) | sort g", airports) + ); + assertEquals("1:66: cannot sort on geohex", error("FROM airports | LIMIT 5 | EVAL g = ST_GEOHEX(location, 1) | sort g", airports)); } public void testSourceSorting() { @@ -1770,7 +1785,8 @@ public void testToDatePeriodTimeDurationInInvalidPosition() { // where assertEquals( "1:26: first argument of [\"3 days\"::date_period == to_dateperiod(\"3 days\")] must be " - + "[boolean, cartesian_point, cartesian_shape, date_nanos, datetime, double, geo_point, geo_shape, integer, ip, keyword, " + + "[boolean, cartesian_point, cartesian_shape, date_nanos, datetime, double, geo_point, geo_shape, " + + "geohash, geohex, geotile, integer, ip, keyword, " + "long, text, unsigned_long or version], found value [\"3 days\"::date_period] type [date_period]", error("row x = \"3 days\" | where \"3 days\"::date_period == to_dateperiod(\"3 days\")") ); @@ -2057,7 +2073,7 @@ public void testChangePoint() { public void testChangePoint_keySortable() { assumeTrue("change_point must be enabled", EsqlCapabilities.Cap.CHANGE_POINT.isEnabled()); List sortableTypes = List.of(BOOLEAN, DOUBLE, DATE_NANOS, DATETIME, INTEGER, IP, KEYWORD, LONG, UNSIGNED_LONG, VERSION); - List unsortableTypes = List.of(CARTESIAN_POINT, CARTESIAN_SHAPE, GEO_POINT, GEO_SHAPE); + List unsortableTypes = List.of(CARTESIAN_POINT, CARTESIAN_SHAPE, GEO_POINT, GEO_SHAPE, GEOHASH, GEOTILE, GEOHEX); for (DataType type : sortableTypes) { query(Strings.format("ROW key=NULL::%s, value=0\n | CHANGE_POINT value ON key", type)); } @@ -2080,6 +2096,9 @@ public void testChangePoint_valueNumeric() { DATETIME, GEO_POINT, GEO_SHAPE, + GEOHASH, + GEOTILE, + GEOHEX, IP, KEYWORD, VERSION diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/MultiRowTestCaseSupplier.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/MultiRowTestCaseSupplier.java index 677eb2389b3fc..3827525d74822 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/MultiRowTestCaseSupplier.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/MultiRowTestCaseSupplier.java @@ -14,6 +14,10 @@ import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.ShapeTestUtils; import org.elasticsearch.geometry.Geometry; +import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.h3.H3; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.versionfield.Version; @@ -453,6 +457,36 @@ private static List spatialCases( return cases; } + public static List geohashCases(int minRows, int maxRows) { + Supplier gen = () -> { + Point point = GeometryTestUtils.randomPoint(); + return Geohash.longEncode(point.getX(), point.getY(), ESTestCase.randomIntBetween(1, Geohash.PRECISION)); + }; + List cases = new ArrayList<>(); + addSuppliers(cases, minRows, maxRows, "", DataType.GEOHASH, gen); + return cases; + } + + public static List geotileCases(int minRows, int maxRows) { + Supplier gen = () -> { + Point point = GeometryTestUtils.randomPoint(); + return GeoTileUtils.longEncode(point.getX(), point.getY(), ESTestCase.randomIntBetween(1, GeoTileUtils.MAX_ZOOM)); + }; + List cases = new ArrayList<>(); + addSuppliers(cases, minRows, maxRows, "", DataType.GEOTILE, gen); + return cases; + } + + public static List geohexCases(int minRows, int maxRows) { + Supplier gen = () -> { + Point point = GeometryTestUtils.randomPoint(); + return H3.geoToH3(point.getLat(), point.getLon(), ESTestCase.randomIntBetween(1, H3.MAX_H3_RES)); + }; + List cases = new ArrayList<>(); + addSuppliers(cases, minRows, maxRows, "", DataType.GEOHEX, gen); + return cases; + } + public static List stringCases(int minRows, int maxRows, DataType type) { List cases = new ArrayList<>(); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/TestCaseSupplier.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/TestCaseSupplier.java index 7a1600db82c58..930bfc7cf7203 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/TestCaseSupplier.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/TestCaseSupplier.java @@ -15,8 +15,12 @@ import org.elasticsearch.common.time.DateUtils; import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.ShapeTestUtils; +import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.h3.H3; import org.elasticsearch.logging.LogManager; import org.elasticsearch.logging.Logger; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.esql.EsqlTestUtils; import org.elasticsearch.xpack.esql.core.expression.Expression; @@ -49,6 +53,7 @@ import java.util.function.UnaryOperator; import java.util.stream.Collectors; +import static org.elasticsearch.test.ESTestCase.randomIntBetween; import static org.elasticsearch.xpack.esql.core.util.NumericUtils.UNSIGNED_LONG_MAX; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.CARTESIAN; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; @@ -655,6 +660,49 @@ public static void forUnaryBoolean( unary(suppliers, expectedEvaluatorToString, booleanCases(), expectedType, v -> expectedValue.apply((Boolean) v), warnings); } + /** + * Generate positive test cases for a unary function operating on an {@link DataType#GEOHASH}. + */ + public static void forUnaryGeoGrid( + List suppliers, + String expectedEvaluatorToString, + DataType sourceType, + DataType expectedType, + Function expectedValue, + List warnings + ) { + if (DataType.isGeoGrid(sourceType)) { + unary(suppliers, expectedEvaluatorToString, geoGridCases(sourceType), expectedType, expectedValue, warnings); + + } else if (DataType.isGeoGrid(expectedType)) { + if (sourceType == DataType.LONG) { + unary( + suppliers, + expectedEvaluatorToString, + geoGridCasesAsLongs(expectedType, ESTestCase::randomBoolean), + expectedType, + expectedValue, + warnings + ); + } else if (sourceType.noText() == DataType.KEYWORD) { + unary( + suppliers, + expectedEvaluatorToString, + geoGridCasesAsStrings(expectedType, sourceType, ESTestCase::randomBoolean), + expectedType, + expectedValue, + warnings + ); + } else { + throw new IllegalArgumentException( + "Expected gro-grid types, got source [" + sourceType + "], expected [" + expectedType + "]" + ); + } + } else { + throw new IllegalArgumentException("Expected gro-grid types, got source [" + sourceType + "], expected [" + expectedType + "]"); + } + } + /** * Generate positive test cases for a unary function operating on an {@link DataType#GEO_POINT}. */ @@ -856,7 +904,7 @@ public static List intCases(int min, int max, boolean include int lower = Math.max(min, 1); int upper = Math.min(max, Integer.MAX_VALUE); if (lower < upper) { - cases.add(new TypedDataSupplier("", () -> ESTestCase.randomIntBetween(lower, upper), DataType.INTEGER)); + cases.add(new TypedDataSupplier("", () -> randomIntBetween(lower, upper), DataType.INTEGER)); } else if (lower == upper) { cases.add(new TypedDataSupplier("<" + lower + " int>", () -> lower, DataType.INTEGER)); } @@ -864,7 +912,7 @@ public static List intCases(int min, int max, boolean include int lower1 = Math.max(min, Integer.MIN_VALUE); int upper1 = Math.min(max, -1); if (lower1 < upper1) { - cases.add(new TypedDataSupplier("", () -> ESTestCase.randomIntBetween(lower1, upper1), DataType.INTEGER)); + cases.add(new TypedDataSupplier("", () -> randomIntBetween(lower1, upper1), DataType.INTEGER)); } else if (lower1 == upper1) { cases.add(new TypedDataSupplier("<" + lower1 + " int>", () -> lower1, DataType.INTEGER)); } @@ -1178,11 +1226,7 @@ public static List datePeriodCases(int yearMin, int monthMin, new TypedDataSupplier("", () -> Period.ZERO, DataType.DATE_PERIOD, true), new TypedDataSupplier( "", - () -> Period.of( - ESTestCase.randomIntBetween(yMin, yMax), - ESTestCase.randomIntBetween(mMin, mMax), - ESTestCase.randomIntBetween(dMin, dMax) - ), + () -> Period.of(randomIntBetween(yMin, yMax), randomIntBetween(mMin, mMax), randomIntBetween(dMin, dMax)), DataType.DATE_PERIOD, true ) @@ -1208,6 +1252,10 @@ public static List timeDurationCases(long minValue, long maxV ); } + public static List geoGridCases(DataType gridType) { + return geoGridCases(gridType, ESTestCase::randomBoolean); + } + public static List geoPointCases() { return geoPointCases(ESTestCase::randomBoolean); } @@ -1224,6 +1272,46 @@ public static List cartesianShapeCases() { return cartesianShapeCases(ESTestCase::randomBoolean); } + /** + * Generate cases for {@link DataType#GEOHASH}. + */ + public static List geoGridCases(DataType gridType, Supplier hasAlt) { + return geoGridCasesAsType(gridType, gridType, hasAlt); + } + + public static List geoGridCasesAsLongs(DataType gridType, Supplier hasAlt) { + return geoGridCasesAsType(gridType, DataType.LONG, hasAlt); + } + + private static List geoGridCasesAsType(DataType gridType, DataType sourceType, Supplier hasAlt) { + Supplier gridId = () -> { + Point point = GeometryTestUtils.randomPoint(hasAlt.get()); + return switch (gridType) { + case GEOHASH -> Geohash.longEncode(point.getX(), point.getY(), randomIntBetween(1, Geohash.PRECISION)); + case GEOTILE -> GeoTileUtils.longEncode(point.getX(), point.getY(), randomIntBetween(0, GeoTileUtils.MAX_ZOOM)); + case GEOHEX -> H3.geoToH3(point.getLat(), point.getLon(), randomIntBetween(0, H3.MAX_H3_RES)); + default -> throw new IllegalArgumentException("Unsupported grid type: " + gridType); + }; + }; + return List.of(new TypedDataSupplier("<" + gridType.esType() + ">", gridId, sourceType)); + } + + public static List geoGridCasesAsStrings(DataType gridType, DataType sourceType, Supplier hasAlt) { + Supplier gridId = () -> { + Point point = GeometryTestUtils.randomPoint(hasAlt.get()); + String gridAddress = switch (gridType) { + case GEOHASH -> Geohash.stringEncode(point.getX(), point.getY(), randomIntBetween(1, Geohash.PRECISION)); + case GEOTILE -> GeoTileUtils.stringEncode( + GeoTileUtils.longEncode(point.getX(), point.getY(), randomIntBetween(0, GeoTileUtils.MAX_ZOOM)) + ); + case GEOHEX -> H3.geoToH3Address(point.getLat(), point.getLon(), randomIntBetween(0, H3.MAX_H3_RES)); + default -> throw new IllegalArgumentException("Unsupported grid type: " + gridType); + }; + return new BytesRef(gridAddress); + }; + return List.of(new TypedDataSupplier("<" + gridType.esType() + ">", gridId, sourceType)); + } + /** * Generate cases for {@link DataType#GEO_POINT}. * diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java index 863a8cc5f255b..b4aafef8fa467 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java @@ -51,6 +51,9 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.geoPointCases(1, 1000, IncludingAltitude.YES), MultiRowTestCaseSupplier.geoShapeCasesWithoutCircle(1, 1000, IncludingAltitude.YES), MultiRowTestCaseSupplier.cartesianShapeCasesWithoutCircle(1, 1000, IncludingAltitude.YES), + MultiRowTestCaseSupplier.geohashCases(1, 1000), + MultiRowTestCaseSupplier.geotileCases(1, 1000), + MultiRowTestCaseSupplier.geohexCases(1, 1000), MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.KEYWORD), MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.TEXT) ).flatMap(List::stream).map(CountTests::makeSupplier).collect(Collectors.toCollection(() -> suppliers)); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SampleTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SampleTests.java index 8b66da40ddb27..e61447a65a820 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SampleTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SampleTests.java @@ -59,7 +59,10 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.geoPointCases(1, 1000, MultiRowTestCaseSupplier.IncludingAltitude.NO), MultiRowTestCaseSupplier.cartesianPointCases(1, 1000, MultiRowTestCaseSupplier.IncludingAltitude.NO), MultiRowTestCaseSupplier.geoShapeCasesWithoutCircle(1, 20, MultiRowTestCaseSupplier.IncludingAltitude.NO), - MultiRowTestCaseSupplier.cartesianShapeCasesWithoutCircle(1, 20, MultiRowTestCaseSupplier.IncludingAltitude.NO) + MultiRowTestCaseSupplier.cartesianShapeCasesWithoutCircle(1, 20, MultiRowTestCaseSupplier.IncludingAltitude.NO), + MultiRowTestCaseSupplier.geohashCases(1, 1000), + MultiRowTestCaseSupplier.geotileCases(1, 1000), + MultiRowTestCaseSupplier.geohexCases(1, 1000) ) .flatMap(List::stream) .map(fieldCaseSupplier -> makeSupplier(fieldCaseSupplier, limitCaseSupplier)) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesTests.java index f386f623e17dc..f23ff3c715ca4 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesTests.java @@ -59,7 +59,10 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.geoPointCases(1, 1000, MultiRowTestCaseSupplier.IncludingAltitude.NO), MultiRowTestCaseSupplier.cartesianPointCases(1, 1000, MultiRowTestCaseSupplier.IncludingAltitude.NO), MultiRowTestCaseSupplier.geoShapeCasesWithoutCircle(1, 20, MultiRowTestCaseSupplier.IncludingAltitude.NO), - MultiRowTestCaseSupplier.cartesianShapeCasesWithoutCircle(1, 20, MultiRowTestCaseSupplier.IncludingAltitude.NO) + MultiRowTestCaseSupplier.cartesianShapeCasesWithoutCircle(1, 20, MultiRowTestCaseSupplier.IncludingAltitude.NO), + MultiRowTestCaseSupplier.geohashCases(1, 100), + MultiRowTestCaseSupplier.geotileCases(1, 100), + MultiRowTestCaseSupplier.geohexCases(1, 100) ).flatMap(List::stream).map(ValuesTests::makeSupplier).collect(Collectors.toCollection(() -> suppliers)); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(suppliers, false); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseTests.java index 8d3b214f97a63..a538f17969bce 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseTests.java @@ -56,6 +56,9 @@ public class CaseTests extends AbstractScalarFunctionTestCase { DataType.GEO_POINT, DataType.CARTESIAN_SHAPE, DataType.GEO_SHAPE, + DataType.GEOHASH, + DataType.GEOTILE, + DataType.GEOHEX, DataType.NULL ).collect(Collectors.toList()); if (Build.current().isSnapshot()) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeErrorTests.java index 9e6f81e649d84..3b689323990dc 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeErrorTests.java @@ -32,6 +32,7 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { - return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "geo_point or geo_shape or string")); + String expectedTypes = "geo_point or geo_shape or geohash or geohex or geotile or string"; + return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> expectedTypes)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeTests.java index 5b75bded802de..a2148a61f4fb1 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeTests.java @@ -18,6 +18,7 @@ import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase; import org.elasticsearch.xpack.esql.expression.function.FunctionName; import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; +import org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter; import java.util.ArrayList; import java.util.List; @@ -39,8 +40,20 @@ public static Iterable parameters() { final Function evaluatorName = s -> "ToGeoShape" + s + "Evaluator[in=" + attribute + "]"; final List suppliers = new ArrayList<>(); + // Points and shapes TestCaseSupplier.forUnaryGeoPoint(suppliers, attribute, DataType.GEO_SHAPE, v -> v, List.of()); TestCaseSupplier.forUnaryGeoShape(suppliers, attribute, DataType.GEO_SHAPE, v -> v, List.of()); + // Geo-Grid types + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + TestCaseSupplier.forUnaryGeoGrid( + suppliers, + "ToGeoShapeFromGeoGridEvaluator[in=Attribute[channel=0], dataType=" + gridType + "]", + gridType, + DataType.GEO_SHAPE, + v -> EsqlDataTypeConverter.geoGridToShape((long) v, gridType), + List.of() + ); + } // random strings that don't look like a geo shape TestCaseSupplier.forUnaryStrings(suppliers, evaluatorName.apply("FromString"), DataType.GEO_SHAPE, bytesRef -> null, bytesRef -> { var exception = expectThrows(Exception.class, () -> GEO.wktToWkb(bytesRef.utf8ToString())); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashErrorTests.java new file mode 100644 index 0000000000000..aefe38d0f8685 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashErrorTests.java @@ -0,0 +1,37 @@ +/* + * 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.convert; + +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 ToGeohashErrorTests extends ErrorsForCasesWithoutExamplesTestCase { + @Override + protected List cases() { + return paramsToSuppliers(ToGeohashTests.parameters()); + } + + @Override + protected Expression build(Source source, List args) { + return new ToGeohash(source, args.get(0)); + } + + @Override + protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "geohash or long or string")); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashSerializationTests.java new file mode 100644 index 0000000000000..244094a627589 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToGeohashSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToGeohash create(Source source, Expression child) { + return new ToGeohash(source, child); + } +} 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/convert/ToGeohashTests.java similarity index 53% rename from x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongTests.java rename to x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashTests.java index fab3655677774..d9c0be69ac42a 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/convert/ToGeohashTests.java @@ -5,7 +5,7 @@ * 2.0. */ -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; @@ -15,6 +15,7 @@ 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.AbstractScalarFunctionTestCase; import org.elasticsearch.xpack.esql.expression.function.FunctionName; import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; @@ -22,42 +23,33 @@ 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) { +@FunctionName("to_geohash") +public class ToGeohashTests extends AbstractScalarFunctionTestCase { + public ToGeohashTests(@Name("TestCase") Supplier testCaseSupplier) { this.testCase = testCaseSupplier.get(); } @ParametersFactory public static Iterable parameters() { + final String attribute = "Attribute[channel=0]"; + final String evaluator = "ToGeohashFromStringEvaluator[in=Attribute[channel=0]]"; final List suppliers = new ArrayList<>(); - forUnaryGeoPoint( - DataType.LONG, - suppliers, - "Attribute[channel=0]", - DataType.LONG, - g -> StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeohashToLongTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "StGeohashToLongFromStringEvaluator[gridId=Attribute[channel=0]]", - DataType.LONG, - g -> new BytesRef(Geohash.stringEncode(StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), - StGeohashToLongTests::valueOf - ); + + TestCaseSupplier.forUnaryGeoGrid(suppliers, attribute, DataType.GEOHASH, DataType.GEOHASH, v -> v, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, attribute, DataType.LONG, DataType.GEOHASH, v -> v, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, evaluator, DataType.KEYWORD, DataType.GEOHASH, ToGeohashTests::valueOf, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, evaluator, DataType.TEXT, DataType.GEOHASH, ToGeohashTests::valueOf, List.of()); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } - private static long valueOf(Object gridid) { - return (gridid instanceof Long hash) ? hash : Geohash.longEncode(((BytesRef) gridid).utf8ToString()); + private static long valueOf(Object gridAddress) { + assert gridAddress instanceof BytesRef; + return Geohash.longEncode(((BytesRef) gridAddress).utf8ToString()); } @Override protected Expression build(Source source, List args) { - return new StGeohashToLong(source, args.get(0)); + return new ToGeohash(source, args.get(0)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexSerializationTests.java new file mode 100644 index 0000000000000..a76c8e4a1e535 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToGeohexSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToGeohex create(Source source, Expression child) { + return new ToGeohex(source, child); + } +} 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/convert/ToGeohexTests.java similarity index 53% rename from x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java rename to x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexTests.java index 7c28fdb551079..75eefec4b3c96 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/convert/ToGeohexTests.java @@ -5,7 +5,7 @@ * 2.0. */ -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; @@ -15,6 +15,7 @@ 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.AbstractScalarFunctionTestCase; import org.elasticsearch.xpack.esql.expression.function.FunctionName; import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; @@ -22,42 +23,33 @@ 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) { +@FunctionName("to_geohex") +public class ToGeohexTests extends AbstractScalarFunctionTestCase { + public ToGeohexTests(@Name("TestCase") Supplier testCaseSupplier) { this.testCase = testCaseSupplier.get(); } @ParametersFactory public static Iterable parameters() { + final String attribute = "Attribute[channel=0]"; + final String evaluator = "ToGeohexFromStringEvaluator[in=Attribute[channel=0]]"; final List suppliers = new ArrayList<>(); - forUnaryGeoPoint( - DataType.LONG, - suppliers, - "Attribute[channel=0]", - DataType.LONG, - g -> StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeohexToLongTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "StGeohexToLongFromStringEvaluator[gridId=Attribute[channel=0]]", - DataType.LONG, - g -> new BytesRef(H3.h3ToString(StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), - StGeohexToLongTests::valueOf - ); + + TestCaseSupplier.forUnaryGeoGrid(suppliers, attribute, DataType.GEOHEX, DataType.GEOHEX, v -> v, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, attribute, DataType.LONG, DataType.GEOHEX, v -> v, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, evaluator, DataType.KEYWORD, DataType.GEOHEX, ToGeohexTests::valueOf, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, evaluator, DataType.TEXT, DataType.GEOHEX, ToGeohexTests::valueOf, List.of()); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } - private static long valueOf(Object gridid) { - return (gridid instanceof Long hash) ? hash : H3.stringToH3(((BytesRef) gridid).utf8ToString()); + private static long valueOf(Object gridAddress) { + assert gridAddress instanceof BytesRef; + return H3.stringToH3(((BytesRef) gridAddress).utf8ToString()); } @Override protected Expression build(Source source, List args) { - return new StGeohexToLong(source, args.get(0)); + return new ToGeohex(source, args.get(0)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexhErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexhErrorTests.java new file mode 100644 index 0000000000000..24e2521731bde --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexhErrorTests.java @@ -0,0 +1,37 @@ +/* + * 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.convert; + +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 ToGeohexhErrorTests extends ErrorsForCasesWithoutExamplesTestCase { + @Override + protected List cases() { + return paramsToSuppliers(ToGeohexTests.parameters()); + } + + @Override + protected Expression build(Source source, List args) { + return new ToGeohex(source, args.get(0)); + } + + @Override + protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "geohex or long or string")); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileErrorTests.java new file mode 100644 index 0000000000000..9696b7399e830 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileErrorTests.java @@ -0,0 +1,37 @@ +/* + * 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.convert; + +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 ToGeotileErrorTests extends ErrorsForCasesWithoutExamplesTestCase { + @Override + protected List cases() { + return paramsToSuppliers(ToGeotileTests.parameters()); + } + + @Override + protected Expression build(Source source, List args) { + return new ToGeotile(source, args.get(0)); + } + + @Override + protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "geotile or long or string")); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileSerializationTests.java new file mode 100644 index 0000000000000..dc6838a96343d --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToGeotileSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToGeotile create(Source source, Expression child) { + return new ToGeotile(source, child); + } +} 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/convert/ToGeotileTests.java similarity index 53% rename from x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongTests.java rename to x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileTests.java index 1f43536719fd8..49776099ada9f 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/convert/ToGeotileTests.java @@ -5,7 +5,7 @@ * 2.0. */ -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; @@ -15,6 +15,7 @@ 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.AbstractScalarFunctionTestCase; import org.elasticsearch.xpack.esql.expression.function.FunctionName; import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; @@ -22,42 +23,33 @@ 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) { +@FunctionName("to_geotile") +public class ToGeotileTests extends AbstractScalarFunctionTestCase { + public ToGeotileTests(@Name("TestCase") Supplier testCaseSupplier) { this.testCase = testCaseSupplier.get(); } @ParametersFactory public static Iterable parameters() { + final String attribute = "Attribute[channel=0]"; + final String evaluator = "ToGeotileFromStringEvaluator[in=Attribute[channel=0]]"; final List suppliers = new ArrayList<>(); - forUnaryGeoPoint( - DataType.LONG, - suppliers, - "Attribute[channel=0]", - DataType.LONG, - g -> StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeotileToLongTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "StGeotileToLongFromStringEvaluator[gridId=Attribute[channel=0]]", - DataType.LONG, - g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), - StGeotileToLongTests::valueOf - ); + + TestCaseSupplier.forUnaryGeoGrid(suppliers, attribute, DataType.GEOTILE, DataType.GEOTILE, v -> v, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, attribute, DataType.LONG, DataType.GEOTILE, v -> v, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, evaluator, DataType.KEYWORD, DataType.GEOTILE, ToGeotileTests::valueOf, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, evaluator, DataType.TEXT, DataType.GEOTILE, ToGeotileTests::valueOf, List.of()); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } - private static long valueOf(Object gridid) { - return (gridid instanceof Long hash) ? hash : GeoTileUtils.longEncode(((BytesRef) gridid).utf8ToString()); + private static long valueOf(Object gridAddress) { + assert gridAddress instanceof BytesRef; + return GeoTileUtils.longEncode(((BytesRef) gridAddress).utf8ToString()); } @Override protected Expression build(Source source, List args) { - return new StGeotileToLong(source, args.get(0)); + return new ToGeotile(source, args.get(0)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongErrorTests.java index cc93e4f050796..4c387c545f6f6 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongErrorTests.java @@ -32,13 +32,8 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { - return equalTo( - typeErrorMessage( - false, - validPerPosition, - signature, - (v, p) -> "boolean or counter_integer or counter_long or date_nanos or datetime or numeric or string" - ) - ); + String expectedTypes = + "boolean or counter_integer or counter_long or date_nanos or datetime or geohash or geohex or geotile or numeric or string"; + return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> expectedTypes)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongTests.java index 50748d582ed1f..b7925fce6b496 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongTests.java @@ -241,6 +241,11 @@ public static Iterable parameters() { l -> ((Integer) l).longValue(), List.of() ); + + // Geo-Grid types + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + TestCaseSupplier.forUnaryGeoGrid(suppliers, read, gridType, DataType.LONG, v -> v, List.of()); + } return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringTests.java index f766deb2e1686..8d8f59b78114d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringTests.java @@ -19,6 +19,7 @@ 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 org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter; import java.math.BigInteger; import java.time.Instant; @@ -141,6 +142,17 @@ public static Iterable parameters() { v -> new BytesRef(v.toString()), List.of() ); + // Geo-Grid types + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + TestCaseSupplier.forUnaryGeoGrid( + suppliers, + "ToStringFromGeoGridEvaluator[gridId=Attribute[channel=0], dataType=" + gridType + "]", + gridType, + DataType.KEYWORD, + v -> new BytesRef(EsqlDataTypeConverter.geoGridToString((long) v, gridType)), + List.of() + ); + } return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/AbstractMultivalueFunctionTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/AbstractMultivalueFunctionTestCase.java index c57847a5daea9..dfa0dc786474c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/AbstractMultivalueFunctionTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/AbstractMultivalueFunctionTestCase.java @@ -12,6 +12,10 @@ import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.ShapeTestUtils; import org.elasticsearch.geometry.Geometry; +import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.h3.H3; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; @@ -571,6 +575,98 @@ protected static void spatial( } } + /** + * Build many test cases with {@code geohash} values that are converted to another type. + * This assumes that the function consumes {@code geohash} values and produces another type. + * For example, mv_count() can consume geo-grid values and produce an integer count. + */ + protected static void geohashGrid( + List cases, + String name, + String evaluatorName, + DataType expectedDataType, + BiFunction, Matcher> matcher + ) { + Supplier supplier = () -> { + Point point = GeometryTestUtils.randomPoint(); + return Geohash.longEncode(point.getX(), point.getY(), randomIntBetween(1, Geohash.PRECISION)); + }; + spatialGrid(cases, name, evaluatorName, DataType.GEOHASH, expectedDataType, supplier, matcher); + } + + /** + * Build many test cases with {@code geotile} values that are converted to another type. + * This assumes that the function consumes {@code geotile} values and produces another type. + * For example, mv_count() can consume geo-grid values and produce an integer count. + */ + protected static void geotileGrid( + List cases, + String name, + String evaluatorName, + DataType expectedDataType, + BiFunction, Matcher> matcher + ) { + Supplier supplier = () -> { + Point point = GeometryTestUtils.randomPoint(); + return GeoTileUtils.longEncode(point.getX(), point.getY(), randomIntBetween(1, GeoTileUtils.MAX_ZOOM)); + }; + spatialGrid(cases, name, evaluatorName, DataType.GEOTILE, expectedDataType, supplier, matcher); + } + + /** + * Build many test cases with {@code geohex} values that are converted to another type. + * This assumes that the function consumes {@code geohex} values and produces another type. + * For example, mv_count() can consume geo-grid values and produce an integer count. + */ + protected static void geohexGrid( + List cases, + String name, + String evaluatorName, + DataType expectedDataType, + BiFunction, Matcher> matcher + ) { + Supplier supplier = () -> { + Point point = GeometryTestUtils.randomPoint(); + return H3.geoToH3(point.getLat(), point.getLon(), randomIntBetween(1, H3.MAX_H3_RES)); + }; + spatialGrid(cases, name, evaluatorName, DataType.GEOHEX, expectedDataType, supplier, matcher); + } + + /** + * Build many test cases for spatial grid values + */ + protected static void spatialGrid( + List cases, + String name, + String evaluatorName, + DataType dataType, + DataType expectedDataType, + Supplier randomGridId, + BiFunction, Matcher> matcher + ) { + cases.add(new TestCaseSupplier(name + "(" + dataType.typeName() + ")", List.of(dataType), () -> { + long gridId = randomGridId.get(); + return new TestCaseSupplier.TestCase( + List.of(new TestCaseSupplier.TypedData(List.of(gridId), dataType, "field")), + evaluatorName + "[field=Attribute[channel=0]]", + expectedDataType, + matcher.apply(1, Stream.of(gridId)) + ); + })); + for (Block.MvOrdering ordering : Block.MvOrdering.values()) { + cases.add(new TestCaseSupplier(name + "(<" + dataType.typeName() + "s>) " + ordering, List.of(dataType), () -> { + List mvData = randomList(1, 100, randomGridId); + putInOrder(mvData, ordering); + return new TestCaseSupplier.TestCase( + List.of(new TestCaseSupplier.TypedData(mvData, dataType, "field")), + evaluatorName + "[field=Attribute[channel=0]]", + expectedDataType, + matcher.apply(mvData.size(), mvData.stream()) + ); + })); + } + } + /** * Build many test cases with unsigned {@code long} values. */ diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendTests.java index c0c14499fa744..d485d990693b1 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendTests.java @@ -29,6 +29,7 @@ import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomLiteral; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.CARTESIAN; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; +import static org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvSliceTests.randomGrid; import static org.hamcrest.Matchers.equalTo; public class MvAppendTests extends AbstractScalarFunctionTestCase { @@ -89,21 +90,13 @@ private static void ints(List suppliers) { } private static void longs(List suppliers) { - suppliers.add(new TestCaseSupplier(List.of(DataType.LONG, DataType.LONG), () -> { - List field1 = randomList(1, 10, () -> randomLong()); - List field2 = randomList(1, 10, () -> randomLong()); - var result = new ArrayList<>(field1); - result.addAll(field2); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field1, DataType.LONG, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.LONG, "field2") - ), - "MvAppendLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", - DataType.LONG, - equalTo(result) - ); - })); + addLongTestCase(suppliers, DataType.LONG, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.DATETIME, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.DATE_NANOS, ESTestCase::randomNonNegativeLong); + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + addLongTestCase(suppliers, gridType, () -> randomGrid(gridType)); + } + suppliers.add(new TestCaseSupplier(List.of(DataType.UNSIGNED_LONG, DataType.UNSIGNED_LONG), () -> { List field1 = randomList(1, 10, ESTestCase::randomLong); List field2 = randomList(1, 10, ESTestCase::randomLong); @@ -118,33 +111,21 @@ private static void longs(List suppliers) { equalTo(result) ); })); - suppliers.add(new TestCaseSupplier(List.of(DataType.DATETIME, DataType.DATETIME), () -> { - List field1 = randomList(1, 10, () -> randomLong()); - List field2 = randomList(1, 10, () -> randomLong()); - var result = new ArrayList<>(field1); - result.addAll(field2); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field1, DataType.DATETIME, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.DATETIME, "field2") - ), - "MvAppendLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", - DataType.DATETIME, - equalTo(result) - ); - })); - suppliers.add(new TestCaseSupplier(List.of(DataType.DATE_NANOS, DataType.DATE_NANOS), () -> { - List field1 = randomList(1, 10, () -> randomNonNegativeLong()); - List field2 = randomList(1, 10, () -> randomNonNegativeLong()); + } + + private static void addLongTestCase(List suppliers, DataType dataType, Supplier longSupplier) { + suppliers.add(new TestCaseSupplier(List.of(dataType, dataType), () -> { + List field1 = randomList(1, 10, longSupplier); + List field2 = randomList(1, 10, longSupplier); var result = new ArrayList<>(field1); result.addAll(field2); return new TestCaseSupplier.TestCase( List.of( - new TestCaseSupplier.TypedData(field1, DataType.DATE_NANOS, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.DATE_NANOS, "field2") + new TestCaseSupplier.TypedData(field1, dataType, "field1"), + new TestCaseSupplier.TypedData(field2, dataType, "field2") ), "MvAppendLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", - DataType.DATE_NANOS, + dataType, equalTo(result) ); })); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsTests.java index 57da6d5c2fe9a..7b833ba86e00d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsTests.java @@ -35,6 +35,7 @@ import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; import static org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier.TypedData.MULTI_ROW_NULL; import static org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier.TypedData.NULL; +import static org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvSliceTests.randomGrid; import static org.hamcrest.Matchers.equalTo; public class MvContainsTests extends AbstractScalarFunctionTestCase { @@ -100,56 +101,24 @@ private static void ints(List suppliers) { } private static void longs(List suppliers) { - suppliers.add(new TestCaseSupplier(List.of(DataType.LONG, DataType.LONG), () -> { - List field1 = randomList(1, 10, ESTestCase::randomLong); - List field2 = randomList(1, 10, ESTestCase::randomLong); - var result = field1.containsAll(field2); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field1, DataType.LONG, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.LONG, "field2") - ), - "MvContainsLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", - DataType.BOOLEAN, - equalTo(result) - ); - })); - suppliers.add(new TestCaseSupplier(List.of(DataType.UNSIGNED_LONG, DataType.UNSIGNED_LONG), () -> { - List field1 = randomList(1, 10, ESTestCase::randomLong); - List field2 = randomList(1, 10, ESTestCase::randomLong); - var result = field1.containsAll(field2); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field1, DataType.UNSIGNED_LONG, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.UNSIGNED_LONG, "field2") - ), - "MvContainsLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", - DataType.BOOLEAN, - equalTo(result) - ); - })); - suppliers.add(new TestCaseSupplier(List.of(DataType.DATETIME, DataType.DATETIME), () -> { - List field1 = randomList(1, 10, ESTestCase::randomLong); - List field2 = randomList(1, 10, ESTestCase::randomLong); - var result = field1.containsAll(field2); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field1, DataType.DATETIME, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.DATETIME, "field2") - ), - "MvContainsLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", - DataType.BOOLEAN, - equalTo(result) - ); - })); - suppliers.add(new TestCaseSupplier(List.of(DataType.DATE_NANOS, DataType.DATE_NANOS), () -> { - List field1 = randomList(1, 10, ESTestCase::randomNonNegativeLong); - List field2 = randomList(1, 10, ESTestCase::randomNonNegativeLong); + addLongTestCase(suppliers, DataType.LONG, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.UNSIGNED_LONG, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.DATETIME, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.DATE_NANOS, ESTestCase::randomNonNegativeLong); + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + addLongTestCase(suppliers, gridType, () -> randomGrid(gridType)); + } + } + + private static void addLongTestCase(List suppliers, DataType dataType, Supplier longSupplier) { + suppliers.add(new TestCaseSupplier(List.of(dataType, dataType), () -> { + List field1 = randomList(1, 10, longSupplier); + List field2 = randomList(1, 10, longSupplier); var result = field1.containsAll(field2); return new TestCaseSupplier.TestCase( List.of( - new TestCaseSupplier.TypedData(field1, DataType.DATE_NANOS, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.DATE_NANOS, "field2") + new TestCaseSupplier.TypedData(field1, dataType, "field1"), + new TestCaseSupplier.TypedData(field2, dataType, "field2") ), "MvContainsLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", DataType.BOOLEAN, diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountTests.java index 6aeab0339c172..a1bcca42a8d93 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountTests.java @@ -41,6 +41,9 @@ public static Iterable parameters() { cartesianPoints(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count()))); geoShape(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count()))); cartesianShape(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count()))); + geohashGrid(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count()))); + geotileGrid(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count()))); + geohexGrid(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count()))); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, cases); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeTests.java index 24fd0a349796c..78e51b802c191 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeTests.java @@ -47,6 +47,9 @@ public static Iterable parameters() { cartesianShape(cases, "mv_dedupe", "MvDedupe", DataType.CARTESIAN_SHAPE, (size, values) -> getMatcher(values)); geoPoints(cases, "mv_dedupe", "MvDedupe", (size, values) -> getMatcher(values)); geoShape(cases, "mv_dedupe", "MvDedupe", DataType.GEO_SHAPE, (size, values) -> getMatcher(values)); + geohashGrid(cases, "mv_dedupe", "MvDedupe", DataType.GEOHASH, (size, values) -> getMatcher(values)); + geotileGrid(cases, "mv_dedupe", "MvDedupe", DataType.GEOTILE, (size, values) -> getMatcher(values)); + geohexGrid(cases, "mv_dedupe", "MvDedupe", DataType.GEOHEX, (size, values) -> getMatcher(values)); unsignedLongs(cases, "mv_dedupe", "MvDedupe", (size, values) -> getMatcher(values)); return parameterSuppliersFromTypedData(anyNullIsNull(false, cases)); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstTests.java index 3ee98364141c6..5d0a4b4b43cda 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstTests.java @@ -42,6 +42,9 @@ public static Iterable parameters() { cartesianPoints(cases, "mv_first", "MvFirst", DataType.CARTESIAN_POINT, (size, values) -> equalTo(values.findFirst().get())); geoShape(cases, "mv_first", "MvFirst", DataType.GEO_SHAPE, (size, values) -> equalTo(values.findFirst().get())); cartesianShape(cases, "mv_first", "MvFirst", DataType.CARTESIAN_SHAPE, (size, values) -> equalTo(values.findFirst().get())); + geohashGrid(cases, "mv_first", "MvFirst", DataType.GEOHASH, (size, values) -> equalTo(values.findFirst().get())); + geotileGrid(cases, "mv_first", "MvFirst", DataType.GEOTILE, (size, values) -> equalTo(values.findFirst().get())); + geohexGrid(cases, "mv_first", "MvFirst", DataType.GEOHEX, (size, values) -> equalTo(values.findFirst().get())); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(false, cases); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastTests.java index a7a13360ce443..a725b03c860f5 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastTests.java @@ -42,6 +42,9 @@ public static Iterable parameters() { cartesianPoints(cases, "mv_last", "MvLast", DataType.CARTESIAN_POINT, (size, values) -> equalTo(values.reduce((f, s) -> s).get())); geoShape(cases, "mv_last", "MvLast", DataType.GEO_SHAPE, (size, values) -> equalTo(values.reduce((f, s) -> s).get())); cartesianShape(cases, "mv_last", "MvLast", DataType.CARTESIAN_SHAPE, (size, values) -> equalTo(values.reduce((f, s) -> s).get())); + geohashGrid(cases, "mv_first", "MvLast", DataType.GEOHASH, (size, values) -> equalTo(values.reduce((f, s) -> s).get())); + geotileGrid(cases, "mv_first", "MvLast", DataType.GEOTILE, (size, values) -> equalTo(values.reduce((f, s) -> s).get())); + geohexGrid(cases, "mv_first", "MvLast", DataType.GEOHEX, (size, values) -> equalTo(values.reduce((f, s) -> s).get())); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(false, cases); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSliceTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSliceTests.java index abecd38cfbba1..a6aa700617f79 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSliceTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSliceTests.java @@ -13,6 +13,11 @@ import org.apache.lucene.util.BytesRef; import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.ShapeTestUtils; +import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.h3.H3; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; +import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.esql.core.InvalidArgumentException; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; @@ -27,6 +32,9 @@ import java.util.function.Supplier; import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomLiteral; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.CARTESIAN; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; import static org.hamcrest.Matchers.equalTo; @@ -52,7 +60,7 @@ public static Iterable parameters() { String evaluatorTypePart = switch (firstArgumentType) { case BOOLEAN -> "Boolean"; case INTEGER -> "Int"; - case LONG, DATE_NANOS, DATETIME, UNSIGNED_LONG -> "Long"; + case LONG, DATE_NANOS, DATETIME, UNSIGNED_LONG, GEOHASH, GEOTILE, GEOHEX -> "Long"; case DOUBLE -> "Double"; case KEYWORD, TEXT, IP, VERSION, GEO_POINT, CARTESIAN_POINT, GEO_SHAPE, CARTESIAN_SHAPE -> "BytesRef"; default -> throw new IllegalArgumentException("Unsupported type: " + firstArgumentType); @@ -210,74 +218,59 @@ private static void ints(List suppliers) { } private static void longs(List suppliers) { - suppliers.add(new TestCaseSupplier(List.of(DataType.LONG, DataType.INTEGER, DataType.INTEGER), () -> { - List field = randomList(1, 10, () -> randomLong()); - int length = field.size(); - int start = randomIntBetween(0, length - 1); - int end = randomIntBetween(start, length - 1); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field, DataType.LONG, "field"), - new TestCaseSupplier.TypedData(start, DataType.INTEGER, "start"), - new TestCaseSupplier.TypedData(end, DataType.INTEGER, "end") - ), - "MvSliceLongEvaluator[field=Attribute[channel=0], start=Attribute[channel=1], end=Attribute[channel=2]]", - DataType.LONG, - equalTo(start == end ? field.get(start) : field.subList(start, end + 1)) - ); - })); + addLongTestCase(suppliers, DataType.LONG, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.DATETIME, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.DATE_NANOS, ESTestCase::randomLong); + for (DataType gridType : new DataType[] { GEOHASH, GEOTILE, GEOHEX }) { + addLongTestCase(suppliers, gridType, () -> randomGrid(gridType)); + } - suppliers.add(new TestCaseSupplier(List.of(DataType.DATETIME, DataType.INTEGER, DataType.INTEGER), () -> { - List field = randomList(1, 10, () -> randomLong()); + suppliers.add(new TestCaseSupplier(List.of(DataType.UNSIGNED_LONG, DataType.INTEGER, DataType.INTEGER), () -> { + List field = randomList(1, 10, () -> randomNonNegativeLong()); + List result = field.stream().map(NumericUtils::unsignedLongAsBigInteger).toList(); int length = field.size(); int start = randomIntBetween(0, length - 1); int end = randomIntBetween(start, length - 1); return new TestCaseSupplier.TestCase( List.of( - new TestCaseSupplier.TypedData(field, DataType.DATETIME, "field"), + new TestCaseSupplier.TypedData(field, DataType.UNSIGNED_LONG, "field"), new TestCaseSupplier.TypedData(start, DataType.INTEGER, "start"), new TestCaseSupplier.TypedData(end, DataType.INTEGER, "end") ), "MvSliceLongEvaluator[field=Attribute[channel=0], start=Attribute[channel=1], end=Attribute[channel=2]]", - DataType.DATETIME, - equalTo(start == end ? field.get(start) : field.subList(start, end + 1)) + DataType.UNSIGNED_LONG, + equalTo(start == end ? result.get(start) : result.subList(start, end + 1)) ); })); + } - suppliers.add(new TestCaseSupplier(List.of(DataType.DATE_NANOS, DataType.INTEGER, DataType.INTEGER), () -> { - List field = randomList(1, 10, () -> randomLong()); + private static void addLongTestCase(List suppliers, DataType dataType, Supplier longSupplier) { + suppliers.add(new TestCaseSupplier(List.of(dataType, DataType.INTEGER, DataType.INTEGER), () -> { + List field = randomList(1, 10, longSupplier); int length = field.size(); int start = randomIntBetween(0, length - 1); int end = randomIntBetween(start, length - 1); return new TestCaseSupplier.TestCase( List.of( - new TestCaseSupplier.TypedData(field, DataType.DATE_NANOS, "field"), + new TestCaseSupplier.TypedData(field, dataType, "field"), new TestCaseSupplier.TypedData(start, DataType.INTEGER, "start"), new TestCaseSupplier.TypedData(end, DataType.INTEGER, "end") ), "MvSliceLongEvaluator[field=Attribute[channel=0], start=Attribute[channel=1], end=Attribute[channel=2]]", - DataType.DATE_NANOS, + dataType, equalTo(start == end ? field.get(start) : field.subList(start, end + 1)) ); })); + } - suppliers.add(new TestCaseSupplier(List.of(DataType.UNSIGNED_LONG, DataType.INTEGER, DataType.INTEGER), () -> { - List field = randomList(1, 10, () -> randomNonNegativeLong()); - List result = field.stream().map(NumericUtils::unsignedLongAsBigInteger).toList(); - int length = field.size(); - int start = randomIntBetween(0, length - 1); - int end = randomIntBetween(start, length - 1); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field, DataType.UNSIGNED_LONG, "field"), - new TestCaseSupplier.TypedData(start, DataType.INTEGER, "start"), - new TestCaseSupplier.TypedData(end, DataType.INTEGER, "end") - ), - "MvSliceLongEvaluator[field=Attribute[channel=0], start=Attribute[channel=1], end=Attribute[channel=2]]", - DataType.UNSIGNED_LONG, - equalTo(start == end ? result.get(start) : result.subList(start, end + 1)) - ); - })); + static long randomGrid(DataType gridType) { + Point point = GeometryTestUtils.randomPoint(); + return switch (gridType) { + case GEOHASH -> Geohash.longEncode(point.getX(), point.getY(), randomIntBetween(1, Geohash.PRECISION)); + case GEOTILE -> GeoTileUtils.longEncode(point.getX(), point.getY(), randomIntBetween(1, GeoTileUtils.MAX_ZOOM)); + case GEOHEX -> H3.geoToH3(point.getLat(), point.getLon(), randomIntBetween(1, H3.MAX_H3_RES)); + default -> throw new IllegalStateException("Invalid grid type: " + gridType); + }; } private static void doubles(List suppliers) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/nulls/CoalesceTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/nulls/CoalesceTests.java index ebbeea3b0e8e4..209cf322b0b9a 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/nulls/CoalesceTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/nulls/CoalesceTests.java @@ -183,14 +183,23 @@ private static TestCaseSupplier.TestCase nullCase(TestCaseSupplier.TestCase dele } protected static void addSpatialCombinations(List suppliers) { - for (DataType dataType : List.of(DataType.GEO_POINT, DataType.GEO_SHAPE, DataType.CARTESIAN_POINT, DataType.CARTESIAN_SHAPE)) { + for (DataType dataType : List.of( + DataType.GEO_POINT, + DataType.GEO_SHAPE, + DataType.CARTESIAN_POINT, + DataType.CARTESIAN_SHAPE, + DataType.GEOHASH, + DataType.GEOTILE, + DataType.GEOHEX + )) { + String blockType = DataType.isGeoGrid(dataType) ? "Long" : "BytesRef"; TestCaseSupplier.TypedDataSupplier leftDataSupplier = SpatialRelatesFunctionTestCase.testCaseSupplier(dataType, false); TestCaseSupplier.TypedDataSupplier rightDataSupplier = SpatialRelatesFunctionTestCase.testCaseSupplier(dataType, false); suppliers.add( TestCaseSupplier.testCaseSupplier( leftDataSupplier, rightDataSupplier, - (l, r) -> equalTo("CoalesceBytesRefEagerEvaluator[values=[Attribute[channel=0], Attribute[channel=1]]]"), + (l, r) -> equalTo("Coalesce" + blockType + "EagerEvaluator[values=[Attribute[channel=0], Attribute[channel=1]]]"), dataType, (l, r) -> l ) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/BinarySpatialFunctionTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/BinarySpatialFunctionTestCase.java index 68dd600489393..1f53ea4d9a72c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/BinarySpatialFunctionTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/BinarySpatialFunctionTestCase.java @@ -28,6 +28,9 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; import static org.elasticsearch.xpack.esql.core.type.DataType.isSpatial; import static org.elasticsearch.xpack.esql.core.type.DataType.isSpatialGeo; import static org.elasticsearch.xpack.esql.core.type.DataType.isString; @@ -49,17 +52,20 @@ protected static Class> getSpatialRelatesFunctionClass() throws ClassNotFoundE 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); + return switch (dataType) { + 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); + return switch (dataType) { + 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); + case GEOHASH -> TestCaseSupplier.geoGridCases(GEOHASH, () -> false).get(0); + case GEOTILE -> TestCaseSupplier.geoGridCases(GEOTILE, () -> false).get(0); + case GEOHEX -> TestCaseSupplier.geoGridCases(GEOHEX, () -> 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/SpatialGridFunctionTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunctionTestCase.java index 0d4eaf6e826d9..d25e98abefd7e 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 @@ -26,7 +26,6 @@ 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.type.DataType.LONG; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; import static org.hamcrest.Matchers.containsString; @@ -70,6 +69,7 @@ private static String getFunctionClassName() { protected static void addTestCaseSuppliers( List suppliers, DataType[] dataTypes, + DataType gridType, BiFunction expectedValue, TriFunction expectedValueWithBounds ) { @@ -91,7 +91,7 @@ protected static void addTestCaseSuppliers( return new TestCaseSupplier.TestCase( List.of(geoTypedData, precisionData), getFunctionClassName() + evaluatorName, - LONG, + gridType, equalTo(expectedValue.apply(geometry, precision)) ); })); @@ -111,7 +111,7 @@ protected static void addTestCaseSuppliers( return new TestCaseSupplier.TestCase( List.of(geoTypedData, precisionData, boundsData.typedData), startsWith(getFunctionClassName() + evaluatorName), - LONG, + gridType, equalTo(expectedValueWithBounds.apply(geometry, precision, boundsData.geoBoundingBox())) ); })); @@ -121,17 +121,17 @@ protected static void addTestCaseSuppliers( public static TestCaseSupplier.TypedDataSupplier testCaseSupplier(DataType dataType, boolean pointsOnly) { if (pointsOnly) { - return switch (dataType.esType()) { - case "geo_point" -> TestCaseSupplier.geoPointCases(() -> false).getFirst(); - case "cartesian_point" -> TestCaseSupplier.cartesianPointCases(() -> false).getFirst(); + return switch (dataType) { + case GEO_POINT -> TestCaseSupplier.geoPointCases(() -> false).getFirst(); + case CARTESIAN_POINT -> TestCaseSupplier.cartesianPointCases(() -> false).getFirst(); default -> throw new IllegalArgumentException("Unsupported datatype for " + functionName() + ": " + dataType); }; } else { - return switch (dataType.esType()) { - case "geo_point" -> TestCaseSupplier.geoPointCases(() -> false).getFirst(); - case "geo_shape" -> TestCaseSupplier.geoShapeCases(() -> false).getFirst(); - case "cartesian_point" -> TestCaseSupplier.cartesianPointCases(() -> false).getFirst(); - case "cartesian_shape" -> TestCaseSupplier.cartesianShapeCases(() -> false).getFirst(); + return switch (dataType) { + case GEO_POINT -> TestCaseSupplier.geoPointCases(() -> false).getFirst(); + case GEO_SHAPE -> TestCaseSupplier.geoShapeCases(() -> false).getFirst(); + case CARTESIAN_POINT -> TestCaseSupplier.cartesianPointCases(() -> false).getFirst(); + case CARTESIAN_SHAPE -> TestCaseSupplier.cartesianShapeCases(() -> false).getFirst(); 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/StGeohashTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java index 185591df91b4d..eba240d1a1973 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 @@ -23,6 +23,8 @@ import java.util.List; import java.util.function.Supplier; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; import static org.hamcrest.Matchers.containsString; @@ -42,7 +44,7 @@ public static License.OperationMode licenseRequirement(List fieldTypes @ParametersFactory public static Iterable parameters() { final List suppliers = new ArrayList<>(); - addTestCaseSuppliers(suppliers, new DataType[] { DataType.GEO_POINT }, StGeohashTests::valueOf, StGeohashTests::boundedValueOf); + addTestCaseSuppliers(suppliers, new DataType[] { GEO_POINT }, GEOHASH, StGeohashTests::valueOf, StGeohashTests::boundedValueOf); 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 deleted file mode 100644 index 58feda75a8ab9..0000000000000 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.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.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.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeohashToStringTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "Attribute[channel=0]", - KEYWORD, - g -> new BytesRef(Geohash.stringEncode(StGeohash.unboundedGrid.calculateGridId(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 index f52241806a3be..1e3319e1bf12e 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 @@ -23,6 +23,8 @@ import java.util.List; import java.util.function.Supplier; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; import static org.hamcrest.Matchers.containsString; @@ -42,7 +44,7 @@ public static License.OperationMode licenseRequirement(List fieldTypes @ParametersFactory public static Iterable parameters() { final List suppliers = new ArrayList<>(); - addTestCaseSuppliers(suppliers, new DataType[] { DataType.GEO_POINT }, StGeohexTests::valueOf, StGeohexTests::boundedValueOf); + addTestCaseSuppliers(suppliers, new DataType[] { GEO_POINT }, GEOHEX, StGeohexTests::valueOf, StGeohexTests::boundedValueOf); 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 deleted file mode 100644 index bf3c734869330..0000000000000 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringTests.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.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.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeohexToStringTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "Attribute[channel=0]", - KEYWORD, - g -> new BytesRef(H3.h3ToString(StGeohex.unboundedGrid.calculateGridId(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 index 5661f1eacf533..6c8582489e767 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 @@ -23,6 +23,8 @@ import java.util.function.Supplier; import static org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils.MAX_ZOOM; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; import static org.hamcrest.Matchers.containsString; @@ -39,10 +41,11 @@ public static License.OperationMode licenseRequirement(List fieldTypes return SpatialGridFunctionTestCase.licenseRequirement(fieldTypes); } + @SuppressWarnings("checkstyle:LineLength") @ParametersFactory public static Iterable parameters() { final List suppliers = new ArrayList<>(); - addTestCaseSuppliers(suppliers, new DataType[] { DataType.GEO_POINT }, StGeotileTests::valueOf, StGeotileTests::boundedValueOf); + addTestCaseSuppliers(suppliers, new DataType[] { GEO_POINT }, GEOTILE, StGeotileTests::valueOf, StGeotileTests::boundedValueOf); 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 deleted file mode 100644 index fd558887c0fda..0000000000000 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringTests.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.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.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeotileToStringTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "Attribute[channel=0]", - KEYWORD, - g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.unboundedGrid.calculateGridId(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)); - } -} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/CastOperatorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/CastOperatorTests.java index 40cb11ea511f0..8ed52cb50a898 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/CastOperatorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/CastOperatorTests.java @@ -72,6 +72,9 @@ public TestCastOperator( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EqualsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EqualsTests.java index 4b9f21187f425..410919ac0fad5 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EqualsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EqualsTests.java @@ -236,6 +236,22 @@ public static Iterable parameters() { ) ); + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + suppliers.addAll( + TestCaseSupplier.forBinaryNotCasting( + "EqualsLongsEvaluator", + "lhs", + "rhs", + Object::equals, + DataType.BOOLEAN, + TestCaseSupplier.geoGridCases(gridType), + TestCaseSupplier.geoGridCases(gridType), + List.of(), + false + ) + ); + } + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/NotEqualsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/NotEqualsTests.java index 95001366f1cad..f7646489419c3 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/NotEqualsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/NotEqualsTests.java @@ -233,6 +233,22 @@ public static Iterable parameters() { ) ); + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + suppliers.addAll( + TestCaseSupplier.forBinaryNotCasting( + "NotEqualsLongsEvaluator", + "lhs", + "rhs", + (l, r) -> false == l.equals(r), + DataType.BOOLEAN, + TestCaseSupplier.geoGridCases(gridType), + TestCaseSupplier.geoGridCases(gridType), + List.of(), + false + ) + ); + } + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); }
diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java index 863a8cc5f255b..b4aafef8fa467 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java @@ -51,6 +51,9 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.geoPointCases(1, 1000, IncludingAltitude.YES), MultiRowTestCaseSupplier.geoShapeCasesWithoutCircle(1, 1000, IncludingAltitude.YES), MultiRowTestCaseSupplier.cartesianShapeCasesWithoutCircle(1, 1000, IncludingAltitude.YES), + MultiRowTestCaseSupplier.geohashCases(1, 1000), + MultiRowTestCaseSupplier.geotileCases(1, 1000), + MultiRowTestCaseSupplier.geohexCases(1, 1000), MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.KEYWORD), MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.TEXT) ).flatMap(List::stream).map(CountTests::makeSupplier).collect(Collectors.toCollection(() -> suppliers)); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SampleTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SampleTests.java index 8b66da40ddb27..e61447a65a820 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SampleTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/SampleTests.java @@ -59,7 +59,10 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.geoPointCases(1, 1000, MultiRowTestCaseSupplier.IncludingAltitude.NO), MultiRowTestCaseSupplier.cartesianPointCases(1, 1000, MultiRowTestCaseSupplier.IncludingAltitude.NO), MultiRowTestCaseSupplier.geoShapeCasesWithoutCircle(1, 20, MultiRowTestCaseSupplier.IncludingAltitude.NO), - MultiRowTestCaseSupplier.cartesianShapeCasesWithoutCircle(1, 20, MultiRowTestCaseSupplier.IncludingAltitude.NO) + MultiRowTestCaseSupplier.cartesianShapeCasesWithoutCircle(1, 20, MultiRowTestCaseSupplier.IncludingAltitude.NO), + MultiRowTestCaseSupplier.geohashCases(1, 1000), + MultiRowTestCaseSupplier.geotileCases(1, 1000), + MultiRowTestCaseSupplier.geohexCases(1, 1000) ) .flatMap(List::stream) .map(fieldCaseSupplier -> makeSupplier(fieldCaseSupplier, limitCaseSupplier)) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesTests.java index f386f623e17dc..f23ff3c715ca4 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesTests.java @@ -59,7 +59,10 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.geoPointCases(1, 1000, MultiRowTestCaseSupplier.IncludingAltitude.NO), MultiRowTestCaseSupplier.cartesianPointCases(1, 1000, MultiRowTestCaseSupplier.IncludingAltitude.NO), MultiRowTestCaseSupplier.geoShapeCasesWithoutCircle(1, 20, MultiRowTestCaseSupplier.IncludingAltitude.NO), - MultiRowTestCaseSupplier.cartesianShapeCasesWithoutCircle(1, 20, MultiRowTestCaseSupplier.IncludingAltitude.NO) + MultiRowTestCaseSupplier.cartesianShapeCasesWithoutCircle(1, 20, MultiRowTestCaseSupplier.IncludingAltitude.NO), + MultiRowTestCaseSupplier.geohashCases(1, 100), + MultiRowTestCaseSupplier.geotileCases(1, 100), + MultiRowTestCaseSupplier.geohexCases(1, 100) ).flatMap(List::stream).map(ValuesTests::makeSupplier).collect(Collectors.toCollection(() -> suppliers)); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(suppliers, false); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseTests.java index 8d3b214f97a63..a538f17969bce 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseTests.java @@ -56,6 +56,9 @@ public class CaseTests extends AbstractScalarFunctionTestCase { DataType.GEO_POINT, DataType.CARTESIAN_SHAPE, DataType.GEO_SHAPE, + DataType.GEOHASH, + DataType.GEOTILE, + DataType.GEOHEX, DataType.NULL ).collect(Collectors.toList()); if (Build.current().isSnapshot()) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeErrorTests.java index 9e6f81e649d84..3b689323990dc 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeErrorTests.java @@ -32,6 +32,7 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { - return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "geo_point or geo_shape or string")); + String expectedTypes = "geo_point or geo_shape or geohash or geohex or geotile or string"; + return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> expectedTypes)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeTests.java index 5b75bded802de..a2148a61f4fb1 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeoShapeTests.java @@ -18,6 +18,7 @@ import org.elasticsearch.xpack.esql.expression.function.AbstractScalarFunctionTestCase; import org.elasticsearch.xpack.esql.expression.function.FunctionName; import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; +import org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter; import java.util.ArrayList; import java.util.List; @@ -39,8 +40,20 @@ public static Iterable parameters() { final Function evaluatorName = s -> "ToGeoShape" + s + "Evaluator[in=" + attribute + "]"; final List suppliers = new ArrayList<>(); + // Points and shapes TestCaseSupplier.forUnaryGeoPoint(suppliers, attribute, DataType.GEO_SHAPE, v -> v, List.of()); TestCaseSupplier.forUnaryGeoShape(suppliers, attribute, DataType.GEO_SHAPE, v -> v, List.of()); + // Geo-Grid types + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + TestCaseSupplier.forUnaryGeoGrid( + suppliers, + "ToGeoShapeFromGeoGridEvaluator[in=Attribute[channel=0], dataType=" + gridType + "]", + gridType, + DataType.GEO_SHAPE, + v -> EsqlDataTypeConverter.geoGridToShape((long) v, gridType), + List.of() + ); + } // random strings that don't look like a geo shape TestCaseSupplier.forUnaryStrings(suppliers, evaluatorName.apply("FromString"), DataType.GEO_SHAPE, bytesRef -> null, bytesRef -> { var exception = expectThrows(Exception.class, () -> GEO.wktToWkb(bytesRef.utf8ToString())); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashErrorTests.java new file mode 100644 index 0000000000000..aefe38d0f8685 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashErrorTests.java @@ -0,0 +1,37 @@ +/* + * 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.convert; + +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 ToGeohashErrorTests extends ErrorsForCasesWithoutExamplesTestCase { + @Override + protected List cases() { + return paramsToSuppliers(ToGeohashTests.parameters()); + } + + @Override + protected Expression build(Source source, List args) { + return new ToGeohash(source, args.get(0)); + } + + @Override + protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "geohash or long or string")); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashSerializationTests.java new file mode 100644 index 0000000000000..244094a627589 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToGeohashSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToGeohash create(Source source, Expression child) { + return new ToGeohash(source, child); + } +} 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/convert/ToGeohashTests.java similarity index 53% rename from x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToLongTests.java rename to x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohashTests.java index fab3655677774..d9c0be69ac42a 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/convert/ToGeohashTests.java @@ -5,7 +5,7 @@ * 2.0. */ -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; @@ -15,6 +15,7 @@ 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.AbstractScalarFunctionTestCase; import org.elasticsearch.xpack.esql.expression.function.FunctionName; import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; @@ -22,42 +23,33 @@ 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) { +@FunctionName("to_geohash") +public class ToGeohashTests extends AbstractScalarFunctionTestCase { + public ToGeohashTests(@Name("TestCase") Supplier testCaseSupplier) { this.testCase = testCaseSupplier.get(); } @ParametersFactory public static Iterable parameters() { + final String attribute = "Attribute[channel=0]"; + final String evaluator = "ToGeohashFromStringEvaluator[in=Attribute[channel=0]]"; final List suppliers = new ArrayList<>(); - forUnaryGeoPoint( - DataType.LONG, - suppliers, - "Attribute[channel=0]", - DataType.LONG, - g -> StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeohashToLongTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "StGeohashToLongFromStringEvaluator[gridId=Attribute[channel=0]]", - DataType.LONG, - g -> new BytesRef(Geohash.stringEncode(StGeohash.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), - StGeohashToLongTests::valueOf - ); + + TestCaseSupplier.forUnaryGeoGrid(suppliers, attribute, DataType.GEOHASH, DataType.GEOHASH, v -> v, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, attribute, DataType.LONG, DataType.GEOHASH, v -> v, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, evaluator, DataType.KEYWORD, DataType.GEOHASH, ToGeohashTests::valueOf, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, evaluator, DataType.TEXT, DataType.GEOHASH, ToGeohashTests::valueOf, List.of()); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } - private static long valueOf(Object gridid) { - return (gridid instanceof Long hash) ? hash : Geohash.longEncode(((BytesRef) gridid).utf8ToString()); + private static long valueOf(Object gridAddress) { + assert gridAddress instanceof BytesRef; + return Geohash.longEncode(((BytesRef) gridAddress).utf8ToString()); } @Override protected Expression build(Source source, List args) { - return new StGeohashToLong(source, args.get(0)); + return new ToGeohash(source, args.get(0)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexSerializationTests.java new file mode 100644 index 0000000000000..a76c8e4a1e535 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToGeohexSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToGeohex create(Source source, Expression child) { + return new ToGeohex(source, child); + } +} 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/convert/ToGeohexTests.java similarity index 53% rename from x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToLongTests.java rename to x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexTests.java index 7c28fdb551079..75eefec4b3c96 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/convert/ToGeohexTests.java @@ -5,7 +5,7 @@ * 2.0. */ -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; @@ -15,6 +15,7 @@ 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.AbstractScalarFunctionTestCase; import org.elasticsearch.xpack.esql.expression.function.FunctionName; import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; @@ -22,42 +23,33 @@ 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) { +@FunctionName("to_geohex") +public class ToGeohexTests extends AbstractScalarFunctionTestCase { + public ToGeohexTests(@Name("TestCase") Supplier testCaseSupplier) { this.testCase = testCaseSupplier.get(); } @ParametersFactory public static Iterable parameters() { + final String attribute = "Attribute[channel=0]"; + final String evaluator = "ToGeohexFromStringEvaluator[in=Attribute[channel=0]]"; final List suppliers = new ArrayList<>(); - forUnaryGeoPoint( - DataType.LONG, - suppliers, - "Attribute[channel=0]", - DataType.LONG, - g -> StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeohexToLongTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "StGeohexToLongFromStringEvaluator[gridId=Attribute[channel=0]]", - DataType.LONG, - g -> new BytesRef(H3.h3ToString(StGeohex.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), - StGeohexToLongTests::valueOf - ); + + TestCaseSupplier.forUnaryGeoGrid(suppliers, attribute, DataType.GEOHEX, DataType.GEOHEX, v -> v, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, attribute, DataType.LONG, DataType.GEOHEX, v -> v, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, evaluator, DataType.KEYWORD, DataType.GEOHEX, ToGeohexTests::valueOf, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, evaluator, DataType.TEXT, DataType.GEOHEX, ToGeohexTests::valueOf, List.of()); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } - private static long valueOf(Object gridid) { - return (gridid instanceof Long hash) ? hash : H3.stringToH3(((BytesRef) gridid).utf8ToString()); + private static long valueOf(Object gridAddress) { + assert gridAddress instanceof BytesRef; + return H3.stringToH3(((BytesRef) gridAddress).utf8ToString()); } @Override protected Expression build(Source source, List args) { - return new StGeohexToLong(source, args.get(0)); + return new ToGeohex(source, args.get(0)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexhErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexhErrorTests.java new file mode 100644 index 0000000000000..24e2521731bde --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeohexhErrorTests.java @@ -0,0 +1,37 @@ +/* + * 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.convert; + +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 ToGeohexhErrorTests extends ErrorsForCasesWithoutExamplesTestCase { + @Override + protected List cases() { + return paramsToSuppliers(ToGeohexTests.parameters()); + } + + @Override + protected Expression build(Source source, List args) { + return new ToGeohex(source, args.get(0)); + } + + @Override + protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "geohex or long or string")); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileErrorTests.java new file mode 100644 index 0000000000000..9696b7399e830 --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileErrorTests.java @@ -0,0 +1,37 @@ +/* + * 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.convert; + +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 ToGeotileErrorTests extends ErrorsForCasesWithoutExamplesTestCase { + @Override + protected List cases() { + return paramsToSuppliers(ToGeotileTests.parameters()); + } + + @Override + protected Expression build(Source source, List args) { + return new ToGeotile(source, args.get(0)); + } + + @Override + protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { + return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "geotile or long or string")); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileSerializationTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileSerializationTests.java new file mode 100644 index 0000000000000..dc6838a96343d --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileSerializationTests.java @@ -0,0 +1,19 @@ +/* + * 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.convert; + +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.AbstractUnaryScalarSerializationTests; + +public class ToGeotileSerializationTests extends AbstractUnaryScalarSerializationTests { + @Override + protected ToGeotile create(Source source, Expression child) { + return new ToGeotile(source, child); + } +} 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/convert/ToGeotileTests.java similarity index 53% rename from x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToLongTests.java rename to x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToGeotileTests.java index 1f43536719fd8..49776099ada9f 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/convert/ToGeotileTests.java @@ -5,7 +5,7 @@ * 2.0. */ -package org.elasticsearch.xpack.esql.expression.function.scalar.spatial; +package org.elasticsearch.xpack.esql.expression.function.scalar.convert; import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; @@ -15,6 +15,7 @@ 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.AbstractScalarFunctionTestCase; import org.elasticsearch.xpack.esql.expression.function.FunctionName; import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; @@ -22,42 +23,33 @@ 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) { +@FunctionName("to_geotile") +public class ToGeotileTests extends AbstractScalarFunctionTestCase { + public ToGeotileTests(@Name("TestCase") Supplier testCaseSupplier) { this.testCase = testCaseSupplier.get(); } @ParametersFactory public static Iterable parameters() { + final String attribute = "Attribute[channel=0]"; + final String evaluator = "ToGeotileFromStringEvaluator[in=Attribute[channel=0]]"; final List suppliers = new ArrayList<>(); - forUnaryGeoPoint( - DataType.LONG, - suppliers, - "Attribute[channel=0]", - DataType.LONG, - g -> StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeotileToLongTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "StGeotileToLongFromStringEvaluator[gridId=Attribute[channel=0]]", - DataType.LONG, - g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2))), - StGeotileToLongTests::valueOf - ); + + TestCaseSupplier.forUnaryGeoGrid(suppliers, attribute, DataType.GEOTILE, DataType.GEOTILE, v -> v, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, attribute, DataType.LONG, DataType.GEOTILE, v -> v, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, evaluator, DataType.KEYWORD, DataType.GEOTILE, ToGeotileTests::valueOf, List.of()); + TestCaseSupplier.forUnaryGeoGrid(suppliers, evaluator, DataType.TEXT, DataType.GEOTILE, ToGeotileTests::valueOf, List.of()); + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } - private static long valueOf(Object gridid) { - return (gridid instanceof Long hash) ? hash : GeoTileUtils.longEncode(((BytesRef) gridid).utf8ToString()); + private static long valueOf(Object gridAddress) { + assert gridAddress instanceof BytesRef; + return GeoTileUtils.longEncode(((BytesRef) gridAddress).utf8ToString()); } @Override protected Expression build(Source source, List args) { - return new StGeotileToLong(source, args.get(0)); + return new ToGeotile(source, args.get(0)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongErrorTests.java index cc93e4f050796..4c387c545f6f6 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongErrorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongErrorTests.java @@ -32,13 +32,8 @@ protected Expression build(Source source, List args) { @Override protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { - return equalTo( - typeErrorMessage( - false, - validPerPosition, - signature, - (v, p) -> "boolean or counter_integer or counter_long or date_nanos or datetime or numeric or string" - ) - ); + String expectedTypes = + "boolean or counter_integer or counter_long or date_nanos or datetime or geohash or geohex or geotile or numeric or string"; + return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> expectedTypes)); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongTests.java index 50748d582ed1f..b7925fce6b496 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToLongTests.java @@ -241,6 +241,11 @@ public static Iterable parameters() { l -> ((Integer) l).longValue(), List.of() ); + + // Geo-Grid types + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + TestCaseSupplier.forUnaryGeoGrid(suppliers, read, gridType, DataType.LONG, v -> v, List.of()); + } return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringTests.java index f766deb2e1686..8d8f59b78114d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToStringTests.java @@ -19,6 +19,7 @@ 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 org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter; import java.math.BigInteger; import java.time.Instant; @@ -141,6 +142,17 @@ public static Iterable parameters() { v -> new BytesRef(v.toString()), List.of() ); + // Geo-Grid types + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + TestCaseSupplier.forUnaryGeoGrid( + suppliers, + "ToStringFromGeoGridEvaluator[gridId=Attribute[channel=0], dataType=" + gridType + "]", + gridType, + DataType.KEYWORD, + v -> new BytesRef(EsqlDataTypeConverter.geoGridToString((long) v, gridType)), + List.of() + ); + } return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/AbstractMultivalueFunctionTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/AbstractMultivalueFunctionTestCase.java index c57847a5daea9..dfa0dc786474c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/AbstractMultivalueFunctionTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/AbstractMultivalueFunctionTestCase.java @@ -12,6 +12,10 @@ import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.ShapeTestUtils; import org.elasticsearch.geometry.Geometry; +import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.h3.H3; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; @@ -571,6 +575,98 @@ protected static void spatial( } } + /** + * Build many test cases with {@code geohash} values that are converted to another type. + * This assumes that the function consumes {@code geohash} values and produces another type. + * For example, mv_count() can consume geo-grid values and produce an integer count. + */ + protected static void geohashGrid( + List cases, + String name, + String evaluatorName, + DataType expectedDataType, + BiFunction, Matcher> matcher + ) { + Supplier supplier = () -> { + Point point = GeometryTestUtils.randomPoint(); + return Geohash.longEncode(point.getX(), point.getY(), randomIntBetween(1, Geohash.PRECISION)); + }; + spatialGrid(cases, name, evaluatorName, DataType.GEOHASH, expectedDataType, supplier, matcher); + } + + /** + * Build many test cases with {@code geotile} values that are converted to another type. + * This assumes that the function consumes {@code geotile} values and produces another type. + * For example, mv_count() can consume geo-grid values and produce an integer count. + */ + protected static void geotileGrid( + List cases, + String name, + String evaluatorName, + DataType expectedDataType, + BiFunction, Matcher> matcher + ) { + Supplier supplier = () -> { + Point point = GeometryTestUtils.randomPoint(); + return GeoTileUtils.longEncode(point.getX(), point.getY(), randomIntBetween(1, GeoTileUtils.MAX_ZOOM)); + }; + spatialGrid(cases, name, evaluatorName, DataType.GEOTILE, expectedDataType, supplier, matcher); + } + + /** + * Build many test cases with {@code geohex} values that are converted to another type. + * This assumes that the function consumes {@code geohex} values and produces another type. + * For example, mv_count() can consume geo-grid values and produce an integer count. + */ + protected static void geohexGrid( + List cases, + String name, + String evaluatorName, + DataType expectedDataType, + BiFunction, Matcher> matcher + ) { + Supplier supplier = () -> { + Point point = GeometryTestUtils.randomPoint(); + return H3.geoToH3(point.getLat(), point.getLon(), randomIntBetween(1, H3.MAX_H3_RES)); + }; + spatialGrid(cases, name, evaluatorName, DataType.GEOHEX, expectedDataType, supplier, matcher); + } + + /** + * Build many test cases for spatial grid values + */ + protected static void spatialGrid( + List cases, + String name, + String evaluatorName, + DataType dataType, + DataType expectedDataType, + Supplier randomGridId, + BiFunction, Matcher> matcher + ) { + cases.add(new TestCaseSupplier(name + "(" + dataType.typeName() + ")", List.of(dataType), () -> { + long gridId = randomGridId.get(); + return new TestCaseSupplier.TestCase( + List.of(new TestCaseSupplier.TypedData(List.of(gridId), dataType, "field")), + evaluatorName + "[field=Attribute[channel=0]]", + expectedDataType, + matcher.apply(1, Stream.of(gridId)) + ); + })); + for (Block.MvOrdering ordering : Block.MvOrdering.values()) { + cases.add(new TestCaseSupplier(name + "(<" + dataType.typeName() + "s>) " + ordering, List.of(dataType), () -> { + List mvData = randomList(1, 100, randomGridId); + putInOrder(mvData, ordering); + return new TestCaseSupplier.TestCase( + List.of(new TestCaseSupplier.TypedData(mvData, dataType, "field")), + evaluatorName + "[field=Attribute[channel=0]]", + expectedDataType, + matcher.apply(mvData.size(), mvData.stream()) + ); + })); + } + } + /** * Build many test cases with unsigned {@code long} values. */ diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendTests.java index c0c14499fa744..d485d990693b1 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvAppendTests.java @@ -29,6 +29,7 @@ import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomLiteral; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.CARTESIAN; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; +import static org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvSliceTests.randomGrid; import static org.hamcrest.Matchers.equalTo; public class MvAppendTests extends AbstractScalarFunctionTestCase { @@ -89,21 +90,13 @@ private static void ints(List suppliers) { } private static void longs(List suppliers) { - suppliers.add(new TestCaseSupplier(List.of(DataType.LONG, DataType.LONG), () -> { - List field1 = randomList(1, 10, () -> randomLong()); - List field2 = randomList(1, 10, () -> randomLong()); - var result = new ArrayList<>(field1); - result.addAll(field2); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field1, DataType.LONG, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.LONG, "field2") - ), - "MvAppendLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", - DataType.LONG, - equalTo(result) - ); - })); + addLongTestCase(suppliers, DataType.LONG, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.DATETIME, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.DATE_NANOS, ESTestCase::randomNonNegativeLong); + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + addLongTestCase(suppliers, gridType, () -> randomGrid(gridType)); + } + suppliers.add(new TestCaseSupplier(List.of(DataType.UNSIGNED_LONG, DataType.UNSIGNED_LONG), () -> { List field1 = randomList(1, 10, ESTestCase::randomLong); List field2 = randomList(1, 10, ESTestCase::randomLong); @@ -118,33 +111,21 @@ private static void longs(List suppliers) { equalTo(result) ); })); - suppliers.add(new TestCaseSupplier(List.of(DataType.DATETIME, DataType.DATETIME), () -> { - List field1 = randomList(1, 10, () -> randomLong()); - List field2 = randomList(1, 10, () -> randomLong()); - var result = new ArrayList<>(field1); - result.addAll(field2); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field1, DataType.DATETIME, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.DATETIME, "field2") - ), - "MvAppendLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", - DataType.DATETIME, - equalTo(result) - ); - })); - suppliers.add(new TestCaseSupplier(List.of(DataType.DATE_NANOS, DataType.DATE_NANOS), () -> { - List field1 = randomList(1, 10, () -> randomNonNegativeLong()); - List field2 = randomList(1, 10, () -> randomNonNegativeLong()); + } + + private static void addLongTestCase(List suppliers, DataType dataType, Supplier longSupplier) { + suppliers.add(new TestCaseSupplier(List.of(dataType, dataType), () -> { + List field1 = randomList(1, 10, longSupplier); + List field2 = randomList(1, 10, longSupplier); var result = new ArrayList<>(field1); result.addAll(field2); return new TestCaseSupplier.TestCase( List.of( - new TestCaseSupplier.TypedData(field1, DataType.DATE_NANOS, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.DATE_NANOS, "field2") + new TestCaseSupplier.TypedData(field1, dataType, "field1"), + new TestCaseSupplier.TypedData(field2, dataType, "field2") ), "MvAppendLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", - DataType.DATE_NANOS, + dataType, equalTo(result) ); })); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsTests.java index 57da6d5c2fe9a..7b833ba86e00d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvContainsTests.java @@ -35,6 +35,7 @@ import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; import static org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier.TypedData.MULTI_ROW_NULL; import static org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier.TypedData.NULL; +import static org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvSliceTests.randomGrid; import static org.hamcrest.Matchers.equalTo; public class MvContainsTests extends AbstractScalarFunctionTestCase { @@ -100,56 +101,24 @@ private static void ints(List suppliers) { } private static void longs(List suppliers) { - suppliers.add(new TestCaseSupplier(List.of(DataType.LONG, DataType.LONG), () -> { - List field1 = randomList(1, 10, ESTestCase::randomLong); - List field2 = randomList(1, 10, ESTestCase::randomLong); - var result = field1.containsAll(field2); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field1, DataType.LONG, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.LONG, "field2") - ), - "MvContainsLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", - DataType.BOOLEAN, - equalTo(result) - ); - })); - suppliers.add(new TestCaseSupplier(List.of(DataType.UNSIGNED_LONG, DataType.UNSIGNED_LONG), () -> { - List field1 = randomList(1, 10, ESTestCase::randomLong); - List field2 = randomList(1, 10, ESTestCase::randomLong); - var result = field1.containsAll(field2); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field1, DataType.UNSIGNED_LONG, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.UNSIGNED_LONG, "field2") - ), - "MvContainsLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", - DataType.BOOLEAN, - equalTo(result) - ); - })); - suppliers.add(new TestCaseSupplier(List.of(DataType.DATETIME, DataType.DATETIME), () -> { - List field1 = randomList(1, 10, ESTestCase::randomLong); - List field2 = randomList(1, 10, ESTestCase::randomLong); - var result = field1.containsAll(field2); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field1, DataType.DATETIME, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.DATETIME, "field2") - ), - "MvContainsLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", - DataType.BOOLEAN, - equalTo(result) - ); - })); - suppliers.add(new TestCaseSupplier(List.of(DataType.DATE_NANOS, DataType.DATE_NANOS), () -> { - List field1 = randomList(1, 10, ESTestCase::randomNonNegativeLong); - List field2 = randomList(1, 10, ESTestCase::randomNonNegativeLong); + addLongTestCase(suppliers, DataType.LONG, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.UNSIGNED_LONG, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.DATETIME, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.DATE_NANOS, ESTestCase::randomNonNegativeLong); + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + addLongTestCase(suppliers, gridType, () -> randomGrid(gridType)); + } + } + + private static void addLongTestCase(List suppliers, DataType dataType, Supplier longSupplier) { + suppliers.add(new TestCaseSupplier(List.of(dataType, dataType), () -> { + List field1 = randomList(1, 10, longSupplier); + List field2 = randomList(1, 10, longSupplier); var result = field1.containsAll(field2); return new TestCaseSupplier.TestCase( List.of( - new TestCaseSupplier.TypedData(field1, DataType.DATE_NANOS, "field1"), - new TestCaseSupplier.TypedData(field2, DataType.DATE_NANOS, "field2") + new TestCaseSupplier.TypedData(field1, dataType, "field1"), + new TestCaseSupplier.TypedData(field2, dataType, "field2") ), "MvContainsLongEvaluator[field1=Attribute[channel=0], field2=Attribute[channel=1]]", DataType.BOOLEAN, diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountTests.java index 6aeab0339c172..a1bcca42a8d93 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvCountTests.java @@ -41,6 +41,9 @@ public static Iterable parameters() { cartesianPoints(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count()))); geoShape(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count()))); cartesianShape(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count()))); + geohashGrid(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count()))); + geotileGrid(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count()))); + geohexGrid(cases, "mv_count", "MvCount", DataType.INTEGER, (size, values) -> equalTo(Math.toIntExact(values.count()))); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, cases); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeTests.java index 24fd0a349796c..78e51b802c191 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvDedupeTests.java @@ -47,6 +47,9 @@ public static Iterable parameters() { cartesianShape(cases, "mv_dedupe", "MvDedupe", DataType.CARTESIAN_SHAPE, (size, values) -> getMatcher(values)); geoPoints(cases, "mv_dedupe", "MvDedupe", (size, values) -> getMatcher(values)); geoShape(cases, "mv_dedupe", "MvDedupe", DataType.GEO_SHAPE, (size, values) -> getMatcher(values)); + geohashGrid(cases, "mv_dedupe", "MvDedupe", DataType.GEOHASH, (size, values) -> getMatcher(values)); + geotileGrid(cases, "mv_dedupe", "MvDedupe", DataType.GEOTILE, (size, values) -> getMatcher(values)); + geohexGrid(cases, "mv_dedupe", "MvDedupe", DataType.GEOHEX, (size, values) -> getMatcher(values)); unsignedLongs(cases, "mv_dedupe", "MvDedupe", (size, values) -> getMatcher(values)); return parameterSuppliersFromTypedData(anyNullIsNull(false, cases)); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstTests.java index 3ee98364141c6..5d0a4b4b43cda 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvFirstTests.java @@ -42,6 +42,9 @@ public static Iterable parameters() { cartesianPoints(cases, "mv_first", "MvFirst", DataType.CARTESIAN_POINT, (size, values) -> equalTo(values.findFirst().get())); geoShape(cases, "mv_first", "MvFirst", DataType.GEO_SHAPE, (size, values) -> equalTo(values.findFirst().get())); cartesianShape(cases, "mv_first", "MvFirst", DataType.CARTESIAN_SHAPE, (size, values) -> equalTo(values.findFirst().get())); + geohashGrid(cases, "mv_first", "MvFirst", DataType.GEOHASH, (size, values) -> equalTo(values.findFirst().get())); + geotileGrid(cases, "mv_first", "MvFirst", DataType.GEOTILE, (size, values) -> equalTo(values.findFirst().get())); + geohexGrid(cases, "mv_first", "MvFirst", DataType.GEOHEX, (size, values) -> equalTo(values.findFirst().get())); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(false, cases); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastTests.java index a7a13360ce443..a725b03c860f5 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvLastTests.java @@ -42,6 +42,9 @@ public static Iterable parameters() { cartesianPoints(cases, "mv_last", "MvLast", DataType.CARTESIAN_POINT, (size, values) -> equalTo(values.reduce((f, s) -> s).get())); geoShape(cases, "mv_last", "MvLast", DataType.GEO_SHAPE, (size, values) -> equalTo(values.reduce((f, s) -> s).get())); cartesianShape(cases, "mv_last", "MvLast", DataType.CARTESIAN_SHAPE, (size, values) -> equalTo(values.reduce((f, s) -> s).get())); + geohashGrid(cases, "mv_first", "MvLast", DataType.GEOHASH, (size, values) -> equalTo(values.reduce((f, s) -> s).get())); + geotileGrid(cases, "mv_first", "MvLast", DataType.GEOTILE, (size, values) -> equalTo(values.reduce((f, s) -> s).get())); + geohexGrid(cases, "mv_first", "MvLast", DataType.GEOHEX, (size, values) -> equalTo(values.reduce((f, s) -> s).get())); return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(false, cases); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSliceTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSliceTests.java index abecd38cfbba1..a6aa700617f79 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSliceTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/MvSliceTests.java @@ -13,6 +13,11 @@ import org.apache.lucene.util.BytesRef; import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.ShapeTestUtils; +import org.elasticsearch.geometry.Point; +import org.elasticsearch.geometry.utils.Geohash; +import org.elasticsearch.h3.H3; +import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils; +import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.esql.core.InvalidArgumentException; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; @@ -27,6 +32,9 @@ import java.util.function.Supplier; import static org.elasticsearch.xpack.esql.EsqlTestUtils.randomLiteral; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.CARTESIAN; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; import static org.hamcrest.Matchers.equalTo; @@ -52,7 +60,7 @@ public static Iterable parameters() { String evaluatorTypePart = switch (firstArgumentType) { case BOOLEAN -> "Boolean"; case INTEGER -> "Int"; - case LONG, DATE_NANOS, DATETIME, UNSIGNED_LONG -> "Long"; + case LONG, DATE_NANOS, DATETIME, UNSIGNED_LONG, GEOHASH, GEOTILE, GEOHEX -> "Long"; case DOUBLE -> "Double"; case KEYWORD, TEXT, IP, VERSION, GEO_POINT, CARTESIAN_POINT, GEO_SHAPE, CARTESIAN_SHAPE -> "BytesRef"; default -> throw new IllegalArgumentException("Unsupported type: " + firstArgumentType); @@ -210,74 +218,59 @@ private static void ints(List suppliers) { } private static void longs(List suppliers) { - suppliers.add(new TestCaseSupplier(List.of(DataType.LONG, DataType.INTEGER, DataType.INTEGER), () -> { - List field = randomList(1, 10, () -> randomLong()); - int length = field.size(); - int start = randomIntBetween(0, length - 1); - int end = randomIntBetween(start, length - 1); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field, DataType.LONG, "field"), - new TestCaseSupplier.TypedData(start, DataType.INTEGER, "start"), - new TestCaseSupplier.TypedData(end, DataType.INTEGER, "end") - ), - "MvSliceLongEvaluator[field=Attribute[channel=0], start=Attribute[channel=1], end=Attribute[channel=2]]", - DataType.LONG, - equalTo(start == end ? field.get(start) : field.subList(start, end + 1)) - ); - })); + addLongTestCase(suppliers, DataType.LONG, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.DATETIME, ESTestCase::randomLong); + addLongTestCase(suppliers, DataType.DATE_NANOS, ESTestCase::randomLong); + for (DataType gridType : new DataType[] { GEOHASH, GEOTILE, GEOHEX }) { + addLongTestCase(suppliers, gridType, () -> randomGrid(gridType)); + } - suppliers.add(new TestCaseSupplier(List.of(DataType.DATETIME, DataType.INTEGER, DataType.INTEGER), () -> { - List field = randomList(1, 10, () -> randomLong()); + suppliers.add(new TestCaseSupplier(List.of(DataType.UNSIGNED_LONG, DataType.INTEGER, DataType.INTEGER), () -> { + List field = randomList(1, 10, () -> randomNonNegativeLong()); + List result = field.stream().map(NumericUtils::unsignedLongAsBigInteger).toList(); int length = field.size(); int start = randomIntBetween(0, length - 1); int end = randomIntBetween(start, length - 1); return new TestCaseSupplier.TestCase( List.of( - new TestCaseSupplier.TypedData(field, DataType.DATETIME, "field"), + new TestCaseSupplier.TypedData(field, DataType.UNSIGNED_LONG, "field"), new TestCaseSupplier.TypedData(start, DataType.INTEGER, "start"), new TestCaseSupplier.TypedData(end, DataType.INTEGER, "end") ), "MvSliceLongEvaluator[field=Attribute[channel=0], start=Attribute[channel=1], end=Attribute[channel=2]]", - DataType.DATETIME, - equalTo(start == end ? field.get(start) : field.subList(start, end + 1)) + DataType.UNSIGNED_LONG, + equalTo(start == end ? result.get(start) : result.subList(start, end + 1)) ); })); + } - suppliers.add(new TestCaseSupplier(List.of(DataType.DATE_NANOS, DataType.INTEGER, DataType.INTEGER), () -> { - List field = randomList(1, 10, () -> randomLong()); + private static void addLongTestCase(List suppliers, DataType dataType, Supplier longSupplier) { + suppliers.add(new TestCaseSupplier(List.of(dataType, DataType.INTEGER, DataType.INTEGER), () -> { + List field = randomList(1, 10, longSupplier); int length = field.size(); int start = randomIntBetween(0, length - 1); int end = randomIntBetween(start, length - 1); return new TestCaseSupplier.TestCase( List.of( - new TestCaseSupplier.TypedData(field, DataType.DATE_NANOS, "field"), + new TestCaseSupplier.TypedData(field, dataType, "field"), new TestCaseSupplier.TypedData(start, DataType.INTEGER, "start"), new TestCaseSupplier.TypedData(end, DataType.INTEGER, "end") ), "MvSliceLongEvaluator[field=Attribute[channel=0], start=Attribute[channel=1], end=Attribute[channel=2]]", - DataType.DATE_NANOS, + dataType, equalTo(start == end ? field.get(start) : field.subList(start, end + 1)) ); })); + } - suppliers.add(new TestCaseSupplier(List.of(DataType.UNSIGNED_LONG, DataType.INTEGER, DataType.INTEGER), () -> { - List field = randomList(1, 10, () -> randomNonNegativeLong()); - List result = field.stream().map(NumericUtils::unsignedLongAsBigInteger).toList(); - int length = field.size(); - int start = randomIntBetween(0, length - 1); - int end = randomIntBetween(start, length - 1); - return new TestCaseSupplier.TestCase( - List.of( - new TestCaseSupplier.TypedData(field, DataType.UNSIGNED_LONG, "field"), - new TestCaseSupplier.TypedData(start, DataType.INTEGER, "start"), - new TestCaseSupplier.TypedData(end, DataType.INTEGER, "end") - ), - "MvSliceLongEvaluator[field=Attribute[channel=0], start=Attribute[channel=1], end=Attribute[channel=2]]", - DataType.UNSIGNED_LONG, - equalTo(start == end ? result.get(start) : result.subList(start, end + 1)) - ); - })); + static long randomGrid(DataType gridType) { + Point point = GeometryTestUtils.randomPoint(); + return switch (gridType) { + case GEOHASH -> Geohash.longEncode(point.getX(), point.getY(), randomIntBetween(1, Geohash.PRECISION)); + case GEOTILE -> GeoTileUtils.longEncode(point.getX(), point.getY(), randomIntBetween(1, GeoTileUtils.MAX_ZOOM)); + case GEOHEX -> H3.geoToH3(point.getLat(), point.getLon(), randomIntBetween(1, H3.MAX_H3_RES)); + default -> throw new IllegalStateException("Invalid grid type: " + gridType); + }; } private static void doubles(List suppliers) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/nulls/CoalesceTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/nulls/CoalesceTests.java index ebbeea3b0e8e4..209cf322b0b9a 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/nulls/CoalesceTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/nulls/CoalesceTests.java @@ -183,14 +183,23 @@ private static TestCaseSupplier.TestCase nullCase(TestCaseSupplier.TestCase dele } protected static void addSpatialCombinations(List suppliers) { - for (DataType dataType : List.of(DataType.GEO_POINT, DataType.GEO_SHAPE, DataType.CARTESIAN_POINT, DataType.CARTESIAN_SHAPE)) { + for (DataType dataType : List.of( + DataType.GEO_POINT, + DataType.GEO_SHAPE, + DataType.CARTESIAN_POINT, + DataType.CARTESIAN_SHAPE, + DataType.GEOHASH, + DataType.GEOTILE, + DataType.GEOHEX + )) { + String blockType = DataType.isGeoGrid(dataType) ? "Long" : "BytesRef"; TestCaseSupplier.TypedDataSupplier leftDataSupplier = SpatialRelatesFunctionTestCase.testCaseSupplier(dataType, false); TestCaseSupplier.TypedDataSupplier rightDataSupplier = SpatialRelatesFunctionTestCase.testCaseSupplier(dataType, false); suppliers.add( TestCaseSupplier.testCaseSupplier( leftDataSupplier, rightDataSupplier, - (l, r) -> equalTo("CoalesceBytesRefEagerEvaluator[values=[Attribute[channel=0], Attribute[channel=1]]]"), + (l, r) -> equalTo("Coalesce" + blockType + "EagerEvaluator[values=[Attribute[channel=0], Attribute[channel=1]]]"), dataType, (l, r) -> l ) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/BinarySpatialFunctionTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/BinarySpatialFunctionTestCase.java index 68dd600489393..1f53ea4d9a72c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/BinarySpatialFunctionTestCase.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/BinarySpatialFunctionTestCase.java @@ -28,6 +28,9 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; import static org.elasticsearch.xpack.esql.core.type.DataType.isSpatial; import static org.elasticsearch.xpack.esql.core.type.DataType.isSpatialGeo; import static org.elasticsearch.xpack.esql.core.type.DataType.isString; @@ -49,17 +52,20 @@ protected static Class> getSpatialRelatesFunctionClass() throws ClassNotFoundE 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); + return switch (dataType) { + 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); + return switch (dataType) { + 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); + case GEOHASH -> TestCaseSupplier.geoGridCases(GEOHASH, () -> false).get(0); + case GEOTILE -> TestCaseSupplier.geoGridCases(GEOTILE, () -> false).get(0); + case GEOHEX -> TestCaseSupplier.geoGridCases(GEOHEX, () -> 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/SpatialGridFunctionTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/SpatialGridFunctionTestCase.java index 0d4eaf6e826d9..d25e98abefd7e 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 @@ -26,7 +26,6 @@ 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.type.DataType.LONG; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; import static org.hamcrest.Matchers.containsString; @@ -70,6 +69,7 @@ private static String getFunctionClassName() { protected static void addTestCaseSuppliers( List suppliers, DataType[] dataTypes, + DataType gridType, BiFunction expectedValue, TriFunction expectedValueWithBounds ) { @@ -91,7 +91,7 @@ protected static void addTestCaseSuppliers( return new TestCaseSupplier.TestCase( List.of(geoTypedData, precisionData), getFunctionClassName() + evaluatorName, - LONG, + gridType, equalTo(expectedValue.apply(geometry, precision)) ); })); @@ -111,7 +111,7 @@ protected static void addTestCaseSuppliers( return new TestCaseSupplier.TestCase( List.of(geoTypedData, precisionData, boundsData.typedData), startsWith(getFunctionClassName() + evaluatorName), - LONG, + gridType, equalTo(expectedValueWithBounds.apply(geometry, precision, boundsData.geoBoundingBox())) ); })); @@ -121,17 +121,17 @@ protected static void addTestCaseSuppliers( public static TestCaseSupplier.TypedDataSupplier testCaseSupplier(DataType dataType, boolean pointsOnly) { if (pointsOnly) { - return switch (dataType.esType()) { - case "geo_point" -> TestCaseSupplier.geoPointCases(() -> false).getFirst(); - case "cartesian_point" -> TestCaseSupplier.cartesianPointCases(() -> false).getFirst(); + return switch (dataType) { + case GEO_POINT -> TestCaseSupplier.geoPointCases(() -> false).getFirst(); + case CARTESIAN_POINT -> TestCaseSupplier.cartesianPointCases(() -> false).getFirst(); default -> throw new IllegalArgumentException("Unsupported datatype for " + functionName() + ": " + dataType); }; } else { - return switch (dataType.esType()) { - case "geo_point" -> TestCaseSupplier.geoPointCases(() -> false).getFirst(); - case "geo_shape" -> TestCaseSupplier.geoShapeCases(() -> false).getFirst(); - case "cartesian_point" -> TestCaseSupplier.cartesianPointCases(() -> false).getFirst(); - case "cartesian_shape" -> TestCaseSupplier.cartesianShapeCases(() -> false).getFirst(); + return switch (dataType) { + case GEO_POINT -> TestCaseSupplier.geoPointCases(() -> false).getFirst(); + case GEO_SHAPE -> TestCaseSupplier.geoShapeCases(() -> false).getFirst(); + case CARTESIAN_POINT -> TestCaseSupplier.cartesianPointCases(() -> false).getFirst(); + case CARTESIAN_SHAPE -> TestCaseSupplier.cartesianShapeCases(() -> false).getFirst(); 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/StGeohashTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashTests.java index 185591df91b4d..eba240d1a1973 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 @@ -23,6 +23,8 @@ import java.util.List; import java.util.function.Supplier; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHASH; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; import static org.hamcrest.Matchers.containsString; @@ -42,7 +44,7 @@ public static License.OperationMode licenseRequirement(List fieldTypes @ParametersFactory public static Iterable parameters() { final List suppliers = new ArrayList<>(); - addTestCaseSuppliers(suppliers, new DataType[] { DataType.GEO_POINT }, StGeohashTests::valueOf, StGeohashTests::boundedValueOf); + addTestCaseSuppliers(suppliers, new DataType[] { GEO_POINT }, GEOHASH, StGeohashTests::valueOf, StGeohashTests::boundedValueOf); 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 deleted file mode 100644 index 58feda75a8ab9..0000000000000 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohashToStringTests.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.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.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeohashToStringTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "Attribute[channel=0]", - KEYWORD, - g -> new BytesRef(Geohash.stringEncode(StGeohash.unboundedGrid.calculateGridId(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 index f52241806a3be..1e3319e1bf12e 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 @@ -23,6 +23,8 @@ import java.util.List; import java.util.function.Supplier; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOHEX; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; import static org.hamcrest.Matchers.containsString; @@ -42,7 +44,7 @@ public static License.OperationMode licenseRequirement(List fieldTypes @ParametersFactory public static Iterable parameters() { final List suppliers = new ArrayList<>(); - addTestCaseSuppliers(suppliers, new DataType[] { DataType.GEO_POINT }, StGeohexTests::valueOf, StGeohexTests::boundedValueOf); + addTestCaseSuppliers(suppliers, new DataType[] { GEO_POINT }, GEOHEX, StGeohexTests::valueOf, StGeohexTests::boundedValueOf); 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 deleted file mode 100644 index bf3c734869330..0000000000000 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeohexToStringTests.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.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.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeohexToStringTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "Attribute[channel=0]", - KEYWORD, - g -> new BytesRef(H3.h3ToString(StGeohex.unboundedGrid.calculateGridId(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 index 5661f1eacf533..6c8582489e767 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 @@ -23,6 +23,8 @@ import java.util.function.Supplier; import static org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils.MAX_ZOOM; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEOTILE; +import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT; import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.UNSPECIFIED; import static org.hamcrest.Matchers.containsString; @@ -39,10 +41,11 @@ public static License.OperationMode licenseRequirement(List fieldTypes return SpatialGridFunctionTestCase.licenseRequirement(fieldTypes); } + @SuppressWarnings("checkstyle:LineLength") @ParametersFactory public static Iterable parameters() { final List suppliers = new ArrayList<>(); - addTestCaseSuppliers(suppliers, new DataType[] { DataType.GEO_POINT }, StGeotileTests::valueOf, StGeotileTests::boundedValueOf); + addTestCaseSuppliers(suppliers, new DataType[] { GEO_POINT }, GEOTILE, StGeotileTests::valueOf, StGeotileTests::boundedValueOf); 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 deleted file mode 100644 index fd558887c0fda..0000000000000 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/spatial/StGeotileToStringTests.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.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.unboundedGrid.calculateGridId(UNSPECIFIED.wkbAsPoint(g), 2), - StGeotileToStringTests::valueOf - ); - forUnaryGeoPoint( - DataType.KEYWORD, - suppliers, - "Attribute[channel=0]", - KEYWORD, - g -> new BytesRef(GeoTileUtils.stringEncode(StGeotile.unboundedGrid.calculateGridId(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)); - } -} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/CastOperatorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/CastOperatorTests.java index 40cb11ea511f0..8ed52cb50a898 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/CastOperatorTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/CastOperatorTests.java @@ -72,6 +72,9 @@ public TestCastOperator( "double", "geo_point", "geo_shape", + "geohash", + "geotile", + "geohex", "integer", "ip", "keyword", diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EqualsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EqualsTests.java index 4b9f21187f425..410919ac0fad5 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EqualsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/EqualsTests.java @@ -236,6 +236,22 @@ public static Iterable parameters() { ) ); + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + suppliers.addAll( + TestCaseSupplier.forBinaryNotCasting( + "EqualsLongsEvaluator", + "lhs", + "rhs", + Object::equals, + DataType.BOOLEAN, + TestCaseSupplier.geoGridCases(gridType), + TestCaseSupplier.geoGridCases(gridType), + List.of(), + false + ) + ); + } + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/NotEqualsTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/NotEqualsTests.java index 95001366f1cad..f7646489419c3 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/NotEqualsTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/comparison/NotEqualsTests.java @@ -233,6 +233,22 @@ public static Iterable parameters() { ) ); + for (DataType gridType : new DataType[] { DataType.GEOHASH, DataType.GEOTILE, DataType.GEOHEX }) { + suppliers.addAll( + TestCaseSupplier.forBinaryNotCasting( + "NotEqualsLongsEvaluator", + "lhs", + "rhs", + (l, r) -> false == l.equals(r), + DataType.BOOLEAN, + TestCaseSupplier.geoGridCases(gridType), + TestCaseSupplier.geoGridCases(gridType), + List.of(), + false + ) + ); + } + return parameterSuppliersFromTypedDataWithDefaultChecksNoErrors(true, suppliers); }