Skip to content

Commit aeb6f04

Browse files
SNOW-2356299: Add support for scalar geospatial functions - part 3 (#3797)
1 parent 6a7ab60 commit aeb6f04

3 files changed

Lines changed: 298 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@
5454
- `h3_uncompact_cells`
5555
- `h3_uncompact_cells_strings`
5656
- `haversine`
57+
- `h3_grid_path`
58+
- `h3_is_pentagon`
59+
- `h3_is_valid_cell`
60+
- `h3_latlng_to_cell`
61+
- `h3_latlng_to_cell_string`
62+
- `h3_point_to_cell`
63+
- `h3_point_to_cell_string`
64+
- `h3_try_coverage`
65+
- `h3_try_coverage_strings`
66+
- `h3_try_grid_distance`
5767
- `hex_decode_binary`
5868
- `last_query_id`
5969
- `last_transaction`

docs/source/snowpark/functions.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,16 @@ Functions
264264
h3_try_polygon_to_cells
265265
h3_uncompact_cells
266266
h3_uncompact_cells_strings
267+
h3_grid_path
268+
h3_is_pentagon
269+
h3_is_valid_cell
270+
h3_latlng_to_cell
271+
h3_latlng_to_cell_string
272+
h3_point_to_cell
273+
h3_point_to_cell_string
274+
h3_try_coverage
275+
h3_try_coverage_strings
276+
h3_try_grid_distance
267277
iff
268278
ifnull
269279
in_

src/snowflake/snowpark/_functions/scalar_functions.py

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1786,3 +1786,281 @@ def st_aswkb(
17861786
"""
17871787
c = _to_col_if_str(geography_or_geometry_expression, "st_aswkb")
17881788
return builtin("st_aswkb", _emit_ast=_emit_ast)(c)
1789+
1790+
1791+
@publicapi
1792+
def h3_grid_path(
1793+
cell_id_1: ColumnOrName, cell_id_2: ColumnOrName, _emit_ast: bool = True
1794+
) -> Column:
1795+
"""
1796+
Returns the grid path between two H3 cell IDs as a JSON array of H3 cell IDs.
1797+
1798+
Args:
1799+
cell_id_1 (ColumnOrName): The starting H3 cell ID.
1800+
cell_id_2 (ColumnOrName): The ending H3 cell ID.
1801+
1802+
Returns:
1803+
Column: A JSON array of H3 cell IDs representing the grid path.
1804+
1805+
Examples::
1806+
1807+
>>> df = session.create_dataframe([
1808+
... [617540519103561727, 617540519052967935],
1809+
... [617540519046414335, 617540519047462911]
1810+
... ], schema=["cell_id_1", "cell_id_2"])
1811+
>>> df.select(h3_grid_path("cell_id_1", "cell_id_2").alias("grid_path")).collect()
1812+
[Row(GRID_PATH='[\\n 617540519103561727,\\n 617540519046414335,\\n 617540519047462911,\\n 617540519044055039,\\n 617540519045103615,\\n 617540519052967935\\n]'), Row(GRID_PATH='[\\n 617540519046414335,\\n 617540519047462911\\n]')]
1813+
"""
1814+
c1 = _to_col_if_str(cell_id_1, "h3_grid_path")
1815+
c2 = _to_col_if_str(cell_id_2, "h3_grid_path")
1816+
return builtin("h3_grid_path", _emit_ast=_emit_ast)(c1, c2)
1817+
1818+
1819+
@publicapi
1820+
def h3_is_pentagon(cell_id: ColumnOrName, _emit_ast: bool = True) -> Column:
1821+
"""
1822+
Returns true if the given H3 cell ID is a pentagon.
1823+
1824+
Args:
1825+
cell_id (ColumnOrName): The H3 cell IDs.
1826+
1827+
Returns:
1828+
Column: Whether each H3 cell ID is a pentagon.
1829+
1830+
Example::
1831+
>>> df = session.create_dataframe([613036919424548863], schema=["cell_id"])
1832+
>>> df.select(h3_is_pentagon(df["cell_id"]).alias("is_pentagon")).collect()
1833+
[Row(IS_PENTAGON=False)]
1834+
>>> df = session.create_dataframe(['804dfffffffffff'], schema=["cell_id"])
1835+
>>> df.select(h3_is_pentagon(df["cell_id"]).alias("is_pentagon")).collect()
1836+
[Row(IS_PENTAGON=True)]
1837+
"""
1838+
c = _to_col_if_str(cell_id, "h3_is_pentagon")
1839+
return builtin("h3_is_pentagon", _emit_ast=_emit_ast)(c)
1840+
1841+
1842+
@publicapi
1843+
def h3_is_valid_cell(cell_id: ColumnOrName, _emit_ast: bool = True) -> Column:
1844+
"""
1845+
Checks if the given H3 cell ID is valid.
1846+
1847+
Args:
1848+
cell_id (ColumnOrName): The H3 cell IDs to validate.
1849+
1850+
Returns:
1851+
Column: Whether each H3 cell ID is valid, returns True for valid H3 cell IDs, False for invalid ones, and None for None inputs.
1852+
1853+
Example::
1854+
1855+
>>> df = session.create_dataframe([613036919424548863, 123456789, None], schema=["cell_id"])
1856+
>>> df.select(h3_is_valid_cell(df["cell_id"]).alias("is_valid")).collect()
1857+
[Row(IS_VALID=True), Row(IS_VALID=False), Row(IS_VALID=None)]
1858+
"""
1859+
c = _to_col_if_str(cell_id, "h3_is_valid_cell")
1860+
return builtin("h3_is_valid_cell", _emit_ast=_emit_ast)(c)
1861+
1862+
1863+
@publicapi
1864+
def h3_latlng_to_cell(
1865+
latitude: ColumnOrName,
1866+
longitude: ColumnOrName,
1867+
target_resolution: ColumnOrName,
1868+
_emit_ast: bool = True,
1869+
) -> Column:
1870+
"""
1871+
Returns the H3 cell ID for the given latitude, longitude, and resolution.
1872+
1873+
Args:
1874+
latitude (ColumnOrName): The latitude values.
1875+
longitude (ColumnOrName): The longitude values.
1876+
target_resolution (ColumnOrName): The target H3 resolution.
1877+
1878+
Returns:
1879+
Column: H3 cell ID for the given latitude, longitude, and resolution.
1880+
1881+
Example::
1882+
1883+
>>> df = session.create_dataframe([[52.516262, 13.377704, 8]], schema=["lat", "lng", "res"])
1884+
>>> df.select(h3_latlng_to_cell(df["lat"], df["lng"], df["res"])).collect()
1885+
[Row(H3_LATLNG_TO_CELL("LAT", "LNG", "RES")=613036919424548863)]
1886+
"""
1887+
lat_col = _to_col_if_str(latitude, "h3_latlng_to_cell")
1888+
lng_col = _to_col_if_str(longitude, "h3_latlng_to_cell")
1889+
res_col = _to_col_if_str(target_resolution, "h3_latlng_to_cell")
1890+
return builtin("h3_latlng_to_cell", _emit_ast=_emit_ast)(lat_col, lng_col, res_col)
1891+
1892+
1893+
@publicapi
1894+
def h3_latlng_to_cell_string(
1895+
latitude: ColumnOrName,
1896+
longitude: ColumnOrName,
1897+
target_resolution: ColumnOrName,
1898+
_emit_ast: bool = True,
1899+
) -> Column:
1900+
"""
1901+
Returns the H3 cell ID string for the given latitude, longitude, and resolution.
1902+
1903+
Args:
1904+
latitude (ColumnOrName): The latitude values.
1905+
longitude (ColumnOrName): The longitude values.
1906+
target_resolution (ColumnOrName): The H3 resolution values (0-15).
1907+
1908+
Returns:
1909+
Column: H3 cell ID string for the given latitude, longitude, and resolution.
1910+
1911+
Example::
1912+
1913+
>>> df = session.create_dataframe([[52.516262, 13.377704, 8]], schema=["lat", "lng", "res"])
1914+
>>> df.select(h3_latlng_to_cell_string("lat", "lng", "res")).collect()
1915+
[Row(H3_LATLNG_TO_CELL_STRING("LAT", "LNG", "RES")='881f1d4887fffff')]
1916+
"""
1917+
lat = _to_col_if_str(latitude, "h3_latlng_to_cell_string")
1918+
lng = _to_col_if_str(longitude, "h3_latlng_to_cell_string")
1919+
res = _to_col_if_str(target_resolution, "h3_latlng_to_cell_string")
1920+
return builtin("h3_latlng_to_cell_string", _emit_ast=_emit_ast)(lat, lng, res)
1921+
1922+
1923+
@publicapi
1924+
def h3_point_to_cell(
1925+
geography_point: ColumnOrName,
1926+
target_resolution: ColumnOrName,
1927+
_emit_ast: bool = True,
1928+
) -> Column:
1929+
"""
1930+
Returns the H3 cell ID for a given geography point at the specified resolution.
1931+
1932+
Args:
1933+
geography_point (ColumnOrName): The geography points.
1934+
target_resolution (ColumnOrName): The target H3 resolution (0-15).
1935+
1936+
Returns:
1937+
Column: H3 cell ID for the given geography point at the specified resolution.
1938+
1939+
Example::
1940+
>>> from snowflake.snowpark.functions import col
1941+
>>> df = session.sql("SELECT ST_POINT(13.377704, 52.516262) as geography_point, 8 as resolution")
1942+
>>> df.select(h3_point_to_cell(col("geography_point"), col("resolution"))).collect()
1943+
[Row(H3_POINT_TO_CELL("GEOGRAPHY_POINT", "RESOLUTION")=613036919424548863)]
1944+
"""
1945+
geography_point_c = _to_col_if_str(geography_point, "h3_point_to_cell")
1946+
target_resolution_c = _to_col_if_str(target_resolution, "h3_point_to_cell")
1947+
return builtin("h3_point_to_cell", _emit_ast=_emit_ast)(
1948+
geography_point_c, target_resolution_c
1949+
)
1950+
1951+
1952+
@publicapi
1953+
def h3_point_to_cell_string(
1954+
geography_point: ColumnOrName,
1955+
target_resolution: ColumnOrName,
1956+
_emit_ast: bool = True,
1957+
) -> Column:
1958+
"""Returns the H3 cell ID string for a given geography point at the specified resolution.
1959+
1960+
Args:
1961+
geography_point (ColumnOrName): The geography point to convert to H3 cell.
1962+
target_resolution (ColumnOrName): The target H3 resolution (0-15).
1963+
1964+
Returns:
1965+
Column: H3 cell ID string for the given geography point at the specified resolution.
1966+
1967+
Example::
1968+
>>> from snowflake.snowpark.functions import col
1969+
>>> df = session.sql("SELECT ST_POINT(13.377704, 52.516262) as point, 8 as resolution")
1970+
>>> df.select(h3_point_to_cell_string(col("point"), col("resolution"))).collect()
1971+
[Row(H3_POINT_TO_CELL_STRING("POINT", "RESOLUTION")='881f1d4887fffff')]
1972+
"""
1973+
geography_point_col = _to_col_if_str(geography_point, "h3_point_to_cell_string")
1974+
target_resolution_col = _to_col_if_str(target_resolution, "h3_point_to_cell_string")
1975+
return builtin("h3_point_to_cell_string", _emit_ast=_emit_ast)(
1976+
geography_point_col, target_resolution_col
1977+
)
1978+
1979+
1980+
@publicapi
1981+
def h3_try_coverage(
1982+
geography_expression: ColumnOrName,
1983+
target_resolution: ColumnOrName,
1984+
_emit_ast: bool = True,
1985+
) -> Column:
1986+
"""
1987+
Returns an array of H3 cell IDs that cover the given geography at the specified resolution.
1988+
This function attempts to provide coverage of the geography using H3 cells, returning None
1989+
if the operation cannot be performed.
1990+
1991+
Args:
1992+
geography_expression (ColumnOrName): The geography object to cover with H3 cells.
1993+
target_resolution (ColumnOrName): The H3 resolution level (0-15) for the coverage.
1994+
1995+
Returns:
1996+
Column: An array of H3 cell IDs covering the geography or None if the operation cannot be performed.
1997+
1998+
Example::
1999+
>>> from snowflake.snowpark.functions import to_geography, lit
2000+
>>> df = session.create_dataframe([
2001+
... ("POLYGON((-122.4194 37.7749, -122.4094 37.7749, -122.4094 37.7849, -122.4194 37.7849, -122.4194 37.7749))",)
2002+
... ], schema=["geog"])
2003+
>>> df.select(h3_try_coverage(to_geography(df["geog"]), lit(9)).alias("coverage")).collect()
2004+
[Row(COVERAGE='[\\n 617700169957507071,\\n 617700169958031359,\\n 617700169958293503,\\n 617700169961701375,\\n 617700169961963519,\\n 617700169962487807,\\n 617700169963012095,\\n 617700169963798527,\\n 617700169964060671,\\n 617700169964322815,\\n 617700169964584959,\\n 617700169964847103,\\n 617700169965109247,\\n 617700169965371391,\\n 617700170001809407,\\n 617700170002857983,\\n 617700170017800191\\n]')]
2005+
"""
2006+
geography_col = _to_col_if_str(geography_expression, "h3_try_coverage")
2007+
resolution_col = _to_col_if_str(target_resolution, "h3_try_coverage")
2008+
return builtin("h3_try_coverage", _emit_ast=_emit_ast)(
2009+
geography_col, resolution_col
2010+
)
2011+
2012+
2013+
@publicapi
2014+
def h3_try_coverage_strings(
2015+
geography_expression: ColumnOrName,
2016+
target_resolution: ColumnOrName,
2017+
_emit_ast: bool = True,
2018+
) -> Column:
2019+
"""
2020+
Returns an array of H3 cell IDs as strings that cover the given geography at the specified resolution.
2021+
This function attempts to provide coverage of the geography using H3 cells, returning the cell IDs as strings.
2022+
2023+
Args:
2024+
geography_expression (ColumnOrName): A geography expression to be covered by H3 cells
2025+
target_resolution (ColumnOrName): The H3 resolution level for the coverage, ranging from 0 to 15
2026+
2027+
Returns:
2028+
Column: An array of H3 cell ID strings that cover the input geography
2029+
2030+
Examples::
2031+
2032+
>>> from snowflake.snowpark.functions import to_geography
2033+
>>> df = session.create_dataframe([
2034+
... "POLYGON((-122.4194 37.7749, -122.4094 37.7749, -122.4094 37.7849, -122.4194 37.7849, -122.4194 37.7749))"
2035+
... ], schema=["geog"])
2036+
>>> df.select(h3_try_coverage_strings(to_geography(df["geog"]), lit(9)).alias("coverage")).collect()
2037+
[Row(COVERAGE='[\\n "89283082803ffff",\\n "8928308280bffff",\\n "8928308280fffff",\\n "89283082843ffff",\\n "89283082847ffff",\\n "8928308284fffff",\\n "89283082857ffff",\\n "89283082863ffff",\\n "89283082867ffff",\\n "8928308286bffff",\\n "8928308286fffff",\\n "89283082873ffff",\\n "89283082877ffff",\\n "8928308287bffff",\\n "89283082aa7ffff",\\n "89283082ab7ffff",\\n "89283082b9bffff"\\n]')]
2038+
"""
2039+
g = _to_col_if_str(geography_expression, "h3_try_coverage_strings")
2040+
r = _to_col_if_str(target_resolution, "h3_try_coverage_strings")
2041+
return builtin("h3_try_coverage_strings", _emit_ast=_emit_ast)(g, r)
2042+
2043+
2044+
@publicapi
2045+
def h3_try_grid_distance(
2046+
cell_id_1: ColumnOrName, cell_id_2: ColumnOrName, _emit_ast: bool = True
2047+
) -> Column:
2048+
"""
2049+
Returns the grid distance between two H3 cell IDs. Returns None if the input is invalid.
2050+
2051+
Args:
2052+
cell_id_1 (ColumnOrName): First H3 cell ID.
2053+
cell_id_2 (ColumnOrName): Second H3 cell ID.
2054+
2055+
Returns:
2056+
Column: The grid distance between the two H3 cell IDs or None if the input is invalid.
2057+
2058+
Example::
2059+
2060+
>>> df = session.create_dataframe([[582046271372525567, 581883543651614719]], schema=["cell_id_1", "cell_id_2"])
2061+
>>> df.select(h3_try_grid_distance(df["cell_id_1"], df["cell_id_2"]).alias("result")).collect()
2062+
[Row(RESULT=None)]
2063+
"""
2064+
cell_id_1 = _to_col_if_str(cell_id_1, "h3_try_grid_distance")
2065+
cell_id_2 = _to_col_if_str(cell_id_2, "h3_try_grid_distance")
2066+
return builtin("h3_try_grid_distance", _emit_ast=_emit_ast)(cell_id_1, cell_id_2)

0 commit comments

Comments
 (0)