diff --git a/clickhouse/base/compressed.cpp b/clickhouse/base/compressed.cpp index f1c3a569..baf0ffed 100644 --- a/clickhouse/base/compressed.cpp +++ b/clickhouse/base/compressed.cpp @@ -1,6 +1,7 @@ #include "compressed.h" #include "wire_format.h" #include "output.h" +#include "../exceptions.h" #include #include @@ -30,7 +31,7 @@ CompressedInput::~CompressedInput() { #else if (!std::uncaught_exceptions()) { #endif - throw std::runtime_error("some data was not read"); + throw LZ4Error("some data was not read"); } } } @@ -59,7 +60,7 @@ bool CompressedInput::Decompress() { } if (method != COMPRESSION_METHOD) { - throw std::runtime_error("unsupported compression method " + std::to_string(int(method))); + throw LZ4Error("unsupported compression method " + std::to_string(int(method))); } else { if (!WireFormat::ReadFixed(*input_, &compressed)) { return false; @@ -69,7 +70,7 @@ bool CompressedInput::Decompress() { } if (compressed > DBMS_MAX_COMPRESSED_SIZE) { - throw std::runtime_error("compressed data too big"); + throw LZ4Error("compressed data too big"); } Buffer tmp(compressed); @@ -87,14 +88,14 @@ bool CompressedInput::Decompress() { return false; } else { if (hash != CityHash128((const char*)tmp.data(), compressed)) { - throw std::runtime_error("data was corrupted"); + throw LZ4Error("data was corrupted"); } } data_ = Buffer(original); if (LZ4_decompress_safe((const char*)tmp.data() + HEADER_SIZE, (char*)data_.data(), compressed - HEADER_SIZE, original) < 0) { - throw std::runtime_error("can't decompress data"); + throw LZ4Error("can't decompress data"); } else { mem_.Reset(data_.data(), original); } @@ -143,7 +144,7 @@ void CompressedOutput::Compress(const void * data, size_t len) { len, static_cast(compressed_buffer_.size() - HEADER_SIZE)); if (compressed_size <= 0) - throw std::runtime_error("Failed to compress chunk of " + std::to_string(len) + " bytes, " + throw LZ4Error("Failed to compress chunk of " + std::to_string(len) + " bytes, " "LZ4 error: " + std::to_string(compressed_size)); { @@ -165,7 +166,7 @@ void CompressedOutput::Compress(const void * data, size_t len) { void CompressedOutput::PreallocateCompressBuffer(size_t input_size) { const auto estimated_compressed_buffer_size = LZ4_compressBound(static_cast(input_size)); if (estimated_compressed_buffer_size <= 0) - throw std::runtime_error("Failed to estimate compressed buffer size, LZ4 error: " + std::to_string(estimated_compressed_buffer_size)); + throw LZ4Error("Failed to estimate compressed buffer size, LZ4 error: " + std::to_string(estimated_compressed_buffer_size)); compressed_buffer_.resize(estimated_compressed_buffer_size + HEADER_SIZE + EXTRA_COMPRESS_BUFFER_SIZE); } diff --git a/clickhouse/base/sslsocket.cpp b/clickhouse/base/sslsocket.cpp index 2b9a6cac..392c22fd 100644 --- a/clickhouse/base/sslsocket.cpp +++ b/clickhouse/base/sslsocket.cpp @@ -1,5 +1,6 @@ #include "sslsocket.h" #include "../client.h" +#include "../exceptions.h" #include @@ -45,7 +46,7 @@ void throwSSLError(SSL * ssl, int error, const char * /*location*/, const char * // << "\n\t last err: " << ERR_peek_last_error() // << std::endl; - throw std::runtime_error(prefix + std::to_string(error) + " : " + reason_str); + throw clickhouse::OpenSSLError(prefix + std::to_string(error) + " : " + reason_str); } void configureSSL(const clickhouse::SSLParams::ConfigurationType & configuration, SSL * ssl, SSL_CTX * context = nullptr) { @@ -75,13 +76,13 @@ void configureSSL(const clickhouse::SSLParams::ConfigurationType & configuration else if (err == 0) throwSSLError(ssl, SSL_ERROR_NONE, nullptr, nullptr, "Failed to configure OpenSSL with command '" + kv.first + "' "); else if (err == 1 && value_present) - throw std::runtime_error("Failed to configure OpenSSL: command '" + kv.first + "' needs no value"); + throw clickhouse::OpenSSLError("Failed to configure OpenSSL: command '" + kv.first + "' needs no value"); else if (err == -2) - throw std::runtime_error("Failed to cofigure OpenSSL: unknown command '" + kv.first + "'"); + throw clickhouse::OpenSSLError("Failed to cofigure OpenSSL: unknown command '" + kv.first + "'"); else if (err == -3) - throw std::runtime_error("Failed to cofigure OpenSSL: command '" + kv.first + "' requires a value"); + throw clickhouse::OpenSSLError("Failed to cofigure OpenSSL: command '" + kv.first + "' requires a value"); else - throw std::runtime_error("Failed to cofigure OpenSSL: command '" + kv.first + "' unknown error: " + std::to_string(err)); + throw clickhouse::OpenSSLError("Failed to cofigure OpenSSL: command '" + kv.first + "' unknown error: " + std::to_string(err)); } } @@ -104,7 +105,7 @@ SSL_CTX * prepareSSLContext(const clickhouse::SSLParams & context_params) { std::unique_ptr ctx(SSL_CTX_new(method), &SSL_CTX_free); if (!ctx) - throw std::runtime_error("Failed to initialize SSL context"); + throw clickhouse::OpenSSLError("Failed to initialize SSL context"); #define HANDLE_SSL_CTX_ERROR(statement) do { \ if (const auto ret_code = (statement); !ret_code) \ @@ -204,7 +205,7 @@ SSLSocket::SSLSocket(const NetworkAddress& addr, const SSLParams & ssl_params, { auto ssl = ssl_.get(); if (!ssl) - throw std::runtime_error("Failed to create SSL instance"); + throw clickhouse::OpenSSLError("Failed to create SSL instance"); std::unique_ptr ip_addr(a2i_IPADDRESS(addr.Host().c_str()), &ASN1_OCTET_STRING_free); @@ -228,7 +229,7 @@ SSLSocket::SSLSocket(const NetworkAddress& addr, const SSLParams & ssl_params, if (const auto verify_result = SSL_get_verify_result(ssl); !ssl_params.skip_verification && verify_result != X509_V_OK) { auto error_message = X509_verify_cert_error_string(verify_result); - throw std::runtime_error("Failed to verify SSL connection, X509_v error: " + throw clickhouse::OpenSSLError("Failed to verify SSL connection, X509_v error: " + std::to_string(verify_result) + " " + error_message + "\nServer certificate: " + getCertificateInfo(SSL_get_peer_certificate(ssl))); diff --git a/clickhouse/base/wire_format.cpp b/clickhouse/base/wire_format.cpp index 00a806f8..dfe51b8a 100644 --- a/clickhouse/base/wire_format.cpp +++ b/clickhouse/base/wire_format.cpp @@ -3,6 +3,8 @@ #include "input.h" #include "output.h" +#include "../exceptions.h" + #include namespace { @@ -38,7 +40,7 @@ void WireFormat::WriteAll(OutputStream& output, const void* buf, size_t len) { } if (len) { - throw std::runtime_error("Failed to write " + std::to_string(original_len) + throw Error("Failed to write " + std::to_string(original_len) + " bytes, only written " + std::to_string(original_len - len)); } } diff --git a/clickhouse/block.cpp b/clickhouse/block.cpp index c4ddb855..aca77c00 100644 --- a/clickhouse/block.cpp +++ b/clickhouse/block.cpp @@ -1,5 +1,7 @@ #include "block.h" +#include "exceptions.h" + #include namespace clickhouse { @@ -54,7 +56,7 @@ void Block::AppendColumn(const std::string& name, const ColumnRef& col) { if (columns_.empty()) { rows_ = col->Size(); } else if (col->Size() != rows_) { - throw std::runtime_error("all columns in block must have same count of rows. Name: ["+name+"], rows: ["+std::to_string(rows_)+"], columns: [" + std::to_string(col->Size())+"]"); + throw ValidationError("all columns in block must have same count of rows. Name: ["+name+"], rows: ["+std::to_string(rows_)+"], columns: [" + std::to_string(col->Size())+"]"); } columns_.push_back(ColumnItem{name, col}); @@ -86,7 +88,7 @@ size_t Block::RefreshRowCount() if (idx == 0UL) rows = col->Size(); else if (rows != col->Size()) - throw std::runtime_error("all columns in block must have same count of rows. Name: ["+name+"], rows: ["+std::to_string(rows)+"], columns: [" + std::to_string(col->Size())+"]"); + throw ValidationError("all columns in block must have same count of rows. Name: ["+name+"], rows: ["+std::to_string(rows)+"], columns: [" + std::to_string(col->Size())+"]"); } rows_ = rows; diff --git a/clickhouse/client.cpp b/clickhouse/client.cpp index 08121f26..8a7c1e22 100644 --- a/clickhouse/client.cpp +++ b/clickhouse/client.cpp @@ -87,7 +87,7 @@ ClientOptions& ClientOptions::SetSSLOptions(ClientOptions::SSLOptions options) return *this; #else (void)options; - throw std::runtime_error("Library was built with no SSL support"); + throw OpenSSLError("Library was built with no SSL support"); #endif } @@ -152,7 +152,7 @@ class Client::Impl { private: /// In case of network errors tries to reconnect to server and /// call fuc several times. - void RetryGuard(std::function fuc); + void RetryGuard(std::function func); private: class EnsureNull { @@ -187,10 +187,6 @@ class Client::Impl { std::unique_ptr output_; std::unique_ptr socket_; -#if defined(WITH_OPENSSL) - std::unique_ptr ssl_context_; -#endif - ServerInfo server_info_; }; @@ -282,7 +278,7 @@ void Client::Impl::Insert(const std::string& table_name, const std::string& quer bool ret = ReceivePacket(&server_packet); if (!ret) { - throw std::runtime_error("fail to receive data packet"); + throw ProtocolError("fail to receive data packet"); } if (server_packet == ServerCodes::Data) { break; @@ -306,7 +302,7 @@ void Client::Impl::Insert(const std::string& table_name, const std::string& quer if (eos_packet != ServerCodes::EndOfStream && eos_packet != ServerCodes::Exception && eos_packet != ServerCodes::Log && options_.rethrow_exceptions) { - throw std::runtime_error(std::string{"unexpected packet from server while receiving end of query, expected (expected Exception, EndOfStream or Log, got: "} + throw ProtocolError(std::string{"unexpected packet from server while receiving end of query, expected (expected Exception, EndOfStream or Log, got: "} + (eos_packet ? std::to_string(eos_packet) : "nothing") + ")"); } } @@ -319,7 +315,7 @@ void Client::Impl::Ping() { const bool ret = ReceivePacket(&server_packet); if (!ret || server_packet != ServerCodes::Pong) { - throw std::runtime_error("fail to ping server"); + throw ProtocolError("fail to ping server"); } } @@ -327,7 +323,7 @@ void Client::Impl::ResetConnection() { InitializeStreams(socket_factory_->connect(options_)); if (!Handshake()) { - throw std::runtime_error("fail to connect to " + options_.host); + throw ProtocolError("fail to connect to " + options_.host); } } @@ -358,7 +354,7 @@ bool Client::Impl::ReceivePacket(uint64_t* server_packet) { switch (packet_type) { case ServerCodes::Data: { if (!ReceiveData()) { - throw std::runtime_error("can't read data packet from input stream"); + throw ProtocolError("can't read data packet from input stream"); } return true; } @@ -431,7 +427,7 @@ bool Client::Impl::ReceivePacket(uint64_t* server_packet) { } default: - throw std::runtime_error("unimplemented " + std::to_string((int)packet_type)); + throw UnimplementedError("unimplemented " + std::to_string((int)packet_type)); break; } @@ -489,12 +485,12 @@ bool Client::Impl::ReadBlock(InputStream& input, Block* block) { if (ColumnRef col = CreateColumnByType(type, create_column_settings)) { if (num_rows && !col->Load(&input, num_rows)) { - throw std::runtime_error("can't load column '" + name + "' of type " + type); + throw ProtocolError("can't load column '" + name + "' of type " + type); } block->AppendColumn(name, col); } else { - throw std::runtime_error(std::string("unsupported column type: ") + type); + throw UnimplementedError(std::string("unsupported column type: ") + type); } } @@ -573,7 +569,7 @@ bool Client::Impl::ReceiveException(bool rethrow) { } if (rethrow || options_.rethrow_exceptions) { - throw ServerException(std::move(e)); + throw ServerError(std::move(e)); } return exception_received; @@ -668,8 +664,8 @@ void Client::Impl::SendData(const Block& block) { if (compression_ == CompressionState::Enable) { assert(options_.compression_method == CompressionMethod::LZ4); - std::unique_ptr compressed_ouput = std::make_unique(output_.get(), options_.max_compression_chunk_size); - BufferedOutput buffered(std::move(compressed_ouput), options_.max_compression_chunk_size); + std::unique_ptr compressed_output = std::make_unique(output_.get(), options_.max_compression_chunk_size); + BufferedOutput buffered(std::move(compressed_output), options_.max_compression_chunk_size); WriteBlock(block, buffered); } else { @@ -794,19 +790,19 @@ void Client::Execute(const Query& query) { } void Client::Select(const std::string& query, SelectCallback cb) { - Execute(Query(query).OnData(cb)); + Execute(Query(query).OnData(std::move(cb))); } void Client::Select(const std::string& query, const std::string& query_id, SelectCallback cb) { - Execute(Query(query, query_id).OnData(cb)); + Execute(Query(query, query_id).OnData(std::move(cb))); } void Client::SelectCancelable(const std::string& query, SelectCancelableCallback cb) { - Execute(Query(query).OnDataCancelable(cb)); + Execute(Query(query).OnDataCancelable(std::move(cb))); } void Client::SelectCancelable(const std::string& query, const std::string& query_id, SelectCancelableCallback cb) { - Execute(Query(query, query_id).OnDataCancelable(cb)); + Execute(Query(query, query_id).OnDataCancelable(std::move(cb))); } void Client::Select(const Query& query) { diff --git a/clickhouse/columns/array.cpp b/clickhouse/columns/array.cpp index a83ba045..c71684d1 100644 --- a/clickhouse/columns/array.cpp +++ b/clickhouse/columns/array.cpp @@ -13,7 +13,7 @@ ColumnArray::ColumnArray(ColumnRef data) void ColumnArray::AppendAsColumn(ColumnRef array) { if (!data_->Type()->IsEqual(array->Type())) { - throw std::runtime_error( + throw ValidationError( "can't append column of type " + array->Type()->GetName() + " " "to column type " + data_->Type()->GetName()); } diff --git a/clickhouse/columns/column.h b/clickhouse/columns/column.h index 19e50988..6db5b39a 100644 --- a/clickhouse/columns/column.h +++ b/clickhouse/columns/column.h @@ -2,6 +2,7 @@ #include "../types/types.h" #include "../columns/itemview.h" +#include "../exceptions.h" #include #include @@ -61,7 +62,7 @@ class Column : public std::enable_shared_from_this { /// Get a view on raw item data if it is supported by column, will throw an exception if index is out of range. /// Please note that view is invalidated once column items are added or deleted, column is loaded from strean or destroyed. virtual ItemView GetItem(size_t) const { - throw std::runtime_error("GetItem() is not supported for column of " + type_->GetName()); + throw UnimplementedError("GetItem() is not supported for column of " + type_->GetName()); } friend void swap(Column& left, Column& right) { diff --git a/clickhouse/columns/date.cpp b/clickhouse/columns/date.cpp index 1301c2ff..78a86be1 100644 --- a/clickhouse/columns/date.cpp +++ b/clickhouse/columns/date.cpp @@ -184,7 +184,7 @@ ItemView ColumnDateTime64::GetItem(size_t index) const { void ColumnDateTime64::Swap(Column& other) { auto& col = dynamic_cast(other); if (col.GetPrecision() != GetPrecision()) { - throw std::runtime_error("Can't swap DateTime64 columns when precisions are not the same: " + throw ValidationError("Can't swap DateTime64 columns when precisions are not the same: " + std::to_string(GetPrecision()) + "(this) != " + std::to_string(col.GetPrecision()) + "(that)"); } diff --git a/clickhouse/columns/decimal.cpp b/clickhouse/columns/decimal.cpp index 489dab5f..8a4186a0 100644 --- a/clickhouse/columns/decimal.cpp +++ b/clickhouse/columns/decimal.cpp @@ -156,21 +156,21 @@ void ColumnDecimal::Append(const std::string& value) { } else if (*c >= '0' && *c <= '9') { if (mulOverflow(int_value, 10, &int_value) || addOverflow(int_value, *c - '0', &int_value)) { - throw std::runtime_error("value is too big for 128-bit integer"); + throw AssertionError("value is too big for 128-bit integer"); } } else { - throw std::runtime_error(std::string("unexpected symbol '") + (*c) + "' in decimal value"); + throw ValidationError(std::string("unexpected symbol '") + (*c) + "' in decimal value"); } ++c; } if (c != end) { - throw std::runtime_error("unexpected symbol '-' in decimal value"); + throw ValidationError("unexpected symbol '-' in decimal value"); } while (zeros) { if (mulOverflow(int_value, 10, &int_value)) { - throw std::runtime_error("value is too big for 128-bit integer"); + throw AssertionError("value is too big for 128-bit integer"); } --zeros; } @@ -187,7 +187,7 @@ Int128 ColumnDecimal::At(size_t i) const { case Type::Int128: return data_->As()->At(i); default: - throw std::runtime_error("Invalid data_ column type in ColumnDecimal"); + throw ValidationError("Invalid data_ column type in ColumnDecimal"); } } diff --git a/clickhouse/columns/factory.cpp b/clickhouse/columns/factory.cpp index 08b362e9..264d2933 100644 --- a/clickhouse/columns/factory.cpp +++ b/clickhouse/columns/factory.cpp @@ -17,6 +17,8 @@ #include "../types/type_parser.h" +#include "../exceptions.h" + #include namespace clickhouse { @@ -162,7 +164,7 @@ static ColumnRef CreateColumnFromAst(const TypeAst& ast, CreateColumnByTypeSetti case Type::FixedString: return std::make_shared>(nested.elements.front().value); default: - throw std::runtime_error("LowCardinality(" + nested.name + ") is not supported"); + throw UnimplementedError("LowCardinality(" + nested.name + ") is not supported"); } } else { @@ -173,7 +175,7 @@ static ColumnRef CreateColumnFromAst(const TypeAst& ast, CreateColumnByTypeSetti case Type::FixedString: return std::make_shared>(nested.elements.front().value); default: - throw std::runtime_error("LowCardinality(" + nested.name + ") is not supported"); + throw UnimplementedError("LowCardinality(" + nested.name + ") is not supported"); } } } diff --git a/clickhouse/columns/ip4.cpp b/clickhouse/columns/ip4.cpp index f7362362..b2327e86 100644 --- a/clickhouse/columns/ip4.cpp +++ b/clickhouse/columns/ip4.cpp @@ -16,13 +16,13 @@ ColumnIPv4::ColumnIPv4(ColumnRef data) , data_(data ? data->As() : nullptr) { if (!data_) - throw std::runtime_error("Expecting ColumnUInt32, got " + (data ? data->GetType().GetName() : "null")); + throw ValidationError("Expecting ColumnUInt32, got " + (data ? data->GetType().GetName() : "null")); } void ColumnIPv4::Append(const std::string& str) { uint32_t address; if (inet_pton(AF_INET, str.c_str(), &address) != 1) - throw std::runtime_error("invalid IPv4 format, ip: " + str); + throw ValidationError("invalid IPv4 format, ip: " + str); data_->Append(htonl(address)); } diff --git a/clickhouse/columns/ip6.cpp b/clickhouse/columns/ip6.cpp index d1f3995d..1d9f14db 100644 --- a/clickhouse/columns/ip6.cpp +++ b/clickhouse/columns/ip6.cpp @@ -1,6 +1,6 @@ - #include "ip6.h" #include "../base/socket.h" // for IPv6 platform-specific stuff +#include "../exceptions.h" #include @@ -19,13 +19,13 @@ ColumnIPv6::ColumnIPv6(ColumnRef data) , data_(data ? data->As() : nullptr) { if (!data_ || data_->FixedSize() != sizeof(in6_addr)) - throw std::runtime_error("Expecting ColumnFixedString(16), got " + (data ? data->GetType().GetName() : "null")); + throw ValidationError("Expecting ColumnFixedString(16), got " + (data ? data->GetType().GetName() : "null")); } void ColumnIPv6::Append(const std::string_view& str) { unsigned char buf[16]; if (inet_pton(AF_INET6, str.data(), buf) != 1) { - throw std::runtime_error("invalid IPv6 format, ip: " + std::string(str)); + throw ValidationError("invalid IPv6 format, ip: " + std::string(str)); } data_->Append(std::string_view((const char*)buf, 16)); } diff --git a/clickhouse/columns/itemview.cpp b/clickhouse/columns/itemview.cpp index 9dc8533f..4f83e36f 100644 --- a/clickhouse/columns/itemview.cpp +++ b/clickhouse/columns/itemview.cpp @@ -49,7 +49,7 @@ void ItemView::ValidateData(Type::Code type, DataType data) { case Type::Code::Nullable: case Type::Code::Tuple: case Type::Code::LowCardinality: - throw std::runtime_error("Unsupported type in ItemView: " + std::to_string(static_cast(type))); + throw UnimplementedError("Unsupported type in ItemView: " + std::to_string(static_cast(type))); case Type::Code::UUID: case Type::Code::Int128: @@ -59,11 +59,11 @@ void ItemView::ValidateData(Type::Code type, DataType data) { break; default: - throw std::runtime_error("Unknon type code:" + std::to_string(static_cast(type))); + throw UnimplementedError("Unknon type code:" + std::to_string(static_cast(type))); } if (expected_size != static_cast(data.size())) { - throw std::runtime_error("Value size mismatch for type " + throw AssertionError("Value size mismatch for type " + std::to_string(static_cast(type)) + " expected: " + std::to_string(expected_size) + ", got: " + std::to_string(data.size())); } diff --git a/clickhouse/columns/itemview.h b/clickhouse/columns/itemview.h index e4e0d5ea..9e43e00b 100644 --- a/clickhouse/columns/itemview.h +++ b/clickhouse/columns/itemview.h @@ -1,6 +1,7 @@ #pragma once #include "../types/types.h" +#include "../exceptions.h" #include #include @@ -59,7 +60,7 @@ struct ItemView { if (sizeof(T) == data.size()) { return *reinterpret_cast(data.data()); } else { - throw std::runtime_error("Incompatitable value type and size."); + throw AssertionError("Incompatitable value type and size."); } } } diff --git a/clickhouse/columns/lowcardinality.cpp b/clickhouse/columns/lowcardinality.cpp index 1cb21fef..694e3eda 100644 --- a/clickhouse/columns/lowcardinality.cpp +++ b/clickhouse/columns/lowcardinality.cpp @@ -49,7 +49,7 @@ ColumnRef createIndexColumn(IndexType type) { return std::make_shared(); } - throw std::runtime_error("Invalid LowCardinality index type value: " + std::to_string(static_cast(type))); + throw ValidationError("Invalid LowCardinality index type value: " + std::to_string(static_cast(type))); } IndexType indexTypeFromIndexColumn(const Column & index_column) { @@ -63,7 +63,7 @@ IndexType indexTypeFromIndexColumn(const Column & index_column) { case Type::UInt64: return IndexType::UInt64; default: - throw std::runtime_error("Invalid index column type for LowCardinality column:" + index_column.Type()->GetName()); + throw ValidationError("Invalid index column type for LowCardinality column:" + index_column.Type()->GetName()); } } @@ -90,7 +90,7 @@ inline auto VisitIndexColumn(Vizitor && vizitor, ColumnType && col) { case Type::UInt64: return vizitor(column_down_cast(col)); default: - throw std::runtime_error("Invalid index column type " + col.GetType().GetName()); + throw ValidationError("Invalid index column type " + col.GetType().GetName()); } } @@ -103,7 +103,7 @@ inline void AppendToDictionary(Column& dictionary, const ItemView & item) { column_down_cast(dictionary).Append(item.get()); return; default: - throw std::runtime_error("Unexpected dictionary column type: " + dictionary.GetType().GetName()); + throw ValidationError("Unexpected dictionary column type: " + dictionary.GetType().GetName()); } } @@ -197,42 +197,42 @@ auto Load(ColumnRef new_dictionary_column, InputStream& input, size_t rows) { // (see corresponding serializeBinaryBulkStateSuffix, serializeBinaryBulkStatePrefix, and serializeBinaryBulkWithMultipleStreams), // but with certain simplifications: no shared dictionaries, no on-the-fly dictionary updates. // - // As for now those fetures not used in client-server protocol and minimal implimintation suffice, + // As for now those features are not used in client-server protocol and minimal implementation suffices, // however some day they may. // prefix uint64_t key_version; if (!WireFormat::ReadFixed(input, &key_version)) - throw std::runtime_error("Failed to read key serialization version."); + throw ProtocolError("Failed to read key serialization version."); if (key_version != KeySerializationVersion::SharedDictionariesWithAdditionalKeys) - throw std::runtime_error("Invalid key serialization version value."); + throw ProtocolError("Invalid key serialization version value."); // body uint64_t index_serialization_type; if (!WireFormat::ReadFixed(input, &index_serialization_type)) - throw std::runtime_error("Failed to read index serializaton type."); + throw ProtocolError("Failed to read index serializaton type."); auto new_index_column = createIndexColumn(static_cast(index_serialization_type & IndexTypeMask)); if (index_serialization_type & IndexFlag::NeedGlobalDictionaryBit) - throw std::runtime_error("Global dictionary is not supported."); + throw UnimplementedError("Global dictionary is not supported."); if ((index_serialization_type & IndexFlag::HasAdditionalKeysBit) == 0) - throw std::runtime_error("HasAdditionalKeysBit is missing."); + throw ValidationError("HasAdditionalKeysBit is missing."); uint64_t number_of_keys; if (!WireFormat::ReadFixed(input, &number_of_keys)) - throw std::runtime_error("Failed to read number of rows in dictionary column."); + throw ProtocolError("Failed to read number of rows in dictionary column."); if (!new_dictionary_column->Load(&input, number_of_keys)) - throw std::runtime_error("Failed to read values of dictionary column."); + throw ProtocolError("Failed to read values of dictionary column."); uint64_t number_of_rows; if (!WireFormat::ReadFixed(input, &number_of_rows)) - throw std::runtime_error("Failed to read number of rows in index column."); + throw ProtocolError("Failed to read number of rows in index column."); if (number_of_rows != rows) - throw std::runtime_error("LowCardinality column must be read in full."); + throw AssertionError("LowCardinality column must be read in full."); new_index_column->Load(&input, number_of_rows); @@ -312,7 +312,7 @@ ColumnRef ColumnLowCardinality::Slice(size_t begin, size_t len) const { void ColumnLowCardinality::Swap(Column& other) { auto & col = dynamic_cast(other); if (!dictionary_column_->Type()->IsEqual(col.dictionary_column_->Type())) - throw std::runtime_error("Can't swap() LowCardinality columns of different types."); + throw ValidationError("Can't swap() LowCardinality columns of different types."); // It is important here not to swap pointers to dictionary object, // but swap contents of dictionaries, so the object inside shared_ptr stays the same diff --git a/clickhouse/columns/nothing.h b/clickhouse/columns/nothing.h index ef7004b5..f3a1e5e2 100644 --- a/clickhouse/columns/nothing.h +++ b/clickhouse/columns/nothing.h @@ -59,7 +59,7 @@ class ColumnNothing : public Column { /// Saves column data to output stream. void Save(OutputStream*) override { - throw std::runtime_error("method Save is not supported for Nothing column"); + throw UnimplementedError("method Save is not supported for Nothing column"); } /// Clear column data . diff --git a/clickhouse/columns/nullable.cpp b/clickhouse/columns/nullable.cpp index 1f0f1efb..65336b31 100644 --- a/clickhouse/columns/nullable.cpp +++ b/clickhouse/columns/nullable.cpp @@ -11,7 +11,7 @@ ColumnNullable::ColumnNullable(ColumnRef nested, ColumnRef nulls) , nulls_(nulls->As()) { if (nested_->Size() != nulls->Size()) { - throw std::runtime_error("count of elements in nested and nulls should be the same"); + throw ValidationError("count of elements in nested and nulls should be the same"); } } @@ -77,7 +77,7 @@ ColumnRef ColumnNullable::Slice(size_t begin, size_t len) const { void ColumnNullable::Swap(Column& other) { auto & col = dynamic_cast(other); if (!nested_->Type()->IsEqual(col.nested_->Type())) - throw std::runtime_error("Can't swap() Nullable columns of different types."); + throw ValidationError("Can't swap() Nullable columns of different types."); nested_.swap(col.nested_); nulls_.swap(col.nulls_); diff --git a/clickhouse/columns/string.cpp b/clickhouse/columns/string.cpp index a2138b96..612f1a4c 100644 --- a/clickhouse/columns/string.cpp +++ b/clickhouse/columns/string.cpp @@ -32,7 +32,7 @@ ColumnFixedString::ColumnFixedString(size_t n) void ColumnFixedString::Append(std::string_view str) { if (str.size() > string_size_) { - throw std::runtime_error("Expected string of length not greater than " + throw ValidationError("Expected string of length not greater than " + std::to_string(string_size_) + " bytes, received " + std::to_string(str.size()) + " bytes."); } @@ -126,7 +126,7 @@ struct ColumnString::Block data_(new CharT[capacity]) {} - inline auto GetAvailble() const + inline auto GetAvailable() const { return capacity - size; } @@ -179,7 +179,7 @@ ColumnString::~ColumnString() {} void ColumnString::Append(std::string_view str) { - if (blocks_.size() == 0 || blocks_.back().GetAvailble() < str.length()) + if (blocks_.size() == 0 || blocks_.back().GetAvailable() < str.length()) { blocks_.emplace_back(std::max(DEFAULT_BLOCK_SIZE, str.size())); } @@ -210,7 +210,7 @@ void ColumnString::Append(ColumnRef column) { const auto total_size = ComputeTotalSize(col->items_); // TODO: fill up existing block with some items and then add a new one for the rest of items - if (blocks_.size() == 0 || blocks_.back().GetAvailble() < total_size) + if (blocks_.size() == 0 || blocks_.back().GetAvailable() < total_size) blocks_.emplace_back(std::max(DEFAULT_BLOCK_SIZE, total_size)); items_.reserve(items_.size() + col->Size()); @@ -233,7 +233,7 @@ bool ColumnString::Load(InputStream* input, size_t rows) { if (!WireFormat::ReadUInt64(*input, &len)) return false; - if (blocks_.size() == 0 || len > block->GetAvailble()) + if (blocks_.size() == 0 || len > block->GetAvailable()) block = &blocks_.emplace_back(std::max(DEFAULT_BLOCK_SIZE, len)); if (!WireFormat::ReadBytes(*input, block->GetCurrentWritePos(), len)) diff --git a/clickhouse/columns/tuple.cpp b/clickhouse/columns/tuple.cpp index d799d104..88201f36 100644 --- a/clickhouse/columns/tuple.cpp +++ b/clickhouse/columns/tuple.cpp @@ -22,7 +22,7 @@ size_t ColumnTuple::TupleSize() const { void ColumnTuple::Append(ColumnRef column) { if (!this->Type()->IsEqual(column->Type())) { - throw std::runtime_error( + throw ValidationError( "can't append column of type " + column->Type()->GetName() + " " "to column type " + this->Type()->GetName()); } diff --git a/clickhouse/columns/uuid.cpp b/clickhouse/columns/uuid.cpp index b69ab9c6..b64bb6b5 100644 --- a/clickhouse/columns/uuid.cpp +++ b/clickhouse/columns/uuid.cpp @@ -1,5 +1,6 @@ #include "uuid.h" #include "utils.h" +#include "../exceptions.h" #include @@ -16,7 +17,7 @@ ColumnUUID::ColumnUUID(ColumnRef data) , data_(data->As()) { if (data_->Size() % 2 != 0) { - throw std::runtime_error("number of entries must be even (two 64-bit numbers for each UUID)"); + throw ValidationError("number of entries must be even (two 64-bit numbers for each UUID)"); } } diff --git a/clickhouse/exceptions.h b/clickhouse/exceptions.h index 44f400f0..4039ccc5 100644 --- a/clickhouse/exceptions.h +++ b/clickhouse/exceptions.h @@ -1,15 +1,43 @@ #pragma once -#include "query.h" +#include "server_exception.h" #include namespace clickhouse { -class ServerException : public std::runtime_error { +class Error : public std::runtime_error { + using std::runtime_error::runtime_error; +}; + +class ValidationError : public Error { + using Error::Error; +}; + +class ProtocolError : public Error { + using Error::Error; +}; + +class UnimplementedError : public Error { + using Error::Error; +}; + +class AssertionError : public Error { + using Error::Error; +}; + +class OpenSSLError : public Error { + using Error::Error; +}; + +class LZ4Error : public Error { + using Error::Error; +}; + +class ServerException : public Error { public: ServerException(std::unique_ptr e) - : runtime_error(std::string()) + : Error(std::string()) , exception_(std::move(e)) { } @@ -29,5 +57,6 @@ class ServerException : public std::runtime_error { private: std::unique_ptr exception_; }; +using ServerError = ServerException; } diff --git a/clickhouse/query.h b/clickhouse/query.h index e9e12856..19a95af8 100644 --- a/clickhouse/query.h +++ b/clickhouse/query.h @@ -1,6 +1,7 @@ #pragma once #include "block.h" +#include "server_exception.h" #include #include @@ -33,16 +34,6 @@ struct QuerySettings { }; -struct Exception { - int code = 0; - std::string name; - std::string display_text; - std::string stack_trace; - /// Pointer to nested exception. - std::unique_ptr nested; -}; - - struct Profile { uint64_t rows = 0; uint64_t blocks = 0; @@ -90,7 +81,7 @@ class Query : public QueryEvents { Query(); Query(const char* query, const char* query_id = nullptr); Query(const std::string& query, const std::string& query_id = default_query_id); - ~Query(); + ~Query() override; /// inline const std::string& GetText() const { @@ -103,25 +94,25 @@ class Query : public QueryEvents { /// Set handler for receiving result data. inline Query& OnData(SelectCallback cb) { - select_cb_ = cb; + select_cb_ = std::move(cb); return *this; } inline Query& OnDataCancelable(SelectCancelableCallback cb) { - select_cancelable_cb_ = cb; + select_cancelable_cb_ = std::move(cb); return *this; } /// Set handler for receiving server's exception. inline Query& OnException(ExceptionCallback cb) { - exception_cb_ = cb; + exception_cb_ = std::move(cb); return *this; } /// Set handler for receiving a progress of query exceution. inline Query& OnProgress(ProgressCallback cb) { - progress_cb_ = cb; + progress_cb_ = std::move(cb); return *this; } diff --git a/clickhouse/server_exception.h b/clickhouse/server_exception.h new file mode 100644 index 00000000..dcc97c51 --- /dev/null +++ b/clickhouse/server_exception.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +namespace clickhouse { +struct Exception { + int code = 0; + std::string name; + std::string display_text; + std::string stack_trace; + /// Pointer to nested exception. + std::unique_ptr nested; +}; + +} diff --git a/clickhouse/types/types.cpp b/clickhouse/types/types.cpp index 32ef9321..8dc6688b 100644 --- a/clickhouse/types/types.cpp +++ b/clickhouse/types/types.cpp @@ -1,5 +1,7 @@ #include "types.h" +#include "../exceptions.h" + #include #include @@ -319,7 +321,7 @@ DateTime64Type::DateTime64Type(size_t precision, std::string timezone) : Type(DateTime64), details::TypeWithTimeZoneMixin(std::move(timezone)), precision_(precision) { if (precision_ > 18) { - throw std::runtime_error("DateTime64 precision is > 18"); + throw ValidationError("DateTime64 precision is > 18"); } }