polardbxengine/plugin/x/protocol/encoders/encoding_xmessages.h

388 lines
16 KiB
C++

/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2.0,
* as published by the Free Software Foundation.
*
* This program is also distributed with certain software (including
* but not limited to OpenSSL) that is licensed under separate terms,
* as designated in a particular file or component or in included license
* documentation. The authors of MySQL hereby grant you an additional
* permission to link the program and your derivative works with the
* separately licensed software that they have included with MySQL.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License, version 2.0, for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef PLUGIN_X_PROTOCOL_ENCODERS_ENCODING_XMESSAGES_H_
#define PLUGIN_X_PROTOCOL_ENCODERS_ENCODING_XMESSAGES_H_
#include <cassert>
#include <cstdint>
#include <string>
#include <utility>
#include "my_dbug.h"
#include "plugin/x/protocol/encoders/galaxy_encoding_xprotocol.h"
#include "plugin/x/generated/encoding_descriptors.h"
#include "plugin/x/ngs/include/ngs/protocol/encode_column_info.h"
#include "plugin/x/ngs/include/ngs/protocol/protocol_protobuf.h"
#include "plugin/x/protocol/encoders/encoding_xprotocol.h"
namespace protocol {
template <typename Base_type>
class XMessage_encoder_base : public Base_type {
private:
constexpr static Mysqlx::Notice::Frame_Type k_state_change =
Mysqlx::Notice::Frame_Type_SESSION_STATE_CHANGED;
constexpr static Mysqlx::Notice::Frame_Scope k_local =
Mysqlx::Notice::Frame_Scope_LOCAL;
constexpr static Mysqlx::Notice::SessionStateChanged_Parameter k_message =
Mysqlx::Notice::SessionStateChanged::PRODUCED_MESSAGE;
constexpr static Mysqlx::Notice::SessionStateChanged_Parameter k_expired =
Mysqlx::Notice::SessionStateChanged::ACCOUNT_EXPIRED;
constexpr static Mysqlx::Notice::SessionStateChanged_Parameter
k_generated_insert_id =
Mysqlx::Notice::SessionStateChanged::GENERATED_INSERT_ID;
constexpr static Mysqlx::Datatypes::Scalar_Type k_string =
Mysqlx::Datatypes::Scalar_Type_V_STRING;
constexpr static Mysqlx::Datatypes::Scalar_Type k_v_uint =
Mysqlx::Datatypes::Scalar_Type_V_UINT;
constexpr static Mysqlx::Notice::SessionStateChanged_Parameter
k_rows_affected = Mysqlx::Notice::SessionStateChanged::ROWS_AFFECTED;
constexpr static Mysqlx::Notice::SessionStateChanged_Parameter k_client_id =
Mysqlx::Notice::SessionStateChanged::CLIENT_ID_ASSIGNED;
public:
// Constructor inheritance doesn't work in solaris
// for template<T> class X: T {...};
//
// ```using Base_type::Base_type;```
//
// Using template constructor instead:
template <typename... Args>
XMessage_encoder_base(Args &&... args)
: Base_type(std::forward<Args>(args)...) {}
void encode_compact_metadata(const uint8_t type, const uint64_t *collation,
const uint32_t *decimals, const uint32_t *length,
const uint32_t *flags,
const uint32_t *content_type) {
using Tags = tags::ColumnMetaData;
// The buffer size is verified by UT in xmessage_buffer.cc
auto xmsg_start =
Base_type::template begin_xmessage<Tags::server_id, 100>();
Base_type::template encode_field_enum<Tags::type>(type);
Base_type::template encode_optional_field_var_uint64<Tags::collation>(
collation);
Base_type::template encode_optional_field_var_uint32<
Tags::fractional_digits>(decimals);
Base_type::template encode_optional_field_var_uint32<Tags::length>(length);
Base_type::template encode_optional_field_var_uint32<Tags::flags>(flags);
Base_type::template encode_optional_field_var_uint32<Tags::content_type>(
content_type);
Base_type::end_xmessage(xmsg_start);
}
void encode_full_metadata(const char *col_name, const char *org_col_name,
const char *table_name, const char *org_table_name,
const char *db_name, const char *catalog,
const uint8_t type, const uint64_t *collation,
const uint32_t *decimals, const uint32_t *length,
const uint32_t *flags,
const uint32_t *content_type) {
using Tags = tags::ColumnMetaData;
// The buffer size is verified by UT in xmessage_buffer.cc
auto xmsg_start =
Base_type::template begin_xmessage<Tags::server_id, 100>();
Base_type::template encode_field_enum<Tags::type>(type);
Base_type::template encode_optional_field_var_uint64<Tags::collation>(
collation);
Base_type::template encode_optional_field_var_uint32<
Tags::fractional_digits>(decimals);
Base_type::template encode_optional_field_var_uint32<Tags::length>(length);
Base_type::template encode_optional_field_var_uint32<Tags::flags>(flags);
Base_type::template encode_optional_field_var_uint32<Tags::content_type>(
content_type);
Base_type::template encode_field_string<Tags::name>(col_name);
Base_type::template encode_field_string<Tags::original_name>(org_col_name);
Base_type::template encode_field_string<Tags::table>(table_name);
Base_type::template encode_field_string<Tags::original_table>(
org_table_name);
Base_type::template encode_field_string<Tags::schema>(db_name);
Base_type::template encode_field_string<Tags::catalog>(catalog);
Base_type::end_xmessage(xmsg_start);
}
void encode_metadata(const ngs::Encode_column_info *column) {
using Tags = tags::ColumnMetaData;
// The buffer size is verified by UT in xmessage_buffer.cc
auto xmsg_start =
Base_type::template begin_xmessage<Tags::server_id, 100>();
Base_type::template encode_field_enum<Tags::type>(column->m_type);
Base_type::template encode_optional_field_var_uint64<Tags::collation>(
column->m_collation_ptr);
Base_type::template encode_optional_field_var_uint32<
Tags::fractional_digits>(column->m_decimals_ptr);
Base_type::template encode_optional_field_var_uint32<Tags::length>(
column->m_length_ptr);
Base_type::template encode_optional_field_var_uint32<Tags::flags>(
column->m_flags_ptr);
Base_type::template encode_optional_field_var_uint32<Tags::content_type>(
column->m_content_type_ptr);
if (!column->m_compact) {
Base_type::template encode_field_string<Tags::name>(column->m_col_name);
Base_type::template encode_field_string<Tags::original_name>(
column->m_org_col_name);
Base_type::template encode_field_string<Tags::table>(
column->m_table_name);
Base_type::template encode_field_string<Tags::original_table>(
column->m_org_table_name);
Base_type::template encode_field_string<Tags::schema>(column->m_db_name);
Base_type::template encode_field_string<Tags::catalog>(column->m_catalog);
}
// GalaxyStore
Base_type::template encode_field_enum<Tags::original_type>(
column->m_original_type);
Base_type::end_xmessage(xmsg_start);
}
void encode_notice_rows_affected(const uint64_t rows) {
using FrameTags = tags::Frame;
using StateTags = tags::SessionStateChanged;
using ScalarTags = tags::Scalar;
// The buffer size is verified by UT in xmessage_buffer.cc
auto xmsg_start =
Base_type::template begin_xmessage<FrameTags::server_id, 145>();
Base_type::template encode_field_const_var_uint<FrameTags::type,
k_state_change>();
Base_type::template encode_field_const_enum<FrameTags::scope, k_local>();
auto field_payload_start =
Base_type::template begin_delimited_field<FrameTags::payload>();
Base_type::template encode_field_const_enum<StateTags::param,
k_rows_affected>();
auto field_value_start =
Base_type::template begin_delimited_field<StateTags::value>();
Base_type::template encode_field_const_enum<ScalarTags::type, k_v_uint>();
Base_type::template encode_field_var_uint64<ScalarTags::v_unsigned_int>(
rows);
Base_type::end_delimited_field(field_value_start);
Base_type::end_delimited_field(field_payload_start);
Base_type::end_xmessage(xmsg_start);
}
void encode_notice_client_id(const uint64_t id) {
using FrameTags = tags::Frame;
using StateTags = tags::SessionStateChanged;
using ScalarTags = tags::Scalar;
// The buffer size is verified by UT in xmessage_buffer.cc
auto xmsg_start =
Base_type::template begin_xmessage<FrameTags::server_id, 145>();
Base_type::template encode_field_const_var_uint<FrameTags::type,
k_state_change>();
Base_type::template encode_field_const_enum<FrameTags::scope, k_local>();
auto field_payload_start =
Base_type::template begin_delimited_field<FrameTags::payload>();
Base_type::template encode_field_const_enum<StateTags::param,
k_client_id>();
auto field_value_start =
Base_type::template begin_delimited_field<StateTags::value>();
Base_type::template encode_field_const_enum<ScalarTags::type, k_v_uint>();
Base_type::template encode_field_var_uint64<ScalarTags::v_unsigned_int>(id);
Base_type::end_delimited_field(field_value_start);
Base_type::end_delimited_field(field_payload_start);
Base_type::end_xmessage(xmsg_start);
}
void encode_notice_expired() {
using FrameTags = tags::Frame;
using StateTags = tags::SessionStateChanged;
// The buffer size is verified by UT in xmessage_buffer.cc
auto xmsg_start =
Base_type::template begin_xmessage<FrameTags::server_id, 85>();
Base_type::template encode_field_const_var_uint<FrameTags::type,
k_state_change>();
Base_type::template encode_field_const_enum<FrameTags::scope, k_local>();
auto field_payload_start =
Base_type::template begin_delimited_field<FrameTags::payload>();
Base_type::template encode_field_const_enum<StateTags::param, k_expired>();
Base_type::end_delimited_field(field_payload_start);
Base_type::end_xmessage(xmsg_start);
}
void encode_notice_generated_insert_id(const uint64_t last_insert_id) {
using FrameTags = tags::Frame;
using StateTags = tags::SessionStateChanged;
using ScalarTags = tags::Scalar;
// The buffer size is verified by UT in xmessage_buffer.cc
auto xmsg_start =
Base_type::template begin_xmessage<FrameTags::server_id, 145>();
Base_type::template encode_field_const_var_uint<FrameTags::type,
k_state_change>();
Base_type::template encode_field_const_enum<FrameTags::scope, k_local>();
auto field_payload_start =
Base_type::template begin_delimited_field<FrameTags::payload>();
Base_type::template encode_field_const_enum<StateTags::param,
k_generated_insert_id>();
auto field_value_start =
Base_type::template begin_delimited_field<StateTags::value>();
Base_type::template encode_field_const_enum<ScalarTags::type, k_v_uint>();
Base_type::template encode_field_var_uint64<ScalarTags::v_unsigned_int>(
last_insert_id);
Base_type::end_delimited_field(field_value_start);
Base_type::end_delimited_field(field_payload_start);
Base_type::end_xmessage(xmsg_start);
}
void encode_notice_text_message(const std::string &message) {
using FrameTags = tags::Frame;
using StateTags = tags::SessionStateChanged;
using ScalarTags = tags::Scalar;
using StringTags = tags::String;
// The buffer size is verified by UT in xmessage_buffer.cc
auto xmsg_start =
Base_type::template begin_xmessage<FrameTags::server_id, 145>();
Base_type::template encode_field_const_var_uint<FrameTags::type,
k_state_change>();
Base_type::template encode_field_const_enum<FrameTags::scope, k_local>();
auto field_payload_start =
Base_type::template begin_delimited_field<FrameTags::payload, 4>();
Base_type::template encode_field_const_enum<StateTags::param, k_message>();
auto field_value_start =
Base_type::template begin_delimited_field<StateTags::value, 4>();
Base_type::template encode_field_const_enum<ScalarTags::type, k_string>();
auto string_start =
Base_type::template begin_delimited_field<ScalarTags::v_string, 4>();
Base_type::template encode_field_string<StringTags::value>(message);
Base_type::end_delimited_field(string_start);
Base_type::end_delimited_field(field_value_start);
Base_type::end_delimited_field(field_payload_start);
Base_type::end_xmessage(xmsg_start);
}
void encode_notice(const uint32_t type, const uint32_t scope,
const std::string &data) {
using FrameTags = tags::Frame;
// The buffer size is verified by UT in xmessage_buffer.cc
auto xmsg_start =
Base_type::template begin_xmessage<FrameTags::server_id, 40>();
Base_type::template encode_field_var_uint32<FrameTags::type>(type);
Base_type::template encode_field_enum<FrameTags::scope>(scope);
Base_type::template encode_field_string<FrameTags::payload>(data);
Base_type::end_xmessage(xmsg_start);
}
void encode_global_notice(const uint32_t type, const std::string &data) {
using FrameTags = tags::Frame;
// The buffer size is verified by UT in xmessage_buffer.cc
auto xmsg_start =
Base_type::template begin_xmessage<FrameTags::server_id, 25>();
Base_type::template encode_field_var_uint32<FrameTags::type>(type);
Base_type::template encode_field_string<FrameTags::payload>(data);
Base_type::end_xmessage(xmsg_start);
}
void encode_fetch_more_resultsets() {
Base_type::template empty_xmessage<
tags::FetchDoneMoreResultsets::server_id>();
}
void encode_fetch_out_params() {
Base_type::template empty_xmessage<
tags::FetchDoneMoreOutParams::server_id>();
}
void encode_fetch_suspended() {
Base_type::template empty_xmessage<tags::FetchSuspended::server_id>();
}
void encode_fetch_done() {
Base_type::template empty_xmessage<tags::FetchDone::server_id>();
}
void encode_token_done() {
Base_type::template empty_xmessage<tags::TokenDone::server_id>();
}
void encode_stmt_execute_ok() {
Base_type::template empty_xmessage<tags::StmtExecuteOk::server_id>();
}
void encode_ok() {
Base_type::template empty_xmessage<tags::Ok::server_id>();
}
void encode_ok(const std::string &message) {
auto xmsg_start =
Base_type::template begin_xmessage<tags::Ok::server_id, 5>();
Base_type::template encode_field_string<tags::Ok::msg>(message);
Base_type::end_xmessage(xmsg_start);
}
void encode_error(const int severity, const uint32_t code,
const std::string &msg, const std::string &sql_state) {
auto xmsg_start =
Base_type::template begin_xmessage<tags::Error::server_id, 40>();
Base_type::template encode_field_enum<tags::Error::severity>(severity);
Base_type::template encode_field_var_uint32<tags::Error::code>(code);
Base_type::template encode_field_string<tags::Error::msg>(msg);
Base_type::template encode_field_string<tags::Error::sql_state>(sql_state);
Base_type::end_xmessage(xmsg_start);
}
template <uint8_t id>
void encode_xmessage(const std::string &serialized_xmessage) {
auto xmsg_start = Base_type::template begin_xmessage<id, 100>();
Base_type::encode_raw(
reinterpret_cast<const uint8_t *>(serialized_xmessage.c_str()),
serialized_xmessage.length());
Base_type::end_xmessage(xmsg_start);
}
};
class XMessage_encoder : public XMessage_encoder_base<GProtocol_encoder> {
public:
using XMessage_encoder_base<GProtocol_encoder>::XMessage_encoder_base;
};
} // namespace protocol
#endif // PLUGIN_X_PROTOCOL_ENCODERS_ENCODING_XMESSAGES_H_