dbms: better exception messages [#METR-8224].

This commit is contained in:
Alexey Milovidov 2013-10-26 03:20:51 +00:00
parent fa7a666a96
commit a38317e1f5
19 changed files with 87 additions and 65 deletions

View File

@ -54,12 +54,12 @@ public:
res->forceConnected(); res->forceConnected();
return res; return res;
} }
catch (const DB::Exception & e) catch (const Exception & e)
{ {
if (e.code() != ErrorCodes::NETWORK_ERROR && e.code() != ErrorCodes::SOCKET_TIMEOUT) if (e.code() != ErrorCodes::NETWORK_ERROR && e.code() != ErrorCodes::SOCKET_TIMEOUT)
throw; throw;
fail_message << "DB::Exception. Code: " << e.code() << ", e.displayText() = " << e.displayText() << ", e.what() = " << e.what(); fail_message << "Code: " << e.code() << ", e.displayText() = " << e.displayText() << ", e.what() = " << e.what();
} }
LOG_WARNING(log, "Connection failed at try №" LOG_WARNING(log, "Connection failed at try №"
@ -71,7 +71,7 @@ public:
} }
} }
throw DB::Exception("All connection tries failed. Log: \n\n" + fail_messages.str() + "\n", throw Exception("All connection tries failed. Log: \n\n" + fail_messages.str() + "\n",
ErrorCodes::ALL_CONNECTION_TRIES_FAILED); ErrorCodes::ALL_CONNECTION_TRIES_FAILED);
} }

View File

@ -28,6 +28,9 @@ public:
Exception * clone() const; Exception * clone() const;
void rethrow() const; void rethrow() const;
/// Дописать к существующему сообщению что-нибудь ещё.
void addMessage(const std::string & arg);
const StackTrace & getStackTrace() const { return trace; } const StackTrace & getStackTrace() const { return trace; }
private: private:

View File

@ -126,7 +126,7 @@ public:
{ {
impl->next(); impl->next();
} }
catch (const DB::Exception & e) catch (const Exception & e)
{ {
if (e.code() == ErrorCodes::CANNOT_WRITE_TO_OSTREAM) if (e.code() == ErrorCodes::CANNOT_WRITE_TO_OSTREAM)
checkStatus(); /// Меняем сообщение об ошибке на более ясное. checkStatus(); /// Меняем сообщение об ошибке на более ясное.

View File

@ -213,7 +213,7 @@ private:
{ {
return mainImpl(args); return mainImpl(args);
} }
catch (const DB::Exception & e) catch (const Exception & e)
{ {
std::string text = e.displayText(); std::string text = e.displayText();
@ -399,7 +399,7 @@ private:
if (!process(query)) if (!process(query))
break; break;
} }
catch (const DB::Exception & e) catch (const Exception & e)
{ {
std::cerr << std::endl std::cerr << std::endl
<< "Exception on client:" << std::endl << "Exception on client:" << std::endl

View File

@ -268,47 +268,58 @@ bool Connection::poll(size_t timeout_microseconds)
Connection::Packet Connection::receivePacket() Connection::Packet Connection::receivePacket()
{ {
//LOG_TRACE(log, "Receiving packet (" << getServerAddress() << ")"); //LOG_TRACE(log, "Receiving packet (" << getServerAddress() << ")");
Packet res;
readVarUInt(res.type, *in);
switch (res.type) try
{ {
case Protocol::Server::Data: Packet res;
res.block = receiveData(); readVarUInt(res.type, *in);
return res;
case Protocol::Server::Exception: switch (res.type)
res.exception = receiveException(); {
return res; case Protocol::Server::Data:
res.block = receiveData();
return res;
case Protocol::Server::Progress: case Protocol::Server::Exception:
res.progress = receiveProgress(); res.exception = receiveException();
return res; return res;
case Protocol::Server::ProfileInfo:
res.profile_info = receiveProfileInfo();
return res;
case Protocol::Server::Totals: case Protocol::Server::Progress:
/// Блок с тотальными значениями передаётся так же, как обычный блок данных. Разница только в идентификаторе пакета. res.progress = receiveProgress();
res.block = receiveData(); return res;
return res;
case Protocol::Server::Extremes: case Protocol::Server::ProfileInfo:
/// Аналогично. res.profile_info = receiveProfileInfo();
res.block = receiveData(); return res;
return res;
case Protocol::Server::EndOfStream: case Protocol::Server::Totals:
return res; /// Блок с тотальными значениями передаётся так же, как обычный блок данных. Разница только в идентификаторе пакета.
res.block = receiveData();
return res;
default: case Protocol::Server::Extremes:
/// Закроем соединение, чтобы не было рассинхронизации. /// Аналогично.
disconnect(); res.block = receiveData();
throw Exception("Unknown packet " return res;
+ toString(res.type)
+ " from server " + getServerAddress(), ErrorCodes::UNKNOWN_PACKET_FROM_SERVER); case Protocol::Server::EndOfStream:
return res;
default:
/// Закроем соединение, чтобы не было рассинхронизации.
disconnect();
throw Exception("Unknown packet "
+ toString(res.type)
+ " from server " + getServerAddress(), ErrorCodes::UNKNOWN_PACKET_FROM_SERVER);
}
}
catch (Exception & e)
{
/// Дописываем в текст исключения адрес сервера, если надо.
if (e.code() != ErrorCodes::UNKNOWN_PACKET_FROM_SERVER)
e.addMessage("while receiving packet from " + getServerAddress());
throw;
} }
} }

View File

@ -44,6 +44,11 @@ void Exception::rethrow() const
throw *this; throw *this;
} }
void Exception::addMessage(const std::string & arg)
{
extendedMessage(arg);
}
void throwFromErrno(const std::string & s, int code, int e) void throwFromErrno(const std::string & s, int code, int e)
{ {

View File

@ -48,9 +48,10 @@ Block BlockInputStreamFromRowInputStream::readImpl()
res.getByPosition(i).column->insert(row[i]); res.getByPosition(i).column->insert(row[i]);
} }
} }
catch (const DB::Exception & e) catch (Exception & e)
{ {
throw DB::Exception(e.message() + " (at row " + toString(total_rows + 1) + ")", e, e.code()); e.addMessage("(at row " + toString(total_rows + 1) + ")");
throw;
} }
res.optimizeNestedArraysOffsets(); res.optimizeNestedArraysOffsets();

