/** * 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.hadoop.hive.ql.exec; import java.io.Serializable; import java.util.List; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.ql.CompilationOpContext; import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.hive.ql.plan.ExprNodeColumnDesc; import org.apache.hadoop.hive.ql.plan.ExprNodeDesc; import org.apache.hadoop.hive.ql.plan.SelectDesc; import org.apache.hadoop.hive.ql.plan.api.OperatorType; /** * Select operator implementation. */ public class SelectOperator extends Operator<SelectDesc> implements Serializable { private static final long serialVersionUID = 1L; protected transient ExprNodeEvaluator[] eval; transient Object[] output; private transient boolean isSelectStarNoCompute = false; /** Kryo ctor. */ protected SelectOperator() { super(); } public SelectOperator(CompilationOpContext ctx) { super(ctx); } @Override protected void initializeOp(Configuration hconf) throws HiveException { super.initializeOp(hconf); // Just forward the row as is if (conf.isSelStarNoCompute()) { isSelectStarNoCompute = true; return; } List<ExprNodeDesc> colList = conf.getColList(); eval = new ExprNodeEvaluator[colList.size()]; for (int i = 0; i < colList.size(); i++) { assert (colList.get(i) != null); eval[i] = ExprNodeEvaluatorFactory.get(colList.get(i), hconf); } if (HiveConf.getBoolVar(hconf, HiveConf.ConfVars.HIVEEXPREVALUATIONCACHE)) { eval = ExprNodeEvaluatorFactory.toCachedEvals(eval); } output = new Object[eval.length]; if (isLogInfoEnabled) { LOG.info("SELECT " + inputObjInspectors[0].getTypeName()); } outputObjInspector = initEvaluatorsAndReturnStruct(eval, conf.getOutputColumnNames(), inputObjInspectors[0]); } @Override public void process(Object row, int tag) throws HiveException { if (isSelectStarNoCompute) { forward(row, inputObjInspectors[tag]); return; } int i = 0; try { for (; i < eval.length; ++i) { output[i] = eval[i].evaluate(row); } } catch (HiveException e) { throw e; } catch (RuntimeException e) { throw new HiveException("Error evaluating " + conf.getColList().get(i).getExprString(), e); } forward(output, outputObjInspector); } /** * @return the name of the operator */ @Override public String getName() { return SelectOperator.getOperatorName(); } static public String getOperatorName() { return "SEL"; } @Override public OperatorType getType() { return OperatorType.SELECT; } @Override public boolean supportSkewJoinOptimization() { return true; } @Override public boolean columnNamesRowResolvedCanBeObtained() { return true; } @Override public boolean supportAutomaticSortMergeJoin() { return true; } @Override public boolean supportUnionRemoveOptimization() { return true; } @Override public boolean acceptLimitPushdown() { return true; } /** * Checks whether this select operator does something to the * input tuples. * * @return if it is an identity select operator or not */ public boolean isIdentitySelect() { // Safety check if(this.getNumParent() != 1) { return false; } if(conf.isSelStarNoCompute()) { return true; } // Check whether the have the same schema RowSchema orig = this.getSchema(); RowSchema dest = this.getParentOperators().get(0).getSchema(); if(orig.getSignature() == null && dest.getSignature() == null) { return true; } if((orig.getSignature() == null && dest.getSignature() != null) || (orig.getSignature() != null && dest.getSignature() == null) ) { return false; } if(orig.getSignature().size() != dest.getSignature().size() || orig.getSignature().size() != conf.getColList().size()) { return false; } for(int i=0; i<orig.getSignature().size(); i++) { ColumnInfo origColumn = orig.getSignature().get(i); ColumnInfo destColumn = dest.getSignature().get(i); if(origColumn == null && destColumn == null) { continue; } if((origColumn == null && destColumn != null) || (origColumn != null && destColumn == null) ) { return false; } if(!origColumn.internalEquals(destColumn)) { return false; } // Now we check if though the schemas are the same, // the operator changes the order of columns in the // output if(!(conf.getColList().get(i) instanceof ExprNodeColumnDesc)) { return false; } ExprNodeColumnDesc col = (ExprNodeColumnDesc) conf.getColList().get(i); if(!col.getColumn().equals(origColumn.getInternalName())) { return false; } } return true; } }