Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
CreateOrAlterViewStmtBase.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 
25 import com.cloudera.impala.thrift.TCreateOrAlterViewParams;
26 import com.cloudera.impala.thrift.TTableName;
27 import com.google.common.base.Preconditions;
28 import com.google.common.collect.Lists;
29 import com.google.common.collect.Sets;
30 
34 public abstract class CreateOrAlterViewStmtBase extends StatementBase {
35  private final static Logger LOG =
36  LoggerFactory.getLogger(CreateOrAlterViewStmtBase.class);
37 
38  protected final boolean ifNotExists_;
39  protected final TableName tableName_;
40  protected final ArrayList<ColumnDef> columnDefs_;
41  protected final String comment_;
42  protected final QueryStmt viewDefStmt_;
43 
44  // Set during analysis
45  protected String dbName_;
46  protected String owner_;
47 
48  // The original SQL-string given as view definition. Set during analysis.
49  // Corresponds to Hive's viewOriginalText.
50  protected String originalViewDef_;
51 
52  // Query statement (as SQL string) that defines the View for view substitution.
53  // It is a transformation of the original view definition, e.g., to enforce the
54  // columnDefs even if the original view definition has explicit column aliases.
55  // If column definitions were given, then this "expanded" view definition
56  // wraps the original view definition in a select stmt as follows.
57  //
58  // SELECT viewName.origCol1 AS colDesc1, viewName.origCol2 AS colDesc2, ...
59  // FROM (originalViewDef) AS viewName
60  //
61  // Corresponds to Hive's viewExpandedText, but is not identical to the SQL
62  // Hive would produce in view creation.
63  protected String inlineViewDef_;
64 
65  // Columns to use in the select list of the expanded SQL string and when registering
66  // this view in the metastore. Set in analysis.
67  protected ArrayList<ColumnDef> finalColDefs_;
68 
69  public CreateOrAlterViewStmtBase(boolean ifNotExists, TableName tableName,
70  ArrayList<ColumnDef> columnDefs, String comment, QueryStmt viewDefStmt) {
71  Preconditions.checkNotNull(tableName);
72  Preconditions.checkNotNull(viewDefStmt);
73  this.ifNotExists_ = ifNotExists;
74  this.tableName_ = tableName;
75  this.columnDefs_ = columnDefs;
76  this.comment_ = comment;
77  this.viewDefStmt_ = viewDefStmt;
78  }
79 
85  protected void createColumnAndViewDefs(Analyzer analyzer) throws AnalysisException {
86  Preconditions.checkNotNull(dbName_);
87  Preconditions.checkNotNull(owner_);
88 
89  // Set the finalColDefs to reflect the given column definitions.
90  if (columnDefs_ != null) {
91  Preconditions.checkState(!columnDefs_.isEmpty());
92  if (columnDefs_.size() != viewDefStmt_.getColLabels().size()) {
93  String cmp =
94  (columnDefs_.size() > viewDefStmt_.getColLabels().size()) ? "more" : "fewer";
95  throw new AnalysisException(String.format("Column-definition list has " +
96  "%s columns (%s) than the view-definition query statement returns (%s).",
97  cmp, columnDefs_.size(), viewDefStmt_.getColLabels().size()));
98  }
99 
101  Preconditions.checkState(
102  columnDefs_.size() == viewDefStmt_.getBaseTblResultExprs().size());
103  for (int i = 0; i < columnDefs_.size(); ++i) {
104  // Set type in the column definition from the view-definition statement.
105  columnDefs_.get(i).setType(viewDefStmt_.getBaseTblResultExprs().get(i).getType());
106  }
107  } else {
108  // Create list of column definitions from the view-definition statement.
109  finalColDefs_ = Lists.newArrayList();
110  List<Expr> exprs = viewDefStmt_.getBaseTblResultExprs();
111  List<String> labels = viewDefStmt_.getColLabels();
112  Preconditions.checkState(exprs.size() == labels.size());
113  for (int i = 0; i < viewDefStmt_.getColLabels().size(); ++i) {
114  ColumnDef colDef = new ColumnDef(labels.get(i), null, null);
115  colDef.setType(exprs.get(i).getType());
116  finalColDefs_.add(colDef);
117  }
118  }
119 
120  // Check that the column definitions have valid names, and that there are no
121  // duplicate column names.
122  Set<String> distinctColNames = Sets.newHashSet();
123  for (ColumnDef colDesc: finalColDefs_) {
124  colDesc.analyze();
125  if (!distinctColNames.add(colDesc.getColName().toLowerCase())) {
126  throw new AnalysisException("Duplicate column name: " + colDesc.getColName());
127  }
128  }
129 
130  // Set original and expanded view-definition SQL strings.
131  originalViewDef_ = viewDefStmt_.toSql();
132 
133  // If no column definitions were given, then the expanded view SQL is the same
134  // as the original one.
135  if (columnDefs_ == null) {
137  return;
138  }
139 
140  // Wrap the original view-definition statement into a SELECT to enforce the
141  // given column definitions.
142  StringBuilder sb = new StringBuilder();
143  sb.append("SELECT ");
144  for (int i = 0; i < finalColDefs_.size(); ++i) {
145  String colRef = ToSqlUtils.getIdentSql(viewDefStmt_.getColLabels().get(i));
146  String colAlias = ToSqlUtils.getIdentSql(finalColDefs_.get(i).getColName());
147  sb.append(String.format("%s.%s AS %s", tableName_.getTbl(), colRef, colAlias));
148  sb.append((i+1 != finalColDefs_.size()) ? ", " : "");
149  }
150  // Do not use 'AS' for table aliases because Hive only accepts them without 'AS'.
151  sb.append(String.format(" FROM (%s) %s", originalViewDef_, tableName_.getTbl()));
152  inlineViewDef_ = sb.toString();
153  }
154 
158  protected void computeLineageGraph(Analyzer analyzer) {
159  ColumnLineageGraph graph = analyzer.getColumnLineageGraph();
160  List<String> colDefs = Lists.newArrayList();
161  for (ColumnDef colDef: finalColDefs_) {
162  colDefs.add(dbName_ + "." + getTbl() + "." + colDef.getColName());
163  }
164  graph.addTargetColumnLabels(colDefs);
165  graph.computeLineageGraph(viewDefStmt_.getResultExprs(), analyzer);
166  LOG.trace("lineage: " + graph.debugString());
167  }
168 
169  public TCreateOrAlterViewParams toThrift() {
170  TCreateOrAlterViewParams params = new TCreateOrAlterViewParams();
171  params.setView_name(new TTableName(getDb(), getTbl()));
172  for (ColumnDef col: finalColDefs_) {
173  params.addToColumns(col.toThrift());
174  }
175  params.setOwner(getOwner());
176  params.setIf_not_exists(getIfNotExists());
177  params.setOriginal_view_def(originalViewDef_);
178  params.setExpanded_view_def(inlineViewDef_);
179  if (comment_ != null) params.setComment(comment_);
180  return params;
181  }
182 
187  public String getDb() {
188  Preconditions.checkNotNull(dbName_);
189  return dbName_;
190  }
191 
195  public String getOwner() {
196  Preconditions.checkNotNull(owner_);
197  return owner_;
198  }
199 
200  public List<ColumnDef> getColumnDescs() {return columnDefs_; }
201  public String getComment() { return comment_; }
202  public boolean getIfNotExists() { return ifNotExists_; }
203  public String getOriginalViewDef() { return originalViewDef_; }
204  public String getInlineViewDef() { return inlineViewDef_; }
205  public String getTbl() { return tableName_.getTbl(); }
206 }
CreateOrAlterViewStmtBase(boolean ifNotExists, TableName tableName, ArrayList< ColumnDef > columnDefs, String comment, QueryStmt viewDefStmt)
ArrayList< Expr > getBaseTblResultExprs()
Definition: QueryStmt.java:280
abstract ArrayList< String > getColLabels()