/**
* 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.parse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hive.ql.parse.BaseSemanticAnalyzer.tableSpec;
/**
* Implementation of the parse information related to a query block.
*
**/
public class QBParseInfo {
private final boolean isSubQ;
private final String alias;
private ASTNode joinExpr;
private ASTNode hints;
private final HashMap<String, ASTNode> aliasToSrc;
private final HashMap<String, ASTNode> nameToDest;
private final HashMap<String, TableSample> nameToSample;
private final Map<ASTNode, String> exprToColumnAlias;
private final Map<String, ASTNode> destToSelExpr;
private final HashMap<String, ASTNode> destToWhereExpr;
private final HashMap<String, ASTNode> destToGroupby;
private final Map<String, ASTNode> destToHaving;
private final HashSet<String> insertIntoTables;
private boolean isAnalyzeCommand; // used for the analyze command (statistics)
private boolean isInsertToTable; // used for insert overwrite command (statistics)
private final HashMap<String, ASTNode> destToSampleExpr; // used for sampling
private final HashMap<String, tableSpec> tableSpecs; // used for statistics
/**
* ClusterBy is a short name for both DistributeBy and SortBy.
*/
private final HashMap<String, ASTNode> destToClusterby;
/**
* DistributeBy controls the hashcode of the row, which determines which
* reducer the rows will go to.
*/
private final HashMap<String, ASTNode> destToDistributeby;
/**
* SortBy controls the reduce keys, which affects the order of rows that the
* reducer receives.
*/
private final HashMap<String, ASTNode> destToSortby;
/**
* Maping from table/subquery aliases to all the associated lateral view nodes.
*/
private final HashMap<String, ArrayList<ASTNode>> aliasToLateralViews;
/* Order by clause */
private final HashMap<String, ASTNode> destToOrderby;
private final HashMap<String, Integer> destToLimit;
private int outerQueryLimit;
// used by GroupBy
private final LinkedHashMap<String, LinkedHashMap<String, ASTNode>> destToAggregationExprs;
private final HashMap<String, List<ASTNode>> destToDistinctFuncExprs;
@SuppressWarnings("unused")
private static final Log LOG = LogFactory.getLog(QBParseInfo.class.getName());
public QBParseInfo(String alias, boolean isSubQ) {
aliasToSrc = new HashMap<String, ASTNode>();
nameToDest = new HashMap<String, ASTNode>();
nameToSample = new HashMap<String, TableSample>();
exprToColumnAlias = new HashMap<ASTNode, String>();
destToSelExpr = new LinkedHashMap<String, ASTNode>();
destToWhereExpr = new HashMap<String, ASTNode>();
destToGroupby = new HashMap<String, ASTNode>();
destToHaving = new HashMap<String, ASTNode>();
destToClusterby = new HashMap<String, ASTNode>();
destToDistributeby = new HashMap<String, ASTNode>();
destToSortby = new HashMap<String, ASTNode>();
destToOrderby = new HashMap<String, ASTNode>();
destToLimit = new HashMap<String, Integer>();
insertIntoTables = new HashSet<String>();
destToSampleExpr = new HashMap<String, ASTNode>(); //sameerag
destToAggregationExprs = new LinkedHashMap<String, LinkedHashMap<String, ASTNode>>();
destToDistinctFuncExprs = new HashMap<String, List<ASTNode>>();
this.alias = alias;
this.isSubQ = isSubQ;
outerQueryLimit = -1;
aliasToLateralViews = new HashMap<String, ArrayList<ASTNode>>();
tableSpecs = new HashMap<String, BaseSemanticAnalyzer.tableSpec>();
}
public void setAggregationExprsForClause(String clause,
LinkedHashMap<String, ASTNode> aggregationTrees) {
destToAggregationExprs.put(clause, aggregationTrees);
}
public void addAggregationExprsForClause(String clause,
LinkedHashMap<String, ASTNode> aggregationTrees) {
if (destToAggregationExprs.containsKey(clause)) {
destToAggregationExprs.get(clause).putAll(aggregationTrees);
} else {
destToAggregationExprs.put(clause, aggregationTrees);
}
}
public void addInsertIntoTable(String table) {
insertIntoTables.add(table);
}
public boolean isInsertIntoTable(String table) {
return insertIntoTables.contains(table);
}
public HashMap<String, ASTNode> getAggregationExprsForClause(String clause) {
return destToAggregationExprs.get(clause);
}
public void setDistinctFuncExprsForClause(String clause, List<ASTNode> ast) {
destToDistinctFuncExprs.put(clause, ast);
}
public List<ASTNode> getDistinctFuncExprsForClause(String clause) {
return destToDistinctFuncExprs.get(clause);
}
public void setSelExprForClause(String clause, ASTNode ast) {
destToSelExpr.put(clause, ast);
}
public void setWhrExprForClause(String clause, ASTNode ast) {
destToWhereExpr.put(clause, ast);
}
public void setHavingExprForClause(String clause, ASTNode ast) {
destToHaving.put(clause, ast);
}
//@sameerag
public void setSampleExprForClause(String clause, ASTNode ast) {
destToSampleExpr.put(clause, ast);
}
public void setGroupByExprForClause(String clause, ASTNode ast) {
destToGroupby.put(clause, ast);
}
public void setDestForClause(String clause, ASTNode ast) {
nameToDest.put(clause, ast);
}
/**
* Set the Cluster By AST for the clause.
*
* @param clause
* the name of the clause
* @param ast
* the abstract syntax tree
*/
public void setClusterByExprForClause(String clause, ASTNode ast) {
destToClusterby.put(clause, ast);
}
/**
* Set the Distribute By AST for the clause.
*
* @param clause
* the name of the clause
* @param ast
* the abstract syntax tree
*/
public void setDistributeByExprForClause(String clause, ASTNode ast) {
destToDistributeby.put(clause, ast);
}
/**
* Set the Sort By AST for the clause.
*
* @param clause
* the name of the clause
* @param ast
* the abstract syntax tree
*/
public void setSortByExprForClause(String clause, ASTNode ast) {
destToSortby.put(clause, ast);
}
public void setOrderByExprForClause(String clause, ASTNode ast) {
destToOrderby.put(clause, ast);
}
public void setSrcForAlias(String alias, ASTNode ast) {
aliasToSrc.put(alias.toLowerCase(), ast);
}
public Set<String> getClauseNames() {
return destToSelExpr.keySet();
}
public Set<String> getClauseNamesForDest() {
return nameToDest.keySet();
}
public ASTNode getDestForClause(String clause) {
return nameToDest.get(clause);
}
//@sameerag
public ASTNode getSampleForClause(String clause) {
return destToSampleExpr.get(clause);
}
public ASTNode getWhrForClause(String clause) {
return destToWhereExpr.get(clause);
}
//@sameerag
public HashMap<String, ASTNode> getDestToSampleExpr() {
return destToSampleExpr;
}
public HashMap<String, ASTNode> getDestToWhereExpr() {
return destToWhereExpr;
}
public ASTNode getGroupByForClause(String clause) {
return destToGroupby.get(clause);
}
public HashMap<String, ASTNode> getDestToGroupBy() {
return destToGroupby;
}
public ASTNode getHavingForClause(String clause) {
return destToHaving.get(clause);
}
public Map<String, ASTNode> getDestToHaving() {
return destToHaving;
}
public ASTNode getSelForClause(String clause) {
return destToSelExpr.get(clause);
}
/**
* Get the Cluster By AST for the clause.
*
* @param clause
* the name of the clause
* @return the abstract syntax tree
*/
public ASTNode getClusterByForClause(String clause) {
return destToClusterby.get(clause);
}
public HashMap<String, ASTNode> getDestToClusterBy() {
return destToClusterby;
}
/**
* Get the Distribute By AST for the clause.
*
* @param clause
* the name of the clause
* @return the abstract syntax tree
*/
public ASTNode getDistributeByForClause(String clause) {
return destToDistributeby.get(clause);
}
public HashMap<String, ASTNode> getDestToDistributeBy() {
return destToDistributeby;
}
/**
* Get the Sort By AST for the clause.
*
* @param clause
* the name of the clause
* @return the abstract syntax tree
*/
public ASTNode getSortByForClause(String clause) {
return destToSortby.get(clause);
}
public ASTNode getOrderByForClause(String clause) {
return destToOrderby.get(clause);
}
public HashMap<String, ASTNode> getDestToSortBy() {
return destToSortby;
}
public HashMap<String, ASTNode> getDestToOrderBy() {
return destToOrderby;
}
public ASTNode getSrcForAlias(String alias) {
return aliasToSrc.get(alias.toLowerCase());
}
public String getAlias() {
return alias;
}
public boolean getIsSubQ() {
return isSubQ;
}
public ASTNode getJoinExpr() {
return joinExpr;
}
public void setJoinExpr(ASTNode joinExpr) {
this.joinExpr = joinExpr;
}
public TableSample getTabSample(String alias) {
return nameToSample.get(alias.toLowerCase());
}
public void setTabSample(String alias, TableSample tableSample) {
nameToSample.put(alias.toLowerCase(), tableSample);
}
public String getExprToColumnAlias(ASTNode expr) {
return exprToColumnAlias.get(expr);
}
public Map<ASTNode, String> getAllExprToColumnAlias() {
return exprToColumnAlias;
}
public boolean hasExprToColumnAlias(ASTNode expr) {
return exprToColumnAlias.containsKey(expr);
}
public void setExprToColumnAlias(ASTNode expr, String alias) {
exprToColumnAlias.put(expr, alias);
}
public void setDestLimit(String dest, Integer limit) {
destToLimit.put(dest, limit);
}
public Integer getDestLimit(String dest) {
return destToLimit.get(dest);
}
/**
* @return the outerQueryLimit
*/
public int getOuterQueryLimit() {
return outerQueryLimit;
}
/**
* @param outerQueryLimit
* the outerQueryLimit to set
*/
public void setOuterQueryLimit(int outerQueryLimit) {
this.outerQueryLimit = outerQueryLimit;
}
public boolean isSelectStarQuery() {
if (isSubQ || (joinExpr != null) || (!nameToSample.isEmpty())
|| (!destToGroupby.isEmpty()) || (!destToClusterby.isEmpty())
|| (!aliasToLateralViews.isEmpty())) {
return false;
}
Iterator<Map.Entry<String, LinkedHashMap<String, ASTNode>>> aggrIter = destToAggregationExprs
.entrySet().iterator();
while (aggrIter.hasNext()) {
HashMap<String, ASTNode> h = aggrIter.next().getValue();
if ((h != null) && (!h.isEmpty())) {
return false;
}
}
if (!destToDistinctFuncExprs.isEmpty()) {
Iterator<Map.Entry<String, List<ASTNode>>> distn = destToDistinctFuncExprs
.entrySet().iterator();
while (distn.hasNext()) {
List<ASTNode> ct = distn.next().getValue();
if (!ct.isEmpty()) {
return false;
}
}
}
Iterator<Map.Entry<String, ASTNode>> iter = nameToDest.entrySet()
.iterator();
while (iter.hasNext()) {
Map.Entry<String, ASTNode> entry = iter.next();
ASTNode v = entry.getValue();
if (!(((ASTNode) v.getChild(0)).getToken().getType() == HiveParser.TOK_TMP_FILE)) {
return false;
}
}
iter = destToSelExpr.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String, ASTNode> entry = iter.next();
ASTNode selExprList = entry.getValue();
// Iterate over the selects
for (int i = 0; i < selExprList.getChildCount(); ++i) {
// list of the columns
ASTNode selExpr = (ASTNode) selExprList.getChild(i);
ASTNode sel = (ASTNode) selExpr.getChild(0);
if (sel.getToken().getType() != HiveParser.TOK_ALLCOLREF) {
return false;
}
}
}
return true;
}
public void setHints(ASTNode hint) {
hints = hint;
}
public ASTNode getHints() {
return hints;
}
public Map<String, ArrayList<ASTNode>> getAliasToLateralViews() {
return aliasToLateralViews;
}
public List<ASTNode> getLateralViewsForAlias(String alias) {
return aliasToLateralViews.get(alias.toLowerCase());
}
public void addLateralViewForAlias(String alias, ASTNode lateralView) {
ArrayList<ASTNode> lateralViews = aliasToLateralViews.get(alias);
if (lateralViews == null) {
lateralViews = new ArrayList<ASTNode>();
aliasToLateralViews.put(alias, lateralViews);
}
lateralViews.add(lateralView);
}
public void setIsAnalyzeCommand(boolean isAnalyzeCommand) {
this.isAnalyzeCommand = isAnalyzeCommand;
}
public boolean isAnalyzeCommand() {
return isAnalyzeCommand;
}
public void setIsInsertToTable(boolean isInsertToTable) {
this.isInsertToTable = isInsertToTable;
}
public boolean isInsertToTable() {
return isInsertToTable;
}
public void addTableSpec(String tName, tableSpec tSpec) {
tableSpecs.put(tName, tSpec);
}
public tableSpec getTableSpec(String tName) {
return tableSpecs.get(tName);
}
/**
* This method is used only for the anlayze command to get the partition specs
*/
public tableSpec getTableSpec() {
Iterator<String> tName = tableSpecs.keySet().iterator();
return tableSpecs.get(tName.next());
}
public HashMap<String, Integer> getDestToLimit() {
return destToLimit;
}
public LinkedHashMap<String, LinkedHashMap<String, ASTNode>> getDestToAggregationExprs() {
return destToAggregationExprs;
}
public HashMap<String, List<ASTNode>> getDestToDistinctFuncExprs() {
return destToDistinctFuncExprs;
}
public HashMap<String, TableSample> getNameToSample() {
return nameToSample;
}
}