/* * 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.analyze.relations; import com.google.common.collect.ImmutableList; import io.crate.analyze.expressions.ExpressionAnalysisContext; import io.crate.analyze.symbol.Symbol; import io.crate.planner.node.dql.join.JoinType; import io.crate.sql.tree.QualifiedName; import javax.annotation.Nullable; import java.util.*; public class RelationAnalysisContext { private final ExpressionAnalysisContext expressionAnalysisContext; private final boolean aliasedRelation; // keep order of sources. // e.g. something like: select * from t1, t2 must not become select t2.*, t1.* private final Map<QualifiedName, AnalyzedRelation> sources = new LinkedHashMap<>(); @Nullable private List<JoinPair> joinPairs; RelationAnalysisContext(boolean aliasedRelation) { this.aliasedRelation = aliasedRelation; expressionAnalysisContext = new ExpressionAnalysisContext(); } boolean isAliasedRelation() { return aliasedRelation; } public Map<QualifiedName, AnalyzedRelation> sources() { return sources; } private void addJoinPair(JoinPair joinType) { if (joinPairs == null) { joinPairs = new ArrayList<>(); } joinPairs.add(joinType); } void addJoinType(JoinType joinType, @Nullable Symbol joinCondition) { int size = sources.size(); assert size >= 2 : "sources must be added first, cannot add join type for only 1 source"; Iterator<QualifiedName> it = sources.keySet().iterator(); QualifiedName left = null; QualifiedName right = null; int idx = 0; while (it.hasNext()) { QualifiedName sourceName = it.next(); if (idx == size - 2) { left = sourceName; } else if (idx == size - 1) { right = sourceName; } idx++; } addJoinPair(new JoinPair(left, right, joinType, joinCondition)); } List<JoinPair> joinPairs() { if (joinPairs == null) { return ImmutableList.of(); } return joinPairs; } private void addSourceRelation(QualifiedName qualifiedName, AnalyzedRelation relation) { if (sources.put(qualifiedName, relation) != null) { String tableName = qualifiedName.toString(); if (tableName.startsWith(".")) { tableName = tableName.substring(1); } String errorMessage = String.format(Locale.ENGLISH, "\"%s\" specified more than once in the FROM clause", tableName); throw new IllegalArgumentException(errorMessage); } } void addSourceRelation(String nameOrAlias, AnalyzedRelation relation) { addSourceRelation(new QualifiedName(nameOrAlias), relation); } void addSourceRelation(String schemaName, String nameOrAlias, AnalyzedRelation relation) { addSourceRelation(new QualifiedName(Arrays.asList(schemaName, nameOrAlias)), relation); } public ExpressionAnalysisContext expressionAnalysisContext() { return expressionAnalysisContext; } }