Skip to content

Commit

Permalink
#921: Fixed: [YCQL] improve error messages related to index DDL
Browse files Browse the repository at this point in the history
Summary:
Updated a few error codes and a set of error messages to rename Table/Index into Object.
Added appropriate tests.

Related doc:   <doc-link>

Test Plan:
ybd  --cxx-test ql-create-index-test
ybd  --cxx-test ql-drop-stmt-test --gtest_filter TestQLDropStmt.TestQLDropIndex

Reviewers: robert, neha, neil

Reviewed By: neil

Subscribers: neha, bogdan, bharat, kannan, eng

Differential Revision: https://phabricator.dev.yugabyte.com/D6264
  • Loading branch information
OlegLoginov committed Mar 19, 2019
1 parent e48b7da commit 509c5a2
Show file tree
Hide file tree
Showing 25 changed files with 408 additions and 242 deletions.
Expand Up @@ -105,7 +105,7 @@ public void testCQLTimesOut() throws Exception {
AssertionWrappers.fail("Not expecting a client side timeout.");
} catch (RuntimeException re) {
LOG.info("Caught execption ", re);
AssertionWrappers.assertTrue(re.getMessage().contains("Timed out"));
AssertionWrappers.assertTrue(re.getMessage().contains("passed its deadline"));
}

// destroy the cluster, without trying to clean up the tables etc.
Expand Down
2 changes: 1 addition & 1 deletion java/yb-cql/src/test/java/org/yb/cql/TestIndex.java
Expand Up @@ -669,7 +669,7 @@ private void assertInvalidUniqueIndexDML(String query, String indexName) {
fail("InvalidQueryException not thrown for " + query);
} catch (InvalidQueryException e) {
assertTrue(e.getMessage().startsWith(
String.format("Query error: Execution Error. Duplicate value disallowed by unique " +
String.format("Execution Error. Duplicate value disallowed by unique " +
"index %s", indexName)));
}
}
Expand Down
2 changes: 1 addition & 1 deletion java/yb-cql/src/test/java/org/yb/cql/TestTransaction.java
Expand Up @@ -469,7 +469,7 @@ public void testSystemTransactionsTable() throws Exception {
Integer.valueOf(3), Integer.valueOf(3), "v3");

thrown.expect(com.datastax.driver.core.exceptions.InvalidQueryException.class);
thrown.expectMessage("Table Not Found");
thrown.expectMessage("Object Not Found");
Iterator<Row> rows = session.execute("SELECT * FROM system.transactions").iterator();
}

