|
48 | 48 | from pyiceberg.table.sorting import SortField, SortOrder |
49 | 49 | from pyiceberg.transforms import IdentityTransform, TruncateTransform |
50 | 50 | from pyiceberg.typedef import RecursiveDict |
| 51 | +from pyiceberg.types import StringType |
51 | 52 | from pyiceberg.utils.config import Config |
52 | 53 |
|
53 | 54 | TEST_URI = "https://iceberg-test-catalog/" |
@@ -2155,3 +2156,86 @@ def test_view_endpoints_enabled_with_config(self, requests_mock: Mocker) -> None |
2155 | 2156 | # View endpoints should be supported when enabled |
2156 | 2157 | catalog._check_endpoint(Capability.V1_LIST_VIEWS) |
2157 | 2158 | catalog._check_endpoint(Capability.V1_DELETE_VIEW) |
| 2159 | + |
| 2160 | + |
| 2161 | +def test_table_uuid_check_on_commit(rest_mock: Mocker, example_table_metadata_v2: dict[str, Any]) -> None: |
| 2162 | + original_uuid = "9c12d441-03fe-4693-9a96-a0705ddf69c1" |
| 2163 | + different_uuid = "550e8400-e29b-41d4-a716-446655440000" |
| 2164 | + metadata_location = "s3://warehouse/database/table/metadata.json" |
| 2165 | + |
| 2166 | + rest_mock.get( |
| 2167 | + f"{TEST_URI}v1/namespaces/namespace/tables/table_name", |
| 2168 | + json={ |
| 2169 | + "metadata-location": metadata_location, |
| 2170 | + "metadata": example_table_metadata_v2, |
| 2171 | + "config": {}, |
| 2172 | + }, |
| 2173 | + status_code=200, |
| 2174 | + request_headers=TEST_HEADERS, |
| 2175 | + ) |
| 2176 | + |
| 2177 | + catalog = RestCatalog("rest", uri=TEST_URI, token=TEST_TOKEN) |
| 2178 | + table = catalog.load_table(("namespace", "table_name")) |
| 2179 | + |
| 2180 | + assert str(table.metadata.table_uuid) == original_uuid |
| 2181 | + |
| 2182 | + metadata_with_different_uuid = {**example_table_metadata_v2, "table-uuid": different_uuid} |
| 2183 | + |
| 2184 | + rest_mock.post( |
| 2185 | + f"{TEST_URI}v1/namespaces/namespace/tables/table_name", |
| 2186 | + json={ |
| 2187 | + "metadata-location": metadata_location, |
| 2188 | + "metadata": metadata_with_different_uuid, |
| 2189 | + }, |
| 2190 | + status_code=200, |
| 2191 | + request_headers=TEST_HEADERS, |
| 2192 | + ) |
| 2193 | + |
| 2194 | + with pytest.raises(ValueError) as exc_info: |
| 2195 | + table.update_schema().add_column("new_col", StringType()).commit() |
| 2196 | + |
| 2197 | + assert "Table UUID does not match" in str(exc_info.value) |
| 2198 | + assert f"current={original_uuid}" in str(exc_info.value) |
| 2199 | + assert f"refreshed={different_uuid}" in str(exc_info.value) |
| 2200 | + |
| 2201 | + |
| 2202 | +def test_table_uuid_check_on_refresh(rest_mock: Mocker, example_table_metadata_v2: dict[str, Any]) -> None: |
| 2203 | + original_uuid = "9c12d441-03fe-4693-9a96-a0705ddf69c1" |
| 2204 | + different_uuid = "550e8400-e29b-41d4-a716-446655440000" |
| 2205 | + metadata_location = "s3://warehouse/database/table/metadata.json" |
| 2206 | + |
| 2207 | + rest_mock.get( |
| 2208 | + f"{TEST_URI}v1/namespaces/namespace/tables/table_name", |
| 2209 | + json={ |
| 2210 | + "metadata-location": metadata_location, |
| 2211 | + "metadata": example_table_metadata_v2, |
| 2212 | + "config": {}, |
| 2213 | + }, |
| 2214 | + status_code=200, |
| 2215 | + request_headers=TEST_HEADERS, |
| 2216 | + ) |
| 2217 | + |
| 2218 | + catalog = RestCatalog("rest", uri=TEST_URI, token=TEST_TOKEN) |
| 2219 | + table = catalog.load_table(("namespace", "table_name")) |
| 2220 | + |
| 2221 | + assert str(table.metadata.table_uuid) == original_uuid |
| 2222 | + |
| 2223 | + metadata_with_different_uuid = {**example_table_metadata_v2, "table-uuid": different_uuid} |
| 2224 | + |
| 2225 | + rest_mock.get( |
| 2226 | + f"{TEST_URI}v1/namespaces/namespace/tables/table_name", |
| 2227 | + json={ |
| 2228 | + "metadata-location": metadata_location, |
| 2229 | + "metadata": metadata_with_different_uuid, |
| 2230 | + "config": {}, |
| 2231 | + }, |
| 2232 | + status_code=200, |
| 2233 | + request_headers=TEST_HEADERS, |
| 2234 | + ) |
| 2235 | + |
| 2236 | + with pytest.raises(ValueError) as exc_info: |
| 2237 | + table.refresh() |
| 2238 | + |
| 2239 | + assert "Table UUID does not match" in str(exc_info.value) |
| 2240 | + assert f"current={original_uuid}" in str(exc_info.value) |
| 2241 | + assert f"refreshed={different_uuid}" in str(exc_info.value) |
0 commit comments