org.apache.iceberg.SingleValueParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of iceberg-core Show documentation
Show all versions of iceberg-core Show documentation
A table format for huge analytic datasets
The newest version!
/*
* 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.
*/
package org.apache.iceberg;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import org.apache.iceberg.data.GenericRecord;
import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
import org.apache.iceberg.relocated.com.google.common.collect.Iterables;
import org.apache.iceberg.relocated.com.google.common.collect.Lists;
import org.apache.iceberg.relocated.com.google.common.io.BaseEncoding;
import org.apache.iceberg.types.Type;
import org.apache.iceberg.types.Types;
import org.apache.iceberg.util.ByteBuffers;
import org.apache.iceberg.util.DateTimeUtil;
import org.apache.iceberg.util.JsonUtil;
public class SingleValueParser {
private SingleValueParser() {}
private static final String KEYS = "keys";
private static final String VALUES = "values";
public static Object fromJson(Type type, JsonNode defaultValue) {
if (defaultValue == null || defaultValue.isNull()) {
return null;
}
switch (type.typeId()) {
case BOOLEAN:
Preconditions.checkArgument(
defaultValue.isBoolean(), "Cannot parse default as a %s value: %s", type, defaultValue);
return defaultValue.booleanValue();
case INTEGER:
Preconditions.checkArgument(
defaultValue.isIntegralNumber() && defaultValue.canConvertToInt(),
"Cannot parse default as a %s value: %s",
type,
defaultValue);
return defaultValue.intValue();
case LONG:
Preconditions.checkArgument(
defaultValue.isIntegralNumber() && defaultValue.canConvertToLong(),
"Cannot parse default as a %s value: %s",
type,
defaultValue);
return defaultValue.longValue();
case FLOAT:
Preconditions.checkArgument(
defaultValue.isFloatingPointNumber(),
"Cannot parse default as a %s value: %s",
type,
defaultValue);
return defaultValue.floatValue();
case DOUBLE:
Preconditions.checkArgument(
defaultValue.isFloatingPointNumber(),
"Cannot parse default as a %s value: %s",
type,
defaultValue);
return defaultValue.doubleValue();
case DECIMAL:
Preconditions.checkArgument(
defaultValue.isTextual(), "Cannot parse default as a %s value: %s", type, defaultValue);
BigDecimal retDecimal;
try {
retDecimal = new BigDecimal(defaultValue.textValue());
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
String.format("Cannot parse default as a %s value: %s", type, defaultValue), e);
}
Preconditions.checkArgument(
retDecimal.scale() == ((Types.DecimalType) type).scale(),
"Cannot parse default as a %s value: %s, the scale doesn't match",
type,
defaultValue);
return retDecimal;
case STRING:
Preconditions.checkArgument(
defaultValue.isTextual(), "Cannot parse default as a %s value: %s", type, defaultValue);
return defaultValue.textValue();
case UUID:
Preconditions.checkArgument(
defaultValue.isTextual() && defaultValue.textValue().length() == 36,
"Cannot parse default as a %s value: %s",
type,
defaultValue);
UUID uuid;
try {
uuid = UUID.fromString(defaultValue.textValue());
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(
String.format("Cannot parse default as a %s value: %s", type, defaultValue), e);
}
return uuid;
case DATE:
Preconditions.checkArgument(
defaultValue.isTextual(), "Cannot parse default as a %s value: %s", type, defaultValue);
return DateTimeUtil.isoDateToDays(defaultValue.textValue());
case TIME:
Preconditions.checkArgument(
defaultValue.isTextual(), "Cannot parse default as a %s value: %s", type, defaultValue);
return DateTimeUtil.isoTimeToMicros(defaultValue.textValue());
case TIMESTAMP:
Preconditions.checkArgument(
defaultValue.isTextual(), "Cannot parse default as a %s value: %s", type, defaultValue);
if (((Types.TimestampType) type).shouldAdjustToUTC()) {
String timestampTz = defaultValue.textValue();
Preconditions.checkArgument(
DateTimeUtil.isUTCTimestamptz(timestampTz),
"Cannot parse default as a %s value: %s, offset must be +00:00",
type,
defaultValue);
return DateTimeUtil.isoTimestamptzToMicros(timestampTz);
} else {
return DateTimeUtil.isoTimestampToMicros(defaultValue.textValue());
}
case FIXED:
Preconditions.checkArgument(
defaultValue.isTextual(), "Cannot parse default as a %s value: %s", type, defaultValue);
int defaultLength = defaultValue.textValue().length();
int fixedLength = ((Types.FixedType) type).length();
Preconditions.checkArgument(
defaultLength == fixedLength * 2,
"Cannot parse default %s value: %s, incorrect length: %s",
type,
defaultValue,
defaultLength);
byte[] fixedBytes =
BaseEncoding.base16().decode(defaultValue.textValue().toUpperCase(Locale.ROOT));
return ByteBuffer.wrap(fixedBytes);
case BINARY:
Preconditions.checkArgument(
defaultValue.isTextual(), "Cannot parse default as a %s value: %s", type, defaultValue);
byte[] binaryBytes =
BaseEncoding.base16().decode(defaultValue.textValue().toUpperCase(Locale.ROOT));
return ByteBuffer.wrap(binaryBytes);
case LIST:
return listFromJson(type, defaultValue);
case MAP:
return mapFromJson(type, defaultValue);
case STRUCT:
return structFromJson(type, defaultValue);
default:
throw new UnsupportedOperationException(String.format("Type: %s is not supported", type));
}
}
private static StructLike structFromJson(Type type, JsonNode defaultValue) {
Preconditions.checkArgument(
defaultValue.isObject(), "Cannot parse default as a %s value: %s", type, defaultValue);
Types.StructType struct = type.asStructType();
StructLike defaultRecord = GenericRecord.create(struct);
List fields = struct.fields();
for (int pos = 0; pos < fields.size(); pos += 1) {
Types.NestedField field = fields.get(pos);
String idString = String.valueOf(field.fieldId());
if (defaultValue.has(idString)) {
defaultRecord.set(pos, fromJson(field.type(), defaultValue.get(idString)));
}
}
return defaultRecord;
}
private static Map
© 2015 - 2025 Weber Informatics LLC | Privacy Policy