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 cb4c690630 [#5199] feat(client-python): add sort order DTO (#8220)
cb4c690630 is described below

commit cb4c69063063ebdf146089f494876957125a1599
Author: George T. C. Lai <[email protected]>
AuthorDate: Thu Aug 21 14:41:03 2025 +0800

    [#5199] feat(client-python): add sort order DTO (#8220)
    
    ### What changes were proposed in this pull request?
    
    This PR is aimed at implementing class `SortOrderDTO` corresponding to
    the one in Java client.
    
    ### Why are the changes needed?
    
    We need to support table partitioning, bucketing and sort ordering and
    indexes
    
    #5199
    
    ### 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]>
---
 .../gravitino/dto/rel/sort_order_dto.py            | 85 ++++++++++++++++++++++
 .../tests/unittests/dto/rel/test_sort_order_dto.py | 68 +++++++++++++++++
 2 files changed, 153 insertions(+)

diff --git a/clients/client-python/gravitino/dto/rel/sort_order_dto.py 
b/clients/client-python/gravitino/dto/rel/sort_order_dto.py
new file mode 100644
index 0000000000..3d6fa77a08
--- /dev/null
+++ b/clients/client-python/gravitino/dto/rel/sort_order_dto.py
@@ -0,0 +1,85 @@
+# 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 ClassVar, List
+
+from gravitino.api.expressions.expression import Expression
+from gravitino.api.expressions.sorts.null_ordering import NullOrdering
+from gravitino.api.expressions.sorts.sort_direction import SortDirection
+from gravitino.api.expressions.sorts.sort_order import SortOrder
+from gravitino.dto.rel.column_dto import ColumnDTO
+from gravitino.dto.rel.expressions.function_arg import FunctionArg
+from gravitino.utils.precondition import Precondition
+
+
+class SortOrderDTO(SortOrder):
+    """Data Transfer Object for SortOrder.
+
+    Attributes:
+        EMPTY_SORT (List[SortOrderDTO]):
+            An empty array of SortOrderDTO.
+    """
+
+    EMPTY_SORT: ClassVar[List["SortOrderDTO"]] = []
+
+    def __init__(
+        self,
+        sort_term: FunctionArg,
+        direction: SortDirection,
+        null_ordering: NullOrdering,
+    ):
+        Precondition.check_argument(sort_term is not None, "expression cannot 
be null")
+
+        self._sort_term = sort_term
+        self._direction = (
+            direction if direction is not None else SortDirection.ASCENDING
+        )
+        self._null_ordering = (
+            null_ordering
+            if null_ordering is not None
+            else direction.default_null_ordering()
+        )
+
+    def sort_term(self) -> FunctionArg:
+        """Returns the sort term.
+
+        Returns:
+            FunctionArg: The sort term.
+        """
+        return self._sort_term
+
+    def expression(self) -> Expression:
+        return self._sort_term
+
+    def direction(self):
+        return self._direction
+
+    def null_ordering(self):
+        return self._null_ordering
+
+    def validate(self, columns: List[ColumnDTO]) -> None:
+        """Validates the sort order.
+
+        Args:
+            columns (List[ColumnDTO]):
+                The column DTOs to validate against.
+
+        Raises:
+            IllegalArgumentException:
+                If the sort order is invalid, this exception is thrown.
+        """
+        self._sort_term.validate(columns)
diff --git 
a/clients/client-python/tests/unittests/dto/rel/test_sort_order_dto.py 
b/clients/client-python/tests/unittests/dto/rel/test_sort_order_dto.py
new file mode 100644
index 0000000000..e7cdf8950a
--- /dev/null
+++ b/clients/client-python/tests/unittests/dto/rel/test_sort_order_dto.py
@@ -0,0 +1,68 @@
+# 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.expressions.sorts.null_ordering import NullOrdering
+from gravitino.api.expressions.sorts.sort_direction import SortDirection
+from gravitino.api.types.types import Types
+from gravitino.dto.rel.column_dto import ColumnDTO
+from gravitino.dto.rel.expressions.field_reference_dto import FieldReferenceDTO
+from gravitino.dto.rel.sort_order_dto import SortOrderDTO
+from gravitino.exceptions.base import IllegalArgumentException
+
+
+class TestSortOrderDTO(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls.field_ref_dto = (
+            FieldReferenceDTO.builder().with_field_name(["field1"]).build()
+        )
+        cls.columns = [
+            ColumnDTO.builder()
+            .with_name("field1")
+            .with_data_type(Types.StringType.get())
+            .build(),
+            ColumnDTO.builder()
+            .with_name("field2")
+            .with_data_type(Types.StringType.get())
+            .build(),
+        ]
+        cls.sort_order_dto = SortOrderDTO(
+            cls.field_ref_dto,
+            SortDirection.ASCENDING,
+            NullOrdering.NULLS_FIRST,
+        )
+
+    def test_sort_dto_class_vars(self):
+        self.assertEqual(SortOrderDTO.EMPTY_SORT, [])
+        self.assertEqual(SortOrderDTO.EMPTY_EXPRESSION, [])
+        self.assertEqual(SortOrderDTO.EMPTY_NAMED_REFERENCE, [])
+
+    def test_sort_order_dto_init(self):
+        with self.assertRaisesRegex(
+            IllegalArgumentException, "expression cannot be null"
+        ):
+            SortOrderDTO(None, SortDirection.ASCENDING, 
NullOrdering.NULLS_FIRST)
+
+        self.sort_order_dto.validate(self.columns)
+        self.assertTrue(self.sort_order_dto.sort_term() == self.field_ref_dto)
+        self.assertIs(self.sort_order_dto.direction(), SortDirection.ASCENDING)
+        self.assertIs(self.sort_order_dto.null_ordering(), 
NullOrdering.NULLS_FIRST)
+        self.assertEqual(
+            self.sort_order_dto.expression(), self.sort_order_dto.sort_term()
+        )

Reply via email to