diff options
author | hcpp <hcpp@ydb.tech> | 2023-11-08 12:09:41 +0300 |
---|---|---|
committer | hcpp <hcpp@ydb.tech> | 2023-11-08 12:56:14 +0300 |
commit | a361f5b98b98b44ea510d274f6769164640dd5e1 (patch) | |
tree | c47c80962c6e2e7b06798238752fd3da0191a3f6 /contrib/libs/libmysql_r/libbinlogevents | |
parent | 9478806fde1f4d40bd5a45e7cbe77237dab613e9 (diff) | |
download | ydb-a361f5b98b98b44ea510d274f6769164640dd5e1.tar.gz |
metrics have been added
Diffstat (limited to 'contrib/libs/libmysql_r/libbinlogevents')
15 files changed, 6121 insertions, 0 deletions
diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/binlog_config-linux.h b/contrib/libs/libmysql_r/libbinlogevents/include/binlog_config-linux.h new file mode 100644 index 0000000000..f490623d4e --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/binlog_config-linux.h @@ -0,0 +1,34 @@ +/** + Copyright (c) 2014, 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 BAPI_CONFIG_INCLUDED +#define BAPI_CONFIG_INCLUDED +/* Symbols we may use */ +/* #undef IS_BIG_ENDIAN */ +#define HAVE_LE64TOH 1 +#define HAVE_LE32TOH 1 +#define HAVE_LE16TOH 1 +#define HAVE_STRNDUP 1 +#define HAVE_ENDIAN_CONVERSION_MACROS 1 + +#endif diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/binlog_config-osx.h b/contrib/libs/libmysql_r/libbinlogevents/include/binlog_config-osx.h new file mode 100644 index 0000000000..d6aea3ef00 --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/binlog_config-osx.h @@ -0,0 +1,34 @@ +/** + Copyright (c) 2014, 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 BAPI_CONFIG_INCLUDED +#define BAPI_CONFIG_INCLUDED +/* Symbols we may use */ +/* #undef IS_BIG_ENDIAN */ +/* #undef HAVE_LE64TOH */ +/* #undef HAVE_LE32TOH */ +/* #undef HAVE_LE16TOH */ +#define HAVE_STRNDUP 1 +/* #undef HAVE_ENDIAN_CONVERSION_MACROS */ + +#endif diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/binlog_config-win.h b/contrib/libs/libmysql_r/libbinlogevents/include/binlog_config-win.h new file mode 100644 index 0000000000..346f370ebd --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/binlog_config-win.h @@ -0,0 +1,34 @@ +/** + Copyright (c) 2014, 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 BAPI_CONFIG_INCLUDED +#define BAPI_CONFIG_INCLUDED +/* Symbols we may use */ +/* #undef IS_BIG_ENDIAN */ +/* #undef HAVE_LE64TOH */ +/* #undef HAVE_LE32TOH */ +/* #undef HAVE_LE16TOH */ +/* #undef HAVE_STRNDUP */ +/* #undef HAVE_ENDIAN_CONVERSION_MACROS */ + +#endif diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/binlog_config.h b/contrib/libs/libmysql_r/libbinlogevents/include/binlog_config.h new file mode 100644 index 0000000000..eef995ed74 --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/binlog_config.h @@ -0,0 +1,13 @@ +#pragma once + +#if defined(__linux__) +#include "binlog_config-linux.h" +#endif + +#if defined(__APPLE__) +#include "binlog_config-osx.h" +#endif + +#if defined(_MSC_VER) +#include "binlog_config-win.h" +#endif diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/binlog_event.h b/contrib/libs/libmysql_r/libbinlogevents/include/binlog_event.h new file mode 100644 index 0000000000..e14a08ef3d --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/binlog_event.h @@ -0,0 +1,940 @@ +/* Copyright (c) 2011, 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 */ + +/** + @addtogroup Replication + @{ + + @file binlog_event.h + + @brief Contains the classes representing events occurring in the replication + stream. Each event is represented as a byte sequence with logical divisions + as event header, event specific data and event footer. The header and footer + are common to all the events and are represented as two different subclasses. +*/ + +#ifndef BINLOG_EVENT_INCLUDED +#define BINLOG_EVENT_INCLUDED + +#include <stdlib.h> +#include <sys/types.h> +#include <zlib.h> //for checksum calculations +#include <climits> +#include <cstdio> +#include <iostream> + +#include "debug_vars.h" +#include "event_reader.h" +#include "my_io.h" + +#if defined(_WIN32) +#include <Winsock2.h> +#else +#include <sys/times.h> +#endif +/* + The symbols below are a part of the common definitions between + the MySQL server and the client. Since they should not be a part of + this library but the server, these should be placed in a header file + common to the library and the MySQL server code, so that if they are + updated in the server code, it is reflected in the libbinlogevent also. + + TODO(WL#7984): Moving the binlog constant in library libbinlogevents into a + separate file and make them const variables +*/ +#ifndef SYSTEM_CHARSET_MBMAXLEN +#define SYSTEM_CHARSET_MBMAXLEN 3 +#endif +#ifndef NAME_CHAR_LEN +#define NAME_CHAR_LEN 64 /* Field/table name length */ +#endif +#ifndef NAME_LEN +#define NAME_LEN (NAME_CHAR_LEN * SYSTEM_CHARSET_MBMAXLEN) +#endif +/* Length of the server_version_split array in FDE class */ +#ifndef ST_SERVER_VER_SPLIT_LEN +#define ST_SERVER_VER_SPLIT_LEN 3 +#endif + +/* + Do not decrease the value of BIN_LOG_HEADER_SIZE. + Do not even increase it before checking code. +*/ +#ifndef BIN_LOG_HEADER_SIZE +#define BIN_LOG_HEADER_SIZE 4U +#endif + +/** + binlog_version 3 is MySQL 4.x; 4 is MySQL 5.0.0. + Compared to version 3, version 4 has: + - a different Start_event, which includes info about the binary log + (sizes of headers); this info is included for better compatibility if the + master's MySQL version is different from the slave's. +*/ +#define BINLOG_VERSION 4 + +/* + Constants used by Query_event. +*/ + +/** + The maximum number of updated databases that a status of + Query-log-event can carry. It can be redefined within a range + [1.. OVER_MAX_DBS_IN_EVENT_MTS]. +*/ +#define MAX_DBS_IN_EVENT_MTS 16 + +/** + When the actual number of databases exceeds MAX_DBS_IN_EVENT_MTS + the value of OVER_MAX_DBS_IN_EVENT_MTS is is put into the + mts_accessed_dbs status. +*/ +#define OVER_MAX_DBS_IN_EVENT_MTS 254 + +/** + Max number of possible extra bytes in a replication event compared to a + packet (i.e. a query) sent from client to master; + First, an auxiliary log_event status vars estimation: +*/ +#define MAX_SIZE_LOG_EVENT_STATUS \ + (1U + 4 /* type, flags2 */ + 1U + 8 /* type, sql_mode */ + 1U + 1 + \ + 255 /* type, length, catalog */ + 1U + 4 /* type, auto_increment */ + 1U + \ + 6 /* type, charset */ + 1U + 1 + 255 /* type, length, time_zone */ + 1U + \ + 2 /* type, lc_time_names_number */ + 1U + \ + 2 /* type, charset_database_number */ + 1U + \ + 8 /* type, table_map_for_update */ + 1U + \ + 4 /* type, master_data_written */ + /* type, db_1, db_2, ... */ \ + 1U + (MAX_DBS_IN_EVENT_MTS * (1 + NAME_LEN)) + 3U + \ + /* type, microseconds */ +1U + 32 * 3 + /* type, user_len, user */ \ + 1 + 255 /* host_len, host */ + 1U + 1 /* type, explicit_def..ts*/ + 1U + \ + 8 /* type, xid of DDL */ + 1U + \ + 2 /* type, default_collation_for_utf8mb4_number */ + \ + 1 /* sql_require_primary_key */ + 1 /* type, default_table_encryption */) + +/** + Uninitialized timestamp value (for either last committed or sequence number). + Often carries meaning of the minimum value in the logical timestamp domain. +*/ +const int64_t SEQ_UNINIT = 0; + +/** We use 7 bytes, 1 bit being used as a flag. */ +#define MAX_COMMIT_TIMESTAMP_VALUE (1ULL << 55) +/** + Used to determine whether the original_commit_timestamp is already known or if + it still needs to be determined when computing it. +*/ +const int64_t UNDEFINED_COMMIT_TIMESTAMP = MAX_COMMIT_TIMESTAMP_VALUE; + +const uint32_t UNDEFINED_SERVER_VERSION = 999999; +const uint32_t UNKNOWN_SERVER_VERSION = 0; + +/** Setting this flag will mark an event as Ignorable */ +#define LOG_EVENT_IGNORABLE_F 0x80 + +/** + In case the variable is updated, + make sure to update it in $MYSQL_SOURCE_DIR/my_io.h. +*/ +#ifndef FN_REFLEN +#define FN_REFLEN 512 /* Max length of full path-name */ +#endif + +/** + Splits server 'version' string into three numeric pieces stored + into 'split_versions': + X.Y.Zabc (X,Y,Z numbers, a not a digit) -> {X,Y,Z} + X.Yabc -> {X,Y,0} + + @param version String representing server version + @param split_versions Array with each element containing one split of the + input version string +*/ +inline void do_server_version_split(const char *version, + unsigned char split_versions[3]) { + const char *p = version; + char *r; + unsigned long number; + for (unsigned int i = 0; i <= 2; i++) { + number = strtoul(p, &r, 10); + /* + It is an invalid version if any version number greater than 255 or + first number is not followed by '.'. + */ + if (number < 256 && (*r == '.' || i != 0)) + split_versions[i] = static_cast<unsigned char>(number); + else { + split_versions[0] = 0; + split_versions[1] = 0; + split_versions[2] = 0; + break; + } + + p = r; + if (*r == '.') p++; // skip the dot + } +} + +/** + Transforms the server version from 'XX.YY.ZZ-suffix' into an integer in the + format XXYYZZ. + + @param version String representing server version + @return The server version in the format XXYYZZ +*/ +inline uint32_t do_server_version_int(const char *version) { + unsigned char version_split[3]; + do_server_version_split(version, version_split); + uint32_t ret = static_cast<uint32_t>(version_split[0]) * 10000 + + static_cast<uint32_t>(version_split[1]) * 100 + + static_cast<uint32_t>(version_split[2]); + return ret; +} + +/** + Calculate the version product from the numeric pieces representing the server + version: + For a server version X.Y.Zabc (X,Y,Z numbers, a not a digit), the input is + {X,Y,Z}. This is converted to XYZ in bit representation. + + @param version_split Array containing the version information of the server + @return The version product of the server +*/ +inline unsigned long version_product(const unsigned char *version_split) { + return ((version_split[0] * 256 + version_split[1]) * 256 + version_split[2]); +} + +/** + Replication event checksum is introduced in the following "checksum-home" + version. The checksum-aware servers extract FD's version to decide whether + the FD event carries checksum info. +*/ +extern const unsigned char checksum_version_split[3]; +extern const unsigned long checksum_version_product; +/** + @namespace binary_log + + The namespace contains classes representing events that can occur in a + replication stream. +*/ +namespace binary_log { +/* + This flag only makes sense for Format_description_event. It is set + when the event is written, and *reset* when a binlog file is + closed (yes, it's the only case when MySQL modifies an already written + part of the binlog). Thus it is a reliable indicator that the binlog was + closed correctly. (Stop_event is not enough, there's always a + small chance that mysqld crashes in the middle of insert and end of + the binlog would look like a Stop_event). + + This flag is used to detect a restart after a crash, and to provide + "unbreakable" binlog. The problem is that on a crash storage engines + rollback automatically, while binlog does not. To solve this we use this + flag and automatically append ROLLBACK to every non-closed binlog (append + virtually, on reading, file itself is not changed). If this flag is found, + mysqlbinlog simply prints "ROLLBACK". Replication master does not abort on + binlog corruption, but takes it as EOF, and replication slave forces a + rollback in this case. + + Note, that old binlogs does not have this flag set, so we get a + a backward-compatible behaviour. +*/ +#define LOG_EVENT_BINLOG_IN_USE_F 0x1 + +/** + Enumeration type for the different types of log events. +*/ +enum Log_event_type { + /** + Every time you add a type, you have to + - Assign it a number explicitly. Otherwise it will cause trouble + if a event type before is deprecated and removed directly from + the enum. + - Fix Format_description_event::Format_description_event(). + */ + UNKNOWN_EVENT = 0, + /* + Deprecated since mysql 8.0.2. It is just a placeholder, + should not be used anywhere else. + */ + START_EVENT_V3 = 1, + QUERY_EVENT = 2, + STOP_EVENT = 3, + ROTATE_EVENT = 4, + INTVAR_EVENT = 5, + + SLAVE_EVENT = 7, + + APPEND_BLOCK_EVENT = 9, + DELETE_FILE_EVENT = 11, + + RAND_EVENT = 13, + USER_VAR_EVENT = 14, + FORMAT_DESCRIPTION_EVENT = 15, + XID_EVENT = 16, + BEGIN_LOAD_QUERY_EVENT = 17, + EXECUTE_LOAD_QUERY_EVENT = 18, + + TABLE_MAP_EVENT = 19, + + /** + The V1 event numbers are used from 5.1.16 until mysql-5.6. + */ + WRITE_ROWS_EVENT_V1 = 23, + UPDATE_ROWS_EVENT_V1 = 24, + DELETE_ROWS_EVENT_V1 = 25, + + /** + Something out of the ordinary happened on the master + */ + INCIDENT_EVENT = 26, + + /** + Heartbeat event to be send by master at its idle time + to ensure master's online status to slave + */ + HEARTBEAT_LOG_EVENT = 27, + + /** + In some situations, it is necessary to send over ignorable + data to the slave: data that a slave can handle in case there + is code for handling it, but which can be ignored if it is not + recognized. + */ + IGNORABLE_LOG_EVENT = 28, + ROWS_QUERY_LOG_EVENT = 29, + + /** Version 2 of the Row events */ + WRITE_ROWS_EVENT = 30, + UPDATE_ROWS_EVENT = 31, + DELETE_ROWS_EVENT = 32, + + GTID_LOG_EVENT = 33, + ANONYMOUS_GTID_LOG_EVENT = 34, + + PREVIOUS_GTIDS_LOG_EVENT = 35, + + TRANSACTION_CONTEXT_EVENT = 36, + + VIEW_CHANGE_EVENT = 37, + + /* Prepared XA transaction terminal event similar to Xid */ + XA_PREPARE_LOG_EVENT = 38, + + /** + Extension of UPDATE_ROWS_EVENT, allowing partial values according + to binlog_row_value_options. + */ + PARTIAL_UPDATE_ROWS_EVENT = 39, + + /** + Add new events here - right above this comment! + Existing events (except ENUM_END_EVENT) should never change their numbers + */ + ENUM_END_EVENT /* end marker */ +}; + +/** + The length of the array server_version, which is used to store the version + of MySQL server. + We could have used SERVER_VERSION_LENGTH, but this introduces an + obscure dependency - if somebody decided to change SERVER_VERSION_LENGTH + this would break the replication protocol + both of these are used to initialize the array server_version + SERVER_VERSION_LENGTH is used for global array server_version + and ST_SERVER_VER_LEN for the Start_event_v3 member server_version +*/ + +#define ST_SERVER_VER_LEN 50 + +/* + Event header offsets; + these point to places inside the fixed header. +*/ +#define EVENT_TYPE_OFFSET 4 +#define SERVER_ID_OFFSET 5 +#define EVENT_LEN_OFFSET 9 +#define LOG_POS_OFFSET 13 +#define FLAGS_OFFSET 17 + +/** start event post-header (for v3 and v4) */ +#define ST_BINLOG_VER_OFFSET 0 +#define ST_SERVER_VER_OFFSET 2 +#define ST_CREATED_OFFSET (ST_SERVER_VER_OFFSET + ST_SERVER_VER_LEN) +#define ST_COMMON_HEADER_LEN_OFFSET (ST_CREATED_OFFSET + 4) + +#define LOG_EVENT_HEADER_LEN 19U /* the fixed header length */ + +/** + Fixed header length, where 4.x and 5.0 agree. That is, 5.0 may have a longer + header (it will for sure when we have the unique event's ID), but at least + the first 19 bytes are the same in 4.x and 5.0. So when we have the unique + event's ID, LOG_EVENT_HEADER_LEN will be something like 26, but + LOG_EVENT_MINIMAL_HEADER_LEN will remain 19. +*/ +#define LOG_EVENT_MINIMAL_HEADER_LEN 19U + +/** + Enumeration spcifying checksum algorithm used to encode a binary log event +*/ +enum enum_binlog_checksum_alg { + /** + Events are without checksum though its generator is checksum-capable + New Master (NM). + */ + BINLOG_CHECKSUM_ALG_OFF = 0, + /** CRC32 of zlib algorithm */ + BINLOG_CHECKSUM_ALG_CRC32 = 1, + /** the cut line: valid alg range is [1, 0x7f] */ + BINLOG_CHECKSUM_ALG_ENUM_END, + /** + Special value to tag undetermined yet checksum or events from + checksum-unaware servers + */ + BINLOG_CHECKSUM_ALG_UNDEF = 255 +}; + +#define CHECKSUM_CRC32_SIGNATURE_LEN 4 + +/** + defined statically while there is just one alg implemented +*/ +#define BINLOG_CHECKSUM_LEN CHECKSUM_CRC32_SIGNATURE_LEN +#define BINLOG_CHECKSUM_ALG_DESC_LEN 1 /* 1 byte checksum alg descriptor */ +#define LOG_EVENT_HEADER_SIZE 20 + +/** + Calculate a long checksum for a memoryblock. + + @param crc start value for crc + @param pos pointer to memory block + @param length length of the block + + @return checksum for a memory block +*/ +inline uint32_t checksum_crc32(uint32_t crc, const unsigned char *pos, + size_t length) { + BAPI_ASSERT(length <= UINT_MAX); + return static_cast<uint32_t>(crc32(static_cast<unsigned int>(crc), pos, + static_cast<unsigned int>(length))); +} + +/* + Forward declaration of Format_description_event class to be used in class + Log_event_header +*/ +class Format_description_event; + +/** + @class Log_event_footer + + The footer, in the current version of the MySQL server, only contains + the checksum algorithm descriptor. The descriptor is contained in the + FDE of the binary log. This is common for all the events contained in + that binary log, and defines the algorithm used to checksum + the events contained in the binary log. + + @anchor Table_common_footer + The footer contains the following: + <table> + <caption>Common-Footer</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>checkusm_alg</td> + <td>enum_checksum_alg</td> + <td>Algorithm used to checksum the events contained in the binary log</td> + </tr> + + </table> + + @note checksum *value* is not generated with the event. On master's side, it + is calculated right before writing the event into the binary log. The + data_written field of the event is adjusted (+BINLOG_CHECKSUM_LEN) to + consider the checksum value as part of the event. On reading the event, + if the Format Description Event (FDE) used when serializing the event + tells that the events have checksum information, the checksum value can + be retrieved from a particular offset of the serialized event buffer + (event length - BINLOG_CHECKSUM_LEN) and checked for corruption by + computing a new value over the event buffer. It is not required after + that. Therefore, the checksum value is not required to be stored in the + instance as a class member. +*/ +class Log_event_footer { + public: + /** + Wrapper to call get_checksum_alg(const char *, ulong) function based on the + event reader object (which knows both buffer and buffer length). + + @param[in] reader The Event_reader object associated to the event buffer + of the FD event. + + @retval BINLOG_CHECKSUM_ALG_UNDEF originator is checksum-unaware + (effectively no checksum). + @retval BINLOG_CHECKSUM_ALG_OFF no checksum. + @retval other the actual checksum algorithm descriptor. + */ + static enum_binlog_checksum_alg get_checksum_alg(Event_reader &reader); + + /** + The method returns the checksum algorithm used to checksum the binary log + from a Format Description Event serialized buffer. + + For MySQL server versions < 5.6, the algorithm is undefined. + + @param buf buffer holding serialized FD event. + @param len length of the event buffer. + + @retval BINLOG_CHECKSUM_ALG_UNDEF originator is checksum-unaware + (effectively no checksum). + @retval BINLOG_CHECKSUM_ALG_OFF no checksum. + @retval other the actual checksum algorithm descriptor. + */ + static enum_binlog_checksum_alg get_checksum_alg(const char *buf, + unsigned long len); + + static bool event_checksum_test(unsigned char *buf, unsigned long event_len, + enum_binlog_checksum_alg alg); + + /* Constructors */ + Log_event_footer() : checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF) {} + + /** + This ctor will create a new object of Log_event_footer, and will adjust + the event reader buffer size with respect to CRC usage. + + @param reader the Event_reader containing the serialized event (including + header, event data and optional checksum information). + @param event_type the type of the event the footer belongs to. + @param fde An FDE event, used to get information about CRC. + */ + Log_event_footer(Event_reader &reader, Log_event_type event_type, + const Format_description_event *fde); + + explicit Log_event_footer(enum_binlog_checksum_alg checksum_alg_arg) + : checksum_alg(checksum_alg_arg) {} + + /** + @verbatim + Master side: + The value is set by caller of FD(Format Description) constructor + In the FD case it's propagated into the last byte + of post_header_len[]. + Slave side: + On the slave side the value is assigned from post_header_len[last] + of the last seen FD event. + @endverbatim + TODO(WL#7546): Revisit this comment when encoder is moved in libbinlogevent + */ + enum_binlog_checksum_alg checksum_alg; +}; + +/** + @class Log_event_header + + The Common-Header always has the same form and length within one + version of MySQL. Each event type specifies a format and length + of the Post-Header. The length of the Common-Header is the same + for all events of the same type. + + @anchor Table_common_header + The binary format of Common-Header is as follows: + <table> + <caption>Common-Header</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>when</td> + <td>4 byte unsigned integer, represented by type struct timeval</td> + <td>The time when the query started, in seconds since 1970. + </td> + </tr> + + <tr> + <td>type_code</td> + <td>1 byte enumeration</td> + <td>See enum #Log_event_type.</td> + </tr> + + <tr> + <td>unmasked_server_id</td> + <td>4 byte unsigned integer</td> + <td>Server ID of the server that created the event.</td> + </tr> + + <tr> + <td>data_written</td> + <td>4 byte unsigned integer</td> + <td>The total size of this event, in bytes. In other words, this + is the sum of the sizes of Common-Header, Post-Header, and Body. + </td> + </tr> + + <tr> + <td>log_pos</td> + <td>4 byte unsigned integer</td> + <td>The position of the next event in the master binary log, in + bytes from the beginning of the file. In a binlog that is not a + relay log, this is just the position of the next event, in bytes + from the beginning of the file. In a relay log, this is + the position of the next event in the master's binlog. + </td> + </tr> + + <tr> + <td>flags</td> + <td>2 byte bitfield</td> + <td>16 or less flags depending on the version of the binary log.</td> + </tr> + </table> + + Summing up the numbers above, we see that the total size of the + common header is 19 bytes. +*/ +class Log_event_header { + public: + /* + Timestamp on the master(for debugging and replication of + NOW()/TIMESTAMP). It is important for queries and LOAD DATA + INFILE. This is set at the event's creation time, except for Query + and Load (and other events) events where this is set at the query's + execution time, which guarantees good replication (otherwise, we + could have a query and its event with different timestamps). + */ + struct timeval when; + + /** + Event type extracted from the header. In the server, it is decoded + by read_log_event(), but adding here for complete decoding. + */ + Log_event_type type_code; + + /* + The server id read from the Binlog. + */ + unsigned int unmasked_server_id; + + /* Length of an event, which will be written by write() function */ + size_t data_written; + + /* + The offset in the log where this event originally appeared (it is + preserved in relay logs, making SHOW SLAVE STATUS able to print + coordinates of the event in the master's binlog). + */ + unsigned long long log_pos; + + /* + 16 or less flags depending on the version of the binary log. + See the definitions above for LOG_EVENT_TIME_F, + LOG_EVENT_FORCED_ROTATE_F, LOG_EVENT_THREAD_SPECIFIC_F, and + LOG_EVENT_SUPPRESS_USE_F for notes. + */ + uint16_t flags; + + /** + The following type definition is to be used whenever data is placed + and manipulated in a common buffer. Use this typedef for buffers + that contain data containing binary and character data. + */ + typedef unsigned char Byte; + + explicit Log_event_header(Log_event_type type_code_arg = ENUM_END_EVENT) + : type_code(type_code_arg), data_written(0), log_pos(0), flags(0) { + when.tv_sec = 0; + when.tv_usec = 0; + } + /** + Log_event_header constructor. + + @param reader the Event_reader containing the serialized event (including + header, event data and optional checksum information). + */ + Log_event_header(Event_reader &reader); + + /** + The get_is_valid function is related to event specific sanity checks to + determine that the object was initialized without errors. + + Note that a given event object may be valid at some point (ancestor + event type initialization was fine) but be turned invalid in a later + stage. + + @return True if the event object is valid, false otherwise. + */ + + bool get_is_valid() { return m_is_valid; } + + /** + Set if the event object shall be considered valid or not. + + @param is_valid if the event object shall be considered valid. + */ + + void set_is_valid(bool is_valid) { m_is_valid = is_valid; } + + private: + /* + As errors might happen when de-serializing events, the m_is_valid variable + will hold information about the validity of the event. + + An invalid event shall never be applied/dumped/displayed, as its + interpretation (accessing its contents) might lead to using invalid + memory pointers. + */ + bool m_is_valid; +}; + +/** + This is the abstract base class for binary log events. + + @section Binary_log_event_binary_format Binary Format + + @anchor Binary_log_event_format + Any @c Binary_log_event saved on disk consists of the following four + components. + + - Common-Header + - Post-Header + - Body + - Footer + + Common header has the same format and length in a given MySQL version. It is + documented @ref Table_common_header "here". + + The Body may be of different format and length even for different events of + the same type. The binary formats of Post-Header and Body are documented + separately in each subclass. + + Footer is common to all the events in a given MySQL version. It is documented + @ref Table_common_footer "here". + + @anchor packed_integer + - Some events, used for RBR use a special format for efficient representation + of unsigned integers, called Packed Integer. A Packed Integer has the + capacity of storing up to 8-byte integers, while small integers + still can use 1, 3, or 4 bytes. The value of the first byte + determines how to read the number, according to the following table: + + <table> + <caption>Format of Packed Integer</caption> + + <tr> + <th>First byte</th> + <th>Format</th> + </tr> + + <tr> + <td>0-250</td> + <td>The first byte is the number (in the range 0-250), and no more + bytes are used.</td> + </tr> + + <tr> + <td>252</td> + <td>Two more bytes are used. The number is in the range + 251-0xffff.</td> + </tr> + + <tr> + <td>253</td> + <td>Three more bytes are used. The number is in the range + 0xffff-0xffffff.</td> + </tr> + + <tr> + <td>254</td> + <td>Eight more bytes are used. The number is in the range + 0xffffff-0xffffffffffffffff.</td> + </tr> + + </table> + + - Strings are stored in various formats. The format of each string + is documented separately. + +*/ +class Binary_log_event { + public: + /* + The number of types we handle in Format_description_event (UNKNOWN_EVENT + is not to be handled, it does not exist in binlogs, it does not have a + format). + */ + static const int LOG_EVENT_TYPES = (ENUM_END_EVENT - 1); + + /** + The lengths for the fixed data part of each event. + This is an enum that provides post-header lengths for all events. + */ + enum enum_post_header_length { + // where 3.23, 4.x and 5.0 agree + QUERY_HEADER_MINIMAL_LEN = (4 + 4 + 1 + 2), + // where 5.0 differs: 2 for length of N-bytes vars. + QUERY_HEADER_LEN = (QUERY_HEADER_MINIMAL_LEN + 2), + STOP_HEADER_LEN = 0, + START_V3_HEADER_LEN = (2 + ST_SERVER_VER_LEN + 4), + // this is FROZEN (the Rotate post-header is frozen) + ROTATE_HEADER_LEN = 8, + INTVAR_HEADER_LEN = 0, + APPEND_BLOCK_HEADER_LEN = 4, + DELETE_FILE_HEADER_LEN = 4, + RAND_HEADER_LEN = 0, + USER_VAR_HEADER_LEN = 0, + FORMAT_DESCRIPTION_HEADER_LEN = (START_V3_HEADER_LEN + 1 + LOG_EVENT_TYPES), + XID_HEADER_LEN = 0, + BEGIN_LOAD_QUERY_HEADER_LEN = APPEND_BLOCK_HEADER_LEN, + ROWS_HEADER_LEN_V1 = 8, + TABLE_MAP_HEADER_LEN = 8, + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN = (4 + 4 + 4 + 1), + EXECUTE_LOAD_QUERY_HEADER_LEN = + (QUERY_HEADER_LEN + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN), + INCIDENT_HEADER_LEN = 2, + HEARTBEAT_HEADER_LEN = 0, + IGNORABLE_HEADER_LEN = 0, + ROWS_HEADER_LEN_V2 = 10, + TRANSACTION_CONTEXT_HEADER_LEN = 18, + VIEW_CHANGE_HEADER_LEN = 52, + XA_PREPARE_HEADER_LEN = 0 + }; // end enum_post_header_length + protected: + /** + This constructor is used to initialize the type_code of header object + m_header. + We set the type code to ENUM_END_EVENT so that the decoder + asserts if event type has not been modified by the sub classes + */ + explicit Binary_log_event(Log_event_type type_code) + : m_reader(nullptr, 0), m_header(type_code) {} + + /** + This constructor will create a new object of Log_event_header and initialize + the variable m_header, which in turn will be used to initialize Log_event's + member common_header. + It will also advance the Event_reader cursor after decoding the header (it + is done through the constructor of Log_event_header) and will be pointing to + the start of event data. + + @param buf Contains the serialized event. + @param fde An FDE event used to get checksum information of non FDE events. + */ + Binary_log_event(const char **buf, const Format_description_event *fde); + + public: +#ifndef HAVE_MYSYS + /* + The print_event_info functions are used in the free standing version of + the library only. Since MySQL server does not use them, and it does not + link to standard input/output library on Windows 32 bit system ,these + methods are commented out when the library(libbinlogevents) is built + with the server. + */ + /** + Returns short information about the event + */ + virtual void print_event_info(std::ostream &info) = 0; + /** + Returns detailed information about the event + */ + virtual void print_long_info(std::ostream &info) = 0; +#endif + virtual ~Binary_log_event() = 0; + + Binary_log_event(const Binary_log_event &) = default; + Binary_log_event(Binary_log_event &&) = default; + Binary_log_event &operator=(const Binary_log_event &) = default; + Binary_log_event &operator=(Binary_log_event &&) = default; + + /** + * Helper method + */ + enum Log_event_type get_event_type() const { return m_header.type_code; } + + /** + Return a const pointer to the header of the log event + */ + const Log_event_header *header() const { return &m_header; } + /** + Return a non-const pointer to the header of the log event + */ + Log_event_header *header() { return &m_header; } + /** + Return a const pointer to the footer of the log event + */ + const Log_event_footer *footer() const { return &m_footer; } + /** + Return a non-const pointer to the footer of the log event + */ + Log_event_footer *footer() { return &m_footer; } + /** + Returns a reference to the event Event_reader object. + */ + Event_reader &reader() { return m_reader; } + + private: + /* + All the accesses to the event buffer shall be performed by using m_reader + methods. + */ + Event_reader m_reader; + Log_event_header m_header; + Log_event_footer m_footer; +}; + +/** + @class Unknown_event + + An unknown event should never occur. It is never written to a binary log. + If an event is read from a binary log that cannot be recognized as + something else, it is treated as UNKNOWN_EVENT. + + The Post-Header and Body for this event type are empty; it only has + the Common-Header. +*/ +class Unknown_event : public Binary_log_event { + public: + /** + This is the minimal constructor, and set the type_code as + UNKNOWN_EVENT in the header object in Binary_log_event + */ + Unknown_event() : Binary_log_event(UNKNOWN_EVENT) {} + + Unknown_event(const char *buf, const Format_description_event *fde); +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &info); + void print_long_info(std::ostream &info); +#endif +}; +} // end namespace binary_log +/** + @} (end of group Replication) +*/ +#endif /* BINLOG_EVENT_INCLUDED */ diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/byteorder.h b/contrib/libs/libmysql_r/libbinlogevents/include/byteorder.h new file mode 100644 index 0000000000..d0223899c8 --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/byteorder.h @@ -0,0 +1,121 @@ +/* Copyright (c) 2014, 2016, 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 */ + +/** + @file libbinlogevents/include/byteorder.h + + @brief The file contains functions to convert the byte encoding of integer + values to and from little-endian and big-endian byte order. +*/ + +#ifndef BYTEORDER_INCLUDED +#define BYTEORDER_INCLUDED + +#include <stdint.h> +#include "binlog_config.h" +#include "my_compiler.h" +#ifndef STANDALONE_BINLOG +#define HAVE_MYSYS 1 +#endif + +/* + Methods for reading and storing in machine independent + format (low byte first). +*/ + +/* + Checking le16toh is required because the machine may have the header + but the functions might not be defined if the version of glibc < 2.9 +*/ +#ifdef HAVE_ENDIAN_CONVERSION_MACROS +#include <endian.h> +#endif + +#if !defined(le16toh) +/** + Converting a 16 bit integer from little-endian byte order to host byteorder + + @param x 16-bit integer in little endian byte order + @return 16-bit integer in host byte order +*/ +uint16_t inline le16toh(uint16_t x) { +#ifndef IS_BIG_ENDIAN + return x; +#else + return ((x >> 8) | (x << 8)); +#endif +} +#endif + +#if !defined(le32toh) +/** + Converting a 32 bit integer from little-endian byte order to host byteorder + + @param x 32-bit integer in little endian byte order + @return 32-bit integer in host byte order +*/ +uint32_t inline le32toh(uint32_t x) { +#ifndef IS_BIG_ENDIAN + return x; +#else + return (((x >> 24) & 0xff) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | + ((x << 24) & 0xff000000)); +#endif +} +#endif + +#if !defined(be32toh) +/** + Converting a 32 bit integer from big-endian byte order to host byteorder + + @param x 32-bit integer in big endian byte order + @return 32-bit integer in host byte order +*/ +uint32_t inline be32toh(uint32_t x) { +#ifndef IS_BIG_ENDIAN + return (((x >> 24) & 0xff) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | + ((x << 24) & 0xff000000)); +#else + return x; +#endif +} +#endif + +#if !defined(le64toh) +/** + Converting a 64 bit integer from little-endian byte order to host byteorder + + @param x 64-bit integer in little endian byte order + @return 64-bit integer in host byte order +*/ +uint64_t inline le64toh(uint64_t x) { +#ifndef IS_BIG_ENDIAN + return x; +#else + x = ((x << 8) & 0xff00ff00ff00ff00ULL) | ((x >> 8) & 0x00ff00ff00ff00ffULL); + x = ((x << 16) & 0xffff0000ffff0000ULL) | ((x >> 16) & 0x0000ffff0000ffffULL); + return (x << 32) | (x >> 32); +#endif +} +#endif + +#endif // BYTEORDER_INCLUDED diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/control_events.h b/contrib/libs/libmysql_r/libbinlogevents/include/control_events.h new file mode 100644 index 0000000000..88de3b2848 --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/control_events.h @@ -0,0 +1,1292 @@ +/* Copyright (c) 2014, 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 */ + +/** + @addtogroup Replication + @{ + + @file control_events.h + + @brief Contains the classes representing events operating in the replication + stream properties. Each event is represented as a byte sequence with logical + divisions as event header, event specific data and event footer. The header + and footer are common to all the events and are represented as two different + subclasses. +*/ + +#ifndef CONTROL_EVENT_INCLUDED +#define CONTROL_EVENT_INCLUDED + +#include <sys/types.h> +#include <time.h> +#include <list> +#include <map> +#include <vector> + +#include "binlog_event.h" +#include "template_utils.h" +#include "uuid.h" + +namespace binary_log { +/** + @class Rotate_event + + When a binary log file exceeds a size limit, a ROTATE_EVENT is written + at the end of the file that points to the next file in the squence. + This event is information for the slave to know the name of the next + binary log it is going to receive. + + ROTATE_EVENT is generated locally and written to the binary log + on the master. It is written to the relay log on the slave when FLUSH LOGS + occurs, and when receiving a ROTATE_EVENT from the master. + In the latter case, there will be two rotate events in total originating + on different servers. + + @section Rotate_event_binary_format Binary Format + + <table> + <caption>Post-Header for Rotate_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>position</td> + <td>8 byte integer</td> + <td>The position within the binary log to rotate to.</td> + </tr> + + </table> + + The Body has one component: + + <table> + <caption>Body for Rotate_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>new_log_ident</td> + <td>variable length string without trailing zero, extending to the + end of the event (determined by the length field of the + Common-Header) + </td> + <td>Name of the binlog to rotate to.</td> + </tr> + + </table> +*/ +class Rotate_event : public Binary_log_event { + public: + const char *new_log_ident; + size_t ident_len; + unsigned int flags; + uint64_t pos; + + enum { + /* Values taken by the flag member variable */ + DUP_NAME = 2, // if constructor should dup the string argument + RELAY_LOG = 4 // rotate event for the relay log + }; + + enum { + /* Rotate event post_header */ + R_POS_OFFSET = 0, + R_IDENT_OFFSET = 8 + }; + + /** + This is the minimal constructor, it will set the type code as ROTATE_EVENT. + */ + Rotate_event(const char *new_log_ident_arg, size_t ident_len_arg, + unsigned int flags_arg, uint64_t pos_arg) + : Binary_log_event(ROTATE_EVENT), + new_log_ident(new_log_ident_arg), + ident_len(ident_len_arg ? ident_len_arg : strlen(new_log_ident_arg)), + flags(flags_arg), + pos(pos_arg) {} + + /** + The layout of Rotate_event data part is as follows: + + <pre> + +-----------------------------------------------------------------------+ + | common_header | post_header | position of the first event | file name | + +-----------------------------------------------------------------------+ + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event, used to get the following information: + -binlog_version + -server_version + -post_header_len + -common_header_len + The content of this object depends on the binlog-version + currently in use. + */ + Rotate_event(const char *buf, const Format_description_event *fde); + +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &); + void print_long_info(std::ostream &); +#endif + + ~Rotate_event() { + if (flags & DUP_NAME) bapi_free(const_cast<char *>(new_log_ident)); + } +}; + +/** + @class Format_description_event + For binlog version 4. + This event is saved by threads which read it, as they need it for future + use (to decode the ordinary events). + + @section Format_description_event_binary_format Binary Format + + The Post-Header has six components: + + <table> + <caption>Post-Header for Format_description_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>created</td> + <td>4 byte unsigned integer</td> + <td>The creation timestamp, if non-zero, + is the time in seconds when this event was created</td> + </tr> + <tr> + <td>binlog_version</td> + <td>2 byte unsigned integer</td> + <td>This is 1 in MySQL 3.23 and 3 in MySQL 4.0 and 4.1 + (In MySQL 5.0 and up, FORMAT_DESCRIPTION_EVENT is + used instead of START_EVENT_V3 and for them its 4).</td> + </tr> + <tr> + <td>server_version</td> + <td>char array of 50 bytes</td> + <td>The MySQL server's version (example: 4.0.14-debug-log), + padded with 0x00 bytes on the right</td> + </tr> + <tr> + <td>common_header_len</td> + <td>1 byte unsigned integer</td> + <td>The length of the event header. This value includes the extra_headers + field, so this header length - 19 yields the size + of the extra_headers field.</td> + </tr> + <tr> + <td>post_header_len</td> + <td>array of type 1 byte unsigned integer</td> + <td>The lengths for the fixed data part of each event</td> + </tr> + <tr> + <td>server_version_split</td> + <td>unsigned char array</td> + <td>Stores the server version of the server + and splits them in three parts</td> + </tr> + <tr> + <td>number_of_event_types</td> + <td>1 byte unsigned integer</td> + <td>number of event types present in the server</td> + </tr> + </table> +*/ +class Format_description_event : public Binary_log_event { + public: + /** + If this event is at the start of the first binary log since server + startup 'created' should be the timestamp when the event (and the + binary log) was created. In the other case (i.e. this event is at + the start of a binary log created by FLUSH LOGS or automatic + rotation), 'created' should be 0. This "trick" is used by MySQL + >=4.0.14 slaves to know whether they must drop stale temporary + tables and whether they should abort unfinished transaction. + + Note that when 'created'!=0, it is always equal to the event's + timestamp; indeed Format_description_event is written only in binlog.cc + where the first constructor below is called, in which 'created' is set to + 'when'. So in fact 'created' is a useless variable. When it is 0 we can + read the actual value from timestamp ('when') and when it is non-zero we + can read the same value from timestamp + ('when'). Conclusion: + - we use timestamp to print when the binlog was created. + - we use 'created' only to know if this is a first binlog or not. + */ + time_t created; + uint16_t binlog_version; + char server_version[ST_SERVER_VER_LEN]; + /* + We set this to 1 if we don't want to have the created time in the log, + which is the case when we rollover to a new log. + */ + bool dont_set_created; + + /** + The size of the fixed header which _all_ events have + (for binlogs written by this version, this is equal to + LOG_EVENT_HEADER_LEN), except FORMAT_DESCRIPTION_EVENT and ROTATE_EVENT + (those have a header of size LOG_EVENT_MINIMAL_HEADER_LEN). + */ + uint8_t common_header_len; + /* + The list of post-headers' lengths followed + by the checksum alg decription byte + */ + std::vector<uint8_t> post_header_len; + unsigned char server_version_split[ST_SERVER_VER_SPLIT_LEN]; + + /** + Format_description_event 1st constructor. + + This constructor can be used to create the event to write to the binary log + (when the server starts or when FLUSH LOGS) + + @param binlog_ver the binlog version for which we want to build + an event. It should only be 4, old versions are not compatible anymore + since 8.0.2. + @param server_ver The MySQL server's version. + */ + Format_description_event(uint8_t binlog_ver, const char *server_ver); + /** + The layout of Format_description_event data part is as follows: + + <pre> + +=====================================+ + | event | binlog_version 19 : 2 | = 4 + | data +----------------------------+ + | | server_version 21 : 50 | + | +----------------------------+ + | | create_timestamp 71 : 4 | + | +----------------------------+ + | | header_length 75 : 1 | + | +----------------------------+ + | | post-header 76 : n | = array of n bytes, one byte + | | lengths for all | per event type that the + | | event types | server knows about + +=====================================+ + </pre> + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + + @note The fde passed to this constructor was created through another + constructor of FDE class. + */ + Format_description_event(const char *buf, + const Format_description_event *fde); + + Format_description_event(const Format_description_event &) = default; + Format_description_event &operator=(const Format_description_event &) = + default; + uint8_t number_of_event_types; + /** + This method is used to find out the version of server that originated + the current FD instance. + + @return the version of server. + */ + unsigned long get_product_version() const; + /** + This method checks the MySQL version to determine whether checksums may be + present in the events contained in the binary log. + + @retval true if the event's version is earlier than one that introduced + the replication event checksum. + @retval false otherwise. + */ + bool is_version_before_checksum() const; + /** + This method populates the array server_version_split which is then used for + lookups to find if the server which created this event has some known bug. + */ + void calc_server_version_split(); +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &info); + void print_long_info(std::ostream &info); +#endif + ~Format_description_event(); + + bool header_is_valid() const { + return ((common_header_len >= LOG_EVENT_MINIMAL_HEADER_LEN) && + (!post_header_len.empty())); + } + + bool version_is_valid() const { + /* It is invalid only when all version numbers are 0 */ + return server_version_split[0] != 0 || server_version_split[1] != 0 || + server_version_split[2] != 0; + } +}; + +/** + @class Stop_event + + A stop event is written to the log files under these circumstances: + - A master writes the event to the binary log when it shuts down. + - A slave writes the event to the relay log when it shuts down or + when a RESET SLAVE statement is executed. + + @section Stop_event_binary_format Binary Format + + The Post-Header and Body for this event type are empty; it only has + the Common-Header. +*/ + +class Stop_event : public Binary_log_event { + public: + /** + It is the minimal constructor, and all it will do is set the type_code as + STOP_EVENT in the header object in Binary_log_event. + */ + Stop_event() : Binary_log_event(STOP_EVENT) {} + + /** + A Stop_event is occurs under these circumstances: + - A master writes the event to the binary log when it shuts down + - A slave writes the event to the relay log when it shuts down or when a + RESET SLAVE statement is executed + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Stop_event(const char *buf, const Format_description_event *fde); + +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &) {} + void print_long_info(std::ostream &info); +#endif +}; + +/** + @class Incident_event + + Class representing an incident, an occurance out of the ordinary, + that happened on the master. + + The event is used to inform the slave that something out of the + ordinary happened on the master that might cause the database to be + in an inconsistent state. + + @section Incident_event_binary_format Binary Format + + <table id="IncidentFormat"> + <caption>Incident event format</caption> + <tr> + <th>Symbol</th> + <th>Format</th> + <th>Description</th> + </tr> + <tr> + <td>INCIDENT</td> + <td align="right">2</td> + <td>Incident number as an unsigned integer</td> + </tr> + <tr> + <td>MSGLEN</td> + <td align="right">1</td> + <td>Message length as an unsigned integer</td> + </tr> + <tr> + <td>MESSAGE</td> + <td align="right">MSGLEN</td> + <td>The message, if present. Not null terminated.</td> + </tr> + </table> + +*/ +class Incident_event : public Binary_log_event { + public: + /** + Enumeration of the incidents that can occur for the server. + */ + enum enum_incident { + /** No incident */ + INCIDENT_NONE = 0, + /** There are possibly lost events in the replication stream */ + INCIDENT_LOST_EVENTS = 1, + /** Shall be last event of the enumeration */ + INCIDENT_COUNT + }; + + enum_incident get_incident_type() { return incident; } + char *get_message() { return message; } + + /** + This will create an Incident_event with an empty message and set the + type_code as INCIDENT_EVENT in the header object in Binary_log_event. + */ + explicit Incident_event(enum_incident incident_arg) + : Binary_log_event(INCIDENT_EVENT), + incident(incident_arg), + message(nullptr), + message_length(0) {} + + /** + Constructor of Incident_event + The buffer layout is as follows: + <pre> + +-----------------------------------------------------+ + | Incident_number | message_length | Incident_message | + +-----------------------------------------------------+ + </pre> + + Incident number codes are listed in binlog_evnet.h. + The only code currently used is INCIDENT_LOST_EVENTS, which indicates that + there may be lost events (a "gap") in the replication stream that requires + databases to be resynchronized. + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Incident_event(const char *buf, const Format_description_event *fde); +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &info); + void print_long_info(std::ostream &info); +#endif + protected: + enum_incident incident; + char *message; + size_t message_length; +}; + +/** + @class Xid_event + + An XID event is generated for a commit of a transaction that modifies one or + more tables of an XA-capable storage engine. + + @section Xid_event_binary_format Binary Format + +The Body has the following component: + + <table> + <caption>Body for Xid_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>xid</td> + <td>8 byte unsigned integer</td> + <td>The XID transaction number.</td> + </tr> + </table> + The Post-Header and Body for this event type are empty; it only has + the common header. +*/ +class Xid_event : public Binary_log_event { + public: + /** + The minimal constructor of Xid_event, it initializes the instance variable + xid and set the type_code as XID_EVENT in the header object in + Binary_log_event + */ + explicit Xid_event(uint64_t xid_arg) + : Binary_log_event(XID_EVENT), xid(xid_arg) {} + + /** + An XID event is generated for a commit of a transaction that modifies one or + more tables of an XA-capable storage engine + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Xid_event(const char *buf, const Format_description_event *fde); + uint64_t xid; +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &info); + void print_long_info(std::ostream &info); +#endif +}; + +/** + @class XA_prepare_event + + An XA_prepare event is generated for a XA prepared transaction. + Like Xid_event it contans XID of the *prepared* transaction. + + @section XA_prepare_event_binary_format Binary Format + +The Body has the following component: + + <table> + <caption>Body for XA_prepare_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>my_xid</td> + <td>a struct similar to mysql/plugin.h containing three members.</td> + <td>serialized XID representation of XA transaction.</td> + </tr> + + <tr> + <td>xid</td> + <td>a pointer to XID object.</td> + <td>a reference to an object for mysql logger.</td> + </tr> + + <tr> + <td>one_phase</td> + <td>a bool</td> + <td>the value specifies the current XA transaction commit method.</td> + </tr> + </table> + The Post-Header and Body for this event type are empty; it only has + the common header. +*/ + +class XA_prepare_event : public Binary_log_event { + /* + Struct def is copied from $MYSQL/include/mysql/plugin.h, + consult there about fine details. + */ + static const int MY_XIDDATASIZE = 128; + + struct MY_XID { + long formatID; + long gtrid_length; + long bqual_length; + char data[MY_XIDDATASIZE]; /* Not \0-terminated */ + }; + + protected: + /* size of serialization buffer is explained in $MYSQL/sql/xa.h. */ + static const uint16_t ser_buf_size = + 8 + 2 * MY_XIDDATASIZE + 4 * sizeof(long) + 1; + MY_XID my_xid; + void *xid; /* Master side only */ + bool one_phase; + + public: + /** + The minimal constructor of XA_prepare_event, it initializes the + instance variable xid and set the type_code as XID_EVENT in the + header object in Binary_log_event + */ + XA_prepare_event(void *xid_arg, bool oph_arg) + : Binary_log_event(XA_PREPARE_LOG_EVENT), + xid(xid_arg), + one_phase(oph_arg) {} + + /** + An XID event is generated for a commit of a transaction that modifies one or + more tables of an XA-capable storage engine + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + XA_prepare_event(const char *buf, const Format_description_event *fde); +#ifndef HAVE_MYSYS + /* + todo: we need to find way how to exploit server's code of + serialize_xid() + */ + void print_event_info(std::ostream &) {} + void print_long_info(std::ostream &) {} +#endif +}; + +/** + @class Ignorable_event + + Base class for ignorable log events. Events deriving from + this class can be safely ignored by slaves that cannot + recognize them. Newer slaves, will be able to read and + handle them. This has been designed to be an open-ended + architecture, so adding new derived events shall not harm + the old slaves that support ignorable log event mechanism + (they will just ignore unrecognized ignorable events). + + @note The only thing that makes an event ignorable is that it has + the LOG_EVENT_IGNORABLE_F flag set. It is not strictly necessary + that ignorable event types derive from Ignorable_event; they may + just as well derive from Binary_log_event and Log_event and pass + LOG_EVENT_IGNORABLE_F as argument to the Log_event constructor. + + @section Ignoarble_event_binary_format Binary format + + The Post-Header and Body for this event type are empty; it only has + the Common-Header. +*/ +class Ignorable_event : public Binary_log_event { + public: + // buf is advanced in Binary_log_event constructor to point to beginning of + // post-header + + /** + The minimal constructor and all it will do is set the type_code as + IGNORABLE_LOG_EVENT in the header object in Binary_log_event. + */ + explicit Ignorable_event(Log_event_type type_arg = IGNORABLE_LOG_EVENT) + : Binary_log_event(type_arg) {} + /** + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Ignorable_event(const char *buf, const Format_description_event *fde); +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &) {} + void print_long_info(std::ostream &) {} +#endif +}; + +/** + @struct gtid_info + Structure to hold the members declared in the class Gtid_log_event those + member are objects of classes defined in server(rpl_gtid.h). As we can not + move all the classes defined there(in rpl_gtid.h) in libbinlogevents so this + structure was created, to provide a way to map the decoded value in Gtid_event + ctor and the class members defined in rpl_gtid.h, these classes are also the + members of Gtid_log_event(subclass of this in server code) + + The structure contains the following components. + <table> + <caption>Structure gtid_info</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + <tr> + <td>rpl_gtid_sidno</td> + <td>4 bytes integer</td> + <td>SIDNO (source ID number, first component of GTID)</td> + </tr> + <tr> + <td>rpl_gtid_gno</td> + <td>8 bytes integer</td> + <td>GNO (group number, second component of GTID)</td> + </tr> + </table> +*/ +struct gtid_info { + int32_t rpl_gtid_sidno; + int64_t rpl_gtid_gno; +}; + +/** + @class Gtid_event + GTID stands for Global Transaction IDentifier + It is composed of two parts: + - SID for Source Identifier, and + - GNO for Group Number. + The basic idea is to + - Associate an identifier, the Global Transaction IDentifier or GTID, + to every transaction. + - When a transaction is copied to a slave, re-executed on the slave, + and written to the slave's binary log, the GTID is preserved. + - When a slave connects to a master, the slave uses GTIDs instead of + (file, offset) + + @section Gtid_event_binary_format Binary Format + + The Body can have up to nine components: + + <table> + <caption>Body for Gtid_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>GTID_FLAGS</td> + <td>1 byte</td> + <td>00000001 = Transaction may have changes logged with SBR. + In 5.6, 5.7.0-5.7.18, and 8.0.0-8.0.1, this flag is always set. + Starting in 5.7.19 and 8.0.2, this flag is cleared if the transaction + only contains row events. It is set if any part of the transaction is + written in statement format.</td> + </tr> + <tr> + <td>SID</td> + <td>16 byte sequence</td> + <td>UUID representing the SID</td> + </tr> + <tr> + <td>GNO</td> + <td>8 byte integer</td> + <td>Group number, second component of GTID.</td> + </tr> + <tr> + <td>logical clock timestamp typecode</td> + <td>1 byte integer</td> + <td>The type of logical timestamp used in the logical clock fields.</td> + </tr> + <tr> + <td>last_committed</td> + <td>8 byte integer</td> + <td>Store the transaction's commit parent sequence_number</td> + </tr> + <tr> + <td>sequence_number</td> + <td>8 byte integer</td> + <td>The transaction's logical timestamp assigned at prepare phase</td> + </tr> + <tr> + <td>immediate_commit_timestamp</td> + <td>7 byte integer</td> + <td>Timestamp of commit on the immediate master</td> + </tr> + <tr> + <td>original_commit_timestamp</td> + <td>7 byte integer</td> + <td>Timestamp of commit on the originating master</td> + </tr> + <tr> + <td>transaction_length</td> + <td>1 to 9 byte integer // See net_length_size(ulonglong num)</td> + <td>The packed transaction's length in bytes, including the Gtid</td> + </tr> + <tr> + <td>immediate_server_version</td> + <td>4 byte integer</td> + <td>Server version of the immediate server</td> + </tr> + <tr> + <td>original_server_version</td> + <td>4 byte integer</td> + <td>Version of the server where the transaction was originally executed</td> + </tr> + </table> + +*/ +class Gtid_event : public Binary_log_event { + public: + /* + The transaction's logical timestamps used for MTS: see + Transaction_ctx::last_committed and + Transaction_ctx::sequence_number for details. + Note: Transaction_ctx is in the MySQL server code. + */ + long long int last_committed; + long long int sequence_number; + /** GTID flags constants */ + unsigned const char FLAG_MAY_HAVE_SBR = 1; + /** Transaction might have changes logged with SBR */ + bool may_have_sbr_stmts; + /** Timestamp when the transaction was committed on the originating master. */ + unsigned long long int original_commit_timestamp; + /** Timestamp when the transaction was committed on the nearest master. */ + unsigned long long int immediate_commit_timestamp; + bool has_commit_timestamps; + /** The length of the transaction in bytes. */ + unsigned long long int transaction_length; + + public: + /** + Ctor of Gtid_event + + The layout of the buffer is as follows + <pre> + +----------+---+---+-------+--------------+---------+----------+ + |gtid flags|SID|GNO|TS_TYPE|logical ts(:s)|commit ts|trx length| + +----------+---+---+-------+------------------------+----------+ + </pre> + TS_TYPE is from {G_COMMIT_TS2} singleton set of values + Details on commit timestamps in Gtid_event(const char*...) + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + + Gtid_event(const char *buf, const Format_description_event *fde); + /** + Constructor. + */ + explicit Gtid_event(long long int last_committed_arg, + long long int sequence_number_arg, + bool may_have_sbr_stmts_arg, + unsigned long long int original_commit_timestamp_arg, + unsigned long long int immediate_commit_timestamp_arg, + uint32_t original_server_version_arg, + uint32_t immediate_server_version_arg) + : Binary_log_event(GTID_LOG_EVENT), + last_committed(last_committed_arg), + sequence_number(sequence_number_arg), + may_have_sbr_stmts(may_have_sbr_stmts_arg), + original_commit_timestamp(original_commit_timestamp_arg), + immediate_commit_timestamp(immediate_commit_timestamp_arg), + transaction_length(0), + original_server_version(original_server_version_arg), + immediate_server_version(immediate_server_version_arg) {} +#ifndef HAVE_MYSYS + // TODO(WL#7684): Implement the method print_event_info and print_long_info + // for all the events supported in MySQL Binlog + void print_event_info(std::ostream &) {} + void print_long_info(std::ostream &) {} +#endif + protected: + static const int ENCODED_FLAG_LENGTH = 1; + static const int ENCODED_SID_LENGTH = 16; // Uuid::BYTE_LENGTH; + static const int ENCODED_GNO_LENGTH = 8; + /// Length of typecode for logical timestamps. + static const int LOGICAL_TIMESTAMP_TYPECODE_LENGTH = 1; + /// Length of two logical timestamps. + static const int LOGICAL_TIMESTAMP_LENGTH = 16; + // Type code used before the logical timestamps. + static const int LOGICAL_TIMESTAMP_TYPECODE = 2; + + static const int IMMEDIATE_COMMIT_TIMESTAMP_LENGTH = 7; + static const int ORIGINAL_COMMIT_TIMESTAMP_LENGTH = 7; + // Length of two timestamps (from original/immediate masters) + static const int FULL_COMMIT_TIMESTAMP_LENGTH = + IMMEDIATE_COMMIT_TIMESTAMP_LENGTH + ORIGINAL_COMMIT_TIMESTAMP_LENGTH; + // We use 7 bytes out of which 1 bit is used as a flag. + static const int ENCODED_COMMIT_TIMESTAMP_LENGTH = 55; + // Minimum and maximum lengths of transaction length field. + static const int TRANSACTION_LENGTH_MIN_LENGTH = 1; + static const int TRANSACTION_LENGTH_MAX_LENGTH = 9; + /// Length of original_server_version + static const int ORIGINAL_SERVER_VERSION_LENGTH = 4; + /// Length of immediate_server_version + static const int IMMEDIATE_SERVER_VERSION_LENGTH = 4; + /// Length of original and immediate server version + static const int FULL_SERVER_VERSION_LENGTH = + ORIGINAL_SERVER_VERSION_LENGTH + IMMEDIATE_SERVER_VERSION_LENGTH; + // We use 4 bytes out of which 1 bit is used as a flag. + static const int ENCODED_SERVER_VERSION_LENGTH = 31; + + /* We have only original commit timestamp if both timestamps are equal. */ + int get_commit_timestamp_length() const { + if (original_commit_timestamp != immediate_commit_timestamp) + return FULL_COMMIT_TIMESTAMP_LENGTH; + return ORIGINAL_COMMIT_TIMESTAMP_LENGTH; + } + + /** + We only store the immediate_server_version if both server versions are the + same. + */ + int get_server_version_length() const { + if (original_server_version != immediate_server_version) + return FULL_SERVER_VERSION_LENGTH; + return IMMEDIATE_SERVER_VERSION_LENGTH; + } + + gtid_info gtid_info_struct; + Uuid Uuid_parent_struct; + + /* Minimum GNO expected in a serialized GTID event */ + static const int64_t MIN_GNO = 1; + /* Maximum GNO expected in a serialized GTID event */ + static const int64_t MAX_GNO = LLONG_MAX; + + public: + /// Total length of post header + static const int POST_HEADER_LENGTH = + ENCODED_FLAG_LENGTH + /* flags */ + ENCODED_SID_LENGTH + /* SID length */ + ENCODED_GNO_LENGTH + /* GNO length */ + LOGICAL_TIMESTAMP_TYPECODE_LENGTH + /* length of typecode */ + LOGICAL_TIMESTAMP_LENGTH; /* length of two logical timestamps */ + + /* + We keep the commit timestamps in the body section because they can be of + variable length. + On the originating master, the event has only one timestamp as the two + timestamps are equal. On every other server we have two timestamps. + */ + static const int MAX_DATA_LENGTH = FULL_COMMIT_TIMESTAMP_LENGTH + + TRANSACTION_LENGTH_MAX_LENGTH + + FULL_SERVER_VERSION_LENGTH; + static const int MAX_EVENT_LENGTH = + LOG_EVENT_HEADER_LEN + POST_HEADER_LENGTH + MAX_DATA_LENGTH; + /** + Set the transaction length information. + + This function should be used when the full transaction length (including + the Gtid event length) is known. + + @param transaction_length_arg The transaction length. + */ + void set_trx_length(unsigned long long int transaction_length_arg) { + transaction_length = transaction_length_arg; + } + + /** The version of the server where the transaction was originally executed */ + uint32_t original_server_version; + /** The version of the immediate server */ + uint32_t immediate_server_version; +}; + +/** + @class Previous_gtids_event + + @section Previous_gtids_event_binary_format Binary Format + + The Post-Header for this event type is empty. The Body has two + components: + + <table> + <caption>Body for Previous_gtids_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>buf</td> + <td>unsigned char array</td> + <td>It contains the Gtids executed in the + last binary log file.</td> + </tr> + + <tr> + <td>buf_size</td> + <td>4 byte integer</td> + <td>Size of the above buffer</td> + </tr> + </table> +*/ +class Previous_gtids_event : public Binary_log_event { + public: + /** + Decodes the gtid_executed in the last binlog file + + <pre> + The buffer layout is as follows + +--------------------------------------------+ + | Gtids executed in the last binary log file | + +--------------------------------------------+ + </pre> + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Previous_gtids_event(const char *buf, const Format_description_event *fde); + /** + This is the minimal constructor, and set the + type_code as PREVIOUS_GTIDS_LOG_EVENT in the header object in + Binary_log_event + */ + Previous_gtids_event() : Binary_log_event(PREVIOUS_GTIDS_LOG_EVENT) {} +#ifndef HAVE_MYSYS + // TODO(WL#7684): Implement the method print_event_info and print_long_info + // for all the events supported in MySQL Binlog + void print_event_info(std::ostream &) {} + void print_long_info(std::ostream &) {} +#endif + protected: + size_t buf_size; + const unsigned char *buf; +}; + +/** + @class Transaction_context_event + + This class is used to combine the information of the ongoing transaction + including the write set and other information of the thread executing the + transaction. + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>thread_id</td> + <td>4 byte integer</td> + <td>The identifier for the thread executing the transaction.</td> + </tr> + + <tr> + <td>gtid_specified</td> + <td>bool type variable</td> + <td>Variable to identify whether the Gtid have been specified for the + ongoing transaction or not. + </td> + </tr> + + <tr> + <td>encoded_snapshot_version</td> + <td>unsigned char array</td> + <td>A gtid_set which is used to store the transaction set used for + conflict detection.</td> + </tr> + + <tr> + <td>encoded_snapshot_version_length</td> + <td>4 byte integer</td> + <td>Length of the above char array.</td> + </tr> + + <tr> + <td>write_set</td> + <td>variable length list to store the hash values. </td> + <td>Used to store the hash values of the rows identifier for the rows + which have changed in the ongoing transaction. + </td> + </tr> + + <tr> + <td>read_set</td> + <td>variable length list to store the read set values. Currently empty. + </td> <td>Will be used to store the read set values of the current + transaction.</td> + </tr> + +*/ +class Transaction_context_event : public Binary_log_event { + public: + /** + Decodes the transaction_context_log_event of the ongoing transaction. + + <pre> + The buffer layout is as follows + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Transaction_context_event(const char *buf, + const Format_description_event *fde); + + Transaction_context_event(unsigned int thread_id_arg, + bool is_gtid_specified_arg) + : Binary_log_event(TRANSACTION_CONTEXT_EVENT), + thread_id(thread_id_arg), + gtid_specified(is_gtid_specified_arg) {} + + virtual ~Transaction_context_event(); + + static const char *read_data_set(const char *pos, uint32_t set_len, + std::list<const char *> *set, + uint32_t remaining_buffer); + + static void clear_set(std::list<const char *> *set); + +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &) {} + void print_long_info(std::ostream &) {} +#endif + + protected: + const char *server_uuid; + uint32_t thread_id; + bool gtid_specified; + const unsigned char *encoded_snapshot_version; + uint32_t encoded_snapshot_version_length; + std::list<const char *> write_set; + std::list<const char *> read_set; + + // The values mentioned on the next class constants is the offset where the + // data that will be copied in the buffer. + + // 1 byte length. + static const int ENCODED_SERVER_UUID_LEN_OFFSET = 0; + // 4 bytes length. + static const int ENCODED_THREAD_ID_OFFSET = 1; + // 1 byte length. + static const int ENCODED_GTID_SPECIFIED_OFFSET = 5; + // 4 bytes length + static const int ENCODED_SNAPSHOT_VERSION_LEN_OFFSET = 6; + // 4 bytes length. + static const int ENCODED_WRITE_SET_ITEMS_OFFSET = 10; + // 4 bytes length. + static const int ENCODED_READ_SET_ITEMS_OFFSET = 14; + + // The values mentioned on the next class's constants is the length of the + // data that will be copied in the buffer. + static const int ENCODED_READ_WRITE_SET_ITEM_LEN = 2; + static const int ENCODED_SNAPSHOT_VERSION_LEN = 2; +}; + +/** + @class View_change_event + + This class is used to add view change markers in the binary log when a + member of the group enters or leaves the group. + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>view_id</td> + <td>40 length character array</td> + <td>This is used to store the view id value of the new view change when a + node add or leaves the group. + </td> + </tr> + + <tr> + <td>seq_number</td> + <td>8 bytes integer</td> + <td>Variable to identify the next sequence number to be alloted to the + certified transaction.</td> + </tr> + + <tr> + <td>certification_info</td> + <td>variable length map to store the certification data.</td> + <td>Map to store the certification info ie. the hash of write_set and the + snapshot sequence value. + </td> + </tr> + +*/ +class View_change_event : public Binary_log_event { + public: + /** + Decodes the view_change_log_event generated incase a server enters or + leaves the group. + + <pre> + The buffer layout is as follows + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + View_change_event(const char *buf, const Format_description_event *fde); + + explicit View_change_event(const char *raw_view_id); + + virtual ~View_change_event(); + +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &) {} + void print_long_info(std::ostream &) {} +#endif + + protected: + // The values mentioned on the next class constants is the offset where the + // data that will be copied in the buffer. + + // 40 bytes length. + static const int ENCODED_VIEW_ID_OFFSET = 0; + // 8 bytes length. + static const int ENCODED_SEQ_NUMBER_OFFSET = 40; + // 4 bytes length. + static const int ENCODED_CERT_INFO_SIZE_OFFSET = 48; + + /* + The layout of the buffer is as follows + +--------------------- -+-------------+----------+ + | View Id | seq number | map size | + +-----------------------+-------------+----------+ + view id (40 bytes) + seq number (8 bytes) + map size (4 bytes) + Sum of the length of the values at the above OFFSETS. + */ + + // The values mentioned on the next class constants is the length of the data + // that will be copied in the buffer. + + // Field sizes on serialization + static const int ENCODED_VIEW_ID_MAX_LEN = 40; + static const int ENCODED_CERT_INFO_KEY_SIZE_LEN = 2; + static const int ENCODED_CERT_INFO_VALUE_LEN = 4; + + char view_id[ENCODED_VIEW_ID_MAX_LEN]; + + long long int seq_number; + + std::map<std::string, std::string> certification_info; +}; + +/** + @class Heartbeat_event + + Replication event to ensure to slave that master is alive. + The event is originated by master's dump thread and sent straight to + slave without being logged. Slave itself does not store it in relay log + but rather uses a data for immediate checks and throws away the event. + + Two members of the class log_ident and Binary_log_event::log_pos comprise + @see the rpl_event_coordinates instance. The coordinates that a heartbeat + instance carries correspond to the last event master has sent from + its binlog. + + @section Heartbeat_event_binary_format Binary Format + + The Body has one component: + + <table> + <caption>Body for Heartbeat_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>log_ident</td> + <td>variable length string without trailing zero, extending to the + end of the event</td> + <td>Name of the current binlog being written to.</td> + </tr> + </table> +*/ +class Heartbeat_event : public Binary_log_event { + public: + /** + Sent by a master to a slave to let the slave know that the master is + still alive. Events of this type do not appear in the binary or relay logs. + They are generated on a master server by the thread that dumps events and + sent straight to the slave without ever being written to the binary log. + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Heartbeat_event(const char *buf, const Format_description_event *fde); + + const char *get_log_ident() { return log_ident; } + unsigned int get_ident_len() { return ident_len; } + + protected: + const char *log_ident; + unsigned int ident_len; /** filename length */ +}; + +} // end namespace binary_log +/** + @} (end of group Replication) +*/ +#endif /* CONTROL_EVENTS_INCLUDED */ diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/debug_vars.h b/contrib/libs/libmysql_r/libbinlogevents/include/debug_vars.h new file mode 100644 index 0000000000..fe2877ab42 --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/debug_vars.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2014, 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 */ + +/** + @file debug_vars.h + + @brief This header file contains the status of variables used by MySQL tests + for debug operations. The variables are set to true by the MySQL server if + the test pertaining to the variable is active. The variables are initialized + with false (in binlog_event.cpp). +*/ +#ifndef DEBUG_VARS_INCLUDED +#define DEBUG_VARS_INCLUDED + +namespace binary_log_debug { +extern bool debug_checksum_test; +extern bool debug_query_mts_corrupt_db_names; +extern bool debug_simulate_invalid_address; +extern bool debug_pretend_version_50034_in_binlog; +// TODO(WL#7546):Add variables here as we move methods into libbinlogevent +// from the server while implementing the WL#7546(Moving binlog event +// encoding into a separate package) +} // namespace binary_log_debug +#endif diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/event_reader.h b/contrib/libs/libmysql_r/libbinlogevents/include/event_reader.h new file mode 100644 index 0000000000..fa7373cd99 --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/event_reader.h @@ -0,0 +1,535 @@ +/* Copyright (c) 2018, 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 */ + +/** + @addtogroup Replication + @{ + + @file event_reader.h + + @brief Contains the class responsible for deserializing fields of an event + previously stored in a buffer. +*/ + +#ifndef EVENT_READER_INCLUDED +#define EVENT_READER_INCLUDED + +#include <list> +#include <map> +#include <vector> +#include "byteorder.h" +#include "wrapper_functions.h" + +namespace binary_log { + +#define PRINT_READER_STATUS(message) \ + BAPI_PRINT("debug", (message ": m_buffer= %p, " \ + "m_limit= %llu, " \ + "m_length= %llu, " \ + "position()= %llu", \ + m_buffer, m_limit, m_length, Event_reader::position())) + +/** + Event_reader class purpose is to avoid out-of-buffer reads when deserializing + binary log events and increase robustness when dealing with corrupted event + buffers. + + The Event_reader is composed by a pointer to the beginning of the serialized + event buffer (m_buffer), a variable containing the buffer length (m_length), a + cursor pointer that tells the current position to be read from the buffer + (m_ptr) and the buffer limit the reader shall respect (m_limit <= m_length). + + All buffer reading functions shall move the cursor forward. + + Before reading from the buffer, the Event_reader will check if the amount of + bytes expected to be read are less or equal to the remaining bytes to read: + + remaining = m_limit - (m_ptr - m_buffer) + + When there are no enough bytes to read from the buffer, Event_reader enters + in error state, so its owner can take an action. +*/ + +class Event_reader { + public: + /** + Event_reader constructor. + + It sets the cursor to the first position of the buffer. + + @param[in] buffer buffer holding a serialized event + @param[in] length known buffer length. + */ + Event_reader(const char *buffer, unsigned long long length) + : m_buffer(buffer), + m_ptr(buffer), + m_length(length), + m_limit(length), + m_error(nullptr) {} + + /** + Returns if the Event_reader is in an error state or not. + + @retval true if the Event_reader is in error state. + @retval false if the Event_reader is not in error state. + */ + bool has_error() { + BAPI_PRINT("debug", ("m_error= %s", m_error ? m_error : "nullptr")); + return m_error != nullptr; + } + + /** + Returns the pointer to the error message. + + @return the pointer to the error message when Event_reader is in error + state, or a nullptr otherwise. + */ + const char *get_error() { return m_error; } + + /** + Sets Event_reader error state by setting the error message. + + @param[in] error pointer to the error message. + */ + void set_error(const char *error); + + /** + Returns the Event_reader buffer length. + + Note: the buffer length might be larger than reader allowed buffer limit, + but the Event_reader will enter error state when trying to read above the + limit. + + Example: an event buffer may contain the serialized event + checksum. The + event reader object will be configured with a buffer length that contains + both the serialized event and the checksum information, but once + Log_event_footer is instantiated, it shall adjust the event reader buffer + limit to the buffer position right before the checksum. This will avoid some + event deserialization relying on event buffer size to assume the checksum as + serialized event content. + + @return the Event_reader buffer length. + */ + unsigned long long length() { return (m_length); } + + /** + Sets Event_reader buffer length and limit. + + The length of the buffer should only be set to values greater or equal to + the current buffer length. Trying to set the length to less than current + buffer length will make the Event_buffer to enter error state. + + The length is initially set in Event_reader constructor to + LOG_EVENT_MINIMAL_HEADER_LEN by the Log_event_header when instantiating it. + This should be enough to read the event header and determine the correct + buffer length. The Log_event_header will adjust the Event_reader length by + calling this function based on the value of event data_written header field. + + @param[in] length the new Event_reader buffer length. + */ + void set_length(unsigned long long length); + + /** + Shrinks the Event_reader buffer limit. + + This function is used by Log_event_footer to remove the checksum payload (if + necessary) from the serialized event size, as many event types rely on the + serialized event size to determine the size of some fields. + + @param[in] bytes the amount of bytes to shrink the Event_reader buffer + length. + */ + void shrink_limit(unsigned long long bytes); + + /** + Returns the Event_reader buffer pointer. + + @return the Event_reader buffer pointer. + */ + const char *buffer() { return m_buffer; } + + /** + Returns a pointer to the Event_reader cursor (next position to be read by + the Event_reader functions). + + @return the pointer to the Event_reader cursor. + */ + const char *ptr() { return m_ptr; } + + /** + Returns a pointer to the Event_reader cursor (next position to be read) and + moves the cursor forward. + + This function is used when the buffer contains a field of a known size and + the deserialization procedure must keep the pointer to the field but moving + the cursor to after it. + + @param[in] length the amount of bytes to move the cursor forward. + + @return the pointer to the Event_reader cursor before forwarding it. + */ + const char *ptr(unsigned long long length); + + /** + Returns the current Event_reader cursor position in bytes. + + @retval m_limit if cursor position is invalid. + @retval position current Event_reader cursor position (if valid). + */ + unsigned long long position() { + return m_ptr >= m_buffer ? m_ptr - m_buffer : m_limit; + } + + /** + Returns the amount of bytes still available to read from cursor position. + + @return the amount of bytes still available to read. + */ + unsigned long long available_to_read() { + BAPI_ASSERT(position() <= m_limit); + return m_limit - position(); + } + + /** + Returns if the Event_reader can read a given amount of bytes from cursor + position. + + @param bytes the amount of bytes expected to be read. + + @retval true if the Event_reader can read the specified amount of bytes. + @retval false if the Event_reader cannot read the specified amount of bytes. + */ + bool can_read(unsigned long long bytes) { + return (available_to_read() >= bytes); + } + + /** + Moves cursor to a given absolute buffer position and returns the pointer to + the cursor. + + @param position the position to jump to. + + @retval pointer a pointer to the new cursor position. + @retval nullptr if the position is out of buffer boundaries. + */ + const char *go_to(unsigned long long position); + + /** + Moves the buffer position forward to a given relative position and returns + the pointer to the buffer on the specified position. + + @param bytes the amount of bytes to move forward. + + @retval pointer a pointer to the new buffer position. + @retval nullptr if the cursor is out of buffer boundaries. + */ + const char *forward(unsigned long long bytes) { + BAPI_PRINT("debug", ("Event_reader::forward(%llu)", bytes)); + return go_to((m_ptr - m_buffer) + bytes); + } + + /** + Reads a basic type - bool, char, int, long, double, etc - from the buffer, + moves the cursor forward the number of bytes returned by sizeof(T)) and + returns the read value. + + @retval value the T read from the cursor position. + @retval 0 if the cursor was out of buffer boundaries. + */ + template <class T> + T read() { + PRINT_READER_STATUS("Event_reader::read"); + if (!can_read(sizeof(T))) { + set_error("Cannot read from out of buffer bounds"); + BAPI_PRINT("debug", ("Event_reader::tread(): " + "sizeof()= %zu", + sizeof(T))); + return 0; + } + T value = 0; + value = (T) * (m_ptr); + m_ptr = m_ptr + sizeof(T); + return value; + } + + /** + Copies a basic type - bool, char, int, long, double, etc - from the buffer, + moves the cursor forward the number of bytes returned by sizeof(T)) and + returns the copied value. + + @retval value the T copied from the cursor position. + @retval 0 if the cursor was out of buffer boundaries. + */ + template <class T> + T memcpy() { + PRINT_READER_STATUS("Event_reader::memcpy"); + if (!can_read(sizeof(T))) { + set_error("Cannot read from out of buffer bounds"); + BAPI_PRINT("debug", ("Event_reader::memcpy(): " + "sizeof()= %zu", + sizeof(T))); + return 0; + } + T value = 0; + ::memcpy((char *)&value, m_ptr, sizeof(T)); + m_ptr = m_ptr + sizeof(T); + return value; + } + + /** + Copies a basic arithmetic type - uint8_t, [u]int16_t, [u]int32_t, + [u]int64_t - from the buffer, moves the cursor forward using specified bytes + parameter (or the number of bytes returned by sizeof(T) when not specified) + and returns the copied value transformed from little endian if necessary). + + @param[in] bytes the amount of bytes to read from the buffer (and to move + forward). When not specified, will use sizeof(T). + + @retval value the T copied from the cursor position. + @retval 0 if the cursor was out of buffer boundaries or there was no memory + to allocate to the new string.. + */ + template <typename T> + T read_and_letoh(unsigned char bytes = sizeof(T)) { + PRINT_READER_STATUS("Event_reader::read_and_letoh"); + if (!can_read(bytes)) { + set_error("Cannot read from out of buffer bounds"); + BAPI_PRINT("debug", ("Event_reader::read_and_letoh(): " + "sizeof()= %zu, bytes= %u", + sizeof(T), bytes)); + return 0; + } + T value = 0; + ::memcpy((char *)&value, m_ptr, bytes); + m_ptr = m_ptr + bytes; + return letoh(value); + } + + /** + Returns a pointer to a new string which is a duplicate of the input string. + The terminating null character is added. See: bapi_strndup(). + + @param[in] length the amount of bytes to read from the buffer (and to move + forward). + + @retval pointer the T pointer from the cursor position. + @retval nullptr if the cursor was out of buffer boundaries. + */ + template <typename T> + T strndup(size_t length) { + PRINT_READER_STATUS("Event_reader::strndup"); + if (!can_read(length)) { + BAPI_PRINT("debug", ("Event_reader::strndup(%zu)", length)); + set_error("Cannot read from out of buffer bounds"); + return nullptr; + } + T str; + str = reinterpret_cast<T>(bapi_strndup(m_ptr, length)); + m_ptr = m_ptr + length; + return str; + } + + /** + Copies from the cursor to an already existent (and allocated) buffer and + moves forward the cursor. + + @param[out] destination a pointer to the destination buffer. + @param[in] length the amount of bytes to read from the buffer (and to move + forward). + */ + template <typename T> + void memcpy(T destination, size_t length) { + PRINT_READER_STATUS("Event_reader::memcpy"); + if (!can_read(length)) { + BAPI_PRINT("debug", ("Event_reader::memcpy(%zu)", length)); + set_error("Cannot read from out of buffer bounds"); + return; + } + ::memcpy(destination, m_ptr, length); + m_ptr = m_ptr + length; + } + + /** + Allocates memory to a destination buffer, copies from the cursor to the + destination buffer using memcpy() and moves forward the cursor. + + This function is useful for pairs of fields when a first field describes the + second field size and the deserialization procedure must allocate a buffer + for the second field and then copy the event buffer content to the new + allocated buffer. + + Before implementing this function and the Event_reader, the deserialization + process did like: + + memcpy(length, ptr, sizeof(length); + ptr+=sizeof(length); + field = malloc(length); + memcpy(field, ptr, length); + + Allocating the memory for the field before knowing if the content can be + read from the event buffer is a mistake, as it might allocate a very large + amount of memory that will not be used. + + So, alloc_and_memcpy ensures that it will only allocate memory for the field + if it can be read from the event buffer, avoiding allocating a memory that + will not be used. + + @param[out] destination the destination buffer. + @param[in] length the amount of bytes to allocate and read from the buffer + (and to move forward). + @param[in] flags flags to pass to MySQL server my_malloc() function. + */ + void alloc_and_memcpy(unsigned char **destination, size_t length, int flags); + + /** + Allocates memory to a destination buffer, copies from the cursor to the + destination buffer using strncpy() and moves forward the cursor. + + See comments on alloc_and_memcpy() for more details. + + @param[out] destination the destination buffer. + @param[in] length the amount of bytes to allocate and read from the buffer + (and to forward). + @param[in] flags flags to pass to MySQL server my_malloc() function. + */ + void alloc_and_strncpy(char **destination, size_t length, int flags); + + /** + Reads string from cursor. + + Reads in the following format: + 1) Reads length stored on cursor first index. Moves cursor forward 1 byte. + 2) Set destination pointer to the cursor. Moves cursor forward length bytes. + + @param[out] destination the destination pointer. + @param[out] length the amount of bytes to allocate and read from the buffer + (and to move forward). + */ + void read_str_at_most_255_bytes(const char **destination, uint8_t *length); + + /** + Reads a packed value. + + This function can move the cursor forward by 1, 3, 4 or 9 bytes depending on + the value to be returned. + + @return the packed value. + */ + uint64_t net_field_length_ll(); + + /** + Reads a transaction context data set. + + @param[in] set_len length of the set object (and to move forward). + @param[out] set pointer to the set object to be filled. + */ + void read_data_set(uint32_t set_len, std::list<const char *> *set); + + /** + Reads a view change certification map. + + @param[in] map_len the length of the certification info map (and to move + forward). + @param[out] map the certification info map to be filled. + */ + void read_data_map(uint32_t map_len, std::map<std::string, std::string> *map); + + /** + Copy a string into the destination buffer up to a max length. + + @param[out] destination the destination buffer. + @param[in] max_length the max length to copy from the cursor. + @param[in] dest_length the max length supported by the destination buffer. + */ + void strncpyz(char *destination, size_t max_length, size_t dest_length); + + /** + Fills a vector with a sequence of bytes from the cursor. + + @param[out] destination the vector be filled. + @param[in] length the amount of bytes to read from the cursor (and to move + forward). + */ + void assign(std::vector<uint8_t> *destination, size_t length); + + private: + /* The buffer with the serialized binary log event */ + const char *m_buffer; + /* The cursor: a pointer to the current read position in the buffer */ + const char *m_ptr; + /* The length of the buffer */ + unsigned long long m_length; + /* The limit the reader shall respect when reading from the buffer */ + unsigned long long m_limit; + /* The pointer to the current error message, or nullptr */ + const char *m_error; + + /** + Wrapper to le16toh to be used by read_and_letoh function. + + @param[in] value the value to be converted. + + @return the converted value. + */ + uint16_t letoh(uint16_t value) { return le16toh(value); } + + /** + Wrapper to le32toh to be used by read_and_letoh function. + + @param[in] value the value to be converted. + + @return the converted value. + */ + int32_t letoh(int32_t value) { return le32toh(value); } + + /** + Wrapper to le32toh to be used by read_and_letoh function. + + @param[in] value the value to be converted. + + @return the converted value. + */ + uint32_t letoh(uint32_t value) { return le32toh(value); } + + /** + Wrapper to le64toh to be used by read_and_letoh function. + + @param[in] value the value to be converted. + + @return the converted value. + */ + int64_t letoh(int64_t value) { return le64toh(value); } + + /** + Wrapper to le64toh to be used by read_and_letoh function. + + @param[in] value the value to be converted. + + @return the converted value. + */ + uint64_t letoh(uint64_t value) { return le64toh(value); } +}; +} // end namespace binary_log +/** + @} (end of group Replication) +*/ +#endif /* EVENT_READER_INCLUDED */ diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/load_data_events.h b/contrib/libs/libmysql_r/libbinlogevents/include/load_data_events.h new file mode 100644 index 0000000000..4c8533bae3 --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/load_data_events.h @@ -0,0 +1,396 @@ +/* Copyright (c) 2014, 2018, 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 */ + +/** + @addtogroup Replication + @{ + + @file load_data_events.h + + @brief LOAD DATA INFILE is not written to the binary log like other + statements. It is written as one or more events in a packed format, + not as a cleartext statement in the binary log. The events indicate + what options are present in the statement and how to process the data file. +*/ + +#ifndef LOAD_DATA_EVENTS_INCLUDED +#define LOAD_DATA_EVENTS_INCLUDED + +#include <sys/types.h> +#include "statement_events.h" +#include "table_id.h" + +/* + These are flags and structs to handle all the LOAD DATA INFILE options (LINES + TERMINATED etc). + DUMPFILE_FLAG is probably not used (DUMPFILE is a clause of SELECT, + not of LOAD DATA). +*/ +#define DUMPFILE_FLAG 0x1 +#define OPT_ENCLOSED_FLAG 0x2 +#define REPLACE_FLAG 0x4 +#define IGNORE_FLAG 0x8 + +#define FIELD_TERM_EMPTY 0x1 +#define ENCLOSED_EMPTY 0x2 +#define LINE_TERM_EMPTY 0x4 +#define LINE_START_EMPTY 0x8 +#define ESCAPED_EMPTY 0x10 + +namespace binary_log { +/** + Elements of this enum describe how LOAD DATA handles duplicates. +*/ +enum enum_load_dup_handling { + LOAD_DUP_ERROR = 0, + LOAD_DUP_IGNORE, + LOAD_DUP_REPLACE +}; + +/** + @class Execute_load_query_event + + Event responsible for LOAD DATA execution, it similar to Query_event + but before executing the query it substitutes original filename in LOAD DATA + query with name of temporary file. + + The first 13 bytes of the Post-Header for this event are the same as for + Query_event, as is the initial status variable block in the Body. + + @section Execute_load_query_event_binary_format Binary Format + + The additional members of the events are the following: + + <table> + <caption>Body for Execute_load_query_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>file_id</td> + <td>4 byte unsigned integer</td> + <td>ID of the temporary file to load</td> + </tr> + + <tr> + <td>fn_pos_start</td> + <td>4 byte unsigned integer</td> + <td>The start position within the statement for filename substitution</td> + </tr> + <tr> + + <td>fn_pos_end</td> + <td>4 byte unsigned integer</td> + <td>The end position within the statement for filename substitution</td> + </tr> + + <tr> + <td>dup_handling</td> + <td>enum_load_dup_handling</td> + <td>Represents information on how to handle duplicates: + LOAD_DUP_ERROR= 0, LOAD_DUP_IGNORE= 1, LOAD_DUP_REPLACE= 2</td> + </tr> + </table> +*/ +class Execute_load_query_event : public virtual Query_event { + public: + enum Execute_load_query_event_offset { + /** ELQ = "Execute Load Query" */ + ELQ_FILE_ID_OFFSET = QUERY_HEADER_LEN, + ELQ_FN_POS_START_OFFSET = ELQ_FILE_ID_OFFSET + 4, + ELQ_FN_POS_END_OFFSET = ELQ_FILE_ID_OFFSET + 8, + ELQ_DUP_HANDLING_OFFSET = ELQ_FILE_ID_OFFSET + 12 + }; + + int32_t file_id; /** file_id of temporary file */ + uint32_t fn_pos_start; /** pointer to the part of the query that should + be substituted */ + uint32_t fn_pos_end; /** pointer to the end of this part of query */ + + /** + We have to store type of duplicate handling explicitly, because + for LOAD DATA it also depends on LOCAL option. And this part + of query will be rewritten during replication so this information + may be lost... + */ + enum_load_dup_handling dup_handling; + + Execute_load_query_event(uint32_t file_id_arg, uint32_t fn_pos_start, + uint32_t fn_pos_end, enum_load_dup_handling dup); + + /** + The constructor receives a buffer and instantiates a + Execute_load_query_event filled in with the data from the buffer. + + <pre> + The fixed event data part buffer layout is as follows: + +---------------------------------------------------------------------+ + | thread_id | query_exec_time | db_len | error_code | status_vars_len | + +---------------------------------------------------------------------+ + +----------------------------------------------------+ + | file_id | fn_pos_start | fn_pos_end | dup_handling | + +----------------------------------------------------+ + </pre> + + <pre> + The fixed event data part buffer layout is as follows: + +------------------------------------------------------------------+ + | Zero or more status variables | db | LOAD DATA INFILE statement | + +------------------------------------------------------------------+ + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Execute_load_query_event(const char *buf, + const Format_description_event *fde); + + ~Execute_load_query_event() {} +}; + +/** + @class Delete_file_event + + DELETE_FILE_EVENT occurs when the LOAD DATA failed on the master. + This event notifies the slave not to do the load and to delete + the temporary file. + + @section Delete_file_event_binary_format Binary Format + + The variable data part is empty. The post header contains the following: + + <table> + <caption>Post header for Delete_file_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>file_id</td> + <td>32 bit integer</td> + <td>The ID of the file to be deleted</td> + </tr> + </table> +*/ +class Delete_file_event : public Binary_log_event { + protected: + // Required by Delete_file_log_event(THD* ..) + Delete_file_event(uint32_t file_id_arg, const char *db_arg) + : Binary_log_event(DELETE_FILE_EVENT), file_id(file_id_arg), db(db_arg) {} + + public: + enum Delete_file_offset { + /** DF = "Delete File" */ + DF_FILE_ID_OFFSET = 0 + }; + + uint32_t file_id; + const char *db; /** see comment in Append_block_event */ + + /** + The buffer layout for fixed data part is as follows: + <pre> + +---------+ + | file_id | + +---------+ + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Delete_file_event(const char *buf, const Format_description_event *fde); + + ~Delete_file_event() {} + +#ifndef HAVE_MYSYS + // TODO(WL#7684): Implement the method print_event_info and print_long_info + // for + // all the events supported in MySQL Binlog + void print_event_info(std::ostream &) {} + void print_long_info(std::ostream &) {} +#endif +}; + +/** + @class Append_block_event + + This event is created to contain the file data. One LOAD_DATA_INFILE + can have 0 or more instances of this event written to the binary log + depending on the size of the file. If the file to be loaded is greater + than the threshold value, which is roughly 2^17 bytes, the file is + divided into blocks of size equal to the threshold, and each block + is sent across as a separate event. + + @section Append_block_event_binary_format Binary Format + + The post header contains the following: + + <table> + <caption>Post header for Append_block_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>file_id</td> + <td>32 bit integer</td> + <td>The ID of the file to append the block to</td> + </tr> + </table> + + The body of the event contains the raw data to load. The raw data + size is the event size minus the size of all the fixed event parts. +*/ +class Append_block_event : public Binary_log_event { + protected: + /** + This constructor is used by the MySQL server. + */ + Append_block_event(const char *db_arg, unsigned char *block_arg, + unsigned int block_len_arg, uint32_t file_id_arg) + : Binary_log_event(APPEND_BLOCK_EVENT), + block(block_arg), + block_len(block_len_arg), + file_id(file_id_arg), + db(db_arg) {} + + Append_block_event(Log_event_type type_arg = APPEND_BLOCK_EVENT) + : Binary_log_event(type_arg) {} + + public: + enum Append_block_offset { + /** AB = "Append Block" */ + AB_FILE_ID_OFFSET = 0, + AB_DATA_OFFSET = APPEND_BLOCK_HEADER_LEN + }; + + unsigned char *block; + unsigned int block_len; + uint32_t file_id; + /** + 'db' is filled when the event is created in mysql_load() (the + event needs to have a 'db' member to be well filtered by + binlog-*-db rules). 'db' is not written to the binlog (it's not + used by Append_block_log_event::write()), so it can't be read in + the Append_block_event(const char* buf, int event_len) + constructor. In other words, 'db' is used only for filtering by + binlog-*-db rules. Create_file_event is different: it's 'db' + (which is inherited from Load_event) is written to the binlog + and can be re-read. + */ + const char *db; + + /** + Appends the buffered data, received as a parameter, to the file being loaded + via LOAD_DATA_FILE. + + The buffer layout for fixed data part is as follows: + <pre> + +---------+ + | file_id | + +---------+ + </pre> + + The buffer layout for variable data part is as follows: + <pre> + +-------------------+ + | block | block_len | + +-------------------+ + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Append_block_event(const char *buf, const Format_description_event *fde); + ~Append_block_event() {} + +#ifndef HAVE_MYSYS + // TODO(WL#7684): Implement the method print_event_info and print_long_info + // for + // all the events supported in MySQL Binlog + void print_event_info(std::ostream &) {} + void print_long_info(std::ostream &) {} +#endif +}; + +/** + @class Begin_load_query_event + + Event for the first block of file to be loaded, its only difference from + Append_block event is that this event creates or truncates existing file + before writing data. + + @section Begin_load_query_event_binary_format Binary Format + + The Post-Header and Body for this event type are empty; it only has + the Common-Header. +*/ +class Begin_load_query_event : public virtual Append_block_event { + protected: + Begin_load_query_event() : Append_block_event(BEGIN_LOAD_QUERY_EVENT) {} + + public: + /** + The buffer layout for fixed data part is as follows: + <pre> + +---------+ + | file_id | + +---------+ + </pre> + + The buffer layout for variable data part is as follows: + <pre> + +-------------------+ + | block | block_len | + +-------------------+ + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Begin_load_query_event(const char *buf, const Format_description_event *fde); + + ~Begin_load_query_event() {} + +#ifndef HAVE_MYSYS + // TODO(WL#7684): Implement the method print_event_info and print_long_info + // for + // all the events supported in MySQL Binlog + void print_event_info(std::ostream &) {} + void print_long_info(std::ostream &) {} +#endif +}; +} // end namespace binary_log +/** + @} (end of group Replication) +*/ +#endif /* LOAD_DATA_EVENTS_INCLUDED */ diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/rows_event.h b/contrib/libs/libmysql_r/libbinlogevents/include/rows_event.h new file mode 100644 index 0000000000..f3593b2c95 --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/rows_event.h @@ -0,0 +1,1165 @@ +/* Copyright (c) 2014, 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 */ + +/** + @addtogroup Replication + @{ + + @file rows_event.h + + @brief Contains the classes representing events which are used for row based + replication. In row-based replication, the master writes events to the binary + log that indicate how individual table rows are changed. +*/ + +#ifndef ROWS_EVENT_INCLUDED +#define ROWS_EVENT_INCLUDED + +#include <vector> +#include "control_events.h" +#include "table_id.h" + +// Undefine conflicting wingdi.h macro +#undef DEFAULT_CHARSET + +/** + 1 byte length, 1 byte format + Length is total length in bytes, including 2 byte header + Length values 0 and 1 are currently invalid and reserved. +*/ +#define EXTRA_ROW_INFO_LEN_OFFSET 0 +#define EXTRA_ROW_INFO_FORMAT_OFFSET 1 +#define EXTRA_ROW_INFO_HEADER_LENGTH 2 +#define EXTRA_ROW_INFO_MAX_PAYLOAD (255 - EXTRA_ROW_INFO_HEADER_LENGTH) + +#define ROWS_MAPID_OFFSET 0 +#define ROWS_FLAGS_OFFSET 6 +#define ROWS_VHLEN_OFFSET 8 +#define EXTRA_ROW_INFO_TYPECODE_LENGTH 1 +#define EXTRA_ROW_PART_INFO_VALUE_LENGTH 2 + +/** + This is the typecode defined for the different elements present in + the container Extra_row_info, this is different from the format information + stored inside extra_row_ndb_info at EXTRA_ROW_INFO_FORMAT_OFFSET. +*/ +enum class enum_extra_row_info_typecode { NDB = 0, PART = 1 }; + +namespace binary_log { +/** + @class Table_map_event + + In row-based mode, every row operation event is preceded by a + Table_map_event which maps a table definition to a number. The + table definition consists of database name, table name, and column + definitions. + + @section Table_map_event_binary_format Binary Format + + The Post-Header has the following components: + + <table> + <caption>Post-Header for Table_map_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>table_id</td> + <td>6 bytes unsigned integer</td> + <td>The number that identifies the table.</td> + </tr> + + <tr> + <td>flags</td> + <td>2 byte bitfield</td> + <td>Reserved for future use; currently always 0.</td> + </tr> + + </table> + + The Body has the following components: + + <table> + <caption>Body for Table_map_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>database_name</td> + <td>one byte string length, followed by null-terminated string</td> + <td>The name of the database in which the table resides. The name + is represented as a one byte unsigned integer representing the + number of bytes in the name, followed by length bytes containing + the database name, followed by a terminating 0 byte. (Note the + redundancy in the representation of the length.) </td> + </tr> + + <tr> + <td>table_name</td> + <td>one byte string length, followed by null-terminated string</td> + <td>The name of the table, encoded the same way as the database + name above.</td> + </tr> + + <tr> + <td>column_count</td> + <td>@ref packed_integer "Packed Integer"</td> + <td>The number of columns in the table, represented as a packed + variable-length integer.</td> + </tr> + + <tr> + <td>column_type</td> + <td>List of column_count 1 byte enumeration values</td> + <td>The type of each column in the table, listed from left to + right. Each byte is mapped to a column type according to the + enumeration type enum_field_types defined in mysql_com.h. The + mapping of types to numbers is listed in the table @ref + Table_table_map_event_column_types "below" (along with + description of the associated metadata field). </td> + </tr> + + <tr> + <td>metadata_length</td> + <td>@ref packed_integer "Packed Integer"</td> + <td>The length of the following metadata block</td> + </tr> + + <tr> + <td>metadata</td> + <td>list of metadata for each column</td> + <td>For each column from left to right, a chunk of data who's + length and semantics depends on the type of the column. The + length and semantics for the metadata for each column are listed + in the table @ref Table_table_map_event_column_types + "below".</td> + </tr> + + <tr> + <td>null_bits</td> + <td>column_count bits, rounded up to nearest byte</td> + <td>For each column, a bit indicating whether data in the column + can be NULL or not. The number of bytes needed for this is + int((column_count + 7) / 8). The flag for the first column from the + left is in the least-significant bit of the first byte, the second + is in the second least significant bit of the first byte, the + ninth is in the least significant bit of the second byte, and so + on. </td> + </tr> + + <tr> + <td>optional metadata fields</td> + <td>optional metadata fields are stored in Type, Length, Value(TLV) format. + Type takes 1 byte. Length is a packed integer value. Values takes + Length bytes. + </td> + <td>There are some optional metadata defined. They are listed in the table + @ref Table_table_map_event_optional_metadata. Optional metadata fields + follow null_bits. Whether binlogging an optional metadata is decided by the + server. The order is not defined, so they can be binlogged in any order. + </td> + </tr> + </table> + + The table below lists all column types, along with the numerical + identifier for it and the size and interpretation of meta-data used + to describe the type. + + @anchor Table_table_map_event_column_types + <table> + <caption>Table_map_event column types: numerical identifier and + metadata</caption> + <tr> + <th>Name</th> + <th>Identifier</th> + <th>Size of metadata in bytes</th> + <th>Description of metadata</th> + </tr> + + <tr> + <td>MYSQL_TYPE_DECIMAL</td><td>0</td> + <td>0</td> + <td>No column metadata.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_TINY</td><td>1</td> + <td>0</td> + <td>No column metadata.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_SHORT</td><td>2</td> + <td>0</td> + <td>No column metadata.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_LONG</td><td>3</td> + <td>0</td> + <td>No column metadata.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_FLOAT</td><td>4</td> + <td>1 byte</td> + <td>1 byte unsigned integer, representing the "pack_length", which + is equal to sizeof(float) on the server from which the event + originates.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_DOUBLE</td><td>5</td> + <td>1 byte</td> + <td>1 byte unsigned integer, representing the "pack_length", which + is equal to sizeof(double) on the server from which the event + originates.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_NULL</td><td>6</td> + <td>0</td> + <td>No column metadata.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_TIMESTAMP</td><td>7</td> + <td>0</td> + <td>No column metadata.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_LONGLONG</td><td>8</td> + <td>0</td> + <td>No column metadata.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_INT24</td><td>9</td> + <td>0</td> + <td>No column metadata.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_DATE</td><td>10</td> + <td>0</td> + <td>No column metadata.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_TIME</td><td>11</td> + <td>0</td> + <td>No column metadata.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_DATETIME</td><td>12</td> + <td>0</td> + <td>No column metadata.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_YEAR</td><td>13</td> + <td>0</td> + <td>No column metadata.</td> + </tr> + + <tr> + <td><i>MYSQL_TYPE_NEWDATE</i></td><td><i>14</i></td> + <td>–</td> + <td><i>This enumeration value is only used internally and cannot + exist in a binlog.</i></td> + </tr> + + <tr> + <td>MYSQL_TYPE_VARCHAR</td><td>15</td> + <td>2 bytes</td> + <td>2 byte unsigned integer representing the maximum length of + the string.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_BIT</td><td>16</td> + <td>2 bytes</td> + <td>A 1 byte unsigned int representing the length in bits of the + bitfield (0 to 64), followed by a 1 byte unsigned int + representing the number of bytes occupied by the bitfield. The + number of bytes is either int((length + 7) / 8) or int(length / 8). + </td> + </tr> + + <tr> + <td>MYSQL_TYPE_NEWDECIMAL</td><td>246</td> + <td>2 bytes</td> + <td>A 1 byte unsigned int representing the precision, followed + by a 1 byte unsigned int representing the number of decimals.</td> + </tr> + + <tr> + <td><i>MYSQL_TYPE_ENUM</i></td><td><i>247</i></td> + <td>–</td> + <td><i>This enumeration value is only used internally and cannot + exist in a binlog.</i></td> + </tr> + + <tr> + <td><i>MYSQL_TYPE_SET</i></td><td><i>248</i></td> + <td>–</td> + <td><i>This enumeration value is only used internally and cannot + exist in a binlog.</i></td> + </tr> + + <tr> + <td>MYSQL_TYPE_TINY_BLOB</td><td>249</td> + <td>–</td> + <td><i>This enumeration value is only used internally and cannot + exist in a binlog.</i></td> + </tr> + + <tr> + <td><i>MYSQL_TYPE_MEDIUM_BLOB</i></td><td><i>250</i></td> + <td>–</td> + <td><i>This enumeration value is only used internally and cannot + exist in a binlog.</i></td> + </tr> + + <tr> + <td><i>MYSQL_TYPE_LONG_BLOB</i></td><td><i>251</i></td> + <td>–</td> + <td><i>This enumeration value is only used internally and cannot + exist in a binlog.</i></td> + </tr> + + <tr> + <td>MYSQL_TYPE_BLOB</td><td>252</td> + <td>1 byte</td> + <td>The pack length, i.e., the number of bytes needed to represent + the length of the blob: 1, 2, 3, or 4.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_VAR_STRING</td><td>253</td> + <td>2 bytes</td> + <td>This is used to store both strings and enumeration values. + The first byte is a enumeration value storing the <i>real + type</i>, which may be either MYSQL_TYPE_VAR_STRING or + MYSQL_TYPE_ENUM. The second byte is a 1 byte unsigned integer + representing the field size, i.e., the number of bytes needed to + store the length of the string.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_STRING</td><td>254</td> + <td>2 bytes</td> + <td>The first byte is always MYSQL_TYPE_VAR_STRING (i.e., 253). + The second byte is the field size, i.e., the number of bytes in + the representation of size of the string: 3 or 4.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_GEOMETRY</td><td>255</td> + <td>1 byte</td> + <td>The pack length, i.e., the number of bytes needed to represent + the length of the geometry: 1, 2, 3, or 4.</td> + </tr> + + <tr> + <td>MYSQL_TYPE_TYPED_ARRAY</td><td>15</td> + <td>up to 4 bytes</td> + <td> + - The first byte holds the MySQL type for the elements. + - The following 0, 1, 2, or 3 bytes holds the metadata for the MySQL + type for the elements. The contents of these bytes depends on the + element type, as described in the other rows of this table. + </td> + </tr> + + </table> + + The table below lists all optional metadata types, along with the numerical + identifier for it and the size and interpretation of meta-data used + to describe the type. + + @anchor Table_table_map_event_optional_metadata + <table> + <caption>Table_map_event optional metadata types: numerical identifier and + metadata. Optional metadata fields are stored in TLV fields. + Format of values are described in this table. </caption> + <tr> + <th>Type</th> + <th>Description</th> + <th>Format</th> + </tr> + <tr> + <td>SIGNEDNESS</td> + <td>signedness of numeric colums. This is included for all values of + binlog_row_metadata.</td> + <td>For each numeric column, a bit indicates whether the numeric + colunm has unsigned flag. 1 means it is unsigned. The number of + bytes needed for this is int((column_count + 7) / 8). The order is + the same as the order of column_type field.</td> + </tr> + <tr> + <td>DEFAULT_CHARSET</td> + <td>Charsets of character columns. It has a default charset for + the case that most of character columns have same charset and the + most used charset is binlogged as default charset.Collation + numbers are binlogged for identifying charsets. They are stored in + packed length format. Either DEFAULT_CHARSET or COLUMN_CHARSET is + included for all values of binlog_row_metadata.</td> + <td>Default charset's collation is logged first. The charsets which are not + same to default charset are logged following default charset. They are + logged as column index and charset collation number pair sequence. The + column index is counted only in all character columns. The order is same to + the order of column_type + field. </td> + </tr> + <tr> + <td>COLUMN_CHARSET</td> + <td>Charsets of character columns. For the case that most of columns have + different charsets, this field is logged. It is never logged with + DEFAULT_CHARSET together. Either DEFAULT_CHARSET or COLUMN_CHARSET is + included for all values of binlog_row_metadata.</td> + <td>It is a collation number sequence for all character columns.</td> + </tr> + <tr> + <td>COLUMN_NAME</td> + <td>Names of columns. This is only included if + binlog_row_metadata=FULL.</td> + <td>A sequence of column names. For each column name, 1 byte for + the string length in bytes is followed by a string without null + terminator.</td> + </tr> + <tr> + <td>SET_STR_VALUE</td> + <td>The string values of SET columns. This is only included if + binlog_row_metadata=FULL.</td> + <td>For each SET column, a pack_length representing the value + count is followed by a sequence of length and string pairs. length + is the byte count in pack_length format. The string has no null + terminator.</td> + </tr> + <tr> + <td>ENUM_STR_VALUE</td> + <td>The string values is ENUM columns. This is only included + if binlog_row_metadata=FULL.</td> + <td>The format is the same as SET_STR_VALUE.</td> + </tr> + <tr> + <td>GEOMETRY_TYPE</td> + <td>The real type of geometry columns. This is only included + if binlog_row_metadata=FULL.</td> + <td>A sequence of real type of geometry columns are stored in pack_length + format. </td> + </tr> + <tr> + <td>SIMPLE_PRIMARY_KEY</td> + <td>The primary key without any prefix. This is only included + if binlog_row_metadata=FULL and there is a primary key where every + key part covers an entire column.</td> + <td>A sequence of column indexes. The indexes are stored in pack_length + format.</td> + </tr> + <tr> + <td>PRIMARY_KEY_WITH_PREFIX</td> + <td>The primary key with some prefix. It doesn't appear together with + SIMPLE_PRIMARY_KEY. This is only included if + binlog_row_metadata=FULL and there is a primary key where some key + part covers a prefix of the column.</td> + <td>A sequence of column index and prefix length pairs. Both + column index and prefix length are in pack_length format. Prefix length + 0 means that the whole column value is used.</td> + </tr> + <tr> + <td>ENUM_AND_SET_DEFAULT_CHARSET</td> + <td>Charsets of ENUM and SET columns. It has the same layout as + DEFAULT_CHARSET. If there are SET or ENUM columns and + binlog_row_metadata=FULL, exactly one of + ENUM_AND_SET_DEFAULT_CHARSET and ENUM_AND_SET_COLUMN_CHARSET + appears (the encoder chooses the representation that uses the + least amount of space). Otherwise, none of them appears.</td> + <td>The same format as for DEFAULT_CHARSET, except it counts ENUM + and SET columns rather than character columns.</td> + </tr> + <tr> + <td>ENUM_AND_SET_COLUMN_CHARSET</td> + <td>Charsets of ENUM and SET columns. It has the same layout as + COLUMN_CHARSET. If there are SET or ENUM columns and + binlog_row_metadata=FULL, exactly one of + ENUM_AND_SET_DEFAULT_CHARSET and ENUM_AND_SET_COLUMN_CHARSET + appears (the encoder chooses the representation that uses the + least amount of space). Otherwise, none of them appears.</td> + <td>The same format as for COLUMN_CHARSET, except it counts ENUM + and SET columns rather than character columns.</td> + </tr> + </table> +*/ +class Table_map_event : public Binary_log_event { + public: + /** Constants representing offsets */ + enum Table_map_event_offset { + /** TM = "Table Map" */ + TM_MAPID_OFFSET = 0, + TM_FLAGS_OFFSET = 6 + }; + + typedef uint16_t flag_set; + + /** + DEFAULT_CHARSET and COLUMN_CHARSET don't appear together, and + ENUM_AND_SET_DEFAULT_CHARSET and ENUM_AND_SET_COLUMN_CHARSET don't + appear together. They are just alternative ways to pack character + set information. When binlogging, it logs character sets in the + way that occupies least storage. + + SIMPLE_PRIMARY_KEY and PRIMARY_KEY_WITH_PREFIX don't appear together. + SIMPLE_PRIMARY_KEY is for the primary keys which only use whole values of + pk columns. PRIMARY_KEY_WITH_PREFIX is + for the primary keys which just use part value of pk columns. + */ + enum Optional_metadata_field_type { + SIGNEDNESS = 1, // UNSIGNED flag of numeric columns + DEFAULT_CHARSET, /* Character set of string columns, optimized to + minimize space when many columns have the + same charset. */ + COLUMN_CHARSET, /* Character set of string columns, optimized to + minimize space when columns have many + different charsets. */ + COLUMN_NAME, + SET_STR_VALUE, // String value of SET columns + ENUM_STR_VALUE, // String value of ENUM columns + GEOMETRY_TYPE, // Real type of geometry columns + SIMPLE_PRIMARY_KEY, // Primary key without prefix + PRIMARY_KEY_WITH_PREFIX, // Primary key with prefix + ENUM_AND_SET_DEFAULT_CHARSET, /* Character set of enum and set + columns, optimized to minimize + space when many columns have the + same charset. */ + ENUM_AND_SET_COLUMN_CHARSET, /* Character set of enum and set + columns, optimized to minimize + space when many columns have the + same charset. */ + }; + + /** + Metadata_fields organizes m_optional_metadata into a structured format which + is easy to access. + */ + struct Optional_metadata_fields { + typedef std::pair<unsigned int, unsigned int> uint_pair; + typedef std::vector<std::string> str_vector; + + struct Default_charset { + Default_charset() : default_charset(0) {} + bool empty() const { return default_charset == 0; } + + // Default charset for the columns which are not in charset_pairs. + unsigned int default_charset; + + /* The uint_pair means <column index, column charset number>. */ + std::vector<uint_pair> charset_pairs; + }; + + // Contents of DEFAULT_CHARSET field are converted into Default_charset. + Default_charset m_default_charset; + // Contents of ENUM_AND_SET_DEFAULT_CHARSET are converted into + // Default_charset. + Default_charset m_enum_and_set_default_charset; + std::vector<bool> m_signedness; + // Character set number of every string column + std::vector<unsigned int> m_column_charset; + // Character set number of every ENUM or SET column. + std::vector<unsigned int> m_enum_and_set_column_charset; + std::vector<std::string> m_column_name; + // each str_vector stores values of one enum/set column + std::vector<str_vector> m_enum_str_value; + std::vector<str_vector> m_set_str_value; + std::vector<unsigned int> m_geometry_type; + /* + The uint_pair means <column index, prefix length>. Prefix length is 0 if + whole column value is used. + */ + std::vector<uint_pair> m_primary_key; + + /* + It parses m_optional_metadata and populates into above variables. + + @param[in] optional_metadata points to the begin of optional metadata + fields in table_map_event. + @param[in] optional_metadata_len length of optional_metadata field. + */ + Optional_metadata_fields(unsigned char *optional_metadata, + unsigned int optional_metadata_len); + // It is used to specify the validity of the deserialized structure + bool is_valid; + }; + + /** + <pre> + The buffer layout for fixed data part is as follows: + +-----------------------------------+ + | table_id | Reserved for future use| + +-----------------------------------+ + </pre> + + <pre> + The buffer layout for variable data part is as follows: + +--------------------------------------------------------------------------+ + | db len| db name | table len| table name | no of cols | array of col types| + +--------------------------------------------------------------------------+ + +---------------------------------------------+ + | metadata len | metadata block | m_null_bits | + +---------------------------------------------+ + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Table_map_event(const char *buf, const Format_description_event *fde); + + Table_map_event(const Table_id &tid, unsigned long colcnt, const char *dbnam, + size_t dblen, const char *tblnam, size_t tbllen) + : Binary_log_event(TABLE_MAP_EVENT), + m_table_id(tid), + m_data_size(0), + m_dbnam(""), + m_dblen(dblen), + m_tblnam(""), + m_tbllen(tbllen), + m_colcnt(colcnt), + m_field_metadata_size(0), + m_field_metadata(0), + m_null_bits(0), + m_optional_metadata_len(0), + m_optional_metadata(nullptr) { + if (dbnam) m_dbnam = std::string(dbnam, m_dblen); + if (tblnam) m_tblnam = std::string(tblnam, m_tbllen); + } + + virtual ~Table_map_event(); + + /** Event post header contents */ + Table_id m_table_id; + flag_set m_flags; + + size_t m_data_size; /** event data size */ + + /** Event body contents */ + std::string m_dbnam; + size_t m_dblen; + std::string m_tblnam; + size_t m_tbllen; + unsigned long m_colcnt; + unsigned char *m_coltype; + + /** + The size of field metadata buffer set by calling save_field_metadata() + */ + unsigned long m_field_metadata_size; + unsigned char *m_field_metadata; /** field metadata */ + unsigned char *m_null_bits; + unsigned int m_optional_metadata_len; + unsigned char *m_optional_metadata; + + Table_map_event() + : Binary_log_event(TABLE_MAP_EVENT), + m_coltype(0), + m_field_metadata_size(0), + m_field_metadata(0), + m_null_bits(0), + m_optional_metadata_len(0), + m_optional_metadata(nullptr) {} + + unsigned long long get_table_id() { return m_table_id.id(); } + std::string get_table_name() { return m_tblnam; } + std::string get_db_name() { return m_dbnam; } + +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &info); + void print_long_info(std::ostream &info); +#endif +}; + +/** + @class Rows_event + + Common base class for all row-containing binary log events. + + RESPONSIBILITIES + + - Provide an interface for adding an individual row to the event. + + @section Rows_event_binary_format Binary Format + + The Post-Header has the following components: + + <table> + <caption>Post-Header for Rows_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>table_id</td> + <td>6 bytes unsigned integer</td> + <td>The number that identifies the table</td> + </tr> + + <tr> + <td>flags</td> + <td>2 byte bitfield</td> + <td>Reserved for future use; currently always 0.</td> + </tr> + + </table> + + The Body has the following components: + + <table> + <caption>Body for Rows_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + + <tr> + <td>width</td> + <td>packed integer</td> + <td>Represents the number of columns in the table</td> + </tr> + + <tr> + <td>cols</td> + <td>Bitfield, variable sized</td> + <td>Indicates whether each column is used, one bit per column. + For this field, the amount of storage required is + INT((width + 7) / 8) bytes. </td> + </tr> + + <tr> + <td>extra_row_info</td> + <td>An object of class Extra_row_info</td> + <td>The class Extra_row_info will be storing the information related + to m_extra_row_ndb_info and partition info (partition_id and + source_partition_id). At any given time a Rows_event can have both, one + or none of ndb_info and partition_info present as part of Rows_event. + In case both ndb_info and partition_info are present then below will + be the order in which they will be stored. + + @verbatim + +----------+--------------------------------------+ + |type_code | extra_row_ndb_info | + +--- ------+--------------------------------------+ + | NDB |Len of ndb_info |Format |ndb_data | + | 1 byte |1 byte |1 byte |len - 2 byte | + +----------+----------------+-------+-------------+ + + In case of INSERT/DELETE + +-----------+----------------+ + | type_code | partition_info | + +-----------+----------------+ + | PART | partition_id | + | (1 byte) | 2 byte | + +-----------+----------------+ + + In case of UPDATE + +-----------+------------------------------------+ + | type_code | partition_info | + +-----------+--------------+---------------------+ + | PART | partition_id | source_partition_id | + | (1 byte) | 2 byte | 2 byte | + +-----------+--------------+---------------------+ + + source_partition_id is used only in the case of Update_event + to log the partition_id of the source partition. + + @endverbatim + This is the format for any information stored as extra_row_info. + type_code is not a part of the class Extra_row_info as it is a constant + values used at the time of serializing and decoding the event. + </td> + </tr> + + <tr> + <td>columns_before_image</td> + <td>vector of elements of type uint8_t</td> + <td>For DELETE and UPDATE only. + Bit-field indicating whether each column is used + one bit per column. For this field, the amount of storage + required for N columns is INT((N + 7) / 8) bytes.</td> + </tr> + + <tr> + <td>columns_after_image</td> + <td>vector of elements of type uint8_t</td> + <td>For WRITE and UPDATE only. + Bit-field indicating whether each column is used in the + UPDATE_ROWS_EVENT and WRITE_ROWS_EVENT after-image; one bit per column. + For this field, the amount of storage required for N columns + is INT((N + 7) / 8) bytes. + + @verbatim + +-------------------------------------------------------+ + | Event Type | Cols_before_image | Cols_after_image | + +-------------------------------------------------------+ + | DELETE | Deleted row | NULL | + | INSERT | NULL | Inserted row | + | UPDATE | Old row | Updated row | + +-------------------------------------------------------+ + @endverbatim + </td> + </tr> + + <tr> + <td>row</td> + <td>vector of elements of type uint8_t</td> + <td> A sequence of zero or more rows. The end is determined by the size + of the event. Each row has the following format: + - A Bit-field indicating whether each field in the row is NULL. + Only columns that are "used" according to the second field in + the variable data part are listed here. If the second field in + the variable data part has N one-bits, the amount of storage + required for this field is INT((N + 7) / 8) bytes. + - The row-image, containing values of all table fields. This only + lists table fields that are used (according to the second field + of the variable data part) and non-NULL (according to the + previous field). In other words, the number of values listed here + is equal to the number of zero bits in the previous field. + (not counting padding bits in the last byte). + @verbatim + For example, if a INSERT statement inserts into 4 columns of a + table, N= 4 (in the formula above). + length of bitmask= (4 + 7) / 8 = 1 + Number of fields in the row= 4. + + +------------------------------------------------+ + |Null_bit_mask(4)|field-1|field-2|field-3|field 4| + +------------------------------------------------+ + @endverbatim + </td> + </tr> + </table> +*/ +class Rows_event : public Binary_log_event { + public: + /** + These definitions allow to combine the flags into an + appropriate flag set using the normal bitwise operators. The + implicit conversion from an enum-constant to an integer is + accepted by the compiler, which is then used to set the real set + of flags. + */ + enum enum_flag { + /** Last event of a statement */ + STMT_END_F = (1U << 0), + /** Value of the OPTION_NO_FOREIGN_KEY_CHECKS flag in thd->options */ + NO_FOREIGN_KEY_CHECKS_F = (1U << 1), + /** Value of the OPTION_RELAXED_UNIQUE_CHECKS flag in thd->options */ + RELAXED_UNIQUE_CHECKS_F = (1U << 2), + /** + Indicates that rows in this event are complete, that is contain + values for all columns of the table. + */ + COMPLETE_ROWS_F = (1U << 3) + }; + + /** + Constructs an event directly. The members are assigned default values. + + @param type_arg Type of ROW_EVENT. Expected types are: + - WRITE_ROWS_EVENT, WRITE_ROWS_EVENT_V1 + - UPDATE_ROWS_EVENT, UPDATE_ROWS_EVENT_V1, + PARTIAL_UPDATE_ROWS_EVENT + - DELETE_ROWS_EVENT, DELETE_ROWS_EVENT_V1 + */ + explicit Rows_event(Log_event_type type_arg) + : Binary_log_event(type_arg), + m_table_id(0), + m_width(0), + columns_before_image(0), + columns_after_image(0), + row(0) {} + /** + The constructor is responsible for decoding the event contained in + the buffer. + + <pre> + The buffer layout for fixed data part is as follows + +------------------------------------+ + | table_id | reserved for future use | + +------------------------------------+ + </pre> + + <pre> + The buffer layout for variable data part is as follows + +------------------------------------------------------------------+ + | var_header_len | column_before_image | columns_after_image | row | + +------------------------------------------------------------------+ + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Rows_event(const char *buf, const Format_description_event *fde); + + virtual ~Rows_event(); + + protected: + Log_event_type m_type; /** Actual event type */ + + /** Post header content */ + Table_id m_table_id; + uint16_t m_flags; /** Flags for row-level events */ + + /* Body of the event */ + unsigned long m_width; /** The width of the columns bitmap */ + uint32_t n_bits_len; /** value determined by (m_width + 7) / 8 */ + uint16_t var_header_len; + + std::vector<uint8_t> columns_before_image; + std::vector<uint8_t> columns_after_image; + std::vector<uint8_t> row; + + public: + class Extra_row_info { + private: + /** partition_id for a row in a partitioned table */ + int m_partition_id; + /** + It is the partition_id of the source partition in case + of Update_event, the target's partition_id is m_partition_id. + This variable is used only in case of Update_event. + */ + int m_source_partition_id; + /** The extra row info provided by NDB */ + unsigned char *m_extra_row_ndb_info; + + public: + Extra_row_info() + : m_partition_id(UNDEFINED), + m_source_partition_id(UNDEFINED), + m_extra_row_ndb_info(nullptr) {} + + Extra_row_info(const Extra_row_info &) = delete; + + int get_partition_id() const { return m_partition_id; } + void set_partition_id(int partition_id) { + BAPI_ASSERT(partition_id <= 65535); + m_partition_id = partition_id; + } + + int get_source_partition_id() const { return m_source_partition_id; } + void set_source_partition_id(int source_partition_id) { + BAPI_ASSERT(source_partition_id <= 65535); + m_source_partition_id = source_partition_id; + } + + unsigned char *get_ndb_info() const { return m_extra_row_ndb_info; } + void set_ndb_info(const unsigned char *ndb_info, size_t len) { + BAPI_ASSERT(!have_ndb_info()); + m_extra_row_ndb_info = + static_cast<unsigned char *>(bapi_malloc(len, 16 /* flags */)); + std::copy(ndb_info, ndb_info + len, m_extra_row_ndb_info); + } + /** + Compares the extra_row_info in a Row event, it checks three things + 1. The m_extra_row_ndb_info pointers. It compares their significant bytes. + 2. Partition_id + 3. source_partition_id + + @return + true all the above variables are same in the event and the one passed + in parameter. + false Any of the above variable has a different value. + */ + bool compare_extra_row_info(const unsigned char *ndb_info_arg, + int part_id_arg, int source_part_id); + + bool have_part() const { return m_partition_id != UNDEFINED; } + + bool have_ndb_info() const { return m_extra_row_ndb_info != nullptr; } + size_t get_ndb_length(); + size_t get_part_length(); + ~Extra_row_info(); + + static const int UNDEFINED{INT_MAX}; + }; + Extra_row_info m_extra_row_info; + + unsigned long long get_table_id() const { return m_table_id.id(); } + + enum_flag get_flags() const { return static_cast<enum_flag>(m_flags); } + + uint32_t get_null_bits_len() const { return n_bits_len; } + + unsigned long get_width() const { return m_width; } + + static std::string get_flag_string(enum_flag flag) { + std::string str = ""; + if (flag & STMT_END_F) str.append(" Last event of the statement"); + if (flag & NO_FOREIGN_KEY_CHECKS_F) str.append(" No foreign Key checks"); + if (flag & RELAXED_UNIQUE_CHECKS_F) str.append(" No unique key checks"); + if (flag & COMPLETE_ROWS_F) str.append(" Complete Rows"); + if (flag & ~(STMT_END_F | NO_FOREIGN_KEY_CHECKS_F | + RELAXED_UNIQUE_CHECKS_F | COMPLETE_ROWS_F)) + str.append("Unknown Flag"); + return str; + } +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &info); + void print_long_info(std::ostream &info); +#endif + + template <class Iterator_value_type> + friend class Row_event_iterator; +}; + +/** + @class Write_rows_event + + Log row insertions. The event contain several insert/update rows + for a table. Note that each event contains only rows for one table. + + @section Write_rows_event_binary_format Binary Format +*/ +class Write_rows_event : public virtual Rows_event { + public: + Write_rows_event(const char *buf, const Format_description_event *fde); + Write_rows_event() : Rows_event(WRITE_ROWS_EVENT) {} +}; + +/** + @class Update_rows_event + + Log row updates with a before image. The event contain several + update rows for a table. Note that each event contains only rows for + one table. + + Also note that the row data consists of pairs of row data: one row + for the old data and one row for the new data. + + @section Update_rows_event_binary_format Binary Format +*/ +class Update_rows_event : public virtual Rows_event { + public: + Update_rows_event(const char *buf, const Format_description_event *fde); + Update_rows_event(Log_event_type event_type) : Rows_event(event_type) {} +}; + +/** + @class Delete_rows_event + + Log row deletions. The event contain several delete rows for a + table. Note that each event contains only rows for one table. + + RESPONSIBILITIES + + - Act as a container for rows that has been deleted on the master + and should be deleted on the slave. + + @section Delete_rows_event_binary_format Binary Format +*/ +class Delete_rows_event : public virtual Rows_event { + public: + Delete_rows_event(const char *buf, const Format_description_event *fde); + Delete_rows_event() : Rows_event(DELETE_ROWS_EVENT) {} +}; + +/** + @class Rows_query_event + + Rows query event type, which is a subclass + of the Ignorable_event, to record the original query for the rows + events in RBR. This event can be used to display the original query as + comments by SHOW BINLOG EVENTS query, or mysqlbinlog client when the + --verbose option is given twice + + @section Rows_query_var_event_binary_format Binary Format + + The Post-Header for this event type is empty. The Body has one + component: + + <table> + <caption>Body for Rows_query_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>m_rows_query</td> + <td>char array</td> + <td>Records the original query executed in RBR </td> + </tr> + </table> +*/ +class Rows_query_event : public virtual Ignorable_event { + public: + /** + It is used to write the original query in the binlog file in case of RBR + when the session flag binlog_rows_query_log_events is set. + + <pre> + The buffer layout is as follows: + +------------------------------------+ + | The original query executed in RBR | + +------------------------------------+ + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + + Rows_query_event(const char *buf, const Format_description_event *fde); + /** + It is the minimal constructor, and all it will do is set the type_code as + ROWS_QUERY_LOG_EVENT in the header object in Binary_log_event. + */ + Rows_query_event() : Ignorable_event(ROWS_QUERY_LOG_EVENT), m_rows_query(0) {} + + virtual ~Rows_query_event(); + + protected: + char *m_rows_query; +}; +} // namespace binary_log + +/** + @} (end of group Replication) +*/ +#endif /* ROWS_EVENT_INCLUDED */ diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/statement_events.h b/contrib/libs/libmysql_r/libbinlogevents/include/statement_events.h new file mode 100644 index 0000000000..cb8ba51220 --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/statement_events.h @@ -0,0 +1,1074 @@ +/* Copyright (c) 2014, 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 */ + +/** + @addtogroup Replication + @{ + + @file statement_events.h + + @brief Contains the classes representing statement events occurring in the + replication stream. Each event is represented as a byte sequence with logical + divisions as event header, event specific data and event footer. The header + and footer are common to all the events and are represented as two different + subclasses. +*/ + +#ifndef STATEMENT_EVENT_INCLUDED +#define STATEMENT_EVENT_INCLUDED + +#include "control_events.h" +#include "mysql/udf_registration_types.h" + +namespace binary_log { +/** + The following constant represents the maximum of MYSQL_XID domain. + The maximum XID value practically is never supposed to grow beyond UINT64 + range. +*/ +const uint64_t INVALID_XID = 0xffffffffffffffffULL; + +/** + @class Query_event + + A @c Query_event is created for each query that modifies the + database, unless the query is logged row-based. + + @section Query_event_binary_format Binary format + + See @ref Binary_log_event_binary_format "Binary format for log events" for + a general discussion and introduction to the binary format of binlog + events. + + The Post-Header has five components: + + <table> + <caption>Post-Header for Query_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>thread_id</td> + <td>4 byte unsigned integer</td> + <td>The ID of the thread that issued this statement. It is needed for + temporary tables.</td> + </tr> + + <tr> + <td>query_exec_time</td> + <td>4 byte unsigned integer</td> + <td>The time from when the query started to when it was logged in + the binlog, in seconds.</td> + </tr> + + <tr> + <td>db_len</td> + <td>1 byte integer</td> + <td>The length of the name of the currently selected database.</td> + </tr> + + <tr> + <td>error_code</td> + <td>2 byte unsigned integer</td> + <td>Error code generated by the master. If the master fails, the + slave will fail with the same error code. + </td> + </tr> + + <tr> + <td>status_vars_len</td> + <td>2 byte unsigned integer</td> + <td>The length of the status_vars block of the Body, in bytes. This is not + present for binlog version 1 and 3. See + @ref Query_event_status_vars "below". + </td> + </tr> + </table> + + The Body has the following components: + + <table> + <caption>Body for Query_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>@anchor Query_event_status_vars status_vars</td> + <td>status_vars_len bytes</td> + <td>Zero or more status variables. Each status variable consists + of one byte identifying the variable stored, followed by the value + of the variable. The possible variables are listed separately in + the table @ref Table_query_event_status_vars "below". MySQL + always writes events in the order defined below; however, it is + capable of reading them in any order. </td> + </tr> + + <tr> + <td>m_db</td> + <td>db_len + 1</td> + <td>The currently selected database, as a null-terminated string. + + (The trailing zero is redundant since the length is already known; + it is db_len from Post-Header.) + </td> + </tr> + + <tr> + <td>m_query</td> + <td>variable length string without trailing zero, extending to the + end of the event (determined by the length field of the + Common-Header) + </td> + <td>The SQL query.</td> + </tr> + </table> + + The following table lists the status variables that may appear in + the status_vars field. + + @anchor Table_query_event_status_vars + <table> + <caption>Status variables for Query_event</caption> + + <tr> + <th>Status variable</th> + <th>1 byte identifier</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>flags2</td> + <td>Q_FLAGS2_CODE == 0</td> + <td>4 byte bitfield</td> + <td>The flags in @c thd->options, binary AND-ed with @c + OPTIONS_WRITTEN_TO_BIN_LOG. The @c thd->options bitfield contains + options for "SELECT". @c OPTIONS_WRITTEN identifies those options + that need to be written to the binlog (not all do). Specifically, + @c OPTIONS_WRITTEN_TO_BIN_LOG equals (@c OPTION_AUTO_IS_NULL | @c + OPTION_NO_FOREIGN_KEY_CHECKS | @c OPTION_RELAXED_UNIQUE_CHECKS | + @c OPTION_NOT_AUTOCOMMIT), or 0x0c084000 in hex. + + These flags correspond to the SQL variables SQL_AUTO_IS_NULL, + FOREIGN_KEY_CHECKS, UNIQUE_CHECKS, and AUTOCOMMIT, documented in + the "SET Syntax" section of the MySQL Manual. + + This field is always written to the binlog in version >= 5.0, and + never written in version < 5.0. + </td> + </tr> + + <tr> + <td>sql_mode</td> + <td>Q_SQL_MODE_CODE == 1</td> + <td>8 byte bitfield</td> + <td>The @c sql_mode variable. See the section "SQL Modes" in the + MySQL manual, and see sql_class.h for a list of the possible + flags. Currently (2007-10-04), the following flags are available: + <pre> + MODE_REAL_AS_FLOAT==0x1 + MODE_PIPES_AS_CONCAT==0x2 + MODE_ANSI_QUOTES==0x4 + MODE_IGNORE_SPACE==0x8 + MODE_NOT_USED==0x10 + MODE_ONLY_FULL_GROUP_BY==0x20 + MODE_NO_UNSIGNED_SUBTRACTION==0x40 + MODE_NO_DIR_IN_CREATE==0x80 + MODE_ANSI==0x80000 + MODE_NO_AUTO_VALUE_ON_ZERO==0x100000 + MODE_NO_BACKSLASH_ESCAPES==0x200000 + MODE_STRICT_TRANS_TABLES==0x400000 + MODE_STRICT_ALL_TABLES==0x800000 + MODE_NO_ZERO_IN_DATE==0x1000000 + MODE_NO_ZERO_DATE==0x2000000 + MODE_INVALID_DATES==0x4000000 + MODE_ERROR_FOR_DIVISION_BY_ZERO==0x8000000 + MODE_TRADITIONAL==0x10000000 + MODE_HIGH_NOT_PRECEDENCE==0x40000000 + MODE_PAD_CHAR_TO_FULL_LENGTH==0x80000000 + MODE_TIME_TRUNCATE_FRACTIONAL==0x100000000 + </pre> + All these flags are replicated from the server. However, all + flags except @c MODE_NO_DIR_IN_CREATE are honored by the slave; + the slave always preserves its old value of @c + MODE_NO_DIR_IN_CREATE. + + This field is always written to the binlog. + </td> + </tr> + + <tr> + <td>catalog</td> + <td>Q_CATALOG_NZ_CODE == 6</td> + <td>Variable-length string: the length in bytes (1 byte) followed + by the characters (at most 255 bytes) + </td> + <td>Stores the client's current catalog. Every database belongs + to a catalog, the same way that every table belongs to a + database. Currently, there is only one catalog, "std". + + This field is written if the length of the catalog is > 0; + otherwise it is not written. + </td> + </tr> + + <tr> + <td>auto_increment</td> + <td>Q_AUTO_INCREMENT == 3</td> + <td>two 2 byte unsigned integers, totally 2+2=4 bytes</td> + + <td>The two variables auto_increment_increment and + auto_increment_offset, in that order. For more information, see + "System variables" in the MySQL manual. + + This field is written if auto_increment > 1. Otherwise, it is not + written. + </td> + </tr> + + <tr> + <td>charset</td> + <td>Q_CHARSET_CODE == 4</td> + <td>three 2 byte unsigned integers, totally 2+2+2=6 bytes</td> + <td>The three variables character_set_client, + collation_connection, and collation_server, in that order. + character_set_client is a code identifying the character set and + collation used by the client to encode the query. + collation_connection identifies the character set and collation + that the master converts the query to when it receives it; this is + useful when comparing literal strings. collation_server is the + default character set and collation used when a new database is + created. + + See also "Connection Character Sets and Collations" in the MySQL + 5.1 manual. + + All three variables are codes identifying a (character set, + collation) pair. To see which codes map to which pairs, run the + query "SELECT id, character_set_name, collation_name FROM + COLLATIONS". + + Cf. Q_CHARSET_DATABASE_CODE below. + + This field is always written. + </td> + </tr> + + <tr> + <td>time_zone</td> + <td>Q_TIME_ZONE_CODE == 5</td> + <td>Variable-length string: the length in bytes (1 byte) followed + by the characters (at most 255 bytes). + <td>The time_zone of the master. + + See also "System Variables" and "MySQL Server Time Zone Support" + in the MySQL manual. + + This field is written if the length of the time zone string is > + 0; otherwise, it is not written. + </td> + </tr> + + <tr> + <td>lc_time_names_number</td> + <td>Q_LC_TIME_NAMES_CODE == 7</td> + <td>2 byte integer</td> + <td>A code identifying a table of month and day names. The + mapping from codes to languages is defined in @c sql_locale.cc. + + This field is written if it is not 0, i.e., if the locale is not + en_US. + </td> + </tr> + + <tr> + <td>charset_database_number</td> + <td>Q_CHARSET_DATABASE_CODE == 8</td> + <td>2 byte integer</td> + + <td>The value of the collation_database system variable (in the + source code stored in @c thd->variables.collation_database), which + holds the code for a (character set, collation) pair as described + above (see Q_CHARSET_CODE). + + collation_database was used in old versions (???WHEN). Its value + was loaded when issuing a "use db" query and could be changed by + issuing a "SET collation_database=xxx" query. It used to affect + the "LOAD DATA INFILE" and "CREATE TABLE" commands. + + In newer versions, "CREATE TABLE" has been changed to take the + character set from the database of the created table, rather than + the character set of the current database. This makes a + difference when creating a table in another database than the + current one. "LOAD DATA INFILE" has not yet changed to do this, + but there are plans to eventually do it, and to make + collation_database read-only. + + This field is written if it is not 0. + </td> + </tr> + <tr> + <td>table_map_for_update</td> + <td>Q_TABLE_MAP_FOR_UPDATE_CODE == 9</td> + <td>8 byte integer</td> + + <td>The value of the table map that is to be updated by the + multi-table update query statement. Every bit of this variable + represents a table, and is set to 1 if the corresponding table is + to be updated by this statement. + + The value of this variable is set when executing a multi-table update + statement and used by slave to apply filter rules without opening + all the tables on slave. This is required because some tables may + not exist on slave because of the filter rules. + </td> + </tr> + <tr> + <td>master_data_written</td> + <td>Q_MASTER_DATA_WRITTEN_CODE == 10</td> + <td>4 byte bitfield</td> + + <td>The value of the original length of a Query_event that comes from a + master. Master's event is relay-logged with storing the original size of + event in this field by the IO thread. The size is to be restored by reading + Q_MASTER_DATA_WRITTEN_CODE-marked event from the relay log. + + This field is not written to slave's server binlog by the SQL thread. + This field only exists in relay logs where master has binlog_version<4 i.e. + server_version < 5.0 and the slave has binlog_version=4. + </td> + </tr> + <tr> + <td>binlog_invoker</td> + <td>Q_INVOKER == 11</td> + <td>2 Variable-length strings: the length in bytes (1 byte) followed + by characters (user), again followed by length in bytes (1 byte) followed + by characters(host)</td> + + <td>The value of boolean variable m_binlog_invoker is set TRUE if + CURRENT_USER() is called in account management statements. SQL thread + uses it as a default definer in CREATE/ALTER SP, SF, Event, TRIGGER or + VIEW statements. + + The field Q_INVOKER has length of user stored in 1 byte followed by the + user string which is assigned to 'user' and the length of host stored in + 1 byte followed by host string which is assigned to 'host'. + </td> + </tr> + <tr> + <td>mts_accessed_dbs</td> + <td>Q_UPDATED_DB_NAMES == 12</td> + <td>1 byte character, and a 2-D array</td> + <td>The total number and the names to of the databases accessed is stored, + to be propagated to the slave in order to facilitate the parallel + applying of the Query events. + </td> + </tr> + <tr> + <td>explicit_defaults_ts</td> + <td>Q_EXPLICIT_DEFAULTS_FOR_TIMESTAMP</td> + <td>1 byte boolean</td> + <td>Stores master connection @@session.explicit_defaults_for_timestamp when + CREATE and ALTER operate on a table with a TIMESTAMP column. </td> + </tr> + <tr> + <td>ddl_xid</td> + <td>Q_DDL_LOGGED_WITH_XID</td> + <td>8 byte integer</td> + <td>Stores variable carrying xid info of 2pc-aware (recoverable) DDL + queries. </td> + </tr> + <tr> + <td>default_collation_for_utf8mb4_number</td> + <td>Q_DEFAULT_COLLATION_FOR_UTF8MB4</td> + <td>2 byte integer</td> + <td>Stores variable carrying the the default collation for the utf8mb4 + character set. Mainly used to support replication 5.7- master to a 8.0+ + slave. + </td> + </tr> + <tr> + <td>sql_require_primary_key</td> + <td>Q_SQL_REQUIRE_PRIMARY_KEY</td> + <td>2 byte integer</td> + <td>Value of the config variable sql_require_primary_key</td> + </tr> + <tr> + <td>default_table_encryption</td> + <td>Q_DEFAULT_TABLE_ENCRYPTION</td> + <td>2 byte integer</td> + <td>Value of the config variable default_table_encryption</td> + </tr> + </table> + + @subsection Query_event_notes_on_previous_versions Notes on Previous Versions + + * Status vars were introduced in version 5.0. To read earlier + versions correctly, check the length of the Post-Header. + + * The status variable Q_CATALOG_CODE == 2 existed in MySQL 5.0.x, + where 0<=x<=3. It was identical to Q_CATALOG_CODE, except that the + string had a trailing '\0'. The '\0' was removed in 5.0.4 since it + was redundant (the string length is stored before the string). The + Q_CATALOG_CODE will never be written by a new master, but can still + be understood by a new slave. + + * See Q_CHARSET_DATABASE_CODE in the table above. + + * When adding new status vars, please don't forget to update the + MAX_SIZE_LOG_EVENT_STATUS. + +*/ + +class Query_event : public Binary_log_event { + public: + /** query event post-header */ + enum Query_event_post_header_offset { + Q_THREAD_ID_OFFSET = 0, + Q_EXEC_TIME_OFFSET = 4, + Q_DB_LEN_OFFSET = 8, + Q_ERR_CODE_OFFSET = 9, + Q_STATUS_VARS_LEN_OFFSET = 11, + Q_DATA_OFFSET = QUERY_HEADER_LEN + }; + + /* these are codes, not offsets; not more than 256 values (1 byte). */ + enum Query_event_status_vars { + Q_FLAGS2_CODE = 0, + Q_SQL_MODE_CODE, + /* + Q_CATALOG_CODE is catalog with end zero stored; it is used only by MySQL + 5.0.x where 0<=x<=3. We have to keep it to be able to replicate these + old masters. + */ + Q_CATALOG_CODE, + Q_AUTO_INCREMENT, + Q_CHARSET_CODE, + Q_TIME_ZONE_CODE, + /* + Q_CATALOG_NZ_CODE is catalog withOUT end zero stored; it is used by MySQL + 5.0.x where x>=4. Saves one byte in every Query_event in binlog, + compared to Q_CATALOG_CODE. The reason we didn't simply re-use + Q_CATALOG_CODE is that then a 5.0.3 slave of this 5.0.x (x>=4) + master would crash (segfault etc) because it would expect a 0 when there + is none. + */ + Q_CATALOG_NZ_CODE, + Q_LC_TIME_NAMES_CODE, + Q_CHARSET_DATABASE_CODE, + Q_TABLE_MAP_FOR_UPDATE_CODE, + /* It is just a placeholder after 8.0.2*/ + Q_MASTER_DATA_WRITTEN_CODE, + Q_INVOKER, + /* + Q_UPDATED_DB_NAMES status variable collects information of accessed + databases i.e. the total number and the names to be propagated to the + slave in order to facilitate the parallel applying of the Query events. + */ + Q_UPDATED_DB_NAMES, + Q_MICROSECONDS, + /* + A old (unused now) code for Query_log_event status similar to G_COMMIT_TS. + */ + Q_COMMIT_TS, + /* + An old (unused after migration to Gtid_event) code for + Query_log_event status, similar to G_COMMIT_TS2. + */ + Q_COMMIT_TS2, + /* + The master connection @@session.explicit_defaults_for_timestamp which + is recorded for queries, CREATE and ALTER table that is defined with + a TIMESTAMP column, that are dependent on that feature. + For pre-WL6292 master's the associated with this code value is zero. + */ + Q_EXPLICIT_DEFAULTS_FOR_TIMESTAMP, + /* + The variable carries xid info of 2pc-aware (recoverable) DDL queries. + */ + Q_DDL_LOGGED_WITH_XID, + /* + This variable stores the default collation for the utf8mb4 character set. + Used to support cross-version replication. + */ + Q_DEFAULT_COLLATION_FOR_UTF8MB4, + + /* + Replicate sql_require_primary_key. + */ + Q_SQL_REQUIRE_PRIMARY_KEY, + + /* + Replicate default_table_encryption. + */ + Q_DEFAULT_TABLE_ENCRYPTION + }; + const char *query; + const char *db; + const char *catalog; + const char *time_zone_str; + + protected: + const char *user; + size_t user_len; + const char *host; + size_t host_len; + + /* Required by the MySQL server class Log_event::Query_event */ + unsigned long data_len; + /* + Copies data into the buffer in the following fashion + +--------+-----------+------+------+---------+----+-------+----+ + | catlog | time_zone | user | host | db name | \0 | Query | \0 | + +--------+-----------+------+------+---------+----+-------+----+ + */ + int fill_data_buf(unsigned char *dest, unsigned long len); + + public: + /* data members defined in order they are packed and written into the log */ + uint32_t thread_id; + uint32_t query_exec_time; + size_t db_len; + uint16_t error_code; + /* + We want to be able to store a variable number of N-bit status vars: + (generally N=32; but N=64 for SQL_MODE) a user may want to log the number + of affected rows (for debugging) while another does not want to lose 4 + bytes in this. + The storage on disk is the following: + status_vars_len is part of the post-header, + status_vars are in the variable-length part, after the post-header, before + the db & query. + status_vars on disk is a sequence of pairs (code, value) where 'code' means + 'sql_mode', 'affected' etc. Sometimes 'value' must be a short string, so + its first byte is its length. For now the order of status vars is: + flags2 - sql_mode - catalog - autoinc - charset + We should add the same thing to Load_event, but in fact + LOAD DATA INFILE is going to be logged with a new type of event (logging of + the plain text query), so Load_event would be frozen, so no need. The + new way of logging LOAD DATA INFILE would use a derived class of + Query_event, so automatically benefit from the work already done for + status variables in Query_event. + */ + uint16_t status_vars_len; + /* + If we already know the length of the query string + we pass it with q_len, so we would not have to call strlen() + otherwise, set it to 0, in which case, we compute it with strlen() + */ + size_t q_len; + + /* The members below represent the status variable block */ + + /* + 'flags2' is a second set of flags (on top of those in Log_event), for + session variables. These are thd->options which is & against a mask + (OPTIONS_WRITTEN_TO_BIN_LOG). + flags2_inited helps make a difference between flags2==0 (3.23 or 4.x + master, we don't know flags2, so use the slave server's global options) and + flags2==0 (5.0 master, we know this has a meaning of flags all down which + must influence the query). + */ + bool flags2_inited; + bool sql_mode_inited; + bool charset_inited; + + uint32_t flags2; + /* In connections sql_mode is 32 bits now but will be 64 bits soon */ + uint64_t sql_mode; + uint16_t auto_increment_increment, auto_increment_offset; + char charset[6]; + size_t time_zone_len; /* 0 means uninited */ + /* + Binlog format 3 and 4 start to differ (as far as class members are + concerned) from here. + */ + size_t catalog_len; // <= 255 char; 0 means uninited + uint16_t lc_time_names_number; /* 0 means en_US */ + uint16_t charset_database_number; + /* + map for tables that will be updated for a multi-table update query + statement, for other query statements, this will be zero. + */ + uint64_t table_map_for_update; + /* + The following member gets set to OFF or ON value when the + Query-log-event is marked as dependent on + @@explicit_defaults_for_timestamp. That is the member is relevant + to queries that declare TIMESTAMP column attribute, like CREATE + and ALTER. + The value is set to @c TERNARY_OFF when @@explicit_defaults_for_timestamp + encoded value is zero, otherwise TERNARY_ON. + */ + enum enum_ternary { + TERNARY_UNSET, + TERNARY_OFF, + TERNARY_ON + } explicit_defaults_ts; + /* + number of updated databases by the query and their names. This info + is requested by both Coordinator and Worker. + */ + unsigned char mts_accessed_dbs; + char mts_accessed_db_names[MAX_DBS_IN_EVENT_MTS][NAME_LEN]; + /* XID value when the event is a 2pc-capable DDL */ + uint64_t ddl_xid; + /* Default collation for the utf8mb4 set. Used in cross-version replication */ + uint16_t default_collation_for_utf8mb4_number; + uint8_t sql_require_primary_key; + + uint8_t default_table_encryption; + + /** + The constructor will be used while creating a Query_event, to be + written to the binary log. + */ + Query_event(const char *query_arg, const char *catalog_arg, + const char *db_arg, uint32_t query_length, + unsigned long thread_id_arg, unsigned long long sql_mode_arg, + unsigned long auto_increment_increment_arg, + unsigned long auto_increment_offset_arg, unsigned int number, + unsigned long long table_map_for_update_arg, int errcode); + + /** + The constructor receives a buffer and instantiates a Query_event filled in + with the data from the buffer + + <pre> + The fixed event data part buffer layout is as follows: + +---------------------------------------------------------------------+ + | thread_id | query_exec_time | db_len | error_code | status_vars_len | + +---------------------------------------------------------------------+ + </pre> + + <pre> + The fixed event data part buffer layout is as follows: + +--------------------------------------------+ + | Zero or more status variables | db | query | + +--------------------------------------------+ + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + @param event_type Required to determine whether the event type is + QUERY_EVENT or EXECUTE_LOAD_QUERY_EVENT + */ + Query_event(const char *buf, const Format_description_event *fde, + Log_event_type event_type); + /** + The simplest constructor that could possibly work. This is used for + creating static objects that have a special meaning and are invisible + to the log. + */ + Query_event(Log_event_type type_arg = QUERY_EVENT); + virtual ~Query_event() {} + +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &info); + void print_long_info(std::ostream &info); +#endif +}; + +/* + Check how many bytes are available on buffer. + + @param buf_start Pointer to buffer start. + @param buf_current Pointer to the current position on buffer. + @param buf_len Buffer length. + + @return Number of bytes available on event buffer. +*/ +template <class T> +T available_buffer(const char *buf_start, const char *buf_current, T buf_len) { + /* Sanity check */ + if (buf_current < buf_start || + buf_len < static_cast<T>(buf_current - buf_start)) + return static_cast<T>(0); + + return static_cast<T>(buf_len - (buf_current - buf_start)); +} + +/** + Check if jump value is within buffer limits. + + @param jump Number of positions we want to advance. + @param buf_start Pointer to buffer start + @param buf_current Pointer to the current position on buffer. + @param buf_len Buffer length. + + @retval True If jump value is within buffer limits. + @retval False Otherwise. +*/ +template <class T> +bool valid_buffer_range(T jump, const char *buf_start, const char *buf_current, + T buf_len) { + return (jump <= available_buffer(buf_start, buf_current, buf_len)); +} + +/** + @class User_var_event + + Written every time a statement uses a user variable; precedes other + events for the statement. Indicates the value to use for the user + variable in the next statement. This is written only before a QUERY_EVENT + and is not used with row-based logging + + The Post-Header has following components: + + <table> + <caption>Post-Header for Format_description_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>Value_type</td> + <td>enum</td> + <td>The user variable type.</td> + </tr> + <tr> + <td>User_var_event_data</td> + <td>enum</td> + <td>User_var event data</td> + </tr> + <tr> + <td>name</td> + <td>const char pointer</td> + <td>User variable name.</td> + </tr> + <tr> + <td>name_len</td> + <td>unsigned int</td> + <td>Length of the user variable name</td> + </tr> + <tr> + <td>val</td> + <td>char pointer</td> + <td>value of the user variable.</td> + </tr> + <tr> + <td>val_len</td> + <td>unsigned long</td> + <td>Length of the value of the user variable</td> + </tr> + <tr> + <td>type</td> + <td>enum Value_type</td> + <td>Type of the user variable</td> + </tr> + <tr> + <td>charset_number</td> + <td>unsigned int</td> + <td>The number of the character set for the user variable (needed for a + string variable). The character set number is really a collation + number that indicates a character set/collation pair.</td> + </tr> + <tr> + <td>is_null</td> + <td>bool</td> + <td>Non-zero if the variable value is the SQL NULL value, 0 otherwise.</td> + </tr> + </table> +*/ +class User_var_event : public Binary_log_event { + public: + using Value_type = Item_result; + enum { UNDEF_F, UNSIGNED_F }; + enum User_var_event_data { + UV_VAL_LEN_SIZE = 4, + UV_VAL_IS_NULL = 1, + UV_VAL_TYPE_SIZE = 1, + UV_NAME_LEN_SIZE = 4, + UV_CHARSET_NUMBER_SIZE = 4 + }; + + /** + This constructor will initialize the instance variables and the type_code, + it will be used only by the server code. + */ + User_var_event(const char *name_arg, unsigned int name_len_arg, char *val_arg, + unsigned long val_len_arg, Value_type type_arg, + unsigned int charset_number_arg, unsigned char flags_arg) + : Binary_log_event(USER_VAR_EVENT), + name(bapi_strndup(name_arg, name_len_arg)), + name_len(name_len_arg), + val(val_arg), + val_len(val_len_arg), + type(type_arg), + charset_number(charset_number_arg), + is_null(!val), + flags(flags_arg) {} + + /** + The constructor receives a buffer and instantiates a User_var_event filled + in with the data from the buffer + Written every time a statement uses a user variable, precedes other + events for the statement. Indicates the value to use for the + user variable in the next statement. This is written only before a + QUERY_EVENT and is not used with row-based logging. + + The buffer layout for variable data part is as follows: + <pre> + +-------------------------------------------------------------------+ + | name_len | name | is_null | type | charset_number | val_len | val | + +-------------------------------------------------------------------+ + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + User_var_event(const char *buf, const Format_description_event *fde); + virtual ~User_var_event(); + const char *name; + unsigned int name_len; + char *val; + uint32_t val_len; + Value_type type; + unsigned int charset_number; + bool is_null; + unsigned char flags; +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &info); + void print_long_info(std::ostream &info); + const char *get_value_type_string(Value_type type_arg) const { + switch (type_arg) { + case STRING_RESULT: + return "String"; + case REAL_RESULT: + return "Real"; + case INT_RESULT: + return "Integer"; + case ROW_RESULT: + return "Row"; + case DECIMAL_RESULT: + return "Decimal"; + default: + return "Unknown"; + } + } +#endif +}; + +/** + @class Intvar_event + + An Intvar_event will be created just before a Query_event, + if the query uses one of the variables LAST_INSERT_ID or INSERT_ID. + Each Intvar_event holds the value of one of these variables. + + @section Intvar_event_binary_format Binary Format + + The Post-Header for this event type is empty. The Body has two + components: + + <table> + <caption>Body for Intvar_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>type</td> + <td>1 byte enumeration</td> + <td>One byte identifying the type of variable stored. Currently, + two identifiers are supported: LAST_INSERT_ID_EVENT == 1 and + INSERT_ID_EVENT == 2. + </td> + </tr> + + <tr> + <td>val</td> + <td>8 byte unsigned integer</td> + <td>The value of the variable.</td> + </tr> + + </table> +*/ +class Intvar_event : public Binary_log_event { + public: + uint8_t type; + uint64_t val; + + /* + The enum recognizes the type of variables that can occur in an + INTVAR_EVENT. The two types supported are LAST_INSERT_ID and + INSERT_ID, in accordance to the SQL query using LAST_INSERT_ID + or INSERT_ID. + */ + enum Int_event_type { + INVALID_INT_EVENT, + LAST_INSERT_ID_EVENT, + INSERT_ID_EVENT + }; + + /** + moving from pre processor symbols from global scope in log_event.h + to an enum inside the class, since these are used only by + members of this class itself. + */ + enum Intvar_event_offset { I_TYPE_OFFSET = 0, I_VAL_OFFSET = 1 }; + + /** + This method returns the string representing the type of the variable + used in the event. Changed the definition to be similar to that + previously defined in log_event.cc. + */ + std::string get_var_type_string() const { + switch (type) { + case INVALID_INT_EVENT: + return "INVALID_INT"; + case LAST_INSERT_ID_EVENT: + return "LAST_INSERT_ID"; + case INSERT_ID_EVENT: + return "INSERT_ID"; + default: /* impossible */ + return "UNKNOWN"; + } + } + + /** + Constructor receives a packet from the MySQL master or the binary + log and decodes it to create an Intvar_event. + + The post header for the event is empty. Buffer layout for the variable + data part is as follows: + <pre> + +--------------------------------+ + | type (4 bytes) | val (8 bytes) | + +--------------------------------+ + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Intvar_event(const char *buf, const Format_description_event *fde); + /** + The minimal constructor for Intvar_event it initializes the instance + variables type & val and set the type_code as INTVAR_EVENT in the header + object in Binary_log_event + */ + Intvar_event(uint8_t type_arg, uint64_t val_arg) + : Binary_log_event(INTVAR_EVENT), type(type_arg), val(val_arg) {} + + ~Intvar_event() {} + +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &info); + void print_long_info(std::ostream &info); +#endif +}; + +/** + @class Rand_event + + Logs random seed used by the next RAND(), and by PASSWORD() in 4.1.0. + 4.1.1 does not need it (it's repeatable again) so this event needn't be + written in 4.1.1 for PASSWORD() (but the fact that it is written is just a + waste, it does not cause bugs). + + The state of the random number generation consists of 128 bits, + which are stored internally as two 64-bit numbers. + + @section Rand_event_binary_format Binary Format + + The Post-Header for this event type is empty. The Body has two + components: + + <table> + <caption>Body for Rand_event</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>seed1</td> + <td>8 byte unsigned integer</td> + <td>64 bit random seed1.</td> + </tr> + + <tr> + <td>seed2</td> + <td>8 byte unsigned integer</td> + <td>64 bit random seed2.</td> + </tr> + </table> +*/ +class Rand_event : public Binary_log_event { + public: + unsigned long long seed1; + unsigned long long seed2; + enum Rand_event_data { RAND_SEED1_OFFSET = 0, RAND_SEED2_OFFSET = 8 }; + + /** + This will initialize the instance variables seed1 & seed2, and set the +type_code as RAND_EVENT in the header object in Binary_log_event + */ + Rand_event(unsigned long long seed1_arg, unsigned long long seed2_arg) + : Binary_log_event(RAND_EVENT) { + seed1 = seed1_arg; + seed2 = seed2_arg; + } + + /** + Written every time a statement uses the RAND() function; precedes other + events for the statement. Indicates the seed values to use for generating a + random number with RAND() in the next statement. This is written only before + a QUERY_EVENT and is not used with row-based logging + + <pre> + The buffer layout for variable part is as follows: + +----------------------------------------------+ + | value for first seed | value for second seed | + +----------------------------------------------+ + </pre> + + @param buf Contains the serialized event. + @param fde An FDE event (see Rotate_event constructor for more info). + */ + Rand_event(const char *buf, const Format_description_event *fde); +#ifndef HAVE_MYSYS + void print_event_info(std::ostream &info); + void print_long_info(std::ostream &info); +#endif +}; +} // end namespace binary_log +/** + @} (end of group Replication) +*/ +#endif /* STATEMENT_EVENTS_INCLUDED */ diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/table_id.h b/contrib/libs/libmysql_r/libbinlogevents/include/table_id.h new file mode 100644 index 0000000000..db9876577a --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/table_id.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2013, 2018, 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 */ +/** + @file table_id.h + + @brief Contains the class Table_id, mainly used for row based replication. +*/ + +#ifndef TABLE_ID_INCLUDED +#define TABLE_ID_INCLUDED +#include <stdint.h> +#include "wrapper_functions.h" + +/** + @class Table_id + + @brief Each table share has a table id, it is mainly used for row based + replication. Meanwhile it is used as table's version too. +*/ +class Table_id { + private: + /* In table map event and rows events, table id is 6 bytes.*/ + static const unsigned long long TABLE_ID_MAX = (~0ULL >> 16); + uint64_t m_id; + + public: + Table_id() : m_id(0) {} + explicit Table_id(unsigned long long id) : m_id(id) {} + + unsigned long long id() const { return m_id; } + bool is_valid() const { return m_id <= TABLE_ID_MAX; } + + Table_id &operator=(unsigned long long id) { + m_id = id; + return *this; + } + + bool operator==(const Table_id &tid) const { return m_id == tid.m_id; } + bool operator!=(const Table_id &tid) const { return m_id != tid.m_id; } + + /* Support implicit type converting from Table_id to unsigned long long */ + operator unsigned long long() const { return m_id; } + + Table_id operator++(int) { + Table_id id(m_id); + + /* m_id is reset to 0, when it exceeds the max value. */ + m_id = (m_id == TABLE_ID_MAX ? 0 : m_id + 1); + + BAPI_ASSERT(m_id <= TABLE_ID_MAX); + return id; + } +}; + +#endif diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/uuid.h b/contrib/libs/libmysql_r/libbinlogevents/include/uuid.h new file mode 100644 index 0000000000..a08061ebb3 --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/uuid.h @@ -0,0 +1,173 @@ +/* Copyright (c) 2017, 2018, 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 UUID_H_INCLUDED +#define UUID_H_INCLUDED 1 + +#include <stddef.h> +#include <stdio.h> +#include <string.h> + +#include <string> +#include <utility> + +#include "template_utils.h" + +namespace binary_log { + +/** + @struct Uuid + + This is a POD. It has to be a POD because it is a member of + Sid_map::Node which is stored in HASH in mysql-server code. + The structure contains the following components. + <table> + <caption>Structure gtid_info</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + <tr> + <td>byte</td> + <td>unsigned char array</td> + <td>This stores the Uuid of the server on which transaction + is originated</td> + </tr> + </table> +*/ + +struct Uuid { + /// Set to all zeros. + void clear() { memset(bytes, 0, BYTE_LENGTH); } + /// Copies the given 16-byte data to this UUID. + void copy_from(const unsigned char *data) { + memcpy(bytes, data, BYTE_LENGTH); + } + /// Copies the given UUID object to this UUID. + void copy_from(const Uuid &data) { + copy_from(pointer_cast<const unsigned char *>(data.bytes)); + } + /// Copies the given UUID object to this UUID. + void copy_to(unsigned char *data) const { memcpy(data, bytes, BYTE_LENGTH); } + /// Returns true if this UUID is equal the given UUID. + bool equals(const Uuid &other) const { + return memcmp(bytes, other.bytes, BYTE_LENGTH) == 0; + } + /** + Returns true if parse() would succeed, but doesn't store the result. + + @param string String that needs to be checked. + @param len Length of that string. + + @retval true valid string. + @retval false invalid string. + */ + static bool is_valid(const char *string, size_t len); + + /** + Stores the UUID represented by a string of the form + XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX or + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX or + {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} + in this object. + + @param string String to be parsed and stored. + @param len Length of that string. + + @retval 0 success. + @retval >0 failure. + */ + int parse(const char *string, size_t len); + + /** + Parses the UUID passed as argument in in_string and functions and writes + the binary representation in out_binary_string. + Depends on UUID's read_section method and the constants for text length. + + @param[in] in_string String to be parsed. + @param[in] len Length of that string. + @param[out] out_binary_string String where the binary UUID will be stored + + @retval 0 success. + @retval >0 failure. + */ + static int parse(const char *in_string, size_t len, + const unsigned char *out_binary_string); + /** + Helper method used to validate and parse one section of a uuid. + If the last parameter, out_binary_str, is NULL then the function will + just validate the section. + + @param[in] section_len Length of the section to be parsed. + @param[in,out] section_str Pointer to a string containing the + section. It will be updated during the + execution as the string is parsed. + @param[out] out_binary_str String where the section will be stored + in binary format. If null, the function + will just validate the input string. + + @retval false success. + @retval true failure. + */ + static bool read_section(int section_len, const char **section_str, + const unsigned char **out_binary_str); + /** The number of bytes in the data of a Uuid. */ + static const size_t BYTE_LENGTH = 16; + /** The data for this Uuid. */ + unsigned char bytes[BYTE_LENGTH]; + /** + Generates a 36+1 character long representation of this UUID object + in the given string buffer. + + @retval 36 - the length of the resulting string. + */ + size_t to_string(char *buf) const; + /// Convert the given binary buffer to a UUID + static size_t to_string(const unsigned char *bytes_arg, char *buf); + void print() const { + char buf[TEXT_LENGTH + 1]; + to_string(buf); + printf("%s\n", buf); + } + /// The number of bytes in the textual representation of a Uuid. + static const size_t TEXT_LENGTH = 36; + /// The number of bits in the data of a Uuid. + static const size_t BIT_LENGTH = 128; + static const int NUMBER_OF_SECTIONS = 5; + static const int bytes_per_section[NUMBER_OF_SECTIONS]; + static const int hex_to_byte[256]; +}; + +struct Hash_Uuid { + size_t operator()(const Uuid &uuid) const { + return std::hash<std::string>()( + std::string(pointer_cast<const char *>(uuid.bytes), Uuid::BYTE_LENGTH)); + } +}; + +inline bool operator==(const Uuid &a, const Uuid &b) { return a.equals(b); } + +} // namespace binary_log + +#endif // UUID_H_INCLUDED diff --git a/contrib/libs/libmysql_r/libbinlogevents/include/wrapper_functions.h b/contrib/libs/libmysql_r/libbinlogevents/include/wrapper_functions.h new file mode 100644 index 0000000000..0515046610 --- /dev/null +++ b/contrib/libs/libmysql_r/libbinlogevents/include/wrapper_functions.h @@ -0,0 +1,193 @@ +/* Copyright (c) 2014, 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 */ + +/** + @file + + @brief Contains wrapper functions for memory allocation and deallocation. + This includes generic functions to be called from the binlogevent library, + which call the appropriate corresponding function, depending on whether + the library is compiled independently, or with the MySQL server. +*/ + +#ifndef WRAPPER_FUNCTIONS_INCLUDED +#define WRAPPER_FUNCTIONS_INCLUDED + +#include "binlog_config.h" +#ifndef STANDALONE_BINLOG +#define HAVE_MYSYS 1 +#endif + +#ifdef HAVE_MYSYS +#include "my_config.h" +#include "my_sys.h" +#include "mysql/service_mysql_alloc.h" + +extern PSI_memory_key key_memory_log_event; +#else +#include <cassert> +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <stdlib.h> +#include <string.h> + +#endif + +#if !defined(DBUG_OFF) + +#include "my_dbug.h" + +#ifdef HAVE_MYSYS +#define BAPI_ASSERT(x) DBUG_ASSERT(x) +#define BAPI_PRINT(name, params) DBUG_PRINT(name, params) +#define BAPI_ENTER(x) DBUG_ENTER(x) +#define BAPI_RETURN(x) DBUG_RETURN(x) +#define BAPI_VOID_RETURN DBUG_VOID_RETURN +#else +#define BAPI_ASSERT(x) assert(x) +#define BAPI_PRINT(name, params) +#define BAPI_ENTER(x) +#define BAPI_RETURN(x) return (x) +#define BAPI_VOID_RETURN return +#endif +#else +#define BAPI_ASSERT(x) \ + do { \ + } while (0) +#define BAPI_PRINT(name, params) +#define BAPI_ENTER(x) +#define BAPI_RETURN(x) return (x) +#define BAPI_VOID_RETURN return +#endif + +#ifndef HAVE_STRNDUP +/** + The strndup() function returns a pointer to a new string which is a duplicate + of the string s, but it only copies at most n bytes. If s is longer than n, + only n bytes are copied, and a terminating null byte ('\0') is added. + Memory for the new string is obtained with malloc, + and can be freed with free. + @param s The string whose copy we want to create + @param n Number of bytes to be copied + + @return The duplicated string, or NULL if insufficient memory was + available. +*/ +inline char *strndup(const char *s, size_t n) { + char *result; + size_t len = strlen(s); + + if (n < len) len = n; + + result = (char *)malloc(len + 1); + if (!result) return 0; + + result[len] = '\0'; + return (char *)memcpy(result, s, len); +} +#endif + +/** + This is a wrapper function, and returns a pointer to a new string which is + a duplicate of the input string. The terminating Null character is added. + + If compiled with MySQL server,the strndup function from the mysys library is + called, which allow instrumenting memory allocated. Else, the standard + string function is called. + + @param destination The string to be duplicated + @param n The number of bytes to be copied + + @return The duplicated string, or NULL if insufficient memory was available. +*/ +inline const char *bapi_strndup(const char *destination, size_t n) { +#ifdef HAVE_MYSYS + /* Call the function in mysys library, required for memory instrumentation */ + return my_strndup(key_memory_log_event, destination, n, MYF(MY_WME)); +#else + return strndup(destination, n); +#endif +} + +/** + This is a wrapper function, and returns a pointer to a new memory with the + contents copied from the input memory pointer, upto a given length + + @param source Pointer to the buffer from which data is to be copied + @param len Length upto which the source should be copied + + @return dest pointer to a new memory if allocation was successful + NULL otherwise +*/ +inline void *bapi_memdup(const void *source, size_t len) { + void *dest; +#ifdef HAVE_MYSYS + /* Call the function in mysys library, required for memory instrumentation */ + dest = my_memdup(key_memory_log_event, source, len, MYF(MY_WME)); +#else + dest = malloc(len); + if (dest) memcpy(dest, source, len); +#endif + return dest; +} + +/** + This is a wrapper function in order to allocate memory from the heap + in the binlogevent library. + + If compiled with the MySQL server, and memory is allocated using memory + allocating methods from the mysys library, my_malloc is called. Otherwise, + the standard malloc() is called from the function. + + @param size Size of the memory to be allocated. + @param flags flags to pass to MySQL server my_malloc functions + @return Void pointer to the allocated chunk of memory +*/ +inline void *bapi_malloc(size_t size, int flags MY_ATTRIBUTE((unused))) { + void *dest = nullptr; +#ifdef HAVE_MYSYS + dest = my_malloc(key_memory_log_event, size, MYF(flags)); +#else + dest = malloc(size); +#endif + return dest; +} + +/** + This is a wrapper function in order to free the memory allocated from the heap + in the binlogevent library. + + If compiled with the MySQL server, and memory is allocated using memory + allocating methods from the mysys library, my_free is called. Otherwise, + the standard free() is called from the function. + + @param ptr Pointer to the memory which is to be freed. +*/ +inline void bapi_free(void *ptr) { +#ifdef HAVE_MYSYS + return my_free(ptr); +#else + return free(ptr); +#endif +} +#endif |