Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
AnalyticInfo.java
Go to the documentation of this file.
1 // Copyright 2014 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 import java.util.List;
19 
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22 
24 import com.google.common.base.Objects;
25 import com.google.common.base.Preconditions;
26 import com.google.common.collect.Lists;
27 
32 public class AnalyticInfo extends AggregateInfoBase {
33  private final static Logger LOG = LoggerFactory.getLogger(AnalyticInfo.class);
34 
35  // All unique analytic exprs of a select block. Used to populate
36  // super.aggregateExprs_ based on AnalyticExpr.getFnCall() for each analytic expr
37  // in this list.
38  private final ArrayList<Expr> analyticExprs_;
39 
40  // Intersection of the partition exps of all the analytic functions.
41  private final List<Expr> commonPartitionExprs_ = Lists.newArrayList();
42 
43  // map from analyticExprs_ to their corresponding analytic tuple slotrefs
45 
46  private AnalyticInfo(ArrayList<Expr> analyticExprs) {
47  super(new ArrayList<Expr>(), new ArrayList<FunctionCallExpr>());
48  analyticExprs_ = Expr.cloneList(analyticExprs);
49  // Extract the analytic function calls for each analytic expr.
50  for (Expr analyticExpr: analyticExprs) {
51  aggregateExprs_.add(((AnalyticExpr) analyticExpr).getFnCall());
52  }
54  }
55 
56  public ArrayList<Expr> getAnalyticExprs() { return analyticExprs_; }
58  public List<Expr> getCommonPartitionExprs() { return commonPartitionExprs_; }
59 
64  static public AnalyticInfo create(
65  ArrayList<Expr> analyticExprs, Analyzer analyzer) {
66  Preconditions.checkState(analyticExprs != null && !analyticExprs.isEmpty());
67  Expr.removeDuplicates(analyticExprs);
68  AnalyticInfo result = new AnalyticInfo(analyticExprs);
69  result.createTupleDescs(analyzer);
70 
71  // The tuple descriptors are logical. Their slots are remapped to physical tuples
72  // during plan generation.
73  result.outputTupleDesc_.setIsMaterialized(false);
74  result.intermediateTupleDesc_.setIsMaterialized(false);
75 
76  // Populate analyticTupleSmap_
77  Preconditions.checkState(analyticExprs.size() ==
78  result.outputTupleDesc_.getSlots().size());
79  for (int i = 0; i < analyticExprs.size(); ++i) {
80  result.analyticTupleSmap_.put(result.analyticExprs_.get(i),
81  new SlotRef(result.outputTupleDesc_.getSlots().get(i)));
82  result.outputTupleDesc_.getSlots().get(i).setSourceExpr(
83  result.analyticExprs_.get(i));
84  }
85  LOG.trace("analytictuple=" + result.outputTupleDesc_.debugString());
86  LOG.trace("analytictuplesmap=" + result.analyticTupleSmap_.debugString());
87  LOG.trace("analytic info:\n" + result.debugString());
88  return result;
89  }
90 
95  private void computeCommonPartitionExprs() {
96  for (Expr analyticExpr: analyticExprs_) {
97  Preconditions.checkState(analyticExpr.isAnalyzed_);
98  List<Expr> partitionExprs = ((AnalyticExpr) analyticExpr).getPartitionExprs();
99  if (partitionExprs == null) continue;
100  if (commonPartitionExprs_.isEmpty()) {
101  commonPartitionExprs_.addAll(partitionExprs);
102  } else {
103  commonPartitionExprs_.retainAll(partitionExprs);
104  if (commonPartitionExprs_.isEmpty()) break;
105  }
106  }
107  }
108 
113  public void getRefdSlots(List<SlotId> ids) {
114  Preconditions.checkState(intermediateTupleDesc_ != null);
115  Expr.getIds(analyticExprs_, null, ids);
116  // The backend assumes that the entire intermediateTupleDesc is materialized
118  ids.add(slotDesc.getId());
119  }
120  }
121 
122  @Override
124  materializedSlots_.clear();
125  List<Expr> exprs = Lists.newArrayList();
126  for (int i = 0; i < analyticExprs_.size(); ++i) {
127  SlotDescriptor outputSlotDesc = outputTupleDesc_.getSlots().get(i);
128  if (!outputSlotDesc.isMaterialized()) continue;
129  intermediateTupleDesc_.getSlots().get(i).setIsMaterialized(true);
130  exprs.add(analyticExprs_.get(i));
131  materializedSlots_.add(i);
132  }
133  List<Expr> resolvedExprs = Expr.substituteList(exprs, smap, analyzer, false);
134  analyzer.materializeSlots(resolvedExprs);
135  }
136 
143  public void checkConsistency() {
144  ArrayList<SlotDescriptor> slots = intermediateTupleDesc_.getSlots();
145 
146  // Check materialized slots.
147  int numMaterializedSlots = 0;
148  for (SlotDescriptor slotDesc: slots) {
149  if (slotDesc.isMaterialized()) ++numMaterializedSlots;
150  }
151  Preconditions.checkState(numMaterializedSlots ==
152  materializedSlots_.size());
153 
154  // Check that analytic expr return types match the slot descriptors.
155  int slotIdx = 0;
156  for (int i = 0; i < analyticExprs_.size(); ++i) {
157  Expr analyticExpr = analyticExprs_.get(i);
158  Type slotType = slots.get(slotIdx).getType();
159  Preconditions.checkState(analyticExpr.getType().equals(slotType),
160  String.format("Analytic expr %s returns type %s but its analytic tuple " +
161  "slot has type %s", analyticExpr.toSql(),
162  analyticExpr.getType().toString(), slotType.toString()));
163  ++slotIdx;
164  }
165  }
166 
167  @Override
168  public String debugString() {
169  StringBuilder out = new StringBuilder(super.debugString());
170  out.append(Objects.toStringHelper(this)
171  .add("analytic_exprs", Expr.debugString(analyticExprs_))
172  .add("smap", analyticTupleSmap_.debugString())
173  .toString());
174  return out.toString();
175  }
176 
177  protected String tupleDebugName() { return "analytic-tuple"; }
178 }
final ExprSubstitutionMap analyticTupleSmap_
static AnalyticInfo create(ArrayList< Expr > analyticExprs, Analyzer analyzer)
void materializeRequiredSlots(Analyzer analyzer, ExprSubstitutionMap smap)
AnalyticInfo(ArrayList< Expr > analyticExprs)