blob: a705f9126a431a029705842448a234034ea0d199 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.impala.catalog;
import java.util.List;
import java.util.Set;
import org.apache.hadoop.hive.metastore.IMetaStoreClient;
import org.apache.hadoop.hive.metastore.api.FieldSchema;
import org.apache.impala.analysis.Parser;
import org.apache.impala.analysis.QueryStmt;
import org.apache.impala.analysis.StatementBase;
import org.apache.impala.common.AnalysisException;
import org.apache.impala.thrift.TCatalogObjectType;
import org.apache.impala.thrift.TTable;
import org.apache.impala.thrift.TTableDescriptor;
import org.apache.impala.thrift.TTableStats;
import org.apache.impala.thrift.TTableType;
import com.google.common.collect.Lists;
/**
* Table metadata representing a catalog view or a local view from a WITH clause.
* Most methods inherited from Table are not supposed to be called on this class because
* views are substituted with their underlying definition during analysis of a statement.
*
* Refreshing or invalidating a view will reload the view's definition but will not
* affect the metadata of the underlying tables (if any).
*/
public class View extends Table implements FeView {
// View definition created by parsing inlineViewDef_ into a QueryStmt.
private QueryStmt queryStmt_;
// Set if this View is from a WITH clause and not persisted in the catalog.
private final boolean isLocalView_;
// Set if this View is from a WITH clause with column labels.
private List<String> colLabels_;
public View(org.apache.hadoop.hive.metastore.api.Table msTable,
Db db, String name, String owner) {
super(msTable, db, name, owner);
isLocalView_ = false;
}
/**
* C'tor for WITH-clause views that already have a parsed QueryStmt and an optional
* list of column labels.
*/
public View(String alias, QueryStmt queryStmt, List<String> colLabels) {
super(null, null, alias, null);
isLocalView_ = true;
queryStmt_ = queryStmt;
colLabels_ = colLabels;
}
/**
* Creates a view for testing purposes.
*/
private View(Db db, String name, QueryStmt queryStmt) {
super(null, db, name, null);
isLocalView_ = false;
queryStmt_ = queryStmt;
colLabels_ = null;
}
@Override
public void load(boolean reuseMetadata, IMetaStoreClient client,
org.apache.hadoop.hive.metastore.api.Table msTbl, String reason)
throws TableLoadingException {
try {
clearColumns();
msTable_ = msTbl;
// Load columns.
List<FieldSchema> fieldSchemas = client.getFields(db_.getName(), name_);
for (int i = 0; i < fieldSchemas.size(); ++i) {
FieldSchema s = fieldSchemas.get(i);
Type type = parseColumnType(s);
Column col = new Column(s.getName(), type, s.getComment(), i);
addColumn(col);
}
// These fields are irrelevant for views.
numClusteringCols_ = 0;
tableStats_ = new TTableStats(-1);
tableStats_.setTotal_file_bytes(-1);
queryStmt_ = parseViewDef(this);
refreshLastUsedTime();
} catch (TableLoadingException e) {
throw e;
} catch (Exception e) {
throw new TableLoadingException("Failed to load metadata for view: " + name_, e);
}
}
@Override
protected void loadFromThrift(TTable t) throws TableLoadingException {
super.loadFromThrift(t);
queryStmt_ = parseViewDef(this);
}
/**
* Parse the expanded view definition SQL-string.
* Throws a TableLoadingException if there was any error parsing the
* the SQL or if the view definition did not parse into a QueryStmt.
*/
public static QueryStmt parseViewDef(FeView view) throws TableLoadingException {
// Query statement (as SQL string) that defines the View for view substitution.
// It is a transformation of the original view definition, e.g., to enforce the
// explicit column definitions even if the original view definition has explicit
// column aliases.
// If column definitions were given, then this "expanded" view definition
// wraps the original view definition in a select stmt as follows.
//
// SELECT viewName.origCol1 AS colDesc1, viewName.origCol2 AS colDesc2, ...
// FROM (originalViewDef) AS viewName
//
// Corresponds to Hive's viewExpandedText, but is not identical to the SQL
// Hive would produce in view creation.
String inlineViewDef = view.getMetaStoreTable().getViewExpandedText();
// Parse the expanded view definition SQL-string into a QueryStmt and
// populate a view definition.
StatementBase node;
try {
node = Parser.parse(inlineViewDef);
} catch (AnalysisException e) {
// Do not pass e as the exception cause because it might reveal the existence
// of tables that the user triggering this load may not have privileges on.
throw new TableLoadingException(
String.format("Failed to parse view-definition statement of view: " +
"%s", view.getFullName()));
}
// Make sure the view definition parses to a query statement.
if (!(node instanceof QueryStmt)) {
throw new TableLoadingException(String.format("View definition of %s " +
"is not a query statement", view.getFullName()));
}
return (QueryStmt) node;
}
@Override
public TCatalogObjectType getCatalogObjectType() { return TCatalogObjectType.VIEW; }
@Override // FeView
public QueryStmt getQueryStmt() { return queryStmt_; }
@Override // FeView
public boolean isLocalView() { return isLocalView_; }
/**
* Returns the column labels the user specified in the WITH-clause.
*/
public List<String> getOriginalColLabels() { return colLabels_; }
@Override
public List<String> getColLabels() {
if (colLabels_ == null) return null;
if (colLabels_.size() >= queryStmt_.getColLabels().size()) return colLabels_;
List<String> explicitColLabels = Lists.newArrayList(colLabels_);
explicitColLabels.addAll(queryStmt_.getColLabels().subList(
colLabels_.size(), queryStmt_.getColLabels().size()));
return explicitColLabels;
}
@Override
public TTableDescriptor toThriftDescriptor(int tableId, Set<Long> referencedPartitions) {
throw new IllegalStateException("Cannot call toThriftDescriptor() on a view.");
}
@Override
public TTable toThrift() {
TTable view = super.toThrift();
view.setTable_type(TTableType.VIEW);
return view;
}
public static View createTestView(Db db, String name, QueryStmt viewDefStmt) {
return new View(db, name, viewDefStmt);
}
}