Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Path.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 
27 import com.google.common.base.Joiner;
28 import com.google.common.base.Preconditions;
29 import com.google.common.collect.Lists;
30 
74 public class Path {
75  // Implicit field names of collections.
76  public static final String ARRAY_ITEM_FIELD_NAME = "item";
77  public static final String ARRAY_POS_FIELD_NAME = "pos";
78  public static final String MAP_KEY_FIELD_NAME = "key";
79  public static final String MAP_VALUE_FIELD_NAME = "value";
80 
81  public static enum PathType {
84  STAR
85  }
86 
87  // Implicit or explicit raw path to be resolved relative to rootDesc_ or rootTable_.
88  // Every raw-path element is mapped to zero, one or two types/positions in resolution.
89  private final List<String> rawPath_;
90 
91  // Registered table alias that this path is rooted at, if any.
92  // Null if the path is rooted at a catalog table/view.
93  private final TupleDescriptor rootDesc_;
94 
95  // Catalog table that this resolved path is rooted at, if any.
96  // Null if the path is rooted at a registered tuple that does not
97  // belong to a catalog table/view.
98  private final Table rootTable_;
99 
100  // Root path that a relative path was created from.
101  private final Path rootPath_;
102 
103  // List of matched types and field positions set during resolution. The matched
104  // types/positions describe the physical path through the schema tree.
105  private final List<Type> matchedTypes_ = Lists.newArrayList();
106  private final List<Integer> matchedPositions_ = Lists.newArrayList();
107 
108  // Remembers the indices into rawPath_ and matchedTypes_ of the first collection
109  // matched during resolution.
110  private int firstCollectionPathIdx_ = -1;
111  private int firstCollectionTypeIdx_ = -1;
112 
113  // Indicates whether this path has been resolved. Set in resolve().
114  private boolean isResolved_ = false;
115 
116  // Caches the result of getAbsolutePath() to avoid re-computing it.
117  private List<Integer> absolutePath_ = null;
118 
122  public Path(TupleDescriptor rootDesc, List<String> rawPath) {
123  Preconditions.checkNotNull(rootDesc);
124  Preconditions.checkNotNull(rawPath);
125  rootTable_ = rootDesc.getTable();
126  rootDesc_ = rootDesc;
127  rootPath_ = null;
128  rawPath_ = rawPath;
129  }
130 
134  public Path(Table rootTable, List<String> rawPath) {
135  Preconditions.checkNotNull(rootTable);
136  Preconditions.checkNotNull(rawPath);
137  rootTable_ = rootTable;
138  rootDesc_ = null;
139  rootPath_ = null;
140  rawPath_ = rawPath;
141  }
142 
146  public Path(Path rootPath, List<String> relRawPath) {
147  Preconditions.checkNotNull(rootPath);
148  Preconditions.checkState(rootPath.isResolved());
149  Preconditions.checkNotNull(relRawPath);
150  rootTable_ = rootPath.rootTable_;
151  rootDesc_ = rootPath.rootDesc_;
152  rootPath_ = rootPath;
153  rawPath_ = Lists.newArrayListWithCapacity(
154  rootPath.getRawPath().size() + relRawPath.size());
155  rawPath_.addAll(rootPath.getRawPath());
156  rawPath_.addAll(relRawPath);
157  matchedTypes_.addAll(rootPath.matchedTypes_);
158  matchedPositions_.addAll(rootPath.matchedPositions_);
159  firstCollectionPathIdx_ = rootPath.firstCollectionPathIdx_;
160  firstCollectionTypeIdx_ = rootPath.firstCollectionTypeIdx_;
161  }
162 
169  public boolean resolve() {
170  if (isResolved_) return true;
171  Preconditions.checkState(rootDesc_ != null || rootTable_ != null);
172  Type currentType = null;
173  int rawPathIdx = 0;
174  if (rootPath_ != null) {
175  // Continue resolving this path relative to the rootPath_.
176  currentType = rootPath_.destType();
177  rawPathIdx = rootPath_.getRawPath().size();
178  } else if (rootDesc_ != null) {
179  currentType = rootDesc_.getType();
180  } else {
181  // Directly start from the item type because only implicit paths are allowed.
182  currentType = rootTable_.getType().getItemType();
183  }
184 
185  // Map all remaining raw-path elements to field types and positions.
186  while (rawPathIdx < rawPath_.size()) {
187  if (!currentType.isComplexType()) return false;
188  StructType structType = getTypeAsStruct(currentType);
189  // Resolve explicit path.
190  StructField field = structType.getField(rawPath_.get(rawPathIdx));
191  if (field == null) {
192  // Resolve implicit path.
193  if (structType instanceof CollectionStructType) {
194  field = ((CollectionStructType) structType).getOptionalField();
195  } else {
196  // Failed to resolve implicit or explicit path.
197  return false;
198  }
199  // Update the physical types/positions.
200  matchedTypes_.add(field.getType());
201  matchedPositions_.add(field.getPosition());
202  currentType = field.getType();
203  // Do not consume a raw-path element.
204  continue;
205  }
206  matchedTypes_.add(field.getType());
207  matchedPositions_.add(field.getPosition());
208  if (field.getType().isCollectionType() && firstCollectionPathIdx_ == -1) {
209  Preconditions.checkState(firstCollectionTypeIdx_ == -1);
210  firstCollectionPathIdx_ = rawPathIdx;
211  firstCollectionTypeIdx_ = matchedTypes_.size() - 1;
212  }
213  currentType = field.getType();
214  ++rawPathIdx;
215  }
216  Preconditions.checkState(matchedTypes_.size() == matchedPositions_.size());
217  Preconditions.checkState(matchedTypes_.size() >= rawPath_.size());
218  isResolved_ = true;
219  return true;
220  }
221 
227  public static StructType getTypeAsStruct(Type t) {
228  Preconditions.checkState(t.isComplexType());
229  if (t.isStructType()) return (StructType) t;
230  if (t.isArrayType()) {
231  return CollectionStructType.createArrayStructType((ArrayType) t);
232  } else {
233  Preconditions.checkState(t.isMapType());
234  return CollectionStructType.createMapStructType((MapType) t);
235  }
236  }
237 
238  public Table getRootTable() { return rootTable_; }
239  public TupleDescriptor getRootDesc() { return rootDesc_; }
240  public List<String> getRawPath() { return rawPath_; }
241  public boolean isResolved() { return isResolved_; }
242 
243  public List<Type> getMatchedTypes() {
244  Preconditions.checkState(isResolved_);
245  return matchedTypes_;
246  }
247 
248  public List<Integer> getMatchedPositions() {
249  Preconditions.checkState(isResolved_);
250  return matchedPositions_;
251  }
252 
253  public boolean hasNonDestCollection() {
254  Preconditions.checkState(isResolved_);
255  return firstCollectionPathIdx_ != -1 &&
256  firstCollectionPathIdx_ != rawPath_.size() - 1;
257  }
258 
259  public String getFirstCollectionName() {
260  Preconditions.checkState(isResolved_);
261  if (firstCollectionPathIdx_ == -1) return null;
262  return rawPath_.get(firstCollectionPathIdx_);
263  }
264 
266  Preconditions.checkState(isResolved_);
267  if (firstCollectionTypeIdx_ == -1) return null;
268  return matchedTypes_.get(firstCollectionTypeIdx_);
269  }
270 
271  public Type destType() {
272  Preconditions.checkState(isResolved_);
273  if (!matchedTypes_.isEmpty()) return matchedTypes_.get(matchedTypes_.size() - 1);
274  if (rootDesc_ != null) return rootDesc_.getType();
275  if (rootTable_ != null) return rootTable_.getType();
276  return null;
277  }
278 
279  public Table destTable() {
280  Preconditions.checkState(isResolved_);
281  if (rootTable_ != null && rootDesc_ == null && matchedTypes_.isEmpty()) {
282  return rootTable_;
283  }
284  return null;
285  }
286 
292  public Column destColumn() {
293  Preconditions.checkState(isResolved_);
294  if (rootTable_ == null || rawPath_.size() != 1) return null;
295  return rootTable_.getColumn(rawPath_.get(rawPath_.size() - 1));
296  }
297 
303  Preconditions.checkState(isResolved_);
304  if (rootDesc_ != null && matchedTypes_.isEmpty()) return rootDesc_;
305  return null;
306  }
307 
308  public List<String> getFullyQualifiedRawPath() {
309  Preconditions.checkState(rootTable_ != null || rootDesc_ != null);
310  List<String> result = Lists.newArrayListWithCapacity(rawPath_.size() + 2);
311  if (rootDesc_ != null) {
312  result.addAll(Lists.newArrayList(rootDesc_.getAlias().split("\\.")));
313  } else {
314  result.add(rootTable_.getDb().getName());
315  result.add(rootTable_.getName());
316  }
317  result.addAll(rawPath_);
318  return result;
319  }
320 
325  public List<Integer> getAbsolutePath() {
326  if (absolutePath_ != null) return absolutePath_;
327  Preconditions.checkState(isResolved_);
328  absolutePath_ = Lists.newArrayList();
329  if (rootDesc_ != null) absolutePath_.addAll(rootDesc_.getPath().getAbsolutePath());
330  absolutePath_.addAll(matchedPositions_);
331  return absolutePath_;
332  }
333 
334  @Override
335  public String toString() {
336  Preconditions.checkState(rootTable_ != null || rootDesc_ != null);
337  String pathRoot = null;
338  if (rootDesc_ != null) {
339  pathRoot = rootDesc_.getAlias();
340  } else {
341  pathRoot = rootTable_.getFullName();
342  }
343  if (rawPath_.isEmpty()) return pathRoot;
344  return pathRoot + "." + Joiner.on(".").join(rawPath_);
345  }
346 
350  public static ArrayList<String> createRawPath(String rootAlias, String fieldName) {
351  ArrayList<String> result = Lists.newArrayList(rootAlias.split("\\."));
352  result.add(fieldName);
353  return result;
354  }
355 
356  public static Path createRelPath(Path rootPath, String... fieldNames) {
357  Preconditions.checkState(rootPath.isResolved());
358  Path result = new Path(rootPath, Lists.newArrayList(fieldNames));
359  return result;
360  }
361 }
final List< Type > matchedTypes_
Definition: Path.java:105
List< Integer > getMatchedPositions()
Definition: Path.java:248
List< String > getFullyQualifiedRawPath()
Definition: Path.java:308
Path(Path rootPath, List< String > relRawPath)
Definition: Path.java:146
final List< Integer > matchedPositions_
Definition: Path.java:106
TupleDescriptor destTupleDesc()
Definition: Path.java:302
static Path createRelPath(Path rootPath, String...fieldNames)
Definition: Path.java:356
List< Integer > getAbsolutePath()
Definition: Path.java:325
Path(Table rootTable, List< String > rawPath)
Definition: Path.java:134
final List< String > rawPath_
Definition: Path.java:89
Path(TupleDescriptor rootDesc, List< String > rawPath)
Definition: Path.java:122
static ArrayList< String > createRawPath(String rootAlias, String fieldName)
Definition: Path.java:350
static final String MAP_VALUE_FIELD_NAME
Definition: Path.java:79
static final String ARRAY_POS_FIELD_NAME
Definition: Path.java:77
List< Type > getMatchedTypes()
Definition: Path.java:243
List< String > getRawPath()
Definition: Path.java:240
static final String ARRAY_ITEM_FIELD_NAME
Definition: Path.java:76
static StructType getTypeAsStruct(Type t)
Definition: Path.java:227
TupleDescriptor getRootDesc()
Definition: Path.java:239
static final String MAP_KEY_FIELD_NAME
Definition: Path.java:78
List< Integer > absolutePath_
Definition: Path.java:117
final TupleDescriptor rootDesc_
Definition: Path.java:93