blob: 5c09adec399f8502c8c5aba5c10b6a1a9022a496 [file] [log] [blame]
/*
* 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.ignite.internal.schema.configuration;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import org.apache.ignite.internal.schema.Column;
import org.apache.ignite.internal.schema.DecimalNativeType;
import org.apache.ignite.internal.schema.InvalidTypeException;
import org.apache.ignite.internal.schema.NativeType;
import org.apache.ignite.internal.schema.NativeTypeSpec;
import org.apache.ignite.internal.schema.NativeTypes;
import org.apache.ignite.internal.schema.SchemaDescriptor;
import org.apache.ignite.internal.schema.SchemaException;
import org.apache.ignite.schema.definition.ColumnDefinition;
import org.apache.ignite.schema.definition.ColumnType;
import org.apache.ignite.schema.definition.TableDefinition;
import static org.apache.ignite.internal.schema.NativeTypes.DOUBLE;
import static org.apache.ignite.internal.schema.NativeTypes.FLOAT;
import static org.apache.ignite.internal.schema.NativeTypes.INT16;
import static org.apache.ignite.internal.schema.NativeTypes.INT32;
import static org.apache.ignite.internal.schema.NativeTypes.INT64;
import static org.apache.ignite.internal.schema.NativeTypes.INT8;
import static org.apache.ignite.internal.schema.NativeTypes.UUID;
/**
* Build SchemaDescriptor from Table internal configuration.
*/
public class SchemaDescriptorConverter {
/**
* Convert ColumnType to NativeType.
*
* @param colType ColumnType.
* @return NativeType.
*/
private static NativeType convert(ColumnType colType) {
assert colType != null;
ColumnType.ColumnTypeSpec type = colType.typeSpec();
switch (type) {
case INT8:
return INT8;
case INT16:
return INT16;
case INT32:
return INT32;
case INT64:
return INT64;
case UINT8:
case UINT16:
case UINT32:
case UINT64:
throw new UnsupportedOperationException("Unsigned types are not supported yet.");
case FLOAT:
return FLOAT;
case DOUBLE:
return DOUBLE;
case DECIMAL: {
ColumnType.DecimalColumnType numType = (ColumnType.DecimalColumnType)colType;
return NativeTypes.decimalOf(numType.precision(), numType.scale());
}
case UUID:
return UUID;
case BITMASK:
return NativeTypes.bitmaskOf(((ColumnType.VarLenColumnType)colType).length());
case STRING: {
int strLen = ((ColumnType.VarLenColumnType)colType).length();
if (strLen == 0)
strLen = Integer.MAX_VALUE;
return NativeTypes.stringOf(strLen);
}
case BLOB: {
int blobLen = ((ColumnType.VarLenColumnType)colType).length();
if (blobLen == 0)
blobLen = Integer.MAX_VALUE;
return NativeTypes.blobOf(blobLen);
}
case DATE:
return NativeTypes.DATE;
case TIME: {
ColumnType.TemporalColumnType temporalType = (ColumnType.TemporalColumnType)colType;
return NativeTypes.time(temporalType.precision());
}
case DATETIME: {
ColumnType.TemporalColumnType temporalType = (ColumnType.TemporalColumnType)colType;
return NativeTypes.datetime(temporalType.precision());
}
case TIMESTAMP: {
ColumnType.TemporalColumnType temporalType = (ColumnType.TemporalColumnType)colType;
return NativeTypes.timestamp(temporalType.precision());
}
case NUMBER: {
ColumnType.NumberColumnType numberType = (ColumnType.NumberColumnType)colType;
return NativeTypes.numberOf(numberType.precision());
}
default:
throw new InvalidTypeException("Unexpected type " + type);
}
}
/**
* Convert column from public configuration to internal.
*
* @param colCfg Column to confvert.
* @return Internal Column.
*/
private static Column convert(ColumnDefinition colCfg) {
NativeType type = convert(colCfg.type());
return new Column(colCfg.name(), type, colCfg.nullable(), new ConstantSupplier(convertDefault(type, (String)colCfg.defaultValue())));
}
/**
* TODO: https://issues.apache.org/jira/browse/IGNITE-14479 Fix default conversion.
*
* @param type Column type.
* @param dflt Column default value.
* @return Parsed object.
*/
private static Serializable convertDefault(NativeType type, String dflt) {
if (dflt == null || dflt.isEmpty() && type.spec() != NativeTypeSpec.STRING)
return null;
assert dflt instanceof String;
switch (type.spec()) {
case INT8:
return Byte.parseByte(dflt);
case INT16:
return Short.parseShort(dflt);
case INT32:
return Integer.parseInt(dflt);
case INT64:
return Long.parseLong(dflt);
case FLOAT:
return Float.parseFloat(dflt);
case DOUBLE:
return Double.parseDouble(dflt);
case DECIMAL:
return new BigDecimal(dflt).setScale(((DecimalNativeType)type).scale(), RoundingMode.HALF_UP);
case NUMBER:
return new BigInteger(dflt);
case STRING:
return dflt;
case UUID:
return java.util.UUID.fromString(dflt);
case DATE:
return LocalDate.parse(dflt);
case TIME:
return LocalTime.parse(dflt);
case DATETIME:
return LocalDateTime.parse(dflt);
case TIMESTAMP:
return Instant.parse(dflt);
default:
throw new SchemaException("Default value is not supported for type: type=" + type.toString());
}
}
/**
* Build schema descriptor by table schema.
*
* @param schemaVer Schema version.
* @param tblCfg Table schema.
* @return SchemaDescriptor.
*/
public static SchemaDescriptor convert(int schemaVer, TableDefinition tblCfg) {
List<ColumnDefinition> keyColsCfg = new ArrayList<>(tblCfg.keyColumns());
Column[] keyCols = new Column[keyColsCfg.size()];
for (int i = 0; i < keyCols.length; i++)
keyCols[i] = convert(keyColsCfg.get(i));
String[] affCols = tblCfg.affinityColumns().stream().map(ColumnDefinition::name)
.toArray(String[]::new);
List<ColumnDefinition> valColsCfg = new ArrayList<>(tblCfg.valueColumns());
Column[] valCols = new Column[valColsCfg.size()];
for (int i = 0; i < valCols.length; i++)
valCols[i] = convert(valColsCfg.get(i));
return new SchemaDescriptor(schemaVer, keyCols, affCols, valCols);
}
/**
* Constant value supplier.
*/
private static class ConstantSupplier implements Supplier<Object>, Serializable {
/** Value. */
private final Serializable val;
/**
* @param val Value.
*/
ConstantSupplier(Serializable val) {
this.val = val;
}
/** {@inheritDoc */
@Override public Object get() {
return val;
}
}
}