blob: 343b9abfde047104a53899031477e0e43a301493 [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.tajo.plan.nameresolver;
import org.apache.tajo.algebra.ColumnReferenceExpr;
import org.apache.tajo.catalog.CatalogUtil;
import org.apache.tajo.catalog.Column;
import org.apache.tajo.catalog.Schema;
import org.apache.tajo.exception.AmbiguousColumnException;
import org.apache.tajo.exception.TajoException;
import org.apache.tajo.exception.UndefinedColumnException;
import org.apache.tajo.plan.LogicalPlan;
import org.apache.tajo.plan.logical.LogicalNode;
import org.apache.tajo.plan.logical.NodeType;
import org.apache.tajo.plan.logical.RelationNode;
import org.apache.tajo.util.Pair;
import java.util.ArrayList;
import java.util.List;
public class ResolverByLegacy extends NameResolver {
@Override
public Column resolve(LogicalPlan plan,
LogicalPlan.QueryBlock block,
ColumnReferenceExpr columnRef,
boolean includeSeflDescTable)
throws TajoException {
if (columnRef.hasQualifier()) {
return resolveColumnWithQualifier(plan, block, columnRef, includeSeflDescTable);
} else {
return resolveColumnWithoutQualifier(plan, block, columnRef, includeSeflDescTable);
}
}
private static Column resolveColumnWithQualifier(LogicalPlan plan, LogicalPlan.QueryBlock block,
ColumnReferenceExpr columnRef, boolean includeSeflDescTable)
throws TajoException {
final String qualifier;
final String qualifiedName;
Pair<String, String> normalized = lookupQualifierAndCanonicalName(block, columnRef, includeSeflDescTable);
qualifier = normalized.getFirst();
qualifiedName = CatalogUtil.buildFQName(qualifier, columnRef.getName());
Column found = resolveFromRelsWithinBlock(plan, block, columnRef, includeSeflDescTable);
if (found == null) {
throw new UndefinedColumnException(columnRef.getCanonicalName());
}
// If code reach here, a column is found.
// But, it may be aliased from bottom logical node.
// If the column is aliased, the found name may not be used in upper node.
// Here, we try to check if column reference is already aliased.
// If so, it replaces the name with aliased name.
LogicalNode currentNode = block.getCurrentNode();
// The condition (currentNode.getInSchema().contains(column)) means
// the column can be used at the current node. So, we don't need to find aliase name.
Schema currentNodeSchema = null;
if (currentNode != null) {
if (currentNode instanceof RelationNode) {
currentNodeSchema = ((RelationNode) currentNode).getLogicalSchema();
} else {
currentNodeSchema = currentNode.getInSchema();
}
}
if (currentNode != null && !currentNodeSchema.contains(found)
&& currentNode.getType() != NodeType.TABLE_SUBQUERY) {
List<Column> candidates = new ArrayList<>();
if (block.getNamedExprsManager().isAliased(qualifiedName)) {
String alias = block.getNamedExprsManager().getAlias(qualifiedName);
found = resolve(plan, block, new ColumnReferenceExpr(alias), NameResolvingMode.LEGACY, includeSeflDescTable);
if (found != null) {
candidates.add(found);
}
}
if (!candidates.isEmpty()) {
return ensureUniqueColumn(candidates);
}
}
return found;
}
static Column resolveColumnWithoutQualifier(LogicalPlan plan, LogicalPlan.QueryBlock block,
ColumnReferenceExpr columnRef, boolean includeSeflDescTable)
throws AmbiguousColumnException, UndefinedColumnException {
Column found = lookupColumnFromAllRelsInBlock(block, columnRef.getName(), includeSeflDescTable);
if (found != null) {
return found;
}
found = resolveAliasedName(block, columnRef);
if (found != null) {
return found;
}
found = resolveFromCurrentAndChildNode(block, columnRef);
if (found != null) {
return found;
}
found = resolveFromAllRelsInAllBlocks(plan, columnRef);
if (found != null) {
return found;
}
throw new UndefinedColumnException(columnRef.getCanonicalName());
}
}