Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
SlotRef.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 import java.util.List;
19 import java.util.Set;
20 
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23 
28 import com.cloudera.impala.thrift.TExprNode;
29 import com.cloudera.impala.thrift.TExprNodeType;
30 import com.cloudera.impala.thrift.TSlotRef;
31 import com.google.common.base.Joiner;
32 import com.google.common.base.Objects;
33 import com.google.common.base.Preconditions;
34 
35 public class SlotRef extends Expr {
36  private final static Logger LOG = LoggerFactory.getLogger(SlotRef.class);
37 
38  private final List<String> rawPath_;
39  private final String label_; // printed in toSql()
40 
41  // Results of analysis.
43 
44  public SlotRef(ArrayList<String> rawPath) {
45  super();
46  rawPath_ = rawPath;
47  label_ = ToSqlUtils.getPathSql(rawPath_);
48  }
49 
53  public SlotRef(String alias) {
54  super();
55  rawPath_ = null;
56  // Relies on the label_ being compared in equals().
57  label_ = ToSqlUtils.getIdentSql(alias.toLowerCase());
58  }
59 
63  public SlotRef(SlotDescriptor desc) {
64  super();
65  if (desc.getPath() != null) {
66  rawPath_ = desc.getPath().getRawPath();
67  } else {
68  rawPath_ = null;
69  }
70  isAnalyzed_ = true;
71  desc_ = desc;
72  type_ = desc.getType();
73  String alias = desc.getParent().getAlias();
74  label_ = (alias != null ? alias + "." : "") + desc.getLabel();
75  numDistinctValues_ = desc.getStats().getNumDistinctValues();
76  }
77 
81  private SlotRef(SlotRef other) {
82  super(other);
83  rawPath_ = other.rawPath_;
84  label_ = other.label_;
85  desc_ = other.desc_;
86  type_ = other.type_;
87  isAnalyzed_ = other.isAnalyzed_;
88  }
89 
90  @Override
91  public void analyze(Analyzer analyzer) throws AnalysisException {
92  if (isAnalyzed_) return;
93  super.analyze(analyzer);
94  Path resolvedPath = null;
95  try {
96  resolvedPath = analyzer.resolvePath(rawPath_, PathType.SLOT_REF);
97  } catch (TableLoadingException e) {
98  // Should never happen because we only check registered table aliases.
99  Preconditions.checkState(false);
100  }
101  Preconditions.checkNotNull(resolvedPath);
102  desc_ = analyzer.registerSlotRef(resolvedPath);
103  type_ = desc_.getType();
104  if (!type_.isSupported()) {
105  throw new AnalysisException("Unsupported type '"
106  + type_.toSql() + "' in '" + toSql() + "'.");
107  }
108  if (type_.isInvalid()) {
109  // In this case, the metastore contained a string we can't parse at all
110  // e.g. map. We could report a better error if we stored the original
111  // HMS string.
112  throw new AnalysisException("Unsupported type in '" + toSql() + "'.");
113  }
114  numDistinctValues_ = desc_.getStats().getNumDistinctValues();
115  if (type_.isBoolean()) selectivity_ = DEFAULT_SELECTIVITY;
116  isAnalyzed_ = true;
117  }
118 
120  Preconditions.checkState(isAnalyzed_);
121  Preconditions.checkNotNull(desc_);
122  return desc_;
123  }
124 
125  public SlotId getSlotId() {
126  Preconditions.checkState(isAnalyzed_);
127  Preconditions.checkNotNull(desc_);
128  return desc_.getId();
129  }
130 
132  Preconditions.checkState(isAnalyzed_);
133  return desc_.getPath();
134  }
135 
136  @Override
137  public String toSqlImpl() {
138  if (label_ != null) return label_;
139  if (rawPath_ != null) return ToSqlUtils.getPathSql(rawPath_);
140  return "<slot " + Integer.toString(desc_.getId().asInt()) + ">";
141  }
142 
143  @Override
144  protected void toThrift(TExprNode msg) {
145  msg.node_type = TExprNodeType.SLOT_REF;
146  msg.slot_ref = new TSlotRef(desc_.getId().asInt());
147  Preconditions.checkState(desc_.getParent().isMaterialized(),
148  String.format("Illegal reference to non-materialized tuple: tid=%s",
149  desc_.getParent().getId()));
150  // we shouldn't be sending exprs over non-materialized slots
151  Preconditions.checkState(desc_.isMaterialized(),
152  String.format("Illegal reference to non-materialized slot: tid=%s sid=%s",
153  desc_.getParent().getId(), desc_.getId()));
154  // we also shouldn't have forgotten to compute the mem layout
155  Preconditions.checkState(desc_.getByteOffset() != -1,
156  String.format("Missing memory layout for tuple with tid=%s",
157  desc_.getParent().getId()));
158  }
159 
160  @Override
161  public String debugString() {
162  Objects.ToStringHelper toStrHelper = Objects.toStringHelper(this);
163  if (rawPath_ != null) toStrHelper.add("path", Joiner.on('.').join(rawPath_));
164  toStrHelper.add("type", type_.toSql());
165  String idStr = (desc_ == null ? "null" : Integer.toString(desc_.getId().asInt()));
166  toStrHelper.add("id", idStr);
167  return toStrHelper.toString();
168  }
169 
170  @Override
171  public int hashCode() {
172  if (desc_ != null) return desc_.getId().hashCode();
173  return Objects.hashCode(Joiner.on('.').join(rawPath_).toLowerCase());
174  }
175 
176  @Override
177  public boolean equals(Object obj) {
178  if (!super.equals(obj)) return false;
179  SlotRef other = (SlotRef) obj;
180  // check slot ids first; if they're both set we only need to compare those
181  // (regardless of how the ref was constructed)
182  if (desc_ != null && other.desc_ != null) {
183  return desc_.getId().equals(other.desc_.getId());
184  }
185  if ((label_ == null) != (other.label_ == null)) return false;
186  if (!label_.equalsIgnoreCase(other.label_)) return false;
187  return true;
188  }
189 
190  @Override
191  public boolean isBoundByTupleIds(List<TupleId> tids) {
192  Preconditions.checkState(desc_ != null);
193  for (TupleId tid: tids) {
194  if (tid.equals(desc_.getParent().getId())) return true;
195  }
196  return false;
197  }
198 
199  @Override
200  public boolean isBoundBySlotIds(List<SlotId> slotIds) {
201  Preconditions.checkState(isAnalyzed_);
202  return slotIds.contains(desc_.getId());
203  }
204 
205  @Override
206  public void getIdsHelper(Set<TupleId> tupleIds, Set<SlotId> slotIds) {
207  Preconditions.checkState(type_.isValid());
208  Preconditions.checkState(desc_ != null);
209  if (slotIds != null) slotIds.add(desc_.getId());
210  if (tupleIds != null) tupleIds.add(desc_.getParent().getId());
211  }
212 
213  @Override
214  public Expr clone() { return new SlotRef(this); }
215 
216  @Override
217  public String toString() {
218  if (desc_ != null) {
219  return "tid=" + desc_.getParent().getId() + " sid=" + desc_.getId();
220  }
221  return "no desc set";
222  }
223 
224  @Override
225  protected Expr uncheckedCastTo(Type targetType) throws AnalysisException {
226  if (type_.isNull()) {
227  // Hack to prevent null SlotRefs in the BE
228  return NullLiteral.create(targetType);
229  } else {
230  return super.uncheckedCastTo(targetType);
231  }
232  }
233 }
void getIdsHelper(Set< TupleId > tupleIds, Set< SlotId > slotIds)
Definition: SlotRef.java:206
final List< String > rawPath_
Definition: SlotRef.java:38
Expr uncheckedCastTo(Type targetType)
Definition: SlotRef.java:225
SlotRef(SlotDescriptor desc)
Definition: SlotRef.java:63
boolean isBoundBySlotIds(List< SlotId > slotIds)
Definition: SlotRef.java:200
SlotRef(ArrayList< String > rawPath)
Definition: SlotRef.java:44
boolean isBoundByTupleIds(List< TupleId > tids)
Definition: SlotRef.java:191
void analyze(Analyzer analyzer)
Definition: SlotRef.java:91
static double DEFAULT_SELECTIVITY
Definition: Expr.java:63