|
20 | 20 | from collections.abc import Generator |
21 | 21 | from pathlib import Path, PosixPath |
22 | 22 |
|
| 23 | +import pyarrow as pa |
23 | 24 | import pytest |
24 | 25 | from pytest_lazy_fixtures import lf |
25 | 26 |
|
|
43 | 44 | from pyiceberg.table.metadata import INITIAL_SPEC_ID |
44 | 45 | from pyiceberg.table.sorting import INITIAL_SORT_ORDER_ID, SortField, SortOrder |
45 | 46 | from pyiceberg.transforms import BucketTransform, DayTransform, IdentityTransform |
46 | | -from pyiceberg.types import IntegerType, LongType, NestedField, TimestampType, UUIDType |
| 47 | +from pyiceberg.types import BooleanType, IntegerType, LongType, NestedField, StringType, TimestampType, UUIDType |
47 | 48 | from tests.conftest import ( |
48 | 49 | clean_up, |
49 | 50 | does_support_atomic_concurrent_updates, |
@@ -866,3 +867,63 @@ def test_load_missing_table(test_catalog: Catalog, database_name: str, table_nam |
866 | 867 |
|
867 | 868 | with pytest.raises(NoSuchTableError): |
868 | 869 | test_catalog.load_table(identifier) |
| 870 | + |
| 871 | + |
| 872 | +@pytest.mark.integration |
| 873 | +@pytest.mark.parametrize("test_catalog", CATALOGS) |
| 874 | +def test_replace_table(test_catalog: Catalog, database_name: str, table_name: str) -> None: |
| 875 | + test_catalog.create_namespace(database_name) |
| 876 | + identifier = (database_name, table_name) |
| 877 | + |
| 878 | + original_schema = Schema( |
| 879 | + NestedField(field_id=1, name="id", field_type=LongType(), required=False), |
| 880 | + NestedField(field_id=2, name="data", field_type=StringType(), required=False), |
| 881 | + ) |
| 882 | + original = test_catalog.create_table(identifier, schema=original_schema) |
| 883 | + original.append( |
| 884 | + pa.Table.from_pydict( |
| 885 | + {"id": [1, 2, 3], "data": ["a", "b", "c"]}, |
| 886 | + schema=pa.schema([pa.field("id", pa.int64()), pa.field("data", pa.large_string())]), |
| 887 | + ) |
| 888 | + ) |
| 889 | + original.refresh() |
| 890 | + original_snapshot_id = original.current_snapshot().snapshot_id # type: ignore[union-attr] |
| 891 | + |
| 892 | + new_schema = Schema( |
| 893 | + NestedField(field_id=1, name="id", field_type=LongType(), required=False), |
| 894 | + NestedField(field_id=2, name="name", field_type=StringType(), required=False), |
| 895 | + NestedField(field_id=3, name="active", field_type=BooleanType(), required=False), |
| 896 | + ) |
| 897 | + replaced = test_catalog.replace_table(identifier, schema=new_schema) |
| 898 | + |
| 899 | + assert replaced.metadata.table_uuid == original.metadata.table_uuid |
| 900 | + assert replaced.current_snapshot() is None |
| 901 | + assert any(s.snapshot_id == original_snapshot_id for s in replaced.metadata.snapshots) |
| 902 | + |
| 903 | + |
| 904 | +@pytest.mark.integration |
| 905 | +@pytest.mark.parametrize("test_catalog", CATALOGS) |
| 906 | +def test_replace_table_transaction(test_catalog: Catalog, database_name: str, table_name: str) -> None: |
| 907 | + test_catalog.create_namespace(database_name) |
| 908 | + identifier = (database_name, table_name) |
| 909 | + |
| 910 | + old_data = pa.Table.from_pydict( |
| 911 | + {"id": [1], "data": ["old"]}, |
| 912 | + schema=pa.schema([pa.field("id", pa.int64()), pa.field("data", pa.large_string())]), |
| 913 | + ) |
| 914 | + original = test_catalog.create_table(identifier, schema=old_data.schema) |
| 915 | + original.append(old_data) |
| 916 | + old_snapshot_id = test_catalog.load_table(identifier).current_snapshot().snapshot_id # type: ignore[union-attr] |
| 917 | + |
| 918 | + new_data = pa.Table.from_pydict( |
| 919 | + {"id": [10, 20], "name": ["alice", "bob"]}, |
| 920 | + schema=pa.schema([pa.field("id", pa.int64()), pa.field("name", pa.large_string())]), |
| 921 | + ) |
| 922 | + with test_catalog.replace_table_transaction(identifier, schema=new_data.schema) as txn: |
| 923 | + txn.append(new_data) |
| 924 | + |
| 925 | + replaced = test_catalog.load_table(identifier) |
| 926 | + assert replaced.current_snapshot() is not None |
| 927 | + assert replaced.current_snapshot().snapshot_id != old_snapshot_id # type: ignore[union-attr] |
| 928 | + assert any(s.snapshot_id == old_snapshot_id for s in replaced.metadata.snapshots) |
| 929 | + assert replaced.scan().to_arrow().num_rows == 2 |
0 commit comments