This is an automated email from the ASF dual-hosted git repository.

jshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 2034a09792 [#8626] feat(client-python): add generic column (#8998)
2034a09792 is described below

commit 2034a097922975a01060451efbb9d767c25bbb42
Author: George T. C. Lai <[email protected]>
AuthorDate: Wed Nov 5 15:17:23 2025 +0800

    [#8626] feat(client-python): add generic column (#8998)
    
    ### What changes were proposed in this pull request?
    
    This PR is aimed at implementing class `GenericColumn` in Java client.
    
    - GenericColumn.java
    
    ### Why are the changes needed?
    
    Before being able to implement `RelationalTable`, we need to create
    class `GenericColumn`.
    
    Fix: #8626
    
    ### Does this PR introduce _any_ user-facing change?
    
    No
    
    ### How was this patch tested?
    
    Unit tests
    
    ---------
    
    Signed-off-by: George T. C. Lai <[email protected]>
---
 clients/client-python/gravitino/api/rel/column.py  |   6 +-
 .../gravitino/client/generic_column.py             |  65 ++++++++++++
 .../tests/unittests/api/rel/test_column.py         |  16 +++
 .../tests/unittests/test_generic_column.py         | 114 +++++++++++++++++++++
 4 files changed, 200 insertions(+), 1 deletion(-)

diff --git a/clients/client-python/gravitino/api/rel/column.py 
b/clients/client-python/gravitino/api/rel/column.py
index 2a5b4ca52d..8631730e06 100644
--- a/clients/client-python/gravitino/api/rel/column.py
+++ b/clients/client-python/gravitino/api/rel/column.py
@@ -219,6 +219,10 @@ class ColumnImpl(Column):
                 self._comment,
                 self._nullable,
                 self._auto_increment,
-                tuple(self._default_value),
+                (
+                    tuple(self._default_value)
+                    if self._default_value is Column.DEFAULT_VALUE_NOT_SET
+                    else self._default_value
+                ),
             )
         )
diff --git a/clients/client-python/gravitino/client/generic_column.py 
b/clients/client-python/gravitino/client/generic_column.py
new file mode 100644
index 0000000000..dd6aff5a6b
--- /dev/null
+++ b/clients/client-python/gravitino/client/generic_column.py
@@ -0,0 +1,65 @@
+# 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.
+
+from typing import Optional, cast
+
+from gravitino.api.rel.column import Column
+from gravitino.api.rel.expressions.expression import Expression
+from gravitino.api.rel.types.type import Type
+from gravitino.utils import HTTPClient
+
+
+class GenericColumn(Column):
+    """Represents a generic column."""
+
+    def __init__(
+        self,
+        column: Column,
+        rest_client: HTTPClient,
+        metalake: str,
+        catalog: str,
+        schema: str,
+        table: str,
+    ):
+        self._internal_column = column
+
+    def name(self) -> str:
+        return self._internal_column.name()
+
+    def data_type(self) -> Type:
+        return self._internal_column.data_type()
+
+    def comment(self) -> Optional[str]:
+        return self._internal_column.comment()
+
+    def nullable(self) -> bool:
+        return self._internal_column.nullable()
+
+    def auto_increment(self) -> bool:
+        return self._internal_column.auto_increment()
+
+    def default_value(self) -> Expression:
+        return self._internal_column.default_value()
+
+    def __hash__(self) -> int:
+        return hash(self._internal_column)
+
+    def __eq__(self, value: object) -> bool:
+        if not isinstance(value, GenericColumn):
+            return False
+        column = cast(GenericColumn, value)
+        return self._internal_column == column._internal_column
diff --git a/clients/client-python/tests/unittests/api/rel/test_column.py 
b/clients/client-python/tests/unittests/api/rel/test_column.py
index b03a88608b..cb04dfc3f3 100644
--- a/clients/client-python/tests/unittests/api/rel/test_column.py
+++ b/clients/client-python/tests/unittests/api/rel/test_column.py
@@ -21,7 +21,9 @@ from unittest.mock import Mock
 from gravitino.api.rel.column import Column, ColumnImpl
 from gravitino.api.rel.expressions.expression import Expression
 from gravitino.api.rel.expressions.function_expression import 
FunctionExpression
+from gravitino.api.rel.expressions.literals.literals import Literals
 from gravitino.api.rel.types.type import Type
