Skip to content

Commit

Permalink
Merge pull request #108 from project-tsurugi/wip/i_975
Browse files Browse the repository at this point in the history
add tsurugi-error handling functionality
  • Loading branch information
t-horikawa authored Sep 24, 2024
2 parents 4aeb58c + e7ac58c commit 68e9d07
Show file tree
Hide file tree
Showing 11 changed files with 929 additions and 159 deletions.
7 changes: 7 additions & 0 deletions include/ogawayama/stub/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,13 @@ class Connection : public manager::message::Receiver {
*/
[[nodiscard]] manager::message::Status receive_drop_index(manager::metadata::ObjectIdType object_id) const override;

/**
* @brief get the error of the last SQL executed
* @param code returns the error code reported by the tsurugidb
* @return error code defined in error_code.h
*/
ErrorCode tsurugi_error(tsurugi_error_code& code);

private:
std::unique_ptr<Impl> impl_;

Expand Down
27 changes: 26 additions & 1 deletion include/ogawayama/stub/error_code.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2023 Project Tsurugi.
* Copyright 2019-2024 Project Tsurugi.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,6 +15,9 @@
*/
#pragma once

#include <cstdint>
#include <string>

namespace ogawayama::stub {

/**
Expand Down Expand Up @@ -87,6 +90,10 @@ enum class ErrorCode {
*/
TRANSACTION_ALREADY_STARTED,

/**
* @brief Encountered server error, where you can obtain error detail with Connection::tsurugi_error() API.
*/
SERVER_ERROR,
};

constexpr std::string_view error_name(ErrorCode code) {
Expand All @@ -107,4 +114,22 @@ constexpr std::string_view error_name(ErrorCode code) {
}
}

struct tsurugi_error_code {
public:
enum class tsurugi_error_type : std::int32_t {
none = 0,
framework_error = 1,
sql_error = 2
};
// SQL or framework error
tsurugi_error_type type{}; //NOLINT(misc-non-private-member-variables-in-classes)
// see SqlServiceCode.java for SQL error
std::uint32_t code{}; //NOLINT(misc-non-private-member-variables-in-classes)
std::string name{}; //NOLINT(misc-non-private-member-variables-in-classes)
std::string detail{}; //NOLINT(misc-non-private-member-variables-in-classes)
std::string supplemental_text{}; //NOLINT(misc-non-private-member-variables-in-classes)

tsurugi_error_code() = default;
};

} // namespace ogawayama::stub
19 changes: 1 addition & 18 deletions src/jogasaki/proto/sql/response.proto
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,6 @@ message Explain {
// request is successfully completed.
Success success = 11;

// deprecated: The result output string of the explain.
string output = 1;

Error error = 2;
}
}
Expand Down Expand Up @@ -144,20 +141,6 @@ message DescribeTable {
}
}

// execute a statement with 2-D parameter table.
message Batch {
reserved 1 to 10;

// the response body.
oneof result {
// request is successfully completed.
Success success = 11;

// engine error was occurred.
Error error = 12;
}
}

