mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
Merge branch '10.11' into 11.4
This commit is contained in:
@@ -207,7 +207,7 @@ static char TMPDIR[FN_REFLEN];
|
||||
static char global_subst_from[200];
|
||||
static char global_subst_to[200];
|
||||
static char *global_subst= NULL;
|
||||
static char *read_command_buf= NULL;
|
||||
static char *read_command_buf= NULL, *read_command_buf_end;
|
||||
static MEM_ROOT require_file_root;
|
||||
static const my_bool my_true= 1;
|
||||
static const my_bool my_false= 0;
|
||||
@@ -3873,9 +3873,24 @@ end:
|
||||
#endif
|
||||
if (error)
|
||||
{
|
||||
uint status= WEXITSTATUS(error);
|
||||
uint status;
|
||||
int i;
|
||||
|
||||
#ifdef _WIN32
|
||||
status= WEXITSTATUS(error);
|
||||
#else
|
||||
/* WEXITSTATUS() is only valid for a normal exit; a process killed by an
|
||||
uncaught signal must be translated using the shell's 128+signal
|
||||
convention, or the real error is silently lost as status 0. */
|
||||
if (WIFEXITED(error))
|
||||
status= WEXITSTATUS(error);
|
||||
else if (WIFSIGNALED(error))
|
||||
status= 128 + WTERMSIG(error);
|
||||
else
|
||||
status= error;
|
||||
|
||||
#endif
|
||||
|
||||
if (command->abort_on_error)
|
||||
{
|
||||
report_or_die("exec of '%s' failed, error: %d, status: %d, errno: %d\n"
|
||||
@@ -5638,7 +5653,7 @@ static void primary(Expression_value *result, const char **s)
|
||||
enum func_type func_type= get_expr_function_type(start,
|
||||
end - start);
|
||||
if (func_type == FUNC_UNKNOWN)
|
||||
die("Syntax error: Unknown function");
|
||||
die("Syntax error: Unknown function '%.*s'", (int) (end - start), start);
|
||||
|
||||
*s= end + 1; // skip '('
|
||||
handle_expr_function_call(func_type, result, s);
|
||||
@@ -6085,47 +6100,48 @@ static void expr(Expression_value *result, const char **s)
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
size_t length;
|
||||
enum func_type type;
|
||||
} function_table[]= {
|
||||
// Numeric functions
|
||||
{"abs", FUNC_ABS},
|
||||
{"bin", FUNC_BIN},
|
||||
{"conv", FUNC_CONV},
|
||||
{"hex", FUNC_HEX},
|
||||
{"oct", FUNC_OCT},
|
||||
{STRING_WITH_LEN("abs"), FUNC_ABS},
|
||||
{STRING_WITH_LEN("bin"), FUNC_BIN},
|
||||
{STRING_WITH_LEN("conv"), FUNC_CONV},
|
||||
{STRING_WITH_LEN("hex"), FUNC_HEX},
|
||||
{STRING_WITH_LEN("oct"), FUNC_OCT},
|
||||
// String functions
|
||||
{"concat", FUNC_CONCAT},
|
||||
{"concat_ws", FUNC_CONCAT_WS},
|
||||
{"greatest", FUNC_GREATEST},
|
||||
{"insert", FUNC_INSERT},
|
||||
{"instr", FUNC_INSTR},
|
||||
{"lcase", FUNC_LOWER},
|
||||
{"least", FUNC_LEAST},
|
||||
{"length", FUNC_LENGTH},
|
||||
{"locate", FUNC_LOCATE},
|
||||
{"lower", FUNC_LOWER},
|
||||
{"lpad", FUNC_LPAD},
|
||||
{"ltrim", FUNC_LTRIM},
|
||||
{"repeat", FUNC_REPEAT},
|
||||
{"replace", FUNC_REPLACE},
|
||||
{"reverse", FUNC_REVERSE},
|
||||
{"rpad", FUNC_RPAD},
|
||||
{"rtrim", FUNC_RTRIM},
|
||||
{"substr", FUNC_SUBSTR},
|
||||
{"substring", FUNC_SUBSTR},
|
||||
{"substring_index", FUNC_SUBSTR_IDX},
|
||||
{"trim", FUNC_TRIM},
|
||||
{"ucase", FUNC_UPPER},
|
||||
{"upper", FUNC_UPPER},
|
||||
{STRING_WITH_LEN("concat"), FUNC_CONCAT},
|
||||
{STRING_WITH_LEN("concat_ws"), FUNC_CONCAT_WS},
|
||||
{STRING_WITH_LEN("greatest"), FUNC_GREATEST},
|
||||
{STRING_WITH_LEN("insert"), FUNC_INSERT},
|
||||
{STRING_WITH_LEN("instr"), FUNC_INSTR},
|
||||
{STRING_WITH_LEN("lcase"), FUNC_LOWER},
|
||||
{STRING_WITH_LEN("least"), FUNC_LEAST},
|
||||
{STRING_WITH_LEN("length"), FUNC_LENGTH},
|
||||
{STRING_WITH_LEN("locate"), FUNC_LOCATE},
|
||||
{STRING_WITH_LEN("lower"), FUNC_LOWER},
|
||||
{STRING_WITH_LEN("lpad"), FUNC_LPAD},
|
||||
{STRING_WITH_LEN("ltrim"), FUNC_LTRIM},
|
||||
{STRING_WITH_LEN("repeat"), FUNC_REPEAT},
|
||||
{STRING_WITH_LEN("replace"), FUNC_REPLACE},
|
||||
{STRING_WITH_LEN("reverse"), FUNC_REVERSE},
|
||||
{STRING_WITH_LEN("rpad"), FUNC_RPAD},
|
||||
{STRING_WITH_LEN("rtrim"), FUNC_RTRIM},
|
||||
{STRING_WITH_LEN("substr"), FUNC_SUBSTR},
|
||||
{STRING_WITH_LEN("substring"), FUNC_SUBSTR},
|
||||
{STRING_WITH_LEN("substring_index"), FUNC_SUBSTR_IDX},
|
||||
{STRING_WITH_LEN("trim"), FUNC_TRIM},
|
||||
{STRING_WITH_LEN("ucase"), FUNC_UPPER},
|
||||
{STRING_WITH_LEN("upper"), FUNC_UPPER},
|
||||
// Regexp functions
|
||||
{"regexp_instr", FUNC_REGEXP_INSTR},
|
||||
{"regexp_replace", FUNC_REGEXP_REPLACE},
|
||||
{"regexp_substr", FUNC_REGEXP_SUBSTR},
|
||||
{STRING_WITH_LEN("regexp_instr"), FUNC_REGEXP_INSTR},
|
||||
{STRING_WITH_LEN("regexp_replace"), FUNC_REGEXP_REPLACE},
|
||||
{STRING_WITH_LEN("regexp_substr"), FUNC_REGEXP_SUBSTR},
|
||||
// Null functions
|
||||
{"coalesce", FUNC_COALESCE},
|
||||
{"ifnull", FUNC_IFNULL},
|
||||
{"nullif", FUNC_NULLIF},
|
||||
{NULL, FUNC_UNKNOWN}
|
||||
{STRING_WITH_LEN("coalesce"), FUNC_COALESCE},
|
||||
{STRING_WITH_LEN("ifnull"), FUNC_IFNULL},
|
||||
{STRING_WITH_LEN("nullif"), FUNC_NULLIF},
|
||||
{NULL, 0, FUNC_UNKNOWN}
|
||||
};
|
||||
|
||||
|
||||
@@ -6365,9 +6381,9 @@ void func_oct(Expression_value args[], int count, Expression_value *result)
|
||||
@param[out] result Expression_value to store result
|
||||
|
||||
@details
|
||||
Converts a number to hexadecimal representation.
|
||||
HEX(N) returns a string representation of the hexadecimal value of N.
|
||||
This is equivalent to CONV(N, 10, 16).
|
||||
HEX(str) returns a hexadecimal representation of the bytes of str.
|
||||
|
||||
@note Dies if argument count != 1
|
||||
*/
|
||||
@@ -6377,7 +6393,15 @@ void func_hex(Expression_value args[], int count, Expression_value *result)
|
||||
if (count != 1)
|
||||
die("hex() expects 1 argument, got %d", count);
|
||||
|
||||
convert_base_helper(args[0].to_string(), 10, 16, result);
|
||||
if (args[0].is_numeric)
|
||||
convert_base_helper(args[0].to_string(), 10, 16, result);
|
||||
else
|
||||
{
|
||||
My_string str= args[0].to_string();
|
||||
My_string hex_str;
|
||||
hex_str.set_hex(str.ptr(), str.length());
|
||||
result->set_string(hex_str.ptr(), hex_str.length());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7641,7 +7665,8 @@ enum func_type get_expr_function_type(const char *name, size_t len)
|
||||
{
|
||||
for (int i= 0; function_table[i].name; ++i)
|
||||
{
|
||||
if (!strncasecmp(function_table[i].name, name, len))
|
||||
if (function_table[i].length == len &&
|
||||
!strncasecmp(function_table[i].name, name, len))
|
||||
return function_table[i].type;
|
||||
}
|
||||
return FUNC_UNKNOWN;
|
||||
@@ -9743,7 +9768,7 @@ int read_line()
|
||||
*p= 0;
|
||||
DBUG_PRINT("exit", ("Found delimiter '%s' at line %d",
|
||||
delimiter, cur_file->lineno));
|
||||
DBUG_RETURN(0);
|
||||
goto ret;
|
||||
}
|
||||
else if ((c == '{' &&
|
||||
(!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
|
||||
@@ -9756,7 +9781,7 @@ int read_line()
|
||||
*p= 0;
|
||||
DBUG_PRINT("exit", ("Found '{' indicating start of block at line %d",
|
||||
cur_file->lineno));
|
||||
DBUG_RETURN(0);
|
||||
goto ret;
|
||||
}
|
||||
else if (c == '\'' || c == '"' || c == '`')
|
||||
{
|
||||
@@ -9790,7 +9815,7 @@ int read_line()
|
||||
*p= 0;
|
||||
DBUG_PRINT("exit", ("Found newline in comment at line: %d",
|
||||
cur_file->lineno));
|
||||
DBUG_RETURN(0);
|
||||
goto ret;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -9810,7 +9835,7 @@ int read_line()
|
||||
DBUG_PRINT("info", ("Found two new lines in a row"));
|
||||
*p++= c;
|
||||
*p= 0;
|
||||
DBUG_RETURN(0);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
/* Query hasn't started yet */
|
||||
@@ -9827,7 +9852,7 @@ int read_line()
|
||||
*p= 0;
|
||||
DBUG_PRINT("exit", ("Found delimiter '%s' at line: %d",
|
||||
delimiter, cur_file->lineno));
|
||||
DBUG_RETURN(0);
|
||||
goto ret;
|
||||
}
|
||||
else if (c == '}')
|
||||
{
|
||||
@@ -9836,7 +9861,7 @@ int read_line()
|
||||
*p= 0;
|
||||
DBUG_PRINT("exit", ("Found '}' in beginning of a line at line: %d",
|
||||
cur_file->lineno));
|
||||
DBUG_RETURN(0);
|
||||
goto ret;
|
||||
}
|
||||
else if (c == '\'' || c == '"' || c == '`')
|
||||
{
|
||||
@@ -9895,6 +9920,8 @@ int read_line()
|
||||
}
|
||||
}
|
||||
}
|
||||
ret:
|
||||
read_command_buf_end= p;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@@ -9910,14 +9937,13 @@ int read_line()
|
||||
|
||||
*/
|
||||
|
||||
void convert_to_format_v1(char* query)
|
||||
void convert_to_format_v1(char* query, char **end)
|
||||
{
|
||||
int last_c_was_quote= 0;
|
||||
char *p= query, *to= query;
|
||||
char *end= strend(query);
|
||||
char last_c;
|
||||
|
||||
while (p <= end)
|
||||
while (p <= *end)
|
||||
{
|
||||
if (*p == '\n' && !last_c_was_quote)
|
||||
{
|
||||
@@ -9948,6 +9974,7 @@ void convert_to_format_v1(char* query)
|
||||
last_c_was_quote= 0;
|
||||
}
|
||||
}
|
||||
*end= to;
|
||||
}
|
||||
|
||||
|
||||
@@ -10064,9 +10091,9 @@ int read_command(struct st_command** command_ptr)
|
||||
}
|
||||
|
||||
if (opt_result_format_version == 1)
|
||||
convert_to_format_v1(read_command_buf);
|
||||
convert_to_format_v1(read_command_buf, &read_command_buf_end);
|
||||
|
||||
char *p= read_command_buf;
|
||||
char *p= read_command_buf, *end= read_command_buf_end;
|
||||
DBUG_PRINT("info", ("query: '%s'", read_command_buf));
|
||||
if (*p == '#')
|
||||
{
|
||||
@@ -10083,29 +10110,32 @@ int read_command(struct st_command** command_ptr)
|
||||
}
|
||||
|
||||
/* Skip leading spaces */
|
||||
while (*p && my_isspace(charset_info, *p))
|
||||
while (p < end && my_isspace(charset_info, *p))
|
||||
p++;
|
||||
|
||||
if (!(command->query_buf= command->query= my_strdup(PSI_NOT_INSTRUMENTED, p, MYF(MY_WME))))
|
||||
if (!(command->query_buf= command->query=
|
||||
(char*)my_memdup(PSI_NOT_INSTRUMENTED, p, end - p, MYF(MY_WME))))
|
||||
die("Out of memory");
|
||||
|
||||
command->query_len= (int)(end - p - 1);
|
||||
command->end= command->query + command->query_len;
|
||||
p= command->query;
|
||||
end= command->end;
|
||||
/*
|
||||
Calculate first word length(the command), terminated
|
||||
by 'space' , '(' or 'delimiter' */
|
||||
p= command->query;
|
||||
while (*p && !my_isspace(charset_info, *p) && *p != '(' && !is_delimiter(p))
|
||||
by 'space' , '(' or 'delimiter'
|
||||
*/
|
||||
while (p < end && !my_isspace(charset_info, *p) && *p != '(' && !is_delimiter(p))
|
||||
p++;
|
||||
command->first_word_len= (uint) (p - command->query);
|
||||
DBUG_PRINT("info", ("first_word: %.*s",
|
||||
command->first_word_len, command->query));
|
||||
|
||||
/* Skip spaces between command and first argument */
|
||||
while (*p && my_isspace(charset_info, *p))
|
||||
while (p < end && my_isspace(charset_info, *p))
|
||||
p++;
|
||||
command->first_argument= p;
|
||||
|
||||
command->end= strend(command->query);
|
||||
command->query_len= (int)(command->end - command->query);
|
||||
parser.read_lines++;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@@ -12403,7 +12433,7 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
|
||||
else
|
||||
{
|
||||
query = command->query;
|
||||
query_len = strlen(query);
|
||||
query_len = command->query_len;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -12793,6 +12823,7 @@ void get_command_type(struct st_command* command)
|
||||
if (type == Q_QUERY)
|
||||
{
|
||||
/* Skip the "query" part */
|
||||
command->query_len-= (int)(command->first_argument - command->query);
|
||||
command->query= command->first_argument;
|
||||
}
|
||||
}
|
||||
@@ -13353,7 +13384,8 @@ int main(int argc, char **argv)
|
||||
if (command->query == command->query_buf)
|
||||
{
|
||||
/* Skip the first part of command, i.e query_xxx */
|
||||
command->query= command->first_argument;
|
||||
command->query_len-= (int)(command->first_argument - command->query);
|
||||
command->query= command->first_argument;
|
||||
command->first_word_len= 0;
|
||||
}
|
||||
/* fall through */
|
||||
@@ -13415,7 +13447,10 @@ int main(int argc, char **argv)
|
||||
|
||||
/* Remove "send" if this is first iteration */
|
||||
if (command->query == command->query_buf)
|
||||
{
|
||||
command->query_len-= (int)(command->first_argument - command->query);
|
||||
command->query= command->first_argument;
|
||||
}
|
||||
|
||||
/*
|
||||
run_query() can execute a query partially, depending on the flags.
|
||||
|
||||
@@ -263,7 +263,7 @@ IF(WITH_WSREP)
|
||||
SETA(CPACK_RPM_server_PACKAGE_REQUIRES
|
||||
"galera-4" "rsync" "grep" "gawk" "iproute"
|
||||
"coreutils" "findutils" "tar")
|
||||
SETA(CPACK_RPM_server_PACKAGE_RECOMMENDS "lsof" "socat" "pv")
|
||||
SETA(CPACK_RPM_server_PACKAGE_RECOMMENDS "lsof" "socat" "pv" "stunnel")
|
||||
SETA(CPACK_RPM_test_PACKAGE_REQUIRES "${CPACK_RPM_PACKAGE_REQUIRES}" "socat")
|
||||
ENDIF()
|
||||
|
||||
|
||||
@@ -64,6 +64,9 @@
|
||||
#
|
||||
# - INSTALL_UNIX_ADDRDIR (path to mysql.sock)
|
||||
#
|
||||
# - INSTALL_RUNDIR (runtime state files that mariadbd must not write,
|
||||
# e.g. what systemd reads as EnvironmentFile)
|
||||
#
|
||||
|
||||
IF(NOT INSTALL_LAYOUT)
|
||||
IF(DEB)
|
||||
@@ -163,7 +166,7 @@ SET(INSTALL_UNIX_ADDRDIR_RPM "${INSTALL_MYSQLDATADIR_RPM}/mysql.sock"
|
||||
SET(INSTALL_SYSTEMD_UNITDIR_RPM "/usr/lib/systemd/system")
|
||||
SET(INSTALL_SYSTEMD_SYSUSERSDIR_RPM "/usr/lib/sysusers.d")
|
||||
SET(INSTALL_SYSTEMD_TMPFILESDIR_RPM "/usr/lib/tmpfiles.d")
|
||||
SET(INSTALL_RUNDATADIR_RPM "/run/mariadb")
|
||||
SET(INSTALL_RUNDIR_RPM "/run")
|
||||
SET(INSTALL_PAMDIR_RPM "/${INSTALL_LIBDIR_RPM}/security")
|
||||
SET(INSTALL_PAMDATADIR_RPM "/etc/security")
|
||||
|
||||
@@ -194,8 +197,8 @@ SET(INSTALL_SUPPORTFILESDIR_DEB "share/mariadb")
|
||||
#
|
||||
SET(INSTALL_MYSQLDATADIR_DEB "/var/lib/mysql")
|
||||
|
||||
SET(INSTALL_RUNDATADIR_DEB "/run/mysqld")
|
||||
SET(INSTALL_UNIX_ADDRDIR_DEB "${INSTALL_RUNDATADIR_DEB}/mysqld.sock")
|
||||
SET(INSTALL_RUNDIR_DEB "/run")
|
||||
SET(INSTALL_UNIX_ADDRDIR_DEB "${INSTALL_RUNDIR_DEB}/mysqld/mysqld.sock")
|
||||
SET(INSTALL_SYSTEMD_UNITDIR_DEB "/lib/systemd/system")
|
||||
SET(INSTALL_SYSTEMD_SYSUSERSDIR_DEB "/usr/lib/sysusers.d")
|
||||
SET(INSTALL_SYSTEMD_TMPFILESDIR_DEB "/usr/lib/tmpfiles.d")
|
||||
@@ -259,7 +262,10 @@ IF(NOT MYSQL_UNIX_ADDR)
|
||||
SET(MYSQL_UNIX_ADDR ${INSTALL_UNIX_ADDRDIR})
|
||||
ENDIF()
|
||||
|
||||
IF(NOT INSTALL_RUNDATADIR)
|
||||
IF(NOT INSTALL_RUNDIR)
|
||||
# No /run in a tarball installation - fall back to the socket directory.
|
||||
# Note that mariadbd can write there, so the isolation that /run gives to
|
||||
# packages (see EnvironmentFile= in mariadb.service) is not achieved.
|
||||
get_filename_component(MYSQL_UNIX_DIR ${MYSQL_UNIX_ADDR} DIRECTORY)
|
||||
SET(INSTALL_RUNDATADIR "${MYSQL_UNIX_DIR}" CACHE FILEPATH "Rundata installation directory" ${FORCE})
|
||||
SET(INSTALL_RUNDIR "${MYSQL_UNIX_DIR}" CACHE FILEPATH "Runtime state directory" ${FORCE})
|
||||
ENDIF()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
Copyright (c) 2026, MariaDB plc.
|
||||
|
||||
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.
|
||||
@@ -183,6 +184,7 @@
|
||||
#cmakedefine HAVE_MMAP 1
|
||||
#cmakedefine HAVE_MMAP64 1
|
||||
#cmakedefine HAVE_MPROTECT 1
|
||||
#cmakedefine HAVE_RO_AFTER_INIT 1
|
||||
#cmakedefine HAVE_PERROR 1
|
||||
#cmakedefine HAVE_POLL 1
|
||||
#cmakedefine HAVE_POSIX_FALLOCATE 1
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
#
|
||||
# Copyright (c) 2026, MariaDB plc.
|
||||
#
|
||||
# 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.
|
||||
@@ -369,6 +370,24 @@ CHECK_FUNCTION_EXISTS (mmap HAVE_MMAP)
|
||||
CHECK_FUNCTION_EXISTS (mmap64 HAVE_MMAP64)
|
||||
CHECK_FUNCTION_EXISTS (mprotect HAVE_MPROTECT)
|
||||
CHECK_FUNCTION_EXISTS (perror HAVE_PERROR)
|
||||
|
||||
IF(HAVE_SYS_MMAN_H AND HAVE_MPROTECT)
|
||||
SET(SAVE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
||||
SET(CMAKE_REQUIRED_FLAGS
|
||||
"${CMAKE_REQUIRED_FLAGS} -Wl,-T,${CMAKE_SOURCE_DIR}/sql/mysqld_ro.lds")
|
||||
CHECK_C_SOURCE_COMPILES("
|
||||
#include <sys/mman.h>
|
||||
__attribute__((section(\"ro_after_init\"))) int hardened= 1;
|
||||
extern char __ro_after_init_start[] __attribute__((weak));
|
||||
extern char __ro_after_init_end[] __attribute__((weak));
|
||||
int main(void) {
|
||||
size_t size= __ro_after_init_end - __ro_after_init_start;
|
||||
mprotect(__ro_after_init_start, size, PROT_READ | PROT_WRITE);
|
||||
return (int)size + hardened;
|
||||
}" HAVE_RO_AFTER_INIT)
|
||||
SET(CMAKE_REQUIRED_FLAGS "${SAVE_CMAKE_REQUIRED_FLAGS}")
|
||||
ENDIF()
|
||||
|
||||
CHECK_FUNCTION_EXISTS (poll HAVE_POLL)
|
||||
CHECK_FUNCTION_EXISTS (posix_fallocate HAVE_POSIX_FALLOCATE)
|
||||
CHECK_FUNCTION_EXISTS (pread HAVE_PREAD)
|
||||
|
||||
3
debian/control
vendored
3
debian/control
vendored
@@ -757,7 +757,8 @@ Suggests: mariadb-test,
|
||||
netcat-openbsd
|
||||
Recommends: libhtml-template-perl,
|
||||
mariadb-server-compat,
|
||||
pv
|
||||
pv,
|
||||
stunnel
|
||||
Pre-Depends: adduser (>= 3.40),
|
||||
debconf,
|
||||
mariadb-common (>= ${source:Version})
|
||||
|
||||
@@ -88,6 +88,25 @@ static mysql_cond_t kill_query_thread_stop;
|
||||
bool sql_thread_started = false;
|
||||
char *mysql_slave_position = NULL;
|
||||
char *mysql_binlog_position = NULL;
|
||||
/*
|
||||
MDEV-38147: the exact binary log file name that
|
||||
write_current_binlog_file() rotated to and shipped into the backup under
|
||||
--galera-info. Remembered here so that write_binlog_info() records the very
|
||||
same file name in xtrabackup_binlog_info, i.e. the file the SST joiner looks
|
||||
for is guaranteed to be the file that was actually sent (no rotation race).
|
||||
*/
|
||||
char *mysql_binlog_file = NULL;
|
||||
/*
|
||||
Position and GTID of that shipped binary log, captured together with
|
||||
mysql_binlog_file at flush time (see write_current_binlog_file()). Used by
|
||||
write_binlog_info() so that, if a rotation intervenes, the whole coordinate
|
||||
tuple it records stays consistent with the file that was actually shipped -
|
||||
which matters for a manual --galera-info backup used as a replication seed,
|
||||
not only for the SST joiner (which reads just the file name).
|
||||
*/
|
||||
static char *mysql_binlog_file_pos = NULL;
|
||||
static char *mysql_binlog_file_gtid_executed = NULL;
|
||||
static char *mysql_binlog_file_gtid_current_pos = NULL;
|
||||
char *buffer_pool_filename = NULL;
|
||||
|
||||
/* History on server */
|
||||
@@ -348,6 +367,30 @@ read_mysql_one_value(MYSQL *mysql, const char *query)
|
||||
return read_mysql_one_value(mysql, query, 0/*offset*/, 1/*total columns*/);
|
||||
}
|
||||
|
||||
/** Poll InnoDB's durably flushed redo LSN from the running server.
|
||||
Log copier uses this as its parse limit; it never accepts a redo log
|
||||
record whose end exceeds this LSN
|
||||
@param connection MariaDB client connection
|
||||
@retval 0 on failure, lsn on success */
|
||||
uint64_t get_log_flushed_lsn(MYSQL *connection) noexcept
|
||||
{
|
||||
if (!connection)
|
||||
return 0;
|
||||
|
||||
uint64_t lsn= 0;
|
||||
MYSQL_RES *res= xb_mysql_query(connection,
|
||||
"SHOW STATUS LIKE 'Innodb_lsn_flushed'",
|
||||
true, false);
|
||||
if (!res)
|
||||
return 0;
|
||||
|
||||
if (MYSQL_ROW row= mysql_fetch_row(res))
|
||||
if (row[1])
|
||||
lsn= strtoull(row[1], nullptr, 10);
|
||||
mysql_free_result(res);
|
||||
return lsn;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
bool
|
||||
@@ -1506,6 +1549,23 @@ write_galera_info(ds_ctxt *datasink, MYSQL *connection)
|
||||
domain_id ? domain_id : domain_id55);
|
||||
}
|
||||
|
||||
/*
|
||||
MDEV-38147: Flush and copy the donor's current binary log into
|
||||
the backup so that it is shipped to the SST joiner.
|
||||
|
||||
A new joiner discards this file and starts a fresh binary log seeded from
|
||||
the storage-engine checkpoint (see wsrep_seed_binlog_gtid_state() in
|
||||
sql/log.cc and the joiner code in scripts/wsrep_sst_mariabackup.sh), which
|
||||
avoids error 1950 with gtid_strict_mode=ON. The file is still shipped for
|
||||
backward compatibility with an old joiner that expects it, and so that a
|
||||
new joiner can deterministically identify and remove exactly the file that
|
||||
was sent instead of colliding with it.
|
||||
|
||||
write_current_binlog_file() remembers the rotated file name in
|
||||
mysql_binlog_file so that write_binlog_info() records the same file in
|
||||
xtrabackup_binlog_info - closing the old race where a concurrent rotation
|
||||
could make the shipped file and the recorded file diverge.
|
||||
*/
|
||||
if (result)
|
||||
write_current_binlog_file(datasink, connection);
|
||||
|
||||
@@ -1526,13 +1586,25 @@ cleanup:
|
||||
|
||||
/*********************************************************************//**
|
||||
Flush and copy the current binary log file into the backup,
|
||||
if GTID is enabled */
|
||||
if GTID is enabled.
|
||||
|
||||
MDEV-38147: the file name that FLUSH BINARY LOGS rotates to is
|
||||
remembered in the global mysql_binlog_file. write_binlog_info() then records
|
||||
that exact name in xtrabackup_binlog_info, so the file the SST joiner looks
|
||||
for is guaranteed to be the file that was shipped. Previously the shipped file
|
||||
(determined here) and the recorded file (determined independently later by
|
||||
write_binlog_info()) were read by two separate SHOW MASTER STATUS calls; a
|
||||
binary log rotation happening in between made them diverge and the wrong file
|
||||
was sent. */
|
||||
bool
|
||||
write_current_binlog_file(ds_ctxt *datasink, MYSQL *connection)
|
||||
{
|
||||
char *executed_gtid_set = NULL;
|
||||
char *gtid_binlog_state = NULL;
|
||||
char *gtid_current_pos = NULL;
|
||||
char *log_bin_file = NULL;
|
||||
char *log_bin_pos = NULL;
|
||||
char *log_bin_gtid_executed = NULL;
|
||||
char *log_bin_dir = NULL;
|
||||
bool gtid_exists;
|
||||
bool result = true;
|
||||
@@ -1543,13 +1615,18 @@ write_current_binlog_file(ds_ctxt *datasink, MYSQL *connection)
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* Capture the shipped file's coordinates together, right after the flush,
|
||||
so they describe exactly the file that is copied below. */
|
||||
mysql_variable status_after_flush[] = {
|
||||
{"File", &log_bin_file},
|
||||
{"Position", &log_bin_pos},
|
||||
{"Executed_Gtid_Set", &log_bin_gtid_executed},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
mysql_variable vars[] = {
|
||||
{"gtid_binlog_state", >id_binlog_state},
|
||||
{"gtid_current_pos", >id_current_pos},
|
||||
{"log_bin_basename", &log_bin_dir},
|
||||
{NULL, NULL}
|
||||
};
|
||||
@@ -1579,6 +1656,32 @@ write_current_binlog_file(ds_ctxt *datasink, MYSQL *connection)
|
||||
log_bin_dir = strdup("./");
|
||||
}
|
||||
|
||||
if (log_bin_dir == NULL || log_bin_file == NULL) {
|
||||
msg("Failed to get master binlog coordinates from "
|
||||
"SHOW MASTER STATUS");
|
||||
result = false;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
Remember the file we just rotated to (before any further
|
||||
rotation can happen), together with its position and GTID, so
|
||||
that write_binlog_info() records this very file - and a matching
|
||||
position/GTID - in xtrabackup_binlog_info, and the joiner looks
|
||||
for exactly the file that is shipped below.
|
||||
*/
|
||||
free(mysql_binlog_file);
|
||||
mysql_binlog_file = strdup(log_bin_file);
|
||||
free(mysql_binlog_file_pos);
|
||||
mysql_binlog_file_pos =
|
||||
log_bin_pos ? strdup(log_bin_pos) : NULL;
|
||||
free(mysql_binlog_file_gtid_executed);
|
||||
mysql_binlog_file_gtid_executed =
|
||||
log_bin_gtid_executed ? strdup(log_bin_gtid_executed) : NULL;
|
||||
free(mysql_binlog_file_gtid_current_pos);
|
||||
mysql_binlog_file_gtid_current_pos =
|
||||
gtid_current_pos ? strdup(gtid_current_pos) : NULL;
|
||||
|
||||
dirname_part(log_bin_dir, log_bin_dir, &log_bin_dir_length);
|
||||
|
||||
/* strip final slash if it is not the only path component */
|
||||
@@ -1587,13 +1690,6 @@ write_current_binlog_file(ds_ctxt *datasink, MYSQL *connection)
|
||||
log_bin_dir[log_bin_dir_length - 1] = 0;
|
||||
}
|
||||
|
||||
if (log_bin_dir == NULL || log_bin_file == NULL) {
|
||||
msg("Failed to get master binlog coordinates from "
|
||||
"SHOW MASTER STATUS");
|
||||
result = false;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
snprintf(filepath, sizeof(filepath), "%s%c%s",
|
||||
log_bin_dir, FN_LIBCHAR, log_bin_file);
|
||||
result = datasink->copy_file(filepath, log_bin_file, 0);
|
||||
@@ -1615,11 +1711,15 @@ bool
|
||||
write_binlog_info(ds_ctxt *datasink, MYSQL *connection)
|
||||
{
|
||||
char *filename = NULL;
|
||||
const char *out_filename;
|
||||
const char *out_position;
|
||||
const char *out_gtid_executed;
|
||||
const char *out_gtid_current_pos;
|
||||
char *position = NULL;
|
||||
char *gtid_mode = NULL;
|
||||
char *gtid_current_pos = NULL;
|
||||
char *gtid_executed = NULL;
|
||||
char *gtid = NULL;
|
||||
const char *gtid = NULL;
|
||||
bool result;
|
||||
bool mysql_gtid;
|
||||
bool mariadb_gtid;
|
||||
@@ -1647,25 +1747,53 @@ write_binlog_info(ds_ctxt *datasink, MYSQL *connection)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
mysql_gtid = ((gtid_mode != NULL) && (strcmp(gtid_mode, "ON") == 0));
|
||||
mariadb_gtid = (gtid_current_pos != NULL);
|
||||
/*
|
||||
MDEV-38147: if write_current_binlog_file() already rotated
|
||||
and shipped a binary log under --galera-info, record that exact file
|
||||
name here rather than whatever SHOW MASTER STATUS reports now. The two
|
||||
are normally identical, but a binary log rotation between the two
|
||||
SHOW MASTER STATUS calls would otherwise make mariadb_backup_binlog_info
|
||||
name a file different from the one that was shipped, so the SST joiner
|
||||
would look for a file that is not there. Use a separate pointer so the
|
||||
string owned by the status[] array is still freed at cleanup.
|
||||
*/
|
||||
out_filename = filename;
|
||||
out_position = position;
|
||||
out_gtid_executed = gtid_executed;
|
||||
out_gtid_current_pos = gtid_current_pos;
|
||||
if (mysql_binlog_file != NULL && strcmp(filename, mysql_binlog_file)) {
|
||||
msg("Binary log rotated to '%s' after '%s' was shipped; recording "
|
||||
"the shipped file and its coordinates in "
|
||||
MB_BINLOG_INFO, filename, mysql_binlog_file);
|
||||
/* Record the whole tuple from the shipped file, not just its name,
|
||||
so file/position/GTID stay consistent (the position and GTID from
|
||||
the SHOW MASTER STATUS above belong to the current, newer file). */
|
||||
out_filename = mysql_binlog_file;
|
||||
out_position = mysql_binlog_file_pos;
|
||||
out_gtid_executed = mysql_binlog_file_gtid_executed;
|
||||
out_gtid_current_pos = mysql_binlog_file_gtid_current_pos;
|
||||
}
|
||||
|
||||
gtid = (gtid_executed != NULL ? gtid_executed : gtid_current_pos);
|
||||
mysql_gtid = ((gtid_mode != NULL) && (strcmp(gtid_mode, "ON") == 0));
|
||||
mariadb_gtid = (out_gtid_current_pos != NULL);
|
||||
|
||||
gtid = (out_gtid_executed != NULL ? out_gtid_executed
|
||||
: out_gtid_current_pos);
|
||||
|
||||
if (mariadb_gtid || mysql_gtid) {
|
||||
ut_a(asprintf(&mysql_binlog_position,
|
||||
"filename '%s', position '%s', "
|
||||
"GTID of the last change '%s'",
|
||||
filename, position, gtid) != -1);
|
||||
out_filename, out_position, gtid) != -1);
|
||||
result = datasink->backup_file_printf(MB_BINLOG_INFO,
|
||||
"%s\t%s\t%s\n", filename, position,
|
||||
"%s\t%s\t%s\n", out_filename, out_position,
|
||||
gtid);
|
||||
} else {
|
||||
ut_a(asprintf(&mysql_binlog_position,
|
||||
"filename '%s', position '%s'",
|
||||
filename, position) != -1);
|
||||
out_filename, out_position) != -1);
|
||||
result = datasink->backup_file_printf(MB_BINLOG_INFO,
|
||||
"%s\t%s\n", filename, position);
|
||||
"%s\t%s\n", out_filename, out_position);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
@@ -1999,6 +2127,10 @@ backup_cleanup()
|
||||
{
|
||||
free(mysql_slave_position);
|
||||
free(mysql_binlog_position);
|
||||
free(mysql_binlog_file);
|
||||
free(mysql_binlog_file_pos);
|
||||
free(mysql_binlog_file_gtid_executed);
|
||||
free(mysql_binlog_file_gtid_current_pos);
|
||||
free(buffer_pool_filename);
|
||||
|
||||
if (mysql_connection) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define XTRABACKUP_BACKUP_MYSQL_H
|
||||
|
||||
#include <mysql.h>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include "datasink.h"
|
||||
@@ -26,6 +27,7 @@ extern time_t history_lock_time;
|
||||
extern bool sql_thread_started;
|
||||
extern char *mysql_slave_position;
|
||||
extern char *mysql_binlog_position;
|
||||
extern char *mysql_binlog_file;
|
||||
extern char *buffer_pool_filename;
|
||||
|
||||
/** connection to mysql server */
|
||||
@@ -97,4 +99,6 @@ bool
|
||||
write_slave_info(ds_ctxt *datasink, MYSQL *connection);
|
||||
|
||||
ulonglong get_current_lsn(MYSQL *connection);
|
||||
|
||||
uint64_t get_log_flushed_lsn(MYSQL *connection) noexcept;
|
||||
#endif
|
||||
|
||||
@@ -205,7 +205,7 @@ struct xb_filter_entry_t{
|
||||
/** whether log_copying_thread() is active; protected by recv_sys.mutex */
|
||||
static bool log_copying_running;
|
||||
/** the log parsing function for --backup */
|
||||
static recv_sys_t::parser backup_log_parse;
|
||||
static recv_sys_t::parser backup_log_parse_low;
|
||||
/** for --backup, target LSN to copy the log to; protected by recv_sys.mutex */
|
||||
lsn_t metadata_to_lsn;
|
||||
|
||||
@@ -251,6 +251,7 @@ const char *defaults_group = "mysqld";
|
||||
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
|
||||
#define HA_INNOBASE_RANGE_COUNT 100
|
||||
|
||||
#define METADATA_LSN_ERROR 1
|
||||
/* The default values for the following, type long or longlong, start-up
|
||||
parameters are declared in mysqld.cc: */
|
||||
|
||||
@@ -3464,6 +3465,41 @@ skip:
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* Maximum LSN the copier may parse up to.
|
||||
Usually derived from the server's durably-flushed redo LSN.
|
||||
When a final target LSN is set, this limit is raised to that
|
||||
target so the last partial block can be copied in full.
|
||||
The copier refuses to accept a mini-transaction whose end
|
||||
exceeds this, so it never parses the volatile tail block
|
||||
the server is still rewriting
|
||||
(which mmap can read torn, leading to a mis-computed mtr
|
||||
length and permanent mid-mtr drift). A pread() of the same
|
||||
still-being-written tail block can likewise return a torn read
|
||||
which can be observed on ext4, though not on XFS).
|
||||
Read/written only under recv_sys.mutex. */
|
||||
static lsn_t max_parse_lsn;
|
||||
|
||||
/* Set by backup_log_parse() when the last parse was
|
||||
rejected because the mtr crossed max_parse_lsn. It means
|
||||
"caught up, wait" condition, not a stall. */
|
||||
static bool reached_parse_limit;
|
||||
|
||||
static recv_sys_t::parse_mtr_result backup_log_parse()
|
||||
{
|
||||
const lsn_t prev_lsn= recv_sys.lsn;
|
||||
const size_t prev_offset= recv_sys.offset;
|
||||
reached_parse_limit= false;
|
||||
recv_sys_t::parse_mtr_result r= backup_log_parse_low(false);
|
||||
if (r == recv_sys_t::OK && max_parse_lsn && recv_sys.lsn > max_parse_lsn)
|
||||
{
|
||||
recv_sys.lsn= prev_lsn;
|
||||
recv_sys.offset= prev_offset;
|
||||
reached_parse_limit= true;
|
||||
return recv_sys_t::GOT_EOF;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
xtrabackup_copy_mmap_snippet(ds_file_t *ds, const byte *start, const byte *end)
|
||||
{
|
||||
@@ -3489,7 +3525,7 @@ static bool xtrabackup_copy_mmap_logfile()
|
||||
const byte *start= &log_sys.buf[recv_sys.offset];
|
||||
ut_d(recv_sys_t::parse_mtr_result r);
|
||||
|
||||
if ((ut_d(r=) backup_log_parse(false)) == recv_sys_t::OK)
|
||||
if ((ut_d(r=) backup_log_parse()) == recv_sys_t::OK)
|
||||
{
|
||||
do
|
||||
{
|
||||
@@ -3507,7 +3543,7 @@ static bool xtrabackup_copy_mmap_logfile()
|
||||
start = seq + 1;
|
||||
}
|
||||
}
|
||||
while ((ut_d(r=) backup_log_parse(false)) == recv_sys_t::OK);
|
||||
while ((ut_d(r=) backup_log_parse()) == recv_sys_t::OK);
|
||||
|
||||
if (xtrabackup_copy_mmap_snippet(dst_log_file, start,
|
||||
&log_sys.buf[recv_sys.offset]))
|
||||
@@ -3580,7 +3616,7 @@ static bool xtrabackup_copy_logfile(bool early_exit)
|
||||
if (log_sys.buf[recv_sys.offset] <= 1)
|
||||
break;
|
||||
|
||||
if (backup_log_parse(false) == recv_sys_t::OK)
|
||||
if (backup_log_parse() == recv_sys_t::OK)
|
||||
{
|
||||
do
|
||||
{
|
||||
@@ -3590,7 +3626,7 @@ static bool xtrabackup_copy_logfile(bool early_exit)
|
||||
sequence_offset));
|
||||
*seq= 1;
|
||||
}
|
||||
while ((r= backup_log_parse(false)) == recv_sys_t::OK);
|
||||
while ((r= backup_log_parse()) == recv_sys_t::OK);
|
||||
|
||||
if (ds_write(dst_log_file, log_sys.buf + start_offset,
|
||||
recv_sys.offset - start_offset))
|
||||
@@ -3620,6 +3656,9 @@ static bool xtrabackup_copy_logfile(bool early_exit)
|
||||
if (retry_count == 100)
|
||||
break;
|
||||
|
||||
if (reached_parse_limit)
|
||||
break;
|
||||
|
||||
mysql_mutex_unlock(&recv_sys.mutex);
|
||||
if (!retry_count++)
|
||||
msg("Retrying read of log at LSN=" LSN_PF, recv_sys.lsn);
|
||||
@@ -3634,13 +3673,32 @@ static bool xtrabackup_copy_logfile(bool early_exit)
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Handles backup log copy timeout or incomplete LSN copy.
|
||||
Checks if the target LSN was reached. If not,
|
||||
logs diagnostic messages advising whether to increase
|
||||
innodb_log_file_size (log wrapped around) or to check
|
||||
server/backup configuration mismatches.
|
||||
@param lsn Target LSN expected by the backup.
|
||||
@param last_lsn Actual maximum LSN copied so far.
|
||||
@return true if target LSN was reached, false otherwise. */
|
||||
static bool backup_wait_timeout(lsn_t lsn, lsn_t last_lsn)
|
||||
{
|
||||
if (last_lsn >= lsn)
|
||||
return true;
|
||||
|
||||
const lsn_t checkpoint_lsn= log_sys.last_checkpoint_lsn.load();
|
||||
const lsn_t capacity= log_sys.file_size - log_sys.START_OFFSET;
|
||||
const lsn_t needed= lsn - checkpoint_lsn;
|
||||
|
||||
msg("Was only able to copy log from " LSN_PF " to " LSN_PF
|
||||
", not " LSN_PF "; try increasing innodb_log_file_size",
|
||||
log_sys.last_checkpoint_lsn.load(), last_lsn, lsn);
|
||||
", not " LSN_PF, checkpoint_lsn, last_lsn, lsn);
|
||||
|
||||
if (needed <= capacity)
|
||||
msg("mariabackup: The required redo still fits within the log "
|
||||
"capacity, so it has not been overwritten; check whether the "
|
||||
"server and backup configuration are the same.");
|
||||
else
|
||||
msg("mariabackup: Try increasing the innodb_log_file_size.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3695,16 +3753,93 @@ static bool backup_wait_for_lsn(lsn_t lsn)
|
||||
static void log_copying_thread()
|
||||
{
|
||||
my_thread_init();
|
||||
mysql_mutex_lock(&recv_sys.mutex);
|
||||
while (!xtrabackup_copy_logfile(false) &&
|
||||
(!metadata_last_lsn || metadata_last_lsn > recv_sys.lsn))
|
||||
MYSQL *limit_con= xb_mysql_connect();
|
||||
if (!limit_con)
|
||||
{
|
||||
/* Without this connection we cannot poll the durably-flushed
|
||||
LSN, so max_parse_lsn could never advance and the copier
|
||||
would either stall or parse the volatile tail block.
|
||||
Fail the copy gracefully and let the main thread report
|
||||
it via backup_wait_timeout(). */
|
||||
msg("mariabackup: Error: cannot open a server connection for "
|
||||
"the log copying thread; the backup will fail.");
|
||||
mysql_mutex_lock(&recv_sys.mutex);
|
||||
log_copying_running= false;
|
||||
pthread_cond_broadcast(&scanned_lsn_cond);
|
||||
mysql_mutex_unlock(&recv_sys.mutex);
|
||||
my_thread_end();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
This thread polls Innodb_lsn_flushed via SHOW STATUS on its own connection.
|
||||
On a Galera donor wsrep_sync_wait may include SHOW, which would make that
|
||||
poll wait until the node has applied the latest cluster transactions. During
|
||||
a backup the donor's commit position can legitimately lag (e.g. a transaction
|
||||
sitting between its binary log write and engine commit), so the poll could
|
||||
block indefinitely and stall the redo log copier - failing the backup with a
|
||||
misleading "Was only able to copy log ..." error. The main backup connection
|
||||
already disables wsrep_sync_wait for the same reason, so do the same here.
|
||||
*/
|
||||
if (have_galera_enabled)
|
||||
xb_mysql_query(limit_con, "SET SESSION wsrep_sync_wait=0", false);
|
||||
|
||||
mysql_mutex_lock(&recv_sys.mutex);
|
||||
for (;;)
|
||||
{
|
||||
/* metadata_last_lsn is set to 1 when error was encountered.
|
||||
Abort the log copier if an error was signaled */
|
||||
if (metadata_last_lsn == METADATA_LSN_ERROR)
|
||||
break;
|
||||
/* Refresh the max_parse_lsn before each copy pass */
|
||||
const lsn_t final_target= metadata_last_lsn > metadata_to_lsn
|
||||
? metadata_last_lsn : metadata_to_lsn;
|
||||
if (final_target)
|
||||
/* Final phase (BLOCK_DDL/BLOCK_COMMIT): fence at the exact target
|
||||
instead of the polled flushed LSN. This is only safe because the
|
||||
target was derived from get_current_lsn(), which runs
|
||||
FLUSH ENGINE LOGS and thus makes the redo durable up to at least
|
||||
final_target; so final_target <= Innodb_lsn_flushed holds here and
|
||||
the bytes up to it are stable. Do not feed this branch an LSN that
|
||||
has not been flushed by the server, or the copier will parse the
|
||||
volatile tail block again (MDEV-39468). */
|
||||
max_parse_lsn= final_target;
|
||||
else
|
||||
{
|
||||
mysql_mutex_unlock(&recv_sys.mutex);
|
||||
lsn_t flushed= get_log_flushed_lsn(limit_con);
|
||||
mysql_mutex_lock(&recv_sys.mutex);
|
||||
if (flushed > log_sys.get_first_lsn())
|
||||
max_parse_lsn= flushed;
|
||||
else if (!max_parse_lsn)
|
||||
{
|
||||
/* We could not obtain a flushed LSN and none was seeded before,
|
||||
so the parse limit is unset and the copier would fall back to
|
||||
parsing the volatile tail block (the MDEV-39468 failure). Warn
|
||||
once so this is diagnosable rather than a silent stall. */
|
||||
static bool warned;
|
||||
if (!warned)
|
||||
{
|
||||
warned= true;
|
||||
msg("mariabackup: Warning: could not read Innodb_lsn_flushed; "
|
||||
"the redo log copier has no parse limit.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xtrabackup_copy_logfile(false))
|
||||
break;
|
||||
if (final_target && final_target <= recv_sys.lsn)
|
||||
break;
|
||||
|
||||
timespec abstime;
|
||||
set_timespec_nsec(abstime, 1000000ULL * xtrabackup_log_copy_interval);
|
||||
mysql_cond_timedwait(&log_copying_stop, &recv_sys.mutex, &abstime);
|
||||
}
|
||||
log_copying_running= false;
|
||||
mysql_mutex_unlock(&recv_sys.mutex);
|
||||
if (limit_con)
|
||||
mysql_close(limit_con);
|
||||
my_thread_end();
|
||||
}
|
||||
|
||||
@@ -4909,7 +5044,7 @@ static bool backup_wait_for_commit_lsn()
|
||||
else
|
||||
{
|
||||
msg("Error: recv_sys.find_checkpoint() failed.");
|
||||
metadata_last_lsn= 1;
|
||||
metadata_last_lsn= METADATA_LSN_ERROR;
|
||||
stop_backup_threads();
|
||||
mysql_mutex_unlock(&recv_sys.mutex);
|
||||
return false;
|
||||
@@ -5508,7 +5643,7 @@ static bool xtrabackup_backup_func()
|
||||
fail:
|
||||
if (log_copying_running) {
|
||||
mysql_mutex_lock(&recv_sys.mutex);
|
||||
metadata_last_lsn = 1;
|
||||
metadata_last_lsn = METADATA_LSN_ERROR;
|
||||
stop_backup_threads();
|
||||
mysql_mutex_unlock(&recv_sys.mutex);
|
||||
}
|
||||
@@ -5635,9 +5770,15 @@ fail:
|
||||
/* copy log file by current position */
|
||||
|
||||
mysql_mutex_lock(&recv_sys.mutex);
|
||||
backup_log_parse = recv_sys.get_backup_parser();
|
||||
backup_log_parse_low = recv_sys.get_backup_parser();
|
||||
recv_sys.lsn = log_sys.last_checkpoint_lsn;
|
||||
|
||||
if (lsn_t flushed= get_log_flushed_lsn(mysql_connection))
|
||||
{
|
||||
if (flushed > log_sys.get_first_lsn())
|
||||
max_parse_lsn= flushed;
|
||||
}
|
||||
|
||||
const bool log_copy_failed = xtrabackup_copy_logfile(true);
|
||||
|
||||
mysql_mutex_unlock(&recv_sys.mutex);
|
||||
|
||||
@@ -30,7 +30,6 @@ extern "C" {
|
||||
#include <my_pthread.h>
|
||||
#include <thr_lock.h>
|
||||
|
||||
#include "my_compare.h"
|
||||
#include "my_tree.h"
|
||||
|
||||
/* defines used by heap-functions */
|
||||
@@ -109,6 +108,7 @@ typedef struct st_heap_block
|
||||
} HP_BLOCK;
|
||||
|
||||
struct st_heap_info; /* For reference */
|
||||
struct st_HA_KEYSEG;
|
||||
|
||||
typedef struct st_hp_keydef /* Key definition with open */
|
||||
{
|
||||
@@ -116,7 +116,7 @@ typedef struct st_hp_keydef /* Key definition with open */
|
||||
uint keysegs; /* Number of key-segment */
|
||||
uint length; /* Length of key (automatic) */
|
||||
uint8 algorithm; /* HASH / BTREE */
|
||||
HA_KEYSEG *seg;
|
||||
struct st_HA_KEYSEG *seg;
|
||||
HP_BLOCK block; /* Where keys are saved */
|
||||
/*
|
||||
Number of buckets used in hash table. Used only to provide
|
||||
|
||||
@@ -114,6 +114,7 @@ typedef struct st_json_path_t
|
||||
} json_path_t;
|
||||
|
||||
|
||||
__attribute__((nonnull, warn_unused_result))
|
||||
int json_path_setup(json_path_t *p,
|
||||
CHARSET_INFO *i_cs, const uchar *str, const uchar *end);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Copyright (c) 2001, 2013, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2022, MariaDB Corporation.
|
||||
Copyright (c) 2009, 2026, MariaDB plc.
|
||||
|
||||
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
|
||||
@@ -820,6 +820,7 @@ typedef long long my_ptrdiff_t;
|
||||
|
||||
#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1))
|
||||
#define MY_ALIGN_DOWN(A,L) ((A) & ~((L) - 1))
|
||||
|
||||
#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double))
|
||||
#define ALIGN_MAX_UNIT (sizeof(double))
|
||||
/* Size to make addressable obj. */
|
||||
@@ -1021,6 +1022,20 @@ typedef ulong myf; /* Type of MyFlags in my_funcs */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
Tag a global variable as "read-only after init". It'll be made read-only
|
||||
just before the server starts accepting connection. All READ_ONLY sysvars
|
||||
must be tagged this way.
|
||||
*/
|
||||
#if defined(HAVE_RO_AFTER_INIT) && !defined(EMBEDDED_LIBRARY)
|
||||
#define READ_ONLY_SYSVAR __attribute__((section("ro_after_init")))
|
||||
#elif defined(_MSC_VER) && !defined(EMBEDDED_LIBRARY)
|
||||
#pragma section("ro_after_init$m", read, write)
|
||||
#define READ_ONLY_SYSVAR __declspec(allocate("ro_after_init$m"))
|
||||
#else
|
||||
#define READ_ONLY_SYSVAR
|
||||
#endif
|
||||
|
||||
#include <my_dbug.h>
|
||||
|
||||
/* Some helper macros */
|
||||
|
||||
@@ -92,7 +92,7 @@ C_MODE_START
|
||||
#define MY_SYNC 4096U /* my_copy(): sync dst file */
|
||||
#define MY_SYNC_DIR 32768U /* my_create/delete/rename: sync directory */
|
||||
#define MY_THREAD_SPECIFIC 0x10000U /* my_malloc(): thread specific */
|
||||
#define MY_ROOT_USE_MPROTECT 0x20000U /* init_alloc_root: read only segments */
|
||||
#define MY_ROOT_USE_VMEM 0x20000U /* init_alloc_root: use my_virtual_mem_commit */
|
||||
/* Tree that should delete things automatically */
|
||||
#define MY_TREE_WITH_DELETE 0x40000U
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2025, MariaDB
|
||||
/* Copyright (c) 2025, 2026, MariaDB plc.
|
||||
|
||||
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
|
||||
@@ -24,12 +24,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
enum my_vmem_prot { MY_VMEM_READONLY= 0, MY_VMEM_READWRITE };
|
||||
|
||||
char *my_virtual_mem_reserve(size_t *size);
|
||||
#endif
|
||||
char *my_virtual_mem_commit(char *ptr, size_t size);
|
||||
void my_virtual_mem_decommit(char *ptr, size_t size);
|
||||
void my_virtual_mem_release(char *ptr, size_t size);
|
||||
void my_virtual_mem_protect(void *ptr, size_t size, enum my_vmem_prot prot);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Submodule libmariadb updated: df953d6b76...8153da40fe
@@ -321,4 +321,13 @@ drop table t1;
|
||||
#
|
||||
# End of 10.5 tests
|
||||
#
|
||||
#
|
||||
# MDEV-31808 Server crash upon altering table with NEXTVAL for default under exclusive lock
|
||||
#
|
||||
CREATE SEQUENCE s ENGINE=Aria;
|
||||
CREATE TABLE t (a INT DEFAULT(NEXTVAL(s)), b INT);
|
||||
ALTER TABLE t FORCE, ALGORITHM=COPY, LOCK=EXCLUSIVE;
|
||||
DROP TABLE t;
|
||||
DROP SEQUENCE s;
|
||||
# End of 10.6 tests
|
||||
set @@default_storage_engine= @save_default_engine;
|
||||
|
||||
@@ -260,4 +260,18 @@ drop table t1;
|
||||
--echo # End of 10.5 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-31808 Server crash upon altering table with NEXTVAL for default under exclusive lock
|
||||
--echo #
|
||||
|
||||
CREATE SEQUENCE s ENGINE=Aria;
|
||||
CREATE TABLE t (a INT DEFAULT(NEXTVAL(s)), b INT);
|
||||
ALTER TABLE t FORCE, ALGORITHM=COPY, LOCK=EXCLUSIVE;
|
||||
|
||||
# Cleanup
|
||||
DROP TABLE t;
|
||||
DROP SEQUENCE s;
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
|
||||
set @@default_storage_engine= @save_default_engine;
|
||||
|
||||
1
mysql-test/main/binlog_invalid_row_v2_tag.result
Normal file
1
mysql-test/main/binlog_invalid_row_v2_tag.result
Normal file
@@ -0,0 +1 @@
|
||||
FOUND 3 /[Uu]nknown [Ee]vent/ in invalid_row_v2_tag.sql
|
||||
14
mysql-test/main/binlog_invalid_row_v2_tag.test
Normal file
14
mysql-test/main/binlog_invalid_row_v2_tag.test
Normal file
@@ -0,0 +1,14 @@
|
||||
# MDEV-39485 Heap-buffer-overflow upon read in `Rows_log_event` constructor
|
||||
#
|
||||
# This binlog file contains a normal Format Description
|
||||
# Event followed by 3 malformed v2 Write Rows Events:
|
||||
# 1. A tag followed by no data
|
||||
# 2. An undersized tagged data followed by an unrecognized tag
|
||||
# 3. A tag followed by a length longer than the entire event
|
||||
|
||||
--source include/not_embedded.inc
|
||||
|
||||
--let SEARCH_PATTERN= [Uu]nknown [Ee]vent
|
||||
--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/invalid_row_v2_tag.sql
|
||||
--exec $MYSQL_BINLOG --force-read --verbose std_data/binlog_invalid_row_v2_tag.001 > $SEARCH_FILE
|
||||
--source include/search_pattern_in_file.inc
|
||||
@@ -3255,9 +3255,21 @@ HEX(a) HEX(b)
|
||||
61 62
|
||||
61 0061
|
||||
DROP TABLE t1;
|
||||
0x00 in the beginning of a value of a non-last ENUM/SET causes an error:
|
||||
0x00 in the beginning of a value of a non-last ENUM/SET (fixed by MDEV-28498):
|
||||
CREATE TABLE t1 (a ENUM('a',0x0061), b ENUM('b'));
|
||||
ERROR HY000: Incorrect information in file: 'DIR/t1.frm'
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` enum('a','\0a') DEFAULT NULL,
|
||||
`b` enum('b') DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
INSERT INTO t1 VALUES (1,1);
|
||||
INSERT INTO t1 VALUES (2,1);
|
||||
SELECT HEX(a), HEX(b) FROM t1 ORDER BY a, b;
|
||||
HEX(a) HEX(b)
|
||||
61 62
|
||||
0061 62
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.1 tests
|
||||
#
|
||||
|
||||
@@ -116,10 +116,13 @@ INSERT INTO t1 VALUES (1,2);
|
||||
SELECT HEX(a), HEX(b) FROM t1 ORDER BY a, b;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo 0x00 in the beginning of a value of a non-last ENUM/SET causes an error:
|
||||
--replace_regex /'.*t1.frm'/'DIR\/t1.frm'/
|
||||
--error ER_NOT_FORM_FILE
|
||||
--echo 0x00 in the beginning of a value of a non-last ENUM/SET (fixed by MDEV-28498):
|
||||
CREATE TABLE t1 (a ENUM('a',0x0061), b ENUM('b'));
|
||||
SHOW CREATE TABLE t1;
|
||||
INSERT INTO t1 VALUES (1,1);
|
||||
INSERT INTO t1 VALUES (2,1);
|
||||
SELECT HEX(a), HEX(b) FROM t1 ORDER BY a, b;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
|
||||
@@ -26,7 +26,8 @@ CREATE EVENT e
|
||||
|
||||
# Wait until the event worker appears in PROCESSLIST for the current user
|
||||
let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
|
||||
WHERE INFO LIKE '%SLEEP(10000)%' AND ID <> CONNECTION_ID();
|
||||
WHERE INFO LIKE '%SLEEP(10000)%' AND ID <> CONNECTION_ID()
|
||||
AND STATE='User sleep';
|
||||
--source include/wait_condition.inc
|
||||
|
||||
# Check that show processlist works
|
||||
|
||||
@@ -2956,6 +2956,133 @@ NULL
|
||||
SELECT JSON_OVERLAPS(JSON_ARRAY_INSERT(NULL,'$[0]',1), '[]') AS x;
|
||||
x
|
||||
NULL
|
||||
#
|
||||
# MDEV-32331 JSON path functions with no charset on path crash server
|
||||
#
|
||||
SELECT 1 FROM
|
||||
(SELECT CASE WHEN x * x THEN x END as a
|
||||
FROM ( SELECT json_array_append ( 'x' , ( 'x' % 'x' ) , 1 , 'x' , 1 ) as x ) dt2
|
||||
) dt
|
||||
WHERE a;
|
||||
1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
SELECT 1 FROM (SELECT CASE WHEN x * x THEN x END as a FROM ( SELECT json_array_append ( 'x' , ( 'x' % 'x' ) , 1 , 'x' , 1 ) as x ) dt2 ) dt WHERE a;
|
||||
1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
SELECT 1 FROM (SELECT CASE WHEN x * x THEN x END as a FROM ( SELECT json_array_insert ( '[1]' , ( 'x' % 'x' ) , 1 , '$[0]' , 9 ) as x ) dt2 ) dt WHERE a;
|
||||
1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
SELECT 1 FROM (SELECT CASE WHEN x * x THEN x END as a FROM ( SELECT json_insert ( '1' , ( 'x' % 'x' ) , 1 , '$.a' , 2 ) as x ) dt2 ) dt WHERE a;
|
||||
1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
SELECT 1 FROM (SELECT CASE WHEN x * x THEN x END as a FROM ( SELECT json_remove ( '[1,2]' , ( 'x' % 'x' ) , '$[0]' ) as x ) dt2 ) dt WHERE a;
|
||||
1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
SELECT 1 FROM (SELECT CASE WHEN x * x THEN x END as a FROM ( SELECT json_replace ( '1' , ( 'x' % 'x' ) , 1 , '$.a' , 2 ) as x ) dt2 ) dt WHERE a;
|
||||
1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
SELECT 1 FROM (SELECT CASE WHEN x * x THEN x END as a FROM ( SELECT json_set ( '1' , ( 'x' % 'x' ) , 1 , '$.a' , 2 ) as x ) dt2 ) dt WHERE a;
|
||||
1
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
Warning 1292 Truncated incorrect DOUBLE value: 'x'
|
||||
SELECT x FROM (SELECT 1 AS x UNION SELECT 2) AS t WHERE x IN ( SELECT JSON_REPLACE('1', UPPER(CAST(NULL AS CHAR)), 100));
|
||||
x
|
||||
SELECT ( WITH RECURSIVE x ( x ) AS (WITH RECURSIVE x ( x ) AS ( SELECT 1 UNION SELECT x + 1 FROM x ) SELECT json_array_append ( '[[], [], []]' , NOT ( NULL LIKE 'ABC%' ) , 315 )) SELECT x FROM x WHERE x > 10 AND x < 1) AS x;
|
||||
x
|
||||
NULL
|
||||
SELECT 1 FROM (SELECT JSON_REMOVE(46, DATE(NULL)) AS x EXCEPT SELECT 1) AS d WHERE NOT(NOT(x > 10)) AND (x < 1 OR x > 1);
|
||||
1
|
||||
#
|
||||
# MDEV-40572 SIGSEGV in JSON_OVERLAPS() on a truncated nested JSON object with different character sets/collations
|
||||
#
|
||||
SET @col=@@collation_connection;
|
||||
SET @char=@@character_set_connection;
|
||||
SET collation_connection=ucs2_general_ci;
|
||||
SELECT JSON_OVERLAPS ('{"B":{}}', '{"B":{') AS exp_ucs2;
|
||||
exp_ucs2
|
||||
0
|
||||
Warnings:
|
||||
Warning 4037 Unexpected end of JSON text in argument 2 to function 'json_overlaps'
|
||||
SET character_set_connection=utf16;
|
||||
SELECT JSON_OVERLAPS ('{"B":{}}', '{"B":{') AS exp_utf16;
|
||||
exp_utf16
|
||||
0
|
||||
Warnings:
|
||||
Warning 4037 Unexpected end of JSON text in argument 2 to function 'json_overlaps'
|
||||
SET @@collation_connection=@col;
|
||||
SET @@character_set_connection=@char;
|
||||
#
|
||||
# MDEV-40165 JSON_EQUAL/JSON_NORMALIZE/JSON_CONTAINS error handling
|
||||
#
|
||||
CREATE TABLE t(c1 JSON, c2 JSON);
|
||||
INSERT INTO t VALUES ('{"a":1,"b":2}', '{"b":2E0, "a":1E0}'),
|
||||
(NULL, '["a", "b"]'),
|
||||
('{"r": 1}', NULL),
|
||||
('[{"a": 3}, {"d": [1, 2, 3]}]', '[{"d": [1E0, 2E0, 3E0]}, {"a":3E0}]');
|
||||
SELECT c1, JSON_EQUALS(c1, '{"r": 1E0}') AS je_c1_const FROM t;
|
||||
c1 je_c1_const
|
||||
{"a":1,"b":2} 0
|
||||
NULL NULL
|
||||
{"r": 1} 1
|
||||
[{"a": 3}, {"d": [1, 2, 3]}] 0
|
||||
SELECT c1, c2, JSON_EQUALS(c1, c2) AS je_c1_c2 FROM t;
|
||||
c1 c2 je_c1_c2
|
||||
{"a":1,"b":2} {"b":2E0, "a":1E0} 1
|
||||
NULL ["a", "b"] NULL
|
||||
{"r": 1} NULL NULL
|
||||
[{"a": 3}, {"d": [1, 2, 3]}] [{"d": [1E0, 2E0, 3E0]}, {"a":3E0}] 0
|
||||
SELECT c1, JSON_CONTAINS(c1, '{"r": 1E0}') AS jc_c1_const FROM t;
|
||||
c1 jc_c1_const
|
||||
{"a":1,"b":2} 0
|
||||
NULL NULL
|
||||
{"r": 1} 1
|
||||
[{"a": 3}, {"d": [1, 2, 3]}] 0
|
||||
SELECT c1, c2, JSON_CONTAINS(c1, c2) AS jc_c1_c2 FROM t;
|
||||
c1 c2 jc_c1_c2
|
||||
{"a":1,"b":2} {"b":2E0, "a":1E0} 1
|
||||
NULL ["a", "b"] NULL
|
||||
{"r": 1} NULL NULL
|
||||
[{"a": 3}, {"d": [1, 2, 3]}] [{"d": [1E0, 2E0, 3E0]}, {"a":3E0}] 1
|
||||
SELECT c1, JSON_OVERLAPS(c1, '{"r": 1E0}') AS jo_c1_const FROM t;
|
||||
c1 jo_c1_const
|
||||
{"a":1,"b":2} 0
|
||||
NULL NULL
|
||||
{"r": 1} 1
|
||||
[{"a": 3}, {"d": [1, 2, 3]}] 0
|
||||
SELECT c1, c2, JSON_OVERLAPS(c1, c2) AS jo_c1_c2 FROM t;
|
||||
c1 c2 jo_c1_c2
|
||||
{"a":1,"b":2} {"b":2E0, "a":1E0} 1
|
||||
NULL ["a", "b"] NULL
|
||||
{"r": 1} NULL NULL
|
||||
[{"a": 3}, {"d": [1, 2, 3]}] [{"d": [1E0, 2E0, 3E0]}, {"a":3E0}] 1
|
||||
DROP TABLE t;
|
||||
# End of 10.11 Test
|
||||
#
|
||||
# MDEV-32007: JSON_VALUE and JSON_EXTRACT doesn't handle dash (-)
|
||||
|
||||
@@ -2104,6 +2104,61 @@ SELECT JSON_ARRAY_INSERT (0,NULL,1) as j;
|
||||
SELECT JSON_EQUALS('[]', JSON_ARRAY_INSERT(NULL,'$[0]',1)) AS x;
|
||||
SELECT JSON_OVERLAPS(JSON_ARRAY_INSERT(NULL,'$[0]',1), '[]') AS x;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-32331 JSON path functions with no charset on path crash server
|
||||
--echo #
|
||||
|
||||
SELECT 1 FROM
|
||||
(SELECT CASE WHEN x * x THEN x END as a
|
||||
FROM ( SELECT json_array_append ( 'x' , ( 'x' % 'x' ) , 1 , 'x' , 1 ) as x ) dt2
|
||||
) dt
|
||||
WHERE a;
|
||||
SELECT 1 FROM (SELECT CASE WHEN x * x THEN x END as a FROM ( SELECT json_array_append ( 'x' , ( 'x' % 'x' ) , 1 , 'x' , 1 ) as x ) dt2 ) dt WHERE a;
|
||||
SELECT 1 FROM (SELECT CASE WHEN x * x THEN x END as a FROM ( SELECT json_array_insert ( '[1]' , ( 'x' % 'x' ) , 1 , '$[0]' , 9 ) as x ) dt2 ) dt WHERE a;
|
||||
SELECT 1 FROM (SELECT CASE WHEN x * x THEN x END as a FROM ( SELECT json_insert ( '1' , ( 'x' % 'x' ) , 1 , '$.a' , 2 ) as x ) dt2 ) dt WHERE a;
|
||||
SELECT 1 FROM (SELECT CASE WHEN x * x THEN x END as a FROM ( SELECT json_remove ( '[1,2]' , ( 'x' % 'x' ) , '$[0]' ) as x ) dt2 ) dt WHERE a;
|
||||
SELECT 1 FROM (SELECT CASE WHEN x * x THEN x END as a FROM ( SELECT json_replace ( '1' , ( 'x' % 'x' ) , 1 , '$.a' , 2 ) as x ) dt2 ) dt WHERE a;
|
||||
SELECT 1 FROM (SELECT CASE WHEN x * x THEN x END as a FROM ( SELECT json_set ( '1' , ( 'x' % 'x' ) , 1 , '$.a' , 2 ) as x ) dt2 ) dt WHERE a;
|
||||
|
||||
SELECT x FROM (SELECT 1 AS x UNION SELECT 2) AS t WHERE x IN ( SELECT JSON_REPLACE('1', UPPER(CAST(NULL AS CHAR)), 100));
|
||||
SELECT ( WITH RECURSIVE x ( x ) AS (WITH RECURSIVE x ( x ) AS ( SELECT 1 UNION SELECT x + 1 FROM x ) SELECT json_array_append ( '[[], [], []]' , NOT ( NULL LIKE 'ABC%' ) , 315 )) SELECT x FROM x WHERE x > 10 AND x < 1) AS x;
|
||||
SELECT 1 FROM (SELECT JSON_REMOVE(46, DATE(NULL)) AS x EXCEPT SELECT 1) AS d WHERE NOT(NOT(x > 10)) AND (x < 1 OR x > 1);
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40572 SIGSEGV in JSON_OVERLAPS() on a truncated nested JSON object with different character sets/collations
|
||||
--echo #
|
||||
|
||||
SET @col=@@collation_connection;
|
||||
SET @char=@@character_set_connection;
|
||||
|
||||
SET collation_connection=ucs2_general_ci;
|
||||
SELECT JSON_OVERLAPS ('{"B":{}}', '{"B":{') AS exp_ucs2;
|
||||
SET character_set_connection=utf16;
|
||||
SELECT JSON_OVERLAPS ('{"B":{}}', '{"B":{') AS exp_utf16;
|
||||
|
||||
SET @@collation_connection=@col;
|
||||
SET @@character_set_connection=@char;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40165 JSON_EQUAL/JSON_NORMALIZE/JSON_CONTAINS error handling
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t(c1 JSON, c2 JSON);
|
||||
INSERT INTO t VALUES ('{"a":1,"b":2}', '{"b":2E0, "a":1E0}'),
|
||||
(NULL, '["a", "b"]'),
|
||||
('{"r": 1}', NULL),
|
||||
('[{"a": 3}, {"d": [1, 2, 3]}]', '[{"d": [1E0, 2E0, 3E0]}, {"a":3E0}]');
|
||||
|
||||
SELECT c1, JSON_EQUALS(c1, '{"r": 1E0}') AS je_c1_const FROM t;
|
||||
SELECT c1, c2, JSON_EQUALS(c1, c2) AS je_c1_c2 FROM t;
|
||||
|
||||
SELECT c1, JSON_CONTAINS(c1, '{"r": 1E0}') AS jc_c1_const FROM t;
|
||||
SELECT c1, c2, JSON_CONTAINS(c1, c2) AS jc_c1_c2 FROM t;
|
||||
|
||||
SELECT c1, JSON_OVERLAPS(c1, '{"r": 1E0}') AS jo_c1_const FROM t;
|
||||
SELECT c1, c2, JSON_OVERLAPS(c1, c2) AS jo_c1_c2 FROM t;
|
||||
DROP TABLE t;
|
||||
|
||||
--echo # End of 10.11 Test
|
||||
|
||||
--echo #
|
||||
|
||||
@@ -459,13 +459,8 @@ select sformat('{:f}', @a);
|
||||
sformat('{:f}', @a)
|
||||
3.140000
|
||||
set names latin1;
|
||||
#
|
||||
# End of 10.7 tests
|
||||
#
|
||||
#
|
||||
# Start of 10.8 tests
|
||||
#
|
||||
#
|
||||
# MDEV-29646 sformat('Num [{:20}]', 42) gives incorrect result in view
|
||||
#
|
||||
create view v1 as select sformat('Num [{:20}]', 42);
|
||||
@@ -498,4 +493,36 @@ bar 2
|
||||
foo 1
|
||||
drop view v;
|
||||
drop table t;
|
||||
#
|
||||
# MDEV-40411 SFORMAT ignores max_allowed_packet
|
||||
#
|
||||
set @old_max_allowed_packet=@@global.max_allowed_packet;
|
||||
set @@global.max_allowed_packet=512*1024;
|
||||
connect u,localhost,root;
|
||||
select length(sformat('{:2147483647}', 1));
|
||||
length(sformat('{:2147483647}', 1))
|
||||
NULL
|
||||
select length(sformat('{:524288}', 1));
|
||||
length(sformat('{:524288}', 1))
|
||||
524288
|
||||
select length(sformat('{:524289}', 1));
|
||||
length(sformat('{:524289}', 1))
|
||||
NULL
|
||||
select length(sformat('{:524287}.', 1));
|
||||
length(sformat('{:524287}.', 1))
|
||||
524288
|
||||
select length(sformat('{:524287}..', 1));
|
||||
length(sformat('{:524287}..', 1))
|
||||
NULL
|
||||
disconnect u;
|
||||
connection default;
|
||||
set @@global.max_allowed_packet= @old_max_allowed_packet;
|
||||
set max_session_mem_used=512*1024;
|
||||
select length(sformat('{:524288}', 1));
|
||||
length(sformat('{:524288}', 1))
|
||||
524288
|
||||
select length(sformat('{:524289}', 1));
|
||||
length(sformat('{:524289}', 1))
|
||||
NULL
|
||||
set max_session_mem_used=default;
|
||||
# End of 10.11 tests
|
||||
|
||||
@@ -236,13 +236,7 @@ set @a=3.14;
|
||||
select sformat('{:f}', @a);
|
||||
set names latin1;
|
||||
|
||||
echo #;
|
||||
echo # End of 10.7 tests;
|
||||
echo #;
|
||||
|
||||
echo #;
|
||||
echo # Start of 10.8 tests;
|
||||
echo #;
|
||||
|
||||
echo #;
|
||||
echo # MDEV-29646 sformat('Num [{:20}]', 42) gives incorrect result in view;
|
||||
@@ -274,4 +268,30 @@ select * from v where a != sformat('{}', 'qux');
|
||||
drop view v;
|
||||
drop table t;
|
||||
|
||||
echo #;
|
||||
echo # MDEV-40411 SFORMAT ignores max_allowed_packet;
|
||||
echo #;
|
||||
set @old_max_allowed_packet=@@global.max_allowed_packet;
|
||||
set @@global.max_allowed_packet=512*1024;
|
||||
connect u,localhost,root;
|
||||
# these three case: fmt allocates the requested size at once
|
||||
select length(sformat('{:2147483647}', 1));
|
||||
select length(sformat('{:524288}', 1));
|
||||
select length(sformat('{:524289}', 1));
|
||||
# here it allocates 524287 and then grows by *1.5
|
||||
select length(sformat('{:524287}.', 1));
|
||||
select length(sformat('{:524287}..', 1));
|
||||
disconnect u;
|
||||
connection default;
|
||||
set @@global.max_allowed_packet= @old_max_allowed_packet;
|
||||
|
||||
disable_cursor_protocol;
|
||||
disable_view_protocol;
|
||||
set max_session_mem_used=512*1024;
|
||||
select length(sformat('{:524288}', 1));
|
||||
select length(sformat('{:524289}', 1));
|
||||
set max_session_mem_used=default;
|
||||
enable_view_protocol;
|
||||
enable_cursor_protocol;
|
||||
|
||||
echo # End of 10.11 tests;
|
||||
|
||||
@@ -110,6 +110,8 @@ Warning 4076 Incorrect GeoJSON format - empty 'coordinates' array.
|
||||
SELECT ST_GEOMFROMGEOJSON("{ \"type\": \"Feature\", \"geometry\": [10, 20] }") as exp;
|
||||
exp
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 4048 Incorrect GeoJSON format specified for st_geomfromgeojson function.
|
||||
SELECT ST_ASTEXT (ST_GEOMFROMGEOJSON ('{ "type": "GEOMETRYCOLLECTION", "coordinates": [102.0, 0.0]}')) as exp;
|
||||
exp
|
||||
NULL
|
||||
@@ -135,7 +137,126 @@ repeat(']}', 2000)
|
||||
exp
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 4040 Limit of 32 on JSON nested structures depth is reached in argument 1 to function 'st_geomfromgeojson' at position 473
|
||||
Warning 4040 Limit of 32 on JSON nested structures depth is reached in argument 1 to function 'st_geomfromgeojson' at position 688
|
||||
# Boundary condition: foreign-member nesting at depth 32
|
||||
SET @geom := '{"type":"Point","coordinates":[1,2]}';
|
||||
SET @doc := CONCAT(
|
||||
REPEAT('{"x":', 29),
|
||||
@geom,
|
||||
REPEAT('}', 29)
|
||||
);
|
||||
SELECT ST_ASTEXT( ST_GeomFromGeoJSON(@doc) ) AS expr;
|
||||
expr
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 4048 Incorrect GeoJSON format specified for st_geomfromgeojson function.
|
||||
# Foreign-member nesting exceeds depth 32
|
||||
SET @geom := '{"type":"Point","coordinates":[1,2]}';
|
||||
SET @doc := CONCAT(
|
||||
REPEAT('{"x":', 30),
|
||||
@geom,
|
||||
REPEAT('}', 30)
|
||||
);
|
||||
SELECT ST_GeomFromGeoJSON(@doc) AS expr;
|
||||
expr
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 4040 Limit of 32 on JSON nested structures depth is reached in argument 1 to function 'st_geomfromgeojson' at position 181
|
||||
# Deep foreign member attached to otherwise valid GeoJSON
|
||||
SET @foreign := CONCAT(
|
||||
REPEAT('{"x":', 28),
|
||||
'{"leaf":1}',
|
||||
REPEAT('}', 28)
|
||||
);
|
||||
SET @doc := CONCAT(
|
||||
'{"type":"Point","coordinates":[10,20],"foreign":',
|
||||
@foreign,
|
||||
'}'
|
||||
);
|
||||
SELECT ST_ASTEXT(ST_GeomFromGeoJSON(@doc)) AS expr;
|
||||
expr
|
||||
POINT(10 20)
|
||||
# Foreign member exceeds depth limit
|
||||
SET @foreign := CONCAT(
|
||||
REPEAT('{"x":', 29),
|
||||
'{"leaf":1}',
|
||||
REPEAT('}', 29)
|
||||
);
|
||||
SET @doc := CONCAT(
|
||||
'{"type":"Point","coordinates":[10,20],"foreign":',
|
||||
@foreign,
|
||||
'}'
|
||||
);
|
||||
SELECT ST_ASTEXT(ST_GeomFromGeoJSON(@doc)) AS expr;
|
||||
expr
|
||||
POINT(10 20)
|
||||
# GeometryCollection containing 33 valid GeoJSON Point objects
|
||||
SET @point := '{"type":"Point","coordinates":[1,2]}';
|
||||
SET @geoms := CONCAT(
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point
|
||||
);
|
||||
SET @doc := CONCAT(
|
||||
'{"type":"GeometryCollection","geometries":[',
|
||||
@geoms,
|
||||
']}'
|
||||
);
|
||||
SELECT ST_AsText(ST_GeomFromGeoJSON(@doc)) AS expr;
|
||||
expr
|
||||
GEOMETRYCOLLECTION(POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2),POINT(1 2))
|
||||
#
|
||||
# MDEV-39981: ST_GEOMFROMGEOJSON returns wrong result with reversed key order
|
||||
#
|
||||
# GeometryCollection: type before geometries (baseline)
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"type":"GeometryCollection","geometries":[]}')) as expr;
|
||||
expr
|
||||
GEOMETRYCOLLECTION EMPTY
|
||||
# GeometryCollection: geometries before type (empty)
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[],"type":"GeometryCollection"}')) as expr;
|
||||
expr
|
||||
GEOMETRYCOLLECTION EMPTY
|
||||
# GeometryCollection: geometries before type (non-empty)
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"type":"Point","coordinates":[0,1]}],"type":"GeometryCollection"}')) as expr;
|
||||
expr
|
||||
GEOMETRYCOLLECTION(POINT(0 1))
|
||||
# GeometryCollection: multiple geometries before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"type":"Point","coordinates":[1,2]},{"type":"Point","coordinates":[3,4]}],"type":"GeometryCollection"}')) as expr;
|
||||
expr
|
||||
GEOMETRYCOLLECTION(POINT(1 2),POINT(3 4))
|
||||
# Point: coordinates before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"coordinates":[0,1],"type":"Point"}')) as expr;
|
||||
expr
|
||||
POINT(0 1)
|
||||
# LineString: coordinates before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"coordinates":[[0,0],[1,1],[2,2]],"type":"LineString"}')) as expr;
|
||||
expr
|
||||
LINESTRING(0 0,1 1,2 2)
|
||||
# Polygon: coordinates before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"coordinates":[[[0,0],[1,0],[1,1],[0,1],[0,0]]],"type":"Polygon"}')) as expr;
|
||||
expr
|
||||
POLYGON((0 0,1 0,1 1,0 1,0 0))
|
||||
# FeatureCollection: features before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"features":[{"geometry":{"type":"Point","coordinates":[5,6]},"type":"Feature","properties":{}}],"type":"FeatureCollection"}')) as expr;
|
||||
expr
|
||||
GEOMETRYCOLLECTION(POINT(5 6))
|
||||
# Feature: geometry before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometry":{"coordinates":[7,8],"type":"Point"},"type":"Feature","properties":{}}')) as expr;
|
||||
expr
|
||||
POINT(7 8)
|
||||
# Unknown keys interspersed (should be ignored)
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"foo":"bar","geometries":[],"type":"GeometryCollection","extra":123}')) as expr;
|
||||
expr
|
||||
GEOMETRYCOLLECTION EMPTY
|
||||
# Deeply nested geometries before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"geometries":[{"type":"Point","coordinates":[9,10]}],"type":"GeometryCollection"}],"type":"GeometryCollection"}')) as expr;
|
||||
expr
|
||||
GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(9 10)))
|
||||
# End of 10.6 tests
|
||||
#
|
||||
# MDEV-34079: ST_AsGeoJSON returns incorrect value for empty geometry
|
||||
|
||||
@@ -70,6 +70,120 @@ SELECT ST_GeomFromGeoJSON(
|
||||
repeat(']}', 2000)
|
||||
)) as exp;
|
||||
|
||||
--echo # Boundary condition: foreign-member nesting at depth 32
|
||||
SET @geom := '{"type":"Point","coordinates":[1,2]}';
|
||||
|
||||
SET @doc := CONCAT(
|
||||
REPEAT('{"x":', 29),
|
||||
@geom,
|
||||
REPEAT('}', 29)
|
||||
);
|
||||
|
||||
SELECT ST_ASTEXT( ST_GeomFromGeoJSON(@doc) ) AS expr;
|
||||
|
||||
|
||||
--echo # Foreign-member nesting exceeds depth 32
|
||||
SET @geom := '{"type":"Point","coordinates":[1,2]}';
|
||||
|
||||
SET @doc := CONCAT(
|
||||
REPEAT('{"x":', 30),
|
||||
@geom,
|
||||
REPEAT('}', 30)
|
||||
);
|
||||
|
||||
SELECT ST_GeomFromGeoJSON(@doc) AS expr;
|
||||
|
||||
|
||||
--echo # Deep foreign member attached to otherwise valid GeoJSON
|
||||
SET @foreign := CONCAT(
|
||||
REPEAT('{"x":', 28),
|
||||
'{"leaf":1}',
|
||||
REPEAT('}', 28)
|
||||
);
|
||||
|
||||
SET @doc := CONCAT(
|
||||
'{"type":"Point","coordinates":[10,20],"foreign":',
|
||||
@foreign,
|
||||
'}'
|
||||
);
|
||||
|
||||
SELECT ST_ASTEXT(ST_GeomFromGeoJSON(@doc)) AS expr;
|
||||
|
||||
|
||||
--echo # Foreign member exceeds depth limit
|
||||
SET @foreign := CONCAT(
|
||||
REPEAT('{"x":', 29),
|
||||
'{"leaf":1}',
|
||||
REPEAT('}', 29)
|
||||
);
|
||||
|
||||
SET @doc := CONCAT(
|
||||
'{"type":"Point","coordinates":[10,20],"foreign":',
|
||||
@foreign,
|
||||
'}'
|
||||
);
|
||||
|
||||
SELECT ST_ASTEXT(ST_GeomFromGeoJSON(@doc)) AS expr;
|
||||
|
||||
--echo # GeometryCollection containing 33 valid GeoJSON Point objects
|
||||
SET @point := '{"type":"Point","coordinates":[1,2]}';
|
||||
|
||||
SET @geoms := CONCAT(
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point, ',', @point, ',', @point, ',',
|
||||
@point, ',', @point, ',', @point
|
||||
);
|
||||
|
||||
SET @doc := CONCAT(
|
||||
'{"type":"GeometryCollection","geometries":[',
|
||||
@geoms,
|
||||
']}'
|
||||
);
|
||||
|
||||
SELECT ST_AsText(ST_GeomFromGeoJSON(@doc)) AS expr;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39981: ST_GEOMFROMGEOJSON returns wrong result with reversed key order
|
||||
--echo #
|
||||
|
||||
--echo # GeometryCollection: type before geometries (baseline)
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"type":"GeometryCollection","geometries":[]}')) as expr;
|
||||
|
||||
--echo # GeometryCollection: geometries before type (empty)
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[],"type":"GeometryCollection"}')) as expr;
|
||||
|
||||
--echo # GeometryCollection: geometries before type (non-empty)
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"type":"Point","coordinates":[0,1]}],"type":"GeometryCollection"}')) as expr;
|
||||
|
||||
--echo # GeometryCollection: multiple geometries before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"type":"Point","coordinates":[1,2]},{"type":"Point","coordinates":[3,4]}],"type":"GeometryCollection"}')) as expr;
|
||||
|
||||
--echo # Point: coordinates before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"coordinates":[0,1],"type":"Point"}')) as expr;
|
||||
|
||||
--echo # LineString: coordinates before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"coordinates":[[0,0],[1,1],[2,2]],"type":"LineString"}')) as expr;
|
||||
|
||||
--echo # Polygon: coordinates before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"coordinates":[[[0,0],[1,0],[1,1],[0,1],[0,0]]],"type":"Polygon"}')) as expr;
|
||||
|
||||
--echo # FeatureCollection: features before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"features":[{"geometry":{"type":"Point","coordinates":[5,6]},"type":"Feature","properties":{}}],"type":"FeatureCollection"}')) as expr;
|
||||
|
||||
--echo # Feature: geometry before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometry":{"coordinates":[7,8],"type":"Point"},"type":"Feature","properties":{}}')) as expr;
|
||||
|
||||
--echo # Unknown keys interspersed (should be ignored)
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"foo":"bar","geometries":[],"type":"GeometryCollection","extra":123}')) as expr;
|
||||
|
||||
--echo # Deeply nested geometries before type
|
||||
SELECT ST_ASTEXT(ST_GEOMFROMGEOJSON('{"geometries":[{"geometries":[{"type":"Point","coordinates":[9,10]}],"type":"GeometryCollection"}],"type":"GeometryCollection"}')) as expr;
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
|
||||
--echo #
|
||||
|
||||
@@ -881,6 +881,66 @@ SELECT ST_CROSSES( ST_GEOMFROMTEXT('POLYGON ((59 18,67 18,67 13,59 13,59 18)) ')
|
||||
a
|
||||
NULL
|
||||
#
|
||||
# MDEV-40584 ST_CROSSES always returns 0 for geometries of different dimensions
|
||||
#
|
||||
SELECT ST_Crosses(ST_GeomFromText('MULTIPOINT(1 3, 2 2, 3 2)'),
|
||||
ST_GeomFromText('LINESTRING(0 3, 1 1, 2 2, 2 0)')) a;
|
||||
a
|
||||
1
|
||||
SELECT ST_Crosses(ST_GeomFromText('MULTIPOINT(1 1, 1 3, 2 3)'),
|
||||
ST_GeomFromText('POLYGON((0 0, 0 3, 2 0, 0 0))')) a;
|
||||
a
|
||||
1
|
||||
SELECT ST_Crosses(ST_GeomFromText('LINESTRING(0 1, 3 2, 4 1)'),
|
||||
ST_GeomFromText('POLYGON((1 0, 1 2, 2 3, 2 1, 1 0))')) a;
|
||||
a
|
||||
1
|
||||
# line x line, crossing (dims 1,1) -> 1
|
||||
SELECT ST_Crosses(ST_GeomFromText('LINESTRING(0 0, 2 2)'),
|
||||
ST_GeomFromText('LINESTRING(0 2, 2 0)')) a;
|
||||
a
|
||||
1
|
||||
# line x line, not crossing (dims 1,1) -> 0
|
||||
SELECT ST_Crosses(ST_GeomFromText('LINESTRING(0 0, 2 0)'),
|
||||
ST_GeomFromText('LINESTRING(0 1, 2 1)')) a;
|
||||
a
|
||||
0
|
||||
# point x line, disjoint (dims 0,1) -> 0
|
||||
SELECT ST_Crosses(ST_GeomFromText('MULTIPOINT(10 10)'),
|
||||
ST_GeomFromText('LINESTRING(0 0, 1 1)')) a;
|
||||
a
|
||||
0
|
||||
# point x polygon, disjoint (dims 0,2) -> 0
|
||||
SELECT ST_Crosses(ST_GeomFromText('MULTIPOINT(100 100)'),
|
||||
ST_GeomFromText('POLYGON((0 0, 0 3, 2 0, 0 0))')) a;
|
||||
a
|
||||
0
|
||||
# line x point (g2 is a point) -> NULL
|
||||
SELECT ST_Crosses(ST_GeomFromText('LINESTRING(0 0, 1 1)'),
|
||||
ST_GeomFromText('POINT(5 5)')) a;
|
||||
a
|
||||
NULL
|
||||
# line x multipoint (g2 is a multipoint) -> NULL
|
||||
SELECT ST_Crosses(ST_GeomFromText('LINESTRING(0 0, 5 5)'),
|
||||
ST_GeomFromText('MULTIPOINT(1 1, 2 2)')) a;
|
||||
a
|
||||
NULL
|
||||
# multipolygon x line (g1 is a multipolygon) -> NULL
|
||||
SELECT ST_Crosses(ST_GeomFromText('MULTIPOLYGON(((0 0, 0 3, 3 3, 3 0, 0 0)))'),
|
||||
ST_GeomFromText('LINESTRING(1 1, 2 2)')) a;
|
||||
a
|
||||
NULL
|
||||
# polygon x line, reversed order of a valid crossing case -> NULL
|
||||
SELECT ST_Crosses(ST_GeomFromText('POLYGON((1 0, 1 2, 2 3, 2 1, 1 0))'),
|
||||
ST_GeomFromText('LINESTRING(0 1, 3 2, 4 1)')) a;
|
||||
a
|
||||
NULL
|
||||
# line x same line, equal (not lower-dim intersection) -> 0
|
||||
SELECT ST_Crosses(ST_GeomFromText('LINESTRING(0 0, 2 2)'),
|
||||
ST_GeomFromText('LINESTRING(0 0, 2 2)')) a;
|
||||
a
|
||||
0
|
||||
#
|
||||
# MDEV-31267 Server crash or assertion failure in get_n_sincos with nested ST_BUFFER.
|
||||
#
|
||||
set @geom=ST_BUFFER(ST_BUFFER(ST_POLYGONFROMTEXT('POLYGON((0 0, 5 5, 6 6, 0 0))'),1),2);
|
||||
|
||||
@@ -494,6 +494,45 @@ SELECT ST_CROSSES( ST_GEOMFROMTEXT('point(1 1)'), st_geomfromtext('point(1 1)')
|
||||
SELECT ST_CROSSES( ST_GEOMFROMTEXT('POLYGON ((59 18,67 18,67 13,59 13,59 18)) '), st_geomfromtext('polygon((2 2,2 4, 4 2,2 2))') ) a;
|
||||
SELECT ST_CROSSES( ST_GEOMFROMTEXT('POLYGON ((59 18,67 18,67 13,59 13,59 18)) '), st_geomfromtext('point(1 1)') ) a;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40584 ST_CROSSES always returns 0 for geometries of different dimensions
|
||||
--echo #
|
||||
|
||||
SELECT ST_Crosses(ST_GeomFromText('MULTIPOINT(1 3, 2 2, 3 2)'),
|
||||
ST_GeomFromText('LINESTRING(0 3, 1 1, 2 2, 2 0)')) a;
|
||||
SELECT ST_Crosses(ST_GeomFromText('MULTIPOINT(1 1, 1 3, 2 3)'),
|
||||
ST_GeomFromText('POLYGON((0 0, 0 3, 2 0, 0 0))')) a;
|
||||
SELECT ST_Crosses(ST_GeomFromText('LINESTRING(0 1, 3 2, 4 1)'),
|
||||
ST_GeomFromText('POLYGON((1 0, 1 2, 2 3, 2 1, 1 0))')) a;
|
||||
|
||||
--echo # line x line, crossing (dims 1,1) -> 1
|
||||
SELECT ST_Crosses(ST_GeomFromText('LINESTRING(0 0, 2 2)'),
|
||||
ST_GeomFromText('LINESTRING(0 2, 2 0)')) a;
|
||||
--echo # line x line, not crossing (dims 1,1) -> 0
|
||||
SELECT ST_Crosses(ST_GeomFromText('LINESTRING(0 0, 2 0)'),
|
||||
ST_GeomFromText('LINESTRING(0 1, 2 1)')) a;
|
||||
--echo # point x line, disjoint (dims 0,1) -> 0
|
||||
SELECT ST_Crosses(ST_GeomFromText('MULTIPOINT(10 10)'),
|
||||
ST_GeomFromText('LINESTRING(0 0, 1 1)')) a;
|
||||
--echo # point x polygon, disjoint (dims 0,2) -> 0
|
||||
SELECT ST_Crosses(ST_GeomFromText('MULTIPOINT(100 100)'),
|
||||
ST_GeomFromText('POLYGON((0 0, 0 3, 2 0, 0 0))')) a;
|
||||
--echo # line x point (g2 is a point) -> NULL
|
||||
SELECT ST_Crosses(ST_GeomFromText('LINESTRING(0 0, 1 1)'),
|
||||
ST_GeomFromText('POINT(5 5)')) a;
|
||||
--echo # line x multipoint (g2 is a multipoint) -> NULL
|
||||
SELECT ST_Crosses(ST_GeomFromText('LINESTRING(0 0, 5 5)'),
|
||||
ST_GeomFromText('MULTIPOINT(1 1, 2 2)')) a;
|
||||
--echo # multipolygon x line (g1 is a multipolygon) -> NULL
|
||||
SELECT ST_Crosses(ST_GeomFromText('MULTIPOLYGON(((0 0, 0 3, 3 3, 3 0, 0 0)))'),
|
||||
ST_GeomFromText('LINESTRING(1 1, 2 2)')) a;
|
||||
--echo # polygon x line, reversed order of a valid crossing case -> NULL
|
||||
SELECT ST_Crosses(ST_GeomFromText('POLYGON((1 0, 1 2, 2 3, 2 1, 1 0))'),
|
||||
ST_GeomFromText('LINESTRING(0 1, 3 2, 4 1)')) a;
|
||||
--echo # line x same line, equal (not lower-dim intersection) -> 0
|
||||
SELECT ST_Crosses(ST_GeomFromText('LINESTRING(0 0, 2 2)'),
|
||||
ST_GeomFromText('LINESTRING(0 0, 2 2)')) a;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-31267 Server crash or assertion failure in get_n_sincos with nested ST_BUFFER.
|
||||
--echo #
|
||||
|
||||
@@ -5644,4 +5644,13 @@ NULL
|
||||
SELECT ST_GEOMFROMWKB (0x01050000000100000082040000000100000000000000000000000000000000000000) as g;
|
||||
g
|
||||
NULL
|
||||
#
|
||||
# MDEV-40552 UBSAN : load of value X, which is not a valid value for type 'wkbByteOrder' Gis_multi_point::init_from_wkb
|
||||
#
|
||||
SELECT ST_GEOMFROMWKB (0x0104000000010000000201000000000000000000000000000000000000000000000000) as multipoint_bad_inner_bo;
|
||||
multipoint_bad_inner_bo
|
||||
NULL
|
||||
SELECT ST_GEOMFROMWKB (0x0104000000010000008201000000000000000000000000000000000000000000000000) as multipoint_bad_inner_bo;
|
||||
multipoint_bad_inner_bo
|
||||
NULL
|
||||
# End of 10.11 tests
|
||||
|
||||
@@ -3605,4 +3605,11 @@ SELECT ST_GEOMFROMWKB (0x01070000000100000082010000000000000000000000) as g;
|
||||
SELECT ST_GEOMFROMWKB (0x01050000000100000002040000000100000000000000000000000000000000000000) as g;
|
||||
SELECT ST_GEOMFROMWKB (0x01050000000100000082040000000100000000000000000000000000000000000000) as g;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40552 UBSAN : load of value X, which is not a valid value for type 'wkbByteOrder' Gis_multi_point::init_from_wkb
|
||||
--echo #
|
||||
|
||||
SELECT ST_GEOMFROMWKB (0x0104000000010000000201000000000000000000000000000000000000000000000000) as multipoint_bad_inner_bo;
|
||||
SELECT ST_GEOMFROMWKB (0x0104000000010000008201000000000000000000000000000000000000000000000000) as multipoint_bad_inner_bo;
|
||||
|
||||
--echo # End of 10.11 tests
|
||||
|
||||
@@ -497,6 +497,34 @@ CREATE USER for u2@localhost
|
||||
CREATE USER `u2`@`localhost` IDENTIFIED BY PASSWORD '*975B2CD4FF9AE554FE8AD33168FBFC326D2021DD'
|
||||
drop user u1@localhost;
|
||||
drop user u2@localhost;
|
||||
#
|
||||
# MDEV-40541 role vs user@localhost acl_cache key confusion
|
||||
#
|
||||
create database db;
|
||||
create table db.t1(a varchar(40));
|
||||
insert into db.t1 values ('role-cache-collision-row');
|
||||
create role r1;
|
||||
create user r1@localhost identified by 'r1pass';
|
||||
create user u1@'127.0.0.1' identified by 'u1pass';
|
||||
grant select on db.* to r1@localhost;
|
||||
grant r1 to u1@'127.0.0.1';
|
||||
connect r1,localhost,r1,r1pass;
|
||||
select a as precache from db.t1;
|
||||
precache
|
||||
role-cache-collision-row
|
||||
connect u1,127.0.0.1,u1,u1pass;
|
||||
set role r1;
|
||||
show grants;
|
||||
Grants for u1@127.0.0.1
|
||||
GRANT `r1` TO `u1`@`127.0.0.1`
|
||||
GRANT USAGE ON *.* TO `u1`@`127.0.0.1` IDENTIFIED BY PASSWORD '*4C5C0A2C80D7567C7CFBDFC09409901AADC4B390'
|
||||
GRANT USAGE ON *.* TO `r1`
|
||||
select a from db.t1;
|
||||
ERROR 42000: SELECT command denied to user 'u1'@'localhost' for table `db`.`t1`
|
||||
connection default;
|
||||
drop database db;
|
||||
drop role r1;
|
||||
drop user r1@localhost, u1@'127.0.0.1';
|
||||
# End of 10.6 tests
|
||||
#
|
||||
# MDEV-37256: The permission check of LOAD INDEX INTO CACHE and CACHE INDEX is broken
|
||||
@@ -519,4 +547,50 @@ disconnect foo;
|
||||
connection default;
|
||||
drop table t1;
|
||||
drop user foo@localhost;
|
||||
#
|
||||
# MDEV-23086 Error codes/messages reveal information about table structure
|
||||
#
|
||||
create database db;
|
||||
create table db.t1 (a int, b int, c int);
|
||||
create user foo@localhost;
|
||||
grant select (a,b) on db.t1 to foo@localhost;
|
||||
alter table db.t1 drop column b;
|
||||
create table db.t2 (x int, y int);
|
||||
grant select on db.t2 to foo@localhost;
|
||||
create table t1 (k int, l int, m int);
|
||||
grant select on test.t1 to foo@localhost;
|
||||
connect con1,localhost,foo,,db;
|
||||
select a from t1;
|
||||
a
|
||||
select b from t1;
|
||||
ERROR 42S22: Unknown column 'b' in 'SELECT'
|
||||
select c from t1;
|
||||
ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'c' in table 't1'
|
||||
select d from t1;
|
||||
ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'd' in table 't1'
|
||||
select a from t0;
|
||||
ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table `db`.`t0`
|
||||
use db2;
|
||||
ERROR 42000: Access denied for user 'foo'@'localhost' to database 'db2'
|
||||
select a from t2;
|
||||
ERROR 42S22: Unknown column 'a' in 'SELECT'
|
||||
select c from t2, t1;
|
||||
ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'c' in table 't1'
|
||||
select c from t1, t2;
|
||||
ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'c' in table 't1'
|
||||
select d from t2, t1;
|
||||
ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'd' in table 't1'
|
||||
select d from t1, t2;
|
||||
ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'd' in table 't1'
|
||||
select t2.c from t2,t1;
|
||||
ERROR 42S22: Unknown column 't2.c' in 'SELECT'
|
||||
select * from test.t1;
|
||||
k l m
|
||||
select test.t1.c from t1,test.t1;
|
||||
ERROR 42S22: Unknown column 'test.t1.c' in 'SELECT'
|
||||
connection default;
|
||||
disconnect con1;
|
||||
drop user foo@localhost;
|
||||
drop database db;
|
||||
drop table t1;
|
||||
# End of 10.11 tests
|
||||
|
||||
@@ -456,6 +456,35 @@ show create user u2@localhost;
|
||||
drop user u1@localhost;
|
||||
drop user u2@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40541 role vs user@localhost acl_cache key confusion
|
||||
--echo #
|
||||
create database db;
|
||||
create table db.t1(a varchar(40));
|
||||
insert into db.t1 values ('role-cache-collision-row');
|
||||
|
||||
create role r1;
|
||||
create user r1@localhost identified by 'r1pass';
|
||||
create user u1@'127.0.0.1' identified by 'u1pass';
|
||||
|
||||
grant select on db.* to r1@localhost;
|
||||
grant r1 to u1@'127.0.0.1';
|
||||
#flush privileges;
|
||||
|
||||
connect r1,localhost,r1,r1pass;
|
||||
select a as precache from db.t1;
|
||||
|
||||
connect u1,127.0.0.1,u1,u1pass;
|
||||
set role r1;
|
||||
show grants;
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
select a from db.t1;
|
||||
|
||||
connection default;
|
||||
drop database db;
|
||||
drop role r1;
|
||||
drop user r1@localhost, u1@'127.0.0.1';
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
|
||||
--echo #
|
||||
@@ -482,4 +511,45 @@ load index into cache test.t2 key (i2);
|
||||
drop table t1;
|
||||
drop user foo@localhost;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-23086 Error codes/messages reveal information about table structure
|
||||
--echo #
|
||||
|
||||
create database db;
|
||||
create table db.t1 (a int, b int, c int);
|
||||
create user foo@localhost;
|
||||
grant select (a,b) on db.t1 to foo@localhost;
|
||||
alter table db.t1 drop column b;
|
||||
|
||||
create table db.t2 (x int, y int);
|
||||
grant select on db.t2 to foo@localhost;
|
||||
|
||||
create table t1 (k int, l int, m int);
|
||||
grant select on test.t1 to foo@localhost;
|
||||
|
||||
connect con1,localhost,foo,,db;
|
||||
|
||||
disable_abort_on_error;
|
||||
select a from t1; # can access, column exist
|
||||
select b from t1; # can access, column doesn't exist
|
||||
select c from t1; # no access, column exists
|
||||
select d from t1; # no access, column doesn't exists
|
||||
select a from t0; # no access, table doesn't exists
|
||||
use db2; # no access, db doesn't exists
|
||||
select a from t2; # table level grant, column doesn't exists
|
||||
select c from t2, t1; # mix tbl/col grant, no access, column exist
|
||||
select c from t1, t2; # mix tbl/col grant, no access, column exist
|
||||
select d from t2, t1; # mix tbl/col grant, no access, column doesn't exists
|
||||
select d from t1, t2; # mix tbl/col grant, no access, column doesn't exist
|
||||
select t2.c from t2,t1; # mix tbl/col grant, explicit tbl, column doesn't exist
|
||||
select * from test.t1; # this should work
|
||||
select test.t1.c from t1,test.t1; # mix, explicit db name, column doesn't exist
|
||||
enable_abort_on_error;
|
||||
|
||||
connection default;
|
||||
disconnect con1;
|
||||
drop user foo@localhost;
|
||||
drop database db;
|
||||
drop table t1;
|
||||
|
||||
--echo # End of 10.11 tests
|
||||
|
||||
@@ -478,3 +478,57 @@ drop table t1;
|
||||
set global innodb_stats_persistent= @innodb_stats_persistent_save;
|
||||
set global innodb_stats_persistent_sample_pages=
|
||||
@innodb_stats_persistent_sample_pages_save;
|
||||
#
|
||||
# Begin 10.11 tests
|
||||
#
|
||||
CREATE TABLE t1 (pk INT, a INT, b INT, PRIMARY KEY (pk), KEY (a,b)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 (pk,a) VALUES (1,11),(2,12),(3,13),(4,14);
|
||||
connect con1,localhost,root,,;
|
||||
DELETE FROM t1 WHERE pk <= 3;
|
||||
connection default;
|
||||
INSERT INTO t1 (pk) VALUES (5);
|
||||
connection con1;
|
||||
START TRANSACTION;
|
||||
INSERT INTO t1 (pk) VALUES (6);
|
||||
connection default;
|
||||
SET @save_innodb_lock_wait_timeout= @@innodb_lock_wait_timeout;
|
||||
SET innodb_lock_wait_timeout= 1;
|
||||
EXPLAIN SELECT MIN(b), MAX(b), a FROM t1 GROUP BY a FOR UPDATE;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range NULL a 10 NULL # Using index for group-by
|
||||
SELECT MIN(b), MAX(b), a FROM t1 GROUP BY a FOR UPDATE;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
SET innodb_lock_wait_timeout= @save_innodb_lock_wait_timeout;
|
||||
connection con1;
|
||||
COMMIT;
|
||||
DROP TABLE t1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, a INT, b INT, c INT,
|
||||
KEY (a,b,c)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 (a,b,c) VALUES
|
||||
(1,1,10),(1,1,11),(1,2,20),(1,2,21),
|
||||
(2,1,10),(2,1,11),(2,2,20),(2,2,21);
|
||||
INSERT INTO t1 (a,b,c) SELECT a,b,c FROM t1;
|
||||
INSERT INTO t1 (a,b,c) SELECT a,b,c FROM t1;
|
||||
INSERT INTO t1 (a,b,c) SELECT a,b,c FROM t1;
|
||||
connect con1,localhost,root,,;
|
||||
START TRANSACTION;
|
||||
INSERT INTO t1 (a,b,c) VALUES (1,2,0);
|
||||
connection default;
|
||||
SET @save_innodb_lock_wait_timeout= @@innodb_lock_wait_timeout;
|
||||
SET innodb_lock_wait_timeout= 1;
|
||||
EXPLAIN SELECT MIN(c) FROM t1 WHERE b = 2 GROUP BY a FOR UPDATE;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range NULL a 15 NULL # Using where; Using index for group-by
|
||||
SELECT MIN(c) FROM t1 WHERE b = 2 GROUP BY a FOR UPDATE;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
SET innodb_lock_wait_timeout= @save_innodb_lock_wait_timeout;
|
||||
connection con1;
|
||||
COMMIT;
|
||||
DROP TABLE t1;
|
||||
disconnect con1;
|
||||
connection default;
|
||||
#
|
||||
# End 10.11 tests
|
||||
#
|
||||
|
||||
@@ -360,3 +360,93 @@ drop table t1;
|
||||
set global innodb_stats_persistent= @innodb_stats_persistent_save;
|
||||
set global innodb_stats_persistent_sample_pages=
|
||||
@innodb_stats_persistent_sample_pages_save;
|
||||
|
||||
--echo #
|
||||
--echo # Begin 10.11 tests
|
||||
--echo #
|
||||
|
||||
# Default client connection to the database.
|
||||
CREATE TABLE t1 (pk INT, a INT, b INT, PRIMARY KEY (pk), KEY (a,b)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 (pk,a) VALUES (1,11),(2,12),(3,13),(4,14);
|
||||
|
||||
# Start a new, separate client connection to the database called 'con1'.
|
||||
--connect (con1,localhost,root,,)
|
||||
--send
|
||||
DELETE FROM t1 WHERE pk <= 3;
|
||||
|
||||
# On the default connection, insert a value into the table.
|
||||
--connection default
|
||||
INSERT INTO t1 (pk) VALUES (5);
|
||||
|
||||
# On 'con1', insert a value within a transaction and hold the transaction while
|
||||
# on the default connection try to compute an aggregate.
|
||||
--connection con1
|
||||
--reap
|
||||
|
||||
START TRANSACTION;
|
||||
INSERT INTO t1 (pk) VALUES (6);
|
||||
|
||||
--connection default
|
||||
SET @save_innodb_lock_wait_timeout= @@innodb_lock_wait_timeout;
|
||||
SET innodb_lock_wait_timeout= 1;
|
||||
# SELECT ... FOR UPDATE locks the rows for write operations and prevents other transactions
|
||||
# from modifying or reading the selected rows until the transaction ends.
|
||||
# This should lead to the error, not a crash.
|
||||
--replace_column 9 #
|
||||
EXPLAIN SELECT MIN(b), MAX(b), a FROM t1 GROUP BY a FOR UPDATE;
|
||||
--error ER_LOCK_WAIT_TIMEOUT
|
||||
SELECT MIN(b), MAX(b), a FROM t1 GROUP BY a FOR UPDATE;
|
||||
SET innodb_lock_wait_timeout= @save_innodb_lock_wait_timeout;
|
||||
|
||||
# Cleanup, commit the 'con1' transaction.
|
||||
--connection con1
|
||||
COMMIT;
|
||||
DROP TABLE t1;
|
||||
--disconnect con1
|
||||
|
||||
# This scenario passes with or without the patch. The query requests only a
|
||||
# MIN, so the max branch never runs. The scenario is kept for coverage, to
|
||||
# execute the early return, which the patch adds in the min branch for symmetry
|
||||
# with the max branch and to honor the convention that no further reads follow
|
||||
# a fatal handler error.
|
||||
--connection default
|
||||
CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, a INT, b INT, c INT,
|
||||
KEY (a,b,c)) ENGINE=InnoDB;
|
||||
|
||||
# Two groups over key part a. Each group has rows with b=1 and rows with
|
||||
# b=2, with enough rows overall that the optimizer chooses the loose
|
||||
# index scan ("Using index for group-by") over a full index scan.
|
||||
INSERT INTO t1 (a,b,c) VALUES
|
||||
(1,1,10),(1,1,11),(1,2,20),(1,2,21),
|
||||
(2,1,10),(2,1,11),(2,2,20),(2,2,21);
|
||||
INSERT INTO t1 (a,b,c) SELECT a,b,c FROM t1;
|
||||
INSERT INTO t1 (a,b,c) SELECT a,b,c FROM t1;
|
||||
INSERT INTO t1 (a,b,c) SELECT a,b,c FROM t1;
|
||||
|
||||
--connect (con1,localhost,root,,)
|
||||
START TRANSACTION;
|
||||
# This uncommitted row becomes the first row of the a=1, b=2 prefix because its
|
||||
# c is smaller than every committed c in that subgroup. The MIN read seeks
|
||||
# exactly this position, so it waits for con1.
|
||||
INSERT INTO t1 (a,b,c) VALUES (1,2,0);
|
||||
|
||||
--connection default
|
||||
SET @save_innodb_lock_wait_timeout= @@innodb_lock_wait_timeout;
|
||||
SET innodb_lock_wait_timeout= 1;
|
||||
# The MIN read inside the loose index scan lands on the row locked by con1.
|
||||
--replace_column 9 #
|
||||
EXPLAIN SELECT MIN(c) FROM t1 WHERE b = 2 GROUP BY a FOR UPDATE;
|
||||
--error ER_LOCK_WAIT_TIMEOUT
|
||||
SELECT MIN(c) FROM t1 WHERE b = 2 GROUP BY a FOR UPDATE;
|
||||
SET innodb_lock_wait_timeout= @save_innodb_lock_wait_timeout;
|
||||
|
||||
# Cleanup, commit the 'con1' transaction.
|
||||
--connection con1
|
||||
COMMIT;
|
||||
DROP TABLE t1;
|
||||
--disconnect con1
|
||||
--connection default
|
||||
|
||||
--echo #
|
||||
--echo # End 10.11 tests
|
||||
--echo #
|
||||
|
||||
@@ -1413,3 +1413,94 @@ a b
|
||||
1 2
|
||||
drop tables t1, t2, t3;
|
||||
set sql_mode= default;
|
||||
#
|
||||
# MDEV-38722 server crash hp_rec_key_cmp
|
||||
#
|
||||
# original reproducer (used to crash), returns a single row
|
||||
SELECT 1 INTERSECT SELECT 1 UNION ALL SELECT 1 EXCEPT ALL SELECT 1;
|
||||
1
|
||||
1
|
||||
CREATE TABLE t1 (i INT);
|
||||
INSERT INTO t1 VALUES (1),(1),(2),(3);
|
||||
CREATE TABLE t2 (i INT);
|
||||
INSERT INTO t2 VALUES (1),(2),(2);
|
||||
CREATE TABLE t3 (i INT);
|
||||
INSERT INTO t3 VALUES (1),(3);
|
||||
SELECT i FROM t1 INTERSECT SELECT i FROM t3
|
||||
UNION ALL SELECT i FROM t2 EXCEPT ALL SELECT i FROM t3 ORDER BY i;
|
||||
i
|
||||
1
|
||||
2
|
||||
2
|
||||
(((SELECT i FROM t1) INTERSECT (SELECT i FROM t3)) UNION ALL (SELECT i FROM t2))
|
||||
EXCEPT ALL (SELECT i FROM t3) ORDER BY i;
|
||||
i
|
||||
1
|
||||
2
|
||||
2
|
||||
# trailing UNION ALL after the EXCEPT ALL
|
||||
SELECT i FROM t1 INTERSECT SELECT i FROM t2 UNION ALL SELECT i FROM t2
|
||||
EXCEPT ALL SELECT i FROM t3 UNION ALL SELECT i FROM t1 ORDER BY i;
|
||||
i
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
2
|
||||
2
|
||||
3
|
||||
((((SELECT i FROM t1) INTERSECT (SELECT i FROM t2)) UNION ALL (SELECT i FROM t2))
|
||||
EXCEPT ALL (SELECT i FROM t3)) UNION ALL (SELECT i FROM t1) ORDER BY i;
|
||||
i
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
2
|
||||
2
|
||||
3
|
||||
# a leading INTERSECT ALL keeps the operation extended while the last
|
||||
# INTERSECT DISTINCT node is the index-release point
|
||||
SELECT i FROM t1 INTERSECT ALL SELECT i FROM t2 INTERSECT SELECT i FROM t3
|
||||
UNION ALL SELECT i FROM t2 ORDER BY i;
|
||||
i
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
(((SELECT i FROM t1) INTERSECT ALL (SELECT i FROM t2)) INTERSECT (SELECT i FROM t3))
|
||||
UNION ALL (SELECT i FROM t2) ORDER BY i;
|
||||
i
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
DROP TABLE t1,t2,t3;
|
||||
# End of 10.6 tests
|
||||
#
|
||||
# MDEV-38722 fix merge problem with view/derived
|
||||
#
|
||||
CREATE TABLE t1 (i INT);
|
||||
INSERT INTO t1 VALUES (1),(1),(2),(3);
|
||||
CREATE TABLE t2 (i INT);
|
||||
INSERT INTO t2 VALUES (1),(2),(2);
|
||||
CREATE TABLE t3 (i INT);
|
||||
INSERT INTO t3 VALUES (1),(3);
|
||||
SELECT * FROM (SELECT i FROM t1 INTERSECT SELECT i FROM t3
|
||||
UNION ALL SELECT i FROM t2 EXCEPT ALL SELECT i FROM t3) d ORDER BY i;
|
||||
i
|
||||
1
|
||||
2
|
||||
2
|
||||
CREATE VIEW v1 AS SELECT i FROM t1 INTERSECT SELECT i FROM t3
|
||||
UNION ALL SELECT i FROM t2 EXCEPT ALL SELECT i FROM t3;
|
||||
SELECT * FROM v1 ORDER BY i;
|
||||
i
|
||||
1
|
||||
2
|
||||
2
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1,t2,t3;
|
||||
# End of 11.4 tests
|
||||
|
||||
@@ -499,3 +499,53 @@ select * from t1 except all select * from t2 intersect all select * from t1 unio
|
||||
select * from t1 except all select * from t2 intersect all select * from t1 union all select * from t2 order by a desc limit 3;
|
||||
drop tables t1, t2, t3;
|
||||
set sql_mode= default;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-38722 server crash hp_rec_key_cmp
|
||||
--echo #
|
||||
--echo # original reproducer (used to crash), returns a single row
|
||||
SELECT 1 INTERSECT SELECT 1 UNION ALL SELECT 1 EXCEPT ALL SELECT 1;
|
||||
|
||||
CREATE TABLE t1 (i INT);
|
||||
INSERT INTO t1 VALUES (1),(1),(2),(3);
|
||||
CREATE TABLE t2 (i INT);
|
||||
INSERT INTO t2 VALUES (1),(2),(2);
|
||||
CREATE TABLE t3 (i INT);
|
||||
INSERT INTO t3 VALUES (1),(3);
|
||||
SELECT i FROM t1 INTERSECT SELECT i FROM t3
|
||||
UNION ALL SELECT i FROM t2 EXCEPT ALL SELECT i FROM t3 ORDER BY i;
|
||||
(((SELECT i FROM t1) INTERSECT (SELECT i FROM t3)) UNION ALL (SELECT i FROM t2))
|
||||
EXCEPT ALL (SELECT i FROM t3) ORDER BY i;
|
||||
--echo # trailing UNION ALL after the EXCEPT ALL
|
||||
SELECT i FROM t1 INTERSECT SELECT i FROM t2 UNION ALL SELECT i FROM t2
|
||||
EXCEPT ALL SELECT i FROM t3 UNION ALL SELECT i FROM t1 ORDER BY i;
|
||||
((((SELECT i FROM t1) INTERSECT (SELECT i FROM t2)) UNION ALL (SELECT i FROM t2))
|
||||
EXCEPT ALL (SELECT i FROM t3)) UNION ALL (SELECT i FROM t1) ORDER BY i;
|
||||
--echo # a leading INTERSECT ALL keeps the operation extended while the last
|
||||
--echo # INTERSECT DISTINCT node is the index-release point
|
||||
SELECT i FROM t1 INTERSECT ALL SELECT i FROM t2 INTERSECT SELECT i FROM t3
|
||||
UNION ALL SELECT i FROM t2 ORDER BY i;
|
||||
(((SELECT i FROM t1) INTERSECT ALL (SELECT i FROM t2)) INTERSECT (SELECT i FROM t3))
|
||||
UNION ALL (SELECT i FROM t2) ORDER BY i;
|
||||
DROP TABLE t1,t2,t3;
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-38722 fix merge problem with view/derived
|
||||
--echo #
|
||||
CREATE TABLE t1 (i INT);
|
||||
INSERT INTO t1 VALUES (1),(1),(2),(3);
|
||||
CREATE TABLE t2 (i INT);
|
||||
INSERT INTO t2 VALUES (1),(2),(2);
|
||||
CREATE TABLE t3 (i INT);
|
||||
INSERT INTO t3 VALUES (1),(3);
|
||||
SELECT * FROM (SELECT i FROM t1 INTERSECT SELECT i FROM t3
|
||||
UNION ALL SELECT i FROM t2 EXCEPT ALL SELECT i FROM t3) d ORDER BY i;
|
||||
CREATE VIEW v1 AS SELECT i FROM t1 INTERSECT SELECT i FROM t3
|
||||
UNION ALL SELECT i FROM t2 EXCEPT ALL SELECT i FROM t3;
|
||||
SELECT * FROM v1 ORDER BY i;
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1,t2,t3;
|
||||
|
||||
--echo # End of 11.4 tests
|
||||
|
||||
@@ -39,7 +39,7 @@ a
|
||||
2
|
||||
3
|
||||
select invisible,a from t1;
|
||||
ERROR 42S22: Unknown column 'invisible' in 'SELECT'
|
||||
ERROR 42000: SELECT command denied to user 'user_1'@'localhost' for column 'invisible' in table 't1'
|
||||
delete from t1 where a =1;
|
||||
update t1 set a=1 where a=3;
|
||||
select * from t1;
|
||||
|
||||
@@ -29,7 +29,7 @@ insert into t1 values(2);
|
||||
select * from t1;
|
||||
insert into t1(a) values(3);
|
||||
select * from t1;
|
||||
--error ER_BAD_FIELD_ERROR
|
||||
--error ER_COLUMNACCESS_DENIED_ERROR
|
||||
select invisible,a from t1;
|
||||
delete from t1 where a =1;
|
||||
update t1 set a=1 where a=3;
|
||||
|
||||
@@ -1 +1 @@
|
||||
--skip-name-resolve
|
||||
--skip-name-resolve --bind-address=::1,127.0.0.1
|
||||
|
||||
@@ -35,8 +35,87 @@ root
|
||||
kill user b;
|
||||
ERROR HY000: Operation KILL USER failed for b@%
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
drop user a@'127.0.0.1';
|
||||
drop user b@'127.0.0.1';
|
||||
#
|
||||
# End of 10.3 tests
|
||||
#
|
||||
# MDEV-40554 KILL checks user (not priv_user) and doesn't verify hostname
|
||||
#
|
||||
create user u1@'::1' identified by 'pw1';
|
||||
create user ''@'127.0.0.1';
|
||||
connect u1_ipv6,::1,u1,pw1;
|
||||
select current_user();
|
||||
current_user()
|
||||
u1@::1
|
||||
# the reported case: same login name, but an anonymous account
|
||||
connect u1_anon,127.0.0.1,u1,;
|
||||
select user(), current_user();
|
||||
user() current_user()
|
||||
u1@127.0.0.1 @127.0.0.1
|
||||
# anonymous users don't see the process list at all
|
||||
show processlist;
|
||||
ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
|
||||
select count(*) as `threads visible` from information_schema.processlist;
|
||||
threads visible
|
||||
1
|
||||
select count(*) as `u1@'::1' visible`
|
||||
from information_schema.processlist where id=$cid_sock;
|
||||
u1@'::1' visible
|
||||
0
|
||||
kill $cid_sock;
|
||||
ERROR HY000: You are not owner of thread CID
|
||||
show explain for $cid_sock;
|
||||
ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
|
||||
kill user u1@'::1';
|
||||
connection u1_ipv6;
|
||||
select user(), current_user();
|
||||
user() current_user()
|
||||
u1@::1 u1@::1
|
||||
connection u1_anon;
|
||||
connection default;
|
||||
disconnect u1_anon;
|
||||
drop user ''@'127.0.0.1';
|
||||
# same login name, a real account, but a different host
|
||||
create user u1@'127.0.0.1' identified by 'pw2';
|
||||
connect u1_ipv4,127.0.0.1,u1,pw2;
|
||||
select current_user();
|
||||
current_user()
|
||||
u1@127.0.0.1
|
||||
# u1@127.0.0.1 must not see u1@'::1' - same user name, other account
|
||||
show processlist;
|
||||
Id User Host db Command Time State Info Progress
|
||||
# u1 # # Query # # # #
|
||||
select count(*) as `u1@'::1' visible`
|
||||
from information_schema.processlist where id=$cid_sock;
|
||||
u1@'::1' visible
|
||||
0
|
||||
kill $cid_sock;
|
||||
ERROR HY000: You are not owner of thread CID
|
||||
show explain for $cid_sock;
|
||||
ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
|
||||
kill user u1@'::1';
|
||||
connection u1_ipv6;
|
||||
select user(), current_user();
|
||||
user() current_user()
|
||||
u1@::1 u1@::1
|
||||
connection u1_ipv4;
|
||||
# but another u1@127.0.0.1 connection is the same account, so it may
|
||||
connect u1_tcp2,127.0.0.1,u1,pw2;
|
||||
select count(*) as `u1@127.0.0.1 visible`
|
||||
from information_schema.processlist where id=$cid_tcp;
|
||||
u1@127.0.0.1 visible
|
||||
1
|
||||
kill $cid_tcp;
|
||||
# u1@'::1' was not killed
|
||||
connection u1_ipv6;
|
||||
select 1;
|
||||
1
|
||||
1
|
||||
connection default;
|
||||
disconnect u1_ipv6;
|
||||
disconnect u1_tcp2;
|
||||
drop user u1@'::1';
|
||||
drop user u1@'127.0.0.1';
|
||||
# End of 10.11 tests
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
# connection does not read() from a socket, but returns control to the
|
||||
# application. 'mysqltest' does not handle the kill request.
|
||||
#
|
||||
-- source include/not_embedded.inc
|
||||
--source include/not_embedded.inc
|
||||
--source include/count_sessions.inc
|
||||
--source include/check_ipv6.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-6896 kill user command cause MariaDB crash!
|
||||
@@ -50,9 +52,92 @@ evalp select user from information_schema.processlist where id in (connection_id
|
||||
--error ER_KILL_DENIED_ERROR
|
||||
kill user b;
|
||||
--connection default
|
||||
--disconnect a
|
||||
--disconnect b
|
||||
drop user a@'127.0.0.1';
|
||||
drop user b@'127.0.0.1';
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.3 tests
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40554 KILL checks user (not priv_user) and doesn't verify hostname
|
||||
--echo #
|
||||
|
||||
create user u1@'::1' identified by 'pw1';
|
||||
create user ''@'127.0.0.1';
|
||||
|
||||
connect u1_ipv6,::1,u1,pw1;
|
||||
select current_user();
|
||||
let $cid_sock=`select connection_id()`;
|
||||
|
||||
--echo # the reported case: same login name, but an anonymous account
|
||||
connect u1_anon,127.0.0.1,u1,;
|
||||
select user(), current_user();
|
||||
|
||||
--echo # anonymous users don't see the process list at all
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
show processlist;
|
||||
select count(*) as `threads visible` from information_schema.processlist;
|
||||
evalp select count(*) as `u1@'::1' visible`
|
||||
from information_schema.processlist where id=$cid_sock;
|
||||
--replace_regex /thread [0-9]+/thread CID/
|
||||
--error ER_KILL_DENIED_ERROR
|
||||
evalp kill $cid_sock;
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
evalp show explain for $cid_sock;
|
||||
|
||||
# killing a non-matching user doesn't report an error to not disclose
|
||||
# that the user exists. but doesn't kill either
|
||||
kill user u1@'::1';
|
||||
connection u1_ipv6;
|
||||
select user(), current_user();
|
||||
connection u1_anon;
|
||||
|
||||
connection default;
|
||||
disconnect u1_anon;
|
||||
drop user ''@'127.0.0.1';
|
||||
|
||||
--echo # same login name, a real account, but a different host
|
||||
create user u1@'127.0.0.1' identified by 'pw2';
|
||||
connect u1_ipv4,127.0.0.1,u1,pw2;
|
||||
select current_user();
|
||||
let $cid_tcp=`select connection_id()`;
|
||||
|
||||
--echo # u1@127.0.0.1 must not see u1@'::1' - same user name, other account
|
||||
--replace_result Execute Query
|
||||
--replace_column 1 # 3 # 4 # 6 # 7 # 8 # 9 #
|
||||
show processlist;
|
||||
evalp select count(*) as `u1@'::1' visible`
|
||||
from information_schema.processlist where id=$cid_sock;
|
||||
--replace_regex /thread [0-9]+/thread CID/
|
||||
--error ER_KILL_DENIED_ERROR
|
||||
evalp kill $cid_sock;
|
||||
--error ER_SPECIFIC_ACCESS_DENIED_ERROR
|
||||
evalp show explain for $cid_sock;
|
||||
|
||||
# doesn't report an error, doesn't kill
|
||||
kill user u1@'::1';
|
||||
connection u1_ipv6;
|
||||
select user(), current_user();
|
||||
connection u1_ipv4;
|
||||
|
||||
--echo # but another u1@127.0.0.1 connection is the same account, so it may
|
||||
connect u1_tcp2,127.0.0.1,u1,pw2;
|
||||
evalp select count(*) as `u1@127.0.0.1 visible`
|
||||
from information_schema.processlist where id=$cid_tcp;
|
||||
evalp kill $cid_tcp;
|
||||
|
||||
--echo # u1@'::1' was not killed
|
||||
connection u1_ipv6;
|
||||
select 1;
|
||||
|
||||
connection default;
|
||||
disconnect u1_ipv6;
|
||||
#u1_ipv4 was killed, must not be disconnected
|
||||
disconnect u1_tcp2;
|
||||
--source include/wait_until_count_sessions.inc
|
||||
|
||||
drop user u1@'::1';
|
||||
drop user u1@'127.0.0.1';
|
||||
|
||||
--echo # End of 10.11 tests
|
||||
|
||||
@@ -169,4 +169,15 @@ id f
|
||||
1 foo
|
||||
2 foo
|
||||
drop table t1;
|
||||
#
|
||||
# MDEV-39846 UNIQUE BLOB contains duplicate records after ALTER IGNORE with READ COMMITTED
|
||||
#
|
||||
create table t1 (pk int primary key, b blob) engine=innodb;
|
||||
insert into t1 values (1,'foo'),(2,'foo');
|
||||
set transaction isolation level read committed;
|
||||
alter ignore table t1 add unique (b);
|
||||
select * from t1;
|
||||
pk b
|
||||
1 foo
|
||||
drop table t1;
|
||||
# End of 10.6 tests
|
||||
|
||||
@@ -176,4 +176,14 @@ update ignore t1 set id = 2;
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39846 UNIQUE BLOB contains duplicate records after ALTER IGNORE with READ COMMITTED
|
||||
--echo #
|
||||
create table t1 (pk int primary key, b blob) engine=innodb;
|
||||
insert into t1 values (1,'foo'),(2,'foo');
|
||||
set transaction isolation level read committed;
|
||||
alter ignore table t1 add unique (b);
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
|
||||
@@ -103,4 +103,16 @@ drop table t3|
|
||||
# MDEV-40409 ST_GeomFromText stack overrun on deeply nested GeometryCollection
|
||||
#
|
||||
SELECT ST_GeomFromText(CONCAT(REPEAT('GEOMETRYCOLLECTION(',5000),'POINT(1 1)',REPEAT(')',5000)));
|
||||
#
|
||||
# MDEV-40540 ST_GeomFromWKB stack overrun on deeply nested GeometryCollection
|
||||
#
|
||||
set @a=concat(0x0107000000, repeat(0x010000000107000000, 120000), 0x00000000);
|
||||
SELECT ST_GeomFromWKB(@a);
|
||||
#
|
||||
# MDEV-39750 ExtractValue does not control recursion depth.
|
||||
#
|
||||
SELECT ExtractValue('<a/>', REPEAT('(', 100000));
|
||||
ERROR HY000: Thread stack overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed. Consider increasing the thread_stack system variable.
|
||||
SELECT ExtractValue('<a/>', REPEAT('/n', 100000));
|
||||
ERROR HY000: Thread stack overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed. Consider increasing the thread_stack system variable.
|
||||
# End of 10.6 tests
|
||||
|
||||
@@ -147,4 +147,24 @@ delimiter ;|
|
||||
SELECT ST_GeomFromText(CONCAT(REPEAT('GEOMETRYCOLLECTION(',5000),'POINT(1 1)',REPEAT(')',5000)));
|
||||
--enable_result_log
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40540 ST_GeomFromWKB stack overrun on deeply nested GeometryCollection
|
||||
--echo #
|
||||
set @a=concat(0x0107000000, repeat(0x010000000107000000, 120000), 0x00000000);
|
||||
--disable_result_log
|
||||
--error ER_STACK_OVERRUN_NEED_MORE
|
||||
SELECT ST_GeomFromWKB(@a);
|
||||
--enable_result_log
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-39750 ExtractValue does not control recursion depth.
|
||||
--echo #
|
||||
--replace_regex /overrun: [0-9]* bytes used of a [0-9]* byte stack, and [0-9]* bytes needed/overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed/
|
||||
--error ER_STACK_OVERRUN_NEED_MORE
|
||||
SELECT ExtractValue('<a/>', REPEAT('(', 100000));
|
||||
|
||||
--replace_regex /overrun: [0-9]* bytes used of a [0-9]* byte stack, and [0-9]* bytes needed/overrun: 'used bytes' used of a 'available' byte stack, and 'X' bytes needed/
|
||||
--error ER_STACK_OVERRUN_NEED_MORE
|
||||
SELECT ExtractValue('<a/>', REPEAT('/n', 100000));
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
|
||||
8
mysql-test/main/mdev-37000.result
Normal file
8
mysql-test/main/mdev-37000.result
Normal file
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# MDEV-37000 Deleting a row from Aria table results to 'Index is corrupt'
|
||||
#
|
||||
CREATE OR REPLACE TABLE t (a INT, b CHAR(8) NOT NULL, KEY(b)) ENGINE=Aria DEFAULT CHARSET=utf8;
|
||||
INSERT INTO t VALUES (1,'20070101'), (2,'20070101');
|
||||
DELETE FROM t LIMIT 2;
|
||||
DROP TABLE t;
|
||||
# End of 10.6 tests
|
||||
9
mysql-test/main/mdev-37000.test
Normal file
9
mysql-test/main/mdev-37000.test
Normal file
@@ -0,0 +1,9 @@
|
||||
--echo #
|
||||
--echo # MDEV-37000 Deleting a row from Aria table results to 'Index is corrupt'
|
||||
--echo #
|
||||
CREATE OR REPLACE TABLE t (a INT, b CHAR(8) NOT NULL, KEY(b)) ENGINE=Aria DEFAULT CHARSET=utf8;
|
||||
INSERT INTO t VALUES (1,'20070101'), (2,'20070101');
|
||||
DELETE FROM t LIMIT 2;
|
||||
DROP TABLE t;
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
@@ -245,6 +245,14 @@ DECLARE a mysql_json;
|
||||
END;
|
||||
$$
|
||||
ERROR HY000: 'MYSQL_JSON' is not allowed in this context
|
||||
#
|
||||
# End of 10.5 tests
|
||||
#
|
||||
# MDEV-40678 mysql_json plugin OOB reads
|
||||
#
|
||||
alter table t1 force;
|
||||
ERROR HY000: Error parsing MySQL JSON format, please dump this table from MySQL and then restore it to be able to use it in MariaDB.
|
||||
flush tables;
|
||||
alter table t1 force;
|
||||
ERROR HY000: Error parsing MySQL JSON format, please dump this table from MySQL and then restore it to be able to use it in MariaDB.
|
||||
drop table t1;
|
||||
# End of 10.6 tests
|
||||
|
||||
@@ -17,7 +17,7 @@ call mtr.add_suppression("Table rebuild required");
|
||||
call mtr.add_suppression("is marked as crashed");
|
||||
call mtr.add_suppression("Checking");
|
||||
|
||||
let $MYSQLD_DATADIR= `select @@datadir`;
|
||||
let MYSQLD_DATADIR= `select @@datadir`;
|
||||
|
||||
SET NAMES utf8;
|
||||
|
||||
@@ -161,6 +161,40 @@ END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.5 tests
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40678 mysql_json plugin OOB reads
|
||||
--echo #
|
||||
|
||||
--copy_file std_data/mysql_json/mysql_json_test.frm $MYSQLD_DATADIR/test/t1.frm
|
||||
--copy_file std_data/mysql_json/mysql_json_test.MYI $MYSQLD_DATADIR/test/t1.MYI
|
||||
--copy_file std_data/mysql_json/mysql_json_test.MYD $MYSQLD_DATADIR/test/t1.MYD
|
||||
|
||||
perl;
|
||||
my $f="$ENV{MYSQLD_DATADIR}/test/t1.MYD";
|
||||
open F, '+<', $f or die "open($f): $!";
|
||||
sysseek F, 0x3c5, 0 or die "sysseek: $!";
|
||||
syswrite F, '(' or die "syswrite: $!";
|
||||
EOF
|
||||
|
||||
--error ER_UNKNOWN_ERROR
|
||||
alter table t1 force;
|
||||
flush tables;
|
||||
|
||||
--remove_file $MYSQLD_DATADIR/test/t1.MYD
|
||||
--copy_file std_data/mysql_json/mysql_json_test.MYD $MYSQLD_DATADIR/test/t1.MYD
|
||||
|
||||
perl;
|
||||
my $f="$ENV{MYSQLD_DATADIR}/test/t1.MYD";
|
||||
open F, '+<', $f or die "open($f): $!";
|
||||
sysseek F, 0x3bc, 0 or die "sysseek: $!";
|
||||
syswrite F, '(' or die "syswrite: $!";
|
||||
EOF
|
||||
|
||||
--error ER_UNKNOWN_ERROR
|
||||
alter table t1 force;
|
||||
|
||||
drop table t1;
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
|
||||
@@ -16,7 +16,17 @@
|
||||
--net-buffer-length=#
|
||||
Buffer length for TCP/IP and socket communication
|
||||
--net-read-timeout=#
|
||||
@@ -1374,6 +1376,10 @@
|
||||
@@ -1216,8 +1218,7 @@
|
||||
(Defaults to on; use --skip-secure-auth to disable.)
|
||||
--secure-file-priv=name
|
||||
Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to
|
||||
- files within specified directory. Empty value means no
|
||||
- limits except /proc
|
||||
+ files within specified directory.
|
||||
--secure-timestamp=name
|
||||
Restricts direct setting of a session timestamp. Possible
|
||||
levels are: YES - timestamp cannot deviate from the
|
||||
@@ -1375,6 +1376,10 @@
|
||||
Alias for log_slow_query_file. Log slow queries to given
|
||||
log file. Defaults logging to 'hostname'-slow.log. Must
|
||||
be enabled to activate other slow log options
|
||||
@@ -27,7 +37,7 @@
|
||||
--socket=name Socket file to use for connection
|
||||
--sort-buffer-size=#
|
||||
Each thread that needs to do a sort allocates a buffer of
|
||||
@@ -1394,6 +1400,7 @@
|
||||
@@ -1395,6 +1400,7 @@
|
||||
aborted. Prevents the common mistake of accidentally
|
||||
deleting or updating every row in a table.
|
||||
--stack-trace Print a symbolic stack trace on failure
|
||||
@@ -35,7 +45,7 @@
|
||||
--standard-compliant-cte
|
||||
Allow only CTEs compliant to SQL standard
|
||||
(Defaults to on; use --skip-standard-compliant-cte to disable.)
|
||||
@@ -1472,6 +1479,12 @@
|
||||
@@ -1473,6 +1479,12 @@
|
||||
--thread-pool-max-threads=#
|
||||
Maximum allowed number of worker threads in the thread
|
||||
pool
|
||||
@@ -48,7 +58,7 @@
|
||||
--thread-pool-oversubscribe=#
|
||||
How many additional active worker threads in a group are
|
||||
allowed.
|
||||
@@ -1510,8 +1523,8 @@
|
||||
@@ -1511,8 +1523,8 @@
|
||||
automatically convert it to an on-disk MyISAM or Aria
|
||||
table.
|
||||
-t, --tmpdir=name Path for temporary files. Several paths may be specified,
|
||||
@@ -59,7 +69,7 @@
|
||||
--transaction-alloc-block-size=#
|
||||
Allocation block size for transactions to be stored in
|
||||
binary log
|
||||
@@ -1731,6 +1744,7 @@
|
||||
@@ -1732,6 +1744,7 @@
|
||||
myisam-stats-method NULLS_UNEQUAL
|
||||
myisam-use-mmap FALSE
|
||||
mysql56-temporal-format TRUE
|
||||
@@ -67,7 +77,7 @@
|
||||
net-buffer-length 16384
|
||||
net-read-timeout 30
|
||||
net-retry-count 10
|
||||
@@ -1891,6 +1905,7 @@
|
||||
@@ -1892,6 +1905,7 @@
|
||||
slave-type-conversions
|
||||
slow-launch-time 2
|
||||
slow-query-log FALSE
|
||||
@@ -75,7 +85,7 @@
|
||||
sort-buffer-size 2097152
|
||||
sql-mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
|
||||
sql-safe-updates FALSE
|
||||
@@ -1917,6 +1932,8 @@
|
||||
@@ -1918,6 +1932,8 @@
|
||||
thread-pool-exact-stats FALSE
|
||||
thread-pool-idle-timeout 60
|
||||
thread-pool-max-threads 65536
|
||||
|
||||
@@ -1274,7 +1274,8 @@ The following specify which files/extra groups are read (specified before remain
|
||||
(Defaults to on; use --skip-secure-auth to disable.)
|
||||
--secure-file-priv=name
|
||||
Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to
|
||||
files within specified directory
|
||||
files within specified directory. Empty value means no
|
||||
limits except /proc
|
||||
--secure-timestamp=name
|
||||
Restricts direct setting of a session timestamp. Possible
|
||||
levels are: YES - timestamp cannot deviate from the
|
||||
|
||||
@@ -1023,6 +1023,12 @@ the false block has written nothing
|
||||
mysqltest: At line 1: End of file encountered before 'eval' delimiter was found
|
||||
# Only 'eval' is allowed as the third argument
|
||||
mysqltest: At line 1: Invalid argument 'junk' to 'write_file', only 'eval' is allowed
|
||||
#
|
||||
# \0 in a query
|
||||
#
|
||||
select hex("1 | ||||