Expand Down
6 changes: 3 additions & 3 deletions src/yb/client/client-internal.cc
Expand Up @@ -443,7 +443,7 @@ Status YBClient::Data::CreateTable(YBClient* client,
*table_id = resp.table_id();
RETURN_NOT_OK(s);
if (resp.has_error()) {
if (resp.error().code() == MasterErrorPB::TABLE_ALREADY_PRESENT && attempts > 1) {
if (resp.error().code() == MasterErrorPB::OBJECT_ALREADY_PRESENT && attempts > 1) {
// If the table already exists and the number of attempts is >
// 1, then it means we may have succeeded in creating the
// table, but client didn't receive the successful
Expand Down Expand Up @@ -570,7 +570,7 @@ Status YBClient::Data::DeleteTable(YBClient* client,
RETURN_NOT_OK(s);

if (resp.has_error()) {
if (resp.error().code() == MasterErrorPB::TABLE_NOT_FOUND && attempts > 1) {
if (resp.error().code() == MasterErrorPB::OBJECT_NOT_FOUND && attempts > 1) {
// A prior attempt to delete the table has succeeded, but
// appeared as a failure to the client due to, e.g., an I/O or
// network issue.
Expand Down Expand Up @@ -617,7 +617,7 @@ Status YBClient::Data::IsDeleteTableInProgress(YBClient* client,
// compiler complains.
RETURN_NOT_OK(s);
if (resp.has_error()) {
if (resp.error().code() == MasterErrorPB::TABLE_NOT_FOUND) {
if (resp.error().code() == MasterErrorPB::OBJECT_NOT_FOUND) {
*delete_in_progress = false;
return Status::OK();
}
Expand Down
6 changes: 3 additions & 3 deletions src/yb/client/client-test.cc
Expand Up @@ -494,7 +494,7 @@ TEST_F(ClientTest, TestBadTable) {
shared_ptr<YBTable> t;
Status s = client_->OpenTable(YBTableName(kKeyspaceName, "xxx-does-not-exist"), &t);
ASSERT_TRUE(s.IsNotFound());
ASSERT_STR_CONTAINS(s.ToString(false), "Not found: The table does not exist");
ASSERT_STR_CONTAINS(s.ToString(false), "Not found: The object does not exist");
}

// Test that, if the master is down, we experience a network error talking
Expand Down Expand Up @@ -1290,7 +1290,7 @@ TEST_F(ClientTest, TestDeleteTable) {
// Try to open the deleted table
Status s = client_table_.Open(kTableName, client_.get());
ASSERT_TRUE(s.IsNotFound());
ASSERT_STR_CONTAINS(s.ToString(), "The table does not exist");
ASSERT_STR_CONTAINS(s.ToString(), "The object does not exist");

// Create a new table with the same name. This is to ensure that the client
// doesn't cache anything inappropriately by table name (see KUDU-1055).
Expand All @@ -1312,7 +1312,7 @@ TEST_F(ClientTest, TestGetTableSchema) {
Status s = client_->GetTableSchema(YBTableName(kKeyspaceName, "MissingTableName"), &schema,
&partition_schema);
ASSERT_TRUE(s.IsNotFound());
ASSERT_STR_CONTAINS(s.ToString(), "The table does not exist");
ASSERT_STR_CONTAINS(s.ToString(), "The object does not exist");
}

TEST_F(ClientTest, TestStaleLocations) {
Expand Down
340 changes: 168 additions & 172 deletions src/yb/master/catalog_manager.cc

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/yb/master/catalog_manager.h
Expand Up @@ -1032,8 +1032,12 @@ class CatalogManager : public tserver::TabletPeerLookupIf {
// Return all the available (user-defined) types.
void GetAllUDTypes(std::vector<scoped_refptr<UDTypeInfo> >* types);

NamespaceName GetNamespaceNameUnlocked(const NamespaceId& id) const;
NamespaceName GetNamespaceName(const NamespaceId& id) const;

NamespaceName GetNamespaceNameUnlocked(const scoped_refptr<TableInfo>& table) const;
NamespaceName GetNamespaceName(const scoped_refptr<TableInfo>& table) const;

void GetAllRoles(std::vector<scoped_refptr<RoleInfo>>* roles);

// Find all the roles for which 'role' is a member of the list 'member_of'.
Expand Down
12 changes: 6 additions & 6 deletions src/yb/master/master-test.cc
Expand Up @@ -798,7 +798,7 @@ TEST_F(MasterTest, TestNamespaces) {
const Status s = CreateNamespace(other_ns_name, &resp);
ASSERT_TRUE(s.IsAlreadyPresent()) << s.ToString();
ASSERT_STR_CONTAINS(s.ToString(),
Substitute("Keyspace $0 already exists", other_ns_name));
Substitute("Keyspace '$0' already exists", other_ns_name));
}
{
ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
Expand Down Expand Up @@ -872,7 +872,7 @@ TEST_F(MasterTest, TestNamespaces) {
const Status s = CreateNamespace(default_namespace_name, &resp);
ASSERT_TRUE(s.IsAlreadyPresent()) << s.ToString();
ASSERT_STR_CONTAINS(s.ToString(),
Substitute("Keyspace $0 already exists", default_namespace_name));
Substitute("Keyspace '$0' already exists", default_namespace_name));
}
{
ASSERT_NO_FATALS(DoListAllNamespaces(&namespaces));
Expand Down Expand Up @@ -1345,10 +1345,10 @@ TEST_F(MasterTest, TestFullTableName) {
ASSERT_OK(proxy_->AlterTable(req, &resp, ResetAndGetController()));
SCOPED_TRACE(resp.DebugString());
ASSERT_TRUE(resp.has_error());
ASSERT_EQ(resp.error().code(), MasterErrorPB::TABLE_ALREADY_PRESENT);
ASSERT_EQ(resp.error().code(), MasterErrorPB::OBJECT_ALREADY_PRESENT);
ASSERT_EQ(resp.error().status().code(), AppStatusPB::ALREADY_PRESENT);
ASSERT_STR_CONTAINS(resp.error().status().ShortDebugString(),
"Table already exists");
" already exists");
}
// Check that nothing's changed (still have 3 tables).
ASSERT_NO_FATALS(DoListAllTables(&tables));
Expand Down Expand Up @@ -1380,10 +1380,10 @@ TEST_F(MasterTest, TestFullTableName) {
ASSERT_OK(proxy_->DeleteTable(req, &resp, ResetAndGetController()));
SCOPED_TRACE(resp.DebugString());
ASSERT_TRUE(resp.has_error());
ASSERT_EQ(resp.error().code(), MasterErrorPB::TABLE_NOT_FOUND);
ASSERT_EQ(resp.error().code(), MasterErrorPB::OBJECT_NOT_FOUND);
ASSERT_EQ(resp.error().status().code(), AppStatusPB::NOT_FOUND);
ASSERT_STR_CONTAINS(resp.error().status().ShortDebugString(),
"The table does not exist");
"The object does not exist");
}

// Delete the table.
Expand Down
8 changes: 4 additions & 4 deletions src/yb/master/master.proto
Expand Up @@ -57,11 +57,11 @@ message MasterErrorPB {
// The schema provided for a request was not well-formed.
INVALID_SCHEMA = 2;

// The requested table does not exist
TABLE_NOT_FOUND = 3;
// The requested table or index does not exist
OBJECT_NOT_FOUND = 3;

// The name requested for the table is already in use
TABLE_ALREADY_PRESENT = 4;
// The name requested for the table or index is already in use
OBJECT_ALREADY_PRESENT = 4;

// The number of tablets requested for a new table is over the per TS limit.
TOO_MANY_TABLETS = 5;
Expand Down
26 changes: 21 additions & 5 deletions src/yb/util/status.cc
Expand Up @@ -147,16 +147,22 @@ std::string Status::CodeAsString() const {
return cstr != nullptr ? cstr : "Incorrect status code " + std::to_string(code);
}

std::string Status::ToUserMessage(bool include_file_and_line) const {
std::string Status::ToUserMessage(bool include_code) const {
if (error_code() == 0) {
// Return empty string for success.
return "";
}
return ToString(include_file_and_line);
// Never include internal file name for the user.
return ToString(/* include_file_and_line */ false, include_code);
}

std::string Status::ToString(bool include_file_and_line) const {
std::string result(CodeAsString());
std::string Status::ToString(bool include_file_and_line, bool include_code) const {
std::string result;

if (include_code) {
result += CodeAsString();
}

if (state_ == nullptr) {
return result;
}
Expand All @@ -176,9 +182,19 @@ std::string Status::ToString(bool include_file_and_line) const {
result.append(std::to_string(state_->line_number));
result.append(")");
}
result.append(": ");

if (!result.empty()) {
result.append(": ");
}

Slice msg = message();
result.append(reinterpret_cast<const char*>(msg.data()), msg.size());

// If no message (rare case) - show code (if it's not shown yet).
if (result.empty()) {
result += CodeAsString();
}

int64_t error = error_code();
if (error != -1) {
char buf[64];
Expand Down
4 changes: 2 additions & 2 deletions src/yb/util/status.h
Expand Up @@ -193,11 +193,11 @@ class Status {

// Returns a text message of this status to be reported to users.
// Returns empty string for success.
std::string ToUserMessage(bool include_file_and_line = false) const;
std::string ToUserMessage(bool include_code = false) const;

// Return a string representation of this status suitable for printing.
// Returns the string "OK" for success.
std::string ToString(bool include_file_and_line = true) const;
std::string ToString(bool include_file_and_line = true, bool include_code = true) const;

// Return a string representation of the status code, without the message
// text or posix code information.
Expand Down
2 changes: 1 addition & 1 deletion src/yb/util/ybc-internal.cc
Expand Up @@ -45,7 +45,7 @@ YBCStatus ToYBCStatus(const Status& status) {
if (status.ok()) {
return nullptr;
}
std::string status_str = status.ToUserMessage();
std::string status_str = status.ToUserMessage(/* include_code */ true);
size_t status_msg_buf_size = status_str.size() + 1;
YBCStatus ybc_status = reinterpret_cast<YBCStatus>(
malloc(sizeof(YBCStatusStruct) + status_msg_buf_size));
Expand Down
16 changes: 8 additions & 8 deletions src/yb/yql/cql/ql/exec/executor.cc
Expand Up @@ -422,16 +422,16 @@ Status Executor::ExecPTNode(const PTCreateTable *tnode) {
if (PREDICT_FALSE(!s.ok())) {
ErrorCode error_code = ErrorCode::SERVER_ERROR;
if (s.IsAlreadyPresent()) {
error_code = ErrorCode::DUPLICATE_TABLE;
error_code = ErrorCode::DUPLICATE_OBJECT;
} else if (s.IsNotFound()) {
error_code = tnode->opcode() == TreeNodeOpcode::kPTCreateIndex
? ErrorCode::TABLE_NOT_FOUND
? ErrorCode::OBJECT_NOT_FOUND
: ErrorCode::KEYSPACE_NOT_FOUND;
} else if (s.IsInvalidArgument()) {
error_code = ErrorCode::INVALID_TABLE_DEFINITION;
}

if (tnode->create_if_not_exists() && error_code == ErrorCode::DUPLICATE_TABLE) {
if (tnode->create_if_not_exists() && error_code == ErrorCode::DUPLICATE_OBJECT) {
return Status::OK();
}

Expand Down Expand Up @@ -509,7 +509,7 @@ Status Executor::ExecPTNode(const PTDropStmt *tnode) {
// Drop the table.
const YBTableName table_name = tnode->yb_table_name();
s = ql_env_->DeleteTable(table_name);
error_not_found = ErrorCode::TABLE_NOT_FOUND;
error_not_found = ErrorCode::OBJECT_NOT_FOUND;
result_ = std::make_shared<SchemaChangeResult>(
"DROPPED", "TABLE", table_name.namespace_name(), table_name.table_name());
ql_env_->RemoveCachedTableDesc(table_name);
Expand All @@ -521,7 +521,7 @@ Status Executor::ExecPTNode(const PTDropStmt *tnode) {
const YBTableName table_name = tnode->yb_table_name();
YBTableName indexed_table_name;
s = ql_env_->DeleteIndexTable(table_name, &indexed_table_name);
error_not_found = ErrorCode::TABLE_NOT_FOUND;
error_not_found = ErrorCode::OBJECT_NOT_FOUND;
result_ = std::make_shared<SchemaChangeResult>(
"UPDATED", "TABLE", indexed_table_name.namespace_name(), indexed_table_name.table_name());
ql_env_->RemoveCachedTableDesc(indexed_table_name);
Expand Down Expand Up @@ -646,7 +646,7 @@ Status Executor::ExecPTNode(const PTSelectStmt *tnode, TnodeContext* tnode_conte
// If this is a system table but the table does not exist, it is okay. Just return OK with void
// result.
return tnode->is_system() ? Status::OK()
: exec_context_->Error(tnode, ErrorCode::TABLE_NOT_FOUND);
: exec_context_->Error(tnode, ErrorCode::OBJECT_NOT_FOUND);
}

const StatementParameters& params = exec_context_->params();
Expand All @@ -655,7 +655,7 @@ Status Executor::ExecPTNode(const PTSelectStmt *tnode, TnodeContext* tnode_conte
// for query without index, or the index id in the leaf node (where child_select is null also).
const bool continue_select = !tnode->child_select() && !params.table_id().empty();
if (continue_select && params.table_id() != table->id()) {
return exec_context_->Error(tnode, "Table no longer exists.", ErrorCode::TABLE_NOT_FOUND);
return exec_context_->Error(tnode, "Object no longer exists.", ErrorCode::OBJECT_NOT_FOUND);
}

// If there is an index to select from, execute it.
Expand Down Expand Up @@ -1898,7 +1898,7 @@ Status Executor::ProcessStatementStatus(const ParseTree& parse_tree, const Statu
errcode == ErrorCode::WRONG_METADATA_VERSION ||
errcode == ErrorCode::INVALID_TABLE_DEFINITION ||
errcode == ErrorCode::INVALID_ARGUMENTS ||
errcode == ErrorCode::TABLE_NOT_FOUND ||
errcode == ErrorCode::OBJECT_NOT_FOUND ||
errcode == ErrorCode::TYPE_NOT_FOUND) {
parse_tree.ClearAnalyzedTableCache(ql_env_);
parse_tree.ClearAnalyzedUDTypeCache(ql_env_);
Expand Down
4 changes: 2 additions & 2 deletions src/yb/yql/cql/ql/ptree/pt_dml.cc
Expand Up @@ -117,7 +117,7 @@ Status PTDmlStmt::LookupTable(SemContext *sem_context) {
if (!table_ || (table_->IsIndex() && !FLAGS_allow_index_table_read_write) ||
// Only looking for CQL tables.
(table_->table_type() != client::YBTableType::YQL_TABLE_TYPE)) {
return sem_context->Error(table_loc(), ErrorCode::TABLE_NOT_FOUND);
return sem_context->Error(table_loc(), ErrorCode::OBJECT_NOT_FOUND);
}
LoadSchema(sem_context, table_, &column_map_);
return Status::OK();
Expand Down Expand Up @@ -340,7 +340,7 @@ Status PTDmlStmt::AnalyzeIndexesForWrites(SemContext *sem_context) {
std::shared_ptr<client::YBTable> index_table = sem_context->GetTableDesc(index_id);
if (index_table == nullptr) {
return sem_context->Error(this, Substitute("Index table $0 not found", index_id).c_str(),
ErrorCode::TABLE_NOT_FOUND);
ErrorCode::OBJECT_NOT_FOUND);
}
pk_only_indexes_.insert(index_table);
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/yb/yql/cql/ql/ptree/pt_select.cc
Expand Up @@ -301,7 +301,7 @@ Status PTSelectStmt::LookupIndex(SemContext *sem_context) {
if (!table_ || !table_->IsIndex() ||
// Only looking for CQL Indexes.
(table_->table_type() != client::YBTableType::YQL_TABLE_TYPE)) {
return sem_context->Error(table_loc(), ErrorCode::TABLE_NOT_FOUND);
return sem_context->Error(table_loc(), ErrorCode::OBJECT_NOT_FOUND);
}
LoadSchema(sem_context, table_, &column_map_);
return Status::OK();
Expand Down
6 changes: 3 additions & 3 deletions src/yb/yql/cql/ql/ptree/sem_context.cc
Expand Up @@ -117,7 +117,7 @@ Status SemContext::LookupTable(const YBTableName& name,
if (*table == nullptr || ((*table)->IsIndex() && !FLAGS_allow_index_table_read_write) ||
// Only looking for CQL tables.
(*table)->table_type() != client::YBTableType::YQL_TABLE_TYPE) {
return Error(loc, ErrorCode::TABLE_NOT_FOUND);
return Error(loc, ErrorCode::OBJECT_NOT_FOUND);
}

return LoadSchema(*table, col_descs, column_definitions);
Expand All @@ -133,7 +133,7 @@ Status SemContext::LookupIndex(const TableId& index_id,
if (*index_table == nullptr || !(*index_table)->IsIndex() ||
// Only looking for CQL Indexes.
(*index_table)->table_type() != client::YBTableType::YQL_TABLE_TYPE) {
return Error(loc, ErrorCode::TABLE_NOT_FOUND);
return Error(loc, ErrorCode::OBJECT_NOT_FOUND);
}

return LoadSchema(*index_table, col_descs, column_definitions);
Expand All @@ -157,7 +157,7 @@ Status SemContext::MapSymbol(const MCString& name, PTAlterColumnDefinition *entr

Status SemContext::MapSymbol(const MCString& name, PTCreateTable *entry) {
if (symtab_[name].create_table_ != nullptr) {
return Error(entry, ErrorCode::DUPLICATE_TABLE);
return Error(entry, ErrorCode::DUPLICATE_OBJECT);
}
symtab_[name].create_table_ = entry;
return Status::OK();
Expand Down
2 changes: 1 addition & 1 deletion src/yb/yql/cql/ql/sem/analyzer.cc
Expand Up @@ -44,7 +44,7 @@ CHECKED_STATUS Analyzer::Analyze(ParseTree::UniPtr parse_tree) {
if (!ptree->reparsed()) {
const ErrorCode errcode = GetErrorCode(s);
if (errcode != ErrorCode::KEYSPACE_NOT_FOUND &&
errcode != ErrorCode::TABLE_NOT_FOUND &&
errcode != ErrorCode::OBJECT_NOT_FOUND &&
errcode != ErrorCode::TYPE_NOT_FOUND &&
sem_context_->cache_used()) {
ptree->ClearAnalyzedTableCache(ql_env_);
Expand Down
1 change: 1 addition & 0 deletions src/yb/yql/cql/ql/test/CMakeLists.txt
Expand Up @@ -22,6 +22,7 @@ add_dependencies(ql_test ql_api)
set(YB_TEST_LINK_LIBS ql_test ${YB_MIN_TEST_LIBS})
ADD_YB_TEST(ql-parser-test)
ADD_YB_TEST(ql-create-table-test)
ADD_YB_TEST(ql-create-index-test)
ADD_YB_TEST(ql-drop-stmt-test)
ADD_YB_TEST(ql-query-test)
ADD_YB_TEST(ql-insert-table-test)
Expand Down

0 comments on commit 509c5a2

Please sign in to comment.