/* * Licensed to Crate under one or more contributor license agreements. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. Crate 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. * * However, if you have executed another commercial license agreement * with Crate these terms will supersede the license and you may use the * software solely pursuant to the terms of the relevant commercial * agreement. */ package io.crate.metadata; import io.crate.analyze.symbol.InputColumn; import io.crate.analyze.symbol.Literal; import io.crate.analyze.symbol.Symbol; import io.crate.types.DataType; import org.elasticsearch.common.xcontent.support.XContentMapValues; import java.util.*; import java.util.function.Function; public class ReferenceToLiteralConverter implements Function<Reference, Symbol> { private final Map<Reference, InputColumn> referenceInputColumnMap; private final BitSet inputIsMap; private Object[] values; public ReferenceToLiteralConverter(List<Reference> insertColumns, Collection<Reference> allReferencedReferences) { referenceInputColumnMap = new HashMap<>(allReferencedReferences.size()); inputIsMap = new BitSet(insertColumns.size()); for (Reference reference : allReferencedReferences) { int idx = 0; for (Reference insertColumn : insertColumns) { if (insertColumn.equals(reference)) { referenceInputColumnMap.put(reference, new InputColumn(idx, reference.valueType())); inputIsMap.set(idx, false); break; } else if (reference.ident().columnIdent().isChildOf(insertColumn.ident().columnIdent())) { referenceInputColumnMap.put(reference, new InputColumn(idx, reference.valueType())); inputIsMap.set(idx, true); break; } idx++; } } } public void values(Object[] values) { this.values = values; } private Symbol resolveReferenceValue(Reference reference) { assert values != null : "values must be set first"; InputColumn inputColumn = referenceInputColumnMap.get(reference); if (inputColumn != null) { assert inputColumn.valueType() != null : "expects dataType to be set on InputColumn"; DataType dataType = inputColumn.valueType(); Object value; if (inputIsMap.get(inputColumn.index())) { ColumnIdent columnIdent = reference.ident().columnIdent().shiftRight(); assert columnIdent != null : "shifted ColumnIdent must not be null"; //noinspection unchecked value = XContentMapValues.extractValue( columnIdent.fqn(), (Map) values[inputColumn.index()]); } else { value = values[inputColumn.index()]; } return Literal.of(dataType, dataType.value(value)); } DataType dataType = reference.valueType(); return Literal.of(dataType, dataType.value(null)); } @Override public Symbol apply(Reference reference) { return resolveReferenceValue(reference); } }