/* * Copyright (c) 2019, 2022, Oracle and/or its affiliates. * * 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 */ #pragma once #include #include #include #include #include "my_dbug.h" // NOLINT(build/include_subdir) #include "../protocol_fwd.h" #include "encoding_descriptors.h" #include "encoding_polarx_protocol.h" namespace protocol { template class XMessage_encoder_base : public Base_type { private: constexpr static Polarx::Notice::Frame_Type k_state_change = Polarx::Notice::Frame_Type_SESSION_STATE_CHANGED; constexpr static Polarx::Notice::Frame_Scope k_local = Polarx::Notice::Frame_Scope_LOCAL; constexpr static Polarx::Notice::SessionStateChanged_Parameter k_message = Polarx::Notice::SessionStateChanged::PRODUCED_MESSAGE; constexpr static Polarx::Notice::SessionStateChanged_Parameter k_expired = Polarx::Notice::SessionStateChanged::ACCOUNT_EXPIRED; constexpr static Polarx::Notice::SessionStateChanged_Parameter k_generated_insert_id = Polarx::Notice::SessionStateChanged::GENERATED_INSERT_ID; constexpr static Polarx::Datatypes::Scalar_Type k_string = Polarx::Datatypes::Scalar_Type_V_STRING; constexpr static Polarx::Datatypes::Scalar_Type k_v_uint = Polarx::Datatypes::Scalar_Type_V_UINT; constexpr static Polarx::Notice::SessionStateChanged_Parameter k_rows_affected = Polarx::Notice::SessionStateChanged::ROWS_AFFECTED; constexpr static Polarx::Notice::SessionStateChanged_Parameter k_client_id = Polarx::Notice::SessionStateChanged::CLIENT_ID_ASSIGNED; public: // Constructor inheritance doesn't work in solaris // for template class X: T {...}; // // ```using Base_type::Base_type;``` // // Using template constructor instead: template explicit XMessage_encoder_base(Args &&...args) : Base_type(std::forward(args)...) {} void encode_compact_metadata(const uint8_t type, const uint8_t org_type, const uint64_t *collation, const uint32_t *decimals, const uint32_t *length, const uint32_t *flags, const uint32_t *content_type, const uint32_t *org_flags) { using Tags = tags::ColumnMetaData; /// The buffer size should large enough. auto xmsg_start = Base_type::template begin_xmessage(); Base_type::template encode_field_enum(type); Base_type::template encode_field_enum(org_type); Base_type::template encode_optional_field_var_uint64( collation); Base_type::template encode_optional_field_var_uint32< Tags::fractional_digits>(decimals); Base_type::template encode_optional_field_var_uint32(length); Base_type::template encode_optional_field_var_uint32(flags); Base_type::template encode_optional_field_var_uint32( content_type); Base_type::template encode_optional_field_var_uint32( org_flags); 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 uint8_t org_type, const uint64_t *collation, const uint32_t *decimals, const uint32_t *length, const uint32_t *flags, const uint32_t *content_type, const uint32_t *org_flags) { using Tags = tags::ColumnMetaData; /// The buffer size should large enough. auto xmsg_start = Base_type::template begin_xmessage(); Base_type::template encode_field_enum(type); Base_type::template encode_field_enum(org_type); Base_type::template encode_optional_field_var_uint64( collation); Base_type::template encode_optional_field_var_uint32< Tags::fractional_digits>(decimals); Base_type::template encode_optional_field_var_uint32(length); Base_type::template encode_optional_field_var_uint32(flags); Base_type::template encode_optional_field_var_uint32( content_type); Base_type::template encode_optional_field_var_uint32( org_flags); /// following will check buffer size Base_type::template encode_field_string(col_name); Base_type::template encode_field_string(org_col_name); Base_type::template encode_field_string(table_name); Base_type::template encode_field_string( org_table_name); Base_type::template encode_field_string(db_name); Base_type::template encode_field_string(catalog); 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 should large enough. auto xmsg_start = Base_type::template begin_xmessage(); Base_type::template encode_field_const_var_uint(); Base_type::template encode_field_const_enum(); auto field_payload_start = Base_type::template begin_delimited_field(); Base_type::template encode_field_const_enum(); auto field_value_start = Base_type::template begin_delimited_field(); Base_type::template encode_field_const_enum(); Base_type::template encode_field_var_uint64( 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 should large enough. auto xmsg_start = Base_type::template begin_xmessage(); Base_type::template encode_field_const_var_uint(); Base_type::template encode_field_const_enum(); auto field_payload_start = Base_type::template begin_delimited_field(); Base_type::template encode_field_const_enum(); auto field_value_start = Base_type::template begin_delimited_field(); Base_type::template encode_field_const_enum(); Base_type::template encode_field_var_uint64(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 should large enough. auto xmsg_start = Base_type::template begin_xmessage(); Base_type::template encode_field_const_var_uint(); Base_type::template encode_field_const_enum(); auto field_payload_start = Base_type::template begin_delimited_field(); Base_type::template encode_field_const_enum(); 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 should large enough. auto xmsg_start = Base_type::template begin_xmessage(); Base_type::template encode_field_const_var_uint(); Base_type::template encode_field_const_enum(); auto field_payload_start = Base_type::template begin_delimited_field(); Base_type::template encode_field_const_enum(); auto field_value_start = Base_type::template begin_delimited_field(); Base_type::template encode_field_const_enum(); Base_type::template encode_field_var_uint64( 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 should large enough. auto xmsg_start = Base_type::template begin_xmessage(); Base_type::template encode_field_const_var_uint(); Base_type::template encode_field_const_enum(); auto field_payload_start = Base_type::template begin_delimited_field(); Base_type::template encode_field_const_enum(); auto field_value_start = Base_type::template begin_delimited_field(); Base_type::template encode_field_const_enum(); auto string_start = Base_type::template begin_delimited_field(); Base_type::template encode_field_string(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 should large enough. auto xmsg_start = Base_type::template begin_xmessage(); Base_type::template encode_field_var_uint32(type); Base_type::template encode_field_enum(scope); Base_type::template encode_field_string(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 should large enough. auto xmsg_start = Base_type::template begin_xmessage(); Base_type::template encode_field_var_uint32(type); Base_type::template encode_field_string(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(); } void encode_fetch_done() { Base_type::template empty_xmessage(); } void encode_token_done() { Base_type::template empty_xmessage(); } void encode_stmt_execute_ok() { Base_type::template empty_xmessage(); } void encode_ok() { Base_type::template empty_xmessage(); } void encode_ok(const std::string &message) { auto xmsg_start = Base_type::template begin_xmessage(); Base_type::template encode_field_string(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(); Base_type::template encode_field_enum(severity); Base_type::template encode_field_var_uint32(code); Base_type::template encode_field_string(msg); Base_type::template encode_field_string(sql_state); Base_type::end_xmessage(xmsg_start); } template void encode_xmessage(const std::string &serialized_xmessage) { auto xmsg_start = Base_type::template begin_xmessage(); Base_type::encode_raw( reinterpret_cast(serialized_xmessage.c_str()), serialized_xmessage.length()); Base_type::end_xmessage(xmsg_start); } template void encode_protobuf_message(const ProtoMsg &message) { std::string out_serialized; message.SerializeToString(&out_serialized); encode_xmessage(out_serialized); } }; class PolarX_Message_encoder : public XMessage_encoder_base { public: using XMessage_encoder_base::XMessage_encoder_base; }; } // namespace protocol