View File

@ -125,7 +125,7 @@ void readEscapedString(DB::String & s, DB::ReadBuffer & buf)
{ {
++buf.position(); ++buf.position();
if (buf.eof()) if (buf.eof())
throw DB::Exception("Cannot parse escape sequence", DB::ErrorCodes::CANNOT_PARSE_ESCAPE_SEQUENCE); throw Exception("Cannot parse escape sequence", DB::ErrorCodes::CANNOT_PARSE_ESCAPE_SEQUENCE);
s += DB::parseEscapeSequence(*buf.position()); s += DB::parseEscapeSequence(*buf.position());
++buf.position(); ++buf.position();
} }

View File

@ -264,7 +264,7 @@ ASTPtr Context::getCreateQuery(const String & database_name, const String & tabl
/// Распарсенный запрос должен заканчиваться на конец входных данных или на точку с запятой. /// Распарсенный запрос должен заканчиваться на конец входных данных или на точку с запятой.
if (!parse_res || (pos != end && *pos != ';')) if (!parse_res || (pos != end && *pos != ';'))
throw DB::Exception("Syntax error while parsing query from file " + metadata_path + ": failed at position " throw Exception("Syntax error while parsing query from file " + metadata_path + ": failed at position "
+ toString(pos - begin) + ": " + toString(pos - begin) + ": "
+ std::string(pos, std::min(SHOW_CHARS_ON_SYNTAX_ERROR, end - pos)) + std::string(pos, std::min(SHOW_CHARS_ON_SYNTAX_ERROR, end - pos))
+ ", expected " + (parse_res ? "end of query" : expected) + ".", + ", expected " + (parse_res ? "end of query" : expected) + ".",

View File

@ -69,7 +69,7 @@ void InterpreterAlterQuery::execute()
/// Проверяем, что колонка еще не существует /// Проверяем, что колонка еще не существует
if (std::find_if(columns_copy.begin(), columns_copy.end(), boost::bind(namesEqual, name_type.name, _1)) != columns_copy.end()) if (std::find_if(columns_copy.begin(), columns_copy.end(), boost::bind(namesEqual, name_type.name, _1)) != columns_copy.end())
throw DB::Exception("Wrong column name. Column already exists", DB::ErrorCodes::ILLEGAL_COLUMN); throw Exception("Wrong column name. Column already exists", DB::ErrorCodes::ILLEGAL_COLUMN);
/// Проверяем опциональный аргумент AFTER /// Проверяем опциональный аргумент AFTER
ASTs::iterator insert_it = columns_copy.end(); ASTs::iterator insert_it = columns_copy.end();
@ -78,7 +78,7 @@ void InterpreterAlterQuery::execute()
const ASTIdentifier & col_after = dynamic_cast<const ASTIdentifier &>(*params.column); const ASTIdentifier & col_after = dynamic_cast<const ASTIdentifier &>(*params.column);
insert_it = std::find_if(columns_copy.begin(), columns_copy.end(), boost::bind(namesEqual, col_after.name, _1)) ; insert_it = std::find_if(columns_copy.begin(), columns_copy.end(), boost::bind(namesEqual, col_after.name, _1)) ;
if (insert_it == columns_copy.end()) if (insert_it == columns_copy.end())
throw DB::Exception("Wrong column name. Cannot find column to insert after", DB::ErrorCodes::ILLEGAL_COLUMN); throw Exception("Wrong column name. Cannot find column to insert after", DB::ErrorCodes::ILLEGAL_COLUMN);
} }
columns_copy.insert(insert_it, params.name_type); columns_copy.insert(insert_it, params.name_type);
} }
@ -88,11 +88,11 @@ void InterpreterAlterQuery::execute()
/// Проверяем, что поле не является ключевым /// Проверяем, что поле не является ключевым
if (identifier_names.find(drop_column.name) != identifier_names.end()) if (identifier_names.find(drop_column.name) != identifier_names.end())
throw DB::Exception("Cannot drop key column", DB::ErrorCodes::ILLEGAL_COLUMN); throw Exception("Cannot drop key column", DB::ErrorCodes::ILLEGAL_COLUMN);
ASTs::iterator drop_it = std::find_if(columns_copy.begin(), columns_copy.end(), boost::bind(namesEqual, drop_column.name, _1)); ASTs::iterator drop_it = std::find_if(columns_copy.begin(), columns_copy.end(), boost::bind(namesEqual, drop_column.name, _1));
if (drop_it == columns_copy.end()) if (drop_it == columns_copy.end())
throw DB::Exception("Wrong column name. Cannot find column to drop", DB::ErrorCodes::ILLEGAL_COLUMN); throw Exception("Wrong column name. Cannot find column to drop", DB::ErrorCodes::ILLEGAL_COLUMN);
else else
columns_copy.erase(drop_it); columns_copy.erase(drop_it);
} }

