Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support drop database/table if exists #3348

Merged
merged 12 commits into from
Jul 14, 2023
18 changes: 18 additions & 0 deletions cases/plan/cmd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ cases:
+-node[CMD]
+-cmd_type: drop table
+-args: [db1, t1]
- id: 14-3
desc: DROP TABLE IF EXISTS
sql: DROP TABLE IF EXISTS t1;
expect:
node_tree_str: |
+-node[CMD]
+-cmd_type: drop table
+-if_not_exists: true
dl239 marked this conversation as resolved.
Show resolved Hide resolved
+-args: [t1]
- id: 15-1
desc: DROP INDEX
sql: DROP INDEX t1.index1
Expand Down Expand Up @@ -171,6 +180,15 @@ cases:
+-node[CMD]
+-cmd_type: drop database
+-args: [db1]
- id: 18
desc: DROP DATABASE IF EXISTS
sql: DROP DATABASE IF EXISTS db1
expect:
node_tree_str: |
+-node[CMD]
+-cmd_type: drop database
+-if_not_exists: true
+-args: [db1]
- id: show_deployments
desc: show deployments
sql: SHOW DEPLOYMENTS;
Expand Down
2 changes: 2 additions & 0 deletions hybridse/src/planv2/ast_node_converter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2011,13 +2011,15 @@ base::Status ConvertDropStatement(const zetasql::ASTDropStatement* root, node::N
*output = dynamic_cast<node::CmdNode*>(
node_manager->MakeCmdNode(node::CmdType::kCmdDropTable, names[0], names[1]));
}
(*output)->SetIfNotExists(root->is_if_exists());
dl239 marked this conversation as resolved.
Show resolved Hide resolved
return base::Status::OK();
}
case zetasql::SchemaObjectKind::kDatabase: {
CHECK_TRUE(1 == names.size(), common::kSqlAstError, "Invalid database path expression ",
root->name()->ToIdentifierPathString())
*output =
dynamic_cast<node::CmdNode*>(node_manager->MakeCmdNode(node::CmdType::kCmdDropDatabase, names[0]));
(*output)->SetIfNotExists(root->is_if_exists());
return base::Status::OK();
}
case zetasql::SchemaObjectKind::kIndex: {
Expand Down
5 changes: 4 additions & 1 deletion src/client/ns_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,16 @@ bool NsClient::ShowDatabase(std::vector<std::string>* dbs, std::string& msg) {
return ok && response.code() == 0;
}

bool NsClient::DropDatabase(const std::string& db, std::string& msg) {
bool NsClient::DropDatabase(const std::string& db, std::string& msg, bool if_not_exists) {
dl239 marked this conversation as resolved.
Show resolved Hide resolved
::openmldb::nameserver::DropDatabaseRequest request;
::openmldb::nameserver::GeneralResponse response;
request.set_db(db);
bool ok = client_.SendRequest(&::openmldb::nameserver::NameServer_Stub::DropDatabase, &request, &response,
FLAGS_request_timeout_ms, 1);
msg = response.msg();
if (if_not_exists) {
return ok && (response.code() == 0 || response.code() == ::openmldb::base::ReturnCode::kDatabaseNotFound);
}
return ok && response.code() == 0;
}

Expand Down
2 changes: 1 addition & 1 deletion src/client/ns_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class NsClient : public Client {
bool ShowDatabase(std::vector<std::string>* dbs,
std::string& msg); // NOLINT

bool DropDatabase(const std::string& db, std::string& msg); // NOLINT
bool DropDatabase(const std::string& db, std::string& msg, bool if_not_exists = false); // NOLINT

bool ShowTablet(std::vector<TabletInfo>& tablets, // NOLINT
std::string& msg); // NOLINT
Expand Down
29 changes: 20 additions & 9 deletions src/sdk/sql_cluster_router.cc
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,8 @@ bool SQLClusterRouter::DropDB(const std::string& db, hybridse::sdk::Status* stat
return true;
}

bool SQLClusterRouter::DropTable(const std::string& db, const std::string& table, hybridse::sdk::Status* status) {
bool SQLClusterRouter::DropTable(const std::string& db, const std::string& table, const bool if_not_exists,
hybridse::sdk::Status* status) {
RET_FALSE_IF_NULL_AND_WARN(status, "output status is nullptr");
if (db.empty() || table.empty()) {
SET_STATUS_AND_WARN(status, StatusCode::kCmdError,
Expand All @@ -916,20 +917,30 @@ bool SQLClusterRouter::DropTable(const std::string& db, const std::string& table
return false;
}

auto tableInfo = GetTableInfo(db, table);
auto table_info = cluster_sdk_->GetTableInfo(db, table);

if (table_info == nullptr) {
if (if_not_exists) {
*status = {};
return true;
} else {
SET_STATUS_AND_WARN(status, StatusCode::kCmdError, "fail to drop, table does not exist!");
return false;
}
}

// delete pre-aggr meta info if need
if (tableInfo.base_table_tid() > 0) {
if (table_info->base_table_tid() > 0) {
std::string meta_db = openmldb::nameserver::INTERNAL_DB;
std::string meta_table = openmldb::nameserver::PRE_AGG_META_NAME;
std::string select_aggr_info =
absl::StrCat("select base_db,base_table,aggr_func,aggr_col,partition_cols,order_by_col,filter_col from ",
meta_db, ".", meta_table, " where aggr_table = '", tableInfo.name(), "';");
meta_db, ".", meta_table, " where aggr_table = '", table_info->name(), "';");
auto rs = ExecuteSQL("", select_aggr_info, true, true, 0, status);
WARN_NOT_OK_AND_RET(status, "get aggr info failed", false);
if (rs->Size() != 1) {
SET_STATUS_AND_WARN(status, StatusCode::kCmdError,
"duplicate records generate with aggr table name: " + tableInfo.name());
"duplicate records generate with aggr table name: " + table_info->name());
return false;
}
std::string idx_key;
Expand Down Expand Up @@ -961,15 +972,15 @@ bool SQLClusterRouter::DropTable(const std::string& db, const std::string& table
}
auto tid = cluster_sdk_->GetTableId(meta_db, meta_table);
std::string msg;
if (!tablet_client->Delete(tid, 0, tableInfo.name(), "aggr_table", msg) ||
if (!tablet_client->Delete(tid, 0, table_info->name(), "aggr_table", msg) ||
!tablet_client->Delete(tid, 0, idx_key, "unique_key", msg)) {
SET_STATUS_AND_WARN(status, StatusCode::kCmdError, "delete aggr meta failed");
return false;
}
}

// Check offline table info first
if (tableInfo.has_offline_table_info()) {
if (table_info->has_offline_table_info()) {
auto taskmanager_client_ptr = cluster_sdk_->GetTaskManagerClient();
if (!taskmanager_client_ptr) {
SET_STATUS_AND_WARN(status, StatusCode::kRuntimeError, "no taskmanager client");
Expand Down Expand Up @@ -1644,7 +1655,7 @@ std::shared_ptr<hybridse::sdk::ResultSet> SQLClusterRouter::HandleSQLCmd(const h
}
case hybridse::node::kCmdDropDatabase: {
std::string name = cmd_node->GetArgs()[0];
if (ns_ptr->DropDatabase(name, msg)) {
if (ns_ptr->DropDatabase(name, msg, cmd_node->IsIfNotExists())) {
*status = {};
} else {
*status = {StatusCode::kCmdError, msg};
Expand Down Expand Up @@ -1886,7 +1897,7 @@ std::shared_ptr<hybridse::sdk::ResultSet> SQLClusterRouter::HandleSQLCmd(const h
if (!CheckAnswerIfInteractive("table", table_name)) {
return {};
}
if (DropTable(db_name, table_name, status)) {
if (DropTable(db_name, table_name, cmd_node -> IsIfNotExists(), status)) {
RefreshCatalog();
}
return {};
Expand Down
3 changes: 2 additions & 1 deletion src/sdk/sql_cluster_router.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ class SQLClusterRouter : public SQLRouter {

bool DropDB(const std::string& db, hybridse::sdk::Status* status) override;

bool DropTable(const std::string& db, const std::string& table, hybridse::sdk::Status* status);
bool DropTable(const std::string& db, const std::string& table, const bool if_not_exists,
hybridse::sdk::Status* status);

bool ShowDB(std::vector<std::string>* dbs, hybridse::sdk::Status* status) override;

Expand Down
39 changes: 39 additions & 0 deletions src/sdk/sql_cluster_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,45 @@ class SQLClusterDDLTest : public SQLClusterTest {
std::shared_ptr<SQLRouter> router;
std::string db;
};

TEST_F(SQLClusterDDLTest, TestIfExists) {
std::string name = "test" + GenRand();
::hybridse::sdk::Status status;
std::string db2 = "db" + GenRand();

std::string ddl;
ddl = "create table " + db2 + "." + name +
"("
"col1 int, col2 bigint, col3 string,"
"index(key=col3, ts=col2));";

ASSERT_TRUE(router->ExecuteDDL(db, "create database " + db2 + ";", &status));

// drop database db2 & table name
ASSERT_TRUE(router->ExecuteDDL(db, ddl, &status));
ASSERT_TRUE(router->ExecuteDDL(db, "drop table " + db2 + "." + name + ";", &status));

// drop table name when name not exist
ASSERT_FALSE(router->ExecuteDDL(db, "drop table " + db2 + "." + name + ";", &status));
ASSERT_TRUE(router->ExecuteDDL(db, "drop database " + db2 + ";", &status));

// drop database db2 when db2 not exist
ASSERT_FALSE(router->ExecuteDDL(db, "drop database " + db2 + ";", &status));

ASSERT_TRUE(router->ExecuteDDL(db, "create database " + db2 + ";", &status));

// if exists drop database db2 & table name
ASSERT_TRUE(router->ExecuteDDL(db, ddl, &status));
ASSERT_TRUE(router->ExecuteDDL(db, "drop table if exists " + db2 + "." + name + ";", &status));

// drop table name when name not exist
ASSERT_TRUE(router->ExecuteDDL(db, "drop table if exists " + db2 + "." + name + ";", &status));
ASSERT_TRUE(router->ExecuteDDL(db, "drop database if exists " + db2 + ";", &status));

// drop database db2 when db2 not exist
ASSERT_TRUE(router->ExecuteDDL(db, "drop database if exists " + db2 + ";", &status));
}

TEST_F(SQLClusterDDLTest, CreateTableWithDatabase) {
std::string name = "test" + GenRand();
::hybridse::sdk::Status status;
Expand Down