polardbxengine/libbinlogevents/include/load_data_events.h

397 lines
12 KiB
Objective-C

/* 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 */