You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by bl...@apache.org on 2022/10/07 20:53:48 UTC
[iceberg] branch master updated: Python: Add partition_type to partition_spec (#5929)
This is an automated email from the ASF dual-hosted git repository.
blue pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iceberg.git
The following commit(s) were added to refs/heads/master by this push:
new bc62cf8dab Python: Add partition_type to partition_spec (#5929)
bc62cf8dab is described below
commit bc62cf8dab42df2b113f9e56f846425daf22123b
Author: Fokko Driesprong <fo...@apache.org>
AuthorDate: Fri Oct 7 22:53:43 2022 +0200
Python: Add partition_type to partition_spec (#5929)
---
python/pyiceberg/table/partitioning.py | 27 +++++++++++++++++++++++++--
python/tests/table/test_partitioning.py | 20 ++++++++++++++++++++
2 files changed, 45 insertions(+), 2 deletions(-)
diff --git a/python/pyiceberg/table/partitioning.py b/python/pyiceberg/table/partitioning.py
index 8dcbf68454..1445a3f327 100644
--- a/python/pyiceberg/table/partitioning.py
+++ b/python/pyiceberg/table/partitioning.py
@@ -27,6 +27,7 @@ from pydantic import Field
from pyiceberg.schema import Schema
from pyiceberg.transforms import Transform
+from pyiceberg.types import NestedField, StructType
from pyiceberg.utils.iceberg_base_model import IcebergBaseModel
INITIAL_PARTITION_SPEC_ID = 0
@@ -77,9 +78,8 @@ class PartitionSpec(IcebergBaseModel):
PartitionSpec captures the transformation from table data to partition values
Attributes:
- schema(Schema): the schema of data table
spec_id(int): any change to PartitionSpec will produce a new specId
- fields(List[PartitionField): list of partition fields to produce partition values
+ fields(Tuple[PartitionField): list of partition fields to produce partition values
"""
spec_id: int = Field(alias="spec-id", default=INITIAL_PARTITION_SPEC_ID)
@@ -158,6 +158,29 @@ class PartitionSpec(IcebergBaseModel):
for this_field, that_field in zip(self.fields, other.fields)
)
+ def partition_type(self, schema: Schema) -> StructType:
+ """Produces a struct of the PartitionSpec
+
+ The partition fields should be optional:
+
+ - All partition transforms are required to produce null if the input value is null, so it can
+ happen when the source column is optional
+ - Partition fields may be added later, in which case not all files would have the result field,
+ and it may be null.
+
+ There is a case where we can guarantee that a partition field in the first and only partition spec
+ that uses a required source column will never be null, but it doesn't seem worth tracking this case.
+
+ :param schema: The schema to bind to
+ :return: A StructType that represents the PartitionSpec, with a NestedField for each PartitionField
+ """
+ nested_fields = []
+ for field in self.fields:
+ source_type = schema.find_type(field.source_id)
+ result_type = field.transform.result_type(source_type)
+ nested_fields.append(NestedField(field.field_id, field.name, result_type, required=False))
+ return StructType(*nested_fields)
+
UNPARTITIONED_PARTITION_SPEC = PartitionSpec(spec_id=0)
diff --git a/python/tests/table/test_partitioning.py b/python/tests/table/test_partitioning.py
index 9aa0f73891..b3cbf30f8f 100644
--- a/python/tests/table/test_partitioning.py
+++ b/python/tests/table/test_partitioning.py
@@ -14,8 +14,15 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+from pyiceberg.schema import Schema
from pyiceberg.table.partitioning import UNPARTITIONED_PARTITION_SPEC, PartitionField, PartitionSpec
from pyiceberg.transforms import BucketTransform, TruncateTransform
+from pyiceberg.types import (
+ IntegerType,
+ NestedField,
+ StringType,
+ StructType,
+)
def test_partition_field_init():
@@ -102,3 +109,16 @@ def test_deserialize_partition_spec():
PartitionField(source_id=2, field_id=1001, transform=BucketTransform(num_buckets=25), name="int_bucket"),
),
)
+
+
+def test_partition_type(table_schema_simple: Schema) -> None:
+ spec = PartitionSpec(
+ PartitionField(source_id=1, field_id=1000, transform=TruncateTransform(width=19), name="str_truncate"),
+ PartitionField(source_id=2, field_id=1001, transform=BucketTransform(num_buckets=25), name="int_bucket"),
+ spec_id=3,
+ )
+
+ assert spec.partition_type(table_schema_simple) == StructType(
+ NestedField(field_id=1000, name="str_truncate", field_type=StringType(), required=False),
+ NestedField(field_id=1001, name="int_bucket", field_type=IntegerType(), required=False),
+ )