Skip to content

Commit 989e415

Browse files
author
Pavan Naik
committed
WL#12114: MTR SUPPORT FOR AUTOMATIC LOADING OF DATA TO SECONDARY
ENGINE AFTER A DDL STATEMENT Description: ------------ This WL will introduce a new MTR option --change-propagation. This option must be used along with --secondary-engine=engine_name option. When this option is defined or enabled, MTR will automatically change the secondary engine of a table to 'engine_name' and will load the table contents from primary engine to secondary engine after a DDL statement. The scope of this WL is limited to following DDL statements 1. ALTER TABLE (ALTER TABLE ... RENAME newtab not supported) 2. CREATE TABLE 3. CREATE INDEX 4. DROP INDEX Change-Id: Ic5e72f5eba6350737a56165ee72ba2fe9e9f779a
1 parent 6668f3e commit 989e415

13 files changed

+684
-147
lines changed

client/CMakeLists.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ IF(NOT WITHOUT_SERVER)
4646
ENDIF()
4747

4848
SET(MYSQLTEST_SRC
49-
mysqltest/mysqltest_expected_error.cc
49+
mysqltest/error_names.cc
50+
mysqltest/expected_errors.cc
51+
mysqltest/secondary_engine.cc
5052
)
5153

5254
MYSQL_ADD_EXECUTABLE(mysqltest mysqltest.cc ${MYSQLTEST_SRC} COMPONENT Test)

client/mysqltest.cc

+83-110
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727
/// See @ref PAGE_MYSQL_TEST_RUN "The MySQL Test Framework" for more
2828
/// information.
2929

30-
#include "client/mysqltest/mysqltest_expected_error.h"
31-
32-
#include "my_config.h"
30+
#include "client/mysqltest/error_names.h"
31+
#include "client/mysqltest/expected_errors.h"
32+
#include "client/mysqltest/secondary_engine.h"
3333

3434
#include <algorithm>
3535
#include <cmath> // std::isinf
@@ -72,6 +72,7 @@
7272
#include "map_helpers.h"
7373
#include "mf_wcomp.h" // wild_compare
7474
#include "my_compiler.h"
75+
#include "my_config.h"
7576
#include "my_dbug.h"
7677
#include "my_default.h"
7778
#include "my_dir.h"
@@ -145,7 +146,8 @@ static void signal_handler(int sig);
145146
static bool get_one_option(int optid, const struct my_option *, char *argument);
146147