message Identifier {
// the label.
string label = 1;
Expand Down Expand Up @@ -295,7 +278,7 @@ message Response {
ExecuteQuery execute_query = 4;
Explain explain = 5;
DescribeTable describe_table = 6;
Batch batch = 7;
// 7 is no longer used.
ListTables list_tables = 8;
GetSearchPath get_search_path = 9;
GetErrorInfo get_error_info = 10;
Expand Down
138 changes: 107 additions & 31 deletions src/ogawayama/stub/connection.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2023 Project Tsurugi.
* Copyright 2019-2024 Project Tsurugi.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -29,6 +29,7 @@

#include <ogawayama/common/bridge.h>
#include "prepared_statementImpl.h"
#include "ogawayama/transport/tsurugi_error.h"
#include "connectionImpl.h"

namespace ogawayama::stub {
Expand Down Expand Up @@ -76,17 +77,22 @@ ErrorCode Connection::Impl::hello()
*/
ErrorCode Connection::Impl::begin(TransactionPtr& transaction)
{
::jogasaki::proto::sql::request::Begin request{};
auto response_opt = transport_.send(request);
if (!response_opt) {
return ErrorCode::SERVER_FAILURE;
}
auto response_begin = response_opt.value();
if (response_begin.has_success()) {
transaction = std::make_unique<Transaction>(std::make_unique<Transaction::Impl>(this, transport_, response_begin.success().transaction_handle()));
return ErrorCode::OK;
try {
::jogasaki::proto::sql::request::Begin request{};

auto response_opt = transport_.send(request);
if (!response_opt) {
return ErrorCode::SERVER_FAILURE;
}
auto response_begin = response_opt.value();
if (response_begin.has_success()) {
transaction = std::make_unique<Transaction>(std::make_unique<Transaction::Impl>(this, transport_, response_begin.success().transaction_handle()));
return ErrorCode::OK;
}
return ErrorCode::SERVER_ERROR;
} catch (std::runtime_error &e) {
return ErrorCode::SERVER_ERROR;
}
return ErrorCode::SERVER_FAILURE;
}

/**
Expand Down Expand Up @@ -143,16 +149,20 @@ ErrorCode Connection::Impl::begin(const boost::property_tree::ptree& option, Tra
}
}

auto response_opt = transport_.send(request);
if (!response_opt) {
try {
auto response_opt = transport_.send(request);
if (!response_opt) {
return ErrorCode::SERVER_FAILURE;
}
auto response_begin = response_opt.value();
if (response_begin.has_success()) {
transaction = std::make_unique<Transaction>(std::make_unique<Transaction::Impl>(this, transport_, response_begin.success().transaction_handle()));
return ErrorCode::OK;
}
return ErrorCode::SERVER_FAILURE;
} catch (std::runtime_error &e) {
return ErrorCode::SERVER_ERROR;
}
auto response_begin = response_opt.value();
if (response_begin.has_success()) {
transaction = std::make_unique<Transaction>(std::make_unique<Transaction::Impl>(this, transport_, response_begin.success().transaction_handle()));
return ErrorCode::OK;
}
return ErrorCode::SERVER_FAILURE;
}

/**
Expand Down Expand Up @@ -207,19 +217,23 @@ ErrorCode Connection::Impl::prepare(std::string_view sql, const placeholders_typ
}
}

auto response_opt = transport_.send(request);
if (!response_opt) {
return ErrorCode::SERVER_FAILURE;
}
auto response_prepare = response_opt.value();
if (response_prepare.has_prepared_statement_handle()) {
auto& psh = response_prepare.prepared_statement_handle();
std::size_t id = psh.handle();
bool has_result_records = psh.has_result_records();
prepared = std::make_unique<PreparedStatement>(std::make_unique<PreparedStatement::Impl>(this, id, has_result_records));
return ErrorCode::OK;
try {
auto response_opt = transport_.send(request);
if (!response_opt) {
return ErrorCode::SERVER_FAILURE;
}
auto response_prepare = response_opt.value();
if (response_prepare.has_prepared_statement_handle()) {
auto& psh = response_prepare.prepared_statement_handle();
std::size_t id = psh.handle();
bool has_result_records = psh.has_result_records();
prepared = std::make_unique<PreparedStatement>(std::make_unique<PreparedStatement::Impl>(this, id, has_result_records));
return ErrorCode::OK;
}
return ErrorCode::SERVER_ERROR;
} catch (std::runtime_error &e) {
return ErrorCode::SERVER_ERROR;
}
return ErrorCode::SERVER_FAILURE;
}

static inline
Expand Down Expand Up @@ -448,6 +462,60 @@ ErrorCode Connection::Impl::end_ddl()
return ERROR_CODE::SERVER_FAILURE; // service returns std::nullopt
}

static inline bool handle_sql_error(ogawayama::stub::tsurugi_error_code& code, ::jogasaki::proto::sql::response::Error& sql_error) {
if (auto itr = ogawayama::transport::error_map.find(sql_error.code()); itr != ogawayama::transport::error_map.end()) {
code.type = tsurugi_error_code::tsurugi_error_type::sql_error;
code.code = itr->second.second;
code.name = itr->second.first;
code.detail = sql_error.detail();
code.supplemental_text = sql_error.supplemental_text();
return true;
}
return false;
}

static inline bool handle_framework_error(ogawayama::stub::tsurugi_error_code& code, ::tateyama::proto::diagnostics::Record& framework_error) {
if (auto itr = ogawayama::transport::framework_error_map.find(framework_error.code()); itr != ogawayama::transport::framework_error_map.end()) {
code.type = tsurugi_error_code::tsurugi_error_type::framework_error;
code.code = itr->second.second;
code.name = itr->second.first;
code.detail = framework_error.message();
return true;
}
return false;
}

/**
* @brief get the error of the last SQL executed
*/
ErrorCode Connection::Impl::tsurugi_error(tsurugi_error_code& code)
{
switch(transport_.last_header().payload_type()) {
case ::tateyama::proto::framework::response::Header_PayloadType::Header_PayloadType_UNKNOWN:
break;
case ::tateyama::proto::framework::response::Header_PayloadType::Header_PayloadType_SERVER_DIAGNOSTICS:
{
auto frame_error = transport_.last_framework_error();
if (handle_framework_error(code, frame_error)) {
return ErrorCode::OK;
}
break;
}
case ::tateyama::proto::framework::response::Header_PayloadType::Header_PayloadType_SERVICE_RESULT:
{
auto sql_error = transport_.last_sql_error();
if (sql_error.code() == ::jogasaki::proto::sql::error::Code::CODE_UNSPECIFIED) {
code.type = tsurugi_error_code::tsurugi_error_type::none;
return ErrorCode::OK;
}
if (handle_sql_error(code, sql_error)) {
return ErrorCode::OK;
}
break;
}
}
return ErrorCode::UNKNOWN;
}

/**
* @brief constructor of Connection class
Expand Down Expand Up @@ -528,4 +596,12 @@ manager::message::Status Connection::receive_drop_index(const manager::metadata:
return {reply == ErrorCode::OK ? manager::message::ErrorCode::SUCCESS : manager::message::ErrorCode::FAILURE, static_cast<int>(reply)};
}

/**
* @brief get the error of the last SQL executed
*/
ErrorCode Connection::tsurugi_error(tsurugi_error_code& code)
{
return impl_->tsurugi_error(code);
}

} // namespace ogawayama::stub
9 changes: 8 additions & 1 deletion src/ogawayama/stub/connectionImpl.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2023 Project Tsurugi.
* Copyright 2019-2024 Project Tsurugi.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -99,6 +99,13 @@ class Connection::Impl
*/
ErrorCode end_ddl();

/**
* @brief get the error of the last SQL executed
* @param code returns the error code reported by the tsurugidb
* @return error code defined in error_code.h
*/
ErrorCode tsurugi_error(tsurugi_error_code& code);

private:
Stub::Impl* manager_;
std::string session_id_;
Expand Down
Loading

0 comments on commit 68e9d07

Please sign in to comment.