blob: a5c39b8d8840c75d4650b81bea7a0e03e27e5427 [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;
import com.google.gson.annotations.Expose;
import org.apache.tajo.catalog.Column;
import org.apache.tajo.common.ProtoObject;
import org.apache.tajo.common.TajoDataTypes.DataType;
import org.apache.tajo.json.GsonObject;
import org.apache.tajo.plan.expr.EvalNode;
import org.apache.tajo.plan.expr.FieldEval;
import org.apache.tajo.plan.serder.LogicalNodeSerializer;
import org.apache.tajo.plan.serder.PlanGsonHelper;
import org.apache.tajo.plan.serder.PlanProto;
import org.apache.tajo.util.TUtil;
/**
* A Target contains how to evaluate an expression and its alias name.
*/
public class Target implements Cloneable, GsonObject, ProtoObject<PlanProto.Target> {
@Expose private EvalNode expr;
@Expose private Column column;
@Expose private String alias = null;
public Target(FieldEval fieldEval) {
this.expr = fieldEval;
this.column = fieldEval.getColumnRef();
}
public Target(final EvalNode eval, final String alias) {
this.expr = eval;
// force lower case
String normalized = alias;
// If an expr is a column reference and its alias is equivalent to column name, ignore a given alias.
if (eval instanceof FieldEval && eval.getName().equals(normalized)) {
column = ((FieldEval) eval).getColumnRef();
} else {
column = new Column(normalized, eval.getValueType());
setAlias(alias);
}
}
public String getCanonicalName() {
return !hasAlias() ? column.getQualifiedName() : alias;
}
public final void setExpr(EvalNode expr) {
this.expr = expr;
}
public final void setAlias(String alias) {
this.alias = alias;
this.column = new Column(alias, expr.getValueType());
}
public final String getAlias() {
return alias;
}
public final boolean hasAlias() {
return alias != null;
}
public DataType getDataType() {
return column.getDataType();
}
public <T extends EvalNode> T getEvalTree() {
return (T) this.expr;
}
public Column getNamedColumn() {
return this.column;
}
public String toString() {
StringBuilder sb = new StringBuilder(expr.toString());
if(hasAlias()) {
sb.append(" as ").append(alias);
}
return sb.toString();
}
public boolean equals(Object obj) {
if(obj instanceof Target) {
Target other = (Target) obj;
boolean b1 = expr.equals(other.expr);
boolean b2 = column.equals(other.column);
boolean b3 = TUtil.checkEquals(alias, other.alias);
return b1 && b2 && b3;
} else {
return false;
}
}
public int hashCode() {
return this.expr.getName().hashCode();
}
@Override
public Object clone() throws CloneNotSupportedException {
Target target = (Target) super.clone();
target.expr = (EvalNode) expr.clone();
target.column = column;
target.alias = alias != null ? alias : null;
return target;
}
public String toJson() {
return PlanGsonHelper.toJson(this, Target.class);
}
@Override
public PlanProto.Target getProto() {
return LogicalNodeSerializer.convertTarget(this);
}
}