Java tutorial
// 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.impala.infra.tableflattener; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; import org.apache.avro.Schema; import org.apache.avro.Schema.Field; import org.apache.avro.Schema.Type; import org.apache.avro.generic.GenericRecord; import org.codehaus.jackson.JsonNode; import java.util.Map; public class SchemaUtil { // Used to validate unions. This is a substitution map for comparison purposes. static final Map<Type, Type> BASE_TYPES = ImmutableMap.<Type, Type>builder().put(Type.STRING, Type.BYTES) .put(Type.FIXED, Type.BYTES).put(Type.DOUBLE, Type.INT).put(Type.FLOAT, Type.INT) .put(Type.LONG, Type.INT).build(); static Field createField(String name, Type type) { return createField(name, type, null, null); } static Field createField(String name, Type type, String doc, JsonNode defaultValue) { return new Field(name, Schema.createUnion(Schema.create(Type.NULL), Schema.create(type)), doc, defaultValue); } static Field createField(String name, Schema schema) { return createField(name, schema, null, null); } static Field createField(String name, Schema schema, String doc, JsonNode defaultValue) { Preconditions.checkState(!schemaHasNesting(schema)); if (schema.getType() == Type.UNION) { return new Field(name, Schema.createUnion(schema.getTypes()), doc, defaultValue); } return createField(name, schema.getType(), doc, defaultValue); } static boolean recordHasField(GenericRecord record, String fieldName) { return record.getSchema().getField(fieldName) != null; } static Schema reduceUnionToNonNull(Schema unionSchema) { Schema reducedSchema = null; Type reducedBaseType = null; for (Schema schema : unionSchema.getTypes()) { if (schema.getType() == Type.NULL) continue; String logicalType = schema.getProp("logicalType"); Type baseType; if (logicalType == null) { baseType = BASE_TYPES.containsKey(schema.getType()) ? BASE_TYPES.get(schema.getType()) : schema.getType(); } else { Preconditions.checkState(logicalType.equals("decimal")); baseType = Type.INT; } if (reducedBaseType == null) { reducedSchema = schema; reducedBaseType = baseType; continue; } if (reducedBaseType != baseType) { throw new RuntimeException(String.format("Union contains incompatible types: %s", Joiner.on(" ,").join(unionSchema.getTypes()))); } } if (reducedSchema == null) { throw new RuntimeException(String.format("Union schema contains no non-null types: %s", Joiner.on(" ,").join(unionSchema.getTypes()))); } return reducedSchema; } static boolean isNullable(Schema schema) { return schema.getType() == Type.NULL || (schema.getType() == Type.UNION && unionIsNullable(schema)); } static boolean unionIsNullable(Schema unionSchema) { for (Schema schema : unionSchema.getTypes()) { if (schema.getType() == Type.NULL) return true; } return false; } static boolean isComplexType(Type type) { Preconditions.checkState(type != Type.UNION); return type == Type.ARRAY || type == Type.MAP || type == Type.RECORD; } static boolean isSimpleType(Schema schema) { if (schema.getType() == Type.UNION) schema = reduceUnionToNonNull(schema); return !isComplexType(schema.getType()); } static boolean requiresChildDataset(Schema schema) { if (schema.getType() == Type.UNION) schema = reduceUnionToNonNull(schema); return schema.getType() == Type.ARRAY || schema.getType() == Type.MAP; } static boolean schemaHasNesting(Schema schema) { if (schema.getType() == Type.UNION) schema = reduceUnionToNonNull(schema); return isComplexType(schema.getType()); } }