/* * 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.metadata.table; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import io.crate.metadata.IndexMappings; import io.crate.Version; import io.crate.action.sql.SessionContext; import io.crate.analyze.WhereClause; import io.crate.analyze.expressions.ExpressionAnalysisContext; import io.crate.analyze.expressions.ExpressionAnalyzer; import io.crate.analyze.expressions.TableReferenceResolver; import io.crate.metadata.*; import io.crate.metadata.doc.DocSysColumns; import io.crate.metadata.doc.DocTableInfo; import io.crate.sql.parser.SqlParser; import io.crate.sql.tree.Expression; import io.crate.types.DataType; import org.apache.lucene.util.BytesRef; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.common.settings.Settings; import javax.annotation.Nullable; import java.util.*; import static org.mockito.Mockito.mock; public class TestingTableInfo extends DocTableInfo { private Routing routing; public TestingTableInfo(TableIdent ident, List<Reference> columns, List<Reference> partitionedByColumns, List<GeneratedReference> generatedColumns, ImmutableMap<ColumnIdent, IndexReference> indexColumns, ImmutableMap<ColumnIdent, Reference> references, List<ColumnIdent> primaryKeys, ColumnIdent clusteredBy, boolean isAlias, boolean hasAutoGeneratedPrimaryKey, String[] concreteIndices, int numberOfShards, BytesRef numberOfReplicas, ImmutableMap<String, Object> tableParameters, List<ColumnIdent> partitionedBy, List<PartitionName> partitions, ColumnPolicy columnPolicy, Routing routing) { super(ident, columns, partitionedByColumns, generatedColumns, indexColumns, references, ImmutableMap.<ColumnIdent, String>of(), primaryKeys, clusteredBy, isAlias, hasAutoGeneratedPrimaryKey, concreteIndices, null, new IndexNameExpressionResolver(Settings.EMPTY), numberOfShards, numberOfReplicas, tableParameters, partitionedBy, partitions, columnPolicy, IndexMappings.DEFAULT_ROUTING_HASH_FUNCTION, Version.CURRENT, null, isAlias ? Operation.SYS_READ_ONLY : Operation.ALL); this.routing = routing; } @Override public Routing getRouting(WhereClause whereClause, @Nullable String preference) { return routing; } public static Builder builder(TableIdent ident, Routing routing) { return new Builder(ident, routing); } public static class Builder { private final ImmutableList.Builder<Reference> columns = ImmutableList.builder(); private final ImmutableMap.Builder<ColumnIdent, Reference> references = ImmutableMap.builder(); private final ImmutableList.Builder<Reference> partitionedByColumns = ImmutableList.builder(); private final ImmutableList.Builder<GeneratedReference> generatedColumns = ImmutableList.builder(); private final ImmutableList.Builder<ColumnIdent> primaryKey = ImmutableList.builder(); private final ImmutableList.Builder<ColumnIdent> partitionedBy = ImmutableList.builder(); private final ImmutableList.Builder<PartitionName> partitions = ImmutableList.builder(); private final ImmutableMap.Builder<ColumnIdent, IndexReference> indexColumns = ImmutableMap.builder(); private ColumnIdent clusteredBy; private final int numberOfShards = 1; private final BytesRef numberOfReplicas = new BytesRef("0"); private final TableIdent ident; private final Routing routing; private boolean isAlias = false; private ColumnPolicy columnPolicy = ColumnPolicy.DYNAMIC; public Builder(TableIdent ident, Routing routing) { this.routing = routing; this.ident = ident; } public DocTableInfo build() { return build(mock(Functions.class)); } public DocTableInfo build(Functions functions) { addDocSysColumns(); ImmutableList<ColumnIdent> pk = primaryKey.build(); ImmutableList<PartitionName> partitionsList = partitions.build(); String[] concreteIndices; if (partitionsList.isEmpty()) { concreteIndices = new String[]{ident.indexName()}; } else { concreteIndices = Lists.transform(partitionsList, new Function<PartitionName, String>() { @Nullable @Override public String apply(@Nullable PartitionName input) { assert input != null; return input.asIndexName(); } }).toArray(new String[partitionsList.size()]); } initializeGeneratedExpressions(functions, references.build().values()); return new TestingTableInfo( ident, columns.build(), partitionedByColumns.build(), generatedColumns.build(), indexColumns.build(), references.build(), pk, clusteredBy, isAlias, pk.isEmpty(), concreteIndices, numberOfShards, numberOfReplicas, null, // tableParameters partitionedBy.build(), partitionsList, columnPolicy, routing ); } private Reference genInfo(ColumnIdent columnIdent, DataType type) { return new Reference( new ReferenceIdent(ident, columnIdent.name(), columnIdent.path()), RowGranularity.DOC, type ); } private void addDocSysColumns() { for (Map.Entry<ColumnIdent, DataType> entry : DocSysColumns.COLUMN_IDENTS.entrySet()) { references.put( entry.getKey(), genInfo(entry.getKey(), entry.getValue()) ); } } public Builder add(String column, DataType type) { return add(column, type, null); } public Builder add(String column, DataType type, List<String> path) { return add(column, type, path, ColumnPolicy.DYNAMIC); } public Builder add(String column, DataType type, List<String> path, ColumnPolicy columnPolicy) { return add(column, type, path, columnPolicy, Reference.IndexType.NOT_ANALYZED, false, true); } public Builder add(String column, DataType type, List<String> path, Reference.IndexType indexType) { return add(column, type, path, ColumnPolicy.DYNAMIC, indexType, false, true); } public Builder add(String column, DataType type, List<String> path, boolean partitionBy) { return add(column, type, path, ColumnPolicy.DYNAMIC, Reference.IndexType.NOT_ANALYZED, partitionBy, true); } public Builder add(String column, DataType type, List<String> path, ColumnPolicy columnPolicy, Reference.IndexType indexType, boolean partitionBy, boolean nullable) { RowGranularity rowGranularity = RowGranularity.DOC; if (partitionBy) { rowGranularity = RowGranularity.PARTITION; } Reference info = new Reference(new ReferenceIdent(ident, column, path), rowGranularity, type, columnPolicy, indexType, nullable); if (info.ident().isColumn()) { columns.add(info); } references.put(info.ident().columnIdent(), info); if (partitionBy) { partitionedByColumns.add(info); partitionedBy.add(info.ident().columnIdent()); } return this; } public Builder addGeneratedColumn(String column, DataType type, String expression, boolean partitionBy) { return addGeneratedColumn(column, type, expression, partitionBy, true); } public Builder addGeneratedColumn(String column, DataType type, String expression, boolean partitionBy, boolean nullable) { RowGranularity rowGranularity = RowGranularity.DOC; if (partitionBy) { rowGranularity = RowGranularity.PARTITION; } GeneratedReference info = new GeneratedReference(new ReferenceIdent(ident, column), rowGranularity, type, ColumnPolicy.DYNAMIC, Reference.IndexType.NOT_ANALYZED, expression, nullable); generatedColumns.add(info); if (info.ident().isColumn()) { columns.add(info); } references.put(info.ident().columnIdent(), info); if (partitionBy) { partitionedByColumns.add(info); partitionedBy.add(info.ident().columnIdent()); } return this; } public Builder addIndex(ColumnIdent columnIdent, Reference.IndexType indexType) { IndexReference info = new IndexReference( new ReferenceIdent(ident, columnIdent), indexType, Collections.emptyList(), null); indexColumns.put(columnIdent, info); return this; } public Builder addPrimaryKey(String column) { primaryKey.add(ColumnIdent.fromPath(column)); return this; } public Builder clusteredBy(String clusteredBy) { this.clusteredBy = ColumnIdent.fromPath(clusteredBy); return this; } public Builder isAlias(boolean isAlias) { this.isAlias = isAlias; return this; } public Builder addPartitions(String... partitionNames) { for (String partitionName : partitionNames) { PartitionName partition = PartitionName.fromIndexOrTemplate(partitionName); partitions.add(partition); } return this; } private void initializeGeneratedExpressions(Functions functions, Collection<Reference> columns) { TableReferenceResolver tableReferenceResolver = new TableReferenceResolver(columns); ExpressionAnalyzer expressionAnalyzer = new ExpressionAnalyzer( functions, SessionContext.SYSTEM_SESSION, null, tableReferenceResolver, null); for (GeneratedReference generatedReferenceInfo : generatedColumns.build()) { Expression expression = SqlParser.createExpression(generatedReferenceInfo.formattedGeneratedExpression()); ExpressionAnalysisContext context = new ExpressionAnalysisContext(); generatedReferenceInfo.generatedExpression(expressionAnalyzer.convert(expression, context)); generatedReferenceInfo.referencedReferences(ImmutableList.copyOf(tableReferenceResolver.references())); tableReferenceResolver.references().clear(); } } } }