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")