147148
enum {
148-
OPT_COLORED_DIFF = OPT_MAX_CLIENT_OPTION,
149+
OPT_CHANGE_PROPAGATION = OPT_MAX_CLIENT_OPTION,
150+
OPT_COLORED_DIFF,
149151
OPT_CURSOR_PROTOCOL,
150152
OPT_EXPLAIN_PROTOCOL,
151153
OPT_JSON_EXPLAIN_PROTOCOL,
@@ -159,6 +161,7 @@ enum {
159161
#ifdef _WIN32
160162
OPT_SAFEPROCESS_PID,
161163
#endif
164+
OPT_SECONDARY_ENGINE,
162165
OPT_SP_PROTOCOL,
163166
OPT_TAIL_LINES,
164167
OPT_TRACE_EXEC,
@@ -206,6 +209,10 @@ static const char *load_default_groups[] = {"mysqltest", "client", 0};
206209
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos = line_buffer;
207210
static bool can_handle_expired_passwords = true;
208211

212+
// Secondary engine options
213+
static int opt_change_propagation;
214+
static const char *opt_secondary_engine;
215+
209216
#ifdef _WIN32
210217
static DWORD opt_safe_process_pid;
211218
static HANDLE mysqltest_thread;
@@ -615,7 +622,6 @@ void str_to_file(const char *fname, char *str, size_t size);
615622
void str_to_file2(const char *fname, char *str, size_t size, bool append);
616623

617624
void fix_win_paths(const char *val, size_t len);
618-
const char *get_errname_from_code(uint error_code);
619625
int multi_reg_replace(struct st_replace_regex *r, char *val);
620626

621627
#ifdef _WIN32
@@ -2354,81 +2360,48 @@ static void do_result_format_version(struct st_command *command) {
23542360
DBUG_VOID_RETURN;
23552361
}
23562362

2357-
/* List of error names to error codes */
2358-
typedef struct {
2359-
const char *name;
2360-
uint code;
2361-
const char *text;
2362-
/* SQLSTATE */
2363-
const char *odbc_state;
2364-
const char *jdbc_state;
2365-
uint error_index;
2366-
} st_error;
2367-
2368-
static st_error global_error_names[] = {{"<No error>", (uint)-1, "", "", "", 0},
2369-
#ifndef IN_DOXYGEN
2370-
#include <mysqlclient_ername.h>
2371-
#include <mysqld_ername.h>
2372-
#endif /* IN_DOXYGEN */
2373-
{0, 0, 0, 0, 0, 0}};
2374-
2375-
uint get_errcode_from_name(char *, char *);
2376-
2377-
/*
2378-
2379-
This function is useful when one needs to convert between error numbers and
2380-
error strings
2381-
2382-
SYNOPSIS
2383-
var_set_convert_error(struct st_command *command,VAR *var)
2384-
2385-
DESCRIPTION
2386-
let $var=convert_error(ER_UNKNOWN_ERROR);
2387-
let $var=convert_error(1234);
2388-
2389-
The variable var will be populated with error number if the argument is
2390-
string. The variable var will be populated with error string if the argument
2391-
is number.
2392-
2393-
*/
2363+
/// Convert between error numbers and error names/strings.
2364+
///
2365+
/// @code
2366+
/// let $var = convert_error(ER_UNKNOWN_ERROR);
2367+
/// let $var = convert_error(1234);
2368+
/// @endcode
2369+
///
2370+
/// The variable '$var' will be populated with error number if the
2371+
/// argument is string. The variable var will be populated with error
2372+
/// string if the argument is number.
2373+
///
2374+
/// @param command Pointer to the st_command structure which holds the
2375+
/// arguments and information for the command.
2376+
/// @param var Pointer to VAR object containing a variable
2377+
/// information.
23942378
static void var_set_convert_error(struct st_command *command, VAR *var) {
2395-
char *last;
2396-
char *first = command->query;
2397-
const char *err_name;
2379+
// The command->query contains the statement convert_error(1234)
2380+
char *first = std::strchr(command->query, '(') + 1;
2381+
char *last = std::strchr(command->query, ')');
23982382

2399-
DBUG_ENTER("var_set_convert_error");
2400-
2401-
DBUG_PRINT("info", ("query: %s", command->query));
2402-
2403-
/* the command->query contains the statement convert_error(1234) */
2404-
first = strchr(command->query, '(') + 1;
2405-
last = strchr(command->query, ')');
2406-
2407-
if (last == first) /* denoting an empty string */
2408-
{
2383+
// Denoting an empty string
2384+
if (last == first) {
24092385
eval_expr(var, "0", 0);
2410-
DBUG_VOID_RETURN;
2386+
return;
24112387
}
24122388

2413-
/* if the string is an error string , it starts with 'E' as is the norm*/
2389+
// If the string is an error string , it starts with 'E' as is the norm
24142390
if (*first == 'E') {
2391+
std::string error_name(first, int(last - first));
2392+
int error = get_errcode_from_name(error_name);
2393+
if (error == -1) die("Unknown SQL error name '%s'.", error_name.c_str());
24152394
char str[100];
2416-
uint num;
2417-
num = get_errcode_from_name(first, last);
2418-
sprintf(str, "%i", num);
2395+
std::sprintf(str, "%d", error);
24192396
eval_expr(var, str, 0);
2420-
} else if (my_isdigit(charset_info, *first)) /* if the error is a number */
2421-
{
2422-
long int err;
2423-
2424-
err = strtol(first, &last, 0);
2425-
err_name = get_errname_from_code(err);
2397+
} else if (my_isdigit(charset_info, *first)) {
2398+
// Error number argument
2399+
long int err = std::strtol(first, &last, 0);
2400+
const char *err_name = get_errname_from_code(err);
24262401
eval_expr(var, err_name, 0);
24272402
} else {
24282403
die("Invalid error in input");
24292404
}
2430-
2431-
DBUG_VOID_RETURN;
24322405
}
24332406

24342407
/*
@@ -5431,47 +5404,6 @@ static void do_shutdown_server(struct st_command *command) {
54315404
DBUG_VOID_RETURN;
54325405
}
54335406

5434-
uint get_errcode_from_name(char *error_name, char *error_end) {
5435-
/* SQL error as string */
5436-
st_error *e = global_error_names;
5437-
5438-
DBUG_ENTER("get_errcode_from_name");
5439-
DBUG_PRINT("enter", ("error_name: %s", error_name));
5440-
5441-
/* Loop through the array of known error names */
5442-
for (; e->name; e++) {
5443-
/*
5444-
If we get a match, we need to check the length of the name we
5445-
matched against in case it was longer than what we are checking
5446-
(as in ER_WRONG_VALUE vs. ER_WRONG_VALUE_COUNT).
5447-
*/
5448-
if (!std::strncmp(error_name, e->name, (int)(error_end - error_name)) &&
5449-
(uint)std::strlen(e->name) == (uint)(error_end - error_name)) {
5450-
DBUG_RETURN(e->code);
5451-
}
5452-
}
5453-
if (!e->name) die("Unknown SQL error name '%s'", error_name);
5454-
DBUG_RETURN(0);
5455-
}
5456-
5457-
const char *get_errname_from_code(uint error_code) {
5458-
st_error *e = global_error_names;
5459-
5460-
DBUG_ENTER("get_errname_from_code");
5461-
DBUG_PRINT("enter", ("error_code: %d", error_code));
5462-
5463-
if (!error_code) {
5464-
DBUG_RETURN("");
5465-
}
5466-
for (; e->name; e++) {
5467-
if (e->code == error_code) {
5468-
DBUG_RETURN(e->name);
5469-
}
5470-
}
5471-
/* Apparently, errors without known names may occur */
5472-
DBUG_RETURN("<Unknown>");
5473-
}
5474-
54755407
/// Get the error code corresponding to an error string or to a
54765408
/// SQLSTATE string.
54775409
///
@@ -5536,7 +5468,10 @@ static void do_get_errcodes(struct st_command *command) {
55365468
else if (*p == 'E' || *p == 'C') {
55375469
// Error name string
55385470
DBUG_PRINT("info", ("Error name: %s", p));
5539-
std::uint32_t error_code = get_errcode_from_name(p, end);
5471+
std::string error_name(p, int(end - p));
5472+
int error_code = get_errcode_from_name(error_name);
5473+
if (error_code == -1)
5474+
die("Unknown SQL error name '%s'.", error_name.c_str());
55405475
expected_errors->add_error(error_code, "00000", ERR_ERRNO);
55415476
DBUG_PRINT("info", ("ERR_ERRNO: %d", error_code));
55425477
} else if (*p == 'e' || *p == 'c') {
@@ -6941,6 +6876,10 @@ static struct my_option my_long_options[] = {
69416876
#include "sslopt-longopts.h"
69426877
{"basedir", 'b', "Basedir for tests.", &opt_basedir, &opt_basedir, 0,
69436878
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6879+
{"change-propagation", OPT_CHANGE_PROPAGATION,
6880+
"Disable/enable change propagation when secondary engine is enabled.",
6881+
&opt_change_propagation, &opt_change_propagation, 0, GET_INT, REQUIRED_ARG,
6882+
-1, -1, 1, 0, 0, 0},
69446883
{"character-sets-dir", OPT_CHARSETS_DIR,
69456884
"Directory for character set files.", &opt_charsets_dir, &opt_charsets_dir,
69466885
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -7050,6 +6989,9 @@ static struct my_option my_long_options[] = {
70506989
&opt_safe_process_pid, &opt_safe_process_pid, 0, GET_INT, REQUIRED_ARG, 0,
70516990
0, 0, 0, 0, 0},
70526991
#endif
6992+
{"secondary-engine", OPT_SECONDARY_ENGINE,
6993+
"Enable a secondary storage engine.", &opt_secondary_engine,
6994+
&opt_secondary_engine, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
70536995
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
70546996
"Base name of shared memory.", &shared_memory_base_name,
70556997
&shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -7715,6 +7657,13 @@ static void run_query_normal(struct st_connection *cn,
77157657
DBUG_PRINT("enter", ("flags: %d", flags));
77167658
DBUG_PRINT("enter", ("query: '%-.60s'", query));
77177659

7660+
if (opt_change_propagation != -1) {
7661+
std::vector<unsigned int> ignore_errors = expected_errors->errors();
7662+
// Run secondary engine unload statements.
7663+
if (run_secondary_engine_unload_statements(query, mysql, ignore_errors))
7664+
die("Original query '%s'.", query);
7665+
}
7666+
77187667
if (flags & QUERY_SEND_FLAG) {
77197668
/*
77207669
Send the query
@@ -7814,6 +7763,15 @@ static void run_query_normal(struct st_connection *cn,
78147763
variable then can be used from the test case itself.
78157764
*/
78167765
var_set_errno(mysql_errno(mysql));
7766+
7767+
if (opt_change_propagation != -1) {
7768+
std::vector<unsigned int> ignore_errors = expected_errors->errors();
7769+
// Run secondary engine load statements.
7770+
if (run_secondary_engine_load_statements(opt_secondary_engine, query, mysql,
7771+
ignore_errors))
7772+
die("Original query '%s'.", query);
7773+
}
7774+
78177775
DBUG_VOID_RETURN;
78187776
}
78197777

@@ -7843,6 +7801,13 @@ static void run_query_stmt(MYSQL *mysql, struct st_command *command,
78437801
DBUG_ENTER("run_query_stmt");
78447802
DBUG_PRINT("query", ("'%-.60s'", query));
78457803

7804+
if (opt_change_propagation != -1) {
7805+
std::vector<unsigned int> ignore_errors = expected_errors->errors();
7806+
// Run secondary engine unload statements.
7807+
if (run_secondary_engine_unload_statements(query, mysql, ignore_errors))
7808+
die("Original query '%s'.", query);
7809+
}
7810+
78467811
/*
78477812
Init a new stmt if it's not already one created for this connection
78487813
*/
@@ -8028,6 +7993,14 @@ static void run_query_stmt(MYSQL *mysql, struct st_command *command,
80287993
cur_con->stmt = NULL;
80297994
}
80307995

7996+
if (opt_change_propagation != -1) {
7997+
std::vector<unsigned int> ignore_errors = expected_errors->errors();
7998+
// Run secondary engine load statements.
7999+
if (run_secondary_engine_load_statements(opt_secondary_engine, query, mysql,
8000+
ignore_errors))
8001+
die("Original query '%s'.", query);
8002+
}
8003+
80318004
DBUG_VOID_RETURN;
80328005
}
80338006

client/mysqltest/error_names.cc

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
//
3+
// This program is free software; you can redistribute it and/or modify
4+
// it under the terms of the GNU General Public License, version 2.0,
5+
// as published by the Free Software Foundation.
6+
//
7+
// This program is also distributed with certain software (including
8+
// but not limited to OpenSSL) that is licensed under separate terms,
9+
// as designated in a particular file or component or in included license
10+
// documentation. The authors of MySQL hereby grant you an additional
11+
// permission to link the program and your derivative works with the
12+
// separately licensed software that they have included with MySQL.
13+
//
14+
// This program is distributed in the hope that it will be useful,
15+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
// GNU General Public License, version 2.0, for more details.
18+
//
19+
// You should have received a copy of the GNU General Public License
20+
// along with this program; if not, write to the Free Software
21+
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22+
23+
#include "client/mysqltest/error_names.h"
24+
25+
static st_error global_error_names[] = {
26+
{"<No error>", static_cast<int>(-1), "", NULL, NULL, 0},
27+
#ifndef IN_DOXYGEN
28+
#include "mysqlclient_ername.h"
29+
#include "mysqld_ername.h"
30+
#endif /* IN_DOXYGEN */
31+
{0, 0, 0, 0, 0, 0}};
32+
33+
int get_errcode_from_name(std::string error_name) {
34+
for (st_error *error = global_error_names; error->name; error++) {
35+
if (error_name.compare(error->name) == 0) return error->error_code;
36+
}
37+
38+
// Unknown SQL error name, return -1
39+
return -1;
40+
}
41+
42+
const char *get_errname_from_code(int error_code) {
43+
// Return an empty string if error code is 0.
44+
if (!error_code) return "";
45+
46+
for (st_error *error = global_error_names; error->error_code; error++) {
47+
if (error->error_code == error_code) return error->name;
48+
}
49+
50+
// Unknown SQL error code, return "<Unknown>" keyword.
51+
return "<Unknown>";
52+
}

0 commit comments

Comments
 (0)