blob: 7efd00c3efdd96ece2f9b61f0e09957b6226af1b [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.analysis;
import org.apache.impala.authorization.Privilege;
import org.apache.impala.catalog.FeDb;
import org.apache.impala.common.AnalysisException;
import org.apache.impala.thrift.TDropDbParams;
/**
* Represents a DROP [IF EXISTS] DATABASE [CASCADE | RESTRICT] statement
*/
public class DropDbStmt extends StatementBase {
private final String dbName_;
private final boolean ifExists_;
private final boolean cascade_;
// Server name needed for privileges. Set during analysis.
private String serverName_;
/**
* Constructor for building the drop statement. If ifExists is true, an error will not
* be thrown if the database does not exist. If cascade is true, all the tables in the
* database will be dropped.
*/
public DropDbStmt(String dbName, boolean ifExists, boolean cascade) {
this.dbName_ = dbName;
this.ifExists_ = ifExists;
this.cascade_ = cascade;
}
public String getDb() { return dbName_; }
public boolean getIfExists() { return ifExists_; }
public boolean getCascade() { return cascade_; }
@Override
public String toSql(ToSqlOptions options) {
StringBuilder sb = new StringBuilder("DROP DATABASE");
if (ifExists_) sb.append(" IF EXISTS ");
sb.append(getDb());
if (cascade_) sb.append(" CASCADE");
return sb.toString();
}
public TDropDbParams toThrift() {
TDropDbParams params = new TDropDbParams();
params.setDb(getDb());
params.setIf_exists(getIfExists());
params.setCascade(getCascade());
params.setServer_name(serverName_);
return params;
}
@Override
public void analyze(Analyzer analyzer) throws AnalysisException {
// Set the servername here if authorization is enabled because analyzer_ is not
// available in the toThrift() method.
serverName_ = analyzer.getServerName();
// Fetch the owner information if the db exists.
FeDb db = analyzer.getDb(dbName_, /*ThrowIfNotExists*/ false);
String ownerUser = db == null ? null : db.getOwnerUser();
if (ifExists_) {
// Start with ANY privilege in case of IF EXISTS, and register DROP privilege
// later only if the database exists. See IMPALA-8851 for more explanation.
analyzer.registerPrivReq(builder ->
builder.allOf(Privilege.ANY)
.onDb(dbName_, ownerUser)
.build());
if (!analyzer.dbExists(dbName_)) return;
}
// Register the DROP privilege request.
db = analyzer.getDb(dbName_, Privilege.DROP, false, false);
if (db == null && !ifExists_) {
throw new AnalysisException(Analyzer.DB_DOES_NOT_EXIST_ERROR_MSG + dbName_);
}
if (analyzer.getDefaultDb().toLowerCase().equals(dbName_.toLowerCase())) {
throw new AnalysisException("Cannot drop current default database: " + dbName_);
}
if (db != null && db.numFunctions() > 0 && !cascade_) {
throw new AnalysisException("Cannot drop non-empty database: " + dbName_);
}
}
}