You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sedona.apache.org by ji...@apache.org on 2024/05/28 08:10:20 UTC
(sedona) branch SEDONA-564 created (now 819d62073)
This is an automated email from the ASF dual-hosted git repository.
jiayu pushed a change to branch SEDONA-564
in repository https://gitbox.apache.org/repos/asf/sedona.git
at 819d62073 Update version
This branch includes the following new commits:
new 24a992a4b [189] Add ST_NumInteriorRing (#138)
new 819d62073 Update version
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(sedona) 01/02: [189] Add ST_NumInteriorRing (#138)
Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
jiayu pushed a commit to branch SEDONA-564
in repository https://gitbox.apache.org/repos/asf/sedona.git
commit 24a992a4bf59e2dface731f866b632bb7d8a0f90
Author: Furqaan Khan <46...@users.noreply.github.com>
AuthorDate: Thu Mar 28 16:13:46 2024 -0400
[189] Add ST_NumInteriorRing (#138)
* feat: add ST_NumInteriorRing
* feat: add python tests
* docs: remove version number
---
docs/api/flink/Function.md | 20 +++++++++++++++
docs/api/snowflake/vector-data/Function.md | 18 ++++++++++++++
docs/api/sql/Function.md | 20 +++++++++++++++
.../main/java/org/apache/sedona/flink/Catalog.java | 1 +
.../apache/sedona/flink/expressions/Functions.java | 8 ++++++
.../java/org/apache/sedona/flink/FunctionTest.java | 7 ++++++
python/sedona/sql/st_functions.py | 11 ++++++++
python/tests/sql/test_dataframe_api.py | 2 ++
python/tests/sql/test_function.py | 23 ++++++++++++++++-
.../sedona/snowflake/snowsql/TestFunctions.java | 13 ++++++++++
.../sedona/snowflake/snowsql/TestFunctionsV2.java | 13 ++++++++++
.../org/apache/sedona/snowflake/snowsql/UDFs.java | 7 ++++++
.../apache/sedona/snowflake/snowsql/UDFsV2.java | 7 ++++++
.../scala/org/apache/sedona/sql/UDF/Catalog.scala | 1 +
.../sql/sedona_sql/expressions/Functions.scala | 8 ++++++
.../sql/sedona_sql/expressions/st_functions.scala | 3 +++
.../org/apache/sedona/sql/functionTestScala.scala | 29 ++++++++++++++++++++++
17 files changed, 190 insertions(+), 1 deletion(-)
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index 5c6b2f6f3..51023b75e 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -2283,6 +2283,26 @@ Output:
1
```
+## ST_NumInteriorRing
+
+Introduction: Returns number of interior rings of polygon geometries. It is an alias of [ST_NumInteriorRings](#st_numinteriorrings).
+
+Format: `ST_NumInteriorRing(geom: Geometry)`
+
+Since: `vTBD`
+
+SQL Example
+
+```sql
+SELECT ST_NumInteriorRing(ST_GeomFromText('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))'))
+```
+
+Output:
+
+```
+1
+```
+
## ST_NumInteriorRings
Introduction: Returns number of interior rings of polygon geometries.
diff --git a/docs/api/snowflake/vector-data/Function.md b/docs/api/snowflake/vector-data/Function.md
index 6f02aaed1..eedcc50a2 100644
--- a/docs/api/snowflake/vector-data/Function.md
+++ b/docs/api/snowflake/vector-data/Function.md
@@ -1759,6 +1759,24 @@ SELECT ST_NumGeometries(df.geometry)
FROM df
```
+## ST_NumInteriorRing
+
+Introduction: Returns number of interior rings of polygon geometries. It is an alias of [ST_NumInteriorRings](#st_numinteriorrings).
+
+Format: `ST_NumInteriorRing(geom: Geometry)`
+
+SQL Example
+
+```sql
+SELECT ST_NumInteriorRing(ST_GeomFromText('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))'))
+```
+
+Output:
+
+```
+1
+```
+
## ST_NumInteriorRings
Introduction: RETURNS number of interior rings of polygon geometries.
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index 814c9c376..8f25489b4 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -2297,6 +2297,26 @@ Output:
1
```
+## ST_NumInteriorRing
+
+Introduction: Returns number of interior rings of polygon geometries. It is an alias of [ST_NumInteriorRings](#st_numinteriorrings).
+
+Format: `ST_NumInteriorRing(geom: Geometry)`
+
+Since: `vTBD`
+
+SQL Example
+
+```sql
+SELECT ST_NumInteriorRing(ST_GeomFromText('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))'))
+```
+
+Output:
+
+```
+1
+```
+
## ST_NumInteriorRings
Introduction: RETURNS number of interior rings of polygon geometries.
diff --git a/flink/src/main/java/org/apache/sedona/flink/Catalog.java b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
index efd07c3ca..69e6ce0b3 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -86,6 +86,7 @@ public class Catalog {
new Functions.ST_NPoints(),
new Functions.ST_NumGeometries(),
new Functions.ST_NumInteriorRings(),
+ new Functions.ST_NumInteriorRing(),
new Functions.ST_ExteriorRing(),
new Functions.ST_AsEWKT(),
new Functions.ST_AsEWKB(),
diff --git a/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java b/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java
index 150c2048a..fe11db120 100644
--- a/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java
+++ b/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java
@@ -475,6 +475,14 @@ public class Functions {
}
}
+ public static class ST_NumInteriorRing extends ScalarFunction {
+ @DataTypeHint("Integer")
+ public Integer eval(@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class) Object o) {
+ Geometry geom = (Geometry) o;
+ return org.apache.sedona.common.Functions.numInteriorRings(geom);
+ }
+ }
+
public static class ST_ExteriorRing extends ScalarFunction {
@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class)
public Geometry eval(@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class) Object o) {
diff --git a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
index c8d1a2f2e..7649e0040 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -572,6 +572,13 @@ public class FunctionTest extends TestBase{
assertEquals(2, first(resultTable).getField(0));
}
+ @Test
+ public void testNumInteriorRing() {
+ Table polygonTable = tableEnv.sqlQuery("SELECT ST_GeomFromText('POLYGON((7 9,8 7,11 6,15 8,16 6,17 7,17 10,18 12,17 14,15 15,11 15,10 13,9 12,7 9),(9 9,10 10,11 11,11 10,10 8,9 9),(12 14,15 14,13 11,12 14))') AS polygon");
+ Table resultTable = polygonTable.select(call(Functions.ST_NumInteriorRing.class.getSimpleName(), $("polygon")));
+ assertEquals(2, first(resultTable).getField(0));
+ }
+
@Test
public void testExteriorRing() {
Table polygonTable = createPolygonTable(1);
diff --git a/python/sedona/sql/st_functions.py b/python/sedona/sql/st_functions.py
index dfd9ae13c..c22b85490 100644
--- a/python/sedona/sql/st_functions.py
+++ b/python/sedona/sql/st_functions.py
@@ -1024,6 +1024,17 @@ def ST_NumInteriorRings(geometry: ColumnOrName) -> Column:
"""
return _call_st_function("ST_NumInteriorRings", geometry)
+@validate_argument_types
+def ST_NumInteriorRing(geometry: ColumnOrName) -> Column:
+ """Return the number of interior rings contained in a polygon geometry.
+
+ :param geometry: Polygon geometry column to return for.
+ :type geometry: ColumnOrName
+ :return: Number of interior rings polygons contain as an integer column.
+ :rtype: Column
+ """
+ return _call_st_function("ST_NumInteriorRing", geometry)
+
@validate_argument_types
def ST_PointN(geometry: ColumnOrName, n: Union[ColumnOrName, int]) -> Column:
diff --git a/python/tests/sql/test_dataframe_api.py b/python/tests/sql/test_dataframe_api.py
index 56ec8212a..44265ca6f 100644
--- a/python/tests/sql/test_dataframe_api.py
+++ b/python/tests/sql/test_dataframe_api.py
@@ -155,6 +155,7 @@ test_configurations = [
(stf.ST_NRings, ("geom",), "square_geom", "", 1),
(stf.ST_NumGeometries, ("geom",), "multipoint", "", 2),
(stf.ST_NumInteriorRings, ("geom",), "geom_with_hole", "", 1),
+ (stf.ST_NumInteriorRing, ("geom",), "geom_with_hole", "", 1),
(stf.ST_NumPoints, ("line",), "linestring_geom", "", 6),
(stf.ST_PointN, ("line", 2), "linestring_geom", "", "POINT (1 0)"),
(stf.ST_PointOnSurface, ("line",), "linestring_geom", "", "POINT (2 0)"),
@@ -314,6 +315,7 @@ wrong_type_configurations = [
(stf.ST_NPoints, (None,)),
(stf.ST_NumGeometries, (None,)),
(stf.ST_NumInteriorRings, (None,)),
+ (stf.ST_NumInteriorRing, (None,)),
(stf.ST_PointN, (None, 2)),
(stf.ST_PointN, ("", None)),
(stf.ST_PointN, ("", 2.0)),
diff --git a/python/tests/sql/test_function.py b/python/tests/sql/test_function.py
index ea8497132..791a3073b 100644
--- a/python/tests/sql/test_function.py
+++ b/python/tests/sql/test_function.py
@@ -781,7 +781,7 @@ class TestPredicateJoin(TestBase):
is_closed_collected = [[*row] for row in is_closed]
assert (is_closed_collected == expected_result)
- def test_num_interior_ring(self):
+ def test_num_interior_rings(self):
geometries = [
(1, "Point(21 52)"),
(2, "Polygon((0 0, 0 1, 1 1, 1 0, 0 0))"),
@@ -802,6 +802,27 @@ class TestPredicateJoin(TestBase):
collected_interior_rings = [[*row] for row in number_of_interior_rings.filter("num is not null").collect()]
assert (collected_interior_rings == [[2, 0], [11, 1]])
+ def test_num_interior_ring(self):
+ geometries = [
+ (1, "Point(21 52)"),
+ (2, "Polygon((0 0, 0 1, 1 1, 1 0, 0 0))"),
+ (3, "Linestring(0 0, 1 1, 1 0)"),
+ (4, "Linestring(0 0, 1 1, 1 0, 0 0)"),
+ (5, "MULTIPOINT ((10 40), (40 30), (20 20), (30 10))"),
+ (6, "MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))"),
+ (7, "MULTILINESTRING ((10 10, 20 20, 10 40, 10 10), (40 40, 30 30, 40 20, 30 10, 40 40))"),
+ (8, "MULTILINESTRING ((10 10, 20 20, 10 40, 10 10), (40 40, 30 30, 40 20, 30 10))"),
+ (9, "MULTILINESTRING ((10 10, 20 20, 10 40), (40 40, 30 30, 40 20, 30 10))"),
+ (10,
+ "GEOMETRYCOLLECTION (POINT (40 10), LINESTRING (10 10, 20 20, 10 40), POLYGON ((40 40, 20 45, 45 30, 40 40)))"),
+ (11, "POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))")]
+
+ geometry_df = self.__wkt_pair_list_with_index_to_data_frame(geometries)
+
+ number_of_interior_rings = geometry_df.selectExpr("index", "ST_NumInteriorRing(geom) as num")
+ collected_interior_rings = [[*row] for row in number_of_interior_rings.filter("num is not null").collect()]
+ assert (collected_interior_rings == [[2, 0], [11, 1]])
+
def test_st_add_point(self):
geometry = [
("Point(21 52)", "Point(21 52)"),
diff --git a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java
index a0b283156..8c26cc404 100644
--- a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java
+++ b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java
@@ -687,6 +687,19 @@ public class TestFunctions extends TestBase {
);
}
+
+ @Test
+ public void test_ST_NumInteriorRing() {
+ registerUDF("ST_NumInteriorRing", byte[].class);
+ verifySqlSingleRes(
+ "select sedona.ST_NumInteriorRing(sedona.ST_GeomFromText('POLYGON((0 0 0,0 5 0,5 0 0,0 0 5),(1 1 0,3 1 0,1 3 0,1 1 0))'))",
+ 1
+ );
+ verifySqlSingleRes(
+ "select sedona.ST_NumInteriorRing(sedona.ST_GeomFromText('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'))",
+ 0
+ );
+ }
@Test
public void test_ST_PointN() {
registerUDF("ST_PointN", byte[].class, int.class);
diff --git a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java
index 3921b4f09..289d40ee3 100644
--- a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java
+++ b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java
@@ -634,6 +634,19 @@ public class TestFunctionsV2
);
}
+
+ @Test
+ public void test_ST_NumInteriorRing() {
+ registerUDFV2("ST_NumInteriorRing", String.class);
+ verifySqlSingleRes(
+ "select sedona.ST_NumInteriorRing(ST_GeometryFromWKT('POLYGON((0 0,0 5,5 0,0 0),(1 1,3 1,1 3,1 1))'))",
+ 1
+ );
+ verifySqlSingleRes(
+ "select sedona.ST_NumInteriorRing(ST_GeometryFromWKT('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'))",
+ 0
+ );
+ }
@Test
public void test_ST_PointN() {
registerUDFV2("ST_PointN", String.class, int.class);
diff --git a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java
index bad3f0c89..fa4de5603 100644
--- a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java
+++ b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java
@@ -875,6 +875,13 @@ public class UDFs {
);
}
+ @UDFAnnotations.ParamMeta(argNames = {"geometry"})
+ public static Integer ST_NumInteriorRing(byte[] geometry) {
+ return Functions.numInteriorRings(
+ GeometrySerde.deserialize(geometry)
+ );
+ }
+
@UDFAnnotations.ParamMeta(argNames = {"leftGeometry", "rightGeometry"})
public static boolean ST_OrderingEquals(byte[] leftGeometry, byte[] rightGeometry) {
return Predicates.orderingEquals(
diff --git a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java
index 2c6ed7907..da0e56027 100644
--- a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java
+++ b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java
@@ -766,6 +766,13 @@ public class UDFsV2
);
}
+ @UDFAnnotations.ParamMeta(argNames = {"geometry"}, argTypes = {"Geometry"})
+ public static Integer ST_NumInteriorRing(String geometry) {
+ return Functions.numInteriorRings(
+ GeometrySerde.deserGeoJson(geometry)
+ );
+ }
+
@UDFAnnotations.ParamMeta(argNames = {"leftGeometry", "rightGeometry"}, argTypes = {"Geometry", "Geometry"})
public static boolean ST_OrderingEquals(String leftGeometry, String rightGeometry) {
return Predicates.orderingEquals(
diff --git a/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala b/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
index bd2e801ad..0384d96d5 100644
--- a/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
+++ b/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala
@@ -123,6 +123,7 @@ object Catalog {
function[ST_IsClosed](),
function[ST_IsCollection](),
function[ST_NumInteriorRings](),
+ function[ST_NumInteriorRing](),
function[ST_AddPoint](-1),
function[ST_RemovePoint](-1),
function[ST_SetPoint](),
diff --git a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
index 4b9c09c03..f734c99de 100644
--- a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
+++ b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala
@@ -621,6 +621,14 @@ case class ST_NumInteriorRings(inputExpressions: Seq[Expression])
}
}
+case class ST_NumInteriorRing(inputExpressions: Seq[Expression])
+ extends InferredExpression(Functions.numInteriorRings _) {
+
+ protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = {
+ copy(inputExpressions = newChildren)
+ }
+}
+
case class ST_AddPoint(inputExpressions: Seq[Expression])
extends InferredExpression(inferrableFunction3(Functions.addPoint)) {
diff --git a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
index b78917303..4ec1885e8 100644
--- a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
+++ b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala
@@ -265,6 +265,9 @@ object st_functions extends DataFrameAPI {
def ST_NumInteriorRings(geometry: Column): Column = wrapExpression[ST_NumInteriorRings](geometry)
def ST_NumInteriorRings(geometry: String): Column = wrapExpression[ST_NumInteriorRings](geometry)
+ def ST_NumInteriorRing(geometry: Column): Column = wrapExpression[ST_NumInteriorRing](geometry)
+ def ST_NumInteriorRing(geometry: String): Column = wrapExpression[ST_NumInteriorRing](geometry)
+
def ST_PointN(geometry: Column, n: Column): Column = wrapExpression[ST_PointN](geometry, n)
def ST_PointN(geometry: String, n: Int): Column = wrapExpression[ST_PointN](geometry, n)
diff --git a/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala b/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
index 3fee1e53c..807513951 100644
--- a/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
+++ b/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala
@@ -1191,6 +1191,35 @@ class functionTestScala extends TestBaseScala with Matchers with GeometrySample
.collect().toList should contain theSameElementsAs List((2, 0), (11, 1))
}
+ it("Should pass ST_NumInteriorRing") {
+ Given("Geometry DataFrame")
+ val geometryDf = Seq(
+ (1, "Point(21 52)"),
+ (2, "Polygon((0 0, 0 1, 1 1, 1 0, 0 0))"),
+ (3, "Linestring(0 0, 1 1, 1 0)"),
+ (4, "Linestring(0 0, 1 1, 1 0, 0 0)"),
+ (5, "MULTIPOINT ((10 40), (40 30), (20 20), (30 10))"),
+ (6, "MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))"),
+ (7, "MULTILINESTRING ((10 10, 20 20, 10 40, 10 10), (40 40, 30 30, 40 20, 30 10, 40 40))"),
+ (8, "MULTILINESTRING ((10 10, 20 20, 10 40, 10 10), (40 40, 30 30, 40 20, 30 10))"),
+ (9, "MULTILINESTRING ((10 10, 20 20, 10 40), (40 40, 30 30, 40 20, 30 10))"),
+ (10, "GEOMETRYCOLLECTION (POINT (40 10), LINESTRING (10 10, 20 20, 10 40), POLYGON ((40 40, 20 45, 45 30, 40 40)))"),
+ (11, "POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))")
+ ).map({ case (index, wkt) => Tuple2(index, wktReader.read(wkt)) }).toDF("id", "geom")
+
+ When("Using ST_NumInteriorRing")
+ val numberOfInteriorRings = geometryDf.selectExpr(
+ "id", "ST_NumInteriorRing(geom) as num"
+ )
+
+ Then("Result should match with expected values")
+
+ numberOfInteriorRings
+ .filter("num is not null")
+ .as[(Int, Int)]
+ .collect().toList should contain theSameElementsAs List((2, 0), (11, 1))
+ }
+
it("Should pass ST_AddPoint") {
Given("Geometry df")
val geometryDf = Seq(
(sedona) 02/02: Update version
Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
jiayu pushed a commit to branch SEDONA-564
in repository https://gitbox.apache.org/repos/asf/sedona.git
commit 819d62073257f854165d3e40bef52afca46f28ab
Author: Jia Yu <ji...@gmail.com>
AuthorDate: Tue May 28 01:10:00 2024 -0700
Update version
---
docs/api/flink/Function.md | 2 +-
docs/api/sql/Function.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index 51023b75e..ca1c5f6b8 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -2289,7 +2289,7 @@ Introduction: Returns number of interior rings of polygon geometries. It is an a
Format: `ST_NumInteriorRing(geom: Geometry)`
-Since: `vTBD`
+Since: `v1.6.1`
SQL Example
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index 8f25489b4..0fe320261 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -2303,7 +2303,7 @@ Introduction: Returns number of interior rings of polygon geometries. It is an a
Format: `ST_NumInteriorRing(geom: Geometry)`
-Since: `vTBD`
+Since: `v1.6.1`
SQL Example