mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
Merge 10.4 into 10.5
This commit is contained in:
commit
d62b0368ca
86 changed files with 2875 additions and 251 deletions
2
CREDITS
2
CREDITS
|
@ -4,9 +4,11 @@ organization registered in the USA.
|
|||
The current main sponsors of the MariaDB Foundation are:
|
||||
|
||||
Alibaba Cloud https://www.alibabacloud.com/ (2017)
|
||||
Intel https://www.intel.com (2022)
|
||||
MariaDB Corporation https://www.mariadb.com (2013)
|
||||
Microsoft https://microsoft.com/ (2017)
|
||||
ServiceNow https://servicenow.com (2019)
|
||||
SIT https://sit.org (2022)
|
||||
Tencent Cloud https://cloud.tencent.com (2017)
|
||||
Development Bank of Singapore https://dbs.com (2016)
|
||||
IBM https://www.ibm.com (2017)
|
||||
|
|
|
@ -2518,6 +2518,7 @@ static Exit_status handle_event_raw_mode(PRINT_EVENT_INFO *print_event_info,
|
|||
error("Could not write into log file '%s'", out_file_name);
|
||||
DBUG_RETURN(ERROR_STOP);
|
||||
}
|
||||
fflush(result_file);
|
||||
|
||||
DBUG_RETURN(OK_CONTINUE);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2021, MariaDB
|
||||
Copyright (c) 2009, 2022, MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -320,6 +320,7 @@ struct st_connection
|
|||
char *name;
|
||||
size_t name_len;
|
||||
MYSQL_STMT* stmt;
|
||||
MYSQL_BIND *ps_params;
|
||||
/* Set after send to disallow other queries before reap */
|
||||
my_bool pending;
|
||||
|
||||
|
@ -394,6 +395,10 @@ enum enum_commands {
|
|||
Q_ENABLE_PREPARE_WARNINGS, Q_DISABLE_PREPARE_WARNINGS,
|
||||
Q_RESET_CONNECTION,
|
||||
Q_OPTIMIZER_TRACE,
|
||||
Q_PS_PREPARE,
|
||||
Q_PS_BIND,
|
||||
Q_PS_EXECUTE,
|
||||
Q_PS_CLOSE,
|
||||
Q_UNKNOWN, /* Unknown command. */
|
||||
Q_COMMENT, /* Comments, ignored. */
|
||||
Q_COMMENT_WITH_COMMAND,
|
||||
|
@ -507,6 +512,10 @@ const char *command_names[]=
|
|||
"disable_prepare_warnings",
|
||||
"reset_connection",
|
||||
"optimizer_trace",
|
||||
"PS_prepare",
|
||||
"PS_bind",
|
||||
"PS_execute",
|
||||
"PS_close",
|
||||
0
|
||||
};
|
||||
|
||||
|
@ -7900,6 +7909,15 @@ static void handle_no_active_connection(struct st_command *command,
|
|||
var_set_errno(2006);
|
||||
}
|
||||
|
||||
/* handler functions to execute prepared statement calls in client C API */
|
||||
void run_prepare_stmt(struct st_connection *cn, struct st_command *command, const char *query,
|
||||
size_t query_len, DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings);
|
||||
void run_bind_stmt(struct st_connection *cn, struct st_command *command, const char *query,
|
||||
size_t query_len, DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings);
|
||||
void run_execute_stmt(struct st_connection *cn, struct st_command *command, const char *query,
|
||||
size_t query_len, DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings);
|
||||
void run_close_stmt(struct st_connection *cn, struct st_command *command, const char *query,
|
||||
size_t query_len, DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings);
|
||||
|
||||
/*
|
||||
Run query using MySQL C API
|
||||
|
@ -7931,6 +7949,32 @@ void run_query_normal(struct st_connection *cn, struct st_command *command,
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/* handle prepared statement commands */
|
||||
switch (command->type) {
|
||||
case Q_PS_PREPARE:
|
||||
run_prepare_stmt(cn, command, query, query_len, ds, ds_warnings);
|
||||
flags &= ~QUERY_SEND_FLAG;
|
||||
goto end;
|
||||
break;
|
||||
case Q_PS_BIND:
|
||||
run_bind_stmt(cn, command, query, query_len, ds, ds_warnings);
|
||||
flags &= ~QUERY_SEND_FLAG;
|
||||
goto end;
|
||||
break;
|
||||
case Q_PS_EXECUTE:
|
||||
run_execute_stmt(cn, command, query, query_len, ds, ds_warnings);
|
||||
flags &= ~QUERY_SEND_FLAG;
|
||||
goto end;
|
||||
break;
|
||||
case Q_PS_CLOSE:
|
||||
run_close_stmt(cn, command, query, query_len, ds, ds_warnings);
|
||||
flags &= ~QUERY_SEND_FLAG;
|
||||
goto end;
|
||||
break;
|
||||
default: /* not a prepared statement command */
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & QUERY_SEND_FLAG)
|
||||
{
|
||||
/*
|
||||
|
@ -8486,6 +8530,411 @@ end:
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
prepare query using prepared statement C API
|
||||
|
||||
SYNPOSIS
|
||||
run_prepare_stmt
|
||||
mysql - mysql handle
|
||||
command - current command pointer
|
||||
query - query string to execute
|
||||
query_len - length query string to execute
|
||||
ds - output buffer where to store result form query
|
||||
|
||||
RETURN VALUE
|
||||
error - function will not return
|
||||
*/
|
||||
|
||||
void run_prepare_stmt(struct st_connection *cn, struct st_command *command, const char *query, size_t query_len, DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
|
||||
{
|
||||
|
||||
MYSQL *mysql= cn->mysql;
|
||||
MYSQL_STMT *stmt;
|
||||
DYNAMIC_STRING ds_prepare_warnings;
|
||||
DBUG_ENTER("run_prepare_stmt");
|
||||
DBUG_PRINT("query", ("'%-.60s'", query));
|
||||
|
||||
/*
|
||||
Init a new stmt if it's not already one created for this connection
|
||||
*/
|
||||
if(!(stmt= cn->stmt))
|
||||
{
|
||||
if (!(stmt= mysql_stmt_init(mysql)))
|
||||
die("unable to init stmt structure");
|
||||
cn->stmt= stmt;
|
||||
}
|
||||
|
||||
/* Init dynamic strings for warnings */
|
||||
if (!disable_warnings)
|
||||
{
|
||||
init_dynamic_string(&ds_prepare_warnings, NULL, 0, 256);
|
||||
}
|
||||
|
||||
/*
|
||||
Prepare the query
|
||||
*/
|
||||
char* PS_query= command->first_argument;
|
||||
size_t PS_query_len= command->end - command->first_argument;
|
||||
if (do_stmt_prepare(cn, PS_query, PS_query_len))
|
||||
{
|
||||
handle_error(command, mysql_stmt_errno(stmt),
|
||||
mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
Get the warnings from mysql_stmt_prepare and keep them in a
|
||||
separate string
|
||||
*/
|
||||
if (!disable_warnings)
|
||||
append_warnings(&ds_prepare_warnings, mysql);
|
||||
end:
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
bind parameters for a prepared statement C API
|
||||
|
||||
SYNPOSIS
|
||||
run_bind_stmt
|
||||
mysql - mysql handle
|
||||
command - current command pointer
|
||||
query - query string to execute
|
||||
query_len - length query string to execute
|
||||
ds - output buffer where to store result form query
|
||||
|
||||
RETURN VALUE
|
||||
error - function will not return
|
||||
*/
|
||||
|
||||
void run_bind_stmt(struct st_connection *cn, struct st_command *command,
|
||||
const char *query, size_t query_len, DYNAMIC_STRING *ds,
|
||||
DYNAMIC_STRING *ds_warnings
|
||||
)
|
||||
{
|
||||
MYSQL_STMT *stmt= cn->stmt;
|
||||
DBUG_ENTER("run_bind_stmt");
|
||||
DBUG_PRINT("query", ("'%-.60s'", query));
|
||||
MYSQL_BIND *ps_params= cn->ps_params;
|
||||
if (ps_params)
|
||||
{
|
||||
for (size_t i=0; i<stmt->param_count; i++)
|
||||
{
|
||||
my_free(ps_params[i].buffer);
|
||||
ps_params[i].buffer= NULL;
|
||||
}
|
||||
my_free(ps_params);
|
||||
ps_params= NULL;
|
||||
}
|
||||
|
||||
/* Init PS-parameters. */
|
||||
cn->ps_params= ps_params = (MYSQL_BIND*)my_malloc(PSI_NOT_INSTRUMENTED,
|
||||
sizeof(MYSQL_BIND) *
|
||||
stmt->param_count,
|
||||
MYF(MY_WME));
|
||||
bzero((char *) ps_params, sizeof(MYSQL_BIND) * stmt->param_count);
|
||||
|
||||
int i=0;
|
||||
char *c;
|
||||
long *l;
|
||||
double *d;
|
||||
|
||||
char *p= strtok((char*)command->first_argument, " ");
|
||||
while (p != nullptr)
|
||||
{
|
||||
(void)strtol(p, &c, 10);
|
||||
if (!*c)
|
||||
{
|
||||
ps_params[i].buffer_type= MYSQL_TYPE_LONG;
|
||||
l= (long*)my_malloc(PSI_NOT_INSTRUMENTED, sizeof(long), MYF(MY_WME));
|
||||
*l= strtol(p, &c, 10);
|
||||
ps_params[i].buffer= (void*)l;
|
||||
ps_params[i].buffer_length= 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)strtod(p, &c);
|
||||
if (!*c)
|
||||
{
|
||||
ps_params[i].buffer_type= MYSQL_TYPE_DECIMAL;
|
||||
d= (double*)my_malloc(PSI_NOT_INSTRUMENTED, sizeof(double),
|
||||
MYF(MY_WME));
|
||||
*d= strtod(p, &c);
|
||||
ps_params[i].buffer= (void*)d;
|
||||
ps_params[i].buffer_length= 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
ps_params[i].buffer_type= MYSQL_TYPE_STRING;
|
||||
ps_params[i].buffer= strdup(p);
|
||||
ps_params[i].buffer_length= (unsigned long)strlen(p);
|
||||
}
|
||||
}
|
||||
|
||||
p= strtok(nullptr, " ");
|
||||
i++;
|
||||
}
|
||||
|
||||
int rc= mysql_stmt_bind_param(stmt, ps_params);
|
||||
if (rc)
|
||||
{
|
||||
die("mysql_stmt_bind_param() failed': %d %s",
|
||||
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
|
||||
}
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
execute query using prepared statement C API
|
||||
|
||||
SYNPOSIS
|
||||
run_axecute_stmt
|
||||
mysql - mysql handle
|
||||
command - current command pointer
|
||||
query - query string to execute
|
||||
query_len - length query string to execute
|
||||
ds - output buffer where to store result form query
|
||||
|
||||
RETURN VALUE
|
||||
error - function will not return
|
||||
*/
|
||||
|
||||
void run_execute_stmt(struct st_connection *cn, struct st_command *command,
|
||||
const char *query, size_t query_len, DYNAMIC_STRING *ds,
|
||||
DYNAMIC_STRING *ds_warnings
|
||||
)
|
||||
{
|
||||
MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */
|
||||
MYSQL *mysql= cn->mysql;
|
||||
MYSQL_STMT *stmt= cn->stmt;
|
||||
DYNAMIC_STRING ds_execute_warnings;
|
||||
DBUG_ENTER("run_execute_stmt");
|
||||
DBUG_PRINT("query", ("'%-.60s'", query));
|
||||
|
||||
/* Init dynamic strings for warnings */
|
||||
if (!disable_warnings)
|
||||
{
|
||||
init_dynamic_string(&ds_execute_warnings, NULL, 0, 256);
|
||||
}
|
||||
|
||||
#if MYSQL_VERSION_ID >= 50000
|
||||
if (cursor_protocol_enabled)
|
||||
{
|
||||
/*
|
||||
Use cursor when retrieving result
|
||||
*/
|
||||
ulong type= CURSOR_TYPE_READ_ONLY;
|
||||
if (mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type))
|
||||
die("mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s",
|
||||
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
Execute the query
|
||||
*/
|
||||
if (do_stmt_execute(cn))
|
||||
{
|
||||
handle_error(command, mysql_stmt_errno(stmt),
|
||||
mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
When running in cursor_protocol get the warnings from execute here
|
||||
and keep them in a separate string for later.
|
||||
*/
|
||||
if (cursor_protocol_enabled && !disable_warnings)
|
||||
append_warnings(&ds_execute_warnings, mysql);
|
||||
|
||||
/*
|
||||
We instruct that we want to update the "max_length" field in
|
||||
mysql_stmt_store_result(), this is our only way to know how much
|
||||
buffer to allocate for result data
|
||||
*/
|
||||
{
|
||||
my_bool one= 1;
|
||||
if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one))
|
||||
die("mysql_stmt_attr_set(STMT_ATTR_UPDATE_MAX_LENGTH) failed': %d %s",
|
||||
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
|
||||
}
|
||||
|
||||
/*
|
||||
If we got here the statement succeeded and was expected to do so,
|
||||
get data. Note that this can still give errors found during execution!
|
||||
Store the result of the query if if will return any fields
|
||||
*/
|
||||
if (mysql_stmt_field_count(stmt) && mysql_stmt_store_result(stmt))
|
||||
{
|
||||
handle_error(command, mysql_stmt_errno(stmt),
|
||||
mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* If we got here the statement was both executed and read successfully */
|
||||
handle_no_error(command);
|
||||
if (!disable_result_log)
|
||||
{
|
||||
/*
|
||||
Not all statements creates a result set. If there is one we can
|
||||
now create another normal result set that contains the meta
|
||||
data. This set can be handled almost like any other non prepared
|
||||
statement result set.
|
||||
*/
|
||||
if ((res= mysql_stmt_result_metadata(stmt)) != NULL)
|
||||
{
|
||||
/* Take the column count from meta info */
|
||||
MYSQL_FIELD *fields= mysql_fetch_fields(res);
|
||||
uint num_fields= mysql_num_fields(res);
|
||||
|
||||
if (display_metadata)
|
||||
append_metadata(ds, fields, num_fields);
|
||||
|
||||
if (!display_result_vertically)
|
||||
append_table_headings(ds, fields, num_fields);
|
||||
|
||||
append_stmt_result(ds, stmt, fields, num_fields);
|
||||
|
||||
mysql_free_result(res); /* Free normal result set with meta data */
|
||||
|
||||
/*
|
||||
Normally, if there is a result set, we do not show warnings from the
|
||||
prepare phase. This is because some warnings are generated both during
|
||||
prepare and execute; this would generate different warning output
|
||||
between normal and ps-protocol test runs.
|
||||
|
||||
The --enable_prepare_warnings command can be used to change this so
|
||||
that warnings from both the prepare and execute phase are shown.
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
This is a query without resultset
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
Fetch info before fetching warnings, since it will be reset
|
||||
otherwise.
|
||||
*/
|
||||
if (!disable_info)
|
||||
append_info(ds, mysql_stmt_affected_rows(stmt), mysql_info(mysql));
|
||||
|
||||
if (display_session_track_info)
|
||||
append_session_track_info(ds, mysql);
|
||||
|
||||
|
||||
if (!disable_warnings)
|
||||
{
|
||||
/* Get the warnings from execute */
|
||||
|
||||
/* Append warnings to ds - if there are any */
|
||||
if (append_warnings(&ds_execute_warnings, mysql) ||
|
||||
ds_execute_warnings.length ||
|
||||
ds_warnings->length)
|
||||
{
|
||||
dynstr_append_mem(ds, "Warnings:\n", 10);
|
||||
if (ds_warnings->length)
|
||||
dynstr_append_mem(ds, ds_warnings->str,
|
||||
ds_warnings->length);
|
||||
if (ds_execute_warnings.length)
|
||||
dynstr_append_mem(ds, ds_execute_warnings.str,
|
||||
ds_execute_warnings.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if (!disable_warnings)
|
||||
{
|
||||
dynstr_free(&ds_execute_warnings);
|
||||
}
|
||||
|
||||
/*
|
||||
We save the return code (mysql_stmt_errno(stmt)) from the last call sent
|
||||
to the server into the mysqltest builtin variable $mysql_errno. This
|
||||
variable then can be used from the test case itself.
|
||||
*/
|
||||
|
||||
var_set_errno(mysql_stmt_errno(stmt));
|
||||
|
||||
revert_properties();
|
||||
|
||||
/* Close the statement if reconnect, need new prepare */
|
||||
{
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
my_bool reconnect;
|
||||
mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect);
|
||||
if (reconnect)
|
||||
#else
|
||||
if (mysql->reconnect)
|
||||
#endif
|
||||
{
|
||||
if (cn->ps_params)
|
||||
{
|
||||
for (size_t i=0; i<stmt->param_count; i++)
|
||||
{
|
||||
my_free(cn->ps_params[i].buffer);
|
||||
cn->ps_params[i].buffer= NULL;
|
||||
}
|
||||
my_free(cn->ps_params);
|
||||
}
|
||||
mysql_stmt_close(stmt);
|
||||
cn->stmt= NULL;
|
||||
cn->ps_params= NULL;
|
||||
}
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
close a prepared statement C API
|
||||
|
||||
SYNPOSIS
|
||||
run_close_stmt
|
||||
mysql - mysql handle
|
||||
command - current command pointer
|
||||
query - query string to execute
|
||||
query_len - length query string to execute
|
||||
ds - output buffer where to store result form query
|
||||
|
||||
RETURN VALUE
|
||||
error - function will not return
|
||||
*/
|
||||
|
||||
void run_close_stmt(struct st_connection *cn, struct st_command *command,
|
||||
const char *query, size_t query_len, DYNAMIC_STRING *ds,
|
||||
DYNAMIC_STRING *ds_warnings
|
||||
)
|
||||
{
|
||||
MYSQL_STMT *stmt= cn->stmt;
|
||||
DBUG_ENTER("run_close_stmt");
|
||||
DBUG_PRINT("query", ("'%-.60s'", query));
|
||||
|
||||
if (cn->ps_params)
|
||||
{
|
||||
|
||||
for (size_t i=0; i<stmt->param_count; i++)
|
||||
{
|
||||
my_free(cn->ps_params[i].buffer);
|
||||
cn->ps_params[i].buffer= NULL;
|
||||
}
|
||||
my_free(cn->ps_params);
|
||||
}
|
||||
|
||||
/* Close the statement */
|
||||
if (stmt)
|
||||
{
|
||||
mysql_stmt_close(stmt);
|
||||
cn->stmt= NULL;
|
||||
}
|
||||
cn->ps_params= NULL;
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -9526,6 +9975,10 @@ int main(int argc, char **argv)
|
|||
/* fall through */
|
||||
case Q_QUERY:
|
||||
case Q_REAP:
|
||||
case Q_PS_PREPARE:
|
||||
case Q_PS_BIND:
|
||||
case Q_PS_EXECUTE:
|
||||
case Q_PS_CLOSE:
|
||||
{
|
||||
my_bool old_display_result_vertically= display_result_vertically;
|
||||
/* Default is full query, both reap and send */
|
||||
|
|
|
@ -17,20 +17,29 @@ IF(GIT_EXECUTABLE AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
|||
${GIT_EXECUTABLE} config cmake.update-submodules yes")
|
||||
ELSEIF(git_config_get_result EQUAL 128)
|
||||
SET(update_result 0)
|
||||
ELSEIF (cmake_update_submodules MATCHES force)
|
||||
MESSAGE(STATUS "Updating submodules (forced)")
|
||||
EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --force --recursive --depth=1
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE update_result)
|
||||
ELSEIF (cmake_update_submodules MATCHES yes)
|
||||
EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive --depth=1
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE update_result)
|
||||
ELSE()
|
||||
MESSAGE(STATUS "Updating submodules")
|
||||
EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive --depth=1
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE update_result)
|
||||
SET(UPDATE_SUBMODULES_COMMAND
|
||||
"${GIT_EXECUTABLE}" submodule update --init --recursive)
|
||||
# Old Git may not work with "--depth 1".
|
||||
# See also: https://github.com/git/git/commit/fb43e31f2b43076e7a30c9cd00d0241cb8cf97eb
|
||||
IF(NOT GIT_VERSION_STRING VERSION_LESS "2.8.0")
|
||||
SET(UPDATE_SUBMODULES_COMMAND ${UPDATE_SUBMODULES_COMMAND} --depth 1)
|
||||
ENDIF()
|
||||
IF(cmake_update_submodules MATCHES force)
|
||||
MESSAGE(STATUS "Updating submodules (forced)")
|
||||
EXECUTE_PROCESS(COMMAND ${UPDATE_SUBMODULES_COMMAND} --force
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE update_result)
|
||||
ELSEIF(cmake_update_submodules MATCHES yes)
|
||||
EXECUTE_PROCESS(COMMAND ${UPDATE_SUBMODULES_COMMAND}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE update_result)
|
||||
ELSE()
|
||||
MESSAGE(STATUS "Updating submodules")
|
||||
EXECUTE_PROCESS(COMMAND ${UPDATE_SUBMODULES_COMMAND}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE update_result)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define MY_ATOMIC_INCLUDED
|
||||
|
||||
/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright (c) 2018, 2020, MariaDB
|
||||
Copyright (c) 2018, 2022, MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -115,22 +115,6 @@
|
|||
#include "atomic/gcc_builtins.h"
|
||||
#endif
|
||||
|
||||
#if SIZEOF_LONG == 4
|
||||
#define my_atomic_addlong(A,B) my_atomic_add32((int32*) (A), (B))
|
||||
#define my_atomic_loadlong(A) my_atomic_load32((int32*) (A))
|
||||
#define my_atomic_loadlong_explicit(A,O) my_atomic_load32_explicit((int32*) (A), (O))
|
||||
#define my_atomic_storelong(A,B) my_atomic_store32((int32*) (A), (B))
|
||||
#define my_atomic_faslong(A,B) my_atomic_fas32((int32*) (A), (B))
|
||||
#define my_atomic_caslong(A,B,C) my_atomic_cas32((int32*) (A), (int32*) (B), (C))
|
||||
#else
|
||||
#define my_atomic_addlong(A,B) my_atomic_add64((int64*) (A), (B))
|
||||
#define my_atomic_loadlong(A) my_atomic_load64((int64*) (A))
|
||||
#define my_atomic_loadlong_explicit(A,O) my_atomic_load64_explicit((int64*) (A), (O))
|
||||
#define my_atomic_storelong(A,B) my_atomic_store64((int64*) (A), (B))
|
||||
#define my_atomic_faslong(A,B) my_atomic_fas64((int64*) (A), (B))
|
||||
#define my_atomic_caslong(A,B,C) my_atomic_cas64((int64*) (A), (int64*) (B), (C))
|
||||
#endif
|
||||
|
||||
#ifndef MY_MEMORY_ORDER_SEQ_CST
|
||||
#define MY_MEMORY_ORDER_RELAXED
|
||||
#define MY_MEMORY_ORDER_CONSUME
|
||||
|
|
|
@ -5,6 +5,8 @@ Tencent Cloud https://cloud.tencent.com Platinum Sponsor of the MariaDB Foundati
|
|||
Microsoft https://microsoft.com/ Platinum Sponsor of the MariaDB Foundation
|
||||
MariaDB Corporation https://mariadb.com Founding member, Platinum Sponsor of the MariaDB Foundation
|
||||
ServiceNow https://servicenow.com Platinum Sponsor of the MariaDB Foundation
|
||||
Intel https://www.intel.com Platinum Sponsor of the MariaDB Foundation
|
||||
SIT https://sit.org Platinum Sponsor of the MariaDB Foundation
|
||||
Visma https://visma.com Gold Sponsor of the MariaDB Foundation
|
||||
DBS https://dbs.com Gold Sponsor of the MariaDB Foundation
|
||||
IBM https://www.ibm.com Gold Sponsor of the MariaDB Foundation
|
||||
|
|
|
@ -2913,5 +2913,30 @@ t1 CREATE TABLE `t1` (
|
|||
DROP TABLE t1;
|
||||
SET NAMES utf8;
|
||||
#
|
||||
# MDEV-28078 Garbage on multiple equal ENUMs with tricky character sets
|
||||
#
|
||||
CREATE TABLE t1 (
|
||||
c1 ENUM ('a','b') CHARACTER SET utf32 DEFAULT 'a',
|
||||
c2 ENUM ('a','b') CHARACTER SET utf32 DEFAULT 'a'
|
||||
);
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` enum('a','b') CHARACTER SET utf32 DEFAULT 'a',
|
||||
`c2` enum('a','b') CHARACTER SET utf32 DEFAULT 'a'
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (
|
||||
c1 ENUM ('00000061','00000062') DEFAULT '00000061' COLLATE latin1_bin,
|
||||
c2 ENUM ('a','b') DEFAULT 'a' COLLATE utf32_general_ci
|
||||
);
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`c1` enum('00000061','00000062') CHARACTER SET latin1 COLLATE latin1_bin DEFAULT '00000061',
|
||||
`c2` enum('a','b') CHARACTER SET utf32 DEFAULT 'a'
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.2 tests
|
||||
#
|
||||
|
|
|
@ -1067,6 +1067,25 @@ DROP TABLE t1;
|
|||
SET NAMES utf8;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-28078 Garbage on multiple equal ENUMs with tricky character sets
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (
|
||||
c1 ENUM ('a','b') CHARACTER SET utf32 DEFAULT 'a',
|
||||
c2 ENUM ('a','b') CHARACTER SET utf32 DEFAULT 'a'
|
||||
);
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (
|
||||
c1 ENUM ('00000061','00000062') DEFAULT '00000061' COLLATE latin1_bin,
|
||||
c2 ENUM ('a','b') DEFAULT 'a' COLLATE utf32_general_ci
|
||||
);
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.2 tests
|
||||
--echo #
|
||||
|
|
|
@ -207,4 +207,19 @@ ERROR 23000: Duplicate entry '0000-00-00 00:00:00' for key 'f2k'
|
|||
DROP VIEW v1;
|
||||
DROP TABLE t3,t4;
|
||||
SET @@sql_mode=@save_sql_mode;
|
||||
#
|
||||
# End of 10.2 tests
|
||||
#
|
||||
#
|
||||
# MDEV-28095 crash in multi-update and implicit grouping
|
||||
#
|
||||
CREATE TABLE t1 (a int) engine=innodb;
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
CREATE TABLE t2 (b int);
|
||||
INSERT INTO t2 VALUES (1),(2);
|
||||
UPDATE t1 NATURAL JOIN t2 SET a = 1 ORDER BY AVG (a) ;
|
||||
ERROR HY000: Invalid use of group function
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# End of 10.3 tests
|
||||
#
|
||||
|
|
|
@ -243,4 +243,23 @@ DROP VIEW v1;
|
|||
DROP TABLE t3,t4;
|
||||
SET @@sql_mode=@save_sql_mode;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.2 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-28095 crash in multi-update and implicit grouping
|
||||
--echo #
|
||||
CREATE TABLE t1 (a int) engine=innodb;
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
CREATE TABLE t2 (b int);
|
||||
INSERT INTO t2 VALUES (1),(2);
|
||||
--error ER_INVALID_GROUP_FUNC_USE
|
||||
UPDATE t1 NATURAL JOIN t2 SET a = 1 ORDER BY AVG (a) ;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.3 tests
|
||||
--echo #
|
||||
|
||||
|
|
|
@ -732,3 +732,30 @@ a b
|
|||
4 4
|
||||
drop table t1;
|
||||
SET @@in_predicate_conversion_threshold= default;
|
||||
#
|
||||
# MDEV-27937: Prepared statement with ? in the list if IN predicate
|
||||
#
|
||||
set in_predicate_conversion_threshold=2;
|
||||
create table t1 (id int, a int, b int);
|
||||
insert into t1 values (1,3,30), (2,7,70), (3,1,10);
|
||||
prepare stmt from "
|
||||
select * from t1 where a in (7, ?, 5, 1);
|
||||
";
|
||||
execute stmt using 3;
|
||||
id a b
|
||||
1 3 30
|
||||
2 7 70
|
||||
3 1 10
|
||||
deallocate prepare stmt;
|
||||
prepare stmt from "
|
||||
select * from t1 where (a,b) in ((7,70), (3,?), (5,50), (1,10));
|
||||
";
|
||||
execute stmt using 30;
|
||||
id a b
|
||||
1 3 30
|
||||
2 7 70
|
||||
3 1 10
|
||||
deallocate prepare stmt;
|
||||
drop table t1;
|
||||
set in_predicate_conversion_threshold=default;
|
||||
# End of 10.3 tests
|
||||
|
|
|
@ -428,3 +428,29 @@ eval $query;
|
|||
drop table t1;
|
||||
SET @@in_predicate_conversion_threshold= default;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-27937: Prepared statement with ? in the list if IN predicate
|
||||
--echo #
|
||||
|
||||
set in_predicate_conversion_threshold=2;
|
||||
|
||||
create table t1 (id int, a int, b int);
|
||||
insert into t1 values (1,3,30), (2,7,70), (3,1,10);
|
||||
|
||||
prepare stmt from "
|
||||
select * from t1 where a in (7, ?, 5, 1);
|
||||
";
|
||||
execute stmt using 3;
|
||||
deallocate prepare stmt;
|
||||
|
||||
prepare stmt from "
|
||||
select * from t1 where (a,b) in ((7,70), (3,?), (5,50), (1,10));
|
||||
";
|
||||
execute stmt using 30;
|
||||
deallocate prepare stmt;
|
||||
|
||||
drop table t1;
|
||||
|
||||
set in_predicate_conversion_threshold=default;
|
||||
|
||||
--echo # End of 10.3 tests
|
||||
|
|
|
@ -40,3 +40,23 @@ utf8mb4_string xxx😎yyy
|
|||
#
|
||||
# End of 10.1 tests
|
||||
#
|
||||
#
|
||||
# Start of 10.3 tests
|
||||
#
|
||||
#
|
||||
# MDEV-28131 Unexpected warning while selecting from information_schema.processlist
|
||||
#
|
||||
connect conn1, localhost, root,,;
|
||||
connection conn1;
|
||||
SELECT SLEEP(1000);
|
||||
connection default;
|
||||
SELECT progress FROM information_schema.processlist WHERE info='SELECT SLEEP(1000)';
|
||||
progress
|
||||
0.000
|
||||
connection conn1;
|
||||
Got one of the listed errors
|
||||
connection default;
|
||||
disconnect conn1;
|
||||
#
|
||||
# End of 10.3 tests
|
||||
#
|
||||
|
|
|
@ -70,3 +70,38 @@ SELECT INFO, INFO_BINARY, 'xxx😎yyy' AS utf8mb4_string FROM INFORMATION_SCHEMA
|
|||
--echo #
|
||||
--echo # End of 10.1 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.3 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-28131 Unexpected warning while selecting from information_schema.processlist
|
||||
--echo #
|
||||
|
||||
connect (conn1, localhost, root,,);
|
||||
connection conn1;
|
||||
let $ID= `select connection_id()`;
|
||||
send SELECT SLEEP(1000);
|
||||
connection default;
|
||||
let $wait_timeout= 10;
|
||||
let $wait_condition=select count(*)=1 from information_schema.processlist
|
||||
where state='User sleep' and info='SELECT SLEEP(1000)';
|
||||
--source include/wait_condition.inc
|
||||
SELECT progress FROM information_schema.processlist WHERE info='SELECT SLEEP(1000)';
|
||||
disable_query_log;
|
||||
eval kill $ID;
|
||||
enable_query_log;
|
||||
let $wait_timeout= 10;
|
||||
let $wait_condition=select count(*)=0 from information_schema.processlist
|
||||
where state='User sleep' and info='SELECT SLEEP(1000)';
|
||||
--source include/wait_condition.inc
|
||||
connection conn1;
|
||||
--error 2013,ER_CONNECTION_KILLED
|
||||
reap;
|
||||
connection default;
|
||||
disconnect conn1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.3 tests
|
||||
--echo #
|
||||
|
|
|
@ -737,3 +737,66 @@ rec.en1
|
|||
c
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-26009: Server crash when calling twice procedure using FOR-loop
|
||||
#
|
||||
CREATE TABLE t1 ( id int, name varchar(24));
|
||||
INSERT INTO t1 values (1, 'x'), (2, 'y'), (3, 'z');
|
||||
create function get_name(_id int) returns varchar(24)
|
||||
return (select name from t1 where id = _id);
|
||||
select get_name(id) from t1;
|
||||
get_name(id)
|
||||
x
|
||||
y
|
||||
z
|
||||
create procedure test_proc()
|
||||
begin
|
||||
declare _cur cursor for select get_name(id) from t1;
|
||||
for row in _cur do select 1; end for;
|
||||
end;
|
||||
^^
|
||||
call test_proc();
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
call test_proc();
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
drop procedure test_proc;
|
||||
drop function get_name;
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (id int, name varchar(24));
|
||||
INSERT INTO t1 (id, name) VALUES (1, 'x'),(2, 'y'),(3, 'z');
|
||||
create function get_name(_id int) returns varchar(24)
|
||||
return (select name from t1 where id = _id);
|
||||
create view v1 as select get_name(id) from t1;
|
||||
create procedure test_proc()
|
||||
begin
|
||||
declare _cur cursor for select 1 from v1;
|
||||
for row in _cur do select 1; end for;
|
||||
end$$
|
||||
call test_proc();
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
call test_proc();
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
drop procedure test_proc;
|
||||
drop view v1;
|
||||
drop function get_name;
|
||||
drop table t1;
|
||||
|
|
|
@ -744,3 +744,59 @@ DELIMITER ;$$
|
|||
CALL p1();
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-26009: Server crash when calling twice procedure using FOR-loop
|
||||
--echo #
|
||||
|
||||
|
||||
CREATE TABLE t1 ( id int, name varchar(24));
|
||||
INSERT INTO t1 values (1, 'x'), (2, 'y'), (3, 'z');
|
||||
|
||||
create function get_name(_id int) returns varchar(24)
|
||||
return (select name from t1 where id = _id);
|
||||
|
||||
select get_name(id) from t1;
|
||||
|
||||
delimiter ^^;
|
||||
|
||||
create procedure test_proc()
|
||||
begin
|
||||
declare _cur cursor for select get_name(id) from t1;
|
||||
for row in _cur do select 1; end for;
|
||||
end;
|
||||
^^
|
||||
delimiter ;^^
|
||||
|
||||
call test_proc();
|
||||
call test_proc();
|
||||
|
||||
drop procedure test_proc;
|
||||
drop function get_name;
|
||||
drop table t1;
|
||||
|
||||
|
||||
CREATE TABLE t1 (id int, name varchar(24));
|
||||
INSERT INTO t1 (id, name) VALUES (1, 'x'),(2, 'y'),(3, 'z');
|
||||
|
||||
create function get_name(_id int) returns varchar(24)
|
||||
return (select name from t1 where id = _id);
|
||||
|
||||
create view v1 as select get_name(id) from t1;
|
||||
|
||||
delimiter $$;
|
||||
create procedure test_proc()
|
||||
begin
|
||||
declare _cur cursor for select 1 from v1;
|
||||
for row in _cur do select 1; end for;
|
||||
end$$
|
||||
delimiter ;$$
|
||||
|
||||
call test_proc();
|
||||
call test_proc();
|
||||
|
||||
drop procedure test_proc;
|
||||
drop view v1;
|
||||
drop function get_name;
|
||||
drop table t1;
|
||||
|
|
|
@ -6846,6 +6846,34 @@ id bar
|
|||
Drop View v1;
|
||||
Drop table t1;
|
||||
#
|
||||
# MDEV-24281: Execution of PREPARE from CREATE VIEW statement
|
||||
#
|
||||
create table t1 (s1 int);
|
||||
insert into t1 values (3), (7), (1);
|
||||
prepare stmt from "
|
||||
create view v1 as select 's1', s1, 1 as My_exp_s1 from t1;
|
||||
";
|
||||
execute stmt;
|
||||
deallocate prepare stmt;
|
||||
show create view v1;
|
||||
View Create View character_set_client collation_connection
|
||||
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 's1' AS `My_exp_1_s1`,`t1`.`s1` AS `s1`,1 AS `My_exp_s1` from `t1` latin1 latin1_swedish_ci
|
||||
select * from v1;
|
||||
My_exp_1_s1 s1 My_exp_s1
|
||||
s1 3 1
|
||||
s1 7 1
|
||||
s1 1 1
|
||||
drop view v1;
|
||||
prepare stmt from "
|
||||
create view v1 as select 's1', s1, 1 as My_exp_s1 from t1;
|
||||
";
|
||||
execute stmt;
|
||||
execute stmt;
|
||||
ERROR 42S01: Table 'v1' already exists
|
||||
deallocate prepare stmt;
|
||||
drop view v1;
|
||||
drop table t1;
|
||||
#
|
||||
# End of 10.3 tests
|
||||
#
|
||||
#
|
||||
|
|
|
@ -6565,6 +6565,32 @@ SELECT v.id, v.foo AS bar FROM v1 v
|
|||
Drop View v1;
|
||||
Drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-24281: Execution of PREPARE from CREATE VIEW statement
|
||||
--echo #
|
||||
|
||||
create table t1 (s1 int);
|
||||
insert into t1 values (3), (7), (1);
|
||||
|
||||
prepare stmt from "
|
||||
create view v1 as select 's1', s1, 1 as My_exp_s1 from t1;
|
||||
";
|
||||
execute stmt;
|
||||
deallocate prepare stmt;
|
||||
show create view v1;
|
||||
select * from v1;
|
||||
drop view v1;
|
||||
|
||||
prepare stmt from "
|
||||
create view v1 as select 's1', s1, 1 as My_exp_s1 from t1;
|
||||
";
|
||||
execute stmt;
|
||||
--error ER_TABLE_EXISTS_ERROR
|
||||
execute stmt;
|
||||
deallocate prepare stmt;
|
||||
drop view v1;
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.3 tests
|
||||
--echo #
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
ALTER TABLE mysql.gtid_slave_pos ENGINE=innodb;
|
||||
# Restart the server so mysqld reads the gtid_slave_pos using innodb
|
||||
# Set gtid_slave_pos should not hang
|
||||
SET GLOBAL gtid_slave_pos=@@gtid_binlog_pos;
|
||||
COMMIT;
|
||||
RESET MASTER;
|
|
@ -0,0 +1,7 @@
|
|||
CREATE TABLE t1 (a int);
|
||||
FLUSH LOGS;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
# timeout TIMEOUT MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=MASTER_MYPORT --stop-never --result-file=MYSQLTEST_VARDIR/tmp/ master-bin.000001
|
||||
# MYSQL_BINLOG MYSQLTEST_VARDIR/tmp/master-bin.000002 > MYSQLTEST_VARDIR/tmp/local-bin.000002.out
|
||||
FOUND 1 /GTID 0-1-2/ in local-bin.000002.out
|
||||
DROP TABLE t1;
|
|
@ -0,0 +1 @@
|
|||
--autocommit=0
|
45
mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang.test
Normal file
45
mysql-test/suite/binlog/t/binlog_autocommit_off_no_hang.test
Normal file
|
@ -0,0 +1,45 @@
|
|||
#
|
||||
# Purpose:
|
||||
# When the mysql.gtid_slave_pos table uses the InnoDB engine, and mysqld
|
||||
# starts, it reads the table and begins a transaction. After mysqld reads the
|
||||
# value, it should end the transaction and release all associated locks.
|
||||
# The bug reported in DBAAS-7828 shows that when autocommit is off, the locks
|
||||
# are not released, resulting in indefinite hangs on future attempts to change
|
||||
# gtid_slave_pos. This test ensures its fix such that the locks are properly
|
||||
# released.
|
||||
#
|
||||
# References:
|
||||
# DBAAS-7828: Primary/replica: configuration change of "autocommit=0" can
|
||||
# not be applied
|
||||
#
|
||||
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_log_bin.inc
|
||||
|
||||
# Reading gtid_slave_pos table is format independent so just use one for
|
||||
# reduced test time
|
||||
--source include/have_binlog_format_row.inc
|
||||
|
||||
--let old_slave_pos_engine= query_get_value(SHOW TABLE STATUS FROM mysql LIKE 'gtid_slave_pos', Engine, 1)
|
||||
|
||||
# Use a transactional engine
|
||||
ALTER TABLE mysql.gtid_slave_pos ENGINE=innodb;
|
||||
|
||||
--echo # Restart the server so mysqld reads the gtid_slave_pos using innodb
|
||||
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
--shutdown_server
|
||||
--source include/wait_until_disconnected.inc
|
||||
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
--enable_reconnect
|
||||
--source include/wait_until_connected_again.inc
|
||||
|
||||
--echo # Set gtid_slave_pos should not hang
|
||||
SET GLOBAL gtid_slave_pos=@@gtid_binlog_pos;
|
||||
COMMIT;
|
||||
|
||||
# Revert table type
|
||||
--disable_query_log
|
||||
--eval ALTER TABLE mysql.gtid_slave_pos ENGINE=$old_slave_pos_engine
|
||||
--enable_query_log
|
||||
|
||||
RESET MASTER;
|
45
mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test
Normal file
45
mysql-test/suite/binlog/t/binlog_mysqlbinlog_raw_flush.test
Normal file
|
@ -0,0 +1,45 @@
|
|||
#
|
||||
# Purpose:
|
||||
# When using mariadb-binlog with options for --raw and --stop-never, events
|
||||
# from the master's currently active log file should be written to their
|
||||
# respective log file specified by --result-file, and shown on-disk. This test
|
||||
# ensures that the log files on disk, created by mariadb-binlog, have the most
|
||||
# up-to-date events from the master.
|
||||
#
|
||||
# Methodology:
|
||||
# On the master, rotate to a newly active binlog file and write an event to
|
||||
# it. Read the master's binlog using mariadb-binlog with --raw and --stop-never
|
||||
# and write the data to an intermediary binlog file (a timeout is used on this
|
||||
# command to ensure it exits). Read the local intermediary binlog file to ensure
|
||||
# that the master's most recent event exists in the local file.
|
||||
#
|
||||
# References:
|
||||
# MDEV-14608: mysqlbinlog lastest backupfile size is 0
|
||||
#
|
||||
|
||||
--source include/linux.inc
|
||||
--source include/have_log_bin.inc
|
||||
|
||||
# Create newly active log
|
||||
CREATE TABLE t1 (a int);
|
||||
FLUSH LOGS;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
|
||||
# Read binlog data from master to intermediary result file
|
||||
--let TIMEOUT=1
|
||||
--echo # timeout TIMEOUT MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=MASTER_MYPORT --stop-never --result-file=MYSQLTEST_VARDIR/tmp/ master-bin.000001
|
||||
--error 124 # Error 124 means timeout was reached
|
||||
--exec timeout $TIMEOUT $MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --stop-never --result-file=$MYSQLTEST_VARDIR/tmp/ master-bin.000001
|
||||
|
||||
# Ensure the binlog output has the most recent events from the master
|
||||
--echo # MYSQL_BINLOG MYSQLTEST_VARDIR/tmp/master-bin.000002 > MYSQLTEST_VARDIR/tmp/local-bin.000002.out
|
||||
--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/tmp/master-bin.000002 > $MYSQLTEST_VARDIR/tmp/local-bin.000002.out
|
||||
--let SEARCH_PATTERN= GTID 0-1-2
|
||||
--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/local-bin.000002.out
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
# Cleanup
|
||||
DROP TABLE t1;
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000001
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000002
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/local-bin.000002.out
|
|
@ -2962,3 +2962,311 @@ END $$
|
|||
CALL xyz.xyz123(17,18,@R);
|
||||
DROP PACKAGE xyz;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-28166 sql_mode=ORACLE: fully qualified package function calls do not work: db.pkg.func()
|
||||
#
|
||||
SELECT `db `.pkg.func();
|
||||
ERROR 42000: Incorrect database name 'db '
|
||||
SELECT db.`pkg `.func();
|
||||
ERROR 42000: Incorrect routine name 'pkg '
|
||||
SELECT db.pkg.`func `();
|
||||
ERROR 42000: Incorrect routine name 'func '
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
FUNCTION f1 RETURN TEXT;
|
||||
FUNCTION f2_db1_pkg1_f1 RETURN TEXT;
|
||||
FUNCTION f2_pkg1_f1 RETURN TEXT;
|
||||
FUNCTION f2_f1 RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1
|
||||
AS
|
||||
FUNCTION f1 RETURN TEXT IS
|
||||
BEGIN
|
||||
RETURN 'This is db1.pkg1.f1';
|
||||
END;
|
||||
FUNCTION f2_db1_pkg1_f1 RETURN TEXT IS
|
||||
BEGIN
|
||||
RETURN db1.pkg1.f1();
|
||||
END;
|
||||
FUNCTION f2_pkg1_f1 RETURN TEXT IS
|
||||
BEGIN
|
||||
RETURN pkg1.f1();
|
||||
END;
|
||||
FUNCTION f2_f1 RETURN TEXT IS
|
||||
BEGIN
|
||||
RETURN f1();
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
USE db1;
|
||||
SELECT pkg1.f2_db1_pkg1_f1();
|
||||
pkg1.f2_db1_pkg1_f1()
|
||||
This is db1.pkg1.f1
|
||||
SELECT pkg1.f2_pkg1_f1();
|
||||
pkg1.f2_pkg1_f1()
|
||||
This is db1.pkg1.f1
|
||||
SELECT pkg1.f2_f1();
|
||||
pkg1.f2_f1()
|
||||
This is db1.pkg1.f1
|
||||
SELECT db1.pkg1.f2_db1_pkg1_f1();
|
||||
db1.pkg1.f2_db1_pkg1_f1()
|
||||
This is db1.pkg1.f1
|
||||
SELECT db1.pkg1.f2_pkg1_f1();
|
||||
db1.pkg1.f2_pkg1_f1()
|
||||
This is db1.pkg1.f1
|
||||
SELECT db1.pkg1.f2_f1();
|
||||
db1.pkg1.f2_f1()
|
||||
This is db1.pkg1.f1
|
||||
USE test;
|
||||
SELECT db1.pkg1.f2_db1_pkg1_f1();
|
||||
db1.pkg1.f2_db1_pkg1_f1()
|
||||
This is db1.pkg1.f1
|
||||
SELECT db1.pkg1.f2_pkg1_f1();
|
||||
db1.pkg1.f2_pkg1_f1()
|
||||
This is db1.pkg1.f1
|
||||
SELECT db1.pkg1.f2_f1();
|
||||
db1.pkg1.f2_f1()
|
||||
This is db1.pkg1.f1
|
||||
DROP DATABASE db1;
|
||||
CREATE DATABASE db1;
|
||||
CREATE DATABASE db2;
|
||||
CREATE PACKAGE db1.pkg1 AS
|
||||
FUNCTION f1 RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db1.pkg1 AS
|
||||
FUNCTION f1 RETURN TEXT AS
|
||||
BEGIN
|
||||
RETURN 'This is db1.pkg1.f1';
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE db2.pkg1 AS
|
||||
FUNCTION f1 RETURN TEXT;
|
||||
FUNCTION var1 RETURN TEXT;
|
||||
FUNCTION var2 RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db2.pkg1 AS
|
||||
m_var1 TEXT;
|
||||
m_var2 TEXT;
|
||||
FUNCTION f1 RETURN TEXT AS
|
||||
BEGIN
|
||||
RETURN 'This is db2.pkg1.f1';
|
||||
END;
|
||||
FUNCTION var1 RETURN TEXT AS
|
||||
BEGIN
|
||||
RETURN m_var1;
|
||||
END;
|
||||
FUNCTION var2 RETURN TEXT AS
|
||||
BEGIN
|
||||
RETURN m_var2;
|
||||
END;
|
||||
BEGIN
|
||||
m_var1:= db1.pkg1.f1();
|
||||
m_var2:= db2.pkg1.f1();
|
||||
END;
|
||||
$$
|
||||
SELECT db2.pkg1.var1(), db2.pkg1.var2();
|
||||
db2.pkg1.var1() db2.pkg1.var2()
|
||||
This is db1.pkg1.f1 This is db2.pkg1.f1
|
||||
DROP DATABASE db1;
|
||||
DROP DATABASE db2;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
FUNCTION f1(a TEXT) RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
FUNCTION f1(a TEXT) RETURN TEXT AS
|
||||
BEGIN
|
||||
RETURN a;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT test.pkg1.f1('xxx');
|
||||
test.pkg1.f1('xxx')
|
||||
xxx
|
||||
SELECT test.pkg1.f1('xxx' AS a);
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'AS a)' at line 1
|
||||
DROP PACKAGE pkg1;
|
||||
#
|
||||
# MDEV-19328 sql_mode=ORACLE: Package function in VIEW
|
||||
#
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE PACKAGE test1 AS
|
||||
FUNCTION f_test RETURN number;
|
||||
END test1;
|
||||
$$
|
||||
CREATE PACKAGE BODY test1
|
||||
AS
|
||||
FUNCTION f_test RETURN NUMBER IS
|
||||
BEGIN
|
||||
RETURN 1;
|
||||
END;
|
||||
END test1;
|
||||
$$
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test();
|
||||
SELECT * FROM v_test;
|
||||
c1
|
||||
1
|
||||
SHOW CREATE VIEW v_test;
|
||||
View v_test
|
||||
Create View CREATE VIEW "v_test" AS select 1 AS "c1" from DUAL where 1 = "test"."test1"."f_test"()
|
||||
character_set_client latin1
|
||||
collation_connection latin1_swedish_ci
|
||||
SET sql_mode=DEFAULT;
|
||||
SELECT * FROM v_test;
|
||||
c1
|
||||
1
|
||||
SHOW CREATE VIEW v_test;
|
||||
View v_test
|
||||
Create View CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_test` AS select 1 AS `c1` from DUAL where 1 = `test`.`test1`.`f_test`()
|
||||
character_set_client latin1
|
||||
collation_connection latin1_swedish_ci
|
||||
DROP VIEW v_test;
|
||||
SET sql_mode=DEFAULT;
|
||||
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test();
|
||||
ERROR 42000: FUNCTION test1.f_test does not exist
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test.test1.f_test();
|
||||
SELECT * FROM v_test;
|
||||
c1
|
||||
1
|
||||
SHOW CREATE VIEW v_test;
|
||||
View v_test
|
||||
Create View CREATE VIEW "v_test" AS select 1 AS "c1" from DUAL where 1 = "test"."test1"."f_test"()
|
||||
character_set_client latin1
|
||||
collation_connection latin1_swedish_ci
|
||||
SET sql_mode=DEFAULT;
|
||||
SELECT * FROM v_test;
|
||||
c1
|
||||
1
|
||||
SHOW CREATE VIEW v_test;
|
||||
View v_test
|
||||
Create View CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_test` AS select 1 AS `c1` from DUAL where 1 = `test`.`test1`.`f_test`()
|
||||
character_set_client latin1
|
||||
collation_connection latin1_swedish_ci
|
||||
DROP VIEW v_test;
|
||||
SET sql_mode=DEFAULT;
|
||||
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test.test1.f_test();
|
||||
SELECT * FROM v_test;
|
||||
c1
|
||||
1
|
||||
SHOW CREATE VIEW v_test;
|
||||
View v_test
|
||||
Create View CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_test` AS select 1 AS `c1` from DUAL where 1 = `test`.`test1`.`f_test`()
|
||||
character_set_client latin1
|
||||
collation_connection latin1_swedish_ci
|
||||
SET sql_mode=ORACLE;
|
||||
SELECT * FROM v_test;
|
||||
c1
|
||||
1
|
||||
SHOW CREATE VIEW v_test;
|
||||
View v_test
|
||||
Create View CREATE VIEW "v_test" AS select 1 AS "c1" from DUAL where 1 = "test"."test1"."f_test"()
|
||||
character_set_client latin1
|
||||
collation_connection latin1_swedish_ci
|
||||
DROP VIEW v_test;
|
||||
SET sql_mode=ORACLE;
|
||||
DROP PACKAGE test1;
|
||||
#
|
||||
# MDEV-19804 sql_mode=ORACLE: call procedure in packages
|
||||
#
|
||||
CALL `db1 `.pkg.p;
|
||||
ERROR 42000: Incorrect database name 'db1 '
|
||||
CALL db1.`pkg `.p;
|
||||
ERROR 42000: Incorrect routine name 'pkg '
|
||||
CALL db1.pkg.`p `;
|
||||
ERROR 42000: Incorrect routine name 'p '
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE PACKAGE pkg1 as
|
||||
PROCEDURE p1();
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1 as
|
||||
PROCEDURE p1() as
|
||||
BEGIN
|
||||
SELECT 'test-function' AS c1;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CALL pkg1.p1;
|
||||
c1
|
||||
test-function
|
||||
CALL test.pkg1.p1;
|
||||
c1
|
||||
test-function
|
||||
SET sql_mode=DEFAULT;
|
||||
CALL test.pkg1.p1;
|
||||
c1
|
||||
test-function
|
||||
SET sql_mode=ORACLE;
|
||||
BEGIN
|
||||
CALL pkg1.p1;
|
||||
CALL test.pkg1.p1;
|
||||
END
|
||||
$$
|
||||
c1
|
||||
test-function
|
||||
c1
|
||||
test-function
|
||||
BEGIN
|
||||
pkg1.p1;
|
||||
test.pkg1.p1;
|
||||
END
|
||||
$$
|
||||
c1
|
||||
test-function
|
||||
c1
|
||||
test-function
|
||||
DROP PACKAGE pkg1;
|
||||
CREATE DATABASE db1;
|
||||
CREATE PACKAGE db1.pkg1 AS
|
||||
PROCEDURE p1(a OUT TEXT);
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db1.pkg1 AS
|
||||
PROCEDURE p1(a OUT TEXT) AS
|
||||
BEGIN
|
||||
a:= 'This is db1.pkg1.p1';
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
CREATE DATABASE db2;
|
||||
CREATE PACKAGE db2.pkg1 AS
|
||||
FUNCTION var1 RETURN TEXT;
|
||||
PROCEDURE p1(a OUT TEXT);
|
||||
PROCEDURE p2_db1_pkg1_p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db2.pkg1 AS
|
||||
m_var1 TEXT;
|
||||
FUNCTION var1 RETURN TEXT AS
|
||||
BEGIN
|
||||
RETURN m_var1;
|
||||
END;
|
||||
PROCEDURE p1(a OUT TEXT) AS
|
||||
BEGIN
|
||||
a:= 'This is db2.pkg1.p1';
|
||||
END;
|
||||
PROCEDURE p2_db1_pkg1_p1 AS
|
||||
a TEXT;
|
||||
BEGIN
|
||||
db1.pkg1.p1(a);
|
||||
SELECT a;
|
||||
END;
|
||||
BEGIN
|
||||
db1.pkg1.p1(m_var1);
|
||||
END;
|
||||
$$
|
||||
SELECT db2.pkg1.var1();
|
||||
db2.pkg1.var1()
|
||||
This is db1.pkg1.p1
|
||||
CALL db2.pkg1.p2_db1_pkg1_p1;
|
||||
a
|
||||
This is db1.pkg1.p1
|
||||
DROP DATABASE db1;
|
||||
DROP DATABASE db2;
|
||||
|
|
|
@ -2689,3 +2689,330 @@ DELIMITER ;$$
|
|||
CALL xyz.xyz123(17,18,@R);
|
||||
DROP PACKAGE xyz;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-28166 sql_mode=ORACLE: fully qualified package function calls do not work: db.pkg.func()
|
||||
--echo #
|
||||
|
||||
--error ER_WRONG_DB_NAME
|
||||
SELECT `db `.pkg.func();
|
||||
--error ER_SP_WRONG_NAME
|
||||
SELECT db.`pkg `.func();
|
||||
--error ER_SP_WRONG_NAME
|
||||
SELECT db.pkg.`func `();
|
||||
|
||||
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
FUNCTION f1 RETURN TEXT;
|
||||
FUNCTION f2_db1_pkg1_f1 RETURN TEXT;
|
||||
FUNCTION f2_pkg1_f1 RETURN TEXT;
|
||||
FUNCTION f2_f1 RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1
|
||||
AS
|
||||
FUNCTION f1 RETURN TEXT IS
|
||||
BEGIN
|
||||
RETURN 'This is db1.pkg1.f1';
|
||||
END;
|
||||
FUNCTION f2_db1_pkg1_f1 RETURN TEXT IS
|
||||
BEGIN
|
||||
RETURN db1.pkg1.f1();
|
||||
END;
|
||||
FUNCTION f2_pkg1_f1 RETURN TEXT IS
|
||||
BEGIN
|
||||
RETURN pkg1.f1();
|
||||
END;
|
||||
FUNCTION f2_f1 RETURN TEXT IS
|
||||
BEGIN
|
||||
RETURN f1();
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
USE db1;
|
||||
SELECT pkg1.f2_db1_pkg1_f1();
|
||||
SELECT pkg1.f2_pkg1_f1();
|
||||
SELECT pkg1.f2_f1();
|
||||
|
||||
SELECT db1.pkg1.f2_db1_pkg1_f1();
|
||||
SELECT db1.pkg1.f2_pkg1_f1();
|
||||
SELECT db1.pkg1.f2_f1();
|
||||
|
||||
USE test;
|
||||
SELECT db1.pkg1.f2_db1_pkg1_f1();
|
||||
SELECT db1.pkg1.f2_pkg1_f1();
|
||||
SELECT db1.pkg1.f2_f1();
|
||||
|
||||
DROP DATABASE db1;
|
||||
|
||||
|
||||
#
|
||||
# Testing db.pkg.func() in the package initialization section
|
||||
#
|
||||
|
||||
CREATE DATABASE db1;
|
||||
CREATE DATABASE db2;
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE db1.pkg1 AS
|
||||
FUNCTION f1 RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db1.pkg1 AS
|
||||
FUNCTION f1 RETURN TEXT AS
|
||||
BEGIN
|
||||
RETURN 'This is db1.pkg1.f1';
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE db2.pkg1 AS
|
||||
FUNCTION f1 RETURN TEXT;
|
||||
FUNCTION var1 RETURN TEXT;
|
||||
FUNCTION var2 RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db2.pkg1 AS
|
||||
m_var1 TEXT;
|
||||
m_var2 TEXT;
|
||||
FUNCTION f1 RETURN TEXT AS
|
||||
BEGIN
|
||||
RETURN 'This is db2.pkg1.f1';
|
||||
END;
|
||||
FUNCTION var1 RETURN TEXT AS
|
||||
BEGIN
|
||||
RETURN m_var1;
|
||||
END;
|
||||
FUNCTION var2 RETURN TEXT AS
|
||||
BEGIN
|
||||
RETURN m_var2;
|
||||
END;
|
||||
BEGIN
|
||||
m_var1:= db1.pkg1.f1();
|
||||
m_var2:= db2.pkg1.f1();
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
SELECT db2.pkg1.var1(), db2.pkg1.var2();
|
||||
|
||||
DROP DATABASE db1;
|
||||
DROP DATABASE db2;
|
||||
|
||||
#
|
||||
# Make sure fully qualified package function call does not support AS syntax:
|
||||
# SELECT db.pkg.func(10 AS a);
|
||||
#
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 AS
|
||||
FUNCTION f1(a TEXT) RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1 AS
|
||||
FUNCTION f1(a TEXT) RETURN TEXT AS
|
||||
BEGIN
|
||||
RETURN a;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
SELECT test.pkg1.f1('xxx');
|
||||
--error ER_PARSE_ERROR
|
||||
SELECT test.pkg1.f1('xxx' AS a);
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-19328 sql_mode=ORACLE: Package function in VIEW
|
||||
--echo #
|
||||
|
||||
SET sql_mode=ORACLE;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE test1 AS
|
||||
FUNCTION f_test RETURN number;
|
||||
END test1;
|
||||
$$
|
||||
CREATE PACKAGE BODY test1
|
||||
AS
|
||||
FUNCTION f_test RETURN NUMBER IS
|
||||
BEGIN
|
||||
RETURN 1;
|
||||
END;
|
||||
END test1;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test();
|
||||
SELECT * FROM v_test;
|
||||
--vertical_results
|
||||
SHOW CREATE VIEW v_test;
|
||||
--horizontal_results
|
||||
SET sql_mode=DEFAULT;
|
||||
SELECT * FROM v_test;
|
||||
--vertical_results
|
||||
SHOW CREATE VIEW v_test;
|
||||
--horizontal_results
|
||||
DROP VIEW v_test;
|
||||
|
||||
|
||||
SET sql_mode=DEFAULT;
|
||||
--error ER_SP_DOES_NOT_EXIST
|
||||
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test1.f_test();
|
||||
|
||||
|
||||
SET sql_mode=ORACLE;
|
||||
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test.test1.f_test();
|
||||
SELECT * FROM v_test;
|
||||
--vertical_results
|
||||
SHOW CREATE VIEW v_test;
|
||||
--horizontal_results
|
||||
SET sql_mode=DEFAULT;
|
||||
SELECT * FROM v_test;
|
||||
--vertical_results
|
||||
SHOW CREATE VIEW v_test;
|
||||
--horizontal_results
|
||||
DROP VIEW v_test;
|
||||
|
||||
|
||||
SET sql_mode=DEFAULT;
|
||||
CREATE VIEW v_test AS SELECT 1 AS c1 FROM DUAL WHERE 1=test.test1.f_test();
|
||||
SELECT * FROM v_test;
|
||||
--vertical_results
|
||||
SHOW CREATE VIEW v_test;
|
||||
--horizontal_results
|
||||
SET sql_mode=ORACLE;
|
||||
SELECT * FROM v_test;
|
||||
--vertical_results
|
||||
SHOW CREATE VIEW v_test;
|
||||
--horizontal_results
|
||||
DROP VIEW v_test;
|
||||
|
||||
SET sql_mode=ORACLE;
|
||||
DROP PACKAGE test1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-19804 sql_mode=ORACLE: call procedure in packages
|
||||
--echo #
|
||||
|
||||
--error ER_WRONG_DB_NAME
|
||||
CALL `db1 `.pkg.p;
|
||||
--error ER_SP_WRONG_NAME
|
||||
CALL db1.`pkg `.p;
|
||||
--error ER_SP_WRONG_NAME
|
||||
CALL db1.pkg.`p `;
|
||||
|
||||
|
||||
SET sql_mode=ORACLE;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg1 as
|
||||
PROCEDURE p1();
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg1 as
|
||||
PROCEDURE p1() as
|
||||
BEGIN
|
||||
SELECT 'test-function' AS c1;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CALL pkg1.p1;
|
||||
CALL test.pkg1.p1;
|
||||
|
||||
# In sql_mode=DEFAULT we support fully qualified package function names
|
||||
# (this is needed for VIEWs). Let's make sure we also support fully
|
||||
# qualified package procedure names, for symmetry
|
||||
|
||||
SET sql_mode=DEFAULT;
|
||||
CALL test.pkg1.p1;
|
||||
SET sql_mode=ORACLE;
|
||||
|
||||
DELIMITER $$;
|
||||
BEGIN
|
||||
CALL pkg1.p1;
|
||||
CALL test.pkg1.p1;
|
||||
END
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DELIMITER $$;
|
||||
BEGIN
|
||||
pkg1.p1;
|
||||
test.pkg1.p1;
|
||||
END
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
|
||||
#
|
||||
# Testing packages in different databases calling each other
|
||||
# in routines and in the initialization section.
|
||||
#
|
||||
|
||||
CREATE DATABASE db1;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE db1.pkg1 AS
|
||||
PROCEDURE p1(a OUT TEXT);
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db1.pkg1 AS
|
||||
PROCEDURE p1(a OUT TEXT) AS
|
||||
BEGIN
|
||||
a:= 'This is db1.pkg1.p1';
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
CREATE DATABASE db2;
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE db2.pkg1 AS
|
||||
FUNCTION var1 RETURN TEXT;
|
||||
PROCEDURE p1(a OUT TEXT);
|
||||
PROCEDURE p2_db1_pkg1_p1;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY db2.pkg1 AS
|
||||
m_var1 TEXT;
|
||||
FUNCTION var1 RETURN TEXT AS
|
||||
BEGIN
|
||||
RETURN m_var1;
|
||||
END;
|
||||
PROCEDURE p1(a OUT TEXT) AS
|
||||
BEGIN
|
||||
a:= 'This is db2.pkg1.p1';
|
||||
END;
|
||||
PROCEDURE p2_db1_pkg1_p1 AS
|
||||
a TEXT;
|
||||
BEGIN
|
||||
db1.pkg1.p1(a);
|
||||
SELECT a;
|
||||
END;
|
||||
BEGIN
|
||||
db1.pkg1.p1(m_var1);
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
SELECT db2.pkg1.var1();
|
||||
CALL db2.pkg1.p2_db1_pkg1_p1;
|
||||
|
||||
DROP DATABASE db1;
|
||||
DROP DATABASE db2;
|
||||
|
|
|
@ -38,3 +38,4 @@ partition : MDEV-19958 Galera test failure on galera.partition
|
|||
query_cache: MDEV-15805 Test failure on galera.query_cache
|
||||
versioning_trx_id: MDEV-18590: galera.versioning_trx_id: Test failure: mysqltest: Result content mismatch
|
||||
galera_bf_abort_at_after_statement : Unstable
|
||||
galera_bf_abort_ps_bind : MDEV-28193 Galera test failure on galera_bf_abort_ps_bind
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
if (!$kill_signal)
|
||||
{
|
||||
--let $kill_signal = 9
|
||||
--let $kill_signal = KILL
|
||||
}
|
||||
|
||||
# Write file to make mysql-test-run.pl expect the crash, but don't start it
|
||||
|
|
23
mysql-test/suite/galera/r/MDEV-24143.result
Normal file
23
mysql-test/suite/galera/r/MDEV-24143.result
Normal file
|
@ -0,0 +1,23 @@
|
|||
connection node_2;
|
||||
connection node_1;
|
||||
CREATE TABLE t1 (c1 BIGINT NOT NULL PRIMARY KEY, c2 BINARY (10), c3 DATETIME);
|
||||
SELECT get_lock ('test2', 0);
|
||||
get_lock ('test2', 0)
|
||||
1
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (c1 SMALLINT NOT NULL AUTO_INCREMENT PRIMARY KEY);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
SET SESSION wsrep_trx_fragment_size=10;
|
||||
SET SESSION autocommit=0;
|
||||
SELECT * FROM t1 WHERE c1 <=0 ORDER BY c1 DESC;
|
||||
c1
|
||||
INSERT INTO t1 VALUES (4),(3),(1),(2);
|
||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||
CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=SEQUENCE;
|
||||
ERROR 42S01: Table 't1' already exists
|
||||
ALTER TABLE t1 DROP COLUMN c2;
|
||||
ERROR 42000: Can't DROP COLUMN `c2`; check that it exists
|
||||
SELECT get_lock ('test', 1.5);
|
||||
get_lock ('test', 1.5)
|
||||
1
|
||||
DROP TABLE t1;
|
46
mysql-test/suite/galera/r/MDEV-27713.result
Normal file
46
mysql-test/suite/galera/r/MDEV-27713.result
Normal file
|
@ -0,0 +1,46 @@
|
|||
connection node_2;
|
||||
connection node_1;
|
||||
CREATE TABLE t1 (
|
||||
f1 INT,
|
||||
f2 VARCHAR(255) PRIMARY KEY
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
INSERT INTO t1 VALUES(1, 'abc');
|
||||
connection node_1;
|
||||
SET AUTOCOMMIT=OFF;
|
||||
START TRANSACTION;
|
||||
INSERT INTO t1 VALUES (2,'def');
|
||||
connection node_2;
|
||||
SET GLOBAL event_scheduler=ON;
|
||||
CREATE PROCEDURE update_table()
|
||||
BEGIN
|
||||
SET AUTOCOMMIT=OFF;
|
||||
DO GET_LOCK('local_lock', 0);
|
||||
SET DEBUG_SYNC = 'innodb_row_update_for_mysql_begin SIGNAL blocked WAIT_FOR continue';
|
||||
UPDATE t1 SET f2 = 'jkl' WHERE f1 != 2;
|
||||
DO RELEASE_LOCK('local_lock');
|
||||
END|
|
||||
CREATE DEFINER=current_user
|
||||
EVENT event
|
||||
ON SCHEDULE AT CURRENT_TIMESTAMP
|
||||
ON COMPLETION PRESERVE
|
||||
ENABLE
|
||||
DO CALL update_table();
|
||||
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR blocked';
|
||||
connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2;
|
||||
SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb";
|
||||
connection node_1;
|
||||
COMMIT;
|
||||
connection node_2b;
|
||||
SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
|
||||
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
|
||||
connection node_2a;
|
||||
SET DEBUG_SYNC = 'now SIGNAL continue';
|
||||
connection node_2;
|
||||
SET GLOBAL event_scheduler=default;
|
||||
DROP PROCEDURE update_table;
|
||||
DROP EVENT event;
|
||||
SET DEBUG_SYNC='reset';
|
||||
SET GLOBAL debug_dbug = DEFAULT;
|
||||
connection node_1;
|
||||
DROP TABLE t1;
|
37
mysql-test/suite/galera/r/galera_bf_abort_ps_bind.result
Normal file
37
mysql-test/suite/galera/r/galera_bf_abort_ps_bind.result
Normal file
|
@ -0,0 +1,37 @@
|
|||
connection node_2;
|
||||
connection node_1;
|
||||
CREATE TABLE t (i int primary key auto_increment, j varchar(20) character set utf8);
|
||||
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
|
||||
connection node_1a;
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
connection node_1;
|
||||
insert into t values (1, 'first');
|
||||
PS_prepare INSERT INTO t(j) VALUES (?);;
|
||||
PS_bind node1;
|
||||
PS_execute;
|
||||
PS_execute;
|
||||
select * from t;
|
||||
i j
|
||||
1 first
|
||||
3 node1
|
||||
5 node1
|
||||
PS_close;
|
||||
PS_prepare INSERT INTO t(j) VALUES (?);;
|
||||
PS_bind node1;
|
||||
begin;
|
||||
update t set j='node1' where i=1;
|
||||
connection node_2;
|
||||
update t set j='node2' where i=1;
|
||||
connection node_1a;
|
||||
connection node_1;
|
||||
PS_execute;
|
||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||
PS_execute;
|
||||
commit;
|
||||
select * from t;
|
||||
i j
|
||||
1 node2
|
||||
3 node1
|
||||
5 node1
|
||||
7 node1
|
||||
drop table t;
|
|
@ -18,6 +18,7 @@ SET SESSION wsrep_on=ON;
|
|||
connection node_1;
|
||||
UPDATE t1 SET f2 = 'd' WHERE f1 > 3;
|
||||
connection node_2;
|
||||
Killing server ...
|
||||
connection node_1;
|
||||
UPDATE t1 SET f2 = 'e' WHERE f1 > 4;
|
||||
connection node_2;
|
||||
|
|
20
mysql-test/suite/galera/t/MDEV-24143.test
Normal file
20
mysql-test/suite/galera/t/MDEV-24143.test
Normal file
|
@ -0,0 +1,20 @@
|
|||
--source include/galera_cluster.inc
|
||||
--source include/have_sequence.inc
|
||||
|
||||
CREATE TABLE t1 (c1 BIGINT NOT NULL PRIMARY KEY, c2 BINARY (10), c3 DATETIME);
|
||||
SELECT get_lock ('test2', 0);
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (c1 SMALLINT NOT NULL AUTO_INCREMENT PRIMARY KEY);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
SET SESSION wsrep_trx_fragment_size=10;
|
||||
SET SESSION autocommit=0;
|
||||
SELECT * FROM t1 WHERE c1 <=0 ORDER BY c1 DESC;
|
||||
--error ER_LOCK_DEADLOCK
|
||||
INSERT INTO t1 VALUES (4),(3),(1),(2);
|
||||
--error ER_TABLE_EXISTS_ERROR
|
||||
CREATE TABLE t1 (pk INT PRIMARY KEY, b INT) ENGINE=SEQUENCE;
|
||||
--error ER_CANT_DROP_FIELD_OR_KEY
|
||||
ALTER TABLE t1 DROP COLUMN c2;
|
||||
SELECT get_lock ('test', 1.5);
|
||||
DROP TABLE t1;
|
||||
|
67
mysql-test/suite/galera/t/MDEV-27713.test
Normal file
67
mysql-test/suite/galera/t/MDEV-27713.test
Normal file
|
@ -0,0 +1,67 @@
|
|||
--source include/galera_cluster.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug.inc
|
||||
--source include/have_debug_sync.inc
|
||||
--source include/big_test.inc
|
||||
|
||||
CREATE TABLE t1 (
|
||||
f1 INT,
|
||||
f2 VARCHAR(255) PRIMARY KEY
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO t1 VALUES(1, 'abc');
|
||||
|
||||
--connection node_1
|
||||
SET AUTOCOMMIT=OFF;
|
||||
START TRANSACTION;
|
||||
INSERT INTO t1 VALUES (2,'def');
|
||||
|
||||
--connection node_2
|
||||
|
||||
SET GLOBAL event_scheduler=ON;
|
||||
|
||||
DELIMITER |;
|
||||
CREATE PROCEDURE update_table()
|
||||
BEGIN
|
||||
SET AUTOCOMMIT=OFF;
|
||||
DO GET_LOCK('local_lock', 0);
|
||||
SET DEBUG_SYNC = 'innodb_row_update_for_mysql_begin SIGNAL blocked WAIT_FOR continue';
|
||||
UPDATE t1 SET f2 = 'jkl' WHERE f1 != 2;
|
||||
DO RELEASE_LOCK('local_lock');
|
||||
END|
|
||||
DELIMITER ;|
|
||||
|
||||
CREATE DEFINER=current_user
|
||||
EVENT event
|
||||
ON SCHEDULE AT CURRENT_TIMESTAMP
|
||||
ON COMPLETION PRESERVE
|
||||
ENABLE
|
||||
DO CALL update_table();
|
||||
|
||||
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR blocked';
|
||||
|
||||
# Applier control thread
|
||||
--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2
|
||||
SET GLOBAL debug_dbug = "+d,sync.wsrep_apply_cb";
|
||||
|
||||
--connection node_1
|
||||
COMMIT;
|
||||
|
||||
# Applier control thread
|
||||
--connection node_2b
|
||||
SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
|
||||
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb";
|
||||
|
||||
--connection node_2a
|
||||
SET DEBUG_SYNC = 'now SIGNAL continue';
|
||||
|
||||
--connection node_2
|
||||
SET GLOBAL event_scheduler=default;
|
||||
DROP PROCEDURE update_table;
|
||||
DROP EVENT event;
|
||||
SET DEBUG_SYNC='reset';
|
||||
SET GLOBAL debug_dbug = DEFAULT;
|
||||
|
||||
--connection node_1
|
||||
DROP TABLE t1;
|
|
@ -7,6 +7,7 @@
|
|||
# masks all deadlock errors
|
||||
#
|
||||
|
||||
--source include/no_protocol.inc
|
||||
--source include/galera_cluster.inc
|
||||
--source suite/galera/t/MW-328-header.inc
|
||||
|
||||
|
|
|
@ -19,7 +19,11 @@ SET SESSION wsrep_osu_method=RSU;
|
|||
ALTER TABLE t1 ADD COLUMN f2 INTEGER;
|
||||
SET SESSION wsrep_osu_method=TOI;
|
||||
|
||||
--let $wait_condition = SELECT COUNT(*) = 2 FROM mysql.general_log WHERE argument LIKE "CREATE%" OR argument LIKE "ALTER%"
|
||||
--let $wait_condition = SELECT COUNT(*) = 1 FROM mysql.general_log WHERE argument LIKE "CREATE%" AND command_type != 'Prepare'
|
||||
--let $wait_condition_on_error_output = SELECT * FROM mysql.general_log
|
||||
--source include/wait_condition_with_debug.inc
|
||||
|
||||
--let $wait_condition = SELECT COUNT(*) = 1 FROM mysql.general_log WHERE argument LIKE "ALTER%" AND command_type != 'Prepare'
|
||||
--let $wait_condition_on_error_output = SELECT * FROM mysql.general_log
|
||||
--source include/wait_condition_with_debug.inc
|
||||
|
||||
|
|
7
mysql-test/suite/galera/t/galera_bf_abort_ps_bind.cnf
Normal file
7
mysql-test/suite/galera/t/galera_bf_abort_ps_bind.cnf
Normal file
|
@ -0,0 +1,7 @@
|
|||
!include ../galera_2nodes.cnf
|
||||
|
||||
[mysqld.1]
|
||||
wsrep-debug=1
|
||||
|
||||
[mysqld.2]
|
||||
wsrep-debug=1
|
58
mysql-test/suite/galera/t/galera_bf_abort_ps_bind.test
Normal file
58
mysql-test/suite/galera/t/galera_bf_abort_ps_bind.test
Normal file
|
@ -0,0 +1,58 @@
|
|||
--source include/galera_cluster.inc
|
||||
--source include/have_innodb.inc
|
||||
|
||||
CREATE TABLE t (i int primary key auto_increment, j varchar(20) character set utf8);
|
||||
|
||||
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
|
||||
--connection node_1a
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
|
||||
--connection node_1
|
||||
insert into t values (1, 'first');
|
||||
|
||||
# prepare a statement for inserting rows into table t
|
||||
--PS_prepare INSERT INTO t(j) VALUES (?);
|
||||
|
||||
# bind parameter, to insert with column j having value 'node1'
|
||||
--PS_bind node1
|
||||
|
||||
# insert two rows with the PS
|
||||
# this is for showing that two execute commands can follow a bind command
|
||||
--PS_execute
|
||||
--PS_execute
|
||||
select * from t;
|
||||
|
||||
# close the prepared statement, and prepare a new PS,
|
||||
# this happens to be same as the first PS
|
||||
# also bind parameter for the PS
|
||||
--PS_close
|
||||
--PS_prepare INSERT INTO t(j) VALUES (?);
|
||||
--PS_bind node1
|
||||
|
||||
# start a transaction and make one update
|
||||
# leaving the transaction open
|
||||
begin;
|
||||
update t set j='node1' where i=1;
|
||||
|
||||
# replicate a transaction from node2, which BF aborts the open
|
||||
# transaction in node1
|
||||
--connection node_2
|
||||
update t set j='node2' where i=1;
|
||||
|
||||
# wait until the BF has completed, and update from node_2 has committed
|
||||
--connection node_1a
|
||||
--let $wait_condition = SELECT COUNT(*) = 1 FROM t WHERE j='node2'
|
||||
--source include/wait_condition.inc
|
||||
|
||||
# continue the open transaction, trying to insert third row, deadlock is now observed
|
||||
--connection node_1
|
||||
--error ER_LOCK_DEADLOCK
|
||||
--PS_execute
|
||||
|
||||
# try to insert one more row
|
||||
--PS_execute
|
||||
commit;
|
||||
|
||||
select * from t;
|
||||
|
||||
drop table t;
|
|
@ -61,19 +61,7 @@ UPDATE t1 SET f2 = 'd' WHERE f1 > 3;
|
|||
|
||||
# Kill node #2 while IST is in progress
|
||||
--connection node_2
|
||||
|
||||
# Kill the connected server
|
||||
--disable_reconnect
|
||||
|
||||
--perl
|
||||
my $pid_filename = $ENV{'KILL_NODE_PIDFILE'};
|
||||
my $mysqld_pid = `cat $pid_filename`;
|
||||
chomp($mysqld_pid);
|
||||
system("kill -9 $mysqld_pid");
|
||||
exit(0);
|
||||
EOF
|
||||
|
||||
--source include/wait_until_disconnected.inc
|
||||
--source include/kill_galera.inc
|
||||
|
||||
--connection node_1
|
||||
--source include/wait_until_connected_again.inc
|
||||
|
|
41
mysql-test/suite/galera_3nodes/r/galera_garbd_backup.result
Normal file
41
mysql-test/suite/galera_3nodes/r/galera_garbd_backup.result
Normal file
|
@ -0,0 +1,41 @@
|
|||
connection node_1;
|
||||
connection node_1;
|
||||
connection node_2;
|
||||
connection node_3;
|
||||
connection node_1;
|
||||
SET GLOBAL innodb_max_dirty_pages_pct=99;
|
||||
SET GLOBAL innodb_max_dirty_pages_pct_lwm=99;
|
||||
connection node_1;
|
||||
CREATE TABLE t1 (f1 INTEGER, f2 varchar(1024)) Engine=InnoDB;
|
||||
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
|
||||
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
|
||||
INSERT INTO t1 (f2) SELECT REPEAT('x', 1024) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
|
||||
connection node_2;
|
||||
Killing node #3 to free ports for garbd ...
|
||||
connection node_3;
|
||||
connection node_1;
|
||||
SET GLOBAL debug_dbug = "+d,sync.wsrep_donor_state";
|
||||
Starting garbd ...
|
||||
SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_donor_state_reached";
|
||||
SET GLOBAL innodb_max_dirty_pages_pct_lwm=0;
|
||||
SET GLOBAL innodb_max_dirty_pages_pct=0;
|
||||
SET SESSION debug_sync = "now SIGNAL signal.wsrep_donor_state";
|
||||
SET GLOBAL debug_dbug = "";
|
||||
SET debug_sync='RESET';
|
||||
connection node_2;
|
||||
Killing garbd ...
|
||||
connection node_1;
|
||||
connection node_2;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE ten;
|
||||
Restarting node #3 to satisfy MTR's end-of-test checks
|
||||
connection node_3;
|
||||
connection node_1;
|
||||
SET GLOBAL innodb_max_dirty_pages_pct = 75.000000;
|
||||
SET GLOBAL innodb_max_dirty_pages_pct_lwm = 0.000000;
|
||||
connection node_1;
|
||||
CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)");
|
||||
connection node_2;
|
||||
CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)");
|
||||
connection node_3;
|
||||
CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)");
|
13
mysql-test/suite/galera_3nodes/t/galera_garbd_backup.cnf
Normal file
13
mysql-test/suite/galera_3nodes/t/galera_garbd_backup.cnf
Normal file
|
@ -0,0 +1,13 @@
|
|||
!include ../galera_3nodes.cnf
|
||||
|
||||
[mysqld]
|
||||
wsrep_sst_method=rsync
|
||||
|
||||
[mysqld.1]
|
||||
wsrep_node_name=node1
|
||||
|
||||
[mysqld.2]
|
||||
wsrep_node_name=node2
|
||||
|
||||
[mysqld.3]
|
||||
wsrep_node_name=node3
|
134
mysql-test/suite/galera_3nodes/t/galera_garbd_backup.test
Normal file
134
mysql-test/suite/galera_3nodes/t/galera_garbd_backup.test
Normal file
|
@ -0,0 +1,134 @@
|
|||
#
|
||||
# A very basic test for the galera arbitrator. We shut down node #3 and use its port allocation to start garbd.
|
||||
# As MTR does not allow multiple servers to be down at the same time, we are limited as to what we can test.
|
||||
#
|
||||
|
||||
--source include/galera_cluster.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_garbd.inc
|
||||
--source include/big_test.inc
|
||||
--source include/have_debug.inc
|
||||
--source include/have_debug_sync.inc
|
||||
|
||||
--connection node_1
|
||||
# Save original auto_increment_offset values.
|
||||
--let $node_1=node_1
|
||||
--let $node_2=node_2
|
||||
--let $node_3=node_3
|
||||
|
||||
--let $galera_connection_name = node_3
|
||||
--let $galera_server_number = 3
|
||||
--source include/galera_connect.inc
|
||||
--source suite/galera/include/galera_base_port.inc
|
||||
--let $NODE_GALERAPORT_3 = $_NODE_GALERAPORT
|
||||
|
||||
--source ../galera/include/auto_increment_offset_save.inc
|
||||
|
||||
# Save galera ports
|
||||
--connection node_1
|
||||
--source suite/galera/include/galera_base_port.inc
|
||||
--let $NODE_GALERAPORT_1 = $_NODE_GALERAPORT
|
||||
--let $datadir= `SELECT @@datadir`
|
||||
|
||||
--let $innodb_max_dirty_pages_pct = `SELECT @@innodb_max_dirty_pages_pct`
|
||||
--let $innodb_max_dirty_pages_pct_lwm = `SELECT @@innodb_max_dirty_pages_pct_lwm`
|
||||
|
||||
SET GLOBAL innodb_max_dirty_pages_pct=99;
|
||||
SET GLOBAL innodb_max_dirty_pages_pct_lwm=99;
|
||||
|
||||
--connection node_1
|
||||
CREATE TABLE t1 (f1 INTEGER, f2 varchar(1024)) Engine=InnoDB;
|
||||
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
|
||||
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
|
||||
INSERT INTO t1 (f2) SELECT REPEAT('x', 1024) FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4;
|
||||
|
||||
--connection node_2
|
||||
--source suite/galera/include/galera_base_port.inc
|
||||
--let $NODE_GALERAPORT_2 = $_NODE_GALERAPORT
|
||||
|
||||
--echo Killing node #3 to free ports for garbd ...
|
||||
--connection node_3
|
||||
--source include/shutdown_mysqld.inc
|
||||
|
||||
--connection node_1
|
||||
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
|
||||
--source include/wait_condition.inc
|
||||
|
||||
# stop SST donor thread when node is in donor state
|
||||
SET GLOBAL debug_dbug = "+d,sync.wsrep_donor_state";
|
||||
|
||||
--echo Starting garbd ...
|
||||
--exec $MTR_GARBD_EXE --address "gcomm://127.0.0.1:$NODE_GALERAPORT_1" --group my_wsrep_cluster --donor node1 --sst backup --options 'base_port=$NODE_GALERAPORT_3' > $MYSQL_TMP_DIR/garbd.log 2>&1 &
|
||||
|
||||
SET SESSION debug_sync = "now WAIT_FOR sync.wsrep_donor_state_reached";
|
||||
|
||||
#
|
||||
# get hash of data directory contents before BP dirty page flushing
|
||||
#
|
||||
--exec find $datadir -type f ! -name tables_flushed ! -name backup_sst_complete -exec md5sum {} \; | md5sum >$MYSQLTEST_VARDIR/tmp/innodb_before
|
||||
|
||||
# this should force buffer pool flushing, if not already done by donor state change transfer
|
||||
SET GLOBAL innodb_max_dirty_pages_pct_lwm=0;
|
||||
SET GLOBAL innodb_max_dirty_pages_pct=0;
|
||||
|
||||
--disable_query_log
|
||||
--disable_result_log
|
||||
select f1 from t1;
|
||||
select * from ten;
|
||||
--enable_result_log
|
||||
--enable_query_log
|
||||
|
||||
#
|
||||
#
|
||||
# record the hash of data directory contents after BP dirty page flushing
|
||||
#
|
||||
--exec find $datadir -type f ! -name tables_flushed ! -name backup_sst_complete -exec md5sum {} \; | md5sum >$MYSQLTEST_VARDIR/tmp/innodb_after
|
||||
|
||||
# there should be no disk writes
|
||||
--diff_files $MYSQLTEST_VARDIR/tmp/innodb_before $MYSQLTEST_VARDIR/tmp/innodb_after
|
||||
|
||||
SET SESSION debug_sync = "now SIGNAL signal.wsrep_donor_state";
|
||||
SET GLOBAL debug_dbug = "";
|
||||
SET debug_sync='RESET';
|
||||
|
||||
--connection node_2
|
||||
|
||||
#
|
||||
# garbd will die automatically, because of the backup SST script
|
||||
# but just to be sure, sending explicit kill here, as well
|
||||
#
|
||||
--echo Killing garbd ...
|
||||
# FreeBSD's /bin/pkill only supports short versions of the options:
|
||||
# -o Select only the oldest (least recently started)
|
||||
# -f Match against full argument lists
|
||||
--error 0,1
|
||||
--exec pkill -o -f garbd.*$NODE_GALERAPORT_3
|
||||
|
||||
--connection node_1
|
||||
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
|
||||
--source include/wait_condition.inc
|
||||
|
||||
--connection node_2
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP TABLE ten;
|
||||
|
||||
--echo Restarting node #3 to satisfy MTR's end-of-test checks
|
||||
--connection node_3
|
||||
let $restart_noprint=2;
|
||||
--source include/start_mysqld.inc
|
||||
|
||||
--connection node_1
|
||||
--eval SET GLOBAL innodb_max_dirty_pages_pct = $innodb_max_dirty_pages_pct
|
||||
--eval SET GLOBAL innodb_max_dirty_pages_pct_lwm = $innodb_max_dirty_pages_pct_lwm
|
||||
|
||||
--source ../galera/include/auto_increment_offset_restore.inc
|
||||
|
||||
--connection node_1
|
||||
CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)");
|
||||
|
||||
--connection node_2
|
||||
CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)");
|
||||
|
||||
--connection node_3
|
||||
CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)");
|
|
@ -14,4 +14,5 @@ GCF-1018B : MDEV-18534 wsrep::transaction::adopt(): Assertion `transaction.is_st
|
|||
GCF-1060 : MDEV-20848 galera_sr.GCF_1060
|
||||
GCF-585 : MDEV-24698 galera_sr.GCF-585 MTR failed with SIGABRT: no such a transition REPLICATING -> APPLYING
|
||||
galera-features#56 : MDEV-24896
|
||||
GCF-1060 : MDEV-26528 wrong usage of mutex LOCK_thd_kill and LOCK_thd_kill
|
||||
galera_sr_shutdown_master : MDEV-23612: galera_sr.galera_sr_shutdown_master MTR failed: WSREP_SST: [ERROR] Possible timeout in receving first data from donor in gtid stage
|
||||
|
|
|
@ -1,23 +1,36 @@
|
|||
connection node_2;
|
||||
connection node_1;
|
||||
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
|
||||
connection node_1;
|
||||
connection node_2;
|
||||
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
|
||||
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
|
||||
connection node_2;
|
||||
SET SESSION wsrep_trx_fragment_size=1;
|
||||
START TRANSACTION;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
SET @@global.debug_dbug="+d,ha_index_init_fail";
|
||||
ROLLBACK;
|
||||
connection node_2;
|
||||
SELECT COUNT(*) `Expect 0` FROM mysql.wsrep_streaming_log;
|
||||
Expect 0
|
||||
0
|
||||
connection node_1;
|
||||
SET @@global.debug_dbug="";
|
||||
SELECT COUNT(*) `Expect 1` FROM mysql.wsrep_streaming_log;
|
||||
Expect 1
|
||||
1
|
||||
SET SESSION wsrep_on=OFF;
|
||||
DELETE FROM mysql.wsrep_streaming_log;
|
||||
SET SESSION wsrep_on=ON;
|
||||
SET @@global.debug_dbug="+d,ha_index_init_fail";
|
||||
ROLLBACK;
|
||||
connection node_1;
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
SELECT COUNT(*) `Expect 0` FROM mysql.wsrep_streaming_log;
|
||||
Expect 0
|
||||
0
|
||||
connection node_2;
|
||||
SET @@global.debug_dbug="";
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
SELECT COUNT(*) `Expect 1` FROM mysql.wsrep_streaming_log;
|
||||
Expect 1
|
||||
1
|
||||
connection node_2;
|
||||
SET GLOBAL wsrep_on=OFF;
|
||||
# restart
|
||||
SELECT COUNT(*) `Expect 0` FROM mysql.wsrep_streaming_log;
|
||||
Expect 0
|
||||
0
|
||||
DROP TABLE t1;
|
||||
CALL mtr.add_suppression("WSREP: Failed to init table for index scan");
|
||||
CALL mtr.add_suppression("WSREP: Failed to apply write set");
|
||||
CALL mtr.add_suppression("Failed to report last committed");
|
||||
|
|
|
@ -5,29 +5,76 @@
|
|||
--source include/galera_cluster.inc
|
||||
--source include/have_debug.inc
|
||||
|
||||
--let $node_1=node_1
|
||||
--let $node_2=node_2
|
||||
--source suite/galera/include/auto_increment_offset_save.inc
|
||||
|
||||
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
|
||||
|
||||
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
|
||||
|
||||
--connection node_1
|
||||
--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
|
||||
--connection node_2
|
||||
SET SESSION wsrep_trx_fragment_size=1;
|
||||
START TRANSACTION;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
# This will result in failure to remove fragments
|
||||
# from streaming log, in the following ROLLBACK.
|
||||
SELECT COUNT(*) `Expect 1` FROM mysql.wsrep_streaming_log;
|
||||
|
||||
#
|
||||
# Issue ROLLBACK and make sure it fails to clean up
|
||||
# the streaming log. Failure to remove fragments
|
||||
# results in apply failure of the rollback fragment.
|
||||
# The node should disconnect from the cluster.
|
||||
#
|
||||
SET @@global.debug_dbug="+d,ha_index_init_fail";
|
||||
ROLLBACK;
|
||||
|
||||
--connection node_2
|
||||
|
||||
#
|
||||
# Expect the cluster to shrink
|
||||
#
|
||||
--connection node_1
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
|
||||
--source include/wait_condition.inc
|
||||
|
||||
#
|
||||
# ROLLBACK should clean up the streaming log just fine in node 1
|
||||
#
|
||||
SELECT COUNT(*) `Expect 0` FROM mysql.wsrep_streaming_log;
|
||||
|
||||
|
||||
--connection node_1
|
||||
#
|
||||
# Expect the failure on ROLLBACK to leave a entry in streaming log
|
||||
#
|
||||
--connection node_2
|
||||
SET @@global.debug_dbug="";
|
||||
SET SESSION wsrep_sync_wait = 0;
|
||||
# Expect node to be disconnected
|
||||
--let wait_condition = SELECT VARIABLE_VALUE = 'Disconnected' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
|
||||
--source include/wait_condition.inc
|
||||
|
||||
SELECT COUNT(*) `Expect 1` FROM mysql.wsrep_streaming_log;
|
||||
|
||||
SET SESSION wsrep_on=OFF;
|
||||
DELETE FROM mysql.wsrep_streaming_log;
|
||||
SET SESSION wsrep_on=ON;
|
||||
|
||||
#
|
||||
# Restart node 2, so that it joins the cluster back
|
||||
#
|
||||
--connection node_2
|
||||
SET GLOBAL wsrep_on=OFF;
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
#
|
||||
# After restart, the streaming log is empty in node 2
|
||||
#
|
||||
SELECT COUNT(*) `Expect 0` FROM mysql.wsrep_streaming_log;
|
||||
|
||||
#
|
||||
# Cleanup
|
||||
#
|
||||
DROP TABLE t1;
|
||||
|
||||
CALL mtr.add_suppression("WSREP: Failed to init table for index scan");
|
||||
CALL mtr.add_suppression("WSREP: Failed to apply write set");
|
||||
CALL mtr.add_suppression("Failed to report last committed");
|
||||
|
||||
--source suite/galera/include/auto_increment_offset_restore.inc
|
||||
|
|
30
mysql-test/suite/rpl/r/mdev_24667.result
Normal file
30
mysql-test/suite/rpl/r/mdev_24667.result
Normal file
|
@ -0,0 +1,30 @@
|
|||
include/rpl_init.inc [topology=1->2->3]
|
||||
call mtr.add_suppression('Unsafe statement written to the binary log using ');
|
||||
connection server_1;
|
||||
set binlog_format=statement;
|
||||
#first bug
|
||||
create table t1 (a int);
|
||||
create temporary table tmp like t1;
|
||||
load data local infile 'MYSQLTEST_VARDIR/load_data' INTO TABLE tmp;
|
||||
insert into t1 select * from tmp;
|
||||
#second bug
|
||||
create table t2 (a int);
|
||||
create temporary table tmp2 like t2;
|
||||
insert into tmp2 values(10);
|
||||
update tmp2 set a = 20 limit 1;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted
|
||||
insert into t2 select * from tmp2;
|
||||
connection server_2;
|
||||
connection server_3;
|
||||
#t1 should have 2 rows
|
||||
select count(*) = 2 from t1;
|
||||
count(*) = 2
|
||||
1
|
||||
#t2 should have 1 rows with a = 20
|
||||
select * from t2;
|
||||
a
|
||||
20
|
||||
connection server_1;
|
||||
drop table t1, t2, tmp, tmp2;
|
||||
include/rpl_end.inc
|
8
mysql-test/suite/rpl/t/mdev_24667.cnf
Normal file
8
mysql-test/suite/rpl/t/mdev_24667.cnf
Normal file
|
@ -0,0 +1,8 @@
|
|||
!include ../my.cnf
|
||||
|
||||
[mysqld.3]
|
||||
log-slave-updates
|
||||
|
||||
[ENV]
|
||||
SERVER_MYPORT_3= @mysqld.3.port
|
||||
SERVER_MYSOCK_3= @mysqld.3.socket
|
56
mysql-test/suite/rpl/t/mdev_24667.test
Normal file
56
mysql-test/suite/rpl/t/mdev_24667.test
Normal file
|
@ -0,0 +1,56 @@
|
|||
#
|
||||
# MDEV-24667 LOAD DATA INFILE/inserted rows not written to binlog
|
||||
#
|
||||
# In this test we will have a replication configuration like 1->2->3
|
||||
# 1 will have statement format
|
||||
# 2 and 3 will have mixed format
|
||||
# We will make some updates on temporary table which are unsafe , So 2 must
|
||||
# Log these queries in row format, Since it is on tmp table , It wont be logged
|
||||
# So the next query which copies the data from tmp table to normal must be logged
|
||||
# into the row format. Instead of checking for the binlog We will compare the
|
||||
# results on the 3, If no binlog is lost(ie it is logged into row format), There
|
||||
# should not be any data loss.
|
||||
--let $rpl_topology=1->2->3
|
||||
--source include/rpl_init.inc
|
||||
--source include/have_binlog_format_mixed.inc
|
||||
call mtr.add_suppression('Unsafe statement written to the binary log using ');
|
||||
--connection server_1
|
||||
|
||||
set binlog_format=statement;
|
||||
--echo #first bug
|
||||
create table t1 (a int);
|
||||
create temporary table tmp like t1;
|
||||
--write_file $MYSQLTEST_VARDIR/load_data
|
||||
1
|
||||
2
|
||||
EOF
|
||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||
eval load data local infile '$MYSQLTEST_VARDIR/load_data' INTO TABLE tmp;
|
||||
insert into t1 select * from tmp;
|
||||
|
||||
--echo #second bug
|
||||
create table t2 (a int);
|
||||
#insert into t2 values(10);
|
||||
create temporary table tmp2 like t2;
|
||||
insert into tmp2 values(10);
|
||||
update tmp2 set a = 20 limit 1;
|
||||
insert into t2 select * from tmp2;
|
||||
--save_master_pos
|
||||
|
||||
--connection server_2
|
||||
--sync_with_master
|
||||
--save_master_pos
|
||||
|
||||
--connection server_3
|
||||
--sync_with_master
|
||||
--echo #t1 should have 2 rows
|
||||
select count(*) = 2 from t1;
|
||||
--echo #t2 should have 1 rows with a = 20
|
||||
select * from t2;
|
||||
|
||||
|
||||
# cleanup
|
||||
--connection server_1
|
||||
drop table t1, t2, tmp, tmp2;
|
||||
--remove_file $MYSQLTEST_VARDIR/load_data
|
||||
--source include/rpl_end.inc
|
|
@ -46,12 +46,15 @@ static BOOL win_rename_with_retries(const char *from, const char *to)
|
|||
|
||||
for (int retry= RENAME_MAX_RETRIES; retry--;)
|
||||
{
|
||||
DWORD ret = MoveFileEx(from, to,
|
||||
BOOL ret= MoveFileEx(from, to,
|
||||
MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
|
||||
|
||||
DBUG_ASSERT(fp == NULL || (ret == FALSE && GetLastError() == ERROR_SHARING_VIOLATION));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!ret && (GetLastError() == ERROR_SHARING_VIOLATION))
|
||||
DWORD last_error= GetLastError();
|
||||
if (last_error == ERROR_SHARING_VIOLATION ||
|
||||
last_error == ERROR_ACCESS_DENIED)
|
||||
{
|
||||
#ifndef DBUG_OFF
|
||||
/*
|
||||
|
|
|
@ -2352,6 +2352,9 @@ int get_db_mysql57(MYSQL_THD thd, char **name, size_t *len)
|
|||
#ifdef __x86_64__
|
||||
db_off= 608;
|
||||
db_len_off= 616;
|
||||
#elif __aarch64__
|
||||
db_off= 632;
|
||||
db_len_off= 640;
|
||||
#else
|
||||
db_off= 0;
|
||||
db_len_off= 0;
|
||||
|
@ -2362,6 +2365,9 @@ int get_db_mysql57(MYSQL_THD thd, char **name, size_t *len)
|
|||
#ifdef __x86_64__
|
||||
db_off= 536;
|
||||
db_len_off= 544;
|
||||
#elif __aarch64__
|
||||
db_off= 552;
|
||||
db_len_off= 560;
|
||||
#else
|
||||
db_off= 0;
|
||||
db_len_off= 0;
|
||||
|
|
|
@ -287,6 +287,7 @@ ELSE()
|
|||
wsrep_sst_mysqldump
|
||||
wsrep_sst_rsync
|
||||
wsrep_sst_mariabackup
|
||||
wsrep_sst_backup
|
||||
)
|
||||
# The following script is sourced from other SST scripts, so it should
|
||||
# not be made executable.
|
||||
|
|
|
@ -541,7 +541,7 @@ mysqld_install_cmd_line()
|
|||
{
|
||||
"$mysqld_bootstrap" $defaults $defaults_group_suffix "$mysqld_opt" --bootstrap $silent_startup\
|
||||
"--basedir=$basedir" "--datadir=$ldata" --log-warnings=0 --enforce-storage-engine="" \
|
||||
"--plugin-dir=${plugindir}" --loose-disable-plugin-file-key-management \
|
||||
"--plugin-dir=${plugindir}" \
|
||||
$args --max_allowed_packet=8M \
|
||||
--net_buffer_length=16K
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
-- Copyright (C) 2003, 2013 Oracle and/or its affiliates.
|
||||
-- Copyright (C) 2010, 2018 MariaDB Corporation
|
||||
-- Copyright (C) 2010, 2022, MariaDB Corporation
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
|
@ -744,6 +744,13 @@ ALTER TABLE help_topic MODIFY url TEXT NOT NULL;
|
|||
# MDEV-7383 - varbinary on mix/max of column_stats
|
||||
alter table column_stats modify min_value varbinary(255) DEFAULT NULL, modify max_value varbinary(255) DEFAULT NULL;
|
||||
|
||||
# MDEV-21873: 10.2 to 10.3 upgrade doesn't remove semi-sync reference from
|
||||
# mysql.plugin table.
|
||||
# As per suggested fix, check INFORMATION_SCHEMA.PLUGINS
|
||||
# and if semisync plugins aren't there, delete them from mysql.plugin.
|
||||
DELETE FROM mysql.plugin WHERE name="rpl_semi_sync_master" AND NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME="rpl_semi_sync_master");
|
||||
DELETE FROM mysql.plugin WHERE name="rpl_semi_sync_slave" AND NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME="rpl_semi_sync_slave");
|
||||
|
||||
--
|
||||
-- Ensure that all tables are of type Aria and transactional
|
||||
--
|
||||
|
|
112
scripts/wsrep_sst_backup.sh
Normal file
112
scripts/wsrep_sst_backup.sh
Normal file
|
@ -0,0 +1,112 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -ue
|
||||
|
||||
# Copyright (C) 2017-2021 MariaDB
|
||||
# Copyright (C) 2010-2014 Codership Oy
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
# 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 for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to the
|
||||
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston
|
||||
# MA 02110-1335 USA.
|
||||
|
||||
# This is a reference script for rsync-based state snapshot transfer
|
||||
|
||||
RSYNC_REAL_PID=0 # rsync process id
|
||||
STUNNEL_REAL_PID=0 # stunnel process id
|
||||
|
||||
OS="$(uname)"
|
||||
[ "$OS" = 'Darwin' ] && export -n LD_LIBRARY_PATH
|
||||
|
||||
# Setting the path for lsof on CentOS
|
||||
export PATH="/usr/sbin:/sbin:$PATH"
|
||||
|
||||
. $(dirname "$0")/wsrep_sst_common
|
||||
|
||||
MAGIC_FILE="$WSREP_SST_OPT_DATA/backup_sst_complete"
|
||||
rm -rf "$MAGIC_FILE"
|
||||
|
||||
WSREP_LOG_DIR=${WSREP_LOG_DIR:-""}
|
||||
# if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf
|
||||
if [ -z "$WSREP_LOG_DIR" ]; then
|
||||
WSREP_LOG_DIR=$(parse_cnf mysqld innodb-log-group-home-dir '')
|
||||
fi
|
||||
|
||||
if [ -n "$WSREP_LOG_DIR" ]; then
|
||||
# handle both relative and absolute paths
|
||||
WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; mkdir -p "$WSREP_LOG_DIR"; cd $WSREP_LOG_DIR; pwd -P)
|
||||
else
|
||||
# default to datadir
|
||||
WSREP_LOG_DIR=$(cd $WSREP_SST_OPT_DATA; pwd -P)
|
||||
fi
|
||||
|
||||
if [ "$WSREP_SST_OPT_ROLE" = 'donor' ]
|
||||
then
|
||||
|
||||
[ -f "$MAGIC_FILE" ] && rm -f "$MAGIC_FILE"
|
||||
|
||||
RC=0
|
||||
|
||||
if [ $WSREP_SST_OPT_BYPASS -eq 0 ]; then
|
||||
|
||||
FLUSHED="$WSREP_SST_OPT_DATA/tables_flushed"
|
||||
ERROR="$WSREP_SST_OPT_DATA/sst_error"
|
||||
|
||||
[ -f "$FLUSHED" ] && rm -f "$FLUSHED"
|
||||
[ -f "$ERROR" ] && rm -f "$ERROR"
|
||||
|
||||
echo "flush tables"
|
||||
|
||||
# Wait for :
|
||||
# (a) Tables to be flushed, AND
|
||||
# (b) Cluster state ID & wsrep_gtid_domain_id to be written to the file, OR
|
||||
# (c) ERROR file, in case flush tables operation failed.
|
||||
|
||||
while [ ! -r "$FLUSHED" ] && \
|
||||
! grep -q -F ':' '--' "$FLUSHED" >/dev/null 2>&1
|
||||
do
|
||||
# Check whether ERROR file exists.
|
||||
if [ -f "$ERROR" ]; then
|
||||
# Flush tables operation failed.
|
||||
rm -f "$ERROR"
|
||||
exit 255
|
||||
fi
|
||||
sleep 0.2
|
||||
done
|
||||
|
||||
STATE=$(cat "$FLUSHED")
|
||||
rm -f "$FLUSHED"
|
||||
|
||||
|
||||
else # BYPASS
|
||||
|
||||
wsrep_log_info "Bypassing state dump."
|
||||
fi
|
||||
|
||||
echo 'continue' # now server can resume updating data
|
||||
|
||||
echo "$STATE" > "$MAGIC_FILE"
|
||||
|
||||
echo "done $STATE"
|
||||
|
||||
elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]
|
||||
then
|
||||
wsrep_log_error "Unrecognized role: '$WSREP_SST_OPT_ROLE'"
|
||||
exit 22 # EINVAL
|
||||
|
||||
|
||||
else
|
||||
wsrep_log_error "Unrecognized role: '$WSREP_SST_OPT_ROLE'"
|
||||
exit 22 # EINVAL
|
||||
fi
|
||||
|
||||
exit 0
|
|
@ -42,6 +42,8 @@ struct show_table_contributors_st show_table_contributors[]= {
|
|||
{"Microsoft", "https://microsoft.com/", "Platinum Sponsor of the MariaDB Foundation"},
|
||||
{"MariaDB Corporation", "https://mariadb.com", "Founding member, Platinum Sponsor of the MariaDB Foundation"},
|
||||
{"ServiceNow", "https://servicenow.com", "Platinum Sponsor of the MariaDB Foundation"},
|
||||
{"Intel", "https://www.intel.com", "Platinum Sponsor of the MariaDB Foundation"},
|
||||
{"SIT", "https://sit.org", "Platinum Sponsor of the MariaDB Foundation"},
|
||||
{"Visma", "https://visma.com", "Gold Sponsor of the MariaDB Foundation"},
|
||||
{"DBS", "https://dbs.com", "Gold Sponsor of the MariaDB Foundation"},
|
||||
{"IBM", "https://www.ibm.com", "Gold Sponsor of the MariaDB Foundation"},
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define HANDLER_INCLUDED
|
||||
/*
|
||||
Copyright (c) 2000, 2019, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2021, MariaDB
|
||||
Copyright (c) 2009, 2022, MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
|
@ -5161,7 +5161,7 @@ static inline const char *ha_resolve_storage_engine_name(const handlerton *db_ty
|
|||
|
||||
static inline bool ha_check_storage_engine_flag(const handlerton *db_type, uint32 flag)
|
||||
{
|
||||
return db_type == NULL ? FALSE : MY_TEST(db_type->flags & flag);
|
||||
return db_type && (db_type->flags & flag);
|
||||
}
|
||||
|
||||
static inline bool ha_storage_engine_is_enabled(const handlerton *db_type)
|
||||
|
|
20
sql/item.cc
20
sql/item.cc
|
@ -2730,9 +2730,11 @@ Item_sp::func_name(THD *thd) const
|
|||
/* Calculate length to avoid reallocation of string for sure */
|
||||
size_t len= (((m_name->m_explicit_name ? m_name->m_db.length : 0) +
|
||||
m_name->m_name.length)*2 + //characters*quoting
|
||||
2 + // ` and `
|
||||
2 + // quotes for the function name
|
||||
2 + // quotes for the package name
|
||||
(m_name->m_explicit_name ?
|
||||
3 : 0) + // '`', '`' and '.' for the db
|
||||
1 + // '.' between package and function
|
||||
1 + // end of string
|
||||
ALIGN_SIZE(1)); // to avoid String reallocation
|
||||
String qname((char *)alloc_root(thd->mem_root, len), len,
|
||||
|
@ -2744,7 +2746,21 @@ Item_sp::func_name(THD *thd) const
|
|||
append_identifier(thd, &qname, &m_name->m_db);
|
||||
qname.append('.');
|
||||
}
|
||||
append_identifier(thd, &qname, &m_name->m_name);
|
||||
if (m_sp && m_sp->m_handler == &sp_handler_package_function)
|
||||
{
|
||||
/*
|
||||
In case of a package function split `pkg.func` and print
|
||||
quoted `pkg` and `func` separately, so the entire result looks like:
|
||||
`db`.`pkg`.`func`
|
||||
*/
|
||||
Database_qualified_name tmp= Database_qualified_name::split(m_name->m_name);
|
||||
DBUG_ASSERT(tmp.m_db.length);
|
||||
append_identifier(thd, &qname, &tmp.m_db);
|
||||
qname.append('.');
|
||||
append_identifier(thd, &qname, &tmp.m_name);
|
||||
}
|
||||
else
|
||||
append_identifier(thd, &qname, &m_name->m_name);
|
||||
return qname.c_ptr_safe();
|
||||
}
|
||||
|
||||
|
|
|
@ -4719,10 +4719,11 @@ void Item_func_in::mark_as_condition_AND_part(TABLE_LIST *embedding)
|
|||
Query_arena *arena, backup;
|
||||
arena= thd->activate_stmt_arena_if_needed(&backup);
|
||||
|
||||
if (to_be_transformed_into_in_subq(thd))
|
||||
if (!transform_into_subq_checked)
|
||||
{
|
||||
transform_into_subq= true;
|
||||
thd->lex->current_select->in_funcs.push_back(this, thd->mem_root);
|
||||
if ((transform_into_subq= to_be_transformed_into_in_subq(thd)))
|
||||
thd->lex->current_select->in_funcs.push_back(this, thd->mem_root);
|
||||
transform_into_subq_checked= true;
|
||||
}
|
||||
|
||||
if (arena)
|
||||
|
|
|
@ -2365,6 +2365,7 @@ protected:
|
|||
SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
|
||||
Field *field, Item *value);
|
||||
bool transform_into_subq;
|
||||
bool transform_into_subq_checked;
|
||||
public:
|
||||
/// An array of values, created when the bisection lookup method is used
|
||||
in_vector *array;
|
||||
|
@ -2387,6 +2388,7 @@ public:
|
|||
Item_func_opt_neg(thd, list),
|
||||
Predicant_to_list_comparator(thd, arg_count - 1),
|
||||
transform_into_subq(false),
|
||||
transform_into_subq_checked(false),
|
||||
array(0), have_null(0),
|
||||
arg_types_compatible(FALSE), emb_on_expr_nest(0)
|
||||
{ }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2000, 2018, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2021, MariaDB Corporation.
|
||||
Copyright (c) 2009, 2022, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -5838,6 +5838,8 @@ THD::binlog_start_trans_and_stmt()
|
|||
}
|
||||
Gtid_log_event gtid_event(this, seqno, domain_id, true,
|
||||
LOG_EVENT_SUPPRESS_USE_F, true, 0);
|
||||
// Replicated events in writeset doesn't have checksum
|
||||
gtid_event.checksum_alg= BINLOG_CHECKSUM_ALG_OFF;
|
||||
gtid_event.server_id= server_id;
|
||||
writer.write(>id_event);
|
||||
wsrep_write_cache_buf(&tmp_io_cache, &buf, &len);
|
||||
|
|
|
@ -1671,7 +1671,7 @@ end:
|
|||
{
|
||||
table->file->ha_index_or_rnd_end();
|
||||
ha_commit_trans(thd, FALSE);
|
||||
ha_commit_trans(thd, TRUE);
|
||||
trans_commit(thd);
|
||||
}
|
||||
if (table_opened)
|
||||
{
|
||||
|
|
|
@ -1229,6 +1229,7 @@ int Repl_semi_sync_master::flush_net(THD *thd,
|
|||
|
||||
net_clear(net, 0);
|
||||
net->pkt_nr++;
|
||||
net->compress_pkt_nr++;
|
||||
result = 0;
|
||||
rpl_semi_sync_master_net_wait_num++;
|
||||
|
||||
|
|
|
@ -3547,6 +3547,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
|
|||
lex_query_tables_own_last= m_lex->query_tables_own_last;
|
||||
prelocking_tables= *lex_query_tables_own_last;
|
||||
*lex_query_tables_own_last= NULL;
|
||||
m_lex->query_tables_last= m_lex->query_tables_own_last;
|
||||
m_lex->mark_as_requiring_prelocking(NULL);
|
||||
}
|
||||
thd->rollback_item_tree_changes();
|
||||
|
|
|
@ -703,6 +703,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
|
|||
wsrep_has_ignored_error(false),
|
||||
wsrep_ignore_table(false),
|
||||
wsrep_aborter(0),
|
||||
wsrep_delayed_BF_abort(false),
|
||||
|
||||
/* wsrep-lib */
|
||||
m_wsrep_next_trx_id(WSREP_UNDEFINED_TRX_ID),
|
||||
|
|
|
@ -4354,13 +4354,13 @@ public:
|
|||
*/
|
||||
DBUG_PRINT("debug",
|
||||
("temporary_tables: %s, in_sub_stmt: %s, system_thread: %s",
|
||||
YESNO(has_thd_temporary_tables()), YESNO(in_sub_stmt),
|
||||
YESNO(has_temporary_tables()), YESNO(in_sub_stmt),
|
||||
show_system_thread(system_thread)));
|
||||
if (in_sub_stmt == 0)
|
||||
{
|
||||
if (wsrep_binlog_format() == BINLOG_FORMAT_ROW)
|
||||
set_current_stmt_binlog_format_row();
|
||||
else if (!has_thd_temporary_tables())
|
||||
else if (!has_temporary_tables())
|
||||
set_current_stmt_binlog_format_stmt();
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
|
@ -5062,6 +5062,10 @@ public:
|
|||
/* thread who has started kill for this THD protected by LOCK_thd_data*/
|
||||
my_thread_id wsrep_aborter;
|
||||
|
||||
/* true if BF abort is observed in do_command() right after reading
|
||||
client's packet, and if the client has sent PS execute command. */
|
||||
bool wsrep_delayed_BF_abort;
|
||||
|
||||
/*
|
||||
Transaction id:
|
||||
* m_wsrep_next_trx_id is assigned on the first query after
|
||||
|
@ -5093,7 +5097,10 @@ public:
|
|||
{
|
||||
return m_wsrep_next_trx_id;
|
||||
}
|
||||
|
||||
/*
|
||||
If node is async slave and have parallel execution, wait for prior commits.
|
||||
*/
|
||||
bool wsrep_parallel_slave_wait_for_prior_commit();
|
||||
private:
|
||||
wsrep_trx_id_t m_wsrep_next_trx_id; /* cast from query_id_t */
|
||||
/* wsrep-lib */
|
||||
|
@ -7271,6 +7278,19 @@ public:
|
|||
}
|
||||
void copy(MEM_ROOT *mem_root, const LEX_CSTRING &db,
|
||||
const LEX_CSTRING &name);
|
||||
|
||||
static Database_qualified_name split(const LEX_CSTRING &txt)
|
||||
{
|
||||
DBUG_ASSERT(txt.str[txt.length] == '\0'); // Expect 0-terminated input
|
||||
const char *dot= strchr(txt.str, '.');
|
||||
if (!dot)
|
||||
return Database_qualified_name(NULL, 0, txt.str, txt.length);
|
||||
size_t dblen= dot - txt.str;
|
||||
Lex_cstring db(txt.str, dblen);
|
||||
Lex_cstring name(txt.str + dblen + 1, txt.length - dblen - 1);
|
||||
return Database_qualified_name(db, name);
|
||||
}
|
||||
|
||||
// Export db and name as a qualified name string: 'db.name'
|
||||
size_t make_qname(char *dst, size_t dstlen) const
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2000, 2019, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2021, MariaDB Corporation.
|
||||
Copyright (c) 2009, 2022, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -9164,6 +9164,43 @@ bool LEX::call_statement_start(THD *thd, const Lex_ident_sys_st *name1,
|
|||
}
|
||||
|
||||
|
||||
bool LEX::call_statement_start(THD *thd,
|
||||
const Lex_ident_sys_st *db,
|
||||
const Lex_ident_sys_st *pkg,
|
||||
const Lex_ident_sys_st *proc)
|
||||
{
|
||||
Database_qualified_name q_db_pkg(db, pkg);
|
||||
Database_qualified_name q_pkg_proc(pkg, proc);
|
||||
sp_name *spname;
|
||||
|
||||
sql_command= SQLCOM_CALL;
|
||||
|
||||
if (check_db_name(reinterpret_cast<LEX_STRING*>
|
||||
(const_cast<LEX_CSTRING*>
|
||||
(static_cast<const LEX_CSTRING*>(db)))))
|
||||
{
|
||||
my_error(ER_WRONG_DB_NAME, MYF(0), db->str);
|
||||
return NULL;
|
||||
}
|
||||
if (check_routine_name(pkg) ||
|
||||
check_routine_name(proc))
|
||||
return NULL;
|
||||
|
||||
// Concat `pkg` and `name` to `pkg.name`
|
||||
LEX_CSTRING pkg_dot_proc;
|
||||
if (q_pkg_proc.make_qname(thd->mem_root, &pkg_dot_proc) ||
|
||||
check_ident_length(&pkg_dot_proc) ||
|
||||
!(spname= new (thd->mem_root) sp_name(db, &pkg_dot_proc, true)))
|
||||
return NULL;
|
||||
|
||||
sp_handler_package_function.add_used_routine(thd->lex, thd, spname);
|
||||
sp_handler_package_body.add_used_routine(thd->lex, thd, &q_db_pkg);
|
||||
|
||||
return !(m_sql_cmd= new (thd->mem_root) Sql_cmd_call(spname,
|
||||
&sp_handler_package_procedure));
|
||||
}
|
||||
|
||||
|
||||
sp_package *LEX::get_sp_package() const
|
||||
{
|
||||
return sphead ? sphead->get_package() : NULL;
|
||||
|
@ -9418,6 +9455,56 @@ Item *LEX::make_item_func_call_generic(THD *thd, Lex_ident_cli_st *cdb,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Create a 3-step qualified function call.
|
||||
Currently it's possible for package routines only, e.g.:
|
||||
SELECT db.pkg.func();
|
||||
*/
|
||||
Item *LEX::make_item_func_call_generic(THD *thd,
|
||||
Lex_ident_cli_st *cdb,
|
||||
Lex_ident_cli_st *cpkg,
|
||||
Lex_ident_cli_st *cfunc,
|
||||
List<Item> *args)
|
||||
{
|
||||
static Lex_cstring dot(".", 1);
|
||||
Lex_ident_sys db(thd, cdb), pkg(thd, cpkg), func(thd, cfunc);
|
||||
Database_qualified_name q_db_pkg(db, pkg);
|
||||
Database_qualified_name q_pkg_func(pkg, func);
|
||||
sp_name *qname;
|
||||
|
||||
if (db.is_null() || pkg.is_null() || func.is_null())
|
||||
return NULL; // EOM
|
||||
|
||||
if (check_db_name((LEX_STRING*) static_cast<LEX_CSTRING*>(&db)))
|
||||
{
|
||||
my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
|
||||
return NULL;
|
||||
}
|
||||
if (check_routine_name(&pkg) ||
|
||||
check_routine_name(&func))
|
||||
return NULL;
|
||||
|
||||
// Concat `pkg` and `name` to `pkg.name`
|
||||
LEX_CSTRING pkg_dot_func;
|
||||
if (q_pkg_func.make_qname(thd->mem_root, &pkg_dot_func) ||
|
||||
check_ident_length(&pkg_dot_func) ||
|
||||
!(qname= new (thd->mem_root) sp_name(&db, &pkg_dot_func, true)))
|
||||
return NULL;
|
||||
|
||||
sp_handler_package_function.add_used_routine(thd->lex, thd, qname);
|
||||
sp_handler_package_body.add_used_routine(thd->lex, thd, &q_db_pkg);
|
||||
|
||||
thd->lex->safe_to_cache_query= 0;
|
||||
|
||||
if (args && args->elements > 0)
|
||||
return new (thd->mem_root) Item_func_sp(thd, thd->lex->current_context(),
|
||||
qname, &sp_handler_package_function,
|
||||
*args);
|
||||
return new (thd->mem_root) Item_func_sp(thd, thd->lex->current_context(),
|
||||
qname, &sp_handler_package_function);
|
||||
}
|
||||
|
||||
|
||||
Item *LEX::make_item_func_call_native_or_parse_error(THD *thd,
|
||||
Lex_ident_cli_st &name,
|
||||
List<Item> *args)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2000, 2019, Oracle and/or its affiliates.
|
||||
Copyright (c) 2010, 2021, MariaDB Corporation
|
||||
Copyright (c) 2010, 2022, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -3850,6 +3850,10 @@ public:
|
|||
bool call_statement_start(THD *thd, const Lex_ident_sys_st *name);
|
||||
bool call_statement_start(THD *thd, const Lex_ident_sys_st *name1,
|
||||
const Lex_ident_sys_st *name2);
|
||||
bool call_statement_start(THD *thd,
|
||||
const Lex_ident_sys_st *db,
|
||||
const Lex_ident_sys_st *pkg,
|
||||
const Lex_ident_sys_st *proc);
|
||||
sp_variable *find_variable(const LEX_CSTRING *name,
|
||||
sp_pcontext **ctx,
|
||||
const Sp_rcontext_handler **rh) const;
|
||||
|
@ -4093,6 +4097,11 @@ public:
|
|||
Item *make_item_func_substr(THD *thd, Item *a, Item *b);
|
||||
Item *make_item_func_call_generic(THD *thd, Lex_ident_cli_st *db,
|
||||
Lex_ident_cli_st *name, List<Item> *args);
|
||||
Item *make_item_func_call_generic(THD *thd,
|
||||
Lex_ident_cli_st *db,
|
||||
Lex_ident_cli_st *pkg,
|
||||
Lex_ident_cli_st *name,
|
||||
List<Item> *args);
|
||||
Item *make_item_func_call_native_or_parse_error(THD *thd,
|
||||
Lex_ident_cli_st &name,
|
||||
List<Item> *args);
|
||||
|
|
|
@ -1163,8 +1163,7 @@ static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables)
|
|||
|
||||
static bool wsrep_command_no_result(char command)
|
||||
{
|
||||
return (command == COM_STMT_PREPARE ||
|
||||
command == COM_STMT_FETCH ||
|
||||
return (command == COM_STMT_FETCH ||
|
||||
command == COM_STMT_SEND_LONG_DATA ||
|
||||
command == COM_STMT_CLOSE);
|
||||
}
|
||||
|
@ -1310,7 +1309,13 @@ bool do_command(THD *thd)
|
|||
DBUG_ASSERT(!thd->mdl_context.has_locks());
|
||||
DBUG_ASSERT(!thd->get_stmt_da()->is_set());
|
||||
/* We let COM_QUIT and COM_STMT_CLOSE to execute even if wsrep aborted. */
|
||||
if (command != COM_STMT_CLOSE &&
|
||||
if (command == COM_STMT_EXECUTE)
|
||||
{
|
||||
WSREP_DEBUG("PS BF aborted at do_command");
|
||||
thd->wsrep_delayed_BF_abort= true;
|
||||
}
|
||||
if (command != COM_STMT_CLOSE &&
|
||||
command != COM_STMT_EXECUTE &&
|
||||
command != COM_QUIT)
|
||||
{
|
||||
my_error(ER_LOCK_DEADLOCK, MYF(0));
|
||||
|
@ -1383,6 +1388,17 @@ out:
|
|||
if (unlikely(wsrep_service_started))
|
||||
wsrep_after_command_after_result(thd);
|
||||
}
|
||||
|
||||
if (thd->wsrep_delayed_BF_abort)
|
||||
{
|
||||
my_error(ER_LOCK_DEADLOCK, MYF(0));
|
||||
WSREP_DEBUG("Deadlock error for PS query: %s", thd->query());
|
||||
thd->reset_killed();
|
||||
thd->mysys_var->abort = 0;
|
||||
thd->wsrep_retry_counter = 0;
|
||||
|
||||
thd->wsrep_delayed_BF_abort= false;
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
DBUG_RETURN(return_value);
|
||||
}
|
||||
|
|
|
@ -2342,6 +2342,10 @@ static bool check_prepared_statement(Prepared_statement *stmt)
|
|||
goto error;
|
||||
}
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
if (wsrep_sync_wait(thd, sql_command))
|
||||
goto error;
|
||||
#endif
|
||||
switch (sql_command) {
|
||||
case SQLCOM_REPLACE:
|
||||
case SQLCOM_INSERT:
|
||||
|
@ -4487,7 +4491,13 @@ Prepared_statement::execute_loop(String *expanded_query,
|
|||
|
||||
if (set_parameters(expanded_query, packet, packet_end))
|
||||
return TRUE;
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
if (thd->wsrep_delayed_BF_abort)
|
||||
{
|
||||
WSREP_DEBUG("delayed BF abort, quitting execute_loop, stmt: %d", id);
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
reexecute:
|
||||
// Make sure that reprepare() did not create any new Items.
|
||||
DBUG_ASSERT(thd->free_list == NULL);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2021, MariaDB
|
||||
Copyright (c) 2009, 2022, MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -3296,6 +3296,16 @@ static my_bool processlist_callback(THD *tmp, processlist_callback_arg *arg)
|
|||
arg->table->field[11]->store((double) tmp->progress.counter /
|
||||
(double) max_counter*100.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
This is a DECIMAL column without DEFAULT.
|
||||
restore_record() fills its Field::ptr to zero bytes,
|
||||
according to pack_length(). But an array of zero bytes
|
||||
is not a valid decimal. Set it explicitly to 0.
|
||||
*/
|
||||
arg->table->field[11]->store((longlong) 0, true);
|
||||
}
|
||||
mysql_mutex_unlock(&tmp->LOCK_thd_data);
|
||||
}
|
||||
|
||||
|
|
|
@ -9957,7 +9957,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
|
|||
{
|
||||
bool engine_changed, error;
|
||||
bool no_ha_table= true; /* We have not created table in storage engine yet */
|
||||
TABLE *table, *new_table;
|
||||
TABLE *table, *new_table= nullptr;
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
bool partition_changed= false;
|
||||
bool fast_alter_partition= false;
|
||||
|
@ -9980,7 +9980,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
|
|||
bool varchar= create_info->varchar, table_creation_was_logged= 0;
|
||||
bool binlog_as_create_select= 0, log_if_exists= 0;
|
||||
uint tables_opened;
|
||||
handlerton *new_db_type, *old_db_type;
|
||||
handlerton *new_db_type= create_info->db_type, *old_db_type;
|
||||
ha_rows copied=0, deleted=0;
|
||||
LEX_CUSTRING frm= {0,0};
|
||||
char index_file[FN_REFLEN], data_file[FN_REFLEN];
|
||||
|
@ -10311,22 +10311,24 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
|
|||
create_info->used_fields |= HA_CREATE_USED_ROW_FORMAT;
|
||||
}
|
||||
|
||||
old_db_type= table->s->db_type();
|
||||
new_db_type= create_info->db_type;
|
||||
|
||||
DBUG_PRINT("info", ("old type: %s new type: %s",
|
||||
ha_resolve_storage_engine_name(table->s->db_type()),
|
||||
ha_resolve_storage_engine_name(create_info->db_type)));
|
||||
if (ha_check_storage_engine_flag(table->s->db_type(), HTON_ALTER_NOT_SUPPORTED))
|
||||
ha_resolve_storage_engine_name(old_db_type),
|
||||
ha_resolve_storage_engine_name(new_db_type)));
|
||||
if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED))
|
||||
{
|
||||
DBUG_PRINT("info", ("doesn't support alter"));
|
||||
my_error(ER_ILLEGAL_HA, MYF(0), hton_name(table->s->db_type())->str,
|
||||
my_error(ER_ILLEGAL_HA, MYF(0), hton_name(old_db_type)->str,
|
||||
alter_ctx.db.str, alter_ctx.table_name.str);
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
if (ha_check_storage_engine_flag(create_info->db_type,
|
||||
HTON_ALTER_NOT_SUPPORTED))
|
||||
if (ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
|
||||
{
|
||||
DBUG_PRINT("info", ("doesn't support alter"));
|
||||
my_error(ER_ILLEGAL_HA, MYF(0), hton_name(create_info->db_type)->str,
|
||||
my_error(ER_ILLEGAL_HA, MYF(0), hton_name(new_db_type)->str,
|
||||
alter_ctx.new_db.str, alter_ctx.new_name.str);
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
@ -10477,6 +10479,17 @@ do_continue:;
|
|||
DBUG_RETURN(true);
|
||||
}
|
||||
}
|
||||
/*
|
||||
If the old table had partitions and we are doing ALTER TABLE ...
|
||||
engine= <new_engine>, the new table must preserve the original
|
||||
partitioning. This means that the new engine is still the
|
||||
partitioning engine, not the engine specified in the parser.
|
||||
This is discovered in prep_alter_part_table, which in such case
|
||||
updates create_info->db_type.
|
||||
It's therefore important that the assignment below is done
|
||||
after prep_alter_part_table.
|
||||
*/
|
||||
new_db_type= create_info->db_type;
|
||||
#endif
|
||||
|
||||
if (mysql_prepare_alter_table(thd, table, create_info, alter_info,
|
||||
|
@ -10557,7 +10570,7 @@ do_continue:;
|
|||
Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
|
||||
|| is_inplace_alter_impossible(table, create_info, alter_info)
|
||||
|| IF_PARTITIONING((partition_changed &&
|
||||
!(table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)), 0))
|
||||
!(old_db_type->partition_flags() & HA_USE_AUTO_PARTITION)), 0))
|
||||
{
|
||||
if (alter_info->algorithm(thd) ==
|
||||
Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
|
||||
|
@ -10575,24 +10588,10 @@ do_continue:;
|
|||
request table rebuild. Set ALTER_RECREATE flag to force table
|
||||
rebuild.
|
||||
*/
|
||||
if (create_info->db_type == table->s->db_type() &&
|
||||
if (new_db_type == old_db_type &&
|
||||
create_info->used_fields & HA_CREATE_USED_ENGINE)
|
||||
alter_info->flags|= ALTER_RECREATE;
|
||||
|
||||
/*
|
||||
If the old table had partitions and we are doing ALTER TABLE ...
|
||||
engine= <new_engine>, the new table must preserve the original
|
||||
partitioning. This means that the new engine is still the
|
||||
partitioning engine, not the engine specified in the parser.
|
||||
This is discovered in prep_alter_part_table, which in such case
|
||||
updates create_info->db_type.
|
||||
It's therefore important that the assignment below is done
|
||||
after prep_alter_part_table.
|
||||
*/
|
||||
new_db_type= create_info->db_type;
|
||||
old_db_type= table->s->db_type();
|
||||
new_table= NULL;
|
||||
|
||||
/*
|
||||
Handling of symlinked tables:
|
||||
If no rename:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2017, 2020, MariaDB
|
||||
/* Copyright (c) 2017, 2022, MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -931,13 +931,11 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
|
|||
{
|
||||
if (!transform_into_subq)
|
||||
return this;
|
||||
|
||||
|
||||
Json_writer_object trace_wrapper(thd);
|
||||
Json_writer_object trace_conv(thd, "in_to_subquery_conversion");
|
||||
trace_conv.add("item", this);
|
||||
|
||||
transform_into_subq= false;
|
||||
|
||||
List<List_item> values;
|
||||
|
||||
LEX *lex= thd->lex;
|
||||
|
@ -1111,15 +1109,38 @@ uint32 Item_func_in::max_length_of_left_expr()
|
|||
|
||||
bool Item_func_in::to_be_transformed_into_in_subq(THD *thd)
|
||||
{
|
||||
bool is_row_list= args[1]->type() == Item::ROW_ITEM;
|
||||
uint values_count= arg_count-1;
|
||||
|
||||
if (args[1]->type() == Item::ROW_ITEM)
|
||||
if (is_row_list)
|
||||
values_count*= ((Item_row *)(args[1]))->cols();
|
||||
|
||||
if (thd->variables.in_subquery_conversion_threshold == 0 ||
|
||||
thd->variables.in_subquery_conversion_threshold > values_count)
|
||||
return false;
|
||||
|
||||
if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_PREPARE))
|
||||
return true;
|
||||
|
||||
/* Occurence of '?' in IN list is checked only for PREPARE <stmt> commands */
|
||||
for (uint i=1; i < arg_count; i++)
|
||||
{
|
||||
if (!is_row_list)
|
||||
{
|
||||
if (args[i]->type() == Item::PARAM_ITEM)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Item_row *row_list= (Item_row *)(args[i]);
|
||||
for (uint j=0; j < row_list->cols(); j++)
|
||||
{
|
||||
if (row_list->element_index(j)->type() == Item::PARAM_ITEM)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -2289,6 +2289,11 @@ multi_update::initialize_tables(JOIN *join)
|
|||
if (unlikely((thd->variables.option_bits & OPTION_SAFE_UPDATES) &&
|
||||
error_if_full_join(join)))
|
||||
DBUG_RETURN(1);
|
||||
if (join->implicit_grouping)
|
||||
{
|
||||
my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
main_table=join->join_tab->table;
|
||||
table_to_update= 0;
|
||||
|
||||
|
|
|
@ -96,7 +96,8 @@ static void make_unique_view_field_name(THD *thd, Item *target,
|
|||
itc.rewind();
|
||||
}
|
||||
|
||||
target->orig_name= target->name.str;
|
||||
if (!target->orig_name)
|
||||
target->orig_name= target->name.str;
|
||||
target->set_name(thd, buff, name_len, system_charset_info);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
|
||||
Copyright (c) 2010, 2021, MariaDB
|
||||
Copyright (c) 2010, 2022, MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -2940,9 +2940,29 @@ sp_suid:
|
|||
;
|
||||
|
||||
call:
|
||||
CALL_SYM sp_name
|
||||
CALL_SYM ident
|
||||
{
|
||||
if (unlikely(Lex->call_statement_start(thd, $2)))
|
||||
if (unlikely(Lex->call_statement_start(thd, &$2)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
opt_sp_cparam_list
|
||||
{
|
||||
if (Lex->check_cte_dependencies_and_resolve_references())
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| CALL_SYM ident '.' ident
|
||||
{
|
||||
if (unlikely(Lex->call_statement_start(thd, &$2, &$4)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
opt_sp_cparam_list
|
||||
{
|
||||
if (Lex->check_cte_dependencies_and_resolve_references())
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| CALL_SYM ident '.' ident '.' ident
|
||||
{
|
||||
if (unlikely(Lex->call_statement_start(thd, &$2, &$4, &$6)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
opt_sp_cparam_list
|
||||
|
@ -10699,6 +10719,11 @@ function_call_generic:
|
|||
if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, $5))))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| ident_cli '.' ident_cli '.' ident_cli '(' opt_expr_list ')'
|
||||
{
|
||||
if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, &$5, $7))))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
fulltext_options:
|
||||
|
@ -18241,6 +18266,10 @@ sp_statement:
|
|||
MYSQL_YYABORT;
|
||||
}
|
||||
opt_sp_cparam_list
|
||||
{
|
||||
if (Lex->check_cte_dependencies_and_resolve_references())
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| ident_cli_directly_assignable '.' ident
|
||||
{
|
||||
Lex_ident_sys tmp(thd, &$1);
|
||||
|
@ -18249,6 +18278,21 @@ sp_statement:
|
|||
MYSQL_YYABORT;
|
||||
}
|
||||
opt_sp_cparam_list
|
||||
{
|
||||
if (Lex->check_cte_dependencies_and_resolve_references())
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| ident_cli_directly_assignable '.' ident '.' ident
|
||||
{
|
||||
Lex_ident_sys tmp(thd, &$1);
|
||||
if (unlikely(Lex->call_statement_start(thd, &tmp, &$3, &$5)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
opt_sp_cparam_list
|
||||
{
|
||||
if (Lex->check_cte_dependencies_and_resolve_references())
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
sp_if_then_statements:
|
||||
|
|
22
sql/table.cc
22
sql/table.cc
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
|
||||
Copyright (c) 2008, 2021, MariaDB
|
||||
Copyright (c) 2008, 2022, MariaDB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -1741,6 +1741,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
|
|||
Field_data_type_info_array field_data_type_info_array;
|
||||
MEM_ROOT *old_root= thd->mem_root;
|
||||
Virtual_column_info **table_check_constraints;
|
||||
bool *interval_unescaped= NULL;
|
||||
extra2_fields extra2;
|
||||
DBUG_ENTER("TABLE_SHARE::init_from_binary_frm_image");
|
||||
|
||||
|
@ -2181,6 +2182,13 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
|
|||
|
||||
goto err;
|
||||
|
||||
if (interval_count)
|
||||
{
|
||||
if (!(interval_unescaped= (bool*) my_alloca(interval_count * sizeof(bool))))
|
||||
goto err;
|
||||
bzero(interval_unescaped, interval_count * sizeof(bool));
|
||||
}
|
||||
|
||||
field_ptr= share->field;
|
||||
table_check_constraints= share->check_constraints;
|
||||
read_length=(uint) (share->fields * field_pack_length +
|
||||
|
@ -2532,11 +2540,17 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
|
|||
if (share->mysql_version < 100200)
|
||||
attr.pack_flag&= ~FIELDFLAG_LONG_DECIMAL;
|
||||
|
||||
if (interval_nr && attr.charset->mbminlen > 1)
|
||||
if (interval_nr && attr.charset->mbminlen > 1 &&
|
||||
!interval_unescaped[interval_nr - 1])
|
||||
{
|
||||
/* Unescape UCS2 intervals from HEX notation */
|
||||
/*
|
||||
Unescape UCS2/UTF16/UTF32 intervals from HEX notation.
|
||||
Note, ENUM/SET columns with equal value list share a single
|
||||
copy of TYPELIB. Unescape every TYPELIB only once.
|
||||
*/
|
||||
TYPELIB *interval= share->intervals + interval_nr - 1;
|
||||
unhex_type2(interval);
|
||||
interval_unescaped[interval_nr - 1]= true;
|
||||
}
|
||||
|
||||
#ifndef TO_BE_DELETED_ON_PRODUCTION
|
||||
|
@ -3256,6 +3270,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
|
|||
share->error= OPEN_FRM_OK;
|
||||
thd->status_var.opened_shares++;
|
||||
thd->mem_root= old_root;
|
||||
my_afree(interval_unescaped);
|
||||
DBUG_RETURN(0);
|
||||
|
||||
err:
|
||||
|
@ -3283,6 +3298,7 @@ err:
|
|||
open_table_error(share, OPEN_FRM_CORRUPTED, share->open_errno);
|
||||
|
||||
thd->mem_root= old_root;
|
||||
my_afree(interval_unescaped);
|
||||
DBUG_RETURN(HA_ERR_NOT_A_TABLE);
|
||||
}
|
||||
|
||||
|
|
|
@ -953,7 +953,16 @@ static uint get_interval_id(uint *int_count,List<Create_field> &create_fields,
|
|||
|
||||
while ((field=it++) != last_field)
|
||||
{
|
||||
if (field->interval_id && field->interval->count == interval->count)
|
||||
/*
|
||||
ENUM/SET columns with equal value lists share a single
|
||||
copy of the underlying TYPELIB.
|
||||
Fields with different mbminlen can't reuse TYPELIBs, because:
|
||||
- mbminlen==1 are written to FRM as is
|
||||
- mbminlen>1 are written to FRM in hex-encoded format
|
||||
*/
|
||||
if (field->interval_id &&
|
||||
field->interval->count == interval->count &&
|
||||
field->charset->mbminlen == last_field->charset->mbminlen)
|
||||
{
|
||||
const char **a,**b;
|
||||
for (a=field->interval->type_names, b=interval->type_names ;
|
||||
|
|
|
@ -342,6 +342,7 @@ int Wsrep_client_service::bf_rollback()
|
|||
m_thd->global_read_lock.unlock_global_read_lock(m_thd);
|
||||
}
|
||||
m_thd->release_transactional_locks();
|
||||
mysql_ull_cleanup(m_thd);
|
||||
m_thd->mdl_context.release_explicit_locks();
|
||||
|
||||
DBUG_RETURN(ret);
|
||||
|
|
|
@ -380,6 +380,7 @@ int Wsrep_high_priority_service::rollback(const wsrep::ws_handle& ws_handle,
|
|||
}
|
||||
int ret= (trans_rollback_stmt(m_thd) || trans_rollback(m_thd));
|
||||
m_thd->release_transactional_locks();
|
||||
mysql_ull_cleanup(m_thd);
|
||||
m_thd->mdl_context.release_explicit_locks();
|
||||
|
||||
free_root(m_thd->mem_root, MYF(MY_KEEP_PREALLOC));
|
||||
|
|
|
@ -1276,6 +1276,73 @@ wsrep_sync_wait_upto (THD* thd,
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool wsrep_is_show_query(enum enum_sql_command command)
|
||||
{
|
||||
DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
|
||||
return (sql_command_flags[command] & CF_STATUS_COMMAND) != 0;
|
||||
}
|
||||
|
||||
static bool wsrep_is_diagnostic_query(enum enum_sql_command command)
|
||||
{
|
||||
assert(command >= 0 && command <= SQLCOM_END);
|
||||
return (sql_command_flags[command] & CF_DIAGNOSTIC_STMT) != 0;
|
||||
}
|
||||
|
||||
static enum enum_wsrep_sync_wait
|
||||
wsrep_sync_wait_mask_for_command(enum enum_sql_command command)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case SQLCOM_SELECT:
|
||||
case SQLCOM_CHECKSUM:
|
||||
return WSREP_SYNC_WAIT_BEFORE_READ;
|
||||
case SQLCOM_DELETE:
|
||||
case SQLCOM_DELETE_MULTI:
|
||||
case SQLCOM_UPDATE:
|
||||
case SQLCOM_UPDATE_MULTI:
|
||||
return WSREP_SYNC_WAIT_BEFORE_UPDATE_DELETE;
|
||||
case SQLCOM_REPLACE:
|
||||
case SQLCOM_INSERT:
|
||||
case SQLCOM_REPLACE_SELECT:
|
||||
case SQLCOM_INSERT_SELECT:
|
||||
return WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE;
|
||||
default:
|
||||
if (wsrep_is_diagnostic_query(command))
|
||||
{
|
||||
return WSREP_SYNC_WAIT_NONE;
|
||||
}
|
||||
if (wsrep_is_show_query(command))
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
case SQLCOM_SHOW_PROFILE:
|
||||
case SQLCOM_SHOW_PROFILES:
|
||||
case SQLCOM_SHOW_SLAVE_HOSTS:
|
||||
case SQLCOM_SHOW_RELAYLOG_EVENTS:
|
||||
case SQLCOM_SHOW_SLAVE_STAT:
|
||||
case SQLCOM_SHOW_BINLOG_STAT:
|
||||
case SQLCOM_SHOW_ENGINE_STATUS:
|
||||
case SQLCOM_SHOW_ENGINE_MUTEX:
|
||||
case SQLCOM_SHOW_ENGINE_LOGS:
|
||||
case SQLCOM_SHOW_PROCESSLIST:
|
||||
case SQLCOM_SHOW_PRIVILEGES:
|
||||
return WSREP_SYNC_WAIT_NONE;
|
||||
default:
|
||||
return WSREP_SYNC_WAIT_BEFORE_SHOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
return WSREP_SYNC_WAIT_NONE;
|
||||
}
|
||||
|
||||
bool wsrep_sync_wait(THD* thd, enum enum_sql_command command)
|
||||
{
|
||||
bool res = false;
|
||||
if (WSREP_CLIENT(thd) && thd->variables.wsrep_sync_wait)
|
||||
res = wsrep_sync_wait(thd, wsrep_sync_wait_mask_for_command(command));
|
||||
return res;
|
||||
}
|
||||
|
||||
void wsrep_keys_free(wsrep_key_arr_t* key_arr)
|
||||
{
|
||||
for (size_t i= 0; i < key_arr->keys_len; ++i)
|
||||
|
@ -2421,6 +2488,12 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
|
|||
if (!wsrep_thd_is_local(thd))
|
||||
return 0;
|
||||
|
||||
if (thd->wsrep_parallel_slave_wait_for_prior_commit())
|
||||
{
|
||||
WSREP_WARN("TOI: wait_for_prior_commit() returned error.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret= 0;
|
||||
mysql_mutex_lock(&thd->LOCK_thd_data);
|
||||
|
||||
|
@ -2949,11 +3022,6 @@ extern bool wsrep_thd_ignore_table(THD *thd)
|
|||
return thd->wsrep_ignore_table;
|
||||
}
|
||||
|
||||
bool wsrep_is_show_query(enum enum_sql_command command)
|
||||
{
|
||||
DBUG_ASSERT(command >= 0 && command <= SQLCOM_END);
|
||||
return (sql_command_flags[command] & CF_STATUS_COMMAND) != 0;
|
||||
}
|
||||
bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
|
||||
TABLE_LIST* src_table,
|
||||
HA_CREATE_INFO *create_info)
|
||||
|
@ -3224,6 +3292,15 @@ enum wsrep::streaming_context::fragment_unit wsrep_fragment_unit(ulong unit)
|
|||
}
|
||||
}
|
||||
|
||||
bool THD::wsrep_parallel_slave_wait_for_prior_commit()
|
||||
{
|
||||
if (rgi_slave && rgi_slave->is_parallel_exec && wait_for_prior_commit())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***** callbacks for wsrep service ************/
|
||||
|
||||
my_bool get_wsrep_recovery()
|
||||
|
|
|
@ -212,6 +212,7 @@ extern bool wsrep_start_replication(const char *wsrep_cluster_address);
|
|||
extern void wsrep_shutdown_replication();
|
||||
extern bool wsrep_must_sync_wait (THD* thd, uint mask= WSREP_SYNC_WAIT_BEFORE_READ);
|
||||
extern bool wsrep_sync_wait (THD* thd, uint mask= WSREP_SYNC_WAIT_BEFORE_READ);
|
||||
extern bool wsrep_sync_wait (THD* thd, enum enum_sql_command command);
|
||||
extern enum wsrep::provider::status
|
||||
wsrep_sync_wait_upto (THD* thd, wsrep_gtid_t* upto, int timeout);
|
||||
extern int wsrep_check_opts();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 2008-2020 Codership Oy <http://www.codership.com>
|
||||
/* Copyright 2008-2022 Codership Oy <http://www.codership.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include "debug_sync.h"
|
||||
|
||||
#include <my_service_manager.h>
|
||||
|
||||
|
@ -1508,6 +1509,33 @@ static int run_sql_command(THD *thd, const char *query)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void sst_disallow_writes (THD* thd, bool yes)
|
||||
{
|
||||
char query_str[64]= { 0, };
|
||||
ssize_t const query_max= sizeof(query_str) - 1;
|
||||
CHARSET_INFO *current_charset;
|
||||
|
||||
current_charset= thd->variables.character_set_client;
|
||||
|
||||
if (!is_supported_parser_charset(current_charset))
|
||||
{
|
||||
/* Do not use non-supported parser character sets */
|
||||
WSREP_WARN("Current client character set is non-supported parser character set: %s", current_charset->csname);
|
||||
thd->variables.character_set_client= &my_charset_latin1;
|
||||
WSREP_WARN("For SST temporally setting character set to : %s",
|
||||
my_charset_latin1.csname);
|
||||
}
|
||||
|
||||
snprintf (query_str, query_max, "SET GLOBAL innodb_disallow_writes=%d",
|
||||
yes ? 1 : 0);
|
||||
|
||||
if (run_sql_command(thd, query_str))
|
||||
{
|
||||
WSREP_ERROR("Failed to disallow InnoDB writes");
|
||||
}
|
||||
thd->variables.character_set_client= current_charset;
|
||||
}
|
||||
|
||||
|
||||
static int sst_flush_tables(THD* thd)
|
||||
{
|
||||
|
@ -1569,6 +1597,11 @@ static int sst_flush_tables(THD* thd)
|
|||
else
|
||||
{
|
||||
WSREP_INFO("Tables flushed.");
|
||||
|
||||
/* disable further disk IO */
|
||||
sst_disallow_writes(thd, true);
|
||||
WSREP_INFO("Disabled further disk IO.");
|
||||
|
||||
/*
|
||||
Tables have been flushed. Create a file with cluster state ID and
|
||||
wsrep_gtid_domain_id.
|
||||
|
@ -1578,6 +1611,9 @@ static int sst_flush_tables(THD* thd)
|
|||
(long long)wsrep_locked_seqno, wsrep_gtid_server.domain_id);
|
||||
err= sst_create_file(flush_success, content);
|
||||
|
||||
if (err)
|
||||
WSREP_INFO("Creating file for flush_success failed %d",err);
|
||||
|
||||
const char base_name[]= "tables_flushed";
|
||||
ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2;
|
||||
char *real_name= (char*) malloc(full_len);
|
||||
|
@ -1617,34 +1653,6 @@ static int sst_flush_tables(THD* thd)
|
|||
return err;
|
||||
}
|
||||
|
||||
|
||||
static void sst_disallow_writes (THD* thd, bool yes)
|
||||
{
|
||||
char query_str[64]= { 0, };
|
||||
ssize_t const query_max= sizeof(query_str) - 1;
|
||||
CHARSET_INFO *current_charset;
|
||||
|
||||
current_charset= thd->variables.character_set_client;
|
||||
|
||||
if (!is_supported_parser_charset(current_charset))
|
||||
{
|
||||
/* Do not use non-supported parser character sets */
|
||||
WSREP_WARN("Current client character set is non-supported parser character set: %s", current_charset->csname);
|
||||
thd->variables.character_set_client= &my_charset_latin1;
|
||||
WSREP_WARN("For SST temporally setting character set to : %s",
|
||||
my_charset_latin1.csname);
|
||||
}
|
||||
|
||||
snprintf (query_str, query_max, "SET GLOBAL innodb_disallow_writes=%d",
|
||||
yes ? 1 : 0);
|
||||
|
||||
if (run_sql_command(thd, query_str))
|
||||
{
|
||||
WSREP_ERROR("Failed to disallow InnoDB writes");
|
||||
}
|
||||
thd->variables.character_set_client= current_charset;
|
||||
}
|
||||
|
||||
static void* sst_donor_thread (void* a)
|
||||
{
|
||||
sst_thread_arg* arg= (sst_thread_arg*)a;
|
||||
|
@ -1692,8 +1700,7 @@ wait_signal:
|
|||
err= sst_flush_tables (thd.ptr);
|
||||
if (!err)
|
||||
{
|
||||
sst_disallow_writes (thd.ptr, true);
|
||||
/*
|
||||
/*
|
||||
Lets also keep statements that modify binary logs (like RESET LOGS,
|
||||
RESET MASTER) from proceeding until the files have been transferred
|
||||
to the joiner node.
|
||||
|
@ -1704,6 +1711,18 @@ wait_signal:
|
|||
}
|
||||
|
||||
locked= true;
|
||||
|
||||
WSREP_INFO("Donor state reached");
|
||||
|
||||
DBUG_EXECUTE_IF("sync.wsrep_donor_state",
|
||||
{
|
||||
const char act[]=
|
||||
"now "
|
||||
"SIGNAL sync.wsrep_donor_state_reached "
|
||||
"WAIT_FOR signal.wsrep_donor_state";
|
||||
assert(!debug_sync_set_action(thd.ptr,
|
||||
STRING_WITH_LEN(act)));
|
||||
};);
|
||||
goto wait_signal;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -768,9 +768,6 @@ buf_page_is_corrupted(
|
|||
|
||||
size_t checksum_field1 = 0;
|
||||
size_t checksum_field2 = 0;
|
||||
uint32_t crc32 = 0;
|
||||
bool crc32_inited = false;
|
||||
bool crc32_chksum = false;
|
||||
const ulint zip_size = fil_space_t::zip_size(fsp_flags);
|
||||
const uint16_t page_type = fil_page_get_type(read_buf);
|
||||
|
||||
|
@ -869,9 +866,14 @@ buf_page_is_corrupted(
|
|||
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
|
||||
return !buf_page_is_checksum_valid_none(
|
||||
read_buf, checksum_field1, checksum_field2);
|
||||
case SRV_CHECKSUM_ALGORITHM_NONE:
|
||||
/* should have returned false earlier */
|
||||
break;
|
||||
case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
|
||||
case SRV_CHECKSUM_ALGORITHM_CRC32:
|
||||
case SRV_CHECKSUM_ALGORITHM_INNODB:
|
||||
const uint32_t crc32 = buf_calc_page_crc32(read_buf);
|
||||
|
||||
if (buf_page_is_checksum_valid_none(read_buf,
|
||||
checksum_field1, checksum_field2)) {
|
||||
#ifdef UNIV_INNOCHECKSUM
|
||||
|
@ -887,16 +889,13 @@ buf_page_is_corrupted(
|
|||
" crc32 = " UINT32PF "; recorded = " ULINTPF ";\n",
|
||||
cur_page_num,
|
||||
buf_calc_page_new_checksum(read_buf),
|
||||
buf_calc_page_crc32(read_buf),
|
||||
crc32,
|
||||
checksum_field1);
|
||||
}
|
||||
#endif /* UNIV_INNOCHECKSUM */
|
||||
return false;
|
||||
}
|
||||
|
||||
crc32_chksum = curr_algo == SRV_CHECKSUM_ALGORITHM_CRC32
|
||||
|| curr_algo == SRV_CHECKSUM_ALGORITHM_FULL_CRC32;
|
||||
|
||||
/* Very old versions of InnoDB only stored 8 byte lsn to the
|
||||
start and the end of the page. */
|
||||
|
||||
|
@ -907,81 +906,33 @@ buf_page_is_corrupted(
|
|||
!= mach_read_from_4(read_buf + FIL_PAGE_LSN)
|
||||
&& checksum_field2 != BUF_NO_CHECKSUM_MAGIC) {
|
||||
|
||||
if (crc32_chksum) {
|
||||
crc32 = buf_calc_page_crc32(read_buf);
|
||||
crc32_inited = true;
|
||||
DBUG_EXECUTE_IF(
|
||||
"page_intermittent_checksum_mismatch", {
|
||||
static int page_counter;
|
||||
if (page_counter++ == 2) return true;
|
||||
});
|
||||
|
||||
DBUG_EXECUTE_IF(
|
||||
"page_intermittent_checksum_mismatch", {
|
||||
static int page_counter;
|
||||
if (page_counter++ == 2) {
|
||||
crc32++;
|
||||
}
|
||||
});
|
||||
|
||||
if (checksum_field2 != crc32
|
||||
&& checksum_field2
|
||||
!= buf_calc_page_old_checksum(read_buf)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
ut_ad(curr_algo
|
||||
== SRV_CHECKSUM_ALGORITHM_INNODB);
|
||||
|
||||
if (checksum_field2
|
||||
!= buf_calc_page_old_checksum(read_buf)) {
|
||||
crc32 = buf_calc_page_crc32(read_buf);
|
||||
crc32_inited = true;
|
||||
|
||||
if (checksum_field2 != crc32) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ((checksum_field1 != crc32
|
||||
|| checksum_field2 != crc32)
|
||||
&& checksum_field2
|
||||
!= buf_calc_page_old_checksum(read_buf)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (checksum_field1 == 0
|
||||
|| checksum_field1 == BUF_NO_CHECKSUM_MAGIC) {
|
||||
} else if (crc32_chksum) {
|
||||
|
||||
if (!crc32_inited) {
|
||||
crc32 = buf_calc_page_crc32(read_buf);
|
||||
crc32_inited = true;
|
||||
}
|
||||
|
||||
if (checksum_field1 != crc32
|
||||
switch (checksum_field1) {
|
||||
case 0:
|
||||
case BUF_NO_CHECKSUM_MAGIC:
|
||||
break;
|
||||
default:
|
||||
if ((checksum_field1 != crc32
|
||||
|| checksum_field2 != crc32)
|
||||
&& checksum_field1
|
||||
!= buf_calc_page_new_checksum(read_buf)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
ut_ad(curr_algo == SRV_CHECKSUM_ALGORITHM_INNODB);
|
||||
|
||||
if (checksum_field1
|
||||
!= buf_calc_page_new_checksum(read_buf)) {
|
||||
|
||||
if (!crc32_inited) {
|
||||
crc32 = buf_calc_page_crc32(read_buf);
|
||||
crc32_inited = true;
|
||||
}
|
||||
|
||||
if (checksum_field1 != crc32) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (crc32_inited
|
||||
&& ((checksum_field1 == crc32
|
||||
&& checksum_field2 != crc32)
|
||||
|| (checksum_field1 != crc32
|
||||
&& checksum_field2 == crc32))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case SRV_CHECKSUM_ALGORITHM_NONE:
|
||||
/* should have returned false earlier */
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1967,10 +1967,11 @@ fil_make_filepath(
|
|||
if (path != NULL) {
|
||||
memcpy(full_name, path, path_len);
|
||||
len = path_len;
|
||||
full_name[len] = '\0';
|
||||
os_normalize_path(full_name);
|
||||
}
|
||||
|
||||
full_name[len] = '\0';
|
||||
os_normalize_path(full_name);
|
||||
|
||||
if (trim_name) {
|
||||
/* Find the offset of the last DIR separator and set it to
|
||||
null in order to strip off the old basename from this path. */
|
||||
|
|
|
@ -2260,9 +2260,7 @@ fts_trx_table_create(
|
|||
fts_trx_table_t* ftt;
|
||||
|
||||
ftt = static_cast<fts_trx_table_t*>(
|
||||
mem_heap_alloc(fts_trx->heap, sizeof(*ftt)));
|
||||
|
||||
memset(ftt, 0x0, sizeof(*ftt));
|
||||
mem_heap_zalloc(fts_trx->heap, sizeof *ftt));
|
||||
|
||||
ftt->table = table;
|
||||
ftt->fts_trx = fts_trx;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* Copyright (c) 2008, 2021, Oracle and/or its affiliates.
|
||||
Copyright (c) 2022, MariaDB Corporation.
|
||||
|
||||
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,
|
||||
|
@ -24,6 +25,9 @@
|
|||
#include <my_sys.h>
|
||||
#include <pfs_global.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_MEMALIGN
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
bool pfs_initialized= false;
|
||||
size_t pfs_allocated_memory_size= 0;
|
||||
|
@ -45,7 +49,17 @@ void *pfs_malloc(PFS_builtin_memory_class *klass, size_t size, myf)
|
|||
if (--stub_alloc_fails_after_count <= 0)
|
||||
return NULL;
|
||||
|
||||
#ifndef PFS_ALIGNEMENT
|
||||
void *ptr= malloc(size);
|
||||
#elif defined HAVE_MEMALIGN
|
||||
void *ptr= memalign(PFS_ALIGNEMENT, size);
|
||||
#elif defined HAVE_ALIGNED_MALLOC
|
||||
void *ptr= _aligned_malloc(size, PFS_ALIGNEMENT);
|
||||
#else
|
||||
void *ptr;
|
||||
if (posix_memalign(&ptr, PFS_ALIGNEMENT, size))
|
||||
ptr= NULL;
|
||||
#endif
|
||||
if (ptr != NULL)
|
||||
memset(ptr, 0, size);
|
||||
return ptr;
|
||||
|
|
|
@ -1128,13 +1128,21 @@ int decimal2ulonglong(const decimal_t *from, ulonglong *to)
|
|||
|
||||
for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
|
||||
{
|
||||
ulonglong y=x;
|
||||
x=x*DIG_BASE + *buf++;
|
||||
if (unlikely(y > ((ulonglong) ULONGLONG_MAX/DIG_BASE) || x < y))
|
||||
/*
|
||||
Check that the decimal is bigger than any possible integer.
|
||||
Do it before we do the x*=DIB_BASE to avoid integer
|
||||
overflow.
|
||||
*/
|
||||
if (unlikely (
|
||||
x >= ULONGLONG_MAX/DIG_BASE &&
|
||||
(x > ULONGLONG_MAX/DIG_BASE ||
|
||||
*buf > (dec1) (ULONGLONG_MAX%DIG_BASE))))
|
||||
{
|
||||
*to=ULONGLONG_MAX;
|
||||
return E_DEC_OVERFLOW;
|
||||
}
|
||||
|
||||
x=x*DIG_BASE + *buf++;
|
||||
}
|
||||
*to=x;
|
||||
for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
|
||||
|
@ -1151,23 +1159,29 @@ int decimal2longlong(const decimal_t *from, longlong *to)
|
|||
|
||||
for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
|
||||
{
|
||||
longlong y=x;
|
||||
/*
|
||||
Check that the decimal is less than any possible integer.
|
||||
Do it before we do the x*=DIB_BASE to avoid integer
|
||||
overflow.
|
||||
Attention: trick!
|
||||
we're calculating -|from| instead of |from| here
|
||||
because |LONGLONG_MIN| > LONGLONG_MAX
|
||||
so we can convert -9223372036854775808 correctly
|
||||
so we can convert -9223372036854775808 correctly.
|
||||
*/
|
||||
x=x*DIG_BASE - *buf++;
|
||||
if (unlikely(y < (LONGLONG_MIN/DIG_BASE) || x > y))
|
||||
if (unlikely (
|
||||
x <= LONGLONG_MIN/DIG_BASE &&
|
||||
(x < LONGLONG_MIN/DIG_BASE ||
|
||||
*buf > (dec1) (-(LONGLONG_MIN%DIG_BASE)))))
|
||||
{
|
||||
/*
|
||||
the decimal is bigger than any possible integer
|
||||
return border integer depending on the sign
|
||||
the decimal is bigger than any possible integer
|
||||
return border integer depending on the sign
|
||||
*/
|
||||
*to= from->sign ? LONGLONG_MIN : LONGLONG_MAX;
|
||||
return E_DEC_OVERFLOW;
|
||||
}
|
||||
|
||||
x=x*DIG_BASE - *buf++;
|
||||
}
|
||||
/* boundary case: 9223372036854775808 */
|
||||
if (unlikely(from->sign==0 && x == LONGLONG_MIN))
|
||||
|
|
Loading…
Reference in a new issue