Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Subquery.java
Go to the documentation of this file.
1 // Copyright 2012 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.cloudera.impala.analysis;
16 
17 import java.util.ArrayList;
18 
19 import org.apache.hadoop.hive.metastore.MetaStoreUtils;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22 
27 import com.cloudera.impala.thrift.TExprNode;
28 import com.google.common.base.Preconditions;
29 import com.google.common.collect.Lists;
30 import com.google.common.collect.Sets;
31 
36 public class Subquery extends Expr {
37  private final static Logger LOG = LoggerFactory.getLogger(Subquery.class);
38 
39  // The QueryStmt of the subquery.
40  protected QueryStmt stmt_;
41  // A subquery has its own analysis context
42  protected Analyzer analyzer_;
43 
44  public Analyzer getAnalyzer() { return analyzer_; }
45  public QueryStmt getStatement() { return stmt_; }
46  @Override
47  public String toSqlImpl() { return "(" + stmt_.toSql() + ")"; }
48 
52  public Subquery(QueryStmt queryStmt) {
53  super();
54  Preconditions.checkNotNull(queryStmt);
55  stmt_ = queryStmt;
56  }
57 
61  public Subquery(Subquery other) {
62  super(other);
63  stmt_ = other.stmt_.clone();
64  isAnalyzed_ = false;
65  }
66 
70  @Override
71  public void analyze(Analyzer analyzer) throws AnalysisException {
72  if (isAnalyzed_) return;
73  super.analyze(analyzer);
74  if (!(stmt_ instanceof SelectStmt)) {
75  throw new AnalysisException("A subquery must contain a single select block: " +
76  toSql());
77  }
78  // The subquery is analyzed with its own analyzer.
79  analyzer_ = new Analyzer(analyzer);
80  analyzer_.setIsSubquery();
81  stmt_.analyze(analyzer_);
82 
83  // Set the subquery type based on the types of the exprs in the
84  // result list of the associated SelectStmt.
85  ArrayList<Expr> stmtResultExprs = stmt_.getResultExprs();
86  if (stmtResultExprs.size() == 1) {
87  type_ = stmtResultExprs.get(0).getType();
88  Preconditions.checkState(!type_.isComplexType());
89  } else {
91  }
92 
93  // If the subquery returns many rows, set its type to ArrayType.
94  if (!((SelectStmt)stmt_).returnsSingleRow()) type_ = new ArrayType(type_);
95 
96  Preconditions.checkNotNull(type_);
97  isAnalyzed_ = true;
98  }
99 
103  public boolean returnsScalarColumn() {
104  ArrayList<Expr> stmtResultExprs = stmt_.getResultExprs();
105  if (stmtResultExprs.size() == 1 && stmtResultExprs.get(0).getType().isScalarType()) {
106  return true;
107  }
108  return false;
109  }
110 
115  ArrayList<Expr> stmtResultExprs = stmt_.getResultExprs();
116  ArrayList<StructField> structFields = Lists.newArrayList();
117  // Check if we have unique labels
118  ArrayList<String> labels = stmt_.getColLabels();
119  boolean hasUniqueLabels = true;
120  if (Sets.newHashSet(labels).size() != labels.size()) hasUniqueLabels = false;
121 
122  // Construct a StructField from each expr in the select list
123  for (int i = 0; i < stmtResultExprs.size(); ++i) {
124  Expr expr = stmtResultExprs.get(i);
125  String fieldName = null;
126  // Check if the label meets the Metastore's requirements.
127  if (MetaStoreUtils.validateName(labels.get(i))) {
128  fieldName = labels.get(i);
129  // Make sure the field names are unique.
130  if (!hasUniqueLabels) {
131  fieldName = "_" + Integer.toString(i) + "_" + fieldName;
132  }
133  } else {
134  // Use the expr ordinal to construct a StructField.
135  fieldName = "_" + Integer.toString(i);
136  }
137  Preconditions.checkNotNull(fieldName);
138  structFields.add(new StructField(fieldName, expr.getType(), null));
139  }
140  Preconditions.checkState(structFields.size() != 0);
141  return new StructType(structFields);
142  }
143 
144  @Override
145  public Subquery clone() { return new Subquery(this); }
146 
147  @Override
148  protected void toThrift(TExprNode msg) {}
149 }
void analyze(Analyzer analyzer)
Definition: Subquery.java:71