blob: 10d3eec2ab600c6bd3a4b489369a6c538823e8d8 [file]
# 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 datetime import time
import unittest
import pyarrow as pa
from pypaimon.execution.python.read.map_shared_shredding import assemble_shared_shredding_map
class SharedShreddingFullRestoreTest(unittest.TestCase):
def test_entry_order_duplicates_unknown_ids_and_slices(self):
for value_type, value in [
(pa.int64(), 9007199254740993),
(pa.list_(pa.int64()), [None, 1]),
(pa.struct([("x", pa.int64())]), {"x": 1}),
(pa.map_(pa.string(), pa.int64()), [("x", None)]),
]:
for mapping_type in [pa.list_(pa.int32()), pa.large_list(pa.int32())]:
with self.subTest(value_type=value_type, mapping_type=mapping_type):
mapping = pa.array([[0, 0], [-1, 99], None, [-1, -1], [1, 0]], type=mapping_type)
values = pa.array([value] * 5, type=value_type)
overflow = pa.array(
[[(0, value), (99, value), (-1, None)], [(1, None)], [(0, value)], None, []],
type=pa.map_(pa.int32(), value_type),
)
column = pa.StructArray.from_arrays(
[mapping, values, pa.nulls(5, type=value_type), overflow],
names=["__field_mapping", "__col_0", "__col_1", "__overflow"],
mask=pa.array([False, False, True, False, False]),
)
expected = [
[("a", value), ("a", None), ("a", value), ("neg", None)],
[("b", None)],
None,
[],
[("b", value), ("a", None)],
]
column = pa.concat_arrays([column] * 9)
expected = expected * 9
for start, size in [(0, 45), (1, 44), (3, 31), (3, 32), (3, 33), (3, 1), (2, 0)]:
result = assemble_shared_shredding_map(
column.slice(start, size), pa.map_(pa.string(), value_type), {0: "a", 1: "b", -1: "neg"}, 2
)
end = start + size
self.assertEqual(expected[start:end], result.to_pylist())
self.assertEqual(pa.map_(pa.string(), value_type), result.type)
def test_mapping_validation_and_missing_columns(self):
for mapping, message in [([0], "length"), ([None, 0], "contain null"), (None, "length"), ([0, 1], "Missing")]:
column = pa.StructArray.from_arrays(
[pa.array([[-1, -1]] * 32 + [mapping], type=pa.list_(pa.int32()))], names=["__field_mapping"]
)
with self.subTest(mapping=mapping):
with self.assertRaisesRegex(ValueError, message):
assemble_shared_shredding_map(column, pa.map_(pa.string(), pa.int64()), {0: "a", 1: "b"}, 2)
column = pa.StructArray.from_arrays(
[pa.array([[-1, 99]], type=pa.list_(pa.int32()))], names=["__field_mapping"]
)
self.assertEqual(
[[]], assemble_shared_shredding_map(column, pa.map_(pa.string(), pa.int64()), {0: "a"}, 2).to_pylist()
)
def test_orc_time_and_no_physical_columns(self):
column = pa.StructArray.from_arrays(
[
pa.array([[], []], type=pa.list_(pa.int32())),
pa.array([[(0, 1234)], []], type=pa.map_(pa.int32(), pa.int32())),
],
names=["__field_mapping", "__overflow"],
)
result = assemble_shared_shredding_map(column, pa.map_(pa.string(), pa.time32("ms")), {0: "a"}, 0)
self.assertEqual([[("a", time(0, 0, 1, 234000))], []], result.to_pylist())
def test_large_integer_ids_are_not_rounded(self):
field_id = 2**63 + 1
column = pa.StructArray.from_arrays(
[pa.array([[field_id]] * 34, type=pa.large_list(pa.uint64())), pa.array(range(34), type=pa.int64())],
names=["__field_mapping", "__col_0"],
)
result = assemble_shared_shredding_map(
column.slice(1, 32), pa.map_(pa.string(), pa.int64()), {field_id: "a"}, 1
)
self.assertEqual([[("a", row)] for row in range(1, 33)], result.to_pylist())