View File

@ -471,6 +471,8 @@ void InterpreterSelectQuery::executeAggregation(BlockInputStreams & streams, Exp
AggregateDescriptions aggregates; AggregateDescriptions aggregates;
query_analyzer->getAggregateInfo(key_names, aggregates); query_analyzer->getAggregateInfo(key_names, aggregates);
/// TODO: Оптимизация для случая, когда есть LIMIT, но нет HAVING и ORDER BY.
bool separate_totals = to_stage > QueryProcessingStage::WithMergeableState; bool separate_totals = to_stage > QueryProcessingStage::WithMergeableState;
/// Если источников несколько, то выполняем параллельную агрегацию /// Если источников несколько, то выполняем параллельную агрегацию

View File

@ -33,7 +33,7 @@ static void executeCreateQuery(const String & query, Context & context, const St
/// Распарсенный запрос должен заканчиваться на конец входных данных или на точку с запятой. /// Распарсенный запрос должен заканчиваться на конец входных данных или на точку с запятой.
if (!parse_res || (pos != end && *pos != ';')) if (!parse_res || (pos != end && *pos != ';'))
throw DB::Exception("Syntax error while executing query from file " + file_name + ": failed at position " throw Exception("Syntax error while executing query from file " + file_name + ": failed at position "
+ toString(pos - begin) + ": " + toString(pos - begin) + ": "
+ std::string(pos, std::min(SHOW_CHARS_ON_SYNTAX_ERROR, end - pos)) + std::string(pos, std::min(SHOW_CHARS_ON_SYNTAX_ERROR, end - pos))
+ ", expected " + (parse_res ? "end of query" : expected) + ".", + ", expected " + (parse_res ? "end of query" : expected) + ".",
@ -131,7 +131,7 @@ void loadMetadata(Context & context)
{ {
executeCreateQuery(s, context, it.name(), tables[j]); executeCreateQuery(s, context, it.name(), tables[j]);
} }
catch (const DB::Exception & e) catch (const Exception & e)
{ {
throw Exception("Cannot create table from metadata file " + tables[j] + ", error: " + e.displayText(), throw Exception("Cannot create table from metadata file " + tables[j] + ", error: " + e.displayText(),
ErrorCodes::CANNOT_CREATE_TABLE_FROM_METADATA); ErrorCodes::CANNOT_CREATE_TABLE_FROM_METADATA);

View File

@ -68,7 +68,7 @@ void formatAST(const IAST & ast, std::ostream & s, size_t indent, bool hilite, b
DISPATCH(AlterQuery) DISPATCH(AlterQuery)
DISPATCH(ShowProcesslistQuery) DISPATCH(ShowProcesslistQuery)
else else
throw DB::Exception("Unknown element in AST: " + ast.getID() + " '" + std::string(ast.range.first, ast.range.second - ast.range.first) + "'", throw Exception("Unknown element in AST: " + ast.getID() + " '" + std::string(ast.range.first, ast.range.second - ast.range.first) + "'",
ErrorCodes::UNKNOWN_ELEMENT_IN_AST); ErrorCodes::UNKNOWN_ELEMENT_IN_AST);
#undef DISPATCH #undef DISPATCH

View File

@ -167,7 +167,7 @@ void HTTPHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Ne
processQuery(request, response); processQuery(request, response);
LOG_INFO(log, "Done processing query"); LOG_INFO(log, "Done processing query");
} }
catch (DB::Exception & e) catch (Exception & e)
{ {
response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
std::stringstream s; std::stringstream s;

View File

@ -103,7 +103,7 @@ namespace DB
processQuery(request, response); processQuery(request, response);
LOG_INFO(log, "Done processing query"); LOG_INFO(log, "Done processing query");
} }
catch (DB::Exception & e) catch (Exception & e)
{ {
response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
std::stringstream s; std::stringstream s;

View File

@ -43,7 +43,7 @@ void TCPHandler::runImpl()
{ {
receiveHello(); receiveHello();
} }
catch (const DB::Exception & e) /// Типично при неправильном имени пользователя, пароле, адресе. catch (const Exception & e) /// Типично при неправильном имени пользователя, пароле, адресе.
{ {
try try
{ {
@ -61,7 +61,7 @@ void TCPHandler::runImpl()
if (!connection_context.isDatabaseExist(default_database)) if (!connection_context.isDatabaseExist(default_database))
{ {
Exception e("Database " + default_database + " doesn't exist", ErrorCodes::UNKNOWN_DATABASE); Exception e("Database " + default_database + " doesn't exist", ErrorCodes::UNKNOWN_DATABASE);
LOG_ERROR(log, "DB::Exception. Code: " << e.code() << ", e.displayText() = " << e.displayText() LOG_ERROR(log, "Code: " << e.code() << ", e.displayText() = " << e.displayText()
<< ", Stack trace:\n\n" << e.getStackTrace().toString()); << ", Stack trace:\n\n" << e.getStackTrace().toString());
sendException(e); sendException(e);
return; return;
@ -90,7 +90,7 @@ void TCPHandler::runImpl()
/** Исключение во время выполнения запроса (его надо отдать по сети клиенту). /** Исключение во время выполнения запроса (его надо отдать по сети клиенту).
* Клиент сможет его принять, если оно не произошло во время отправки другого пакета и клиент ещё не разорвал соединение. * Клиент сможет его принять, если оно не произошло во время отправки другого пакета и клиент ещё не разорвал соединение.
*/ */
SharedPtr<DB::Exception> exception; SharedPtr<Exception> exception;
try try
{ {
@ -118,9 +118,9 @@ void TCPHandler::runImpl()
state.reset(); state.reset();
} }
catch (const DB::Exception & e) catch (const Exception & e)
{ {
LOG_ERROR(log, "DB::Exception. Code: " << e.code() << ", e.displayText() = " << e.displayText() << ", e.what() = " << e.what() LOG_ERROR(log, "Code: " << e.code() << ", e.displayText() = " << e.displayText() << ", e.what() = " << e.what()
<< ", Stack trace:\n\n" << e.getStackTrace().toString()); << ", Stack trace:\n\n" << e.getStackTrace().toString());
exception = e.clone(); exception = e.clone();
@ -621,9 +621,9 @@ void TCPHandler::run()
LOG_INFO(log, "Done processing connection."); LOG_INFO(log, "Done processing connection.");
} }
catch (DB::Exception & e) catch (Exception & e)
{ {
LOG_ERROR(log, "DB::Exception. Code: " << e.code() << ", e.displayText() = " << e.displayText() LOG_ERROR(log, "Code: " << e.code() << ", e.displayText() = " << e.displayText()
<< ", Stack trace:\n\n" << e.getStackTrace().toString()); << ", Stack trace:\n\n" << e.getStackTrace().toString());
} }
catch (Poco::Exception & e) catch (Poco::Exception & e)

View File

@ -168,7 +168,7 @@ void IStorage::alter_columns(const ASTAlterQuery::Parameters & params, NamesAndT
NamesAndTypesList::reverse_iterator reverse_insert_it = std::find_if(columns->rbegin(), columns->rend(), boost::bind(namesEqual, column_name, _1) ); NamesAndTypesList::reverse_iterator reverse_insert_it = std::find_if(columns->rbegin(), columns->rend(), boost::bind(namesEqual, column_name, _1) );
if (reverse_insert_it == columns->rend()) if (reverse_insert_it == columns->rend())
throw DB::Exception("Wrong column name. Cannot find column to insert after", DB::ErrorCodes::ILLEGAL_COLUMN); throw Exception("Wrong column name. Cannot find column to insert after", DB::ErrorCodes::ILLEGAL_COLUMN);
else else
{ {
/// base возвращает итератор уже смещенный на один элемент вправо /// base возвращает итератор уже смещенный на один элемент вправо
@ -206,7 +206,7 @@ void IStorage::alter_columns(const ASTAlterQuery::Parameters & params, NamesAndT
if (column_it == columns->end()) if (column_it == columns->end())
{ {
if (is_first) if (is_first)
throw DB::Exception("Wrong column name. Cannot find column to drop", DB::ErrorCodes::ILLEGAL_COLUMN); throw Exception("Wrong column name. Cannot find column to drop", DB::ErrorCodes::ILLEGAL_COLUMN);
} }
else else
columns->erase(column_it); columns->erase(column_it);

View File

@ -172,9 +172,9 @@ void StorageChunkMerger::mergeThread()
merged = maybeMergeSomething(); merged = maybeMergeSomething();
error = false; error = false;
} }
catch (const DB::Exception & e) catch (const Exception & e)
{ {
LOG_ERROR(log, "StorageChunkMerger at " << this_database << "." << name << " failed to merge: DB::Exception. Code: " << e.code() << ", e.displayText() = " << e.displayText() << ", e.what() = " << e.what() LOG_ERROR(log, "StorageChunkMerger at " << this_database << "." << name << " failed to merge: Code: " << e.code() << ", e.displayText() = " << e.displayText() << ", e.what() = " << e.what()
<< ", Stack trace:\n\n" << e.getStackTrace().toString()); << ", Stack trace:\n\n" << e.getStackTrace().toString());
} }
catch (const Poco::Exception & e) catch (const Poco::Exception & e)
@ -351,7 +351,7 @@ bool StorageChunkMerger::mergeChunks(const Storages & chunks)
/// Распарсенный запрос должен заканчиваться на конец входных данных. /// Распарсенный запрос должен заканчиваться на конец входных данных.
if (!parse_res || pos != end) if (!parse_res || pos != end)
throw DB::Exception("Syntax error while parsing create query made by ChunkMerger." throw Exception("Syntax error while parsing create query made by ChunkMerger."
" The query is \"" + create_query + "\"." " The query is \"" + create_query + "\"."
+ " Failed at position " + toString(pos - begin) + ": " + " Failed at position " + toString(pos - begin) + ": "
+ std::string(pos, std::min(SHOW_CHARS_ON_SYNTAX_ERROR, end - pos)) + std::string(pos, std::min(SHOW_CHARS_ON_SYNTAX_ERROR, end - pos))

View File

@ -49,7 +49,7 @@ void StorageChunkRef::dropImpl()
{ {
getSource().removeReference(); getSource().removeReference();
} }
catch (const DB::Exception & e) catch (const Exception & e)
{ {
if (e.code() != ErrorCodes::UNKNOWN_TABLE) if (e.code() != ErrorCodes::UNKNOWN_TABLE)
throw; throw;