Merge 10.4 into 10.5
This commit is contained in:
commit
d62b0368ca
2
CREDITS
2
CREDITS
@ -4,9 +4,11 @@ organization registered in the USA.
|
|||||||
The current main sponsors of the MariaDB Foundation are:
|
The current main sponsors of the MariaDB Foundation are:
|
||||||
|
|
||||||
Alibaba Cloud https://www.alibabacloud.com/ (2017)
|
Alibaba Cloud https://www.alibabacloud.com/ (2017)
|
||||||
|
Intel https://www.intel.com (2022)
|
||||||
MariaDB Corporation https://www.mariadb.com (2013)
|
MariaDB Corporation https://www.mariadb.com (2013)
|
||||||
Microsoft https://microsoft.com/ (2017)
|
Microsoft https://microsoft.com/ (2017)
|
||||||
ServiceNow https://servicenow.com (2019)
|
ServiceNow https://servicenow.com (2019)
|
||||||
|
SIT https://sit.org (2022)
|
||||||
Tencent Cloud https://cloud.tencent.com (2017)
|
Tencent Cloud https://cloud.tencent.com (2017)
|
||||||
Development Bank of Singapore https://dbs.com (2016)
|
Development Bank of Singapore https://dbs.com (2016)
|
||||||
IBM https://www.ibm.com (2017)
|
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);
|
error("Could not write into log file '%s'", out_file_name);
|
||||||
DBUG_RETURN(ERROR_STOP);
|
DBUG_RETURN(ERROR_STOP);
|
||||||
}
|
}
|
||||||
|
fflush(result_file);
|
||||||
|
|
||||||
DBUG_RETURN(OK_CONTINUE);
|
DBUG_RETURN(OK_CONTINUE);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
|
/* 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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -320,6 +320,7 @@ struct st_connection
|
|||||||
char *name;
|
char *name;
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
MYSQL_STMT* stmt;
|
MYSQL_STMT* stmt;
|
||||||
|
MYSQL_BIND *ps_params;
|
||||||
/* Set after send to disallow other queries before reap */
|
/* Set after send to disallow other queries before reap */
|
||||||
my_bool pending;
|
my_bool pending;
|
||||||
|
|
||||||
@ -394,6 +395,10 @@ enum enum_commands {
|
|||||||
Q_ENABLE_PREPARE_WARNINGS, Q_DISABLE_PREPARE_WARNINGS,
|
Q_ENABLE_PREPARE_WARNINGS, Q_DISABLE_PREPARE_WARNINGS,
|
||||||
Q_RESET_CONNECTION,
|
Q_RESET_CONNECTION,
|
||||||
Q_OPTIMIZER_TRACE,
|
Q_OPTIMIZER_TRACE,
|
||||||
|
Q_PS_PREPARE,
|
||||||
|
Q_PS_BIND,
|
||||||
|
Q_PS_EXECUTE,
|
||||||
|
Q_PS_CLOSE,
|
||||||
Q_UNKNOWN, /* Unknown command. */
|
Q_UNKNOWN, /* Unknown command. */
|
||||||
Q_COMMENT, /* Comments, ignored. */
|
Q_COMMENT, /* Comments, ignored. */
|
||||||
Q_COMMENT_WITH_COMMAND,
|
Q_COMMENT_WITH_COMMAND,
|
||||||
@ -507,6 +512,10 @@ const char *command_names[]=
|
|||||||
"disable_prepare_warnings",
|
"disable_prepare_warnings",
|
||||||
"reset_connection",
|
"reset_connection",
|
||||||
"optimizer_trace",
|
"optimizer_trace",
|
||||||
|
"PS_prepare",
|
||||||
|
"PS_bind",
|
||||||
|
"PS_execute",
|
||||||
|
"PS_close",
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -7900,6 +7909,15 @@ static void handle_no_active_connection(struct st_command *command,
|
|||||||
var_set_errno(2006);
|
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
|
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;
|
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)
|
if (flags & QUERY_SEND_FLAG)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -8486,6 +8530,411 @@ end:
|
|||||||
DBUG_VOID_RETURN;
|
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 */
|
/* fall through */
|
||||||
case Q_QUERY:
|
case Q_QUERY:
|
||||||
case Q_REAP:
|
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;
|
my_bool old_display_result_vertically= display_result_vertically;
|
||||||
/* Default is full query, both reap and send */
|
/* 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")
|
${GIT_EXECUTABLE} config cmake.update-submodules yes")
|
||||||
ELSEIF(git_config_get_result EQUAL 128)
|
ELSEIF(git_config_get_result EQUAL 128)
|
||||||
SET(update_result 0)
|
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()
|
ELSE()
|
||||||
MESSAGE(STATUS "Updating submodules")
|
SET(UPDATE_SUBMODULES_COMMAND
|
||||||
EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update --init --recursive --depth=1
|
"${GIT_EXECUTABLE}" submodule update --init --recursive)
|
||||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
# Old Git may not work with "--depth 1".
|
||||||
RESULT_VARIABLE update_result)
|
# 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()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define MY_ATOMIC_INCLUDED
|
#define MY_ATOMIC_INCLUDED
|
||||||
|
|
||||||
/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
/* 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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -115,22 +115,6 @@
|
|||||||
#include "atomic/gcc_builtins.h"
|
#include "atomic/gcc_builtins.h"
|
||||||
#endif
|
#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
|
#ifndef MY_MEMORY_ORDER_SEQ_CST
|
||||||
#define MY_MEMORY_ORDER_RELAXED
|
#define MY_MEMORY_ORDER_RELAXED
|
||||||
#define MY_MEMORY_ORDER_CONSUME
|
#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
|
Microsoft https://microsoft.com/ Platinum Sponsor of the MariaDB Foundation
|
||||||
MariaDB Corporation https://mariadb.com Founding member, 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
|
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
|
Visma https://visma.com Gold Sponsor of the MariaDB Foundation
|
||||||
DBS https://dbs.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
|
IBM https://www.ibm.com Gold Sponsor of the MariaDB Foundation
|
||||||
|
@ -2913,5 +2913,30 @@ t1 CREATE TABLE `t1` (
|
|||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
SET NAMES utf8;
|
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
|
# End of 10.2 tests
|
||||||
#
|
#
|
||||||
|
@ -1067,6 +1067,25 @@ DROP TABLE t1;
|
|||||||
SET NAMES utf8;
|
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 #
|
||||||
--echo # End of 10.2 tests
|
--echo # End of 10.2 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@ -207,4 +207,19 @@ ERROR 23000: Duplicate entry '0000-00-00 00:00:00' for key 'f2k'
|
|||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
DROP TABLE t3,t4;
|
DROP TABLE t3,t4;
|
||||||
SET @@sql_mode=@save_sql_mode;
|
SET @@sql_mode=@save_sql_mode;
|
||||||
|
#
|
||||||
# End of 10.2 tests
|
# 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;
|
DROP TABLE t3,t4;
|
||||||
SET @@sql_mode=@save_sql_mode;
|
SET @@sql_mode=@save_sql_mode;
|
||||||
|
|
||||||
|
--echo #
|
||||||
--echo # End of 10.2 tests
|
--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
|
4 4
|
||||||
drop table t1;
|
drop table t1;
|
||||||
SET @@in_predicate_conversion_threshold= default;
|
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;
|
drop table t1;
|
||||||
SET @@in_predicate_conversion_threshold= default;
|
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
|
# 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 #
|
||||||
--echo # End of 10.1 tests
|
--echo # End of 10.1 tests
|
||||||
--echo #
|
--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
|
c
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
DROP TABLE t1;
|
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();
|
CALL p1();
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
DROP TABLE t1;
|
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 View v1;
|
||||||
Drop table t1;
|
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
|
# End of 10.3 tests
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -6565,6 +6565,32 @@ SELECT v.id, v.foo AS bar FROM v1 v
|
|||||||
Drop View v1;
|
Drop View v1;
|
||||||
Drop table t1;
|
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 #
|
||||||
--echo # End of 10.3 tests
|
--echo # End of 10.3 tests
|
||||||
--echo #
|
--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);
|
CALL xyz.xyz123(17,18,@R);
|
||||||
DROP PACKAGE xyz;
|
DROP PACKAGE xyz;
|
||||||
DROP TABLE t1;
|
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);
|
CALL xyz.xyz123(17,18,@R);
|
||||||
DROP PACKAGE xyz;
|
DROP PACKAGE xyz;
|
||||||
DROP TABLE t1;
|
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
|
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
|
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_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)
|
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
|
# 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;
|
connection node_1;
|
||||||
UPDATE t1 SET f2 = 'd' WHERE f1 > 3;
|
UPDATE t1 SET f2 = 'd' WHERE f1 > 3;
|
||||||
connection node_2;
|
connection node_2;
|
||||||
|
Killing server ...
|
||||||
connection node_1;
|
connection node_1;
|
||||||
UPDATE t1 SET f2 = 'e' WHERE f1 > 4;
|
UPDATE t1 SET f2 = 'e' WHERE f1 > 4;
|
||||||
connection node_2;
|
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
|
# masks all deadlock errors
|
||||||
#
|
#
|
||||||
|
|
||||||
|
--source include/no_protocol.inc
|
||||||
--source include/galera_cluster.inc
|
--source include/galera_cluster.inc
|
||||||
--source suite/galera/t/MW-328-header.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;
|
ALTER TABLE t1 ADD COLUMN f2 INTEGER;
|
||||||
SET SESSION wsrep_osu_method=TOI;
|
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
|
--let $wait_condition_on_error_output = SELECT * FROM mysql.general_log
|
||||||
--source include/wait_condition_with_debug.inc
|
--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
|
# Kill node #2 while IST is in progress
|
||||||
--connection node_2
|
--connection node_2
|
||||||
|
--source include/kill_galera.inc
|
||||||
# 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
|
|
||||||
|
|
||||||
--connection node_1
|
--connection node_1
|
||||||
--source include/wait_until_connected_again.inc
|
--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-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
|
GCF-585 : MDEV-24698 galera_sr.GCF-585 MTR failed with SIGABRT: no such a transition REPLICATING -> APPLYING
|
||||||
galera-features#56 : MDEV-24896
|
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
|
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_2;
|
||||||
connection node_1;
|
connection node_1;
|
||||||
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
|
|
||||||
connection node_1;
|
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;
|
SET SESSION wsrep_trx_fragment_size=1;
|
||||||
START TRANSACTION;
|
START TRANSACTION;
|
||||||
INSERT INTO t1 VALUES (1);
|
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;
|
SELECT COUNT(*) `Expect 1` FROM mysql.wsrep_streaming_log;
|
||||||
Expect 1
|
Expect 1
|
||||||
1
|
1
|
||||||
SET SESSION wsrep_on=OFF;
|
SET @@global.debug_dbug="+d,ha_index_init_fail";
|
||||||
DELETE FROM mysql.wsrep_streaming_log;
|
ROLLBACK;
|
||||||
SET SESSION wsrep_on=ON;
|
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;
|
DROP TABLE t1;
|
||||||
CALL mtr.add_suppression("WSREP: Failed to init table for index scan");
|
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/galera_cluster.inc
|
||||||
--source include/have_debug.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);
|
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
|
||||||
|
|
||||||
--connection node_1
|
--connection node_2
|
||||||
--let $wsrep_cluster_address_orig = `SELECT @@wsrep_cluster_address`
|
|
||||||
SET SESSION wsrep_trx_fragment_size=1;
|
SET SESSION wsrep_trx_fragment_size=1;
|
||||||
START TRANSACTION;
|
START TRANSACTION;
|
||||||
INSERT INTO t1 VALUES (1);
|
INSERT INTO t1 VALUES (1);
|
||||||
# This will result in failure to remove fragments
|
SELECT COUNT(*) `Expect 1` FROM mysql.wsrep_streaming_log;
|
||||||
# from streaming log, in the following ROLLBACK.
|
|
||||||
|
#
|
||||||
|
# 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";
|
SET @@global.debug_dbug="+d,ha_index_init_fail";
|
||||||
ROLLBACK;
|
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;
|
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 @@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;
|
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;
|
DROP TABLE t1;
|
||||||
|
|
||||||
CALL mtr.add_suppression("WSREP: Failed to init table for index scan");
|
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--;)
|
for (int retry= RENAME_MAX_RETRIES; retry--;)
|
||||||
{
|
{
|
||||||
DWORD ret = MoveFileEx(from, to,
|
BOOL ret= MoveFileEx(from, to,
|
||||||
MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
|
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
|
#ifndef DBUG_OFF
|
||||||
/*
|
/*
|
||||||
|
@ -2352,6 +2352,9 @@ int get_db_mysql57(MYSQL_THD thd, char **name, size_t *len)
|
|||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
db_off= 608;
|
db_off= 608;
|
||||||
db_len_off= 616;
|
db_len_off= 616;
|
||||||
|
#elif __aarch64__
|
||||||
|
db_off= 632;
|
||||||
|
db_len_off= 640;
|
||||||
#else
|
#else
|
||||||
db_off= 0;
|
db_off= 0;
|
||||||
db_len_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__
|
#ifdef __x86_64__
|
||||||
db_off= 536;
|
db_off= 536;
|
||||||
db_len_off= 544;
|
db_len_off= 544;
|
||||||
|
#elif __aarch64__
|
||||||
|
db_off= 552;
|
||||||
|
db_len_off= 560;
|
||||||
#else
|
#else
|
||||||
db_off= 0;
|
db_off= 0;
|
||||||
db_len_off= 0;
|
db_len_off= 0;
|
||||||
|
@ -287,6 +287,7 @@ ELSE()
|
|||||||
wsrep_sst_mysqldump
|
wsrep_sst_mysqldump
|
||||||
wsrep_sst_rsync
|
wsrep_sst_rsync
|
||||||
wsrep_sst_mariabackup
|
wsrep_sst_mariabackup
|
||||||
|
wsrep_sst_backup
|
||||||
)
|
)
|
||||||
# The following script is sourced from other SST scripts, so it should
|
# The following script is sourced from other SST scripts, so it should
|
||||||
# not be made executable.
|
# not be made executable.
|
||||||
|
@ -541,7 +541,7 @@ mysqld_install_cmd_line()
|
|||||||
{
|
{
|
||||||
"$mysqld_bootstrap" $defaults $defaults_group_suffix "$mysqld_opt" --bootstrap $silent_startup\
|
"$mysqld_bootstrap" $defaults $defaults_group_suffix "$mysqld_opt" --bootstrap $silent_startup\
|
||||||
"--basedir=$basedir" "--datadir=$ldata" --log-warnings=0 --enforce-storage-engine="" \
|
"--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 \
|
$args --max_allowed_packet=8M \
|
||||||
--net_buffer_length=16K
|
--net_buffer_length=16K
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
-- Copyright (C) 2003, 2013 Oracle and/or its affiliates.
|
-- 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
|
-- 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
|
-- 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
|
# 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;
|
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
|
-- 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"},
|
{"Microsoft", "https://microsoft.com/", "Platinum Sponsor of the MariaDB Foundation"},
|
||||||
{"MariaDB Corporation", "https://mariadb.com", "Founding member, 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"},
|
{"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"},
|
{"Visma", "https://visma.com", "Gold Sponsor of the MariaDB Foundation"},
|
||||||
{"DBS", "https://dbs.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"},
|
{"IBM", "https://www.ibm.com", "Gold Sponsor of the MariaDB Foundation"},
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#define HANDLER_INCLUDED
|
#define HANDLER_INCLUDED
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2000, 2019, Oracle and/or its affiliates.
|
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
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License
|
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)
|
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)
|
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 */
|
/* Calculate length to avoid reallocation of string for sure */
|
||||||
size_t len= (((m_name->m_explicit_name ? m_name->m_db.length : 0) +
|
size_t len= (((m_name->m_explicit_name ? m_name->m_db.length : 0) +
|
||||||
m_name->m_name.length)*2 + //characters*quoting
|
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 ?
|
(m_name->m_explicit_name ?
|
||||||
3 : 0) + // '`', '`' and '.' for the db
|
3 : 0) + // '`', '`' and '.' for the db
|
||||||
|
1 + // '.' between package and function
|
||||||
1 + // end of string
|
1 + // end of string
|
||||||
ALIGN_SIZE(1)); // to avoid String reallocation
|
ALIGN_SIZE(1)); // to avoid String reallocation
|
||||||
String qname((char *)alloc_root(thd->mem_root, len), len,
|
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);
|
append_identifier(thd, &qname, &m_name->m_db);
|
||||||
qname.append('.');
|
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();
|
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;
|
Query_arena *arena, backup;
|
||||||
arena= thd->activate_stmt_arena_if_needed(&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;
|
if ((transform_into_subq= to_be_transformed_into_in_subq(thd)))
|
||||||
thd->lex->current_select->in_funcs.push_back(this, thd->mem_root);
|
thd->lex->current_select->in_funcs.push_back(this, thd->mem_root);
|
||||||
|
transform_into_subq_checked= true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arena)
|
if (arena)
|
||||||
|
@ -2365,6 +2365,7 @@ protected:
|
|||||||
SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
|
SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
|
||||||
Field *field, Item *value);
|
Field *field, Item *value);
|
||||||
bool transform_into_subq;
|
bool transform_into_subq;
|
||||||
|
bool transform_into_subq_checked;
|
||||||
public:
|
public:
|
||||||
/// An array of values, created when the bisection lookup method is used
|
/// An array of values, created when the bisection lookup method is used
|
||||||
in_vector *array;
|
in_vector *array;
|
||||||
@ -2387,6 +2388,7 @@ public:
|
|||||||
Item_func_opt_neg(thd, list),
|
Item_func_opt_neg(thd, list),
|
||||||
Predicant_to_list_comparator(thd, arg_count - 1),
|
Predicant_to_list_comparator(thd, arg_count - 1),
|
||||||
transform_into_subq(false),
|
transform_into_subq(false),
|
||||||
|
transform_into_subq_checked(false),
|
||||||
array(0), have_null(0),
|
array(0), have_null(0),
|
||||||
arg_types_compatible(FALSE), emb_on_expr_nest(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) 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
|
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
|
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,
|
Gtid_log_event gtid_event(this, seqno, domain_id, true,
|
||||||
LOG_EVENT_SUPPRESS_USE_F, true, 0);
|
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;
|
gtid_event.server_id= server_id;
|
||||||
writer.write(>id_event);
|
writer.write(>id_event);
|
||||||
wsrep_write_cache_buf(&tmp_io_cache, &buf, &len);
|
wsrep_write_cache_buf(&tmp_io_cache, &buf, &len);
|
||||||
|
@ -1671,7 +1671,7 @@ end:
|
|||||||
{
|
{
|
||||||
table->file->ha_index_or_rnd_end();
|
table->file->ha_index_or_rnd_end();
|
||||||
ha_commit_trans(thd, FALSE);
|
ha_commit_trans(thd, FALSE);
|
||||||
ha_commit_trans(thd, TRUE);
|
trans_commit(thd);
|
||||||
}
|
}
|
||||||
if (table_opened)
|
if (table_opened)
|
||||||
{
|
{
|
||||||
|
@ -1229,6 +1229,7 @@ int Repl_semi_sync_master::flush_net(THD *thd,
|
|||||||
|
|
||||||
net_clear(net, 0);
|
net_clear(net, 0);
|
||||||
net->pkt_nr++;
|
net->pkt_nr++;
|
||||||
|
net->compress_pkt_nr++;
|
||||||
result = 0;
|
result = 0;
|
||||||
rpl_semi_sync_master_net_wait_num++;
|
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;
|
lex_query_tables_own_last= m_lex->query_tables_own_last;
|
||||||
prelocking_tables= *lex_query_tables_own_last;
|
prelocking_tables= *lex_query_tables_own_last;
|
||||||
*lex_query_tables_own_last= NULL;
|
*lex_query_tables_own_last= NULL;
|
||||||
|
m_lex->query_tables_last= m_lex->query_tables_own_last;
|
||||||
m_lex->mark_as_requiring_prelocking(NULL);
|
m_lex->mark_as_requiring_prelocking(NULL);
|
||||||
}
|
}
|
||||||
thd->rollback_item_tree_changes();
|
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_has_ignored_error(false),
|
||||||
wsrep_ignore_table(false),
|
wsrep_ignore_table(false),
|
||||||
wsrep_aborter(0),
|
wsrep_aborter(0),
|
||||||
|
wsrep_delayed_BF_abort(false),
|
||||||
|
|
||||||
/* wsrep-lib */
|
/* wsrep-lib */
|
||||||
m_wsrep_next_trx_id(WSREP_UNDEFINED_TRX_ID),
|
m_wsrep_next_trx_id(WSREP_UNDEFINED_TRX_ID),
|
||||||
|
@ -4354,13 +4354,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
DBUG_PRINT("debug",
|
DBUG_PRINT("debug",
|
||||||
("temporary_tables: %s, in_sub_stmt: %s, system_thread: %s",
|
("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)));
|
show_system_thread(system_thread)));
|
||||||
if (in_sub_stmt == 0)
|
if (in_sub_stmt == 0)
|
||||||
{
|
{
|
||||||
if (wsrep_binlog_format() == BINLOG_FORMAT_ROW)
|
if (wsrep_binlog_format() == BINLOG_FORMAT_ROW)
|
||||||
set_current_stmt_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();
|
set_current_stmt_binlog_format_stmt();
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -5062,6 +5062,10 @@ public:
|
|||||||
/* thread who has started kill for this THD protected by LOCK_thd_data*/
|
/* thread who has started kill for this THD protected by LOCK_thd_data*/
|
||||||
my_thread_id wsrep_aborter;
|
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:
|
Transaction id:
|
||||||
* m_wsrep_next_trx_id is assigned on the first query after
|
* m_wsrep_next_trx_id is assigned on the first query after
|
||||||
@ -5093,7 +5097,10 @@ public:
|
|||||||
{
|
{
|
||||||
return m_wsrep_next_trx_id;
|
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:
|
private:
|
||||||
wsrep_trx_id_t m_wsrep_next_trx_id; /* cast from query_id_t */
|
wsrep_trx_id_t m_wsrep_next_trx_id; /* cast from query_id_t */
|
||||||
/* wsrep-lib */
|
/* wsrep-lib */
|
||||||
@ -7271,6 +7278,19 @@ public:
|
|||||||
}
|
}
|
||||||
void copy(MEM_ROOT *mem_root, const LEX_CSTRING &db,
|
void copy(MEM_ROOT *mem_root, const LEX_CSTRING &db,
|
||||||
const LEX_CSTRING &name);
|
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'
|
// Export db and name as a qualified name string: 'db.name'
|
||||||
size_t make_qname(char *dst, size_t dstlen) const
|
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) 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
|
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
|
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
|
sp_package *LEX::get_sp_package() const
|
||||||
{
|
{
|
||||||
return sphead ? sphead->get_package() : NULL;
|
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,
|
Item *LEX::make_item_func_call_native_or_parse_error(THD *thd,
|
||||||
Lex_ident_cli_st &name,
|
Lex_ident_cli_st &name,
|
||||||
List<Item> *args)
|
List<Item> *args)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Copyright (c) 2000, 2019, Oracle and/or its affiliates.
|
/* 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
|
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
|
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 *name);
|
||||||
bool call_statement_start(THD *thd, const Lex_ident_sys_st *name1,
|
bool call_statement_start(THD *thd, const Lex_ident_sys_st *name1,
|
||||||
const Lex_ident_sys_st *name2);
|
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_variable *find_variable(const LEX_CSTRING *name,
|
||||||
sp_pcontext **ctx,
|
sp_pcontext **ctx,
|
||||||
const Sp_rcontext_handler **rh) const;
|
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_substr(THD *thd, Item *a, Item *b);
|
||||||
Item *make_item_func_call_generic(THD *thd, Lex_ident_cli_st *db,
|
Item *make_item_func_call_generic(THD *thd, Lex_ident_cli_st *db,
|
||||||
Lex_ident_cli_st *name, List<Item> *args);
|
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,
|
Item *make_item_func_call_native_or_parse_error(THD *thd,
|
||||||
Lex_ident_cli_st &name,
|
Lex_ident_cli_st &name,
|
||||||
List<Item> *args);
|
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)
|
static bool wsrep_command_no_result(char command)
|
||||||
{
|
{
|
||||||
return (command == COM_STMT_PREPARE ||
|
return (command == COM_STMT_FETCH ||
|
||||||
command == COM_STMT_FETCH ||
|
|
||||||
command == COM_STMT_SEND_LONG_DATA ||
|
command == COM_STMT_SEND_LONG_DATA ||
|
||||||
command == COM_STMT_CLOSE);
|
command == COM_STMT_CLOSE);
|
||||||
}
|
}
|
||||||
@ -1310,7 +1309,13 @@ bool do_command(THD *thd)
|
|||||||
DBUG_ASSERT(!thd->mdl_context.has_locks());
|
DBUG_ASSERT(!thd->mdl_context.has_locks());
|
||||||
DBUG_ASSERT(!thd->get_stmt_da()->is_set());
|
DBUG_ASSERT(!thd->get_stmt_da()->is_set());
|
||||||
/* We let COM_QUIT and COM_STMT_CLOSE to execute even if wsrep aborted. */
|
/* 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)
|
command != COM_QUIT)
|
||||||
{
|
{
|
||||||
my_error(ER_LOCK_DEADLOCK, MYF(0));
|
my_error(ER_LOCK_DEADLOCK, MYF(0));
|
||||||
@ -1383,6 +1388,17 @@ out:
|
|||||||
if (unlikely(wsrep_service_started))
|
if (unlikely(wsrep_service_started))
|
||||||
wsrep_after_command_after_result(thd);
|
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 */
|
#endif /* WITH_WSREP */
|
||||||
DBUG_RETURN(return_value);
|
DBUG_RETURN(return_value);
|
||||||
}
|
}
|
||||||
|
@ -2342,6 +2342,10 @@ static bool check_prepared_statement(Prepared_statement *stmt)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
if (wsrep_sync_wait(thd, sql_command))
|
||||||
|
goto error;
|
||||||
|
#endif
|
||||||
switch (sql_command) {
|
switch (sql_command) {
|
||||||
case SQLCOM_REPLACE:
|
case SQLCOM_REPLACE:
|
||||||
case SQLCOM_INSERT:
|
case SQLCOM_INSERT:
|
||||||
@ -4487,7 +4491,13 @@ Prepared_statement::execute_loop(String *expanded_query,
|
|||||||
|
|
||||||
if (set_parameters(expanded_query, packet, packet_end))
|
if (set_parameters(expanded_query, packet, packet_end))
|
||||||
return TRUE;
|
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:
|
reexecute:
|
||||||
// Make sure that reprepare() did not create any new Items.
|
// Make sure that reprepare() did not create any new Items.
|
||||||
DBUG_ASSERT(thd->free_list == NULL);
|
DBUG_ASSERT(thd->free_list == NULL);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
|
/* 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
|
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
|
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 /
|
arg->table->field[11]->store((double) tmp->progress.counter /
|
||||||
(double) max_counter*100.0);
|
(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);
|
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 engine_changed, error;
|
||||||
bool no_ha_table= true; /* We have not created table in storage engine yet */
|
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
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||||
bool partition_changed= false;
|
bool partition_changed= false;
|
||||||
bool fast_alter_partition= 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 varchar= create_info->varchar, table_creation_was_logged= 0;
|
||||||
bool binlog_as_create_select= 0, log_if_exists= 0;
|
bool binlog_as_create_select= 0, log_if_exists= 0;
|
||||||
uint tables_opened;
|
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;
|
ha_rows copied=0, deleted=0;
|
||||||
LEX_CUSTRING frm= {0,0};
|
LEX_CUSTRING frm= {0,0};
|
||||||
char index_file[FN_REFLEN], data_file[FN_REFLEN];
|
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;
|
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",
|
DBUG_PRINT("info", ("old type: %s new type: %s",
|
||||||
ha_resolve_storage_engine_name(table->s->db_type()),
|
ha_resolve_storage_engine_name(old_db_type),
|
||||||
ha_resolve_storage_engine_name(create_info->db_type)));
|
ha_resolve_storage_engine_name(new_db_type)));
|
||||||
if (ha_check_storage_engine_flag(table->s->db_type(), HTON_ALTER_NOT_SUPPORTED))
|
if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("doesn't support alter"));
|
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);
|
alter_ctx.db.str, alter_ctx.table_name.str);
|
||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ha_check_storage_engine_flag(create_info->db_type,
|
if (ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
|
||||||
HTON_ALTER_NOT_SUPPORTED))
|
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("doesn't support alter"));
|
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);
|
alter_ctx.new_db.str, alter_ctx.new_name.str);
|
||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
}
|
}
|
||||||
@ -10477,6 +10479,17 @@ do_continue:;
|
|||||||
DBUG_RETURN(true);
|
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
|
#endif
|
||||||
|
|
||||||
if (mysql_prepare_alter_table(thd, table, create_info, alter_info,
|
if (mysql_prepare_alter_table(thd, table, create_info, alter_info,
|
||||||
@ -10557,7 +10570,7 @@ do_continue:;
|
|||||||
Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
|
Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
|
||||||
|| is_inplace_alter_impossible(table, create_info, alter_info)
|
|| is_inplace_alter_impossible(table, create_info, alter_info)
|
||||||
|| IF_PARTITIONING((partition_changed &&
|
|| 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) ==
|
if (alter_info->algorithm(thd) ==
|
||||||
Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
|
Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
|
||||||
@ -10575,24 +10588,10 @@ do_continue:;
|
|||||||
request table rebuild. Set ALTER_RECREATE flag to force table
|
request table rebuild. Set ALTER_RECREATE flag to force table
|
||||||
rebuild.
|
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)
|
create_info->used_fields & HA_CREATE_USED_ENGINE)
|
||||||
alter_info->flags|= ALTER_RECREATE;
|
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:
|
Handling of symlinked tables:
|
||||||
If no rename:
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -936,8 +936,6 @@ Item *Item_func_in::in_predicate_to_in_subs_transformer(THD *thd,
|
|||||||
Json_writer_object trace_conv(thd, "in_to_subquery_conversion");
|
Json_writer_object trace_conv(thd, "in_to_subquery_conversion");
|
||||||
trace_conv.add("item", this);
|
trace_conv.add("item", this);
|
||||||
|
|
||||||
transform_into_subq= false;
|
|
||||||
|
|
||||||
List<List_item> values;
|
List<List_item> values;
|
||||||
|
|
||||||
LEX *lex= thd->lex;
|
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 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;
|
uint values_count= arg_count-1;
|
||||||
|
|
||||||
if (args[1]->type() == Item::ROW_ITEM)
|
if (is_row_list)
|
||||||
values_count*= ((Item_row *)(args[1]))->cols();
|
values_count*= ((Item_row *)(args[1]))->cols();
|
||||||
|
|
||||||
if (thd->variables.in_subquery_conversion_threshold == 0 ||
|
if (thd->variables.in_subquery_conversion_threshold == 0 ||
|
||||||
thd->variables.in_subquery_conversion_threshold > values_count)
|
thd->variables.in_subquery_conversion_threshold > values_count)
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2289,6 +2289,11 @@ multi_update::initialize_tables(JOIN *join)
|
|||||||
if (unlikely((thd->variables.option_bits & OPTION_SAFE_UPDATES) &&
|
if (unlikely((thd->variables.option_bits & OPTION_SAFE_UPDATES) &&
|
||||||
error_if_full_join(join)))
|
error_if_full_join(join)))
|
||||||
DBUG_RETURN(1);
|
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;
|
main_table=join->join_tab->table;
|
||||||
table_to_update= 0;
|
table_to_update= 0;
|
||||||
|
|
||||||
|
@ -96,7 +96,8 @@ static void make_unique_view_field_name(THD *thd, Item *target,
|
|||||||
itc.rewind();
|
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);
|
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) 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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -2940,9 +2940,29 @@ sp_suid:
|
|||||||
;
|
;
|
||||||
|
|
||||||
call:
|
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;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
opt_sp_cparam_list
|
opt_sp_cparam_list
|
||||||
@ -10699,6 +10719,11 @@ function_call_generic:
|
|||||||
if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, $5))))
|
if (unlikely(!($$= Lex->make_item_func_call_generic(thd, &$1, &$3, $5))))
|
||||||
MYSQL_YYABORT;
|
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:
|
fulltext_options:
|
||||||
@ -18241,6 +18266,10 @@ sp_statement:
|
|||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
opt_sp_cparam_list
|
opt_sp_cparam_list
|
||||||
|
{
|
||||||
|
if (Lex->check_cte_dependencies_and_resolve_references())
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
| ident_cli_directly_assignable '.' ident
|
| ident_cli_directly_assignable '.' ident
|
||||||
{
|
{
|
||||||
Lex_ident_sys tmp(thd, &$1);
|
Lex_ident_sys tmp(thd, &$1);
|
||||||
@ -18249,6 +18278,21 @@ sp_statement:
|
|||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
opt_sp_cparam_list
|
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:
|
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) 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
|
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
|
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;
|
Field_data_type_info_array field_data_type_info_array;
|
||||||
MEM_ROOT *old_root= thd->mem_root;
|
MEM_ROOT *old_root= thd->mem_root;
|
||||||
Virtual_column_info **table_check_constraints;
|
Virtual_column_info **table_check_constraints;
|
||||||
|
bool *interval_unescaped= NULL;
|
||||||
extra2_fields extra2;
|
extra2_fields extra2;
|
||||||
DBUG_ENTER("TABLE_SHARE::init_from_binary_frm_image");
|
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;
|
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;
|
field_ptr= share->field;
|
||||||
table_check_constraints= share->check_constraints;
|
table_check_constraints= share->check_constraints;
|
||||||
read_length=(uint) (share->fields * field_pack_length +
|
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)
|
if (share->mysql_version < 100200)
|
||||||
attr.pack_flag&= ~FIELDFLAG_LONG_DECIMAL;
|
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;
|
TYPELIB *interval= share->intervals + interval_nr - 1;
|
||||||
unhex_type2(interval);
|
unhex_type2(interval);
|
||||||
|
interval_unescaped[interval_nr - 1]= true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TO_BE_DELETED_ON_PRODUCTION
|
#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;
|
share->error= OPEN_FRM_OK;
|
||||||
thd->status_var.opened_shares++;
|
thd->status_var.opened_shares++;
|
||||||
thd->mem_root= old_root;
|
thd->mem_root= old_root;
|
||||||
|
my_afree(interval_unescaped);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@ -3283,6 +3298,7 @@ err:
|
|||||||
open_table_error(share, OPEN_FRM_CORRUPTED, share->open_errno);
|
open_table_error(share, OPEN_FRM_CORRUPTED, share->open_errno);
|
||||||
|
|
||||||
thd->mem_root= old_root;
|
thd->mem_root= old_root;
|
||||||
|
my_afree(interval_unescaped);
|
||||||
DBUG_RETURN(HA_ERR_NOT_A_TABLE);
|
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)
|
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;
|
const char **a,**b;
|
||||||
for (a=field->interval->type_names, b=interval->type_names ;
|
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->global_read_lock.unlock_global_read_lock(m_thd);
|
||||||
}
|
}
|
||||||
m_thd->release_transactional_locks();
|
m_thd->release_transactional_locks();
|
||||||
|
mysql_ull_cleanup(m_thd);
|
||||||
m_thd->mdl_context.release_explicit_locks();
|
m_thd->mdl_context.release_explicit_locks();
|
||||||
|
|
||||||
DBUG_RETURN(ret);
|
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));
|
int ret= (trans_rollback_stmt(m_thd) || trans_rollback(m_thd));
|
||||||
m_thd->release_transactional_locks();
|
m_thd->release_transactional_locks();
|
||||||
|
mysql_ull_cleanup(m_thd);
|
||||||
m_thd->mdl_context.release_explicit_locks();
|
m_thd->mdl_context.release_explicit_locks();
|
||||||
|
|
||||||
free_root(m_thd->mem_root, MYF(MY_KEEP_PREALLOC));
|
free_root(m_thd->mem_root, MYF(MY_KEEP_PREALLOC));
|
||||||
|
@ -1276,6 +1276,73 @@ wsrep_sync_wait_upto (THD* thd,
|
|||||||
return ret;
|
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)
|
void wsrep_keys_free(wsrep_key_arr_t* key_arr)
|
||||||
{
|
{
|
||||||
for (size_t i= 0; i < key_arr->keys_len; ++i)
|
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))
|
if (!wsrep_thd_is_local(thd))
|
||||||
return 0;
|
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;
|
int ret= 0;
|
||||||
mysql_mutex_lock(&thd->LOCK_thd_data);
|
mysql_mutex_lock(&thd->LOCK_thd_data);
|
||||||
|
|
||||||
@ -2949,11 +3022,6 @@ extern bool wsrep_thd_ignore_table(THD *thd)
|
|||||||
return thd->wsrep_ignore_table;
|
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,
|
bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
|
||||||
TABLE_LIST* src_table,
|
TABLE_LIST* src_table,
|
||||||
HA_CREATE_INFO *create_info)
|
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 ************/
|
/***** callbacks for wsrep service ************/
|
||||||
|
|
||||||
my_bool get_wsrep_recovery()
|
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 void wsrep_shutdown_replication();
|
||||||
extern bool wsrep_must_sync_wait (THD* thd, uint mask= WSREP_SYNC_WAIT_BEFORE_READ);
|
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, uint mask= WSREP_SYNC_WAIT_BEFORE_READ);
|
||||||
|
extern bool wsrep_sync_wait (THD* thd, enum enum_sql_command command);
|
||||||
extern enum wsrep::provider::status
|
extern enum wsrep::provider::status
|
||||||
wsrep_sync_wait_upto (THD* thd, wsrep_gtid_t* upto, int timeout);
|
wsrep_sync_wait_upto (THD* thd, wsrep_gtid_t* upto, int timeout);
|
||||||
extern int wsrep_check_opts();
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include "debug_sync.h"
|
||||||
|
|
||||||
#include <my_service_manager.h>
|
#include <my_service_manager.h>
|
||||||
|
|
||||||
@ -1508,6 +1509,33 @@ static int run_sql_command(THD *thd, const char *query)
|
|||||||
return 0;
|
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)
|
static int sst_flush_tables(THD* thd)
|
||||||
{
|
{
|
||||||
@ -1569,6 +1597,11 @@ static int sst_flush_tables(THD* thd)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
WSREP_INFO("Tables flushed.");
|
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
|
Tables have been flushed. Create a file with cluster state ID and
|
||||||
wsrep_gtid_domain_id.
|
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);
|
(long long)wsrep_locked_seqno, wsrep_gtid_server.domain_id);
|
||||||
err= sst_create_file(flush_success, content);
|
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";
|
const char base_name[]= "tables_flushed";
|
||||||
ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2;
|
ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2;
|
||||||
char *real_name= (char*) malloc(full_len);
|
char *real_name= (char*) malloc(full_len);
|
||||||
@ -1617,34 +1653,6 @@ static int sst_flush_tables(THD* thd)
|
|||||||
return err;
|
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)
|
static void* sst_donor_thread (void* a)
|
||||||
{
|
{
|
||||||
sst_thread_arg* arg= (sst_thread_arg*)a;
|
sst_thread_arg* arg= (sst_thread_arg*)a;
|
||||||
@ -1692,8 +1700,7 @@ wait_signal:
|
|||||||
err= sst_flush_tables (thd.ptr);
|
err= sst_flush_tables (thd.ptr);
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
sst_disallow_writes (thd.ptr, true);
|
/*
|
||||||
/*
|
|
||||||
Lets also keep statements that modify binary logs (like RESET LOGS,
|
Lets also keep statements that modify binary logs (like RESET LOGS,
|
||||||
RESET MASTER) from proceeding until the files have been transferred
|
RESET MASTER) from proceeding until the files have been transferred
|
||||||
to the joiner node.
|
to the joiner node.
|
||||||
@ -1704,6 +1711,18 @@ wait_signal:
|
|||||||
}
|
}
|
||||||
|
|
||||||
locked= true;
|
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;
|
goto wait_signal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -768,9 +768,6 @@ buf_page_is_corrupted(
|
|||||||
|
|
||||||
size_t checksum_field1 = 0;
|
size_t checksum_field1 = 0;
|
||||||
size_t checksum_field2 = 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 ulint zip_size = fil_space_t::zip_size(fsp_flags);
|
||||||
const uint16_t page_type = fil_page_get_type(read_buf);
|
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:
|
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
|
||||||
return !buf_page_is_checksum_valid_none(
|
return !buf_page_is_checksum_valid_none(
|
||||||
read_buf, checksum_field1, checksum_field2);
|
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_FULL_CRC32:
|
||||||
case SRV_CHECKSUM_ALGORITHM_CRC32:
|
case SRV_CHECKSUM_ALGORITHM_CRC32:
|
||||||
case SRV_CHECKSUM_ALGORITHM_INNODB:
|
case SRV_CHECKSUM_ALGORITHM_INNODB:
|
||||||
|
const uint32_t crc32 = buf_calc_page_crc32(read_buf);
|
||||||
|
|
||||||
if (buf_page_is_checksum_valid_none(read_buf,
|
if (buf_page_is_checksum_valid_none(read_buf,
|
||||||
checksum_field1, checksum_field2)) {
|
checksum_field1, checksum_field2)) {
|
||||||
#ifdef UNIV_INNOCHECKSUM
|
#ifdef UNIV_INNOCHECKSUM
|
||||||
@ -887,16 +889,13 @@ buf_page_is_corrupted(
|
|||||||
" crc32 = " UINT32PF "; recorded = " ULINTPF ";\n",
|
" crc32 = " UINT32PF "; recorded = " ULINTPF ";\n",
|
||||||
cur_page_num,
|
cur_page_num,
|
||||||
buf_calc_page_new_checksum(read_buf),
|
buf_calc_page_new_checksum(read_buf),
|
||||||
buf_calc_page_crc32(read_buf),
|
crc32,
|
||||||
checksum_field1);
|
checksum_field1);
|
||||||
}
|
}
|
||||||
#endif /* UNIV_INNOCHECKSUM */
|
#endif /* UNIV_INNOCHECKSUM */
|
||||||
return false;
|
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
|
/* Very old versions of InnoDB only stored 8 byte lsn to the
|
||||||
start and the end of the page. */
|
start and the end of the page. */
|
||||||
|
|
||||||
@ -907,81 +906,33 @@ buf_page_is_corrupted(
|
|||||||
!= mach_read_from_4(read_buf + FIL_PAGE_LSN)
|
!= mach_read_from_4(read_buf + FIL_PAGE_LSN)
|
||||||
&& checksum_field2 != BUF_NO_CHECKSUM_MAGIC) {
|
&& checksum_field2 != BUF_NO_CHECKSUM_MAGIC) {
|
||||||
|
|
||||||
if (crc32_chksum) {
|
DBUG_EXECUTE_IF(
|
||||||
crc32 = buf_calc_page_crc32(read_buf);
|
"page_intermittent_checksum_mismatch", {
|
||||||
crc32_inited = true;
|
static int page_counter;
|
||||||
|
if (page_counter++ == 2) return true;
|
||||||
|
});
|
||||||
|
|
||||||
DBUG_EXECUTE_IF(
|
if ((checksum_field1 != crc32
|
||||||
"page_intermittent_checksum_mismatch", {
|
|| checksum_field2 != crc32)
|
||||||
static int page_counter;
|
&& checksum_field2
|
||||||
if (page_counter++ == 2) {
|
!= buf_calc_page_old_checksum(read_buf)) {
|
||||||
crc32++;
|
return true;
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
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 == 0
|
switch (checksum_field1) {
|
||||||
|| checksum_field1 == BUF_NO_CHECKSUM_MAGIC) {
|
case 0:
|
||||||
} else if (crc32_chksum) {
|
case BUF_NO_CHECKSUM_MAGIC:
|
||||||
|
break;
|
||||||
if (!crc32_inited) {
|
default:
|
||||||
crc32 = buf_calc_page_crc32(read_buf);
|
if ((checksum_field1 != crc32
|
||||||
crc32_inited = true;
|
|| checksum_field2 != crc32)
|
||||||
}
|
|
||||||
|
|
||||||
if (checksum_field1 != crc32
|
|
||||||
&& checksum_field1
|
&& checksum_field1
|
||||||
!= buf_calc_page_new_checksum(read_buf)) {
|
!= buf_calc_page_new_checksum(read_buf)) {
|
||||||
return true;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1967,10 +1967,11 @@ fil_make_filepath(
|
|||||||
if (path != NULL) {
|
if (path != NULL) {
|
||||||
memcpy(full_name, path, path_len);
|
memcpy(full_name, path, path_len);
|
||||||
len = 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) {
|
if (trim_name) {
|
||||||
/* Find the offset of the last DIR separator and set it to
|
/* Find the offset of the last DIR separator and set it to
|
||||||
null in order to strip off the old basename from this path. */
|
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;
|
fts_trx_table_t* ftt;
|
||||||
|
|
||||||
ftt = static_cast<fts_trx_table_t*>(
|
ftt = static_cast<fts_trx_table_t*>(
|
||||||
mem_heap_alloc(fts_trx->heap, sizeof(*ftt)));
|
mem_heap_zalloc(fts_trx->heap, sizeof *ftt));
|
||||||
|
|
||||||
memset(ftt, 0x0, sizeof(*ftt));
|
|
||||||
|
|
||||||
ftt->table = table;
|
ftt->table = table;
|
||||||
ftt->fts_trx = fts_trx;
|
ftt->fts_trx = fts_trx;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* Copyright (c) 2008, 2021, Oracle and/or its affiliates.
|
/* 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
|
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,
|
it under the terms of the GNU General Public License, version 2.0,
|
||||||
@ -24,6 +25,9 @@
|
|||||||
#include <my_sys.h>
|
#include <my_sys.h>
|
||||||
#include <pfs_global.h>
|
#include <pfs_global.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#ifdef HAVE_MEMALIGN
|
||||||
|
# include <malloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
bool pfs_initialized= false;
|
bool pfs_initialized= false;
|
||||||
size_t pfs_allocated_memory_size= 0;
|
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)
|
if (--stub_alloc_fails_after_count <= 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
#ifndef PFS_ALIGNEMENT
|
||||||
void *ptr= malloc(size);
|
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)
|
if (ptr != NULL)
|
||||||
memset(ptr, 0, size);
|
memset(ptr, 0, size);
|
||||||
return ptr;
|
return ptr;
|
||||||
|
@ -1128,13 +1128,21 @@ int decimal2ulonglong(const decimal_t *from, ulonglong *to)
|
|||||||
|
|
||||||
for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
|
for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
|
||||||
{
|
{
|
||||||
ulonglong y=x;
|
/*
|
||||||
x=x*DIG_BASE + *buf++;
|
Check that the decimal is bigger than any possible integer.
|
||||||
if (unlikely(y > ((ulonglong) ULONGLONG_MAX/DIG_BASE) || x < y))
|
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;
|
*to=ULONGLONG_MAX;
|
||||||
return E_DEC_OVERFLOW;
|
return E_DEC_OVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x=x*DIG_BASE + *buf++;
|
||||||
}
|
}
|
||||||
*to=x;
|
*to=x;
|
||||||
for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
|
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)
|
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!
|
Attention: trick!
|
||||||
we're calculating -|from| instead of |from| here
|
we're calculating -|from| instead of |from| here
|
||||||
because |LONGLONG_MIN| > LONGLONG_MAX
|
because |LONGLONG_MIN| > LONGLONG_MAX
|
||||||
so we can convert -9223372036854775808 correctly
|
so we can convert -9223372036854775808 correctly.
|
||||||
*/
|
*/
|
||||||
x=x*DIG_BASE - *buf++;
|
if (unlikely (
|
||||||
if (unlikely(y < (LONGLONG_MIN/DIG_BASE) || x > y))
|
x <= LONGLONG_MIN/DIG_BASE &&
|
||||||
|
(x < LONGLONG_MIN/DIG_BASE ||
|
||||||
|
*buf > (dec1) (-(LONGLONG_MIN%DIG_BASE)))))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
the decimal is bigger than any possible integer
|
the decimal is bigger than any possible integer
|
||||||
return border integer depending on the sign
|
return border integer depending on the sign
|
||||||
*/
|
*/
|
||||||
*to= from->sign ? LONGLONG_MIN : LONGLONG_MAX;
|
*to= from->sign ? LONGLONG_MIN : LONGLONG_MAX;
|
||||||
return E_DEC_OVERFLOW;
|
return E_DEC_OVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x=x*DIG_BASE - *buf++;
|
||||||
}
|
}
|
||||||
/* boundary case: 9223372036854775808 */
|
/* boundary case: 9223372036854775808 */
|
||||||
if (unlikely(from->sign==0 && x == LONGLONG_MIN))
|
if (unlikely(from->sign==0 && x == LONGLONG_MIN))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user