Skip to content

Commit c05bde8

Browse files
Core: View history entry core implementation (apache#6565)
Co-authored-by: John Zhuge <jzhuge@apache.org>
1 parent e5ea152 commit c05bde8

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed

api/src/main/java/org/apache/iceberg/view/ViewHistoryEntry.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818
*/
1919
package org.apache.iceberg.view;
2020

21+
import org.immutables.value.Value;
22+
2123
/**
2224
* View history entry.
2325
*
2426
* <p>An entry contains a change to the view state. At the given timestamp, the current version was
2527
* set to the given version ID.
2628
*/
29+
@Value.Immutable
2730
public interface ViewHistoryEntry {
2831
/** Return the timestamp in milliseconds of the change */
2932
long timestampMillis();
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.iceberg.view;
20+
21+
import com.fasterxml.jackson.core.JsonGenerator;
22+
import com.fasterxml.jackson.databind.JsonNode;
23+
import java.io.IOException;
24+
import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
25+
import org.apache.iceberg.util.JsonUtil;
26+
27+
class ViewHistoryEntryParser {
28+
29+
private ViewHistoryEntryParser() {}
30+
31+
static final String VERSION_ID = "version-id";
32+
static final String TIMESTAMP_MS = "timestamp-ms";
33+
34+
static String toJson(ViewHistoryEntry entry) {
35+
return JsonUtil.generate(gen -> toJson(entry, gen), false);
36+
}
37+
38+
static void toJson(ViewHistoryEntry entry, JsonGenerator generator) throws IOException {
39+
Preconditions.checkArgument(entry != null, "Invalid view history entry: null");
40+
generator.writeStartObject();
41+
generator.writeNumberField(TIMESTAMP_MS, entry.timestampMillis());
42+
generator.writeNumberField(VERSION_ID, entry.versionId());
43+
generator.writeEndObject();
44+
}
45+
46+
static ViewHistoryEntry fromJson(String json) {
47+
return JsonUtil.parse(json, ViewHistoryEntryParser::fromJson);
48+
}
49+
50+
static ViewHistoryEntry fromJson(JsonNode node) {
51+
Preconditions.checkArgument(node != null, "Cannot parse view history entry from null object");
52+
Preconditions.checkArgument(
53+
node.isObject(), "Cannot parse view history entry from non-object: %s", node);
54+
return ImmutableViewHistoryEntry.builder()
55+
.versionId(JsonUtil.getInt(VERSION_ID, node))
56+
.timestampMillis(JsonUtil.getLong(TIMESTAMP_MS, node))
57+
.build();
58+
}
59+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.iceberg.view;
20+
21+
import com.fasterxml.jackson.databind.JsonNode;
22+
import org.assertj.core.api.Assertions;
23+
import org.junit.Assert;
24+
import org.junit.Test;
25+
26+
public class TestViewHistoryEntryParser {
27+
28+
@Test
29+
public void testViewHistoryEntryFromJson() {
30+
String json = "{\"timestamp-ms\":123,\"version-id\":1}";
31+
ViewHistoryEntry viewHistoryEntry =
32+
ImmutableViewHistoryEntry.builder().versionId(1).timestampMillis(123).build();
33+
Assert.assertEquals(
34+
"Should be able to deserialize valid view history entry",
35+
viewHistoryEntry,
36+
ViewHistoryEntryParser.fromJson(json));
37+
}
38+
39+
@Test
40+
public void testViewHistoryEntryToJson() {
41+
String json = "{\"timestamp-ms\":123,\"version-id\":1}";
42+
ViewHistoryEntry viewHistoryEntry =
43+
ImmutableViewHistoryEntry.builder().versionId(1).timestampMillis(123).build();
44+
Assert.assertEquals(
45+
"Should be able to serialize view history entry",
46+
json,
47+
ViewHistoryEntryParser.toJson(viewHistoryEntry));
48+
}
49+
50+
@Test
51+
public void testNullViewHistoryEntry() {
52+
Assertions.assertThatThrownBy(() -> ViewHistoryEntryParser.fromJson((JsonNode) null))
53+
.isInstanceOf(IllegalArgumentException.class)
54+
.hasMessage("Cannot parse view history entry from null object");
55+
56+
Assertions.assertThatThrownBy(() -> ViewHistoryEntryParser.toJson(null))
57+
.isInstanceOf(IllegalArgumentException.class)
58+
.hasMessage("Invalid view history entry: null");
59+
}
60+
61+
@Test
62+
public void testViewHistoryEntryMissingFields() {
63+
Assertions.assertThatThrownBy(() -> ViewHistoryEntryParser.fromJson("{}"))
64+
.isInstanceOf(IllegalArgumentException.class)
65+
.hasMessage("Cannot parse missing int: version-id");
66+
67+
Assertions.assertThatThrownBy(
68+
() -> ViewHistoryEntryParser.fromJson("{\"timestamp-ms\":\"123\"}"))
69+
.isInstanceOf(IllegalArgumentException.class)
70+
.hasMessage("Cannot parse missing int: version-id");
71+
72+
Assertions.assertThatThrownBy(() -> ViewHistoryEntryParser.fromJson("{\"version-id\":1}"))
73+
.isInstanceOf(IllegalArgumentException.class)
74+
.hasMessage("Cannot parse missing long: timestamp-ms");
75+
}
76+
}

0 commit comments

Comments
 (0)