This is an automated email from the ASF dual-hosted git repository.
junrui pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git
The following commit(s) were added to refs/heads/master by this push:
new ec391138d3c [FLINK-39195][Table SQL/API] ObjectPath should implement
Comparable
ec391138d3c is described below
commit ec391138d3c0b0592652bc7c36867dfd41d15c05
Author: Myracle <[email protected]>
AuthorDate: Tue Mar 3 15:19:17 2026 +0800
[FLINK-39195][Table SQL/API] ObjectPath should implement Comparable
---
flink-python/pyflink/table/catalog.py | 23 +++
flink-python/pyflink/table/tests/test_catalog.py | 160 +++++++++++++++++++++
.../org/apache/flink/table/catalog/ObjectPath.java | 11 +-
.../apache/flink/table/catalog/ObjectPathTest.java | 107 ++++++++++++++
4 files changed, 300 insertions(+), 1 deletion(-)
diff --git a/flink-python/pyflink/table/catalog.py
b/flink-python/pyflink/table/catalog.py
index d72eca4293c..27d9329ebb5 100644
--- a/flink-python/pyflink/table/catalog.py
+++ b/flink-python/pyflink/table/catalog.py
@@ -1251,6 +1251,29 @@ class ObjectPath(object):
def get_full_name(self) -> str:
return self._j_object_path.getFullName()
+ def compare_to(self, other: 'ObjectPath') -> int:
+ return self._j_object_path.compareTo(other._j_object_path)
+
+ def __lt__(self, other):
+ if not isinstance(other, ObjectPath):
+ return NotImplemented
+ return self.compare_to(other) < 0
+
+ def __le__(self, other):
+ if not isinstance(other, ObjectPath):
+ return NotImplemented
+ return self.compare_to(other) <= 0
+
+ def __gt__(self, other):
+ if not isinstance(other, ObjectPath):
+ return NotImplemented
+ return self.compare_to(other) > 0
+
+ def __ge__(self, other):
+ if not isinstance(other, ObjectPath):
+ return NotImplemented
+ return self.compare_to(other) >= 0
+
@staticmethod
def from_string(full_name: str) -> 'ObjectPath':
gateway = get_gateway()
diff --git a/flink-python/pyflink/table/tests/test_catalog.py
b/flink-python/pyflink/table/tests/test_catalog.py
index aaeb86ad514..1e3023cc462 100644
--- a/flink-python/pyflink/table/tests/test_catalog.py
+++ b/flink-python/pyflink/table/tests/test_catalog.py
@@ -1037,3 +1037,163 @@ class CatalogTestBase(PyFlinkTestCase):
self.assertEqual(1,
len(self.catalog.list_partitions(
self.path1,
self.create_another_partition_spec_subset())))
+
+
+class ObjectPathTest(PyFlinkTestCase):
+ """Unit tests for ObjectPath covering construction, property
+ access, equality, hashing, string representation, comparison
+ operators and edge cases."""
+
+ def test_get_database_name(self):
+ path = ObjectPath("db", "table")
+ self.assertEqual("db", path.get_database_name())
+
+ def test_get_object_name(self):
+ path = ObjectPath("db", "table")
+ self.assertEqual("table", path.get_object_name())
+
+ def test_get_full_name(self):
+ path = ObjectPath("db", "table")
+ self.assertEqual("db.table", path.get_full_name())
+
+ def test_str(self):
+ path = ObjectPath("mydb", "mytable")
+ self.assertEqual("mydb.mytable", str(path))
+
+ def test_from_string(self):
+ path = ObjectPath.from_string("mydb.mytable")
+ self.assertEqual("mydb", path.get_database_name())
+ self.assertEqual("mytable", path.get_object_name())
+
+ # ---- __eq__ and __hash__ tests ----
+
+ def test_eq_same_path(self):
+ path1 = ObjectPath("db", "table")
+ path2 = ObjectPath("db", "table")
+ self.assertEqual(path1, path2)
+
+ def test_eq_different_database(self):
+ path1 = ObjectPath("db1", "table")
+ path2 = ObjectPath("db2", "table")
+ self.assertNotEqual(path1, path2)
+
+ def test_eq_different_object(self):
+ path1 = ObjectPath("db", "table1")
+ path2 = ObjectPath("db", "table2")
+ self.assertNotEqual(path1, path2)
+
+ def test_eq_non_object_path(self):
+ path = ObjectPath("db", "table")
+ self.assertNotEqual(path, "db.table")
+ self.assertNotEqual(path, 42)
+ self.assertNotEqual(path, None)
+
+ def test_hash_equal_objects(self):
+ path1 = ObjectPath("db", "table")
+ path2 = ObjectPath("db", "table")
+ self.assertEqual(hash(path1), hash(path2))
+
+ def test_hash_can_be_dict_key(self):
+ path1 = ObjectPath("db", "t1")
+ path2 = ObjectPath("db", "t2")
+ d = {path1: "value1", path2: "value2"}
+ self.assertEqual("value1", d[ObjectPath("db", "t1")])
+ self.assertEqual("value2", d[ObjectPath("db", "t2")])
+
+ def test_hash_can_be_in_set(self):
+ path1 = ObjectPath("db", "table")
+ path2 = ObjectPath("db", "table")
+ s = {path1, path2}
+ self.assertEqual(1, len(s))
+
+ # ---- Comparison operator tests (happy path) ----
+
+ def test_lt(self):
+ path_a = ObjectPath("a", "table")
+ path_b = ObjectPath("b", "table")
+ self.assertTrue(path_a < path_b)
+ self.assertFalse(path_b < path_a)
+
+ def test_lt_same(self):
+ path1 = ObjectPath("db", "table")
+ path2 = ObjectPath("db", "table")
+ self.assertFalse(path1 < path2)
+
+ def test_le(self):
+ path_a = ObjectPath("a", "table")
+ path_b = ObjectPath("b", "table")
+ path_a2 = ObjectPath("a", "table")
+ self.assertTrue(path_a <= path_b)
+ self.assertTrue(path_a <= path_a2)
+ self.assertFalse(path_b <= path_a)
+
+ def test_gt(self):
+ path_a = ObjectPath("a", "table")
+ path_b = ObjectPath("b", "table")
+ self.assertTrue(path_b > path_a)
+ self.assertFalse(path_a > path_b)
+
+ def test_gt_same(self):
+ path1 = ObjectPath("db", "table")
+ path2 = ObjectPath("db", "table")
+ self.assertFalse(path1 > path2)
+
+ def test_ge(self):
+ path_a = ObjectPath("a", "table")
+ path_b = ObjectPath("b", "table")
+ path_b2 = ObjectPath("b", "table")
+ self.assertTrue(path_b >= path_a)
+ self.assertTrue(path_b >= path_b2)
+ self.assertFalse(path_a >= path_b)
+
+ def test_compare_by_object_name(self):
+ """Within the same database, ordering is by object name."""
+ path1 = ObjectPath("db", "alpha")
+ path2 = ObjectPath("db", "beta")
+ self.assertTrue(path1 < path2)
+ self.assertTrue(path2 > path1)
+
+ def test_sorting(self):
+ """Verify that a list of ObjectPath instances can be correctly
sorted."""
+ paths = [
+ ObjectPath("db2", "table"),
+ ObjectPath("db1", "table"),
+ ObjectPath("db1", "alpha"),
+ ]
+ sorted_paths = sorted(paths)
+ self.assertEqual("db1.alpha", str(sorted_paths[0]))
+ self.assertEqual("db1.table", str(sorted_paths[1]))
+ self.assertEqual("db2.table", str(sorted_paths[2]))
+
+ # ---- Comparison with non-ObjectPath objects (edge cases) ----
+
+ def test_lt_non_object_path_raises_type_error(self):
+ """Comparison with a non-ObjectPath object should raise TypeError."""
+ path = ObjectPath("db", "table")
+ with self.assertRaises(TypeError):
+ path < 42
+
+ def test_le_non_object_path_raises_type_error(self):
+ path = ObjectPath("db", "table")
+ with self.assertRaises(TypeError):
+ path <= "some_string"
+
+ def test_gt_non_object_path_raises_type_error(self):
+ path = ObjectPath("db", "table")
+ with self.assertRaises(TypeError):
+ path > 3.14
+
+ def test_ge_non_object_path_raises_type_error(self):
+ path = ObjectPath("db", "table")
+ with self.assertRaises(TypeError):
+ path >= None
+
+ def test_comparison_with_list_raises_type_error(self):
+ path = ObjectPath("db", "table")
+ with self.assertRaises(TypeError):
+ path < ["db", "table"]
+
+ def test_comparison_with_dict_raises_type_error(self):
+ path = ObjectPath("db", "table")
+ with self.assertRaises(TypeError):
+ path >= {"db": "table"}
diff --git
a/flink-table/flink-table-common/src/main/java/org/apache/flink/table/catalog/ObjectPath.java
b/flink-table/flink-table-common/src/main/java/org/apache/flink/table/catalog/ObjectPath.java
index c50644af7e7..209d812c565 100644
---
a/flink-table/flink-table-common/src/main/java/org/apache/flink/table/catalog/ObjectPath.java
+++
b/flink-table/flink-table-common/src/main/java/org/apache/flink/table/catalog/ObjectPath.java
@@ -28,7 +28,7 @@ import static
org.apache.flink.util.Preconditions.checkArgument;
/** A database name and object (table/view/function) name combo in a catalog.
*/
@PublicEvolving
-public class ObjectPath implements Serializable {
+public class ObjectPath implements Serializable, Comparable<ObjectPath> {
private final String databaseName;
private final String objectName;
@@ -96,4 +96,13 @@ public class ObjectPath implements Serializable {
public String toString() {
return String.format("%s.%s", databaseName, objectName);
}
+
+ @Override
+ public int compareTo(ObjectPath other) {
+ int cmp = this.databaseName.compareTo(other.databaseName);
+ if (cmp != 0) {
+ return cmp;
+ }
+ return this.objectName.compareTo(other.objectName);
+ }
}
diff --git
a/flink-table/flink-table-common/src/test/java/org/apache/flink/table/catalog/ObjectPathTest.java
b/flink-table/flink-table-common/src/test/java/org/apache/flink/table/catalog/ObjectPathTest.java
new file mode 100644
index 00000000000..146d689850e
--- /dev/null
+++
b/flink-table/flink-table-common/src/test/java/org/apache/flink/table/catalog/ObjectPathTest.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.table.catalog;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/** Tests for {@link ObjectPath}. */
+class ObjectPathTest {
+
+ @Test
+ void testCompareToWithDifferentDatabaseName() {
+ ObjectPath path1 = new ObjectPath("aDatabase", "table1");
+ ObjectPath path2 = new ObjectPath("bDatabase", "table1");
+
+ assertThat(path1.compareTo(path2)).isLessThan(0);
+ assertThat(path2.compareTo(path1)).isGreaterThan(0);
+ }
+
+ @Test
+ void testCompareToWithSameDatabaseDifferentObjectName() {
+ ObjectPath path1 = new ObjectPath("myDb", "aTable");
+ ObjectPath path2 = new ObjectPath("myDb", "bTable");
+
+ assertThat(path1.compareTo(path2)).isLessThan(0);
+ assertThat(path2.compareTo(path1)).isGreaterThan(0);
+ }
+
+ @Test
+ void testCompareToWithEqualPaths() {
+ ObjectPath path1 = new ObjectPath("myDb", "myTable");
+ ObjectPath path2 = new ObjectPath("myDb", "myTable");
+
+ assertThat(path1.compareTo(path2)).isEqualTo(0);
+ }
+
+ @Test
+ void testCompareToWithSelf() {
+ ObjectPath path = new ObjectPath("myDb", "myTable");
+
+ assertThat(path.compareTo(path)).isEqualTo(0);
+ }
+
+ @Test
+ void testCompareToConsistentWithEquals() {
+ ObjectPath path1 = new ObjectPath("db", "table");
+ ObjectPath path2 = new ObjectPath("db", "table");
+
+ // compareTo == 0 should be consistent with equals
+ assertThat(path1.compareTo(path2) == 0).isEqualTo(path1.equals(path2));
+ }
+
+ @Test
+ void testSortingWithCollections() {
+ ObjectPath path1 = new ObjectPath("cDb", "zTable");
+ ObjectPath path2 = new ObjectPath("aDb", "mTable");
+ ObjectPath path3 = new ObjectPath("bDb", "aTable");
+ ObjectPath path4 = new ObjectPath("aDb", "aTable");
+
+ List<ObjectPath> paths = Arrays.asList(path1, path2, path3, path4);
+ paths.sort(null);
+
+ // After sorting: aDb.aTable, aDb.mTable, bDb.aTable, cDb.zTable
+ assertThat(paths).containsExactly(path4, path2, path3, path1);
+ }
+
+ @Test
+ void testCompareToTransitivity() {
+ ObjectPath path1 = new ObjectPath("aDb", "aTable");
+ ObjectPath path2 = new ObjectPath("bDb", "aTable");
+ ObjectPath path3 = new ObjectPath("cDb", "aTable");
+
+ // Transitivity: path1 < path2 and path2 < path3, then path1 < path3
+ assertThat(path1.compareTo(path2)).isLessThan(0);
+ assertThat(path2.compareTo(path3)).isLessThan(0);
+ assertThat(path1.compareTo(path3)).isLessThan(0);
+ }
+
+ @Test
+ void testCompareToDatabaseNameTakesPrecedence() {
+ // Even if objectName order is reversed, databaseName comparison takes
precedence
+ ObjectPath path1 = new ObjectPath("aDb", "zTable");
+ ObjectPath path2 = new ObjectPath("bDb", "aTable");
+
+ assertThat(path1.compareTo(path2)).isLessThan(0);
+ }
+}