-
Notifications
You must be signed in to change notification settings - Fork 212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug Fix] cast None current-snapshot-id
as -1 for Backwards Compatibility
#473
Changes from 9 commits
710f913
d401045
cd38c5a
3a4ada5
7b810c7
fecbd4d
cc9ead5
a929d20
a102467
f4a302b
130b3cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,7 +28,7 @@ | |
Union, | ||
) | ||
|
||
from pydantic import Field, field_validator, model_validator | ||
from pydantic import Field, field_serializer, field_validator, model_validator | ||
from pydantic import ValidationError as PydanticValidationError | ||
from typing_extensions import Annotated | ||
|
||
|
@@ -50,6 +50,7 @@ | |
Properties, | ||
) | ||
from pyiceberg.types import transform_dict_value_to_str | ||
from pyiceberg.utils.config import Config | ||
from pyiceberg.utils.datetime import datetime_to_millis | ||
|
||
CURRENT_SNAPSHOT_ID = "current-snapshot-id" | ||
|
@@ -121,7 +122,7 @@ def check_sort_orders(table_metadata: TableMetadata) -> TableMetadata: | |
|
||
def construct_refs(table_metadata: TableMetadata) -> TableMetadata: | ||
"""Set the main branch if missing.""" | ||
if table_metadata.current_snapshot_id is not None: | ||
if table_metadata.current_snapshot_id is not None and table_metadata.current_snapshot_id != -1: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this -1 check still necessary? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right! I'll submit a fix thank you!
sungwy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if MAIN_BRANCH not in table_metadata.refs: | ||
table_metadata.refs[MAIN_BRANCH] = SnapshotRef( | ||
snapshot_id=table_metadata.current_snapshot_id, snapshot_ref_type=SnapshotRefType.BRANCH | ||
|
@@ -263,6 +264,12 @@ def sort_order_by_id(self, sort_order_id: int) -> Optional[SortOrder]: | |
"""Get the sort order by sort_order_id.""" | ||
return next((sort_order for sort_order in self.sort_orders if sort_order.order_id == sort_order_id), None) | ||
|
||
@field_serializer('current_snapshot_id') | ||
def serialize_current_snapshot_id(self, current_snapshot_id: Optional[int]) -> Optional[int]: | ||
if current_snapshot_id is None and Config().get_bool("legacy-current-snapshot-id"): | ||
return -1 | ||
return current_snapshot_id | ||
Comment on lines
+267
to
+271
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Beautiful! |
||
|
||
|
||
def _generate_snapshot_id() -> int: | ||
"""Generate a new Snapshot ID from a UUID. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# 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 json | ||
import os | ||
import uuid | ||
from typing import Any, Dict | ||
|
||
import pytest | ||
from pytest_mock import MockFixture | ||
|
||
from pyiceberg.serializers import ToOutputFile | ||
from pyiceberg.table import StaticTable | ||
from pyiceberg.table.metadata import TableMetadataV1 | ||
|
||
|
||
def test_legacy_current_snapshot_id( | ||
mocker: MockFixture, tmp_path_factory: pytest.TempPathFactory, example_table_metadata_no_snapshot_v1: Dict[str, Any] | ||
) -> None: | ||
from pyiceberg.io.pyarrow import PyArrowFileIO | ||
|
||
metadata_location = str(tmp_path_factory.mktemp("metadata") / f"{uuid.uuid4()}.metadata.json") | ||
metadata = TableMetadataV1(**example_table_metadata_no_snapshot_v1) | ||
ToOutputFile.table_metadata(metadata, PyArrowFileIO().new_output(location=metadata_location), overwrite=True) | ||
static_table = StaticTable.from_metadata(metadata_location) | ||
assert static_table.metadata.current_snapshot_id is None | ||
|
||
mocker.patch.dict(os.environ, values={"PYICEBERG_LEGACY_CURRENT_SNAPSHOT_ID": "True"}) | ||
|
||
ToOutputFile.table_metadata(metadata, PyArrowFileIO().new_output(location=metadata_location), overwrite=True) | ||
with PyArrowFileIO().new_input(location=metadata_location).open() as input_stream: | ||
metadata_json_bytes = input_stream.read() | ||
assert json.loads(metadata_json_bytes)['current-snapshot-id'] == -1 | ||
backwards_compatible_static_table = StaticTable.from_metadata(metadata_location) | ||
assert backwards_compatible_static_table.metadata.current_snapshot_id is None | ||
assert backwards_compatible_static_table.metadata == static_table.metadata |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe not a big deal: Shall we set
exclude_none=False
only in the legacy mode?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer that. Let me put in this update