Package io.crate.analyze

Source Code of io.crate.analyze.AnalyzedTableElements

/*
* Licensed to CRATE Technology GmbH ("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.analyze;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.crate.exceptions.ColumnUnknownException;
import io.crate.metadata.ColumnIdent;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;

import javax.annotation.Nullable;
import java.util.*;

public class AnalyzedTableElements {

    List<AnalyzedColumnDefinition> partitionedByColumns = new ArrayList<>();
    List<AnalyzedColumnDefinition> columns = new ArrayList<>();
    Set<ColumnIdent> columnIdents = new HashSet<>();
    Map<ColumnIdent, String> columnTypes = new HashMap<>();
    List<String> primaryKeys;
    List<List<String>> partitionedBy;

    /**
     * additional primary keys that are not inline with a column definition
     */
    private List<String> additionalPrimaryKeys = new ArrayList<>();
    private Map<String, Set<String>> copyToMap = new HashMap<>();


    public Map<String, Object> toMapping() {
        Map<String, Object> mapping = new HashMap<>();
        Map<String, Object> meta = new HashMap<>();
        Map<String, Object> metaColumns = new HashMap<>();
        Map<String, Object> properties = new HashMap<>(columns.size());

        Map<String, Object> indicesMap = new HashMap<>();
        for (AnalyzedColumnDefinition column : columns) {
            properties.put(column.name(), column.toMapping());
            if (column.hasMetaInfo()) {
                metaColumns.put(column.name(), column.toMetaMapping());
            }
            if (column.isIndex()) {
                indicesMap.put(column.name(), column.toMetaIndicesMapping());
            }
        }

        if (!partitionedByColumns.isEmpty()) {
            meta.put("partitioned_by", partitionedBy());
        }
        if (!metaColumns.isEmpty()) {
            meta.put("columns", metaColumns);
        }
        if (!indicesMap.isEmpty()) {
            meta.put("indices", indicesMap);
        }
        if (!primaryKeys().isEmpty()) {
            meta.put("primary_keys", primaryKeys());
        }
        mapping.put("_meta", meta);
        mapping.put("properties", properties);
        mapping.put("_all", ImmutableMap.of("enabled", false));

        return mapping;
    }

    public List<List<String>> partitionedBy() {
        if (partitionedBy == null) {
            partitionedBy = new ArrayList<>(partitionedByColumns.size());
            for (AnalyzedColumnDefinition partitionedByColumn : partitionedByColumns) {
                partitionedBy.add(ImmutableList.of(
                        partitionedByColumn.ident().fqn(),
                        partitionedByColumn.dataType())
                );
            }
        }

        return partitionedBy;
    }

    private void expandColumnIdents() {
        for (AnalyzedColumnDefinition column : columns) {
            expandColumn(column);
        }
    }

    private void expandColumn(AnalyzedColumnDefinition column) {
        if (column.isIndex()) {
            columnIdents.remove(column.ident());
            return;
        }

        columnIdents.add(column.ident());
        columnTypes.put(column.ident(), column.dataType());
        for (AnalyzedColumnDefinition child : column.children()) {
            expandColumn(child);
        }
    }

    public List<String> primaryKeys() {
        if (primaryKeys == null) {
            primaryKeys = new ArrayList<>();
            for (AnalyzedColumnDefinition column : columns) {
                if (column.isPrimaryKey()) {
                    primaryKeys.add(column.ident().fqn());
                }
            }
            primaryKeys.addAll(additionalPrimaryKeys);
        }
        return primaryKeys;
    }

    public void addPrimaryKey(String fqColumnName) {
        additionalPrimaryKeys.add(fqColumnName);
    }

    public void add(AnalyzedColumnDefinition analyzedColumnDefinition) {
        if (columnIdents.contains(analyzedColumnDefinition.ident())) {
            throw new IllegalArgumentException(String.format(
                    "column \"%s\" specified more than once", analyzedColumnDefinition.ident().sqlFqn()));
        }
        columnIdents.add(analyzedColumnDefinition.ident());
        columns.add(analyzedColumnDefinition);
        columnTypes.put(analyzedColumnDefinition.ident(), analyzedColumnDefinition.dataType());
    }

    public Settings settings() {
        ImmutableSettings.Builder builder = ImmutableSettings.builder();
        for (AnalyzedColumnDefinition column : columns) {
            builder.put(column.analyzerSettings());
        }
        return builder.build();
    }

    public void finalizeAndValidate() {
        expandColumnIdents();
        for (AnalyzedColumnDefinition column : columns) {
            column.validate();
            addCopyToInfo(column);
        }
        validateIndexDefinitions();
        validatePrimaryKeys();
    }

    private void addCopyToInfo(AnalyzedColumnDefinition column) {
        if (!column.isIndex()) {
            Set<String> targets = copyToMap.get(column.ident().fqn());
            if (targets != null) {
                column.addCopyTo(targets);
            }
        }
        for (AnalyzedColumnDefinition child : column.children()) {
            addCopyToInfo(child);
        }
    }

    private void validatePrimaryKeys() {
        for (String additionalPrimaryKey : additionalPrimaryKeys) {
            if (!columnIdents.contains(ColumnIdent.fromPath(additionalPrimaryKey))) {
                throw new ColumnUnknownException(additionalPrimaryKey);
            }
        }
    }

    private void validateIndexDefinitions() {
        for (Map.Entry<String, Set<String>> entry : copyToMap.entrySet()) {
            ColumnIdent columnIdent = ColumnIdent.fromPath(entry.getKey());
            if (!columnIdents.contains(columnIdent)) {
                throw new ColumnUnknownException(columnIdent.sqlFqn());
            }
            if (!columnTypes.get(columnIdent).equalsIgnoreCase("string")) {
                throw new IllegalArgumentException("INDEX definition only support 'string' typed source columns");
            }
        }
    }

    public void addCopyTo(String sourceColumn, String targetIndex) {
         Set<String> targetColumns = copyToMap.get(sourceColumn);
         if (targetColumns == null) {
             targetColumns = new HashSet<>();
             copyToMap.put(sourceColumn, targetColumns);
         }
         targetColumns.add(targetIndex);
    }

    public Set<ColumnIdent> columnIdents() {
        return columnIdents;
    }

    @Nullable
    private AnalyzedColumnDefinition columnDefinitionByIdent(ColumnIdent ident, boolean removeIfFound) {
        AnalyzedColumnDefinition result = null;
        ColumnIdent root = ident.getRoot();
        for (AnalyzedColumnDefinition column : columns) {
            if (column.ident().equals(root)) {
                result = column;
                break;
            }
        }
        if (result == null) {
            return null;
        }

        if (result.ident().equals(ident)) {
            if (removeIfFound) {
                columns.remove(result);
            }
            return result;
        }

        return findInChildren(result, ident, removeIfFound);
    }

    private AnalyzedColumnDefinition findInChildren(AnalyzedColumnDefinition column,
                                                    ColumnIdent ident,
                                                    boolean removeIfFound) {
        AnalyzedColumnDefinition result = null;
        for (AnalyzedColumnDefinition child : column.children()) {
            if (child.ident().equals(ident)) {
                result = child;
                break;
            }
            AnalyzedColumnDefinition inChildren = findInChildren(child, ident, removeIfFound);
            if (inChildren != null) {
                return inChildren;
            }
        }

        if (removeIfFound && result != null) {
            column.children().remove(result);
        }
        return result;
    }

    public void changeToPartitionedByColumn(ColumnIdent partitionedByIdent, boolean skipIfNotFound) {
        Preconditions.checkArgument(!partitionedByIdent.name().startsWith("_"),
                "Cannot use system columns in PARTITIONED BY clause");

        // need to call primaryKeys() before the partition column is removed from the columns list
        if (!primaryKeys().isEmpty() && !primaryKeys().contains(partitionedByIdent.fqn())) {
            throw new IllegalArgumentException(String.format(Locale.ENGLISH,
                    "Cannot use non primary key column '%s' in PARTITIONED BY clause if primary key is set on table",
                    partitionedByIdent.sqlFqn()));
        }

        AnalyzedColumnDefinition columnDefinition = columnDefinitionByIdent(partitionedByIdent, true);
        if (columnDefinition == null) {
            if (skipIfNotFound) {
                return;
            }
            throw new ColumnUnknownException(partitionedByIdent.sqlFqn());
        }
        if (columnDefinition.dataType().equals("object")) {
            throw new IllegalArgumentException(String.format(Locale.ENGLISH,
                    "Cannot use object column '%s' in PARTITIONED BY clause",
                    columnDefinition.ident().sqlFqn()));
        }
        if (columnDefinition.isArrayOrInArray()) {
            throw new IllegalArgumentException(String.format(Locale.ENGLISH,
                    "Cannot use array column '%s' in PARTITIONED BY clause", columnDefinition.ident().sqlFqn()));


        }if (columnDefinition.index().equals("analyzed")) {
            throw new IllegalArgumentException(String.format(Locale.ENGLISH,
                    "Cannot use column '%s' with fulltext index in PARTITIONED BY clause",
                    columnDefinition.ident().sqlFqn()));
        }
        columnIdents.remove(columnDefinition.ident());
        partitionedByColumns.add(columnDefinition);
    }

    public List<AnalyzedColumnDefinition> columns() {
        return columns;
    }
}
TOP

Related Classes of io.crate.analyze.AnalyzedTableElements

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.