+from gravitino.api.rel.types.types import Types
 from gravitino.exceptions.base import (
     IllegalArgumentException,
     UnsupportedOperationException,
@@ -90,6 +92,20 @@ class TestColumn(unittest.TestCase):
         self.assertEqual(hash(col1), hash(col2))
         self.assertNotEqual(hash(col1), hash(col3))
 
+        col4 = Column.of(
+            name="test",
+            data_type=Types.StringType.get(),
+            comment="comment",
+            default_value=Literals.string_literal(value="test"),
+        )
+        col5 = Column.of(
+            name="test",
+            data_type=Types.StringType.get(),
+            comment="comment",
+            default_value=Literals.string_literal(value="test"),
+        )
+        self.assertEqual(hash(col4), hash(col5))
+
     def test_supports_tags_raises_exception(self):
         """Test that supports_tags raises `UnsupportedOperationException`."""
 
diff --git a/clients/client-python/tests/unittests/test_generic_column.py 
b/clients/client-python/tests/unittests/test_generic_column.py
new file mode 100644
index 0000000000..97fab80a23
--- /dev/null
+++ b/clients/client-python/tests/unittests/test_generic_column.py
@@ -0,0 +1,114 @@
+# 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.
+
+import unittest
+
+from gravitino.api.rel.column import Column
+from gravitino.api.rel.expressions.literals.literals import Literals
+from gravitino.api.rel.types.types import Types
+from gravitino.client.generic_column import GenericColumn
+from gravitino.utils import HTTPClient
+
+
+class TestGenericColumn(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls._rest_client = HTTPClient("http://localhost:8090";)
+        cls._metalake_name = "metalake_demo"
+        cls._catalog_name = "relational_catalog"
+        cls._schema_name = "test_schema"
+        cls._table_name = "test_table"
+        cls._column_name = "test_column"
+        cls._column_data_type = Types.StringType.get()
+        cls._column_default_value = Literals.string_literal(value="test")
+        cls._column = Column.of(
+            name=TestGenericColumn._column_name,
+            data_type=TestGenericColumn._column_data_type,
+            nullable=False,
+            default_value=TestGenericColumn._column_default_value,
+        )
+        cls._generic_column = GenericColumn(
+            column=TestGenericColumn._column,
+            rest_client=TestGenericColumn._rest_client,
+            metalake=TestGenericColumn._metalake_name,
+            catalog=TestGenericColumn._catalog_name,
+            schema=TestGenericColumn._schema_name,
+            table=TestGenericColumn._table_name,
+        )
+
+    def test_generic_column(self):
+        self.assertEqual(
+            TestGenericColumn._generic_column.name(), 
TestGenericColumn._column.name()
+        )
+        self.assertEqual(
+            TestGenericColumn._generic_column.data_type(),
+            TestGenericColumn._column.data_type(),
+        )
+        self.assertEqual(
+            TestGenericColumn._generic_column.nullable(),
+            TestGenericColumn._column.nullable(),
+        )
+        self.assertEqual(
+            TestGenericColumn._generic_column.default_value(),
+            TestGenericColumn._column.default_value(),
+        )
+        self.assertEqual(
+            TestGenericColumn._generic_column.auto_increment(),
+            TestGenericColumn._column.auto_increment(),
+        )
+        self.assertEqual(
+            TestGenericColumn._generic_column.comment(),
+            TestGenericColumn._column.comment(),
+        )
+
+    def test_generic_column_hash(self):
+        another_column = Column.of(
+            name="another_column",
+            data_type=TestGenericColumn._column_data_type,
+            nullable=False,
+            default_value=TestGenericColumn._column_default_value,
+        )
+        another_generic_column = GenericColumn(
+            column=another_column,
+            rest_client=TestGenericColumn._rest_client,
+            metalake=TestGenericColumn._metalake_name,
+            catalog=TestGenericColumn._catalog_name,
+            schema=TestGenericColumn._schema_name,
+            table=TestGenericColumn._table_name,
+        )
+        self.assertNotEqual(
+            hash(TestGenericColumn._generic_column),
+            hash(another_generic_column),
+        )
+
+    def test_generic_column_equality(self):
+        another_column = Column.of(
+            name=TestGenericColumn._column_name,
+            data_type=TestGenericColumn._column_data_type,
+            nullable=False,
+            default_value=TestGenericColumn._column_default_value,
+        )
+        another_generic_column = GenericColumn(
+            column=another_column,
+            rest_client=TestGenericColumn._rest_client,
+            metalake=TestGenericColumn._metalake_name,
+            catalog=TestGenericColumn._catalog_name,
+            schema=TestGenericColumn._schema_name,
+            table=TestGenericColumn._table_name,
+        )
+        self.assertEqual(TestGenericColumn._generic_column, 
another_generic_column)
+        self.assertFalse(another_generic_column == "invalid_generic_column")

Reply via email to