diff --git a/README.md b/README.md index e123e5b64c9..f4fab1bd3a3 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ -Code status: ------------- +# Code status: * [![Appveyor CI status](https://ci.appveyor.com/api/projects/status/4u6pexmtpuf8jq66?svg=true)](https://ci.appveyor.com/project/rasmushoj/server) ci.appveyor.com -## MariaDB: The innovative open source database +## MariaDB: The innovative open source database MariaDB was designed as a drop-in replacement of MySQL(R) with more features, new storage engines, fewer bugs, and better performance. @@ -33,20 +32,19 @@ https://mariadb.com/kb/en/mariadb-versus-mysql-compatibility/ https://mariadb.com/kb/en/new-and-old-releases/ -Getting the code, building it and testing it ---------------------------------------------------------------- +# Getting the code, building it and testing it -Refer to the following guide: https://mariadb.org/get-involved/getting-started-for-developers/get-code-build-test/ which outlines how to correctly build the source code and run the MariaDB testing framework. +Refer to the following guide: https://mariadb.org/get-involved/getting-started-for-developers/get-code-build-test/ +which outlines how to build the source code correctly and run the MariaDB testing framework, +as well as which branch to target for your contributions. -Help ------ +# Help More help is available from the Maria Discuss mailing list https://lists.mariadb.org/postorius/lists/discuss.lists.mariadb.org/ and MariaDB's Zulip -instance, https://mariadb.zulipchat.com/ +instance, https://mariadb.zulipchat.com/ -Licensing ---------- +# Licensing *************************************************************************** @@ -60,8 +58,7 @@ license information can be found in the THIRDPARTY file. *************************************************************************** -Bug Reports ------------- +# Bug Reports Bug and/or error reports regarding MariaDB should be submitted at: https://jira.mariadb.org diff --git a/appveyor.yml b/appveyor.yml index 190627790a6..a0b1d132394 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -31,4 +31,14 @@ test_script: - set /A parallel=4*%NUMBER_OF_PROCESSORS% - perl mysql-test-run.pl --force --max-test-fail=10 --retry=2 --parallel=%parallel% --testcase-timeout=4 --suite=main --skip-test-list=%APPVEYOR_BUILD_FOLDER%\win\appveyor_skip_tests.txt --mysqld=--loose-innodb-flush-log-at-trx-commit=2 +skip_commits: + files: + - debian/ + - '**/*.sh' + +branches: + only: + - /bb-/ + - /\d+\.\d+$/ + image: Visual Studio 2022 diff --git a/client/mysql.cc b/client/mysql.cc index ca659786cdb..e0129611dff 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -248,7 +248,8 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0, default_pager_set= 0, opt_sigint_ignore= 0, auto_vertical_output= 0, show_query_cost= 0, show_warnings= 0, executing_query= 0, - ignore_spaces= 0, opt_binhex= 0, opt_progress_reports; + ignore_spaces= 0, opt_binhex= 0, opt_progress_reports, + opt_print_query_on_error; static my_bool debug_info_flag, debug_check_flag, batch_abort_on_error; static my_bool column_types_flag; static my_bool preserve_comments= 0; @@ -326,6 +327,7 @@ static int com_quit(String *str,char*), com_prompt(String *str, char*), com_delimiter(String *str, char*), com_warnings(String *str, char*), com_nowarnings(String *str, char*), com_sandbox(String *str, char*); +static void print_query_to_stderr(String *buffer); static int com_query_cost(String *str, char*); #ifdef USE_POPEN @@ -1210,6 +1212,8 @@ inline int get_command_index(char cmd_char) static int delimiter_index= -1; static int charset_index= -1; +static int sandbox_index= -1; + static bool real_binary_mode= FALSE; @@ -1220,7 +1224,8 @@ int main(int argc,char *argv[]) MY_INIT(argv[0]); DBUG_ENTER("main"); DBUG_PROCESS(argv[0]); - + + sandbox_index= get_command_index('-'); charset_index= get_command_index('C'); delimiter_index= get_command_index('d'); delimiter_str= delimiter; @@ -1798,6 +1803,10 @@ static struct my_option my_long_options[] = #endif "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", &opt_mysql_port, &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"print-query-on-error", 0, + "Print the query if there was an error. Is only enabled in --batch mode if verbose is not set (as then the query would be printed anyway)", + &opt_print_query_on_error, &opt_print_query_on_error, 0, GET_BOOL, NO_ARG, + 1, 0, 0, 0, 0, 0}, {"progress-reports", 0, "Get progress reports for long running commands (like ALTER TABLE)", &opt_progress_reports, &opt_progress_reports, 0, GET_BOOL, NO_ARG, 1, 0, @@ -2375,8 +2384,9 @@ static int read_and_execute(bool interactive) /** It checks if the input is a short form command. It returns the command's - pointer if a command is found, else return NULL. Note that if binary-mode - is set, then only \C is searched for. + pointer if a command is found, else return NULL. + + Note that if binary-mode is set, then only \C and \- are searched for. @param cmd_char A character of one byte. @@ -2391,13 +2401,23 @@ static COMMANDS *find_command(char cmd_char) int index= -1; /* - In binary-mode, we disallow all mysql commands except '\C' - and DELIMITER. + In binary-mode, we disallow all client commands except '\C', + DELIMITER (see long comand finding find_command(char *)) + and '\-' (sandbox, see following comment). */ if (real_binary_mode) { if (cmd_char == 'C') index= charset_index; + /* + binary-mode enforces stricter controls compared to sandbox mode. + Whether sandbox mode is enabled or not is irrelevant when + binary-mode is active. + The only purpose of processing sandbox mode here is to avoid error + messages on files made by mysqldump. + */ + else if (cmd_char == '-') + index= sandbox_index; } else index= get_command_index(cmd_char); @@ -2453,6 +2473,12 @@ static COMMANDS *find_command(char *name) len= (uint) strlen(name); int index= -1; + /* + In binary-mode, we disallow all client commands except DELIMITER + and short commands '\C' and '\-' (see short command finding + find_command(char)). + */ + if (real_binary_mode) { if (is_delimiter_command(name, len)) @@ -3208,6 +3234,11 @@ int mysql_real_query_for_lazy(const char *buf, size_t length) int error; if (!mysql_real_query(&mysql,buf,(ulong)length)) return 0; + if (opt_print_query_on_error) + { + String query(buf, length, charset_info); + (void) print_query_to_stderr(&query); + } error= put_error(&mysql); if (mysql_errno(&mysql) != CR_SERVER_GONE_ERROR || retry > 1 || !opt_reconnect) @@ -3430,7 +3461,6 @@ static int com_charset(String *, char *line) 1 if fatal error */ - static int com_go(String *buffer, char *) { char buff[200]; /* about 110 chars used so far */ @@ -3503,6 +3533,8 @@ static int com_go(String *buffer, char *) { if (!(result=mysql_use_result(&mysql)) && mysql_field_count(&mysql)) { + if (opt_print_query_on_error) + print_query_to_stderr(buffer); error= put_error(&mysql); goto end; } @@ -3556,7 +3588,11 @@ static int com_go(String *buffer, char *) (long) mysql_num_rows(result) == 1 ? "row" : "rows"); end_pager(); if (mysql_errno(&mysql)) + { + if (opt_print_query_on_error) + print_query_to_stderr(buffer); error= put_error(&mysql); + } } } else if (mysql_affected_rows(&mysql) == ~(ulonglong) 0) @@ -3583,13 +3619,21 @@ static int com_go(String *buffer, char *) put_info("",INFO_RESULT); // Empty row if (result && !mysql_eof(result)) /* Something wrong when using quick */ + { + if (opt_print_query_on_error) + print_query_to_stderr(buffer); error= put_error(&mysql); + } else if (unbuffered) fflush(stdout); mysql_free_result(result); } while (!(err= mysql_next_result(&mysql))); if (err >= 1) + { + if (opt_print_query_on_error) + print_query_to_stderr(buffer); error= put_error(&mysql); + } end: @@ -4547,14 +4591,35 @@ static int com_shell(String *, char *line) #endif +static void print_query(String *buffer, FILE *file) +{ + tee_puts("--------------", file); + (void) tee_fputs(buffer->c_ptr(), file); + if (!buffer->length() || (*buffer)[buffer->length()-1] != '\n') + tee_putc('\n', file); + tee_puts("--------------\n", file); +} + + +/* + Print query to stderr in batch mode if verbose is not set +*/ + +static void print_query_to_stderr(String *buffer) +{ + if ((status.batch || in_com_source) && !verbose) + { + fflush(stdout); + print_query(buffer, stderr); + fflush(stderr); + } +} + + static int com_print(String *buffer,char *) { - tee_puts("--------------", stdout); - (void) tee_fputs(buffer->c_ptr(), stdout); - if (!buffer->length() || (*buffer)[buffer->length()-1] != '\n') - tee_putc('\n', stdout); - tee_puts("--------------\n", stdout); - return 0; /* If empty buffer */ + print_query(buffer, stdout); + return 0; } @@ -5309,8 +5374,9 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate) static int put_error(MYSQL *con) { - return put_info(mysql_error(con), INFO_ERROR, mysql_errno(con), - mysql_sqlstate(con)); + DBUG_ENTER("put_error"); + DBUG_RETURN(put_info(mysql_error(con), INFO_ERROR, + mysql_errno(con), mysql_sqlstate(con))); } diff --git a/client/mysql_plugin.c b/client/mysql_plugin.c index 44abe8614e9..6c205d78c3b 100644 --- a/client/mysql_plugin.c +++ b/client/mysql_plugin.c @@ -683,7 +683,7 @@ static int load_plugin_data(char *plugin_name, char *config_file) if (i == -1) /* if first pass, read this line as so_name */ { /* Add proper file extension for soname */ - if (safe_strcpy(line + line_len - 1, sizeof(line), FN_SOEXT)) + if (safe_strcpy_truncated(line + line_len - 1, sizeof line, FN_SOEXT)) { reason= "Plugin name too long."; fclose(file_ptr); @@ -746,7 +746,7 @@ static int check_options(int argc, char **argv, char *operation) const char *plugin_dir_prefix = "--plugin_dir="; size_t plugin_dir_len= strlen(plugin_dir_prefix); - strcpy(plugin_name, ""); + *plugin_name= '\0'; for (i = 0; i < argc && num_found < 5; i++) { @@ -784,8 +784,8 @@ static int check_options(int argc, char **argv, char *operation) /* read the plugin config file and check for match against argument */ else { - if (safe_strcpy(plugin_name, sizeof(plugin_name), argv[i]) || - safe_strcpy(config_file, sizeof(config_file), argv[i]) || + if (safe_strcpy_truncated(plugin_name, sizeof plugin_name, argv[i]) || + safe_strcpy_truncated(config_file, sizeof config_file, argv[i]) || safe_strcat(config_file, sizeof(config_file), ".ini")) { fprintf(stderr, "ERROR: argument is too long.\n"); diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 3f60d169edc..4f3ababbe22 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -626,7 +626,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, { my_close(fd, MYF(MY_WME)); my_delete(query_file_path, MYF(0)); - die("Failed to write to '%s'", query_file_path); + die("Failed to write query to '%s'", query_file_path); } } @@ -635,7 +635,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, { my_close(fd, MYF(MY_WME)); my_delete(query_file_path, MYF(0)); - die("Failed to write to '%s'", query_file_path); + die("Failed to write query to '%s'", query_file_path); } ret= run_tool(mysql_path, @@ -645,6 +645,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res, "--batch", /* Turns off pager etc. */ force ? "--force": "--skip-force", opt_verbose >= 5 ? "--verbose" : "", + "--print-query-on-error", ds_res || opt_silent ? "--silent": "", "<", query_file_path, @@ -1092,18 +1093,6 @@ static char* get_line(char* line) return line; } - -/* Print the current line to stderr */ -static void print_line(char* line) -{ - while (*line && *line != '\n') - { - fputc(*line, stderr); - line++; - } - fputc('\n', stderr); -} - static my_bool from_before_10_1() { my_bool ret= TRUE; @@ -1322,16 +1311,21 @@ static int check_slave_repositories(void) static int run_sql_fix_privilege_tables(void) { - int found_real_errors= 0; + int found_real_errors= 0, query_started= 0; const char **query_ptr; + const char *end; DYNAMIC_STRING ds_script; DYNAMIC_STRING ds_result; + DYNAMIC_STRING ds_query; DBUG_ENTER("run_sql_fix_privilege_tables"); - if (init_dynamic_string(&ds_script, "", 65536, 1024)) + if (init_dynamic_string(&ds_script, "", 96*1024, 8196)) die("Out of memory"); - if (init_dynamic_string(&ds_result, "", 512, 512)) + if (init_dynamic_string(&ds_result, "", 1024, 1024)) + die("Out of memory"); + + if (init_dynamic_string(&ds_query, "", 1024, 1024)) die("Out of memory"); verbose("Phase %d/%d: Running 'mysql_fix_privilege_tables'", @@ -1360,22 +1354,46 @@ static int run_sql_fix_privilege_tables(void) "Unknown column" and "Duplicate key name" since they just indicate the system tables are already up to date */ - char *line= ds_result.str; + const char *line= ds_result.str; do { + size_t length; + end= strchr(line, '\n'); + if (!end) + end= strend(line); + else + end++; /* Include end \n */ + length= (size_t) (end - line); + if (!is_expected_error(line)) { /* Something unexpected failed, dump error line to screen */ found_real_errors++; - print_line(line); + if (ds_query.length) + fwrite(ds_query.str, sizeof(char), ds_query.length, stderr); + fwrite(line, sizeof(char), length, stderr); + query_started= 0; } else if (strncmp(line, "WARNING", 7) == 0) { - print_line(line); + fwrite(line, sizeof(char), length, stderr); + query_started= 0; } - } while ((line= get_line(line)) && *line); + else if (!strncmp(line, "--------------\n", 16)) + { + /* mariadb separates query from the error with a line of '-' */ + if (!query_started++) + ds_query.length= 0; /* Truncate */ + else + query_started= 0; /* End of query */ + } + else if (query_started) + { + dynstr_append_mem(&ds_query, line, length); + } + } while (*(line= end)); } - + dynstr_free(&ds_query); dynstr_free(&ds_result); dynstr_free(&ds_script); DBUG_RETURN(found_real_errors); diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 77bcdf506c8..90ea88f885a 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -421,7 +421,7 @@ int main(int argc,char *argv[]) is given a t!=0, we get an endless loop, or n iterations if --count=n was given an n!=0. If --sleep wasn't given, we get one iteration. - To wit, --wait loops the connection-attempts, while --sleep loops + To wait, --wait loops the connection-attempts, while --sleep loops the command execution (endlessly if no --count is given). */ diff --git a/client/mysqldump.cc b/client/mysqldump.cc index e3952c27452..c9526256b09 100644 --- a/client/mysqldump.cc +++ b/client/mysqldump.cc @@ -3027,7 +3027,7 @@ static void get_sequence_structure(const char *seq, const char *db) row= mysql_fetch_row(result); if (row[0]) { - fprintf(sql_file, "SELECT SETVAL(%s, %s, 0);\n", result_seq, row[0]); + fprintf(sql_file, "DO SETVAL(%s, %s, 0);\n", result_seq, row[0]); } // Sequences will not use inserts, so no need for REPLACE and LOCKS mysql_free_result(result); @@ -6037,7 +6037,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) free_root(&glob_root, MYF(0)); } maybe_die(EX_ILLEGAL_TABLE, "Couldn't find table: \"%s\"", *table_names); - /* We shall countinue here, if --force was given */ + /* We shall continue here, if --force was given */ } } end= pos; @@ -6058,7 +6058,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) free_root(&glob_root, MYF(0)); } DB_error(mysql, "when doing LOCK TABLES"); - /* We shall countinue here, if --force was given */ + /* We shall continue here, if --force was given */ } } dynstr_free(&lock_tables_query); @@ -6070,7 +6070,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables) free_root(&glob_root, MYF(0)); DB_error(mysql, "when doing refresh"); } - /* We shall countinue here, if --force was given */ + /* We shall continue here, if --force was given */ else verbose_msg("-- dump_selected_tables : logs flushed successfully!\n"); } diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 2f8a75c890a..4d9b8348f09 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -430,7 +430,7 @@ static void lock_table(MYSQL *mysql, int tablecount, char **raw_tablename) dynstr_append(&query, " WRITE,"); } if (mysql_real_query(mysql, query.str, (ulong)query.length-1)) - db_error(mysql); /* We shall countinue here, if --force was given */ + db_error(mysql); /* We shall continue here, if --force was given */ } @@ -621,7 +621,7 @@ pthread_handler_t worker_thread(void *arg) if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;")) { - db_error(mysql); /* We shall countinue here, if --force was given */ + db_error(mysql); /* We shall continue here, if --force was given */ goto error; } @@ -749,12 +749,12 @@ int main(int argc, char **argv) if (!(mysql= db_connect(current_host,current_db,current_user,opt_password))) { free_defaults(argv_to_free); - return(1); /* purecov: deadcode */ + return(1); /* purecov: dead code */ } if (mysql_query(mysql, "/*!40101 set @@character_set_database=binary */;")) { - db_error(mysql); /* We shall countinue here, if --force was given */ + db_error(mysql); /* We shall continue here, if --force was given */ return(1); } diff --git a/client/mysqltest.cc b/client/mysqltest.cc index c71afdc75c8..01724a0ae26 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -6013,14 +6013,20 @@ int connect_n_handle_errors(struct st_command *command, stay clear of trying to work out which exact user-limit was exceeded. */ + auto my_err= mysql_errno(con); + if(my_err == 0) + { + /* Workaround client library bug, not indicating connection error. */ + my_err= CR_SERVER_LOST; + } - if (((mysql_errno(con) == ER_TOO_MANY_USER_CONNECTIONS) || - (mysql_errno(con) == ER_USER_LIMIT_REACHED)) && + if (((my_err == ER_TOO_MANY_USER_CONNECTIONS) || + (my_err == ER_USER_LIMIT_REACHED)) && (failed_attempts++ < opt_max_connect_retries)) { int i; - i= match_expected_error(command, mysql_errno(con), mysql_sqlstate(con)); + i= match_expected_error(command, my_err, mysql_sqlstate(con)); if (i >= 0) goto do_handle_error; /* expected error, handle */ @@ -6030,9 +6036,9 @@ int connect_n_handle_errors(struct st_command *command, } do_handle_error: - var_set_errno(mysql_errno(con)); - handle_error(command, mysql_errno(con), mysql_error(con), - mysql_sqlstate(con), ds); + var_set_errno(my_err); + handle_error(command, my_err, mysql_error(con), + mysql_sqlstate(con), ds); return 0; /* Not connected */ } @@ -6370,7 +6376,7 @@ int do_done(struct st_command *command) if (*cur_block->delim) { /* Restore "old" delimiter after false if block */ - if (safe_strcpy(delimiter, sizeof(delimiter), cur_block->delim)) + if (safe_strcpy_truncated(delimiter, sizeof delimiter, cur_block->delim)) die("Delimiter too long, truncated"); delimiter_length= strlen(delimiter); @@ -6658,7 +6664,8 @@ void do_block(enum block_cmd cmd, struct st_command* command) else { /* Remember "old" delimiter if entering a false if block */ - if (safe_strcpy(cur_block->delim, sizeof(cur_block->delim), delimiter)) + if (safe_strcpy_truncated(cur_block->delim, sizeof cur_block->delim, + delimiter)) die("Delimiter too long, truncated"); } diff --git a/cmake/maintainer.cmake b/cmake/maintainer.cmake index dfc725c36b9..5143e745ac6 100644 --- a/cmake/maintainer.cmake +++ b/cmake/maintainer.cmake @@ -44,7 +44,7 @@ FOREACH(F ${MY_WARNING_FLAGS}) MY_CHECK_AND_SET_COMPILER_FLAG(${F} DEBUG RELWITHDEBINFO) ENDFOREACH() -SET(MY_ERROR_FLAGS -Werror) +SET(MY_ERROR_FLAGS -Werror -fno-operator-names) IF(CMAKE_COMPILER_IS_GNUCC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "6.0.0") SET(MY_ERROR_FLAGS ${MY_ERROR_FLAGS} -Wno-error=maybe-uninitialized) diff --git a/debian/autobake-deb.sh b/debian/autobake-deb.sh index 0e1b771b6cc..a09c10c6c0a 100755 --- a/debian/autobake-deb.sh +++ b/debian/autobake-deb.sh @@ -58,6 +58,7 @@ disable_libfmt() } architecture=$(dpkg-architecture -q DEB_BUILD_ARCH) +uname_machine=$(uname -m) # Parse release name and number from Linux standard base release # Example: @@ -188,6 +189,14 @@ then BUILDPACKAGE_DPKGCMD+=("eatmydata") fi +# If running autobake-debs.sh inside docker/podman host machine which +# has 64 bits cpu but container image is 32 bit make sure that we set +# correct arch with linux32 for 32 bit enviroment +if [ "$architecture" = "i386" ] && [ "$uname_machine" = "x86_64" ] +then + BUILDPACKAGE_DPKGCMD+=("linux32") +fi + BUILDPACKAGE_DPKGCMD+=("dpkg-buildpackage") # Using dpkg-buildpackage args diff --git a/debian/mariadb-server.postrm b/debian/mariadb-server.postrm index 841be00b6c6..601fe87f7e9 100644 --- a/debian/mariadb-server.postrm +++ b/debian/mariadb-server.postrm @@ -12,8 +12,6 @@ fi ${DEBIAN_SCRIPT_TRACE:+ echo "#42#DEBUG# RUNNING $0 $*" 1>&2 } -#DEBHELPER# - # # - Purge logs and data only if they are ours (#307473) # - Remove the mysql user only after all his owned files are purged. diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index 83ed8e4e5f9..a328f5e0ec7 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -901,14 +901,14 @@ bool is_system_table(const char *dbname, const char *tablename) DBUG_ASSERT(dbname); DBUG_ASSERT(tablename); - LEX_CSTRING lex_dbname; - LEX_CSTRING lex_tablename; + Lex_ident_db lex_dbname; + Lex_ident_table lex_tablename; lex_dbname.str = dbname; lex_dbname.length = strlen(dbname); lex_tablename.str = tablename; lex_tablename.length = strlen(tablename); - TABLE_CATEGORY tg = get_table_category(&lex_dbname, &lex_tablename); + TABLE_CATEGORY tg = get_table_category(lex_dbname, lex_tablename); return (tg == TABLE_CATEGORY_LOG) || (tg == TABLE_CATEGORY_SYSTEM); } diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index c4cb0fa3cb2..6357bb89e18 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -1600,11 +1600,11 @@ struct my_option xb_client_options[]= { GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"rsync", OPT_RSYNC, - "Obsolete depricated option", + "Obsolete, deprecated option", &ignored_option, &ignored_option, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-backup-locks", OPT_NO_BACKUP_LOCKS, - "Obsolete depricated option", + "Obsolete, deprecated option", &ignored_option, &ignored_option, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"force-non-empty-directories", OPT_FORCE_NON_EMPTY_DIRS, @@ -6996,7 +6996,7 @@ static bool check_all_privileges() if (opt_galera_info || opt_slave_info || opt_safe_slave_backup) { check_result |= check_privilege(granted_privileges, - "REPLICA MONITOR", "*", "*", + "SLAVE MONITOR", "*", "*", PRIVILEGE_WARNING); } diff --git a/include/m_string.h b/include/m_string.h index fcbb3769192..30d20322ae9 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -240,15 +240,14 @@ static inline void lex_string_set3(LEX_CSTRING *lex_str, const char *c_str, lex_str->length= len; } -/* - Copies src into dst and ensures dst is a NULL terminated C string. +/** + Copies a string. - Returns 1 if the src string was truncated due to too small size of dst. - Returns 0 if src completely fit within dst. Pads the remaining dst with '\0' - - Note: dst_size must be > 0 + @param dst destination buffer, will be NUL padded. + @param dst_size size of dst buffer, must be > 0 + @param src NUL terminated source string */ -static inline int safe_strcpy(char *dst, size_t dst_size, const char *src) +static inline void safe_strcpy(char *dst, size_t dst_size, const char *src) { DBUG_ASSERT(dst_size > 0); @@ -257,45 +256,49 @@ static inline int safe_strcpy(char *dst, size_t dst_size, const char *src) * * 2) IF there is no 0 byte in the first dst_size bytes of src, strncpy will * copy dst_size bytes, and the final byte won't be 0. - * - * In GCC 8+, the `-Wstringop-truncation` warning will object to strncpy() - * being used in this way, so we need to disable this warning for this - * single statement. */ -#if defined(__GNUC__) && __GNUC__ >= 8 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstringop-truncation" -#endif strncpy(dst, src, dst_size); -#if defined(__GNUC__) && __GNUC__ >= 8 -#pragma GCC diagnostic pop -#endif + dst[dst_size - 1]= 0; +} - if (dst[dst_size-1]) +/** + Copies a string, checking for truncation. + + @param dst destination buffer, will be NUL padded. + @param dst_size size of dst buffer, must be > 0 + @param src NUL terminated source string + + @retval 1 if the src string was truncated due to too small size of dst. + @retval 0 if src completely fit within dst, +*/ +static inline int safe_strcpy_truncated(char *dst, size_t dst_size, + const char *src) +{ + DBUG_ASSERT(dst_size > 0); + + strncpy(dst, src, dst_size); + if (dst[dst_size - 1]) { - /* Only possible in case (2), meaning src was truncated. */ - dst[dst_size-1]= 0; + dst[dst_size - 1]= 0; return 1; } return 0; } -/* - Appends src to dst and ensures dst is a NULL terminated C string. +/** + Appends src to dst and ensures dst is a NUL terminated C string. - Returns 1 if the src string was truncated due to too small size of dst. - Returns 0 if src completely fit within the remaining dst space. Pads the - remaining dst with '\0'. - - Note: dst_size must be > 0 + @retval 1 if the src string was truncated due to too small size of dst. + @retval 0 if src completely fit within the remaining dst space, + including NUL termination. */ static inline int safe_strcat(char *dst, size_t dst_size, const char *src) { size_t init_len= strlen(dst); - if (init_len >= dst_size - 1) + if (init_len > dst_size) return 1; - return safe_strcpy(dst + init_len, dst_size - init_len, src); + return safe_strcpy_truncated(dst + init_len, dst_size - init_len, src); } #ifdef __cplusplus diff --git a/include/my_rdtsc.h b/include/my_rdtsc.h index 21e44847d9a..31af5d48ccb 100644 --- a/include/my_rdtsc.h +++ b/include/my_rdtsc.h @@ -242,6 +242,18 @@ static inline ulonglong my_timer_cycles(void) #endif } +#if MY_TIMER_ROUTINE_CYCLES == 0 +static inline size_t my_pseudo_random(void) +{ + /* In some platforms, pthread_self() might return a structure + that cannot be converted to a number like this. Possible alternatives + could include gettid() or sched_getcpu(). */ + return ((size_t) pthread_self()) / 16; +} +#else +# define my_pseudo_random my_timer_cycles +#endif + /** A nanosecond timer. @return the current timer value, in nanoseconds. diff --git a/man/mariadb-admin.1 b/man/mariadb-admin.1 index 82c5dfc01fa..85dab8d2682 100644 --- a/man/mariadb-admin.1 +++ b/man/mariadb-admin.1 @@ -409,7 +409,7 @@ shell> \fBmysqladmin password "my new password"\fR .sp .\} .RS 4 -.it 1 an-trap +.it 1 .nr an-no-space-flag 1 .nr an-break-flag 1 .br diff --git a/man/mariadb-binlog.1 b/man/mariadb-binlog.1 index 70636d55e2f..e5f4a98949a 100644 --- a/man/mariadb-binlog.1 +++ b/man/mariadb-binlog.1 @@ -167,7 +167,7 @@ option is given\&. .sp .\} .RS 4 -.it 1 an-trap +.it 1 .nr an-no-space-flag 1 .nr an-break-flag 1 .br @@ -424,7 +424,7 @@ USE\&. (In particular, no cross\-database updates should be used\&.) .sp .\} .RS 4 -.it 1 an-trap +.it 1 .nr an-no-space-flag 1 .nr an-break-flag 1 .br @@ -1337,7 +1337,7 @@ capability enabled\&. .sp .\} .RS 4 -.it 1 an-trap +.it 1 .nr an-no-space-flag 1 .nr an-break-flag 1 .br @@ -1985,7 +1985,7 @@ shell> \fBmysqlbinlog \-v \-\-base64\-output=DECODE\-ROWS \fR\fB\fIlog_file\fR\f .sp .\} .RS 4 -.it 1 an-trap +.it 1 .nr an-no-space-flag 1 .nr an-break-flag 1 .br diff --git a/man/mariadb-check.1 b/man/mariadb-check.1 index 6191e933442..0b101ccb7d1 100644 --- a/man/mariadb-check.1 +++ b/man/mariadb-check.1 @@ -101,7 +101,7 @@ with partitioned tables is not supported\&. .sp .\} .RS 4 -.it 1 an-trap +.it 1 .nr an-no-space-flag 1 .nr an-break-flag 1 .br diff --git a/man/mariadb-dump.1 b/man/mariadb-dump.1 index 06ffd651c6c..d81ac2f7aed 100644 --- a/man/mariadb-dump.1 +++ b/man/mariadb-dump.1 @@ -2358,7 +2358,7 @@ file that contains its data\&. The option value is the directory in which to wri .sp .\} .RS 4 -.it 1 an-trap +.it 1 .nr an-no-space-flag 1 .nr an-break-flag 1 .br diff --git a/man/mariadb-upgrade.1 b/man/mariadb-upgrade.1 index 8532003a2b8..fb4988cd040 100644 --- a/man/mariadb-upgrade.1 +++ b/man/mariadb-upgrade.1 @@ -36,7 +36,7 @@ performs a table check\&. If any problems are found, a table repair is attempted .sp .\} .RS 4 -.it 1 an-trap +.it 1 .nr an-no-space-flag 1 .nr an-break-flag 1 .br @@ -54,7 +54,7 @@ with administrator privileges\&. You can do this by running a Command Prompt as .sp .\} .RS 4 -.it 1 an-trap +.it 1 .nr an-no-space-flag 1 .nr an-break-flag 1 .br diff --git a/man/mariadbd-safe.1 b/man/mariadbd-safe.1 index ffd1d691f97..a96e1487980 100644 --- a/man/mariadbd-safe.1 +++ b/man/mariadbd-safe.1 @@ -733,7 +733,7 @@ If none of these options is given, the default is .sp .\} .RS 4 -.it 1 an-trap +.it 1 .nr an-no-space-flag 1 .nr an-break-flag 1 .br diff --git a/man/myisamchk.1 b/man/myisamchk.1 index dae679bd4d5..1dc053337ec 100644 --- a/man/myisamchk.1 +++ b/man/myisamchk.1 @@ -38,7 +38,7 @@ with partitioned tables is not supported\&. .sp .\} .RS 4 -.it 1 an-trap +.it 1 .nr an-no-space-flag 1 .nr an-break-flag 1 .br @@ -168,7 +168,7 @@ the section called \(lqMYISAMCHK MEMORY USAGE\(rq\&. .sp .\} .RS 4 -.it 1 an-trap +.it 1 .nr an-no-space-flag 1 .nr an-break-flag 1 .br diff --git a/mysql-test/include/log_bin.combinations b/mysql-test/include/log_bin.combinations new file mode 100644 index 00000000000..1eeb8fb4614 --- /dev/null +++ b/mysql-test/include/log_bin.combinations @@ -0,0 +1,4 @@ +[binlogoff] + +[binlogon] +log-bin diff --git a/mysql-test/include/log_bin.inc b/mysql-test/include/log_bin.inc new file mode 100644 index 00000000000..d318c7967e1 --- /dev/null +++ b/mysql-test/include/log_bin.inc @@ -0,0 +1,3 @@ +# include file for test files that can be run with and without log-bin +# (see include/log_bin.combinations) + diff --git a/mysql-test/lib/My/Platform.pm b/mysql-test/lib/My/Platform.pm index f33875e14aa..279fea02ffb 100644 --- a/mysql-test/lib/My/Platform.pm +++ b/mysql-test/lib/My/Platform.pm @@ -23,7 +23,7 @@ use File::Path; use Carp; use base qw(Exporter); -our @EXPORT= qw(IS_CYGWIN IS_MSYS IS_WINDOWS IS_WIN32PERL IS_AIX IS_MAC +our @EXPORT= qw(IS_CYGWIN IS_MSYS IS_WINDOWS IS_WIN32PERL IS_AIX IS_MAC IS_FREEBSD native_path posix_path mixed_path check_socket_path_length process_alive open_for_append); @@ -79,6 +79,15 @@ BEGIN { } } +BEGIN { + if ($^O eq "freebsd") { + eval 'sub IS_FREEBSD { 1 }'; + } + else { + eval 'sub IS_FREEBSD { 0 }'; + } +} + # # native_path # Convert from path format used by perl to the underlying diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index be1c2be8d3f..00c51c7eee4 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -398,7 +398,8 @@ sub collect_suite_name($$) { my @dirs = my_find_dir(dirname($::glob_mysql_test_dir), ["mariadb-test/suite", "mysql-test/suite", @plugin_suitedirs ], - $suitename); + $suitename, + $::opt_skip_not_found ? NOT_REQUIRED : undef); # # if $suitename contained wildcards, we'll have many suites and # their overlays here. Let's group them appropriately. diff --git a/mysql-test/main/analyze_engine_stats2.opt b/mysql-test/main/analyze_engine_stats2.opt new file mode 100644 index 00000000000..a5bb9a93636 --- /dev/null +++ b/mysql-test/main/analyze_engine_stats2.opt @@ -0,0 +1 @@ +--innodb_buffer_pool_dump_at_shutdown=off --innodb_buffer_pool_load_at_startup=off --innodb-stats-persistent=1 --innodb-stats-auto-recalc=off diff --git a/mysql-test/main/analyze_engine_stats2.result b/mysql-test/main/analyze_engine_stats2.result new file mode 100644 index 00000000000..08a09538426 --- /dev/null +++ b/mysql-test/main/analyze_engine_stats2.result @@ -0,0 +1,68 @@ +# +# MDEV-34125: ANALYZE FORMAT=JSON: r_engine_stats.pages_read_time_ms has wrong scale +# +create table t1 ( +a varchar(255), +b varchar(255), +c varchar(255), +d varchar(255), +primary key(a,b,c,d) +) engine=innodb; +SET STATEMENT unique_checks=0,foreign_key_checks=0 FOR +insert into t1 select +repeat(uuid(), 7), +repeat(uuid(), 7), +repeat(uuid(), 7), +repeat(uuid(), 7) +from seq_1_to_16384; +SET GLOBAL innodb_fast_shutdown=0; +# restart +set log_slow_verbosity='engine'; +set long_query_time=0.0; +set @js='$analyze_output'; +select @js; +@js +{ + "query_optimization": { + "r_total_time_ms": "REPLACED" + }, + "query_block": { + "select_id": 1, + "cost": 0.011647987, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "nested_loop": [ + { + "table": { + "table_name": "t1", + "access_type": "index", + "key": "PRIMARY", + "key_length": "1028", + "used_key_parts": ["a", "b", "c", "d"], + "loops": 1, + "r_loops": 1, + "rows": 1, + "r_rows": 16384, + "cost": 0.0110178, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "r_engine_stats": { + "pages_accessed": "REPLACED", + "pages_read_count": "REPLACED", + "pages_read_time_ms": "REPLACED" + }, + "filtered": 100, + "r_filtered": 100 + } + } + ] + } +} +set @pages_read_time_ms= +(select json_value(@js,'$.query_block.nested_loop[0].table.r_engine_stats.pages_read_time_ms')); + + + OK: pages_read_time is same in slow log and ANALYZE + +set long_query_time=default; +drop table t1; diff --git a/mysql-test/main/analyze_engine_stats2.test b/mysql-test/main/analyze_engine_stats2.test new file mode 100644 index 00000000000..36f6a76585e --- /dev/null +++ b/mysql-test/main/analyze_engine_stats2.test @@ -0,0 +1,75 @@ +# +# r_engine_stats tests that require slow query log. +# +--source include/analyze-format.inc +--source include/have_sequence.inc +--source include/have_innodb.inc + +--echo # +--echo # MDEV-34125: ANALYZE FORMAT=JSON: r_engine_stats.pages_read_time_ms has wrong scale +--echo # + +# Each row is 1K. +create table t1 ( + a varchar(255), + b varchar(255), + c varchar(255), + d varchar(255), + primary key(a,b,c,d) +) engine=innodb; + +# The data size is 160K * 1K = 160M +# 16M / (page_size=16K) = 1K pages. +SET STATEMENT unique_checks=0,foreign_key_checks=0 FOR +insert into t1 select + repeat(uuid(), 7), + repeat(uuid(), 7), + repeat(uuid(), 7), + repeat(uuid(), 7) +from seq_1_to_16384; + +SET GLOBAL innodb_fast_shutdown=0; +source include/restart_mysqld.inc; +set log_slow_verbosity='engine'; +set long_query_time=0.0; + +let $analyze_output= `analyze format=json +select * from t1 force index (PRIMARY) order by a desc, b desc, c desc, d desc`; +evalp set @js='$analyze_output'; + +# Print it out for user-friendlines +--replace_regex /("(r_[a-z_]*_time_ms|pages[^"]*)": )[^, \n]*/\1"REPLACED"/ +select @js; + +set @pages_read_time_ms= + (select json_value(@js,'$.query_block.nested_loop[0].table.r_engine_stats.pages_read_time_ms')); + +let ANALYZE_PAGES=`select @pages_read_time_ms`; +let SLOW_LOG_FILE= `select @@slow_query_log_file`; + +perl; + my $slow_log_file= $ENV{'SLOW_LOG_FILE'} or die "SLOW_LOG_FILE not set"; + my $analyze_pages=$ENV{'ANALYZE_PAGES'}; + open(FILE, $slow_log_file) or die "Failed to open $slow_log_file"; + # We didn't run any queries touching a storage engine after the query of + # interest, so we will be fine here if we just get the last occurrence of + # Pages_read_time: NNNN in the file + while() { + $slow_log_pages=$1 if (/Pages_read_time: ([0-9.]+)/); + } + close(FILE); + + if ( $slow_log_pages > $analyze_pages * 0.95 && + $slow_log_pages < $analyze_pages * 1.05) { + print "\n\n OK: pages_read_time is same in slow log and ANALYZE\n\n"; + } else { + print "\n\n FAIL: $slow_log_pages not equal to $analyze_pages\n"; + } + +EOF + + +set long_query_time=default; +drop table t1; + + diff --git a/mysql-test/main/connect-no-db.result b/mysql-test/main/connect-no-db.result new file mode 100644 index 00000000000..75597c0753c --- /dev/null +++ b/mysql-test/main/connect-no-db.result @@ -0,0 +1,9 @@ +# +# MDEV-34226 On startup: UBSAN: applying zero offset to null pointer in my_copy_fix_mb from strings/ctype-mb.c and other locations +# +connect con1,localhost,root,,"*NO-ONE*"; +SELECT database(); +database() +NULL +disconnect con1; +connection default; diff --git a/mysql-test/main/connect-no-db.test b/mysql-test/main/connect-no-db.test new file mode 100644 index 00000000000..bc36499e703 --- /dev/null +++ b/mysql-test/main/connect-no-db.test @@ -0,0 +1,10 @@ +--echo # +--echo # MDEV-34226 On startup: UBSAN: applying zero offset to null pointer in my_copy_fix_mb from strings/ctype-mb.c and other locations +--echo # + +# Connect without a database + +connect (con1,localhost,root,,"*NO-ONE*"); +SELECT database(); +disconnect con1; +connection default; diff --git a/mysql-test/main/create.result b/mysql-test/main/create.result index d7f4eb274ea..ab466fdaebb 100644 --- a/mysql-test/main/create.result +++ b/mysql-test/main/create.result @@ -2060,4 +2060,11 @@ DROP TABLE t1; # CREATE TABLE t1 (id1 INT, id2 INT, primary key (id1), unique index (id2) visible); drop table t1; +# +# MDEV-32376 SHOW CREATE DATABASE statement crashes the server when db name contains some unicode characters, ASAN stack-buffer-overflow +# +SET NAMES utf8mb3; +SHOW CREATE DATABASE `#testone#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■`; +ERROR 42000: Incorrect database name '#testone#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■...' +SET NAMES DEFAULT; # End of 10.5 Test diff --git a/mysql-test/main/create.test b/mysql-test/main/create.test index 088cb4e397f..dada6963fdb 100644 --- a/mysql-test/main/create.test +++ b/mysql-test/main/create.test @@ -1935,4 +1935,13 @@ DROP TABLE t1; CREATE TABLE t1 (id1 INT, id2 INT, primary key (id1), unique index (id2) visible); drop table t1; +--echo # +--echo # MDEV-32376 SHOW CREATE DATABASE statement crashes the server when db name contains some unicode characters, ASAN stack-buffer-overflow +--echo # + +SET NAMES utf8mb3; +--error ER_WRONG_DB_NAME +SHOW CREATE DATABASE `#testone#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■`; +SET NAMES DEFAULT; + --echo # End of 10.5 Test diff --git a/mysql-test/main/ctype_utf8mb4_unicode_ci_def.result b/mysql-test/main/ctype_utf8mb4_unicode_ci_def.result index 2e15931248b..a80d6160ed8 100644 --- a/mysql-test/main/ctype_utf8mb4_unicode_ci_def.result +++ b/mysql-test/main/ctype_utf8mb4_unicode_ci_def.result @@ -9,3 +9,48 @@ DROP TABLE t1; # # End of 10.3 tests # +# +# Start of 10.11 tests +# +# +# MDEV-34288 SET NAMES DEFAULT crashes `mariadbd --collation-server=utf8mb4_unicode_ci` +# +SET NAMES DEFAULT COLLATE latin1_bin; +ERROR 42000: COLLATION 'latin1_bin' is not valid for CHARACTER SET 'utf8mb4' +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; +@@character_set_connection @@collation_connection @@character_set_results +latin1 latin1_swedish_ci latin1 +SET NAMES DEFAULT COLLATE utf8mb4_bin; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; +@@character_set_connection @@collation_connection @@character_set_results +utf8mb4 utf8mb4_bin utf8mb4 +SET NAMES DEFAULT COLLATE uca1400_ai_ci; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; +@@character_set_connection @@collation_connection @@character_set_results +utf8mb4 utf8mb4_uca1400_ai_ci utf8mb4 +SET @@global.character_set_client=latin1; +SET NAMES DEFAULT; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; +@@character_set_connection @@collation_connection @@character_set_results +latin1 latin1_swedish_ci latin1 +SET @@global.character_set_client=utf8mb3; +SET NAMES DEFAULT; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; +@@character_set_connection @@collation_connection @@character_set_results +utf8mb3 utf8mb3_general_ci utf8mb3 +SET @@global.character_set_client=DEFAULT; +SET NAMES DEFAULT; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; +@@character_set_connection @@collation_connection @@character_set_results +utf8mb4 utf8mb4_general_ci utf8mb4 +SET NAMES DEFAULT; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; +@@character_set_connection @@collation_connection @@character_set_results +utf8mb4 utf8mb4_general_ci utf8mb4 +SET NAMES DEFAULT COLLATE DEFAULT; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; +@@character_set_connection @@collation_connection @@character_set_results +utf8mb4 utf8mb4_general_ci utf8mb4 +# +# End of 10.11 tests +# diff --git a/mysql-test/main/ctype_utf8mb4_unicode_ci_def.test b/mysql-test/main/ctype_utf8mb4_unicode_ci_def.test index fb7fbe04e3b..3e55d1e6b1e 100644 --- a/mysql-test/main/ctype_utf8mb4_unicode_ci_def.test +++ b/mysql-test/main/ctype_utf8mb4_unicode_ci_def.test @@ -13,3 +13,45 @@ DROP TABLE t1; --echo # --echo # End of 10.3 tests --echo # + + +--echo # +--echo # Start of 10.11 tests +--echo # + +--echo # +--echo # MDEV-34288 SET NAMES DEFAULT crashes `mariadbd --collation-server=utf8mb4_unicode_ci` +--echo # + +--error ER_COLLATION_CHARSET_MISMATCH +SET NAMES DEFAULT COLLATE latin1_bin; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; + +SET NAMES DEFAULT COLLATE utf8mb4_bin; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; + +SET NAMES DEFAULT COLLATE uca1400_ai_ci; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; + +SET @@global.character_set_client=latin1; +SET NAMES DEFAULT; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; + +SET @@global.character_set_client=utf8mb3; +SET NAMES DEFAULT; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; + +SET @@global.character_set_client=DEFAULT; +SET NAMES DEFAULT; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; + +SET NAMES DEFAULT; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; + +SET NAMES DEFAULT COLLATE DEFAULT; +SELECT @@character_set_connection, @@collation_connection, @@character_set_results; + + +--echo # +--echo # End of 10.11 tests +--echo # diff --git a/mysql-test/main/drop.result b/mysql-test/main/drop.result index 73beabc35fa..f4415117dc9 100644 --- a/mysql-test/main/drop.result +++ b/mysql-test/main/drop.result @@ -258,3 +258,8 @@ drop database mysqltest; Warnings: Note 1008 Can't drop database 'mysqltest'; database doesn't exist set @@session.sql_if_exists=0; +# +# MDEV-34205 ASAN stack-buffer-overflow in strxnmov | frm_file_exists +# +DROP TABLE `##################################################_long`.`#################################################_long`; +ERROR 42S02: Unknown table '##################################################_long.#########################################...' diff --git a/mysql-test/main/drop.test b/mysql-test/main/drop.test index 5185ce30db0..6b926d3f0c1 100644 --- a/mysql-test/main/drop.test +++ b/mysql-test/main/drop.test @@ -361,3 +361,9 @@ drop table mysqltest.does_not_exists; drop database mysqltest; drop database mysqltest; set @@session.sql_if_exists=0; + +--echo # +--echo # MDEV-34205 ASAN stack-buffer-overflow in strxnmov | frm_file_exists +--echo # +--error ER_BAD_TABLE_ERROR +DROP TABLE `##################################################_long`.`#################################################_long`; diff --git a/mysql-test/main/dyncol.result b/mysql-test/main/dyncol.result index 64ce60b4e45..d0a34a10ab0 100644 --- a/mysql-test/main/dyncol.result +++ b/mysql-test/main/dyncol.result @@ -1950,12 +1950,6 @@ ex # End of 10.4 tests # # -# Start of 10.5 tests -# -# -# Start of 10.5 tests -# -# # MDEV-33788 HEX(COLUMN_CREATE(.. AS CHAR ...)) fails with --view-protocol # SELECT hex(column_create(1,'a' AS CHAR CHARACTER SET utf8mb3 COLLATE utf8mb3_bin)) AS ex; @@ -1967,5 +1961,16 @@ SELECT hex(column_add(column_create( ex 00020001000302001353612162 # -# Start of 10.5 tests +# MDEV-31566 Fix buffer overrun of column_json function # +create table t1 ( +c1 varchar(32) primary key, +d1 blob +); +insert into t1 values ('var', 0x0402000A0000000300030023076A736E7375626A6563742E0005006C0027000200290002002B0002002D0002002F0002000C31000C3B000C4B000C51000F62006631663266336634663509E5A79AE8BF9CE6B48B0FE8819AE9809AE98791E6A1A5E5BA970537343530301031313634332F393634352F31313630300C080000000000EFBFBDEFBFBD192E), ('zzz', 0x0402000900000003000300740C6A736E766F6C756D652E000900EFBFBD004300020045000200470003004A0004004E00050053000500580005005D000500620005000C67000C6A000C6D000C7000052C00051B00052C000CEFBFBD0007EFBFBD006638663966313070696332626F785F63626F785F67626F785F6B626F785F7666355F696402343402343402333241687474703A2F2F6F73732E68646238382E636F6D2F302F70686F746F2F30373865653765376336343634616236386130343833373333323636613532612E67696608302E303532323732244F1E00030180C106); +select c1,column_json(d1) as not_crashing from t1 order by c1; +c1 not_crashing +var {"jsn":"\u0000\u0005\u0000l\u0000'\u0000\u0002\u0000)\u0000\u0002\u0000+\u0000\u0002\u0000-\u0000\u0002\u0000/\u0000\u0002\u0000\u000C1\u0000\u000C;\u0000\u000CK\u0000\u000CQ\u0000\u000Fb\u0000f1f2f3f4f5\u0009姚远洋\u000F聚通金桥店\u000574500\u001011643/9645/11600\u000C\u0008\u0000\u0000\u0000\u0000\u0000��\u0019","subject":""} +zzz {"jsn":"\u0000\u0009\u0000�\u0000C\u0000\u0002\u0000E\u0000\u0002\u0000G\u0000\u0003\u0000J\u0000\u0004\u0000N\u0000\u0005\u0000S\u0000\u0005\u0000X\u0000\u0005\u0000]\u0000\u0005\u0000b\u0000\u0005\u0000\u000Cg\u0000\u000Cj\u0000\u000Cm\u0000\u000Cp\u0000\u0005,\u0000\u0005\u001B\u0000\u0005,\u0000\u000C�\u0000\u0007�\u0000f8f9f10pic2box_cbox_gbox_kbox_vf5_id\u000244\u000244\u000232Ahttp://oss.hdb88.com/0/photo/078ee7e7c6464ab68a0483733266a52a.gif\u00080.052272$O\u001E\u0000","volume":193.6} +drop table t1; +# End of 10.5 tests diff --git a/mysql-test/main/dyncol.test b/mysql-test/main/dyncol.test index 1343025d5c5..693c768768f 100644 --- a/mysql-test/main/dyncol.test +++ b/mysql-test/main/dyncol.test @@ -1001,14 +1001,6 @@ SELECT HEX(COLUMN_ADD(COLUMN_CREATE(1,10),2,NULL,1,NULL)) as ex; --echo # End of 10.4 tests --echo # ---echo # ---echo # Start of 10.5 tests ---echo # - ---echo # ---echo # Start of 10.5 tests ---echo # - --echo # --echo # MDEV-33788 HEX(COLUMN_CREATE(.. AS CHAR ...)) fails with --view-protocol --echo # @@ -1019,5 +1011,18 @@ SELECT hex(column_add(column_create( 2, 'b' AS CHAR CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci)) AS ex; --echo # ---echo # Start of 10.5 tests +--echo # MDEV-31566 Fix buffer overrun of column_json function --echo # + + +create table t1 ( + c1 varchar(32) primary key, + d1 blob +); +insert into t1 values ('var', 0x0402000A0000000300030023076A736E7375626A6563742E0005006C0027000200290002002B0002002D0002002F0002000C31000C3B000C4B000C51000F62006631663266336634663509E5A79AE8BF9CE6B48B0FE8819AE9809AE98791E6A1A5E5BA970537343530301031313634332F393634352F31313630300C080000000000EFBFBDEFBFBD192E), ('zzz', 0x0402000900000003000300740C6A736E766F6C756D652E000900EFBFBD004300020045000200470003004A0004004E00050053000500580005005D000500620005000C67000C6A000C6D000C7000052C00051B00052C000CEFBFBD0007EFBFBD006638663966313070696332626F785F63626F785F67626F785F6B626F785F7666355F696402343402343402333241687474703A2F2F6F73732E68646238382E636F6D2F302F70686F746F2F30373865653765376336343634616236386130343833373333323636613532612E67696608302E303532323732244F1E00030180C106); + +select c1,column_json(d1) as not_crashing from t1 order by c1; + +drop table t1; + +--echo # End of 10.5 tests diff --git a/mysql-test/main/func_date_add.result b/mysql-test/main/func_date_add.result index a6201a3c23f..1c2d9ab5eb1 100644 --- a/mysql-test/main/func_date_add.result +++ b/mysql-test/main/func_date_add.result @@ -200,3 +200,34 @@ select 30 + (20010101 + interval 2 day), x from v1; 20010133 20010133 drop view v1; End of 10.2 tests +# +# Start of 10.5 tests +# +# +# MDEV-30931 UBSAN: negation of -X cannot be represented in type 'long long int'; cast to an unsigned type to negate this value to itself in get_interval_value on SELECT +# +SELECT DATE_ADD('01-01-23',INTERVAL '9223372036854775808-02' WEEK); +DATE_ADD('01-01-23',INTERVAL '9223372036854775808-02' WEEK) +NULL +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '9223372036854775808-02' +Warning 1441 Datetime function: datetime field overflow +SELECT DATE_ADD('01-01-23',INTERVAL -9223372036854775807 WEEK); +DATE_ADD('01-01-23',INTERVAL -9223372036854775807 WEEK) +NULL +Warnings: +Warning 1441 Datetime function: datetime field overflow +SELECT DATE_ADD('01-01-23',INTERVAL -9223372036854775808 WEEK); +DATE_ADD('01-01-23',INTERVAL -9223372036854775808 WEEK) +NULL +Warnings: +Warning 1441 Datetime function: datetime field overflow +SELECT DATE_ADD('01-01-23',INTERVAL -9223372036854775809 WEEK); +DATE_ADD('01-01-23',INTERVAL -9223372036854775809 WEEK) +NULL +Warnings: +Warning 1916 Got overflow when converting '-9223372036854775809' to INT. Value truncated +Warning 1441 Datetime function: datetime field overflow +# +# End of 10.5 tests +# diff --git a/mysql-test/main/func_date_add.test b/mysql-test/main/func_date_add.test index f9287b952d2..aa00fd144e2 100644 --- a/mysql-test/main/func_date_add.test +++ b/mysql-test/main/func_date_add.test @@ -169,3 +169,20 @@ select 30 + (20010101 + interval 2 day), x from v1; drop view v1; --echo End of 10.2 tests + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-30931 UBSAN: negation of -X cannot be represented in type 'long long int'; cast to an unsigned type to negate this value to itself in get_interval_value on SELECT +--echo # + +SELECT DATE_ADD('01-01-23',INTERVAL '9223372036854775808-02' WEEK); +SELECT DATE_ADD('01-01-23',INTERVAL -9223372036854775807 WEEK); +SELECT DATE_ADD('01-01-23',INTERVAL -9223372036854775808 WEEK); +SELECT DATE_ADD('01-01-23',INTERVAL -9223372036854775809 WEEK); + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index fec066a1177..a403b6b3ae2 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -1717,6 +1717,17 @@ SELECT JSON_REMOVE('{"A": { "B": 1 }}', '$.A.B.C.D'); JSON_REMOVE('{"A": { "B": 1 }}', '$.A.B.C.D') {"A": {"B": 1}} # +# MDEV-34143: Server crashes when executing JSON_EXTRACT after setting non-default collation_connection +# +SET @save_collation_connection= @@collation_connection; +SET collation_connection='utf16_bin'; +SELECT JSON_EXTRACT('{"a": 1,"b": 2}','$.a'); +JSON_EXTRACT('{"a": 1,"b": 2}','$.a') +NULL +Warnings: +Warning 4036 Character disallowed in JSON in argument 1 to function 'json_extract' at position 2 +SET @@collation_connection= @save_collation_connection; +# # End of 10.5 tests # # diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index 050e54f2b21..a9688f2bee8 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -1152,6 +1152,20 @@ SELECT JSON_TYPE(json_value(JSON_OBJECT("id", 1, "name", 'Monty', "date", Cast(' SELECT JSON_REMOVE('{"A": { "B": 1 }}', '$.A.B.C.D'); + +--echo # +--echo # MDEV-34143: Server crashes when executing JSON_EXTRACT after setting non-default collation_connection +--echo # + +SET @save_collation_connection= @@collation_connection; + +SET collation_connection='utf16_bin'; +--disable_service_connection +SELECT JSON_EXTRACT('{"a": 1,"b": 2}','$.a'); +--enable_service_connection + +SET @@collation_connection= @save_collation_connection; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/func_str.result b/mysql-test/main/func_str.result index 59595dffa99..3706d54f597 100644 --- a/mysql-test/main/func_str.result +++ b/mysql-test/main/func_str.result @@ -5310,6 +5310,14 @@ NULL DROP TABLE t1; DROP VIEW v1; # +# MDEV-28387 UBSAN: runtime error: negation of -9223372036854775808 cannot be represented in type 'long long int'; cast to an unsigned type to negate this value to itself in my_strtoll10 on SELECT +# +SET @a='-9223372036854775808'; +CREATE TABLE t (c1 INT,c2 CHAR); +SELECT SUBSTR(0,@a) FROM t; +SUBSTR(0,@a) +DROP TABLE t; +# # End of 10.5 tests # # diff --git a/mysql-test/main/func_str.test b/mysql-test/main/func_str.test index 163b65d5578..488ea08e0a0 100644 --- a/mysql-test/main/func_str.test +++ b/mysql-test/main/func_str.test @@ -1548,6 +1548,7 @@ CREATE TABLE t1 ( a TEXT ); SELECT insert( substring_index( 'a', 'a', 'b' ), 1, 0, 'x' ); --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/bug58165.txt' INTO TABLE t1; +--remove_file $MYSQLTEST_VARDIR/tmp/bug58165.txt SELECT * FROM t1; DROP TABLE t1; @@ -2351,6 +2352,15 @@ DROP TABLE t1; DROP VIEW v1; +--echo # +--echo # MDEV-28387 UBSAN: runtime error: negation of -9223372036854775808 cannot be represented in type 'long long int'; cast to an unsigned type to negate this value to itself in my_strtoll10 on SELECT +--echo # + +SET @a='-9223372036854775808'; # Quite specific value; considerably varying it will not work +CREATE TABLE t (c1 INT,c2 CHAR); +SELECT SUBSTR(0,@a) FROM t; +DROP TABLE t; + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/lowercase_table2.result b/mysql-test/main/lowercase_table2.result index e062edd0a69..d89a916611c 100644 --- a/mysql-test/main/lowercase_table2.result +++ b/mysql-test/main/lowercase_table2.result @@ -409,6 +409,7 @@ show tables like 't%'; Tables_in_test (t%) t1 t2 +drop temporary table t2, T1; # End of 11.2 tests # # MDEV-32026 lowercase_table2.test failures in 11.3 diff --git a/mysql-test/main/lowercase_table2.test b/mysql-test/main/lowercase_table2.test index 99ba73fed5b..47c84014381 100644 --- a/mysql-test/main/lowercase_table2.test +++ b/mysql-test/main/lowercase_table2.test @@ -347,6 +347,7 @@ select table_name from information_schema.tables where table_schema='test' and table_name='T1'; show tables like '_1'; show tables like 't%'; +drop temporary table t2, T1; --echo # End of 11.2 tests diff --git a/mysql-test/main/lowercase_table5.result b/mysql-test/main/lowercase_table5.result index 77318a8e2aa..2baa50282b5 100644 --- a/mysql-test/main/lowercase_table5.result +++ b/mysql-test/main/lowercase_table5.result @@ -47,3 +47,145 @@ DROP PROCEDURE SP; # # End of 10.4 tests # +# +# Start of 10.5 tests +# +# +# MDEV-33084 LASTVAL(t1) and LASTVAL(T1) do not work well with lower-case-table-names=0 +# +CREATE SEQUENCE t1; +CREATE SEQUENCE T1; +SELECT nextval(t1), lastval(t1); +nextval(t1) lastval(t1) +1 1 +SELECT nextval(T1), lastval(T1); +nextval(T1) lastval(T1) +1 1 +SELECT lastval(t1), lastval(T1) l2; +lastval(t1) l2 +1 1 +DROP SEQUENCE t1, T1; +# +# MDEV-33086 SHOW OPEN TABLES IN DB1 -- is case insensitive with lower-case-table-names=0 +# +CREATE DATABASE db1; +CREATE TABLE db1.t1 (a INT); +SELECT * FROM db1.t1; +a +SHOW OPEN TABLES IN DB1; +Database Table In_use Name_locked +SHOW OPEN TABLES IN db1; +Database Table In_use Name_locked +db1 t1 0 0 +DROP DATABASE db1; +# +# MDEV-33088 Cannot create triggers in the database `MYSQL` +# +CREATE DATABASE MYSQL; +CREATE TABLE MYSQL.t1 (a INT); +CREATE TABLE MYSQL.t2 (a INT); +CREATE TRIGGER MYSQL.tr1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES (new.a); +INSERT INTO MYSQL.t1 VALUES (10); +SELECT * FROM MYSQL.t1; +a +10 +SELECT * FROM MYSQL.t2; +a +10 +DROP DATABASE MYSQL; +# +# MDEV-33103 LOCK TABLE t1 AS t2 -- alias is not case sensitive with lower-case-table-names=0 +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1); +LOCK TABLE t1 AS t2 READ; +SELECT * FROM t1 AS t2; +a +1 +UNLOCK TABLES; +LOCK TABLE t1 AS t2 READ; +SELECT * FROM t1 AS T2; +ERROR HY000: Table 'T2' was not locked with LOCK TABLES +UNLOCK TABLES; +DROP TABLE t1; +# +# MDEV-33108 TABLE_STATISTICS and INDEX_STATISTICS are case insensitive with lower-case-table-names=0 +# +SET GLOBAL userstat=1; +CREATE TABLE t1 (a INT, KEY(a)); +INSERT INTO t1 VALUES (1),(2),(3),(4); +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +CREATE TABLE T1 (a INT, KEY(a)); +INSERT INTO T1 VALUES (1),(2),(3),(4); +SELECT * FROM T1 ORDER BY a; +a +1 +2 +3 +4 +SELECT * FROM INFORMATION_SCHEMA.TABLE_STATISTICS ORDER BY BINARY TABLE_NAME; +TABLE_SCHEMA TABLE_NAME ROWS_READ ROWS_CHANGED ROWS_CHANGED_X_INDEXES +test T1 4 4 4 +test t1 4 4 4 +SELECT * FROM INFORMATION_SCHEMA.INDEX_STATISTICS ORDER BY BINARY TABLE_NAME; +TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ +test T1 a 4 +test t1 a 4 +DROP TABLE t1; +DROP TABLE T1; +SET GLOBAL userstat=DEFAULT; +# +# MDEV-33109 DROP DATABASE MYSQL -- does not drop SP with lower-case-table-names=0 +# +CREATE DATABASE MYSQL; +CREATE FUNCTION MYSQL.f1() RETURNS INT RETURN 1; +DROP DATABASE MYSQL; +SELECT db, name, body FROM mysql.proc WHERE db=BINARY 'MYSQL' AND name='f1'; +db name body +# +# MDEV-33110 HANDLER commands are case insensitive with lower-case-table-names=0 +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +a +1 +CREATE OR REPLACE TABLE T1 (a INT); +DROP TABLE T1; +HANDLER t1 READ NEXT; +a +2 +HANDLER t1 CLOSE; +DROP TABLE t1; +# +# MDEV-33120 System log table names are case insensitive with lower-cast-table-names=0 +# +CREATE TABLE mysql.GENERAL_log (a INT); +INSERT INTO mysql.GENERAL_log VALUES (1),(2); +DROP TABLE mysql.GENERAL_log; +CREATE TABLE mysql.SLOW_log (a INT); +INSERT INTO mysql.SLOW_log VALUES (1),(2); +DROP TABLE mysql.SLOW_log; +CREATE TABLE mysql.TRANSACTION_registry (a INT); +INSERT INTO mysql.TRANSACTION_registry VALUES (1),(2); +DROP TABLE mysql.TRANSACTION_registry; +CREATE DATABASE MYSQL; +CREATE TABLE MYSQL.general_log (a INT); +INSERT INTO MYSQL.general_log VALUES (1),(2); +DROP TABLE MYSQL.general_log; +CREATE TABLE MYSQL.slow_log (a INT); +INSERT INTO MYSQL.slow_log VALUES (1),(2); +DROP TABLE MYSQL.slow_log; +CREATE TABLE MYSQL.transaction_registry (a INT); +INSERT INTO MYSQL.transaction_registry VALUES (1),(2); +DROP TABLE MYSQL.transaction_registry; +DROP DATABASE MYSQL; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/lowercase_table5.test b/mysql-test/main/lowercase_table5.test index 0103dbf5fd2..fcbb3fefb33 100644 --- a/mysql-test/main/lowercase_table5.test +++ b/mysql-test/main/lowercase_table5.test @@ -49,3 +49,141 @@ DROP PROCEDURE SP; --echo # --echo # End of 10.4 tests --echo # + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-33084 LASTVAL(t1) and LASTVAL(T1) do not work well with lower-case-table-names=0 +--echo # + +CREATE SEQUENCE t1; +CREATE SEQUENCE T1; +--disable_ps2_protocol +SELECT nextval(t1), lastval(t1); +SELECT nextval(T1), lastval(T1); +SELECT lastval(t1), lastval(T1) l2; +--enable_ps2_protocol +DROP SEQUENCE t1, T1; + +--echo # +--echo # MDEV-33086 SHOW OPEN TABLES IN DB1 -- is case insensitive with lower-case-table-names=0 +--echo # + +CREATE DATABASE db1; +CREATE TABLE db1.t1 (a INT); +SELECT * FROM db1.t1; +SHOW OPEN TABLES IN DB1; +SHOW OPEN TABLES IN db1; +DROP DATABASE db1; + +--echo # +--echo # MDEV-33088 Cannot create triggers in the database `MYSQL` +--echo # + +CREATE DATABASE MYSQL; +CREATE TABLE MYSQL.t1 (a INT); +CREATE TABLE MYSQL.t2 (a INT); +CREATE TRIGGER MYSQL.tr1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES (new.a); +INSERT INTO MYSQL.t1 VALUES (10); +SELECT * FROM MYSQL.t1; +SELECT * FROM MYSQL.t2; +DROP DATABASE MYSQL; + + +--echo # +--echo # MDEV-33103 LOCK TABLE t1 AS t2 -- alias is not case sensitive with lower-case-table-names=0 +--echo # + +--disable_view_protocol +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1); +LOCK TABLE t1 AS t2 READ; +SELECT * FROM t1 AS t2; +UNLOCK TABLES; +LOCK TABLE t1 AS t2 READ; +--error ER_TABLE_NOT_LOCKED +SELECT * FROM t1 AS T2; +UNLOCK TABLES; +DROP TABLE t1; +--enable_view_protocol + + +--echo # +--echo # MDEV-33108 TABLE_STATISTICS and INDEX_STATISTICS are case insensitive with lower-case-table-names=0 +--echo # + +SET GLOBAL userstat=1; +CREATE TABLE t1 (a INT, KEY(a)); +INSERT INTO t1 VALUES (1),(2),(3),(4); +--disable_ps2_protocol +SELECT * FROM t1 ORDER BY a; +CREATE TABLE T1 (a INT, KEY(a)); +INSERT INTO T1 VALUES (1),(2),(3),(4); +SELECT * FROM T1 ORDER BY a; +--enable_ps2_protocol +SELECT * FROM INFORMATION_SCHEMA.TABLE_STATISTICS ORDER BY BINARY TABLE_NAME; +SELECT * FROM INFORMATION_SCHEMA.INDEX_STATISTICS ORDER BY BINARY TABLE_NAME; +DROP TABLE t1; +DROP TABLE T1; +SET GLOBAL userstat=DEFAULT; + + +--echo # +--echo # MDEV-33109 DROP DATABASE MYSQL -- does not drop SP with lower-case-table-names=0 +--echo # + +CREATE DATABASE MYSQL; +CREATE FUNCTION MYSQL.f1() RETURNS INT RETURN 1; +DROP DATABASE MYSQL; +SELECT db, name, body FROM mysql.proc WHERE db=BINARY 'MYSQL' AND name='f1'; + + +--echo # +--echo # MDEV-33110 HANDLER commands are case insensitive with lower-case-table-names=0 +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +CREATE OR REPLACE TABLE T1 (a INT); +DROP TABLE T1; +HANDLER t1 READ NEXT; +HANDLER t1 CLOSE; +DROP TABLE t1; + +--echo # +--echo # MDEV-33120 System log table names are case insensitive with lower-cast-table-names=0 +--echo # + +CREATE TABLE mysql.GENERAL_log (a INT); +INSERT INTO mysql.GENERAL_log VALUES (1),(2); +DROP TABLE mysql.GENERAL_log; + +CREATE TABLE mysql.SLOW_log (a INT); +INSERT INTO mysql.SLOW_log VALUES (1),(2); +DROP TABLE mysql.SLOW_log; + +CREATE TABLE mysql.TRANSACTION_registry (a INT); +INSERT INTO mysql.TRANSACTION_registry VALUES (1),(2); +DROP TABLE mysql.TRANSACTION_registry; + +CREATE DATABASE MYSQL; +CREATE TABLE MYSQL.general_log (a INT); +INSERT INTO MYSQL.general_log VALUES (1),(2); +DROP TABLE MYSQL.general_log; + +CREATE TABLE MYSQL.slow_log (a INT); +INSERT INTO MYSQL.slow_log VALUES (1),(2); +DROP TABLE MYSQL.slow_log; + +CREATE TABLE MYSQL.transaction_registry (a INT); +INSERT INTO MYSQL.transaction_registry VALUES (1),(2); +DROP TABLE MYSQL.transaction_registry; +DROP DATABASE MYSQL; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/mysql.result b/mysql-test/main/mysql.result index f25d649d9bf..16c083c4941 100644 --- a/mysql-test/main/mysql.result +++ b/mysql-test/main/mysql.result @@ -137,6 +137,10 @@ c int(11) YES NULL drop table t1; 1 1 +-------------- + use +-------------- + ERROR 1064 (42000) at line 3: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1 ERROR at line 1: USE must be followed by a database name 1 +1 @@ -166,6 +170,10 @@ count(*) drop table t17583; Test connect without db- or host-name => reconnect Test connect with dbname only => new dbname, old hostname +-------------- +connecttest +-------------- + ERROR 1064 (42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'connecttest' at line 1 Test connect with _invalid_ dbname only => new invalid dbname, old hostname ERROR 1049 (42000) at line 1: Unknown database 'invalid' @@ -662,6 +670,17 @@ tee source ^^^ 3 +# +# MDEV-34203: Sandbox mode \- is not compatible with --binary-mode +# +create table t1 (a int); +drop table t1; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +drop table t1; # End of 10.5 tests # # MDEV-30327 Client crashes in print_last_query_cost diff --git a/mysql-test/main/mysql.test b/mysql-test/main/mysql.test index 1bd5b8c0dd1..c5a401142d5 100644 --- a/mysql-test/main/mysql.test +++ b/mysql-test/main/mysql.test @@ -756,6 +756,22 @@ source $MYSQL_TMP_DIR/mysql_in;" $MYSQL_TMP_DIR/mysql_in2; --remove_file $MYSQL_TMP_DIR/mysql_in --remove_file $MYSQL_TMP_DIR/mysql_in2 +--echo # +--echo # MDEV-34203: Sandbox mode \- is not compatible with --binary-mode +--echo # + +create table t1 (a int); + +--exec $MYSQL_DUMP test t1 > $MYSQLTEST_VARDIR/tmp/MDEV-34203.sql + +drop table t1; + +--exec $MYSQL --binary-mode test 2>&1 < $MYSQLTEST_VARDIR/tmp/MDEV-34203.sql + +show create table t1; +drop table t1; +--remove_file $MYSQLTEST_VARDIR/tmp/MDEV-34203.sql + --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/mysqldump.result b/mysql-test/main/mysqldump.result index f814e9c4860..7e0fe270e33 100644 --- a/mysql-test/main/mysqldump.result +++ b/mysql-test/main/mysqldump.result @@ -6489,14 +6489,6 @@ Table Create Table s4 CREATE SEQUENCE `s4` start with 400 minvalue 400 maxvalue 1400 increment by 40 cache 1000 cycle ENGINE=MyISAM # Dump sequence without `--no-data` # Restore from mysqldump -SETVAL(`s1`, 1101, 0) -1101 -SETVAL(`s2`, 1201, 0) -1201 -SETVAL(`s3`, 1301, 0) -1301 -SETVAL(`s4`, 1401, 0) -1401 # Show create after restore show create sequence d.s1; Table Create Table @@ -6515,14 +6507,6 @@ NEXTVAL(d.s1) NEXTVAL(d.s2) NEXTVAL(d.s3) NEXTVAL(d.s4) 100 200 300 400 # Dump sequence with `--no-data` # Restore from mysqldump -SETVAL(`s1`, 1101, 0) -1101 -SETVAL(`s2`, 1201, 0) -1201 -SETVAL(`s3`, 1301, 0) -1301 -SETVAL(`s4`, 1401, 0) -1401 # Show create after restore `--no-data` show create sequence d.s1; Table Create Table @@ -6541,14 +6525,6 @@ NEXTVAL(d.s1) NEXTVAL(d.s2) NEXTVAL(d.s3) NEXTVAL(d.s4) 100 200 300 400 # Restore to different database than original create database d2; -SETVAL(`s1`, 1101, 0) -1101 -SETVAL(`s2`, 1201, 0) -1201 -SETVAL(`s3`, 1301, 0) -1301 -SETVAL(`s4`, 1401, 0) -1401 show create sequence d2.s1; Table Create Table s1 CREATE SEQUENCE `s1` start with 100 minvalue 100 maxvalue 1100 increment by 10 cache 1000 cycle ENGINE=MyISAM @@ -6576,9 +6552,15 @@ j integer INSERT INTO t VALUES (1,1),(2,2),(3,3),(4,4); # Dump database 1 # Restore from database 1 to database 2 +-------------- +INSERT INTO `t` VALUES +(1,1), +(2,2), +(3,3), +(4,4) +-------------- + ERROR 1100 (HY000) at line 46: Table 'seq_t_i' was not locked with LOCK TABLES -SETVAL(`seq_t_i`, 1, 0) -1 DROP DATABASE IF EXISTS test1; DROP DATABASE IF EXISTS test2; # diff --git a/mysql-test/main/ps_mem_leaks.result b/mysql-test/main/ps_mem_leaks.result index 2ddf47a992c..e647c89b740 100644 --- a/mysql-test/main/ps_mem_leaks.result +++ b/mysql-test/main/ps_mem_leaks.result @@ -89,3 +89,32 @@ f DEALLOCATE PREPARE stmt; DROP TABLE t1; # End of 10.4 tests +# +# MDEV-33769: Memory leak found in the test main.rownum run with --ps-protocol against a server built with the option -DWITH_PROTECT_STATEMENT_MEMROOT +# +CREATE OR REPLACE TABLE t1(a INT); +PREPARE stmt FROM 'SELECT 1 FROM t1 WHERE ROWNUM() < 2'; +EXECUTE stmt; +1 +EXECUTE stmt; +1 +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); +PREPARE stmt FROM 'SELECT * FROM t1 WHERE ROWNUM() < ?'; +# Expected output is two rows (1), (2) +EXECUTE stmt USING 3; +a +1 +2 +# Expected output is one row (1) +EXECUTE stmt USING 2; +a +1 +# Expected output is three rows (1), (2), (3) +EXECUTE stmt USING 4; +a +1 +2 +# Clean up +DEALLOCATE PREPARE stmt; +DROP TABLE t1; +# End of 10.6 tests diff --git a/mysql-test/main/ps_mem_leaks.test b/mysql-test/main/ps_mem_leaks.test index dacb4ecabba..16a46596c94 100644 --- a/mysql-test/main/ps_mem_leaks.test +++ b/mysql-test/main/ps_mem_leaks.test @@ -110,3 +110,27 @@ DEALLOCATE PREPARE stmt; DROP TABLE t1; --echo # End of 10.4 tests + +--echo # +--echo # MDEV-33769: Memory leak found in the test main.rownum run with --ps-protocol against a server built with the option -DWITH_PROTECT_STATEMENT_MEMROOT +--echo # +CREATE OR REPLACE TABLE t1(a INT); +PREPARE stmt FROM 'SELECT 1 FROM t1 WHERE ROWNUM() < 2'; +EXECUTE stmt; +EXECUTE stmt; + +INSERT INTO t1 VALUES (1), (2), (3), (4), (5); + +PREPARE stmt FROM 'SELECT * FROM t1 WHERE ROWNUM() < ?'; +--echo # Expected output is two rows (1), (2) +EXECUTE stmt USING 3; +--echo # Expected output is one row (1) +EXECUTE stmt USING 2; +--echo # Expected output is three rows (1), (2), (3) +EXECUTE stmt USING 4; + +--echo # Clean up +DEALLOCATE PREPARE stmt; +DROP TABLE t1; + +--echo # End of 10.6 tests diff --git a/mysql-test/main/sp-vars.result b/mysql-test/main/sp-vars.result index a5616b9e231..a89eb0eba59 100644 --- a/mysql-test/main/sp-vars.result +++ b/mysql-test/main/sp-vars.result @@ -1171,7 +1171,7 @@ SET j= 1 + i; END| CALL ctest(); Warnings: -Warning 1292 Truncated incorrect DOUBLE value: 'string ' +Warning 1292 Truncated incorrect DOUBLE value: 'string' DROP PROCEDURE ctest; CREATE PROCEDURE vctest() BEGIN diff --git a/mysql-test/main/type_char.result b/mysql-test/main/type_char.result new file mode 100644 index 00000000000..07dfe7cdc29 --- /dev/null +++ b/mysql-test/main/type_char.result @@ -0,0 +1,40 @@ +# +# Start of 10.5 tests +# +# +# MDEV-34295 CAST(char_col AS DOUBLE) prints redundant spaces in a warning +# +CREATE TABLE t1 (a CHAR(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci); +INSERT INTO t1 VALUES ('1x'), ('x'); +SELECT a, CAST(a AS DOUBLE) FROM t1 ORDER BY a; +a CAST(a AS DOUBLE) +1x 1 +x 0 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '1x' +Warning 1292 Truncated incorrect DOUBLE value: 'x' +SELECT a, CAST(a AS DECIMAL(20,2)) FROM t1 ORDER BY a; +a CAST(a AS DECIMAL(20,2)) +1x 1.00 +x 0.00 +Warnings: +Warning 1292 Truncated incorrect DECIMAL value: '1x' +Warning 1292 Truncated incorrect DECIMAL value: 'x' +SELECT a, CAST(a AS SIGNED) FROM t1 ORDER BY a; +a CAST(a AS SIGNED) +1x 1 +x 0 +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '1x' +Warning 1292 Truncated incorrect INTEGER value: 'x' +SELECT a, CAST(a AS UNSIGNED) FROM t1 ORDER BY a; +a CAST(a AS UNSIGNED) +1x 1 +x 0 +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '1x' +Warning 1292 Truncated incorrect INTEGER value: 'x' +DROP TABLE t1; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/type_char.test b/mysql-test/main/type_char.test new file mode 100644 index 00000000000..053613c5dad --- /dev/null +++ b/mysql-test/main/type_char.test @@ -0,0 +1,19 @@ +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-34295 CAST(char_col AS DOUBLE) prints redundant spaces in a warning +--echo # + +CREATE TABLE t1 (a CHAR(5) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci); +INSERT INTO t1 VALUES ('1x'), ('x'); +SELECT a, CAST(a AS DOUBLE) FROM t1 ORDER BY a; +SELECT a, CAST(a AS DECIMAL(20,2)) FROM t1 ORDER BY a; +SELECT a, CAST(a AS SIGNED) FROM t1 ORDER BY a; +SELECT a, CAST(a AS UNSIGNED) FROM t1 ORDER BY a; +DROP TABLE t1; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/type_varchar.result b/mysql-test/main/type_varchar.result index a4b99ad98d5..b064841696d 100644 --- a/mysql-test/main/type_varchar.result +++ b/mysql-test/main/type_varchar.result @@ -465,7 +465,7 @@ a (a + 0) t 0 Warnings: Warning 1292 Truncated incorrect DOUBLE value: '1a' -Warning 1292 Truncated incorrect DOUBLE value: 't ' +Warning 1292 Truncated incorrect DOUBLE value: 't' SELECT a,(a DIV 2) FROM t1 ORDER BY a; a (a DIV 2) 10 5 @@ -476,7 +476,7 @@ a (a DIV 2) t 0 Warnings: Warning 1292 Truncated incorrect DECIMAL value: '1a' -Warning 1292 Truncated incorrect DECIMAL value: 't ' +Warning 1292 Truncated incorrect DECIMAL value: 't' SELECT a,CAST(a AS SIGNED) FROM t1 ORDER BY a; a CAST(a AS SIGNED) 10 10 @@ -508,8 +508,8 @@ SELECT 5 = a FROM t1; 0 0 Warnings: -Warning 1292 Truncated incorrect DECIMAL value: 's ' -Warning 1292 Truncated incorrect DECIMAL value: ' ' +Warning 1292 Truncated incorrect DECIMAL value: 's' +Warning 1292 Truncated incorrect DECIMAL value: '' DROP TABLE t1; # # MDEV-13530 VARBINARY doesn't convert to to BLOB for sizes 65533, 65534 and 65535 diff --git a/mysql-test/main/view_grant.result b/mysql-test/main/view_grant.result index cfb8f7df60e..18290b6bafe 100644 --- a/mysql-test/main/view_grant.result +++ b/mysql-test/main/view_grant.result @@ -1948,6 +1948,38 @@ connection default; drop user user_11766767; drop database mysqltest1; drop database mysqltest2; +# +# MDEV-33119 User is case insensitive in INFORMATION_SCHEMA.VIEWS +# +USE test; +CREATE USER foo; +CREATE USER FOO; +GRANT SELECT ON test.* TO foo; +GRANT SELECT ON test.* TO FOO; +CREATE DEFINER=foo SQL SECURITY INVOKER VIEW v1 AS SELECT 1 AS c1; +connect FOO, localhost, FOO, , test; +connection FOO; +SELECT CURRENT_USER; +CURRENT_USER +FOO@% +SELECT * FROM INFORMATION_SCHEMA.VIEWS; +TABLE_CATALOG def +TABLE_SCHEMA test +TABLE_NAME v1 +VIEW_DEFINITION +CHECK_OPTION NONE +IS_UPDATABLE NO +DEFINER foo@% +SECURITY_TYPE INVOKER +CHARACTER_SET_CLIENT latin1 +COLLATION_CONNECTION latin1_swedish_ci +ALGORITHM UNDEFINED +disconnect FOO; +connection default; +DROP VIEW v1; +DROP USER foo; +DROP USER FOO; +# End of 10.5 tests # Check that a user without access to the schema 'foo' cannot query # a JSON_TABLE view in that schema. CREATE SCHEMA foo; @@ -1964,3 +1996,4 @@ connection default; disconnect con1; drop user foo@localhost; drop schema foo; +# End of 10.6 tests diff --git a/mysql-test/main/view_grant.test b/mysql-test/main/view_grant.test index a7990b44636..f106808bd18 100644 --- a/mysql-test/main/view_grant.test +++ b/mysql-test/main/view_grant.test @@ -2207,6 +2207,35 @@ drop user user_11766767; drop database mysqltest1; drop database mysqltest2; +--echo # +--echo # MDEV-33119 User is case insensitive in INFORMATION_SCHEMA.VIEWS +--echo # + +USE test; +CREATE USER foo; +CREATE USER FOO; +GRANT SELECT ON test.* TO foo; +GRANT SELECT ON test.* TO FOO; + +CREATE DEFINER=foo SQL SECURITY INVOKER VIEW v1 AS SELECT 1 AS c1; + +--connect (FOO, localhost, FOO, , test) +--connection FOO + +SELECT CURRENT_USER; +--vertical_results +--query_vertical SELECT * FROM INFORMATION_SCHEMA.VIEWS +--horizontal_results + +--disconnect FOO +--connection default + +DROP VIEW v1; +DROP USER foo; +DROP USER FOO; + +--echo # End of 10.5 tests + --echo # Check that a user without access to the schema 'foo' cannot query --echo # a JSON_TABLE view in that schema. CREATE SCHEMA foo; @@ -2225,7 +2254,7 @@ connection default; disconnect con1; drop user foo@localhost; drop schema foo; +--echo # End of 10.6 tests # Wait till we reached the initial number of concurrent sessions --source include/wait_until_count_sessions.inc - diff --git a/mysql-test/main/win.result b/mysql-test/main/win.result index 93652834a80..61b6bd19bcc 100644 --- a/mysql-test/main/win.result +++ b/mysql-test/main/win.result @@ -4514,6 +4514,180 @@ row_number() OVER (order by a) 3 drop table t1; # +# MDEV-29307: join of 2 derived tables over the same grouping view such +# that the first of the joined tables contains a window +# function and the view's specification contains a subquery +# with a set function aggregated on the top level +# +CREATE TABLE t1 ( +tst int NOT NULL, +flat tinyint unsigned NOT NULL, +type tinyint unsigned NOT NULL, +val int NOT NULL, +PRIMARY KEY (tst,flat,type) +) ENGINE=ARIA; +INSERT INTO t1 VALUES +(5, 20, 2, 100), +(7, 20, 2, 150), +(9, 20, 1, 200); +CREATE VIEW v1 AS ( +SELECT +flat, +type, +( SELECT val FROM t1 sw +WHERE sw.tst = MAX(w.tst) AND sw.flat = w.flat AND sw.type = w.type) +AS total +FROM t1 w +GROUP BY flat, type +); +EXPLAIN EXTENDED SELECT w2.total AS w2_total, w1.total AS w1_total +FROM +( +SELECT flat, type, total +FROM v1 +WHERE type = 1 +) AS w1 +JOIN +( +SELECT flat, type, total +FROM v1 +WHERE type = 2 +) AS w2 +ON w1.flat = w2.flat; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 3 100.00 Using where +1 PRIMARY ref key0 key0 1 v1.flat 1 100.00 Using where +6 DERIVED w index NULL PRIMARY 6 NULL 3 100.00 Using where; Using index; Using temporary; Using filesort +7 DEPENDENT SUBQUERY sw eq_ref PRIMARY PRIMARY 6 func,func,func 1 100.00 Using index condition +4 DERIVED w index NULL PRIMARY 6 NULL 3 100.00 Using where; Using index; Using temporary; Using filesort +5 DEPENDENT SUBQUERY sw eq_ref PRIMARY PRIMARY 6 func,func,func 1 100.00 Using index condition +Warnings: +Note 1276 Field or reference 'test.w.tst' of SELECT #5 was resolved in SELECT #4 +Note 1981 Aggregate function 'max()' of SELECT #5 belongs to SELECT #4 +Note 1276 Field or reference 'test.w.flat' of SELECT #5 was resolved in SELECT #4 +Note 1276 Field or reference 'test.w.type' of SELECT #5 was resolved in SELECT #4 +Note 1276 Field or reference 'test.w.tst' of SELECT #7 was resolved in SELECT #6 +Note 1981 Aggregate function 'max()' of SELECT #7 belongs to SELECT #6 +Note 1276 Field or reference 'test.w.flat' of SELECT #7 was resolved in SELECT #6 +Note 1276 Field or reference 'test.w.type' of SELECT #7 was resolved in SELECT #6 +Note 1003 /* select#1 */ select `v1`.`total` AS `w2_total`,`v1`.`total` AS `w1_total` from `test`.`v1` join `test`.`v1` where `v1`.`flat` = `v1`.`flat` and `v1`.`type` = 2 and `v1`.`type` = 1 +SELECT w2.total AS w2_total, w1.total AS w1_total +FROM +( +SELECT flat, type, total +FROM v1 +WHERE type = 1 +) AS w1 +JOIN +( +SELECT flat, type, total +FROM v1 +WHERE type = 2 +) AS w2 +ON w1.flat = w2.flat; +w2_total w1_total +150 200 +EXPLAIN EXTENDED SELECT w2.total AS w2_total, w1.total AS w1_total +FROM +( +SELECT flat, type, total, +COUNT(total) OVER (PARTITION BY type ORDER BY type) AS u +FROM v1 +WHERE type = 1 +) AS w1 +JOIN +( +SELECT flat, type, total +FROM v1 +WHERE type = 2 +) AS w2 +ON w1.flat = w2.flat; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 3 100.00 Using where +1 PRIMARY ref key0 key0 1 w1.flat 1 100.00 Using where +6 DERIVED w index NULL PRIMARY 6 NULL 3 100.00 Using where; Using index; Using temporary; Using filesort +7 DEPENDENT SUBQUERY sw eq_ref PRIMARY PRIMARY 6 func,func,func 1 100.00 Using index condition +2 DERIVED ALL NULL NULL NULL NULL 3 100.00 Using where; Using temporary +4 DERIVED w index NULL PRIMARY 6 NULL 3 100.00 Using where; Using index; Using temporary; Using filesort +5 DEPENDENT SUBQUERY sw eq_ref PRIMARY PRIMARY 6 func,func,func 1 100.00 Using index condition +Warnings: +Note 1276 Field or reference 'test.w.tst' of SELECT #5 was resolved in SELECT #4 +Note 1981 Aggregate function 'max()' of SELECT #5 belongs to SELECT #4 +Note 1276 Field or reference 'test.w.flat' of SELECT #5 was resolved in SELECT #4 +Note 1276 Field or reference 'test.w.type' of SELECT #5 was resolved in SELECT #4 +Note 1276 Field or reference 'test.w.tst' of SELECT #7 was resolved in SELECT #6 +Note 1981 Aggregate function 'max()' of SELECT #7 belongs to SELECT #6 +Note 1276 Field or reference 'test.w.flat' of SELECT #7 was resolved in SELECT #6 +Note 1276 Field or reference 'test.w.type' of SELECT #7 was resolved in SELECT #6 +Note 1003 /* select#1 */ select `v1`.`total` AS `w2_total`,`w1`.`total` AS `w1_total` from (/* select#2 */ select `v1`.`flat` AS `flat`,`v1`.`type` AS `type`,`v1`.`total` AS `total`,count(`v1`.`total`) over ( partition by `v1`.`type` order by `v1`.`type`) AS `u` from `test`.`v1` where `v1`.`type` = 1) `w1` join `test`.`v1` where `v1`.`flat` = `w1`.`flat` and `v1`.`type` = 2 +SELECT w2.total AS w2_total, w1.total AS w1_total +FROM +( +SELECT flat, type, total, +COUNT(total) OVER (PARTITION BY type ORDER BY type) AS u +FROM v1 +WHERE type = 1 +) AS w1 +JOIN +( +SELECT flat, type, total +FROM v1 +WHERE type = 2 +) AS w2 +ON w1.flat = w2.flat; +w2_total w1_total +150 200 +EXPLAIN EXTENDED SELECT w2.total AS w2_total, w1.total AS w1_total, u +FROM +( +SELECT flat, type, total, +COUNT(total) OVER (PARTITION BY flat ORDER BY flat) AS u +FROM v1 +) AS w1 +JOIN +( +SELECT flat, type, total +FROM v1 +) AS w2; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 3 100.00 +1 PRIMARY ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join) +6 DERIVED w index NULL PRIMARY 6 NULL 3 100.00 Using index; Using temporary; Using filesort +7 DEPENDENT SUBQUERY sw eq_ref PRIMARY PRIMARY 6 func,func,func 1 100.00 Using index condition +2 DERIVED ALL NULL NULL NULL NULL 3 100.00 Using temporary +4 DERIVED w index NULL PRIMARY 6 NULL 3 100.00 Using index; Using temporary; Using filesort +5 DEPENDENT SUBQUERY sw eq_ref PRIMARY PRIMARY 6 func,func,func 1 100.00 Using index condition +Warnings: +Note 1276 Field or reference 'test.w.tst' of SELECT #5 was resolved in SELECT #4 +Note 1981 Aggregate function 'max()' of SELECT #5 belongs to SELECT #4 +Note 1276 Field or reference 'test.w.flat' of SELECT #5 was resolved in SELECT #4 +Note 1276 Field or reference 'test.w.type' of SELECT #5 was resolved in SELECT #4 +Note 1276 Field or reference 'test.w.tst' of SELECT #7 was resolved in SELECT #6 +Note 1981 Aggregate function 'max()' of SELECT #7 belongs to SELECT #6 +Note 1276 Field or reference 'test.w.flat' of SELECT #7 was resolved in SELECT #6 +Note 1276 Field or reference 'test.w.type' of SELECT #7 was resolved in SELECT #6 +Note 1003 /* select#1 */ select `v1`.`total` AS `w2_total`,`w1`.`total` AS `w1_total`,`w1`.`u` AS `u` from (/* select#2 */ select `v1`.`flat` AS `flat`,`v1`.`type` AS `type`,`v1`.`total` AS `total`,count(`v1`.`total`) over ( partition by `v1`.`flat` order by `v1`.`flat`) AS `u` from `test`.`v1`) `w1` join `test`.`v1` +SELECT w2.total AS w2_total, w1.total AS w1_total, u +FROM +( +SELECT flat, type, total, +COUNT(total) OVER (PARTITION BY flat ORDER BY flat) AS u +FROM v1 +) AS w1 +JOIN +( +SELECT flat, type, total +FROM v1 +) AS w2; +w2_total w1_total u +150 150 2 +150 200 2 +200 150 2 +200 200 2 +DROP VIEW v1; +DROP TABLE t1; +# End of 10.5 tests +# # MDEV-28206 SIGSEGV in Item_field::fix_fields when using LEAD...OVER # CREATE TABLE t(c1 INT); diff --git a/mysql-test/main/win.test b/mysql-test/main/win.test index 51c91eb605d..6ec89fc168c 100644 --- a/mysql-test/main/win.test +++ b/mysql-test/main/win.test @@ -2886,6 +2886,99 @@ insert into t1 values (1),(2),(3); SELECT row_number() OVER (order by a) FROM t1 order by NAME_CONST('myname',NULL); drop table t1; +--echo # +--echo # MDEV-29307: join of 2 derived tables over the same grouping view such +--echo # that the first of the joined tables contains a window +--echo # function and the view's specification contains a subquery +--echo # with a set function aggregated on the top level +--echo # + +CREATE TABLE t1 ( + tst int NOT NULL, + flat tinyint unsigned NOT NULL, + type tinyint unsigned NOT NULL, + val int NOT NULL, + PRIMARY KEY (tst,flat,type) +) ENGINE=ARIA; + +INSERT INTO t1 VALUES +(5, 20, 2, 100), +(7, 20, 2, 150), +(9, 20, 1, 200); + +CREATE VIEW v1 AS ( + SELECT + flat, + type, + ( SELECT val FROM t1 sw + WHERE sw.tst = MAX(w.tst) AND sw.flat = w.flat AND sw.type = w.type) + AS total + FROM t1 w + GROUP BY flat, type +); + +let $q1= +SELECT w2.total AS w2_total, w1.total AS w1_total +FROM +( + SELECT flat, type, total + FROM v1 + WHERE type = 1 +) AS w1 +JOIN +( + SELECT flat, type, total + FROM v1 + WHERE type = 2 +) AS w2 +ON w1.flat = w2.flat; + +eval EXPLAIN EXTENDED $q1; +eval $q1; + +let $q2= +SELECT w2.total AS w2_total, w1.total AS w1_total +FROM +( + SELECT flat, type, total, + COUNT(total) OVER (PARTITION BY type ORDER BY type) AS u + FROM v1 + WHERE type = 1 +) AS w1 +JOIN +( + SELECT flat, type, total + FROM v1 + WHERE type = 2 +) AS w2 +ON w1.flat = w2.flat; + +eval EXPLAIN EXTENDED $q2; +eval $q2; + +let $q3= +SELECT w2.total AS w2_total, w1.total AS w1_total, u +FROM +( + SELECT flat, type, total, + COUNT(total) OVER (PARTITION BY flat ORDER BY flat) AS u + FROM v1 +) AS w1 +JOIN +( + SELECT flat, type, total + FROM v1 +) AS w2; + +eval EXPLAIN EXTENDED $q3; +--sorted_result +eval $q3; + +DROP VIEW v1; +DROP TABLE t1; + +--echo # End of 10.5 tests + --echo # --echo # MDEV-28206 SIGSEGV in Item_field::fix_fields when using LEAD...OVER --echo # diff --git a/mysql-test/main/xml.result b/mysql-test/main/xml.result index efaca961b4a..d0acb0debf3 100644 --- a/mysql-test/main/xml.result +++ b/mysql-test/main/xml.result @@ -991,20 +991,20 @@ CALL spxml('b1b2', '1 and string'); ExtractValue(xml,'/a/b[$i]') b1 Warnings: -Warning 1292 Truncated incorrect INTEGER value: '1 and string ' -Warning 1292 Truncated incorrect INTEGER value: '1 and string ' +Warning 1292 Truncated incorrect INTEGER value: '1 and string' +Warning 1292 Truncated incorrect INTEGER value: '1 and string' CALL spxml('b1b2', 'string and 1'); ExtractValue(xml,'/a/b[$i]') Warnings: -Warning 1292 Truncated incorrect INTEGER value: 'string and 1 ' -Warning 1292 Truncated incorrect INTEGER value: 'string and 1 ' +Warning 1292 Truncated incorrect INTEGER value: 'string and 1' +Warning 1292 Truncated incorrect INTEGER value: 'string and 1' CALL spxml('b1b2', 'string'); ExtractValue(xml,'/a/b[$i]') Warnings: -Warning 1292 Truncated incorrect INTEGER value: 'string ' -Warning 1292 Truncated incorrect INTEGER value: 'string ' +Warning 1292 Truncated incorrect INTEGER value: 'string' +Warning 1292 Truncated incorrect INTEGER value: 'string' DROP PROCEDURE spxml; select UpdateXML('a',repeat('a b ',1000),''); ERROR HY000: XPATH syntax error: 'b a b a b a b a b a b a b a b...' diff --git a/mysql-test/mariadb-test-run.pl b/mysql-test/mariadb-test-run.pl index e2d3fa64c92..2817f58e67f 100755 --- a/mysql-test/mariadb-test-run.pl +++ b/mysql-test/mariadb-test-run.pl @@ -339,7 +339,11 @@ my $opt_max_test_fail= env_or_val(MTR_MAX_TEST_FAIL => 10); my $opt_core_on_failure= 0; my $opt_parallel= $ENV{MTR_PARALLEL} || 1; -my $opt_port_group_size = $ENV{MTR_PORT_GROUP_SIZE} || 20; +# Some galera tests starts 6 galera nodes. Each galera node requires +# three ports: 6*3 = 18. Plus 6 ports are needed for 6 mariadbd servers. +# Since the number of ports is rounded up to 10 everywhere, we will +# take 30 as the default value: +my $opt_port_group_size = $ENV{MTR_PORT_GROUP_SIZE} || 30; # lock file to stop tests my $opt_stop_file= $ENV{MTR_STOP_FILE}; @@ -436,7 +440,7 @@ sub main { { $opt_parallel= $ENV{NUMBER_OF_PROCESSORS} || 1; } - elsif (IS_MAC) + elsif (IS_MAC || IS_FREEBSD) { $opt_parallel= `sysctl -n hw.ncpu`; } @@ -5587,6 +5591,8 @@ sub start_check_testcase ($$$) { mtr_add_arg($args, "--record"); } my $errfile= "$opt_vardir/tmp/$name.err"; + + My::Debugger::setup_client_args(\$args, \$exe_mysqltest); my $proc= My::SafeProcess->new ( name => $name, diff --git a/mysql-test/suite/csv/lowercase_table0.result b/mysql-test/suite/csv/lowercase_table0.result new file mode 100644 index 00000000000..fba6a509aea --- /dev/null +++ b/mysql-test/suite/csv/lowercase_table0.result @@ -0,0 +1,15 @@ +# +# MDEV-33085 Tables T1 and t1 do not work well with ENGINE=CSV and lower-case-table-names=0 +# +CREATE OR REPLACE TABLE t1 (a INT NOT NULL) ENGINE=CSV; +CREATE OR REPLACE TABLE T1 (a INT NOT NULL) ENGINE=CSV; +INSERT INTO t1 VALUES (10); +INSERT INTO T1 VALUES (20); +SELECT * FROM t1; +a +10 +SELECT * FROM T1; +a +20 +DROP TABLE t1; +DROP TABLE T1; diff --git a/mysql-test/suite/csv/lowercase_table0.test b/mysql-test/suite/csv/lowercase_table0.test new file mode 100644 index 00000000000..2bb0e486cb6 --- /dev/null +++ b/mysql-test/suite/csv/lowercase_table0.test @@ -0,0 +1,16 @@ +--source include/have_csv.inc +--source include/have_lowercase0.inc +--source include/have_case_sensitive_file_system.inc + +--echo # +--echo # MDEV-33085 Tables T1 and t1 do not work well with ENGINE=CSV and lower-case-table-names=0 +--echo # + +CREATE OR REPLACE TABLE t1 (a INT NOT NULL) ENGINE=CSV; +CREATE OR REPLACE TABLE T1 (a INT NOT NULL) ENGINE=CSV; +INSERT INTO t1 VALUES (10); +INSERT INTO T1 VALUES (20); +SELECT * FROM t1; +SELECT * FROM T1; +DROP TABLE t1; +DROP TABLE T1; diff --git a/mysql-test/suite/encryption/r/tempfiles_encrypted.result b/mysql-test/suite/encryption/r/tempfiles_encrypted.result index 3560672e509..daa22e38289 100644 --- a/mysql-test/suite/encryption/r/tempfiles_encrypted.result +++ b/mysql-test/suite/encryption/r/tempfiles_encrypted.result @@ -4520,6 +4520,180 @@ row_number() OVER (order by a) 3 drop table t1; # +# MDEV-29307: join of 2 derived tables over the same grouping view such +# that the first of the joined tables contains a window +# function and the view's specification contains a subquery +# with a set function aggregated on the top level +# +CREATE TABLE t1 ( +tst int NOT NULL, +flat tinyint unsigned NOT NULL, +type tinyint unsigned NOT NULL, +val int NOT NULL, +PRIMARY KEY (tst,flat,type) +) ENGINE=ARIA; +INSERT INTO t1 VALUES +(5, 20, 2, 100), +(7, 20, 2, 150), +(9, 20, 1, 200); +CREATE VIEW v1 AS ( +SELECT +flat, +type, +( SELECT val FROM t1 sw +WHERE sw.tst = MAX(w.tst) AND sw.flat = w.flat AND sw.type = w.type) +AS total +FROM t1 w +GROUP BY flat, type +); +EXPLAIN EXTENDED SELECT w2.total AS w2_total, w1.total AS w1_total +FROM +( +SELECT flat, type, total +FROM v1 +WHERE type = 1 +) AS w1 +JOIN +( +SELECT flat, type, total +FROM v1 +WHERE type = 2 +) AS w2 +ON w1.flat = w2.flat; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 3 100.00 Using where +1 PRIMARY ref key0 key0 1 v1.flat 1 100.00 Using where +6 DERIVED w index NULL PRIMARY 6 NULL 3 100.00 Using where; Using index; Using temporary; Using filesort +7 DEPENDENT SUBQUERY sw eq_ref PRIMARY PRIMARY 6 func,func,func 1 100.00 Using index condition +4 DERIVED w index NULL PRIMARY 6 NULL 3 100.00 Using where; Using index; Using temporary; Using filesort +5 DEPENDENT SUBQUERY sw eq_ref PRIMARY PRIMARY 6 func,func,func 1 100.00 Using index condition +Warnings: +Note 1276 Field or reference 'test.w.tst' of SELECT #5 was resolved in SELECT #4 +Note 1981 Aggregate function 'max()' of SELECT #5 belongs to SELECT #4 +Note 1276 Field or reference 'test.w.flat' of SELECT #5 was resolved in SELECT #4 +Note 1276 Field or reference 'test.w.type' of SELECT #5 was resolved in SELECT #4 +Note 1276 Field or reference 'test.w.tst' of SELECT #7 was resolved in SELECT #6 +Note 1981 Aggregate function 'max()' of SELECT #7 belongs to SELECT #6 +Note 1276 Field or reference 'test.w.flat' of SELECT #7 was resolved in SELECT #6 +Note 1276 Field or reference 'test.w.type' of SELECT #7 was resolved in SELECT #6 +Note 1003 /* select#1 */ select `v1`.`total` AS `w2_total`,`v1`.`total` AS `w1_total` from `test`.`v1` join `test`.`v1` where `v1`.`flat` = `v1`.`flat` and `v1`.`type` = 2 and `v1`.`type` = 1 +SELECT w2.total AS w2_total, w1.total AS w1_total +FROM +( +SELECT flat, type, total +FROM v1 +WHERE type = 1 +) AS w1 +JOIN +( +SELECT flat, type, total +FROM v1 +WHERE type = 2 +) AS w2 +ON w1.flat = w2.flat; +w2_total w1_total +150 200 +EXPLAIN EXTENDED SELECT w2.total AS w2_total, w1.total AS w1_total +FROM +( +SELECT flat, type, total, +COUNT(total) OVER (PARTITION BY type ORDER BY type) AS u +FROM v1 +WHERE type = 1 +) AS w1 +JOIN +( +SELECT flat, type, total +FROM v1 +WHERE type = 2 +) AS w2 +ON w1.flat = w2.flat; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 3 100.00 Using where +1 PRIMARY ref key0 key0 1 w1.flat 1 100.00 Using where +6 DERIVED w index NULL PRIMARY 6 NULL 3 100.00 Using where; Using index; Using temporary; Using filesort +7 DEPENDENT SUBQUERY sw eq_ref PRIMARY PRIMARY 6 func,func,func 1 100.00 Using index condition +2 DERIVED ALL NULL NULL NULL NULL 3 100.00 Using where; Using temporary +4 DERIVED w index NULL PRIMARY 6 NULL 3 100.00 Using where; Using index; Using temporary; Using filesort +5 DEPENDENT SUBQUERY sw eq_ref PRIMARY PRIMARY 6 func,func,func 1 100.00 Using index condition +Warnings: +Note 1276 Field or reference 'test.w.tst' of SELECT #5 was resolved in SELECT #4 +Note 1981 Aggregate function 'max()' of SELECT #5 belongs to SELECT #4 +Note 1276 Field or reference 'test.w.flat' of SELECT #5 was resolved in SELECT #4 +Note 1276 Field or reference 'test.w.type' of SELECT #5 was resolved in SELECT #4 +Note 1276 Field or reference 'test.w.tst' of SELECT #7 was resolved in SELECT #6 +Note 1981 Aggregate function 'max()' of SELECT #7 belongs to SELECT #6 +Note 1276 Field or reference 'test.w.flat' of SELECT #7 was resolved in SELECT #6 +Note 1276 Field or reference 'test.w.type' of SELECT #7 was resolved in SELECT #6 +Note 1003 /* select#1 */ select `v1`.`total` AS `w2_total`,`w1`.`total` AS `w1_total` from (/* select#2 */ select `v1`.`flat` AS `flat`,`v1`.`type` AS `type`,`v1`.`total` AS `total`,count(`v1`.`total`) over ( partition by `v1`.`type` order by `v1`.`type`) AS `u` from `test`.`v1` where `v1`.`type` = 1) `w1` join `test`.`v1` where `v1`.`flat` = `w1`.`flat` and `v1`.`type` = 2 +SELECT w2.total AS w2_total, w1.total AS w1_total +FROM +( +SELECT flat, type, total, +COUNT(total) OVER (PARTITION BY type ORDER BY type) AS u +FROM v1 +WHERE type = 1 +) AS w1 +JOIN +( +SELECT flat, type, total +FROM v1 +WHERE type = 2 +) AS w2 +ON w1.flat = w2.flat; +w2_total w1_total +150 200 +EXPLAIN EXTENDED SELECT w2.total AS w2_total, w1.total AS w1_total, u +FROM +( +SELECT flat, type, total, +COUNT(total) OVER (PARTITION BY flat ORDER BY flat) AS u +FROM v1 +) AS w1 +JOIN +( +SELECT flat, type, total +FROM v1 +) AS w2; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL NULL NULL NULL NULL 3 100.00 +1 PRIMARY ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join) +6 DERIVED w index NULL PRIMARY 6 NULL 3 100.00 Using index; Using temporary; Using filesort +7 DEPENDENT SUBQUERY sw eq_ref PRIMARY PRIMARY 6 func,func,func 1 100.00 Using index condition +2 DERIVED ALL NULL NULL NULL NULL 3 100.00 Using temporary +4 DERIVED w index NULL PRIMARY 6 NULL 3 100.00 Using index; Using temporary; Using filesort +5 DEPENDENT SUBQUERY sw eq_ref PRIMARY PRIMARY 6 func,func,func 1 100.00 Using index condition +Warnings: +Note 1276 Field or reference 'test.w.tst' of SELECT #5 was resolved in SELECT #4 +Note 1981 Aggregate function 'max()' of SELECT #5 belongs to SELECT #4 +Note 1276 Field or reference 'test.w.flat' of SELECT #5 was resolved in SELECT #4 +Note 1276 Field or reference 'test.w.type' of SELECT #5 was resolved in SELECT #4 +Note 1276 Field or reference 'test.w.tst' of SELECT #7 was resolved in SELECT #6 +Note 1981 Aggregate function 'max()' of SELECT #7 belongs to SELECT #6 +Note 1276 Field or reference 'test.w.flat' of SELECT #7 was resolved in SELECT #6 +Note 1276 Field or reference 'test.w.type' of SELECT #7 was resolved in SELECT #6 +Note 1003 /* select#1 */ select `v1`.`total` AS `w2_total`,`w1`.`total` AS `w1_total`,`w1`.`u` AS `u` from (/* select#2 */ select `v1`.`flat` AS `flat`,`v1`.`type` AS `type`,`v1`.`total` AS `total`,count(`v1`.`total`) over ( partition by `v1`.`flat` order by `v1`.`flat`) AS `u` from `test`.`v1`) `w1` join `test`.`v1` +SELECT w2.total AS w2_total, w1.total AS w1_total, u +FROM +( +SELECT flat, type, total, +COUNT(total) OVER (PARTITION BY flat ORDER BY flat) AS u +FROM v1 +) AS w1 +JOIN +( +SELECT flat, type, total +FROM v1 +) AS w2; +w2_total w1_total u +150 150 2 +150 200 2 +200 150 2 +200 200 2 +DROP VIEW v1; +DROP TABLE t1; +# End of 10.5 tests +# # MDEV-28206 SIGSEGV in Item_field::fix_fields when using LEAD...OVER # CREATE TABLE t(c1 INT); diff --git a/mysql-test/suite/funcs_1/r/innodb_func_view.result b/mysql-test/suite/funcs_1/r/innodb_func_view.result index b603d36f5ec..1e63c2e012f 100644 --- a/mysql-test/suite/funcs_1/r/innodb_func_view.result +++ b/mysql-test/suite/funcs_1/r/innodb_func_view.result @@ -2202,9 +2202,9 @@ IS NOT TRUE <--------30 characters-------> 3 IS NOT TRUE ---äÖüß@µ*$-- 4 IS TRUE -1 5 Warnings: -Warning 1292 Truncated incorrect DOUBLE value: ' ' +Warning 1292 Truncated incorrect DOUBLE value: '' Warning 1292 Truncated incorrect DOUBLE value: '<--------30 characters------->' -Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- ' +Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$--' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select if(`t1_values`.`my_char_30`,'IS TRUE','IS NOT TRUE') AS `IF(my_char_30, 'IS TRUE', 'IS NOT TRUE')`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -2218,9 +2218,9 @@ IS NOT TRUE <--------30 characters-------> 3 IS NOT TRUE ---äÖüß@µ*$-- 4 IS TRUE -1 5 Warnings: -Warning 1292 Truncated incorrect DOUBLE value: ' ' +Warning 1292 Truncated incorrect DOUBLE value: '' Warning 1292 Truncated incorrect DOUBLE value: '<--------30 characters------->' -Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- ' +Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$--' DROP VIEW v1; @@ -3523,9 +3523,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 26 Warnings: -Warning 1292 Truncated incorrect DECIMAL value: ' ' +Warning 1292 Truncated incorrect DECIMAL value: '' Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' +Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$--' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_char_30` as decimal(37,2)) AS `CAST(my_char_30 AS DECIMAL(37,2))`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3540,9 +3540,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 26 Warnings: -Warning 1292 Truncated incorrect DECIMAL value: ' ' +Warning 1292 Truncated incorrect DECIMAL value: '' Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' +Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$--' DROP VIEW v1; diff --git a/mysql-test/suite/funcs_1/r/memory_func_view.result b/mysql-test/suite/funcs_1/r/memory_func_view.result index e9b88b9309a..84af1109454 100644 --- a/mysql-test/suite/funcs_1/r/memory_func_view.result +++ b/mysql-test/suite/funcs_1/r/memory_func_view.result @@ -2203,9 +2203,9 @@ IS NOT TRUE <--------30 characters-------> 3 IS NOT TRUE ---äÖüß@µ*$-- 4 IS TRUE -1 5 Warnings: -Warning 1292 Truncated incorrect DOUBLE value: ' ' +Warning 1292 Truncated incorrect DOUBLE value: '' Warning 1292 Truncated incorrect DOUBLE value: '<--------30 characters------->' -Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- ' +Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$--' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select if(`t1_values`.`my_char_30`,'IS TRUE','IS NOT TRUE') AS `IF(my_char_30, 'IS TRUE', 'IS NOT TRUE')`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -2219,9 +2219,9 @@ IS NOT TRUE <--------30 characters-------> 3 IS NOT TRUE ---äÖüß@µ*$-- 4 IS TRUE -1 5 Warnings: -Warning 1292 Truncated incorrect DOUBLE value: ' ' +Warning 1292 Truncated incorrect DOUBLE value: '' Warning 1292 Truncated incorrect DOUBLE value: '<--------30 characters------->' -Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- ' +Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$--' DROP VIEW v1; @@ -3524,9 +3524,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 26 Warnings: -Warning 1292 Truncated incorrect DECIMAL value: ' ' +Warning 1292 Truncated incorrect DECIMAL value: '' Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' +Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$--' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_char_30` as decimal(37,2)) AS `CAST(my_char_30 AS DECIMAL(37,2))`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3541,9 +3541,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 26 Warnings: -Warning 1292 Truncated incorrect DECIMAL value: ' ' +Warning 1292 Truncated incorrect DECIMAL value: '' Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' +Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$--' DROP VIEW v1; diff --git a/mysql-test/suite/funcs_1/r/myisam_func_view.result b/mysql-test/suite/funcs_1/r/myisam_func_view.result index e9b88b9309a..84af1109454 100644 --- a/mysql-test/suite/funcs_1/r/myisam_func_view.result +++ b/mysql-test/suite/funcs_1/r/myisam_func_view.result @@ -2203,9 +2203,9 @@ IS NOT TRUE <--------30 characters-------> 3 IS NOT TRUE ---äÖüß@µ*$-- 4 IS TRUE -1 5 Warnings: -Warning 1292 Truncated incorrect DOUBLE value: ' ' +Warning 1292 Truncated incorrect DOUBLE value: '' Warning 1292 Truncated incorrect DOUBLE value: '<--------30 characters------->' -Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- ' +Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$--' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select if(`t1_values`.`my_char_30`,'IS TRUE','IS NOT TRUE') AS `IF(my_char_30, 'IS TRUE', 'IS NOT TRUE')`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -2219,9 +2219,9 @@ IS NOT TRUE <--------30 characters-------> 3 IS NOT TRUE ---äÖüß@µ*$-- 4 IS TRUE -1 5 Warnings: -Warning 1292 Truncated incorrect DOUBLE value: ' ' +Warning 1292 Truncated incorrect DOUBLE value: '' Warning 1292 Truncated incorrect DOUBLE value: '<--------30 characters------->' -Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$-- ' +Warning 1292 Truncated incorrect DOUBLE value: ' ---äÖüß@µ*$--' DROP VIEW v1; @@ -3524,9 +3524,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 26 Warnings: -Warning 1292 Truncated incorrect DECIMAL value: ' ' +Warning 1292 Truncated incorrect DECIMAL value: '' Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' +Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$--' SHOW CREATE VIEW v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_char_30` as decimal(37,2)) AS `CAST(my_char_30 AS DECIMAL(37,2))`,`t1_values`.`my_char_30` AS `my_char_30`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci @@ -3541,9 +3541,9 @@ NULL NULL 1 -1.00 -1 5 -3333.33 -3333.3333 26 Warnings: -Warning 1292 Truncated incorrect DECIMAL value: ' ' +Warning 1292 Truncated incorrect DECIMAL value: '' Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->' -Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- ' +Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$--' DROP VIEW v1; diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 752994c4a26..412834c5cf2 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -23,4 +23,3 @@ galera_slave_replay : MDEV-32780 galera_as_slave_replay: assertion in the wsrep: galera_sst_mysqldump_with_key : MDEV-32782 galera_sst_mysqldump_with_key test failed galera_var_ignore_apply_errors : MENT-1997 galera_var_ignore_apply_errors test freezes galera_desync_overlapped : MDEV-21538 galera_desync_overlapped MTR failed: Result content mismatch -galera_create_table_as_select : MDEV-33952 fails sporadically diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf index eefb94522fe..442a8a130e5 100644 --- a/mysql-test/suite/galera/galera_2nodes.cnf +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -33,6 +33,9 @@ wsrep_node_address='127.0.0.1:@mysqld.2.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' +[sst] +sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log + [ENV] NODE_MYPORT_1= @mysqld.1.port NODE_MYSOCK_1= @mysqld.1.socket diff --git a/mysql-test/suite/galera/galera_2nodes_as_master.cnf b/mysql-test/suite/galera/galera_2nodes_as_master.cnf index 28970d05807..e590160df50 100644 --- a/mysql-test/suite/galera/galera_2nodes_as_master.cnf +++ b/mysql-test/suite/galera/galera_2nodes_as_master.cnf @@ -47,6 +47,9 @@ wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' wsrep-on=OFF server-id=3 +[sst] +sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log + [ENV] NODE_MYPORT_1= @mysqld.1.port NODE_MYSOCK_1= @mysqld.1.socket diff --git a/mysql-test/suite/galera/galera_2nodes_as_slave.cnf b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf index dbf1544df43..879699efb02 100644 --- a/mysql-test/suite/galera/galera_2nodes_as_slave.cnf +++ b/mysql-test/suite/galera/galera_2nodes_as_slave.cnf @@ -46,6 +46,9 @@ wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' wsrep-on=OFF server-id=3 +[sst] +sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log + [ENV] NODE_MYPORT_1= @mysqld.1.port NODE_MYSOCK_1= @mysqld.1.socket diff --git a/mysql-test/suite/galera/galera_2x2nodes.cnf b/mysql-test/suite/galera/galera_2x2nodes.cnf index 0311ff09eb7..ac6b08d9bb2 100644 --- a/mysql-test/suite/galera/galera_2x2nodes.cnf +++ b/mysql-test/suite/galera/galera_2x2nodes.cnf @@ -11,7 +11,6 @@ default-storage-engine=innodb wsrep_gtid_mode=1 gtid_ignore_duplicates auto_increment_increment=3 - wsrep-provider=@ENV.WSREP_PROVIDER # enforce read-committed characteristics across the cluster # wsrep-causal-reads=ON @@ -61,6 +60,9 @@ wsrep_node_address='127.0.0.1:@mysqld.4.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.4.port wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port' +[sst] +sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log + [ENV] NODE_MYPORT_1= @mysqld.1.port NODE_MYSOCK_1= @mysqld.1.socket @@ -73,5 +75,3 @@ NODE_MYSOCK_3= @mysqld.3.socket NODE_MYPORT_4= @mysqld.4.port NODE_MYSOCK_4= @mysqld.4.socket - - diff --git a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf index 79b498868ad..7c4d7e40b7b 100644 --- a/mysql-test/suite/galera/galera_3nodes_as_slave.cnf +++ b/mysql-test/suite/galera/galera_3nodes_as_slave.cnf @@ -59,6 +59,9 @@ wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port' wsrep-on=OFF server-id=4 +[sst] +sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log + [ENV] NODE_MYPORT_1= @mysqld.1.port NODE_MYSOCK_1= @mysqld.1.socket diff --git a/mysql-test/suite/galera/galera_4nodes.cnf b/mysql-test/suite/galera/galera_4nodes.cnf index e39f206abd4..055c08c242f 100644 --- a/mysql-test/suite/galera/galera_4nodes.cnf +++ b/mysql-test/suite/galera/galera_4nodes.cnf @@ -59,6 +59,9 @@ wsrep_node_incoming_address=127.0.0.1:@mysqld.4.port wsrep_sst_receive_address='127.0.0.1:@mysqld.4.#sst_port' auto-increment-offset=4 +[sst] +sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log + [ENV] NODE_MYPORT_1= @mysqld.1.port NODE_MYSOCK_1= @mysqld.1.socket diff --git a/mysql-test/suite/galera/r/MDEV-33523.result b/mysql-test/suite/galera/r/MDEV-33523.result new file mode 100644 index 00000000000..3ce8371fc63 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-33523.result @@ -0,0 +1,6 @@ +connection node_2; +connection node_1; +SET SESSION wsrep_on=OFF; +BEGIN; +ROLLBACK; +SET SESSION wsrep_on=OFF; diff --git a/mysql-test/suite/galera/r/galera_as_slave_gtid_myisam.result b/mysql-test/suite/galera/r/galera_as_slave_gtid_myisam.result index 6559c7828be..5698ebf9fd3 100644 --- a/mysql-test/suite/galera/r/galera_as_slave_gtid_myisam.result +++ b/mysql-test/suite/galera/r/galera_as_slave_gtid_myisam.result @@ -22,12 +22,6 @@ EXPECT_1 1 gtid_binlog_state_equal 0 -connection node_2; -SELECT COUNT(*) AS EXPECT_1 FROM t1; -EXPECT_1 -1 -gtid_binlog_state_equal -0 #cleanup connection node_3; DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_bf_kill.result b/mysql-test/suite/galera/r/galera_bf_kill.result index 3738e8c9684..71b0366081b 100644 --- a/mysql-test/suite/galera/r/galera_bf_kill.result +++ b/mysql-test/suite/galera/r/galera_bf_kill.result @@ -49,16 +49,23 @@ a b disconnect node_2a; disconnect node_2b; connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; +connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2a; SET SESSION wsrep_on=OFF; begin; update t1 set a =5, b=2; connection node_2; ALTER TABLE t1 ADD UNIQUE KEY b3(b); +connection node_2b; +SET SESSION wsrep_sync_wait=0; +connection node_2a; select * from t1; a b -2 1 +5 2 +commit; +connection node_2; disconnect node_2a; +disconnect node_2b; connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2; connection node_2a; SET SESSION wsrep_on=OFF; @@ -67,7 +74,7 @@ update t1 set a =5, b=2; connection node_2; select * from t1; a b -2 1 +5 2 disconnect node_2a; connection node_1; drop table t1; diff --git a/mysql-test/suite/galera/r/galera_create_table_as_select.result b/mysql-test/suite/galera/r/galera_create_table_as_select.result index beda5f30fe2..4ee313fd683 100644 --- a/mysql-test/suite/galera/r/galera_create_table_as_select.result +++ b/mysql-test/suite/galera/r/galera_create_table_as_select.result @@ -76,22 +76,21 @@ EXECUTE stmt; DEALLOCATE PREPARE stmt; DROP TABLE t1, t2; connection node_1; +SET GLOBAL DEBUG_DBUG = 'd,sync.wsrep_apply_cb'; CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t2 VALUES (1),(2),(3),(4),(5); -connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; -LOCK TABLE t2 WRITE; -connection node_1; +SET DEBUG_SYNC = 'create_table_select_before_create WAIT_FOR sync.wsrep_apply_cb_reached'; +SET DEBUG_SYNC = 'create_table_select_before_lock SIGNAL signal.wsrep_apply_cb WAIT_FOR bf_abort'; CREATE TABLE t1 AS SELECT * FROM t2;; -connection node_1a; connection node_2; SELECT COUNT(*) = 5 FROM t2; COUNT(*) = 5 1 CREATE TABLE t1 AS SELECT * FROM t2; -connection node_1a; -UNLOCK TABLES; connection node_1; -Got one of the listed errors +ERROR 70100: Query execution was interrupted +SET GLOBAL DEBUG_DBUG = ''; +SET DEBUG_SYNC = 'RESET'; DROP TABLE t1, t2; CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t2 VALUES (1),(2),(3),(4),(5); diff --git a/mysql-test/suite/galera/r/galera_partition_key.result b/mysql-test/suite/galera/r/galera_partition_key.result new file mode 100644 index 00000000000..b4965482779 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_partition_key.result @@ -0,0 +1,46 @@ +connection node_2; +connection node_1; +connection node_1; +CREATE TABLE `t1` ( +`id` int(10) unsigned NOT NULL, +`other_id` int(10) unsigned NOT NULL, +PRIMARY KEY (`id`,`other_id`) +) ENGINE=InnoDB +PARTITION BY LIST (`id` MOD 2) +(PARTITION `p0` VALUES IN (0) ENGINE = InnoDB, +PARTITION `p1` VALUES IN (1) ENGINE = InnoDB); +INSERT INTO t1 VALUES (1, 0); +CREATE TABLE t2 LIKE t1; +START TRANSACTION; +INSERT INTO t2(SELECT * FROM t1 WHERE id = 1); +DELETE FROM t1 WHERE id = 1; +COMMIT; +connection node_2; +SELECT * from t1; +id other_id +SELECT * from t2; +id other_id +1 0 +DROP TABLE t1, t2; +connection node_1; +CREATE TABLE `t1` ( +`id` int(10) unsigned NOT NULL, +`other_id` int(10) unsigned NOT NULL, +PRIMARY KEY (`id`) +) ENGINE=InnoDB +PARTITION BY LIST (`id` MOD 2) +(PARTITION `p0` VALUES IN (0) ENGINE = InnoDB, +PARTITION `p1` VALUES IN (1) ENGINE = InnoDB); +INSERT INTO t1 VALUES (1, 0); +CREATE TABLE t2 LIKE t1; +START TRANSACTION; +INSERT INTO t2(SELECT * FROM t1 WHERE id = 1); +DELETE FROM t1 WHERE id = 1; +COMMIT; +connection node_2; +SELECT * from t1; +id other_id +SELECT * from t2; +id other_id +1 0 +DROP TABLE t1, t2; diff --git a/mysql-test/suite/galera/r/galera_replica_no_gtid.result b/mysql-test/suite/galera/r/galera_replica_no_gtid.result new file mode 100644 index 00000000000..80d713c2348 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_replica_no_gtid.result @@ -0,0 +1,71 @@ +connection node_2; +connection node_1; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +create user repl@'%' identified by 'repl'; +grant all on *.* to repl@'%'; +flush privileges; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +connection node_1; +connection node_2; +connection node_2; +START SLAVE; +connection node_3; +CREATE TABLE t1 (id bigint primary key, msg varchar(100)) engine=innodb; +SELECT COUNT(*) AS EXPECT_10000 FROM t1; +EXPECT_10000 +10000 +connection node_2; +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +EXPECT_1 +1 +SELECT COUNT(*) AS EXPECT_10000 FROM t1; +EXPECT_10000 +10000 +connection node_1; +SELECT COUNT(*) AS EXPECT_0 FROM mysql.gtid_slave_pos; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_10000 FROM t1; +EXPECT_10000 +10000 +connection node_2; +# Verify that graceful shutdown succeeds. +# Force SST +connection node_1; +# Waiting until node_2 is not part of cluster anymore +connection node_2; +# Start node_2 again +¤ Wait until node_2 is back on cluster +connection node_2; +call mtr.add_suppression("Slave: Operation CREATE USER failed for .*"); +SELECT COUNT(*) AS EXPECT_0 FROM mysql.gtid_slave_pos; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_10000 FROM t1; +EXPECT_10000 +10000 +connection node_1; +SELECT COUNT(*) AS EXPECT_0 FROM mysql.gtid_slave_pos; +EXPECT_0 +0 +SELECT COUNT(*) AS EXPECT_10000 FROM t1; +EXPECT_10000 +10000 +connection node_3; +SELECT COUNT(*) AS EXPECT_10000 FROM t1; +EXPECT_10000 +10000 +connection node_2; +STOP SLAVE; +RESET SLAVE ALL; +connection node_3; +RESET MASTER; +drop table t1; +connection node_2; +DROP TABLE t1; +connection node_1; +connection node_1; +disconnect node_3; +disconnect node_2; +disconnect node_1; +# End of test diff --git a/mysql-test/suite/galera/t/MDEV-33523.test b/mysql-test/suite/galera/t/MDEV-33523.test new file mode 100644 index 00000000000..5a2463d1973 --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-33523.test @@ -0,0 +1,11 @@ +# +# MDEV-33523: Spurious deadlock error when wsrep_on=OFF +# +--source include/galera_cluster.inc + +SET SESSION wsrep_on=OFF; +BEGIN; +# If bug is present, the following rollback +# results in ER_LOCK_DEADLOCK error. +ROLLBACK; +SET SESSION wsrep_on=OFF; diff --git a/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.test b/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.test index fd18de168f9..38f062b1748 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.test +++ b/mysql-test/suite/galera/t/galera_as_slave_gtid_myisam.test @@ -46,18 +46,8 @@ SELECT LENGTH(@@global.gtid_binlog_state) > 1; SELECT COUNT(*) AS EXPECT_1 FROM t1; ---disable_query_log ---eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal; ---enable_query_log - ---connection node_2 ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; ---source include/wait_condition.inc - ---let $wait_condition = SELECT COUNT(*) = 1 FROM t1; ---source include/wait_condition.inc - -SELECT COUNT(*) AS EXPECT_1 FROM t1; +# Note that MyISAM tables are not replicated by Galera so we do not here +# check node_2 --disable_query_log --eval SELECT '$gtid_binlog_state_node1' = @@global.gtid_binlog_state AS gtid_binlog_state_equal; diff --git a/mysql-test/suite/galera/t/galera_bf_kill.test b/mysql-test/suite/galera/t/galera_bf_kill.test index c8564bc9219..1b35b609a96 100644 --- a/mysql-test/suite/galera/t/galera_bf_kill.test +++ b/mysql-test/suite/galera/t/galera_bf_kill.test @@ -94,27 +94,43 @@ select * from t1; --disconnect node_2b # -# Test case 5: Start a transaction on node_2a with wsrep disabled -# and start a DDL on other transaction that will then abort node_2a -# transactions +# Test case 5: Start a transaction on node_2a with wsrep disabled. +# A conflicting DDL on other transaction can't BF abort +# transaction from node_2a (wsrep disabled). # --connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2 --connection node_2a SET SESSION wsrep_on=OFF; begin; update t1 set a =5, b=2; --connection node_2 -ALTER TABLE t1 ADD UNIQUE KEY b3(b); +--send ALTER TABLE t1 ADD UNIQUE KEY b3(b) +--connection node_2b +SET SESSION wsrep_sync_wait=0; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'Waiting for table metadata lock'; +--source include/wait_condition.inc + +--connection node_2a select * from t1; +# We expect that ALTER should not be able to BF abort +# this transaction, it must wait for it to finish. +# Expect commit to succeed. +commit; + +--connection node_2 +--reap + --disconnect node_2a +--disconnect node_2b # -# Test case 6: Start a transaction on node_2a with wsrep disabled -# and kill it from other connection on same node +# Test case 6: Start a transaction on node_2a with wsrep disabled +# and kill it from other connection on same node. # --connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 diff --git a/mysql-test/suite/galera/t/galera_create_table_as_select.test b/mysql-test/suite/galera/t/galera_create_table_as_select.test index cfee63e5e27..63af9b552e0 100644 --- a/mysql-test/suite/galera/t/galera_create_table_as_select.test +++ b/mysql-test/suite/galera/t/galera_create_table_as_select.test @@ -3,6 +3,8 @@ # --source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc --connection node_1 SET SESSION default_storage_engine=InnoDB; @@ -103,31 +105,27 @@ DROP TABLE t1, t2; # --connection node_1 +# Pause applying CTAS command from the other node +SET GLOBAL DEBUG_DBUG = 'd,sync.wsrep_apply_cb'; CREATE TABLE t2 (f1 INTEGER) ENGINE=InnoDB; INSERT INTO t2 VALUES (1),(2),(3),(4),(5); ---connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 -LOCK TABLE t2 WRITE; - ---connection node_1 +# Wait until local CTAS grabs MDL lock and let applied CTAS BF-abort it +SET DEBUG_SYNC = 'create_table_select_before_create WAIT_FOR sync.wsrep_apply_cb_reached'; +SET DEBUG_SYNC = 'create_table_select_before_lock SIGNAL signal.wsrep_apply_cb WAIT_FOR bf_abort'; --send CREATE TABLE t1 AS SELECT * FROM t2; ---connection node_1a ---let $wait_condition = SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE STATE LIKE 'Waiting for table metadata lock%' ---source include/wait_condition.inc - --connection node_2 SELECT COUNT(*) = 5 FROM t2; CREATE TABLE t1 AS SELECT * FROM t2; ---connection node_1a -UNLOCK TABLES; - --connection node_1 ---error ER_TABLE_EXISTS_ERROR,ER_QUERY_INTERRUPTED +--error ER_QUERY_INTERRUPTED --reap +SET GLOBAL DEBUG_DBUG = ''; +SET DEBUG_SYNC = 'RESET'; DROP TABLE t1, t2; # diff --git a/mysql-test/suite/galera/t/galera_myisam_autocommit.test b/mysql-test/suite/galera/t/galera_myisam_autocommit.test index 0612aabb233..5a10d646181 100644 --- a/mysql-test/suite/galera/t/galera_myisam_autocommit.test +++ b/mysql-test/suite/galera/t/galera_myisam_autocommit.test @@ -1,5 +1,6 @@ --source include/galera_cluster.inc --source include/have_innodb.inc +--source include/log_bin.inc # # This tests simple autocommit replication of MyISAM tables. diff --git a/mysql-test/suite/galera/t/galera_partition.test b/mysql-test/suite/galera/t/galera_partition.test index 269291311f1..d69f87b6472 100644 --- a/mysql-test/suite/galera/t/galera_partition.test +++ b/mysql-test/suite/galera/t/galera_partition.test @@ -2,6 +2,7 @@ --source include/have_partition.inc --source include/big_test.inc --source include/force_restart.inc +--source include/log_bin.inc --connection node_1 diff --git a/mysql-test/suite/galera/t/galera_partition_key.test b/mysql-test/suite/galera/t/galera_partition_key.test new file mode 100644 index 00000000000..ac1fcf72f06 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_partition_key.test @@ -0,0 +1,55 @@ +--source include/galera_cluster.inc +--source include/have_partition.inc +--source include/log_bin.inc + +--connection node_1 +CREATE TABLE `t1` ( + `id` int(10) unsigned NOT NULL, + `other_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`,`other_id`) +) ENGINE=InnoDB + PARTITION BY LIST (`id` MOD 2) +(PARTITION `p0` VALUES IN (0) ENGINE = InnoDB, + PARTITION `p1` VALUES IN (1) ENGINE = InnoDB); + +INSERT INTO t1 VALUES (1, 0); + +CREATE TABLE t2 LIKE t1; + +START TRANSACTION; + +INSERT INTO t2(SELECT * FROM t1 WHERE id = 1); +DELETE FROM t1 WHERE id = 1; + +COMMIT; + +--connection node_2 +SELECT * from t1; +SELECT * from t2; +DROP TABLE t1, t2; + +--connection node_1 +CREATE TABLE `t1` ( + `id` int(10) unsigned NOT NULL, + `other_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB + PARTITION BY LIST (`id` MOD 2) +(PARTITION `p0` VALUES IN (0) ENGINE = InnoDB, + PARTITION `p1` VALUES IN (1) ENGINE = InnoDB); + +INSERT INTO t1 VALUES (1, 0); + +CREATE TABLE t2 LIKE t1; + +START TRANSACTION; + +INSERT INTO t2(SELECT * FROM t1 WHERE id = 1); +DELETE FROM t1 WHERE id = 1; + +COMMIT; + +--connection node_2 +SELECT * from t1; +SELECT * from t2; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/galera/t/galera_replica_no_gtid.cnf b/mysql-test/suite/galera/t/galera_replica_no_gtid.cnf new file mode 100644 index 00000000000..916c1c1847f --- /dev/null +++ b/mysql-test/suite/galera/t/galera_replica_no_gtid.cnf @@ -0,0 +1,9 @@ +!include ../galera_2nodes_as_slave.cnf + +[mysqld] +wsrep-debug=1 +server_id=15 +wsrep_gtid_mode=OFF +wsrep_gtid_domain_id=16 +gtid_domain_id=11 +gtid_strict_mode=OFF diff --git a/mysql-test/suite/galera/t/galera_replica_no_gtid.test b/mysql-test/suite/galera/t/galera_replica_no_gtid.test new file mode 100644 index 00000000000..8cc88ef211a --- /dev/null +++ b/mysql-test/suite/galera/t/galera_replica_no_gtid.test @@ -0,0 +1,124 @@ +# +# Test Galera as a replica to a MySQL async replication +# +# The galera/galera_2node_slave.cnf describes the setup of the nodes +# +--source include/force_restart.inc +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_sequence.inc + +# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it +# we open the node_3 connection here +--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 + +create user repl@'%' identified by 'repl'; +grant all on *.* to repl@'%'; +flush privileges; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; + +--let $node_1 = node_1 +--let $node_2 = node_2 +--source include/auto_increment_offset_save.inc + +--connection node_2 +--disable_query_log +--eval CHANGE MASTER TO master_host='127.0.0.1', master_user='repl', master_password='repl', master_port=$NODE_MYPORT_3, master_use_gtid=slave_pos; +--enable_query_log +START SLAVE; + +--connection node_3 + +CREATE TABLE t1 (id bigint primary key, msg varchar(100)) engine=innodb; +--disable_query_log +INSERT INTO t1 SELECT seq, 'test' from seq_1_to_10000; +--enable_query_log +SELECT COUNT(*) AS EXPECT_10000 FROM t1; + +--connection node_2 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 10000 FROM t1; +--source include/wait_condition.inc + +# +# Node_2 is slave so mysql.gtid_slave_pos table is also replicated +# +SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos; +SELECT COUNT(*) AS EXPECT_10000 FROM t1; + +--connection node_1 +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--let $wait_condition = SELECT COUNT(*) = 10000 FROM t1; +--source include/wait_condition.inc + +# +# mysql-gtid_slave_pos table should not be replicated by Galera +# +SELECT COUNT(*) AS EXPECT_0 FROM mysql.gtid_slave_pos; +SELECT COUNT(*) AS EXPECT_10000 FROM t1; + +--connection node_2 +--echo # Verify that graceful shutdown succeeds. +--source include/shutdown_mysqld.inc +--echo # Force SST +--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat + +--connection node_1 +--echo # Waiting until node_2 is not part of cluster anymore +--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc + +--connection node_2 +--echo # Start node_2 again +--source include/start_mysqld.inc + +--echo ¤ Wait until node_2 is back on cluster +--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +--source include/wait_condition.inc +--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready'; +--source include/wait_condition.inc + +--connection node_2 +call mtr.add_suppression("Slave: Operation CREATE USER failed for .*"); +SELECT COUNT(*) AS EXPECT_0 FROM mysql.gtid_slave_pos; +SELECT COUNT(*) AS EXPECT_10000 FROM t1; + +--connection node_1 +SELECT COUNT(*) AS EXPECT_0 FROM mysql.gtid_slave_pos; +SELECT COUNT(*) AS EXPECT_10000 FROM t1; + +--connection node_3 +SELECT COUNT(*) AS EXPECT_10000 FROM t1; + +# +# Cleanup +# +--connection node_2 +STOP SLAVE; +RESET SLAVE ALL; + +--connection node_3 +RESET MASTER; +drop table t1; + +--connection node_2 +DROP TABLE t1; + +--connection node_1 +--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; +--source include/wait_condition.inc + +--connection node_1 +--disconnect node_3 + +--source include/auto_increment_offset_restore.inc +--source include/galera_end.inc +--echo # End of test diff --git a/mysql-test/suite/galera/t/mdev-22063.test b/mysql-test/suite/galera/t/mdev-22063.test index d0f3e3bc4b4..d3ddb164d3d 100644 --- a/mysql-test/suite/galera/t/mdev-22063.test +++ b/mysql-test/suite/galera/t/mdev-22063.test @@ -1,6 +1,6 @@ --source include/galera_cluster.inc --source include/have_innodb.inc ---source include/have_log_bin.inc +--source include/log_bin.inc --source include/have_sequence.inc --source include/have_aria.inc diff --git a/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf b/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf index 56da3150792..f670ba5a93e 100644 --- a/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf +++ b/mysql-test/suite/galera_3nodes/galera_2x3nodes.cnf @@ -83,6 +83,9 @@ wsrep_node_address='127.0.0.1:@mysqld.6.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.6.port wsrep_sst_receive_address='127.0.0.1:@mysqld.6.#sst_port' +[sst] +sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log + [ENV] NODE_MYPORT_1= @mysqld.1.port NODE_MYSOCK_1= @mysqld.1.socket diff --git a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf index d43f1373ed3..832dd2a34e7 100644 --- a/mysql-test/suite/galera_3nodes/galera_3nodes.cnf +++ b/mysql-test/suite/galera_3nodes/galera_3nodes.cnf @@ -46,6 +46,9 @@ wsrep_node_address='127.0.0.1:@mysqld.3.#galera_port' wsrep_node_incoming_address=127.0.0.1:@mysqld.3.port wsrep_sst_receive_address='127.0.0.1:@mysqld.3.#sst_port' +[sst] +sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log + [ENV] NODE_MYPORT_1= @mysqld.1.port NODE_MYSOCK_1= @mysqld.1.socket diff --git a/mysql-test/suite/galera_3nodes/r/galera_gtid_2_cluster.result b/mysql-test/suite/galera_3nodes/r/galera_gtid_2_cluster.result index 7d4751e79af..1cb14cd3eff 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_gtid_2_cluster.result +++ b/mysql-test/suite/galera_3nodes/r/galera_gtid_2_cluster.result @@ -75,15 +75,15 @@ insert into t1 values (2, 21, 1); select @@gtid_binlog_state; @@gtid_binlog_state 1-11-2,2-21-1 -select * from t1; -cluster_domain_id node_server_id seq_no -1 11 2 -2 21 1 #wait for sync cluster 1 and 2 connection node_1; include/save_master_gtid.inc connection node_4; include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +2 21 1 cluster 1 node 2 connection node_2; select @@gtid_binlog_state; @@ -98,6 +98,11 @@ connection node_1; include/save_master_gtid.inc connection node_4; include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +2 21 1 cluster 1 node 3 connection node_3; select @@gtid_binlog_state; @@ -112,6 +117,12 @@ connection node_1; include/save_master_gtid.inc connection node_4; include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 cluster 2 node 2 connection node_5; select @@gtid_binlog_state; @@ -126,6 +137,13 @@ connection node_4; include/save_master_gtid.inc connection node_1; include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 +2 22 2 cluster 2 node 3 connection node_6; select @@gtid_binlog_state; @@ -140,6 +158,63 @@ connection node_4; include/save_master_gtid.inc connection node_1; include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 +2 22 2 +2 23 3 +# check other nodes are consistent +connection node_2; +select @@gtid_binlog_state; +@@gtid_binlog_state +1-11-4,2-21-3 +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 +2 22 2 +2 23 3 +connection node_3; +select @@gtid_binlog_state; +@@gtid_binlog_state +1-11-4,2-21-3 +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 +2 22 2 +2 23 3 +connection node_5; +select @@gtid_binlog_state; +@@gtid_binlog_state +1-11-4,2-21-3 +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 +2 22 2 +2 23 3 +connection node_6; +select @@gtid_binlog_state; +@@gtid_binlog_state +1-11-4,2-21-3 +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 +2 22 2 +2 23 3 cluster 1 node 1 connection node_1; select @@gtid_binlog_state; @@ -220,15 +295,15 @@ insert into t1 values (2, 21, 1); select @@gtid_binlog_state; @@gtid_binlog_state 1-11-7,2-21-4 -select * from t1; -cluster_domain_id node_server_id seq_no -1 11 2 -2 21 1 #wait for sync cluster 1 and 2 connection node_1; include/save_master_gtid.inc connection node_4; include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +2 21 1 cluster 1 node 2 connection node_2; select @@gtid_binlog_state; @@ -243,6 +318,11 @@ connection node_1; include/save_master_gtid.inc connection node_4; include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +2 21 1 cluster 1 node 3 connection node_3; select @@gtid_binlog_state; @@ -257,6 +337,12 @@ connection node_1; include/save_master_gtid.inc connection node_4; include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 cluster 2 node 2 connection node_5; select @@gtid_binlog_state; @@ -271,6 +357,13 @@ connection node_4; include/save_master_gtid.inc connection node_1; include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 +2 22 2 cluster 2 node 3 connection node_6; select @@gtid_binlog_state; @@ -285,6 +378,63 @@ connection node_4; include/save_master_gtid.inc connection node_1; include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 +2 22 2 +2 23 3 +# check other nodes are consistent +connection node_2; +select @@gtid_binlog_state; +@@gtid_binlog_state +1-11-9,2-21-6 +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 +2 22 2 +2 23 3 +connection node_3; +select @@gtid_binlog_state; +@@gtid_binlog_state +1-11-9,2-21-6 +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 +2 22 2 +2 23 3 +connection node_5; +select @@gtid_binlog_state; +@@gtid_binlog_state +1-11-9,2-21-6 +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 +2 22 2 +2 23 3 +connection node_6; +select @@gtid_binlog_state; +@@gtid_binlog_state +1-11-9,2-21-6 +select * from t1 order by 1, 2, 3; +cluster_domain_id node_server_id seq_no +1 11 2 +1 12 3 +1 13 4 +2 21 1 +2 22 2 +2 23 3 cluster 1 node 1 connection node_1; select @@gtid_binlog_state; diff --git a/mysql-test/suite/galera_3nodes/t/galera_gtid_2_cluster.cnf b/mysql-test/suite/galera_3nodes/t/galera_gtid_2_cluster.cnf index dc5535ef34a..bc64d114275 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_gtid_2_cluster.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_gtid_2_cluster.cnf @@ -9,11 +9,11 @@ server-id=11 [mysqld.2] wsrep_gtid_domain_id=1 -server-id=12 +server-id=11 [mysqld.3] wsrep_gtid_domain_id=1 -server-id=13 +server-id=11 [mysqld.4] wsrep_gtid_domain_id=2 @@ -21,8 +21,8 @@ server-id=21 [mysqld.5] wsrep_gtid_domain_id=2 -server-id=22 +server-id=21 [mysqld.6] wsrep_gtid_domain_id=2 -server-id=23 +server-id=21 diff --git a/mysql-test/suite/galera_3nodes/t/galera_gtid_2_cluster.test b/mysql-test/suite/galera_3nodes/t/galera_gtid_2_cluster.test index 925600ffaa8..c8247f15aba 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_gtid_2_cluster.test +++ b/mysql-test/suite/galera_3nodes/t/galera_gtid_2_cluster.test @@ -11,6 +11,7 @@ --source include/big_test.inc --source include/galera_cluster.inc --source include/have_innodb.inc +--source include/force_restart.inc --connection node_1 --echo cluster 1 node 1 @@ -75,12 +76,12 @@ select @@gtid_binlog_state; select @@gtid_binlog_state; insert into t1 values (2, 21, 1); select @@gtid_binlog_state; -select * from t1; --echo #wait for sync cluster 1 and 2 --connection node_1 --source include/save_master_gtid.inc --connection node_4 --source include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; --echo cluster 1 node 2 @@ -94,6 +95,7 @@ select @@gtid_binlog_state; --source include/save_master_gtid.inc --connection node_4 --source include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; --echo cluster 1 node 3 --connection node_3 @@ -106,6 +108,7 @@ select @@gtid_binlog_state; --source include/save_master_gtid.inc --connection node_4 --source include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; --echo cluster 2 node 2 --connection node_5 @@ -118,6 +121,7 @@ select @@gtid_binlog_state; --source include/save_master_gtid.inc --connection node_1 --source include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; --echo cluster 2 node 3 --connection node_6 @@ -130,7 +134,21 @@ select @@gtid_binlog_state; --source include/save_master_gtid.inc --connection node_1 --source include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; +--echo # check other nodes are consistent +--connection node_2 +select @@gtid_binlog_state; +select * from t1 order by 1, 2, 3; +--connection node_3 +select @@gtid_binlog_state; +select * from t1 order by 1, 2, 3; +--connection node_5 +select @@gtid_binlog_state; +select * from t1 order by 1, 2, 3; +--connection node_6 +select @@gtid_binlog_state; +select * from t1 order by 1, 2, 3; --echo cluster 1 node 1 --connection node_1 @@ -226,13 +244,13 @@ select @@gtid_binlog_state; --connection node_4 insert into t1 values (2, 21, 1); select @@gtid_binlog_state; -select * from t1; --echo #wait for sync cluster 1 and 2 --connection node_1 --source include/save_master_gtid.inc --connection node_4 --source include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; --echo cluster 1 node 2 @@ -246,6 +264,7 @@ select @@gtid_binlog_state; --source include/save_master_gtid.inc --connection node_4 --source include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; --echo cluster 1 node 3 --connection node_3 @@ -258,6 +277,7 @@ select @@gtid_binlog_state; --source include/save_master_gtid.inc --connection node_4 --source include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; --echo cluster 2 node 2 --connection node_5 @@ -270,6 +290,7 @@ select @@gtid_binlog_state; --source include/save_master_gtid.inc --connection node_1 --source include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; --echo cluster 2 node 3 --connection node_6 @@ -282,7 +303,21 @@ select @@gtid_binlog_state; --source include/save_master_gtid.inc --connection node_1 --source include/sync_with_master_gtid.inc +select * from t1 order by 1, 2, 3; +--echo # check other nodes are consistent +--connection node_2 +select @@gtid_binlog_state; +select * from t1 order by 1, 2, 3; +--connection node_3 +select @@gtid_binlog_state; +select * from t1 order by 1, 2, 3; +--connection node_5 +select @@gtid_binlog_state; +select * from t1 order by 1, 2, 3; +--connection node_6 +select @@gtid_binlog_state; +select * from t1 order by 1, 2, 3; --echo cluster 1 node 1 --connection node_1 diff --git a/mysql-test/suite/innodb/r/innodb_status_variables.result b/mysql-test/suite/innodb/r/innodb_status_variables.result index 2eeed4f169a..194528c99da 100644 --- a/mysql-test/suite/innodb/r/innodb_status_variables.result +++ b/mysql-test/suite/innodb/r/innodb_status_variables.result @@ -98,3 +98,4 @@ INNODB_ENCRYPTION_N_ROWLOG_BLOCKS_DECRYPTED INNODB_ENCRYPTION_N_TEMP_BLOCKS_ENCRYPTED INNODB_ENCRYPTION_N_TEMP_BLOCKS_DECRYPTED INNODB_ENCRYPTION_NUM_KEY_REQUESTS +INNODB_BULK_OPERATIONS diff --git a/mysql-test/suite/innodb/r/insert_into_empty.result b/mysql-test/suite/innodb/r/insert_into_empty.result index d4ffaf89a91..c679f11ac0a 100644 --- a/mysql-test/suite/innodb/r/insert_into_empty.result +++ b/mysql-test/suite/innodb/r/insert_into_empty.result @@ -20,9 +20,17 @@ DROP TEMPORARY TABLE t; SET @save_ahi = @@global.innodb_adaptive_hash_index; SET GLOBAL innodb_adaptive_hash_index = 1; CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB; +SET @old_bulk_op= +(SELECT variable_value FROM information_schema.global_status +WHERE variable_name = 'innodb_bulk_operations'); BEGIN; INSERT INTO t1 SELECT * FROM seq_1_to_65536; ROLLBACK; +SELECT variable_value-@old_bulk_op bulk_operations +FROM information_schema.global_status +WHERE variable_name = 'innodb_bulk_operations'; +bulk_operations +1 CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK @@ -260,6 +268,19 @@ PARTITION BY KEY(a) PARTITIONS 16; INSERT INTO t1 VALUES(1); UPDATE t1 SET a = 2 WHERE a = 1; DROP TABLE t1; +# +# MDEV-34265 Possible hang during IO burst with innodb_flush_sync enabled +# +CREATE TABLE t1(f1 MEDIUMTEXT)ENGINE=InnoDB; +SET @save_dbug=@@GLOBAL.debug_dbug; +SET @@GLOBAL.debug_dbug='+d,ib_page_cleaner_sleep'; +SET STATEMENT debug_dbug='+d,ib_free_page_sleep' FOR +INSERT INTO t1 VALUES(REPEAT(1, 8459264)); +SET @@GLOBAL.debug_dbug=@save_dbug; +SELECT length(f1) FROM t1; +length(f1) +8459264 +DROP TABLE t1; # End of 10.6 tests # # MDEV-26947 UNIQUE column checks fail in InnoDB resulting diff --git a/mysql-test/suite/innodb/r/lock_memory.result b/mysql-test/suite/innodb/r/lock_memory.result new file mode 100644 index 00000000000..9859fdfd1f4 --- /dev/null +++ b/mysql-test/suite/innodb/r/lock_memory.result @@ -0,0 +1,20 @@ +# +# MDEV-28800 SIGABRT due to running out of memory for InnoDB locks +# +CREATE TABLE t1 (col1 INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +START TRANSACTION; +INSERT INTO t1 SELECT a.* FROM t1 a, t1 b, t1 c, t1 d; +SELECT CASE WHEN (POOL_SIZE - (FREE_BUFFERS + DATABASE_PAGES)) <= 10 THEN "PASSED" + ELSE (POOL_SIZE - (FREE_BUFFERS + DATABASE_PAGES)) END +FROM information_schema.innodb_buffer_pool_stats; +CASE WHEN (POOL_SIZE - (FREE_BUFFERS + DATABASE_PAGES)) <= 10 THEN "PASSED" + ELSE (POOL_SIZE - (FREE_BUFFERS + DATABASE_PAGES)) END +PASSED +COMMIT; +SELECT COUNT(*) FROM t1; +COUNT(*) +65552 +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/lock_memory_debug.result b/mysql-test/suite/innodb/r/lock_memory_debug.result new file mode 100644 index 00000000000..36d7433974e --- /dev/null +++ b/mysql-test/suite/innodb/r/lock_memory_debug.result @@ -0,0 +1,13 @@ +# +# MDEV-34166 Server could hang with BP < 80M under stress +# +call mtr.add_suppression("\\[Warning\\] InnoDB: Over 67 percent of the buffer pool"); +CREATE TABLE t1 (col1 INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +SET STATEMENT debug_dbug='+d,innodb_skip_lock_bitmap' FOR +INSERT INTO t1 SELECT a.* FROM t1 a, t1 b, t1 c, t1 d, t1 e, t1 f, t1 g LIMIT 45000; +ERROR HY000: The total number of locks exceeds the lock table size +SELECT COUNT(*) FROM t1; +COUNT(*) +5 +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/open_files_limit.result b/mysql-test/suite/innodb/r/open_files_limit.result new file mode 100644 index 00000000000..d6785cc4775 --- /dev/null +++ b/mysql-test/suite/innodb/r/open_files_limit.result @@ -0,0 +1,6 @@ +call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*"); +call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is exceeded \\(.* files stay open\\)"); +FOUND 1 /\[Warning\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*/ in mysqld.1.err +CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB; +DROP TABLE t1; +# restart: --innodb_open_files=0 diff --git a/mysql-test/suite/innodb/r/table_flags.result b/mysql-test/suite/innodb/r/table_flags.result index e38eb93e781..c4470b00017 100644 --- a/mysql-test/suite/innodb/r/table_flags.result +++ b/mysql-test/suite/innodb/r/table_flags.result @@ -185,3 +185,14 @@ ALTER TABLE t1 PAGE_COMPRESSED = 1; INSERT INTO t1 VALUES(2); # restart DROP TABLE t1; +# +# MDEV-34222 Alter operation on redundant table aborts the server +# +SET @df_row = @@global.INNODB_DEFAULT_ROW_FORMAT; +SET GLOBAL INNODB_DEFAULT_ROW_FORMAT=REDUNDANT; +CREATE TABLE t1 (c CHAR(1)) ENGINE=InnoDB; +SET GLOBAL INNODB_DEFAULT_ROW_FORMAT=compact; +ALTER TABLE t1 PAGE_COMPRESSED=1; +ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'PAGE_COMPRESSED=1 ROW_FORMAT=REDUNDANT' +DROP TABLE t1; +SET @@global.INNODB_DEFAULT_ROW_FORMAT = @df_row; diff --git a/mysql-test/suite/innodb/r/temporary_table.result b/mysql-test/suite/innodb/r/temporary_table.result index e90302daba4..bb5f960e7cb 100644 --- a/mysql-test/suite/innodb/r/temporary_table.result +++ b/mysql-test/suite/innodb/r/temporary_table.result @@ -801,4 +801,14 @@ CHECK TABLE t EXTENDED; Table Op Msg_type Msg_text test.t check status OK DROP TEMPORARY TABLE t; +# +# MDEV-34118 fsp_alloc_free_extent() fails to flag DB_OUT_OF_FILE_SPACE +# +SET @save_increment = @@GLOBAL.innodb_autoextend_increment; +SET GLOBAL innodb_autoextend_increment=1; +CREATE TEMPORARY TABLE t (c LONGTEXT) ENGINE=INNODB; +INSERT INTO t VALUES (REPEAT ('1',16777216)); +ERROR HY000: The table 't' is full +DROP TEMPORARY TABLE t; +SET GLOBAL innodb_autoextend_increment=@save_increment; # End of 10.6 tests diff --git a/mysql-test/suite/innodb/r/undo_space_dblwr.result b/mysql-test/suite/innodb/r/undo_space_dblwr.result index 4466df9857b..2172ce53cb7 100644 --- a/mysql-test/suite/innodb/r/undo_space_dblwr.result +++ b/mysql-test/suite/innodb/r/undo_space_dblwr.result @@ -12,7 +12,7 @@ set global innodb_fil_make_page_dirty_debug = 1; SET GLOBAL innodb_buf_flush_list_now = 1; # Kill the server # restart: --debug_dbug=+d,ib_log_checkpoint_avoid_hard --innodb_flush_sync=0 -FOUND 1 /Checksum mismatch in the first page of file/ in mysqld.1.err +FOUND 1 /Restoring page \[page id: space=1, page number=0\] of datafile '.*undo001' from the doublewrite buffer./ in mysqld.1.err check table t1; Table Op Msg_type Msg_text test.t1 check status OK diff --git a/mysql-test/suite/innodb/r/xa_recovery.result b/mysql-test/suite/innodb/r/xa_recovery.result index f61e29be20e..0caa501c1e1 100644 --- a/mysql-test/suite/innodb/r/xa_recovery.result +++ b/mysql-test/suite/innodb/r/xa_recovery.result @@ -1,4 +1,4 @@ -CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connect con1,localhost,root; XA START 'x'; @@ -6,7 +6,7 @@ UPDATE t1 set a=2; XA END 'x'; XA PREPARE 'x'; connect con2,localhost,root; -CREATE TABLE t2 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; XA START 'y'; INSERT INTO t2 VALUES (1); XA END 'y'; @@ -30,10 +30,21 @@ XA ROLLBACK 'x'; SELECT * FROM t1; a 1 -DROP TABLE t1; DROP TABLE t2; ERROR HY000: Lock wait timeout exceeded; try restarting transaction XA ROLLBACK 'y'; DROP TABLE t2; +CREATE TABLE t3(a INT PRIMARY KEY REFERENCES t1(a)) ENGINE=InnoDB; +XA START 'a'; +INSERT INTO t3 SET a=1; +INSERT INTO t3 SET a=42; +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t3`, CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +XA END 'a'; +XA PREPARE 'a'; SET GLOBAL innodb_fast_shutdown=0; # restart +XA COMMIT 'a'; +SELECT * FROM t3; +a +1 +DROP TABLE t3,t1; diff --git a/mysql-test/suite/innodb/t/insert_into_empty.test b/mysql-test/suite/innodb/t/insert_into_empty.test index e22ed11d723..ec9bb0b8802 100644 --- a/mysql-test/suite/innodb/t/insert_into_empty.test +++ b/mysql-test/suite/innodb/t/insert_into_empty.test @@ -26,9 +26,19 @@ DROP TEMPORARY TABLE t; SET @save_ahi = @@global.innodb_adaptive_hash_index; SET GLOBAL innodb_adaptive_hash_index = 1; CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB; + +SET @old_bulk_op= +(SELECT variable_value FROM information_schema.global_status +WHERE variable_name = 'innodb_bulk_operations'); + BEGIN; INSERT INTO t1 SELECT * FROM seq_1_to_65536; ROLLBACK; + +SELECT variable_value-@old_bulk_op bulk_operations +FROM information_schema.global_status +WHERE variable_name = 'innodb_bulk_operations'; + CHECK TABLE t1; --echo # --echo # MDEV-24832 Root page AHI Removal fails fails during @@ -153,9 +163,9 @@ DROP TABLE t1,t2; CREATE TABLE t1 (a INT KEY) ENGINE=InnoDB; ---error 0,1193 +--error 0,ER_UNKNOWN_SYSTEM_VARIABLE SET @save_limit = @@GLOBAL.innodb_limit_optimistic_insert_debug; ---error 0,1193 +--error 0,ER_UNKNOWN_SYSTEM_VARIABLE SET GLOBAL innodb_limit_optimistic_insert_debug = 2; BEGIN; @@ -281,6 +291,32 @@ CREATE TABLE t1(a INT KEY)ENGINE=InnoDB INSERT INTO t1 VALUES(1); UPDATE t1 SET a = 2 WHERE a = 1; DROP TABLE t1; + +--echo # +--echo # MDEV-34265 Possible hang during IO burst with innodb_flush_sync enabled +--echo # +CREATE TABLE t1(f1 MEDIUMTEXT)ENGINE=InnoDB; + +--error 0,ER_UNKNOWN_SYSTEM_VARIABLE +SET @save_dbug=@@GLOBAL.debug_dbug; +--error 0,ER_UNKNOWN_SYSTEM_VARIABLE +SET @@GLOBAL.debug_dbug='+d,ib_page_cleaner_sleep'; + +if ($have_debug) { + SET STATEMENT debug_dbug='+d,ib_free_page_sleep' FOR + INSERT INTO t1 VALUES(REPEAT(1, 8459264)); +} +if (!$have_debug) { + --echo SET STATEMENT debug_dbug='+d,ib_free_page_sleep' FOR + INSERT INTO t1 VALUES(REPEAT(1, 8459264)); +} + +--error 0,ER_UNKNOWN_SYSTEM_VARIABLE +SET @@GLOBAL.debug_dbug=@save_dbug; + +SELECT length(f1) FROM t1; +DROP TABLE t1; + --echo # End of 10.6 tests --echo # diff --git a/mysql-test/suite/innodb/t/lock_memory.test b/mysql-test/suite/innodb/t/lock_memory.test new file mode 100644 index 00000000000..6b936e18dfc --- /dev/null +++ b/mysql-test/suite/innodb/t/lock_memory.test @@ -0,0 +1,29 @@ +--source include/have_innodb.inc +--source include/have_innodb_16k.inc + +--echo # +--echo # MDEV-28800 SIGABRT due to running out of memory for InnoDB locks +--echo # + +CREATE TABLE t1 (col1 INT) ENGINE=InnoDB; + +INSERT INTO t1 VALUES (1),(2),(3),(4); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; + +START TRANSACTION; + +# Insert 64K records +INSERT INTO t1 SELECT a.* FROM t1 a, t1 b, t1 c, t1 d; + +# The check needs to be adjusted if we start using more memory for locks. It +# needs 9 pages for 16k page size and we put the limit as 10. +SELECT CASE WHEN (POOL_SIZE - (FREE_BUFFERS + DATABASE_PAGES)) <= 10 THEN "PASSED" + ELSE (POOL_SIZE - (FREE_BUFFERS + DATABASE_PAGES)) END +FROM information_schema.innodb_buffer_pool_stats; + +COMMIT; + +SELECT COUNT(*) FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/lock_memory_debug.opt b/mysql-test/suite/innodb/t/lock_memory_debug.opt new file mode 100644 index 00000000000..67c8423cf2a --- /dev/null +++ b/mysql-test/suite/innodb/t/lock_memory_debug.opt @@ -0,0 +1 @@ +--innodb_buffer_pool_size=5M diff --git a/mysql-test/suite/innodb/t/lock_memory_debug.test b/mysql-test/suite/innodb/t/lock_memory_debug.test new file mode 100644 index 00000000000..51e0e8fd57e --- /dev/null +++ b/mysql-test/suite/innodb/t/lock_memory_debug.test @@ -0,0 +1,19 @@ +--source include/have_innodb.inc +--source include/have_debug.inc + +--echo # +--echo # MDEV-34166 Server could hang with BP < 80M under stress +--echo # + +call mtr.add_suppression("\\[Warning\\] InnoDB: Over 67 percent of the buffer pool"); + +CREATE TABLE t1 (col1 INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); + +--error ER_LOCK_TABLE_FULL +SET STATEMENT debug_dbug='+d,innodb_skip_lock_bitmap' FOR +INSERT INTO t1 SELECT a.* FROM t1 a, t1 b, t1 c, t1 d, t1 e, t1 f, t1 g LIMIT 45000; + +SELECT COUNT(*) FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/open_files_limit.opt b/mysql-test/suite/innodb/t/open_files_limit.opt new file mode 100644 index 00000000000..cd71a062da8 --- /dev/null +++ b/mysql-test/suite/innodb/t/open_files_limit.opt @@ -0,0 +1,3 @@ +--innodb_undo_tablespaces=8 +--innodb_open_files=10 +--innodb_temp_data_file_path=ibtmp1:32M;ibtmp2:32M:autoextend diff --git a/mysql-test/suite/innodb/t/open_files_limit.test b/mysql-test/suite/innodb/t/open_files_limit.test new file mode 100644 index 00000000000..8b45c73aac5 --- /dev/null +++ b/mysql-test/suite/innodb/t/open_files_limit.test @@ -0,0 +1,12 @@ +--source include/have_innodb.inc +--source include/not_embedded.inc +call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*"); +call mtr.add_suppression("\\[Warning\\] InnoDB: innodb_open_files=.* is exceeded \\(.* files stay open\\)"); +let SEARCH_PATTERN= \[Warning\] InnoDB: innodb_open_files=.* is not greater than the number of system tablespace files, temporary tablespace files, innodb_undo_tablespaces=.*; +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; +--source include/search_pattern_in_file.inc + +CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB; +DROP TABLE t1; +let $restart_parameters=--innodb_open_files=0; +--source include/restart_mysqld.inc diff --git a/mysql-test/suite/innodb/t/table_flags.test b/mysql-test/suite/innodb/t/table_flags.test index e88499a4278..8badb6af79b 100644 --- a/mysql-test/suite/innodb/t/table_flags.test +++ b/mysql-test/suite/innodb/t/table_flags.test @@ -256,3 +256,15 @@ INSERT INTO t1 VALUES(2); let $shutdown_timeout = 0; --source include/restart_mysqld.inc DROP TABLE t1; + +--echo # +--echo # MDEV-34222 Alter operation on redundant table aborts the server +--echo # +SET @df_row = @@global.INNODB_DEFAULT_ROW_FORMAT; +SET GLOBAL INNODB_DEFAULT_ROW_FORMAT=REDUNDANT; +CREATE TABLE t1 (c CHAR(1)) ENGINE=InnoDB; +SET GLOBAL INNODB_DEFAULT_ROW_FORMAT=compact; +--error ER_ILLEGAL_HA_CREATE_OPTION +ALTER TABLE t1 PAGE_COMPRESSED=1; +DROP TABLE t1; +SET @@global.INNODB_DEFAULT_ROW_FORMAT = @df_row; diff --git a/mysql-test/suite/innodb/t/temporary_table.test b/mysql-test/suite/innodb/t/temporary_table.test index 9c742ce75c6..0a8e72969d5 100644 --- a/mysql-test/suite/innodb/t/temporary_table.test +++ b/mysql-test/suite/innodb/t/temporary_table.test @@ -635,4 +635,23 @@ CHECK TABLE t; CHECK TABLE t EXTENDED; DROP TEMPORARY TABLE t; +--echo # +--echo # MDEV-34118 fsp_alloc_free_extent() fails to flag DB_OUT_OF_FILE_SPACE +--echo # +SET @save_increment = @@GLOBAL.innodb_autoextend_increment; +SET GLOBAL innodb_autoextend_increment=1; +CREATE TEMPORARY TABLE t (c LONGTEXT) ENGINE=INNODB; +if ($MTR_COMBINATION_4K) +{ +--error ER_RECORD_FILE_FULL +INSERT INTO t VALUES (REPEAT ('1',16777216)); +} +if (!$MTR_COMBINATION_4K) +{ +INSERT INTO t VALUES (REPEAT ('1',16777216)); +--echo ERROR HY000: The table 't' is full +} +DROP TEMPORARY TABLE t; +SET GLOBAL innodb_autoextend_increment=@save_increment; + --echo # End of 10.6 tests diff --git a/mysql-test/suite/innodb/t/undo_space_dblwr.test b/mysql-test/suite/innodb/t/undo_space_dblwr.test index 52b19a4b7fb..4cf4d3b8b6d 100644 --- a/mysql-test/suite/innodb/t/undo_space_dblwr.test +++ b/mysql-test/suite/innodb/t/undo_space_dblwr.test @@ -39,7 +39,7 @@ EOF --source include/start_mysqld.inc let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; -let SEARCH_PATTERN= Checksum mismatch in the first page of file; +let SEARCH_PATTERN= Restoring page \[page id: space=1, page number=0\] of datafile '.*undo001' from the doublewrite buffer.; --source include/search_pattern_in_file.inc check table t1; diff --git a/mysql-test/suite/innodb/t/xa_recovery.test b/mysql-test/suite/innodb/t/xa_recovery.test index 547c4eb9d54..e3479f6fe78 100644 --- a/mysql-test/suite/innodb/t/xa_recovery.test +++ b/mysql-test/suite/innodb/t/xa_recovery.test @@ -10,12 +10,12 @@ call mtr.add_suppression("Found [12] prepared XA transactions"); FLUSH TABLES; --enable_query_log -CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connect (con1,localhost,root); XA START 'x'; UPDATE t1 set a=2; XA END 'x'; XA PREPARE 'x'; connect (con2,localhost,root); -CREATE TABLE t2 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; XA START 'y'; INSERT INTO t2 VALUES (1); XA END 'y'; XA PREPARE 'y'; connection default; @@ -53,11 +53,21 @@ SELECT * FROM t1; XA ROLLBACK 'x'; SELECT * FROM t1; -DROP TABLE t1; --error ER_LOCK_WAIT_TIMEOUT DROP TABLE t2; XA ROLLBACK 'y'; DROP TABLE t2; +CREATE TABLE t3(a INT PRIMARY KEY REFERENCES t1(a)) ENGINE=InnoDB; +XA START 'a'; +INSERT INTO t3 SET a=1; +--error ER_NO_REFERENCED_ROW_2 +INSERT INTO t3 SET a=42; +XA END 'a'; +XA PREPARE 'a'; SET GLOBAL innodb_fast_shutdown=0; --source include/restart_mysqld.inc + +XA COMMIT 'a'; +SELECT * FROM t3; +DROP TABLE t3,t1; diff --git a/mysql-test/suite/innodb_fts/r/fts_sync_commit_resiliency.result b/mysql-test/suite/innodb_fts/r/fts_sync_commit_resiliency.result new file mode 100644 index 00000000000..1908502c9db --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/fts_sync_commit_resiliency.result @@ -0,0 +1,63 @@ +CREATE TABLE opening_lines ( +id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, +opening_line TEXT(500), +author VARCHAR(200), +title VARCHAR(200) +) ENGINE=InnoDB; +CREATE FULLTEXT INDEX idx ON opening_lines(opening_line); +CREATE FULLTEXT INDEX ft_idx1 ON opening_lines(title); +INSERT INTO opening_lines(opening_line,author,title) VALUES +('Call me Ishmael.','Herman Melville','Moby Dick'), +('A screaming comes across the sky.','Thomas Pynchon','Gravity\'s Rainbow'), + ('I am an invisible man.','Ralph Ellison','Invisible Man'), + ('Where now? Who now? When now?','Samuel Beckett','The Unnamable'), + ('It was love at first sight.','Joseph Heller','Catch-22'), + ('All this happened, more or less.','Kurt Vonnegut','Slaughterhouse-Five'), + ('Mrs. Dalloway said she would buy the flowers herself.','Virginia Woolf','Mrs. Dalloway'), + ('It was a pleasure to burn.','Ray Bradbury','Fahrenheit 451'); +SET GLOBAL innodb_ft_aux_table='test/opening_lines'; +SELECT * FROM information_schema.innodb_ft_config; +KEY VALUE +optimize_checkpoint_limit 180 +synced_doc_id 0 +stopword_table_name +use_stopword 1 +SELECT * FROM opening_lines WHERE MATCH(opening_line) AGAINST('Ishmael'); +id opening_line author title +1 Call me Ishmael. Herman Melville Moby Dick +SELECT * FROM opening_lines WHERE MATCH(opening_line) AGAINST('invisible'); +id opening_line author title +3 I am an invisible man. Ralph Ellison Invisible Man +SELECT * FROM opening_lines; +id opening_line author title +1 Call me Ishmael. Herman Melville Moby Dick +2 A screaming comes across the sky. Thomas Pynchon Gravity's Rainbow +3 I am an invisible man. Ralph Ellison Invisible Man +4 Where now? Who now? When now? Samuel Beckett The Unnamable +5 It was love at first sight. Joseph Heller Catch-22 +6 All this happened, more or less. Kurt Vonnegut Slaughterhouse-Five +7 Mrs. Dalloway said she would buy the flowers herself. Virginia Woolf Mrs. Dalloway +8 It was a pleasure to burn. Ray Bradbury Fahrenheit 451 +SET GLOBAL innodb_optimize_fulltext_only=ON; +SET DEBUG_SYNC='fts_crash_before_commit_sync SIGNAL hung WAIT_FOR ever'; +OPTIMIZE TABLE opening_lines; +connect con1,localhost,root,,; +SET DEBUG_SYNC='now WAIT_FOR hung'; +# restart +SELECT * FROM opening_lines WHERE MATCH(opening_line) AGAINST('Ishmael'); +id opening_line author title +1 Call me Ishmael. Herman Melville Moby Dick +SELECT * FROM opening_lines WHERE MATCH(opening_line) AGAINST('invisible'); +id opening_line author title +3 I am an invisible man. Ralph Ellison Invisible Man +SELECT * FROM opening_lines; +id opening_line author title +1 Call me Ishmael. Herman Melville Moby Dick +2 A screaming comes across the sky. Thomas Pynchon Gravity's Rainbow +3 I am an invisible man. Ralph Ellison Invisible Man +4 Where now? Who now? When now? Samuel Beckett The Unnamable +5 It was love at first sight. Joseph Heller Catch-22 +6 All this happened, more or less. Kurt Vonnegut Slaughterhouse-Five +7 Mrs. Dalloway said she would buy the flowers herself. Virginia Woolf Mrs. Dalloway +8 It was a pleasure to burn. Ray Bradbury Fahrenheit 451 +DROP TABLE opening_lines; diff --git a/mysql-test/suite/innodb_fts/t/fts_sync_commit_resiliency.opt b/mysql-test/suite/innodb_fts/t/fts_sync_commit_resiliency.opt new file mode 100644 index 00000000000..9e0e66f6620 --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/fts_sync_commit_resiliency.opt @@ -0,0 +1 @@ +--innodb_ft_config diff --git a/mysql-test/suite/innodb_fts/t/fts_sync_commit_resiliency.test b/mysql-test/suite/innodb_fts/t/fts_sync_commit_resiliency.test new file mode 100644 index 00000000000..357d001f6e6 --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/fts_sync_commit_resiliency.test @@ -0,0 +1,47 @@ +# Test database resiliency against scenario where the server crashes +# right before fts_sync_commit commits its transaction +source include/have_innodb.inc; +source include/have_debug.inc; +source include/not_embedded.inc; +source include/have_debug_sync.inc; + +CREATE TABLE opening_lines ( + id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, + opening_line TEXT(500), + author VARCHAR(200), + title VARCHAR(200) + ) ENGINE=InnoDB; + +CREATE FULLTEXT INDEX idx ON opening_lines(opening_line); +CREATE FULLTEXT INDEX ft_idx1 ON opening_lines(title); + +INSERT INTO opening_lines(opening_line,author,title) VALUES + ('Call me Ishmael.','Herman Melville','Moby Dick'), + ('A screaming comes across the sky.','Thomas Pynchon','Gravity\'s Rainbow'), + ('I am an invisible man.','Ralph Ellison','Invisible Man'), + ('Where now? Who now? When now?','Samuel Beckett','The Unnamable'), + ('It was love at first sight.','Joseph Heller','Catch-22'), + ('All this happened, more or less.','Kurt Vonnegut','Slaughterhouse-Five'), + ('Mrs. Dalloway said she would buy the flowers herself.','Virginia Woolf','Mrs. Dalloway'), + ('It was a pleasure to burn.','Ray Bradbury','Fahrenheit 451'); + +SET GLOBAL innodb_ft_aux_table='test/opening_lines'; +SELECT * FROM information_schema.innodb_ft_config; + +SELECT * FROM opening_lines WHERE MATCH(opening_line) AGAINST('Ishmael'); +SELECT * FROM opening_lines WHERE MATCH(opening_line) AGAINST('invisible'); +SELECT * FROM opening_lines; + +SET GLOBAL innodb_optimize_fulltext_only=ON; +SET DEBUG_SYNC='fts_crash_before_commit_sync SIGNAL hung WAIT_FOR ever'; +send OPTIMIZE TABLE opening_lines; + +connect(con1,localhost,root,,); +SET DEBUG_SYNC='now WAIT_FOR hung'; +let $shutdown_timeout=0; +--source include/restart_mysqld.inc + +SELECT * FROM opening_lines WHERE MATCH(opening_line) AGAINST('Ishmael'); +SELECT * FROM opening_lines WHERE MATCH(opening_line) AGAINST('invisible'); +SELECT * FROM opening_lines; +DROP TABLE opening_lines; diff --git a/mysql-test/suite/maria/range.result b/mysql-test/suite/maria/range.result new file mode 100644 index 00000000000..49b8dc0fdc0 --- /dev/null +++ b/mysql-test/suite/maria/range.result @@ -0,0 +1,6 @@ +# +# MDEV-22935 Erroneous Aria Index / Optimizer behaviour +# +create table t1 (a char(255), b datetime, primary key(a,b)) engine=aria transactional=0 pack_keys=0; +insert into t1 select concat("hello world hello world", truncate(seq/100,0)),from_unixtime(seq+1) from seq_1_to_20000; +drop table t1; diff --git a/mysql-test/suite/maria/range.test b/mysql-test/suite/maria/range.test new file mode 100644 index 00000000000..00a74ad30c4 --- /dev/null +++ b/mysql-test/suite/maria/range.test @@ -0,0 +1,22 @@ +--source include/have_sequence.inc + +--echo # +--echo # MDEV-22935 Erroneous Aria Index / Optimizer behaviour +--echo # + +create table t1 (a char(255), b datetime, primary key(a,b)) engine=aria transactional=0 pack_keys=0; +insert into t1 select concat("hello world hello world", truncate(seq/100,0)),from_unixtime(seq+1) from seq_1_to_20000; + +let $i= 200; +--disable_query_log +while ($i) +{ + let $tmp= `select count(*) from t1 where a="hello world hello world$i" and b <= from_unixtime($i*100+1)`; + if (`SELECT $tmp != 1`) + { + --echo "Found $tmp rows, expected 1, for value $i" + } + dec $i; +} +--enable_query_log +drop table t1; diff --git a/mysql-test/suite/mariabackup/backup_grants.result b/mysql-test/suite/mariabackup/backup_grants.result index 3407d288264..c268d4fb19d 100644 --- a/mysql-test/suite/mariabackup/backup_grants.result +++ b/mysql-test/suite/mariabackup/backup_grants.result @@ -1,13 +1,17 @@ CREATE user backup@localhost IDENTIFIED BY 'xyz'; +NOT FOUND /missing required privilege/ in backup.log FOUND 1 /missing required privilege RELOAD/ in backup.log FOUND 1 /missing required privilege PROCESS/ in backup.log FOUND 1 /GRANT USAGE ON/ in backup.log GRANT RELOAD, PROCESS on *.* to backup@localhost; -FOUND 1 /missing required privilege REPLICA MONITOR/ in backup.log +NOT FOUND /missing required privilege/ in backup.log +FOUND 1 /missing required privilege SLAVE MONITOR/ in backup.log GRANT REPLICA MONITOR ON *.* TO backup@localhost; +NOT FOUND /missing required privilege/ in backup.log REVOKE REPLICA MONITOR ON *.* FROM backup@localhost; FOUND 1 /missing required privilege REPLICATION SLAVE ADMIN/ in backup.log -FOUND 1 /missing required privilege REPLICA MONITOR/ in backup.log +FOUND 1 /missing required privilege SLAVE MONITOR/ in backup.log GRANT REPLICATION SLAVE ADMIN ON *.* TO backup@localhost; GRANT REPLICA MONITOR ON *.* TO backup@localhost; +NOT FOUND /missing required privilege/ in backup.log DROP USER backup@localhost; diff --git a/mysql-test/suite/mariabackup/backup_grants.test b/mysql-test/suite/mariabackup/backup_grants.test index a90b4678d44..1e1d6a34f3d 100644 --- a/mysql-test/suite/mariabackup/backup_grants.test +++ b/mysql-test/suite/mariabackup/backup_grants.test @@ -1,10 +1,14 @@ let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; CREATE user backup@localhost IDENTIFIED BY 'xyz'; +let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/backup.log; # backup possible for unprivileges user, with --no-lock --disable_result_log -exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 -ubackup -pxyz --no-lock --target-dir=$targetdir; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 -ubackup -pxyz --no-lock --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log 2>&1; --enable_result_log + +--let SEARCH_PATTERN= missing required privilege +--source include/search_pattern_in_file.inc rmdir $targetdir; # backup fails without --no-lock, because of FTWRL @@ -13,7 +17,6 @@ error 1; exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 -ubackup -pxyz --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log 2>&1; --enable_result_log -let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/backup.log; --let SEARCH_PATTERN= missing required privilege RELOAD --source include/search_pattern_in_file.inc --let SEARCH_PATTERN= missing required privilege PROCESS @@ -23,25 +26,29 @@ let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/backup.log; # backup succeeds with RELOAD privilege GRANT RELOAD, PROCESS on *.* to backup@localhost; --disable_result_log -exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --user=backup --password=xyz --target-dir=$targetdir; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --user=backup --password=xyz --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log 2>&1; --enable_result_log +--let SEARCH_PATTERN= missing required privilege +--source include/search_pattern_in_file.inc rmdir $targetdir; # MDEV-23607 Warning: missing required privilege REPLICATION CLIENT -# --slave-info and galera info require REPLICA MONITOR +# --slave-info and --galera-info require REPLICA MONITOR --disable_result_log error 1; exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --user=backup --password=xyz --slave-info --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log 2>&1; --enable_result_log rmdir $targetdir; ---let SEARCH_PATTERN= missing required privilege REPLICA MONITOR +--let SEARCH_PATTERN= missing required privilege SLAVE MONITOR --source include/search_pattern_in_file.inc GRANT REPLICA MONITOR ON *.* TO backup@localhost; --disable_result_log -exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --user backup --password xyz --slave-info --target-dir=$targetdir; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --user backup --password xyz --slave-info --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log 2>&1; --enable_result_log +--let SEARCH_PATTERN= missing required privilege +--source include/search_pattern_in_file.inc rmdir $targetdir; REVOKE REPLICA MONITOR ON *.* FROM backup@localhost; @@ -54,14 +61,16 @@ rmdir $targetdir; --let SEARCH_PATTERN= missing required privilege REPLICATION SLAVE ADMIN --source include/search_pattern_in_file.inc ---let SEARCH_PATTERN= missing required privilege REPLICA MONITOR +--let SEARCH_PATTERN= missing required privilege SLAVE MONITOR --source include/search_pattern_in_file.inc GRANT REPLICATION SLAVE ADMIN ON *.* TO backup@localhost; GRANT REPLICA MONITOR ON *.* TO backup@localhost; --disable_result_log -exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup -pxyz --safe-slave-backup --target-dir=$targetdir; +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup -ubackup -pxyz --safe-slave-backup --target-dir=$targetdir > $MYSQLTEST_VARDIR/tmp/backup.log 2>&1; --enable_result_log +--let SEARCH_PATTERN= missing required privilege +--source include/search_pattern_in_file.inc rmdir $targetdir; DROP USER backup@localhost; diff --git a/mysql-test/suite/parts/r/mdev_24610.result b/mysql-test/suite/parts/r/mdev_24610.result new file mode 100644 index 00000000000..6b49b059993 --- /dev/null +++ b/mysql-test/suite/parts/r/mdev_24610.result @@ -0,0 +1,24 @@ +CREATE TABLE t (c BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=MEMORY PARTITION BY KEY(); +INSERT INTO t VALUES (18446744073709551615); +select * from t; +c +18446744073709551615 +drop table t; +CREATE TABLE t (c BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=MEMORY; +INSERT INTO t VALUES (18446744073709551615); +ALTER TABLE t PARTITION BY KEY(); +INSERT INTO t VALUES (1); +select * from t; +c +18446744073709551615 +1 +drop table t; +CREATE TABLE t (c BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=MEMORY; +INSERT INTO t VALUES (18446744073709551615); +ALTER TABLE t PARTITION BY KEY(); +INSERT INTO t VALUES (NULL); +ERROR HY000: Failed to read auto-increment value from storage engine +select * from t; +c +18446744073709551615 +drop table t; diff --git a/mysql-test/suite/parts/t/mdev_24610.test b/mysql-test/suite/parts/t/mdev_24610.test new file mode 100644 index 00000000000..df3ce9fdf0b --- /dev/null +++ b/mysql-test/suite/parts/t/mdev_24610.test @@ -0,0 +1,22 @@ +--source include/have_innodb.inc +--source include/have_partition.inc + +CREATE TABLE t (c BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=MEMORY PARTITION BY KEY(); +INSERT INTO t VALUES (18446744073709551615); +select * from t; +drop table t; + +CREATE TABLE t (c BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=MEMORY; +INSERT INTO t VALUES (18446744073709551615); +ALTER TABLE t PARTITION BY KEY(); +INSERT INTO t VALUES (1); +select * from t; +drop table t; + +CREATE TABLE t (c BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=MEMORY; +INSERT INTO t VALUES (18446744073709551615); +ALTER TABLE t PARTITION BY KEY(); +--error ER_AUTOINC_READ_FAILED +INSERT INTO t VALUES (NULL); +select * from t; +drop table t; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.test b/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.test index c8870e47e00..d3523a149ef 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_no_missed_ack_after_add_slave.test @@ -70,6 +70,10 @@ if (`SELECT $slave1_sent_ack`) --connection server_3 --echo # Verifying server_3 did send ACK +--let $status_var= Rpl_semi_sync_slave_send_ack +--let $status_var_comparsion= > +--let $status_var_value= 0 +--source include/wait_for_status_var.inc --let $slave2_sent_ack= query_get_value(SHOW STATUS LIKE 'rpl_semi_sync_slave_send_ack', Value, 1) if (`SELECT NOT $slave2_sent_ack`) { diff --git a/mysql-test/suite/sql_sequence/mysqldump.result b/mysql-test/suite/sql_sequence/mysqldump.result index 7282804340c..428a38285aa 100644 --- a/mysql-test/suite/sql_sequence/mysqldump.result +++ b/mysql-test/suite/sql_sequence/mysqldump.result @@ -5,9 +5,9 @@ CREATE SEQUENCE x1 engine=innodb; # dump whole database /*!999999\- enable the sandbox mode */ CREATE SEQUENCE `a1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=Aria; -SELECT SETVAL(`a1`, 1, 0); +DO SETVAL(`a1`, 1, 0); CREATE SEQUENCE `x1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; -SELECT SETVAL(`x1`, 1, 0); +DO SETVAL(`x1`, 1, 0); /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( @@ -21,9 +21,9 @@ INSERT INTO `t1` VALUES # dump by tables order 1 /*!999999\- enable the sandbox mode */ CREATE SEQUENCE `a1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=Aria; -SELECT SETVAL(`a1`, 1, 0); +DO SETVAL(`a1`, 1, 0); CREATE SEQUENCE `x1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; -SELECT SETVAL(`x1`, 1, 0); +DO SETVAL(`x1`, 1, 0); /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( @@ -37,9 +37,9 @@ INSERT INTO `t1` VALUES # dump by tables order 2 /*!999999\- enable the sandbox mode */ CREATE SEQUENCE `a1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=Aria; -SELECT SETVAL(`a1`, 1, 0); +DO SETVAL(`a1`, 1, 0); CREATE SEQUENCE `x1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; -SELECT SETVAL(`x1`, 1, 0); +DO SETVAL(`x1`, 1, 0); /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( @@ -65,9 +65,9 @@ INSERT INTO `t1` VALUES # dump by tables only sequences /*!999999\- enable the sandbox mode */ CREATE SEQUENCE `a1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=Aria; -SELECT SETVAL(`a1`, 1, 0); +DO SETVAL(`a1`, 1, 0); CREATE SEQUENCE `x1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB; -SELECT SETVAL(`x1`, 1, 0); +DO SETVAL(`x1`, 1, 0); # end of dumps DROP TABLE a1,t1,x1; set default_storage_engine=InnoDB; diff --git a/mysys/crc32/crc32c.cc b/mysys/crc32/crc32c.cc index 32a45478e94..6de7af70db7 100644 --- a/mysys/crc32/crc32c.cc +++ b/mysys/crc32/crc32c.cc @@ -526,7 +526,7 @@ extern "C" const char *my_crc32c_implementation() } // namespace crc32c } // namespace mysys_namespace -extern "C" unsigned my_crc32c(unsigned int crc, const char *buf, size_t size) +extern "C" uint32 my_crc32c(uint32 crc, const void *buf, size_t size) { return mysys_namespace::crc32c::ChosenExtend(crc,buf, size); } diff --git a/mysys/crc32/crc32c_amd64.cc b/mysys/crc32/crc32c_amd64.cc index 147c0ccaba6..6706ed0fadc 100644 --- a/mysys/crc32/crc32c_amd64.cc +++ b/mysys/crc32/crc32c_amd64.cc @@ -184,9 +184,9 @@ static inline uint64_t CombineCRC( // Compute CRC-32C using the Intel hardware instruction. extern "C" USE_PCLMUL -uint32_t crc32c_3way(uint32_t crc, const char *buf, size_t len) +uint32_t crc32c_3way(uint32_t crc, const void *buf, size_t len) { - const unsigned char* next = (const unsigned char*)buf; + const unsigned char* next = static_cast(buf); uint64_t count; uint64_t crc0, crc1, crc2; crc0 = crc ^ 0xffffffffu; diff --git a/mysys/crc32/crc32c_x86.cc b/mysys/crc32/crc32c_x86.cc index 02dbf2920eb..6d9169f9384 100644 --- a/mysys/crc32/crc32c_x86.cc +++ b/mysys/crc32/crc32c_x86.cc @@ -24,7 +24,11 @@ # endif #else # include -# if __GNUC__ >= 11 || (defined __clang_major__ && __clang_major__ >= 8) +# ifdef __APPLE__ /* AVX512 states are not enabled in XCR0 */ +# elif __GNUC__ >= 14 || (defined __clang_major__ && __clang_major__ >= 18) +# define TARGET "pclmul,evex512,avx512f,avx512dq,avx512bw,avx512vl,vpclmulqdq" +# define USE_VPCLMULQDQ __attribute__((target(TARGET))) +# elif __GNUC__ >= 11 || (defined __clang_major__ && __clang_major__ >= 8) # define TARGET "pclmul,avx512f,avx512dq,avx512bw,avx512vl,vpclmulqdq" # define USE_VPCLMULQDQ __attribute__((target(TARGET))) # endif @@ -50,9 +54,9 @@ static uint32_t cpuid_ecx() #endif } -typedef unsigned (*my_crc32_t)(unsigned, const void *, size_t); -extern "C" unsigned int crc32_pclmul(unsigned int, const void *, size_t); -extern "C" unsigned int crc32c_3way(unsigned int, const void *, size_t); +typedef uint32_t (*my_crc32_t)(uint32_t, const void *, size_t); +extern "C" uint32_t crc32_pclmul(uint32_t, const void *, size_t); +extern "C" uint32_t crc32c_3way(uint32_t, const void *, size_t); #ifdef USE_VPCLMULQDQ # include @@ -173,19 +177,11 @@ static inline __m512i combine512(__m512i a, __m512i tab, __m512i b) # define and128(a, b) _mm_and_si128(a, b) template USE_VPCLMULQDQ -/** Pick a 128-bit component of a 512-bit vector */ +/** Pick and zero-extend 128 bits of a 512-bit vector (vextracti32x4) */ static inline __m512i extract512_128(__m512i a) { static_assert(bits <= 3, "usage"); -# if defined __GNUC__ && __GNUC__ >= 11 - /* While technically incorrect, this would seem to translate into a - vextracti32x4 instruction, which actually outputs a ZMM register - (anything above the XMM range is cleared). */ - return _mm512_castsi128_si512(_mm512_extracti64x2_epi64(a, bits)); -# else - /* On clang, this is needed in order to get a correct result. */ - return _mm512_maskz_shuffle_i64x2(3, a, a, bits); -# endif + return _mm512_zextsi128_si512(_mm512_extracti64x2_epi64(a, bits)); } alignas(16) static const uint64_t shuffle128[4] = { diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index 4dc41645530..8726349daa4 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -242,8 +242,10 @@ void lf_pinbox_put_pins(LF_PINS *pins) return; } -static int ptr_cmp(void **a, void **b) +static int ptr_cmp(const void *pa, const void *pb) { + const void *const*a= pa; + const void *const*b= pb; return *a < *b ? -1 : *a == *b ? 0 : 1; } @@ -283,8 +285,10 @@ struct st_harvester { callback forlf_dynarray_iterate: scan all pins of all threads and accumulate all pins */ -static int harvest_pins(LF_PINS *el, struct st_harvester *hv) +static int harvest_pins(void *e, void *h) { + LF_PINS *el= e; + struct st_harvester *hv= h; int i; LF_PINS *el_end= el+MY_MIN(hv->npins, LF_DYNARRAY_LEVEL_LENGTH); for (; el < el_end; el++) @@ -310,8 +314,9 @@ static int harvest_pins(LF_PINS *el, struct st_harvester *hv) callback forlf_dynarray_iterate: scan all pins of all threads and see if addr is present there */ -static int match_pins(LF_PINS *el, void *addr) +static int match_pins(void *e, void *addr) { + LF_PINS *el= e; int i; LF_PINS *el_end= el+LF_DYNARRAY_LEVEL_LENGTH; for (; el < el_end; el++) @@ -352,13 +357,12 @@ static void lf_pinbox_real_free(LF_PINS *pins) hv.granary= addr; hv.npins= npins; /* scan the dynarray and accumulate all pinned addresses */ - lf_dynarray_iterate(&pinbox->pinarray, - (lf_dynarray_func)harvest_pins, &hv); + lf_dynarray_iterate(&pinbox->pinarray, harvest_pins, &hv); npins= (int)(hv.granary-addr); /* and sort them */ if (npins) - qsort(addr, npins, sizeof(void *), (qsort_cmp)ptr_cmp); + qsort(addr, npins, sizeof(void *), ptr_cmp); } } #endif @@ -387,8 +391,7 @@ static void lf_pinbox_real_free(LF_PINS *pins) } else /* no alloca - no cookie. linear search here */ { - if (lf_dynarray_iterate(&pinbox->pinarray, - (lf_dynarray_func)match_pins, cur)) + if (lf_dynarray_iterate(&pinbox->pinarray, match_pins, cur)) goto found; } } @@ -416,10 +419,11 @@ found: 'first' and 'last' are the ends of the linked list of nodes: first->el->el->....->el->last. Use first==last to free only one element. */ -static void alloc_free(uchar *first, - uchar volatile *last, - LF_ALLOCATOR *allocator) +static void alloc_free(void *f, void *l, void *alloc) { + uchar *first= f; + uchar volatile *last= l; + LF_ALLOCATOR *allocator= alloc; /* we need a union here to access type-punned pointer reliably. otherwise gcc -fstrict-aliasing will not see 'tmp' changed in the loop @@ -448,8 +452,7 @@ static void alloc_free(uchar *first, */ void lf_alloc_init(LF_ALLOCATOR *allocator, uint size, uint free_ptr_offset) { - lf_pinbox_init(&allocator->pinbox, free_ptr_offset, - (lf_pinbox_free_func *)alloc_free, allocator); + lf_pinbox_init(&allocator->pinbox, free_ptr_offset, alloc_free, allocator); allocator->top= 0; allocator->mallocs= 0; allocator->element_size= size; diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index 35060b17665..60aaffba227 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -3848,13 +3848,13 @@ my_bool dynstr_append_json_quoted(DYNAMIC_STRING *str, register char c= append[i]; if (unlikely(((uchar)c) <= 0x1F)) { - if (lim < 5) + if (lim < 6) { if (dynstr_realloc(str, additional)) return TRUE; lim+= additional; } - lim-= 5; + lim -= 6; str->str[str->length++]= '\\'; str->str[str->length++]= 'u'; str->str[str->length++]= '0'; @@ -3865,17 +3865,18 @@ my_bool dynstr_append_json_quoted(DYNAMIC_STRING *str, } else { + if (lim < 2) + { + if (dynstr_realloc(str, additional)) + return TRUE; + lim += additional; + } if (c == '"' || c == '\\') { - if (!lim) - { - if (dynstr_realloc(str, additional)) - return TRUE; - lim= additional; - } lim--; str->str[str->length++]= '\\'; } + lim--; str->str[str->length++]= c; } } diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index 8714a7a6003..550bc83e2ab 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -62,14 +62,10 @@ my_bool safe_mutex_deadlock_detector= 1; /* On by default */ static struct st_safe_mutex_create_info_t *safe_mutex_create_root= NULL; #endif -static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex, - safe_mutex_deadlock_t *locked_mutex); -static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex, - safe_mutex_t *current_mutex); -static my_bool remove_from_locked_mutex(safe_mutex_t *mp, - safe_mutex_t *delete_mutex); -static my_bool remove_from_used_mutex(safe_mutex_deadlock_t *locked_mutex, - safe_mutex_t *mutex); +static my_bool add_used_to_locked_mutex(void *used, void *locked); +static my_bool add_to_locked_mutex(void *locked, void *current); +static my_bool remove_from_locked_mutex(void *m, void* remove); +static my_bool remove_from_used_mutex(void *locked, void *m); static void print_deadlock_warning(safe_mutex_t *new_mutex, safe_mutex_t *conflicting_mutex); #endif @@ -375,8 +371,7 @@ int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file, are now locking (C) in B->C, then we would add C into B->locked_mutex and A->locked_mutex */ - my_hash_iterate(mutex_root->used_mutex, - (my_hash_walk_action) add_used_to_locked_mutex, + my_hash_iterate(mutex_root->used_mutex, add_used_to_locked_mutex, deadlock); /* @@ -656,12 +651,8 @@ void safe_mutex_free_deadlock_data(safe_mutex_t *mp) if (!(mp->create_flags & MYF_NO_DEADLOCK_DETECTION) && mp->used_mutex != NULL) { pthread_mutex_lock(&THR_LOCK_mutex); - my_hash_iterate(mp->used_mutex, - (my_hash_walk_action) remove_from_locked_mutex, - mp); - my_hash_iterate(mp->locked_mutex, - (my_hash_walk_action) remove_from_used_mutex, - mp); + my_hash_iterate(mp->used_mutex, remove_from_locked_mutex, mp); + my_hash_iterate(mp->locked_mutex, remove_from_used_mutex, mp); pthread_mutex_unlock(&THR_LOCK_mutex); my_hash_free(mp->used_mutex); @@ -712,15 +703,15 @@ void safe_mutex_end(FILE *file __attribute__((unused))) #endif /* SAFE_MUTEX_DETECT_DESTROY */ } -static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex, - safe_mutex_deadlock_t *locked_mutex) +static my_bool add_used_to_locked_mutex(void *used, void *locked) { + safe_mutex_t *used_mutex= used; + safe_mutex_deadlock_t *locked_mutex= locked; /* Add mutex to all parent of the current mutex */ if (!locked_mutex->warning_only) { (void) my_hash_iterate(locked_mutex->mutex->locked_mutex, - (my_hash_walk_action) add_to_locked_mutex, - used_mutex); + add_to_locked_mutex, used_mutex); /* mark that locked_mutex is locked after used_mutex */ (void) add_to_locked_mutex(locked_mutex, used_mutex); } @@ -732,12 +723,13 @@ static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex, register that locked_mutex was locked after current_mutex */ -static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex, - safe_mutex_t *current_mutex) +static my_bool add_to_locked_mutex(void *locked, void *current) { + safe_mutex_deadlock_t *locked_mutex= locked; + safe_mutex_t *current_mutex= current; DBUG_ENTER("add_to_locked_mutex"); - DBUG_PRINT("info", ("inserting 0x%lx into 0x%lx (id: %lu -> %lu)", - (ulong) locked_mutex, (long) current_mutex, + DBUG_PRINT("info", ("inserting %p into %p (id: %lu -> %lu)", + locked_mutex, current_mutex, locked_mutex->id, current_mutex->id)); if (my_hash_insert(current_mutex->locked_mutex, (uchar*) locked_mutex)) { @@ -765,13 +757,14 @@ static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex, When counter goes to 0, we delete the safe_mutex_deadlock_t entry. */ -static my_bool remove_from_locked_mutex(safe_mutex_t *mp, - safe_mutex_t *delete_mutex) +static my_bool remove_from_locked_mutex(void *m, void *remove) { + safe_mutex_t *mp= m; + safe_mutex_t *delete_mutex= remove; safe_mutex_deadlock_t *found; DBUG_ENTER("remove_from_locked_mutex"); - DBUG_PRINT("enter", ("delete_mutex: 0x%lx mutex: 0x%lx (id: %lu <- %lu)", - (ulong) delete_mutex, (ulong) mp, + DBUG_PRINT("enter", ("delete_mutex: %p mutex: %p (id: %lu <- %lu)", + delete_mutex, mp, delete_mutex->id, mp->id)); found= (safe_mutex_deadlock_t *) my_hash_search(mp->locked_mutex, @@ -790,12 +783,13 @@ static my_bool remove_from_locked_mutex(safe_mutex_t *mp, DBUG_RETURN(0); } -static my_bool remove_from_used_mutex(safe_mutex_deadlock_t *locked_mutex, - safe_mutex_t *mutex) +static my_bool remove_from_used_mutex(void *locked, void *m) { + safe_mutex_deadlock_t *locked_mutex= locked; + safe_mutex_t *mutex= m; DBUG_ENTER("remove_from_used_mutex"); - DBUG_PRINT("enter", ("delete_mutex: 0x%lx mutex: 0x%lx (id: %lu <- %lu)", - (ulong) mutex, (ulong) locked_mutex, + DBUG_PRINT("enter", ("delete_mutex: %p mutex: %p (id: %lu <- %lu)", + mutex, locked_mutex, mutex->id, locked_mutex->id)); if (my_hash_delete(locked_mutex->mutex->used_mutex, (uchar*) mutex)) { diff --git a/mysys/waiting_threads.c b/mysys/waiting_threads.c index a03f8da3009..7c20c2eec5d 100644 --- a/mysys/waiting_threads.c +++ b/mysys/waiting_threads.c @@ -424,8 +424,10 @@ static void wt_resource_destroy(uchar *arg) It's called from lf_hash when an element is inserted. */ static void wt_resource_init(LF_HASH *hash __attribute__((unused)), - WT_RESOURCE *rc, WT_RESOURCE_ID *id) + void *resource, const void *ident) { + WT_RESOURCE *rc= resource; + const WT_RESOURCE_ID *id= ident; DBUG_ENTER("wt_resource_init"); rc->id= *id; rc->waiter_count= 0; diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 1ba63b7759f..b7366f032f0 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -38,6 +38,7 @@ force=0 in_rpm=0 ip_only=0 cross_bootstrap=0 +do_resolve=0 auth_root_authentication_method=socket auth_root_socket_user="" skip_test_db=0 @@ -336,6 +337,11 @@ parse_arguments PICK-ARGS-FROM-ARGV "$@" rel_mysqld="$dirname0/@INSTALL_SBINDIR@/mariadbd" +if test "$cross_bootstrap" -eq 0 -a "$in_rpm" -eq 0 -a "$force" -eq 0 +then + do_resolve=1 +fi + # Configure paths to support files if test -n "$srcdir" then @@ -428,7 +434,7 @@ fi hostname=`@HOSTNAME@` # Check if hostname is valid -if test "$cross_bootstrap" -eq 0 -a "$in_rpm" -eq 0 -a "$force" -eq 0 +if test "$do_resolve" -eq 1 then resolved=`"$resolveip" $hostname 2>&1` if test $? -ne 0 @@ -454,7 +460,7 @@ then fi fi -if test "$ip_only" -eq 1 +if test "$do_resolve" -eq 1 -a "$ip_only" -eq 1 then hostname=`echo "$resolved" | while read a; do echo ${a##* }; done` fi diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index fec659d0179..aee96c5b30b 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -714,7 +714,7 @@ cleanup_at_exit() fi # Final cleanup - pgid=$(ps -o pgid= $$ 2>/dev/null | grep -o -E '[0-9]+' || :) + pgid=$(ps -o 'pgid=' $$ 2>/dev/null | grep -o -E '[0-9]+' || :) # This means no setsid done in mysqld. # We don't want to kill mysqld here otherwise. @@ -1086,17 +1086,19 @@ if [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then tmpdir=$(parse_cnf "$encgroups" 'tmpdir') if [ -z "$tmpdir" ]; then xtmpdir="$(mktemp -d)" + itmpdir="$(mktemp -d)" elif [ "$OS" = 'Linux' ]; then - xtmpdir=$(mktemp '-d' "--tmpdir=$tmpdir") + xtmpdir=$(mktemp -d "--tmpdir=$tmpdir") + itmpdir=$(mktemp -d "--tmpdir=$tmpdir") else - xtmpdir=$(TMPDIR="$tmpdir"; mktemp '-d') + xtmpdir=$(TMPDIR="$tmpdir"; mktemp -d) + itmpdir=$(TMPDIR="$tmpdir"; mktemp -d) fi wsrep_log_info "Using '$xtmpdir' as mariadb-backup temporary directory" tmpopts=" --tmpdir='$xtmpdir'" - itmpdir="$(mktemp -d)" - wsrep_log_info "Using '$itmpdir' as mariadb-abackup working directory" + wsrep_log_info "Using '$itmpdir' as mariadb-backup working directory" usrst=0 if [ -n "$WSREP_SST_OPT_USER" ]; then diff --git a/sql-common/client.c b/sql-common/client.c index 9b88855f1a5..6d030ce0a17 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -21,7 +21,7 @@ The differences for the two cases are: - Things that only works for the client: - - Trying to automaticly determinate user name if not supplied to + - Trying to automatically determinate user name if not supplied to mysql_real_connect() - Support for reading local file with LOAD DATA LOCAL - SHARED memory handling @@ -30,7 +30,7 @@ - Things that only works for the server - Alarm handling on connect - In all other cases, the code should be idential for the client and + In all other cases, the code should be identical for the client and server. */ @@ -1463,7 +1463,7 @@ mysql_init(MYSQL *mysql) mysql_reconnect()). This is a change: < 5.0.3 mysql->reconnect was set to 1 by default. How this change impacts existing apps: - - existing apps which relyed on the default will see a behaviour change; + - existing apps which relied on the default will see a behaviour change; they will have to set reconnect=1 after mysql_real_connect(). - existing apps which explicitly asked for reconnection (the only way they could do it was by setting mysql.reconnect to 1 after mysql_real_connect()) @@ -1894,7 +1894,7 @@ typedef struct { /* - Write 1-8 bytes of string length header infromation to dest depending on + Write 1-8 bytes of string length header information to dest depending on value of src_len, then copy src_len bytes from src to dest. @param dest Destination buffer of size src_len+8 @@ -2200,7 +2200,7 @@ static int send_client_reply_packet(MCPVIO_EXT *mpvio, } #endif /* HAVE_OPENSSL */ - DBUG_PRINT("info",("Server version = '%s' capabilites: %lu status: %u client_flag: %lu", + DBUG_PRINT("info",("Server version = '%s' capabilities: %lu status: %u client_flag: %lu", mysql->server_version, mysql->server_capabilities, mysql->server_status, mysql->client_flag)); @@ -2337,7 +2337,7 @@ static int client_mpvio_read_packet(struct st_plugin_vio *mpv, uchar **buf) to send data to the server. It transparently wraps the data into a change user or authentication - handshake packet, if neccessary. + handshake packet, if necessary. */ static int client_mpvio_write_packet(struct st_plugin_vio *mpv, const uchar *pkt, int pkt_len) @@ -3788,7 +3788,7 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) mysql->options.compress= 1; /* Remember for connect */ mysql->options.client_flag|= CLIENT_COMPRESS; break; - case MYSQL_OPT_NAMED_PIPE: /* This option is depricated */ + case MYSQL_OPT_NAMED_PIPE: /* This option is deprecated */ mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */ break; case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/ diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 96674723b34..eff39cd5eae 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -475,7 +475,7 @@ str_to_DDhhmmssff_internal(my_bool neg, const char *str, size_t length, DESCRIPTION - At least the following formats are recogniced (based on number of digits) + At least the following formats are recognized (based on number of digits) YYMMDD, YYYYMMDD, YYMMDDHHMMSS, YYYYMMDDHHMMSS YY-MM-DD, YYYY-MM-DD, YY-MM-DD HH.MM.SS YYYYMMDDTHHMMSS where T is a the character T (ISO8601) @@ -1223,7 +1223,7 @@ long calc_daynr(uint year,uint month,uint day) /* Convert time in MYSQL_TIME representation in system time zone to its - my_time_t form (number of seconds in UTC since begginning of Unix Epoch). + my_time_t form (number of seconds in UTC since beginning of Unix Epoch). SYNOPSIS my_system_gmt_sec() @@ -1291,7 +1291,7 @@ my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone, uint *error_code) two days earlier, and then add these days to the final value. The same trick is done for the values close to 0 in time_t - representation for platfroms with unsigned time_t (QNX). + representation for platforms with unsigned time_t (QNX). To be more verbose, here is a sample (extracted from the code below): (calc_daynr(2038, 1, 19) - (long) days_at_timestart)*86400L + 4*3600L @@ -1303,9 +1303,9 @@ my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone, uint *error_code) will give -3600. On some platforms, (E.g. on QNX) time_t is unsigned and localtime(-3600) - wil give us a date around 2106 year. Which is no good. + will give us a date around 2106 year. Which is no good. - Theoreticaly, there could be problems with the latter conversion: + Theoretically, there could be problems with the latter conversion: there are at least two timezones, which had time switches near 1 Jan of 1970 (because of political reasons). These are America/Hermosillo and America/Mazatlan time zones. They changed their offset on @@ -1335,7 +1335,7 @@ my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone, uint *error_code) else { /* - We can get 0 in time_t representaion only on 1969, 31 of Dec or on + We can get 0 in time_t representation only on 1969, 31 of Dec or on 1970, 1 of Jan. For both dates we use shift, which is added to t->day in order to step out a bit from the border. This is required for platforms, where time_t is unsigned. @@ -1430,9 +1430,9 @@ my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone, uint *error_code) First check will pass for platforms with signed time_t. instruction above (tmp+= shift*86400L) could exceed MAX_INT32 (== TIMESTAMP_MAX_VALUE) and overflow will happen. - So, tmp < TIMESTAMP_MIN_VALUE will be triggered. On platfroms + So, tmp < TIMESTAMP_MIN_VALUE will be triggered. On platforms with unsigned time_t tmp+= shift*86400L might result in a number, - larger then TIMESTAMP_MAX_VALUE, so another check will work. + larger than TIMESTAMP_MAX_VALUE, so another check will work. */ if (!IS_TIME_T_VALID_FOR_TIMESTAMP(tmp)) { @@ -1545,8 +1545,8 @@ static inline char* fmt_number2(uint8 val, char *out) - 0.225 sec (current) - 0.219 sec (array) - It demonstrated an additional 3% performance imrovement one these queries. - However, as the array size is too huge, we afraid that it will flush data + It demonstrated an additional 3% performance improvement one these queries. + However, as the array size is too huge, we are afraid that it will flush data from the CPU memory cache, which under real load may affect negatively. Let's keep using the fmt_number4() version with division and remainder diff --git a/sql/field.cc b/sql/field.cc index 9cf95ec59fb..5b9cf1b1995 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7608,11 +7608,11 @@ double Field_string::val_real(void) { DBUG_ASSERT(marked_for_read()); THD *thd= get_thd(); - return Converter_strntod_with_warn(get_thd(), + const LEX_CSTRING str= to_lex_cstring(); + return Converter_strntod_with_warn(thd, Warn_filter_string(thd, this), Field_string::charset(), - (const char *) ptr, - field_length).result(); + str.str, str.length).result(); } @@ -7620,10 +7620,10 @@ longlong Field_string::val_int(void) { DBUG_ASSERT(marked_for_read()); THD *thd= get_thd(); + const LEX_CSTRING str= to_lex_cstring(); return Converter_strntoll_with_warn(thd, Warn_filter_string(thd, this), Field_string::charset(), - (const char *) ptr, - field_length).result(); + str.str, str.length).result(); } @@ -7639,20 +7639,26 @@ sql_mode_t Field_string::can_handle_sql_mode_dependency_on_store() const } -String *Field_string::val_str(String *val_buffer __attribute__((unused)), - String *val_ptr) +LEX_CSTRING Field_string::to_lex_cstring() const { DBUG_ASSERT(marked_for_read()); /* See the comment for Field_long::store(long long) */ DBUG_ASSERT(!table || table->in_use == current_thd); - size_t length; - if (get_thd()->variables.sql_mode & - MODE_PAD_CHAR_TO_FULL_LENGTH) - length= field_charset()->charpos(ptr, ptr + field_length, - Field_string::char_length()); - else - length= field_charset()->lengthsp((const char*) ptr, field_length); - val_ptr->set((const char*) ptr, length, field_charset()); + if (get_thd()->variables.sql_mode & MODE_PAD_CHAR_TO_FULL_LENGTH) + return Lex_cstring((const char*) ptr, + field_charset()->charpos(ptr, ptr + field_length, + Field_string::char_length())); + return Lex_cstring((const char *) ptr, + field_charset()->lengthsp((const char*) ptr, field_length)); +} + + +String *Field_string::val_str(String *val_buffer __attribute__((unused)), + String *val_ptr) +{ + DBUG_ASSERT(marked_for_read()); + const LEX_CSTRING str= to_lex_cstring(); + val_ptr->set(str.str, str.length, field_charset()); return val_ptr; } @@ -7661,12 +7667,12 @@ my_decimal *Field_string::val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(marked_for_read()); THD *thd= get_thd(); + const LEX_CSTRING str= to_lex_cstring(); Converter_str2my_decimal_with_warn(thd, Warn_filter_string(thd, this), E_DEC_FATAL_ERROR & ~E_DEC_BAD_NUM, Field_string::charset(), - (const char *) ptr, - field_length, decimal_value); + str.str, str.length, decimal_value); return decimal_value; } diff --git a/sql/field.h b/sql/field.h index 39e0da61e6f..c1d120436e7 100644 --- a/sql/field.h +++ b/sql/field.h @@ -4068,6 +4068,7 @@ class Field_string final :public Field_longstr { field_length >= 4 && orig_table->s->frm_version < FRM_VER_TRUE_VARCHAR; } + LEX_CSTRING to_lex_cstring() const; public: bool can_alter_field_type; Field_string(uchar *ptr_arg, uint32 len_arg,uchar *null_ptr_arg, diff --git a/sql/gcalc_slicescan.cc b/sql/gcalc_slicescan.cc index f94c7190532..9af635eb5ab 100644 --- a/sql/gcalc_slicescan.cc +++ b/sql/gcalc_slicescan.cc @@ -144,7 +144,7 @@ static void GCALC_DBUG_PRINT_SLICE(const char *header, size_t nbuf; char buf[1024]; nbuf= strlen(header); - strcpy(buf, header); + safe_strcpy(buf, sizeof(buf), header); for (; slice; slice= slice->get_next()) { size_t lnbuf= nbuf; diff --git a/sql/ha_handler_stats.h b/sql/ha_handler_stats.h index 726ba6041dc..60ae5deedbe 100644 --- a/sql/ha_handler_stats.h +++ b/sql/ha_handler_stats.h @@ -26,9 +26,14 @@ public: ulonglong pages_accessed; /* Pages accessed from page cache */ ulonglong pages_updated; /* Pages changed in page cache */ ulonglong pages_read_count; /* Pages read from disk */ - ulonglong pages_read_time; /* Time reading pages, in microsec. */ + + /* Time spent reading pages, in timer_tracker_frequency() units */ + ulonglong pages_read_time; + ulonglong undo_records_read; - ulonglong engine_time; /* Time spent in engine in microsec */ + + /* Time spent in engine, in timer_tracker_frequency() units */ + ulonglong engine_time; uint active; /* <> 0 if status has to be updated */ #define first_stat pages_accessed #define last_stat engine_time diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 177f49fb926..98be21d67d3 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3973,7 +3973,8 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) m_part_info->part_expr->get_monotonicity_info(); else if (m_part_info->list_of_part_fields) m_part_func_monotonicity_info= MONOTONIC_STRICT_INCREASING; - info(HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_OPEN); + if ((error= info(HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_OPEN))) + goto err_handler; DBUG_RETURN(0); err_handler: diff --git a/sql/handler.cc b/sql/handler.cc index 18d67cb567a..d94a66f2afd 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -300,13 +300,20 @@ redo: } +/* + Resolve the storage engine by name. + + Succeed if the storage engine is found and initialised. Otherwise + fail if the sql mode contains NO_ENGINE_SUBSTITUTION. +*/ bool Storage_engine_name::resolve_storage_engine_with_error(THD *thd, handlerton **ha, bool tmp_table) { - if (plugin_ref plugin= ha_resolve_by_name(thd, &m_storage_engine_name, - tmp_table)) + plugin_ref plugin; + if ((plugin= ha_resolve_by_name(thd, &m_storage_engine_name, tmp_table)) && + (plugin_ref_to_int(plugin)->state == PLUGIN_IS_READY)) { *ha= plugin_hton(plugin); return false; @@ -4871,7 +4878,7 @@ void handler::print_error(int error, myf errflag) if (error < HA_ERR_FIRST && bas_ext()[0]) { char buff[FN_REFLEN]; - strxnmov(buff, sizeof(buff), + strxnmov(buff, sizeof(buff)-1, table_share->normalized_path.str, bas_ext()[0], NULL); my_error(textno, errflag, buff, error); } diff --git a/sql/hostname.cc b/sql/hostname.cc index d5f342b9216..0641528f98b 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -514,42 +514,48 @@ int ip_to_hostname(struct sockaddr_storage *ip_storage, DBUG_EXECUTE_IF("getnameinfo_error_noname", { - strcpy(hostname_buffer, ""); + safe_strcpy(hostname_buffer, sizeof(hostname_buffer), + ""); err_code= EAI_NONAME; } ); DBUG_EXECUTE_IF("getnameinfo_error_again", { - strcpy(hostname_buffer, ""); + safe_strcpy(hostname_buffer, sizeof(hostname_buffer), + ""); err_code= EAI_AGAIN; } ); DBUG_EXECUTE_IF("getnameinfo_fake_ipv4", { - strcpy(hostname_buffer, "santa.claus.ipv4.example.com"); + safe_strcpy(hostname_buffer, sizeof(hostname_buffer), + "santa.claus.ipv4.example.com"); err_code= 0; } ); DBUG_EXECUTE_IF("getnameinfo_fake_ipv6", { - strcpy(hostname_buffer, "santa.claus.ipv6.example.com"); + safe_strcpy(hostname_buffer, sizeof(hostname_buffer), + "santa.claus.ipv6.example.com"); err_code= 0; } ); DBUG_EXECUTE_IF("getnameinfo_format_ipv4", { - strcpy(hostname_buffer, "12.12.12.12"); + safe_strcpy(hostname_buffer, sizeof(hostname_buffer), + "12.12.12.12"); err_code= 0; } ); DBUG_EXECUTE_IF("getnameinfo_format_ipv6", { - strcpy(hostname_buffer, "12:DEAD:BEEF:0"); + safe_strcpy(hostname_buffer, sizeof(hostname_buffer), + "12:DEAD:BEEF:0"); err_code= 0; } ); diff --git a/sql/item_create.cc b/sql/item_create.cc index a347f49acee..a5cb8cfdd1e 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -6485,8 +6485,7 @@ const Native_func_registry func_array_oracle_overrides[] = { { STRING_WITH_LEN("REGEXP_REPLACE") }, BUILDER(Create_func_regexp_replace_oracle)}, { { STRING_WITH_LEN("RPAD") }, BUILDER(Create_func_rpad_oracle)}, - { { STRING_WITH_LEN("RTRIM") }, BUILDER(Create_func_rtrim_oracle)}, - { {0, 0}, NULL} + { { STRING_WITH_LEN("RTRIM") }, BUILDER(Create_func_rtrim_oracle)} }; Native_func_registry_array diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index ed07ad4ab26..88f971694e4 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -1144,11 +1144,18 @@ String *Item_func_json_extract::read_json(String *str, je= sav_je; } - for (int count= 0; count < count_path; count++) + if ((not_first_value && str->append(", ", 2))) + goto error; + while(count_path) { - if (str->append((const char *) value, v_len) || - str->append(", ", 2)) - goto error; /* Out of memory. */ + if (str->append((const char *) value, v_len)) + goto error; + count_path--; + if (count_path) + { + if (str->append(", ", 2)) + goto error; + } } not_first_value= 1; @@ -1170,11 +1177,6 @@ String *Item_func_json_extract::read_json(String *str, goto return_null; } - if (str->length()>2) - { - str->chop(); - str->chop(); - } if (possible_multiple_values && str->append(']')) goto error; /* Out of memory. */ diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 462a6d381a3..b69874ae339 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1544,6 +1544,12 @@ bool Item_func_sformat::fix_length_and_dec(THD *thd) */ namespace fmt { template <> struct formatter: formatter { + template + auto format(String c, FormatContext& ctx) const -> decltype(ctx.out()) { + string_view name = { c.ptr(), c.length() }; + return formatter::format(name, ctx); + }; + /* needed below function for libfmt-7.1.3 compatibility, (not 9.1.0+) */ template auto format(String c, FormatContext& ctx) -> decltype(ctx.out()) { string_view name = { c.ptr(), c.length() }; @@ -5920,7 +5926,7 @@ static NATSORT_ERR to_natsort_key(const String *in, String *out, { size_t n_digits= 0; size_t n_lead_zeros= 0; - size_t num_start; + size_t num_start= 0; size_t reserve_length= std::min( natsort_max_key_size(in->length()) + MAX_BIGINT_WIDTH + 2, max_key_size); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 275451ab271..82adc27769d 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -196,7 +196,11 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) } if (window_func_sum_expr_flag) + { + thd->lex->in_sum_func= in_sum_func; return false; + } + /* The value of max_arg_level is updated if an argument of the set function contains a column reference resolved against a subquery whose level is diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 2cf63c2d284..a3fa8d9b38d 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1331,6 +1331,15 @@ my_decimal *Item_func_time_to_sec::decimal_op(my_decimal* buf) } +static inline +uint32 adjust_interval_field_uint32(ulonglong value, int32 multiplier) +{ + return value > ((ulonglong) (uint32) (UINT_MAX32)) / multiplier ? + (uint32) UINT_MAX32 : + (uint32) (value * multiplier); +} + + /** Convert a string to a interval value. @@ -1341,7 +1350,7 @@ bool get_interval_value(THD *thd, Item *args, interval_type int_type, INTERVAL *interval) { ulonglong array[5]; - longlong UNINIT_VAR(value); + ulonglong UNINIT_VAR(value); const char *UNINIT_VAR(str); size_t UNINIT_VAR(length); CHARSET_INFO *UNINIT_VAR(cs); @@ -1368,14 +1377,17 @@ bool get_interval_value(THD *thd, Item *args, } else if ((int) int_type <= INTERVAL_MICROSECOND) { - value= args->val_int(); - if (args->null_value) - return 1; - if (value < 0) - { - interval->neg=1; - value= -value; - } + /* + Let's use Longlong_hybrid_null to handle correctly: + - signed and unsigned values + - the corner case with LONGLONG_MIN + (avoid undefined behavior with its negation) + */ + const Longlong_hybrid_null nr= args->to_longlong_hybrid_null(); + if (nr.is_null()) + return true; + value= nr.abs(); + interval->neg= nr.neg() ? 1 : 0; } else { @@ -1402,13 +1414,13 @@ bool get_interval_value(THD *thd, Item *args, interval->year= (ulong) value; break; case INTERVAL_QUARTER: - interval->month= (ulong)(value*3); + interval->month= adjust_interval_field_uint32(value, 3); break; case INTERVAL_MONTH: interval->month= (ulong) value; break; case INTERVAL_WEEK: - interval->day= (ulong)(value*7); + interval->day= adjust_interval_field_uint32(value, 7); break; case INTERVAL_DAY: interval->day= (ulong) value; diff --git a/sql/lex_charset.h b/sql/lex_charset.h index 43854c375d9..0145176f8f0 100644 --- a/sql/lex_charset.h +++ b/sql/lex_charset.h @@ -289,6 +289,12 @@ public: DBUG_ASSERT(0); return m_ci->coll_name; } + static Lex_extended_collation_st collate_default() + { + Lex_extended_collation_st res; + res.set_collate_default(); + return res; + } void set_collate_default() { m_ci= &my_collation_contextually_typed_default; diff --git a/sql/lex_ident.h b/sql/lex_ident.h index f39273b7da5..69dd61f6bf0 100644 --- a/sql/lex_ident.h +++ b/sql/lex_ident.h @@ -20,6 +20,7 @@ #include "char_buffer.h" +extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *table_alias_charset; /* Identifiers for the database objects stored on disk, @@ -45,6 +46,33 @@ public: bool is_in_lower_case() const; bool ok_for_lower_case_names() const; #endif +#if MYSQL_VERSION_ID<=110501 +private: + static bool is_valid_ident(const LEX_CSTRING &str) + { + // NULL identifier, or 0-terminated identifier + return (str.str == NULL && str.length == 0) || str.str[str.length] == 0; + } +public: + static CHARSET_INFO *charset_info() + { + return table_alias_charset; + } + bool streq(const LEX_CSTRING &rhs) const + { + DBUG_ASSERT(is_valid_ident(*this)); + DBUG_ASSERT(is_valid_ident(rhs)); + return length == rhs.length && + my_strcasecmp(charset_info(), str, rhs.str) == 0; + } +#else +/* + Starting from 11.5.1 streq() is inherited from the base. + The above implementations of + charset_info(), streq() and is_valid_ident() should be removed. +*/ +#error Remove streq() above. +#endif // MYSQL_VERSION_ID<=110501 }; @@ -56,6 +84,10 @@ public: */ class Lex_ident_db: public Lex_ident_fs { + bool is_null() const + { + return length == 0 && str == NULL; + } // {empty_c_string,0} is used by derived tables bool is_empty() const { @@ -65,10 +97,15 @@ public: Lex_ident_db() :Lex_ident_fs(NULL, 0) { } + explicit Lex_ident_db(const LEX_CSTRING &str) + :Lex_ident_fs(str) + { + DBUG_SLOW_ASSERT(is_null() || is_empty() || !check_db_name()); + } Lex_ident_db(const char *str, size_t length) :Lex_ident_fs(str, length) { - DBUG_SLOW_ASSERT(is_empty() || !check_db_name()); + DBUG_SLOW_ASSERT(is_null() || is_empty() || !check_db_name()); } }; @@ -94,6 +131,13 @@ public: }; +class Lex_ident_table: public Lex_ident_fs +{ +public: + using Lex_ident_fs::Lex_ident_fs; +}; + + template class IdentBuffer: public CharBuffer { diff --git a/sql/log.cc b/sql/log.cc index 259ff7c1b8b..c27c4f3353b 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5561,6 +5561,15 @@ MYSQL_BIN_LOG::is_xidlist_idle_nolock() return true; } +#ifdef WITH_WSREP +static bool is_gtid_written_on_trans_start(const THD *thd) +{ + return wsrep_on(thd) && + (thd->variables.gtid_seq_no || thd->variables.wsrep_gtid_seq_no) && + (thd->wsrep_cs().mode() == wsrep::client_state::m_local); +} +#endif + /** Create a new log file name. @@ -6264,10 +6273,7 @@ THD::binlog_start_trans_and_stmt() Ha_trx_info *ha_info; ha_info= this->ha_data[binlog_hton->slot].ha_info + (mstmt_mode ? 1 : 0); - if (!ha_info->is_started() && - (this->variables.gtid_seq_no || this->variables.wsrep_gtid_seq_no) && - wsrep_on(this) && - (this->wsrep_cs().mode() == wsrep::client_state::m_local)) + if (!ha_info->is_started() && is_gtid_written_on_trans_start(this)) { uchar *buf= 0; size_t len= 0; diff --git a/sql/log.h b/sql/log.h index d15b8ff63aa..23513c75ac5 100644 --- a/sql/log.h +++ b/sql/log.h @@ -1140,7 +1140,7 @@ public: mysql_mutex_assert_not_owner(&LOCK_binlog_end_pos); lock_binlog_end_pos(); binlog_end_pos= pos; - strcpy(binlog_end_pos_file, file_name); + safe_strcpy(binlog_end_pos_file, sizeof(binlog_end_pos_file), file_name); signal_bin_log_update(); unlock_binlog_end_pos(); } @@ -1153,7 +1153,7 @@ public: { mysql_mutex_assert_not_owner(&LOCK_log); mysql_mutex_assert_owner(&LOCK_binlog_end_pos); - strcpy(file_name_buf, binlog_end_pos_file); + safe_strcpy(file_name_buf, FN_REFLEN, binlog_end_pos_file); return binlog_end_pos; } void lock_binlog_end_pos() { mysql_mutex_lock(&LOCK_binlog_end_pos); } diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index f7029b39960..5a7d748b2d8 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -1852,6 +1852,11 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi, thd->variables.pseudo_thread_id= thread_id; // for temp tables DBUG_PRINT("query",("%s", thd->query())); +#ifdef WITH_WSREP + WSREP_DEBUG("Query_log_event thread=%llu for query=%s", + thd_get_thread_id(thd), wsrep_thd_query(thd)); +#endif + if (unlikely(!(expected_error= !is_rb_alter ? error_code : 0)) || ignored_error_code(expected_error) || !unexpected_error_code(expected_error)) diff --git a/sql/mdl.cc b/sql/mdl.cc index 13a97b8e58b..69367f6024a 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -673,8 +673,10 @@ public: { ((MDL_lock*)(arg + LF_HASH_OVERHEAD))->~MDL_lock(); } static void lf_hash_initializer(LF_HASH *hash __attribute__((unused)), - MDL_lock *lock, MDL_key *key_arg) + void *_lock, const void *_key_arg) { + MDL_lock *lock= static_cast(_lock); + const MDL_key *key_arg= static_cast(_key_arg); DBUG_ASSERT(key_arg->mdl_namespace() != MDL_key::BACKUP); new (&lock->key) MDL_key(key_arg); if (key_arg->mdl_namespace() == MDL_key::SCHEMA) @@ -760,8 +762,10 @@ struct mdl_iterate_arg }; -static my_bool mdl_iterate_lock(MDL_lock *lock, mdl_iterate_arg *arg) +static my_bool mdl_iterate_lock(void *lk, void *a) { + MDL_lock *lock= static_cast(lk); + mdl_iterate_arg *arg= static_cast(a); /* We can skip check for m_strategy here, becase m_granted must be empty for such locks anyway. @@ -784,14 +788,13 @@ int mdl_iterate(mdl_iterator_callback callback, void *arg) { DBUG_ENTER("mdl_iterate"); mdl_iterate_arg argument= { callback, arg }; - LF_PINS *pins= mdl_locks.get_pins(); int res= 1; - if (pins) + if (LF_PINS *pins= mdl_locks.get_pins()) { res= mdl_iterate_lock(mdl_locks.m_backup_lock, &argument) || - lf_hash_iterate(&mdl_locks.m_locks, pins, - (my_hash_walk_action) mdl_iterate_lock, &argument); + lf_hash_iterate(&mdl_locks.m_locks, pins, mdl_iterate_lock, + &argument); lf_hash_put_pins(pins); } DBUG_RETURN(res); diff --git a/sql/my_json_writer.cc b/sql/my_json_writer.cc index 54eb8423caf..b645d4e28b9 100644 --- a/sql/my_json_writer.cc +++ b/sql/my_json_writer.cc @@ -212,7 +212,7 @@ void Json_writer::add_ull(ulonglong val) } -/* Add a memory size, printing in Kb, Kb, Gb if necessary */ +/* Add a memory size, printing in Kb, Mb if necessary */ void Json_writer::add_size(longlong val) { char buf[64]; @@ -220,18 +220,10 @@ void Json_writer::add_size(longlong val) if (val < 1024) len= my_snprintf(buf, sizeof(buf), "%lld", val); else if (val < 1024*1024*16) - { /* Values less than 16MB are specified in KB for precision */ - len= my_snprintf(buf, sizeof(buf), "%lld", val/1024); - strcpy(buf + len, "Kb"); - len+= 2; - } + len= my_snprintf(buf, sizeof(buf), "%lldKb", val/1024); else - { - len= my_snprintf(buf, sizeof(buf), "%lld", val/(1024*1024)); - strcpy(buf + len, "Mb"); - len+= 2; - } + len= my_snprintf(buf, sizeof(buf), "%lldMb", val/(1024*1024)); add_str(buf, len); } diff --git a/sql/mysql_install_db.cc b/sql/mysql_install_db.cc index 5294b91738b..9217a231af2 100644 --- a/sql/mysql_install_db.cc +++ b/sql/mysql_install_db.cc @@ -160,7 +160,7 @@ int main(int argc, char **argv) char *datadir = NULL; MY_INIT(argv[0]); GetModuleFileName(NULL, self_name, MAX_PATH); - strcpy(mysqld_path,self_name); + safe_strcpy(mysqld_path, sizeof(mysqld_path), self_name); p= strrchr(mysqld_path, FN_LIBCHAR); if (p) { @@ -224,7 +224,7 @@ int main(int argc, char **argv) Figure out default data directory. It "data" directory, next to "bin" directory, where mysql_install_db.exe resides. */ - strcpy(default_datadir, self_name); + safe_strcpy(default_datadir, sizeof(default_datadir), self_name); p = strrchr(default_datadir, FN_LIBCHAR); if (p) { diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 23d60146bc1..2b12001de9e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3195,6 +3195,15 @@ static void start_signal_handler(void) DBUG_VOID_RETURN; } +/** Called only from signal_hand function. */ +static void* exit_signal_handler() +{ + my_thread_end(); + signal_thread_in_use= 0; + pthread_exit(0); // Safety + return nullptr; // Avoid compiler warnings +} + /** This threads handles all signals and alarms. */ /* ARGSUSED */ @@ -3298,7 +3307,7 @@ pthread_handler_t signal_hand(void *) my_thread_end(); signal_thread_in_use= 0; pthread_exit(0); // Safety - return(0); /* purecov: deadcode */ + return exit_signal_handler(); } static void check_data_home(const char *path) @@ -4245,8 +4254,10 @@ static int init_common_variables() if (is_supported_parser_charset(default_charset_info)) { global_system_variables.collation_connection= default_charset_info; - global_system_variables.character_set_results= default_charset_info; - global_system_variables.character_set_client= default_charset_info; + global_system_variables.character_set_results= + global_system_variables.character_set_client= + Lex_exact_charset_opt_extended_collate(default_charset_info, true). + find_compiled_default_collation(); } else { diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 27c10f21c00..b9f012d3029 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -715,13 +715,16 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, #ifdef WITH_WSREP /* - We should replicate local gtid_slave_pos updates to other nodes. + We should replicate local gtid_slave_pos updates to other nodes if + wsrep gtid mode is set. In applier we should not append them to galera writeset. */ - if (WSREP_ON_ && wsrep_thd_is_local(thd)) + if (WSREP_ON_ && wsrep_gtid_mode && wsrep_thd_is_local(thd)) { thd->wsrep_ignore_table= false; table->file->row_logging= 1; // replication requires binary logging + if (thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID) + thd->set_query_id(next_query_id()); wsrep_start_trx_if_not_started(thd); } else @@ -904,10 +907,12 @@ rpl_slave_state::gtid_delete_pending(THD *thd, #ifdef WITH_WSREP /* - We should replicate local gtid_slave_pos updates to other nodes. + We should replicate local gtid_slave_pos updates to other nodes if + wsrep gtid mode is set. In applier we should not append them to galera writeset. */ - if (WSREP_ON_ && wsrep_thd_is_local(thd) && + if (WSREP_ON_ && wsrep_gtid_mode && + wsrep_thd_is_local(thd) && thd->wsrep_cs().state() != wsrep::client_state::s_none) { if (thd->wsrep_trx().active() == false) @@ -918,7 +923,8 @@ rpl_slave_state::gtid_delete_pending(THD *thd, } thd->wsrep_ignore_table= false; } - thd->wsrep_ignore_table= true; + else + thd->wsrep_ignore_table= true; #endif thd_saved_option= thd->variables.option_bits; diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index bbfc02110a7..a75c0e49650 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -54,11 +54,13 @@ rpt_handle_event(rpl_parallel_thread::queued_event *qev, thd->system_thread_info.rpl_sql_info->rpl_filter = rli->mi->rpl_filter; ev->thd= thd; - strcpy(rgi->event_relay_log_name_buf, qev->event_relay_log_name); + safe_strcpy(rgi->event_relay_log_name_buf, sizeof(rgi->event_relay_log_name_buf), + qev->event_relay_log_name); rgi->event_relay_log_name= rgi->event_relay_log_name_buf; rgi->event_relay_log_pos= qev->event_relay_log_pos; rgi->future_event_relay_log_pos= qev->future_event_relay_log_pos; - strcpy(rgi->future_event_master_log_name, qev->future_event_master_log_name); + safe_strcpy(rgi->future_event_master_log_name, sizeof(rgi->future_event_master_log_name), + qev->future_event_master_log_name); if (event_can_update_last_master_timestamp(ev)) rgi->last_master_timestamp= ev->when + (time_t)ev->exec_time; err= apply_event_and_update_pos_for_parallel(ev, thd, rgi); @@ -115,7 +117,8 @@ handle_queued_pos_update(THD *thd, rpl_parallel_thread::queued_event *qev) cmp= compare_log_name(rli->group_master_log_name, qev->future_event_master_log_name); if (cmp < 0) { - strcpy(rli->group_master_log_name, qev->future_event_master_log_name); + safe_strcpy(rli->group_master_log_name, sizeof(rli->group_master_log_name), + qev->future_event_master_log_name); rli->group_master_log_pos= qev->future_event_master_log_pos; } else if (cmp == 0 @@ -2051,10 +2054,13 @@ rpl_parallel_thread::get_qev(Log_event *ev, ulonglong event_size, queued_event *qev= get_qev_common(ev, event_size); if (!qev) return NULL; - strcpy(qev->event_relay_log_name, rli->event_relay_log_name); + safe_strcpy(qev->event_relay_log_name, sizeof(qev->event_relay_log_name), + rli->event_relay_log_name); qev->event_relay_log_pos= rli->event_relay_log_pos; qev->future_event_relay_log_pos= rli->future_event_relay_log_pos; - strcpy(qev->future_event_master_log_name, rli->future_event_master_log_name); + safe_strcpy(qev->future_event_master_log_name, + sizeof(qev->future_event_master_log_name), + rli->future_event_master_log_name); return qev; } @@ -2068,11 +2074,13 @@ rpl_parallel_thread::retry_get_qev(Log_event *ev, queued_event *orig_qev, if (!qev) return NULL; qev->rgi= orig_qev->rgi; - strcpy(qev->event_relay_log_name, relay_log_name); + safe_strcpy(qev->event_relay_log_name, sizeof(qev->event_relay_log_name), + relay_log_name); qev->event_relay_log_pos= event_pos; qev->future_event_relay_log_pos= event_pos+event_size; - strcpy(qev->future_event_master_log_name, - orig_qev->future_event_master_log_name); + safe_strcpy(qev->future_event_master_log_name, + sizeof(qev->future_event_master_log_name), + orig_qev->future_event_master_log_name); return qev; } diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 7f020bde162..7a99c677afa 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -997,7 +997,8 @@ void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, { if (cmp < 0) { - strcpy(group_master_log_name, rgi->future_event_master_log_name); + safe_strcpy(group_master_log_name, sizeof(group_master_log_name), + rgi->future_event_master_log_name); group_master_log_pos= log_pos; } else if (group_master_log_pos < log_pos) diff --git a/sql/semisync_master.cc b/sql/semisync_master.cc index fdf2cf21cf1..bee2f4ac37e 100644 --- a/sql/semisync_master.cc +++ b/sql/semisync_master.cc @@ -422,7 +422,8 @@ Repl_semi_sync_master::Repl_semi_sync_master() m_state(0), m_wait_point(0) { - m_reply_file_name[0]= m_wait_file_name[0]= 0; + m_reply_file_name[0]= '\0'; + m_wait_file_name[0]= '\0'; } int Repl_semi_sync_master::init_object() @@ -802,7 +803,8 @@ int Repl_semi_sync_master::report_binlog_update(THD *trans_thd, return 1; trans_thd->semisync_info= log_info; } - strcpy(log_info->log_file, log_file + dirname_length(log_file)); + safe_strcpy(log_info->log_file, sizeof(log_info->log_file), + log_file + dirname_length(log_file)); log_info->log_pos = log_pos; return write_tranx_in_binlog(waiter_thd, log_info->log_file, diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 8806462bfc3..08fce3c6c69 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7326,8 +7326,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, continue; // Add next user } - db_name= table_list->get_db_name(); - table_name= table_list->get_table_name(); + db_name= table_list->get_db_name().str; + table_name= table_list->get_table_name().str; /* Find/create cached table grant */ grant_table= table_hash_search(Str->host.str, NullS, db_name, @@ -8402,8 +8402,8 @@ bool check_grant(THD *thd, privilege_t want_access, TABLE_LIST *tables, const ACL_internal_table_access *access= get_cached_table_access(&t_ref->grant.m_internal, - t_ref->get_db_name(), - t_ref->get_table_name()); + t_ref->get_db_name().str, + t_ref->get_table_name().str); if (access) { @@ -8468,7 +8468,8 @@ bool check_grant(THD *thd, privilege_t want_access, TABLE_LIST *tables, mysql_rwlock_rdlock(&LOCK_grant); } - t_ref->grant.read(sctx, t_ref->get_db_name(), t_ref->get_table_name()); + t_ref->grant.read(sctx, + t_ref->get_db_name().str, t_ref->get_table_name().str); if (!t_ref->grant.grant_table_user && !t_ref->grant.grant_table_role && @@ -8513,7 +8514,7 @@ err: command, sctx->priv_user, sctx->host_or_ip, tl ? tl->db.str : "unknown", - tl ? tl->get_table_name() : "unknown"); + tl ? tl->get_table_name().str : "unknown"); } DBUG_RETURN(TRUE); } @@ -14020,9 +14021,11 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, Since 4.1 all database names are stored in utf8 The cast is ok as copy_with_error will create a new area for db */ + DBUG_ASSERT(db || !db_len); + // Don't pass db==nullptr to avoid UB nullptr+0 inside copy_with_error() if (unlikely(thd->copy_with_error(system_charset_info, (LEX_STRING*) &mpvio->db, - thd->charset(), db, db_len))) + thd->charset(), db ? db : "", db_len))) return packet_error; user_len= copy_and_convert(user_buff, sizeof(user_buff) - 1, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 240ccf6f378..207e3a6d00c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -202,9 +202,9 @@ uint get_table_def_key(const TABLE_LIST *table_list, const char **key) is properly initialized, so table definition cache can be produced from key used by MDL subsystem. */ - DBUG_ASSERT(!strcmp(table_list->get_db_name(), + DBUG_ASSERT(!strcmp(table_list->get_db_name().str, table_list->mdl_request.key.db_name())); - DBUG_ASSERT(!strcmp(table_list->get_table_name(), + DBUG_ASSERT(!strcmp(table_list->get_table_name().str, table_list->mdl_request.key.name())); *key= (const char*)table_list->mdl_request.key.ptr() + 1; @@ -235,33 +235,41 @@ uint get_table_def_key(const TABLE_LIST *table_list, const char **key) # Pointer to list of names of open tables. */ -struct list_open_tables_arg +class list_open_tables_arg { +public: THD *thd; - const char *db; + const Lex_ident_db db; const char *wild; TABLE_LIST table_list; OPEN_TABLE_LIST **start_list, *open_list; + + list_open_tables_arg(THD *thd_arg, const LEX_CSTRING &db_arg, + const char *wild_arg) + :thd(thd_arg), db(db_arg), wild(wild_arg), + start_list(&open_list), open_list(0) + { + bzero((char*) &table_list, sizeof(table_list)); + } }; -static my_bool list_open_tables_callback(TDC_element *element, - list_open_tables_arg *arg) +static my_bool list_open_tables_callback(void *el, void *a) { - const char *db= (char*) element->m_key; - size_t db_length= strlen(db); - const char *table_name= db + db_length + 1; + TDC_element *element= static_cast(el); + list_open_tables_arg *arg= static_cast(a); + const Lex_ident_db + db= Lex_ident_db(Lex_cstring_strlen((const char*) element->m_key)); + const char *table_name= db.str + db.length + 1; - if (arg->db && my_strcasecmp(system_charset_info, arg->db, db)) + if (arg->db.str && !arg->db.streq(db)) return FALSE; if (arg->wild && wild_compare(table_name, arg->wild, 0)) return FALSE; /* Check if user has SELECT privilege for any column in the table */ - arg->table_list.db.str= db; - arg->table_list.db.length= db_length; - arg->table_list.table_name.str= table_name; - arg->table_list.table_name.length= strlen(table_name); + arg->table_list.db= db; + arg->table_list.table_name= Lex_cstring_strlen(table_name); arg->table_list.grant.privilege= NO_ACL; if (check_table_access(arg->thd, SELECT_ACL, &arg->table_list, TRUE, 1, TRUE)) @@ -273,7 +281,7 @@ static my_bool list_open_tables_callback(TDC_element *element, strmov((*arg->start_list)->table= strmov(((*arg->start_list)->db= (char*) ((*arg->start_list) + 1)), - db) + 1, table_name); + db.str) + 1, table_name); (*arg->start_list)->in_use= 0; mysql_mutex_lock(&element->LOCK_table_share); @@ -290,20 +298,14 @@ static my_bool list_open_tables_callback(TDC_element *element, } -OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild) +OPEN_TABLE_LIST *list_open_tables(THD *thd, + const LEX_CSTRING &db, + const char *wild) { - list_open_tables_arg argument; DBUG_ENTER("list_open_tables"); + list_open_tables_arg argument(thd, db, wild); - argument.thd= thd; - argument.db= db; - argument.wild= wild; - bzero((char*) &argument.table_list, sizeof(argument.table_list)); - argument.start_list= &argument.open_list; - argument.open_list= 0; - - if (tdc_iterate(thd, (my_hash_walk_action) list_open_tables_callback, - &argument, true)) + if (tdc_iterate(thd, list_open_tables_callback, &argument, true)) DBUG_RETURN(0); DBUG_RETURN(argument.open_list); @@ -462,9 +464,10 @@ struct tc_collect_arg flush_tables_type flush_type; }; -static my_bool tc_collect_used_shares(TDC_element *element, - tc_collect_arg *arg) +static my_bool tc_collect_used_shares(void *el, void *a) { + TDC_element *element= static_cast(el); + tc_collect_arg *arg= static_cast(a); my_bool result= FALSE; DYNAMIC_ARRAY *shares= &arg->shares; @@ -574,8 +577,7 @@ bool flush_tables(THD *thd, flush_tables_type flag) my_init_dynamic_array(PSI_INSTRUMENT_ME, &collect_arg.shares, sizeof(TABLE_SHARE*), 100, 100, MYF(0)); collect_arg.flush_type= flag; - if (tdc_iterate(thd, (my_hash_walk_action) tc_collect_used_shares, - &collect_arg, true)) + if (tdc_iterate(thd, tc_collect_used_shares, &collect_arg, true)) { /* Release already collected shares */ for (uint i= 0 ; i < collect_arg.shares.elements ; i++) @@ -1902,7 +1904,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) TABLE *table; const char *key; uint key_length; - const char *alias= table_list->alias.str; + const LEX_CSTRING &alias= table_list->alias; uint flags= ot_ctx->get_flags(); MDL_ticket *mdl_ticket; TABLE_SHARE *share; @@ -1970,7 +1972,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) if (table->s->table_cache_key.length == key_length && !memcmp(table->s->table_cache_key.str, key, key_length)) { - if (!my_strcasecmp(system_charset_info, table->alias.c_ptr(), alias) && + if (Lex_ident_table(table->alias.to_lex_cstring()).streq(alias) && table->query_id != thd->query_id && /* skip tables already used */ (thd->locked_tables_mode == LTM_LOCK_TABLES || table->query_id == 0)) @@ -2044,7 +2046,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) if (thd->locked_tables_mode == LTM_PRELOCKED) my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db.str, table_list->alias.str); else - my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias); + my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias.str); DBUG_RETURN(TRUE); } diff --git a/sql/sql_base.h b/sql/sql_base.h index 505fd618c36..e9717d02f6d 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -319,7 +319,8 @@ bool flush_tables(THD *thd, flush_tables_type flag); void close_all_tables_for_name(THD *thd, TABLE_SHARE *share, ha_extra_function extra, TABLE *skip_table); -OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild); +OPEN_TABLE_LIST *list_open_tables(THD *thd, const LEX_CSTRING &db, + const char *wild); bool tdc_open_view(THD *thd, TABLE_LIST *table_list, uint flags); TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b1aab54552a..c27f70032e1 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -857,7 +857,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) my_hash_init(key_memory_user_var_entry, &user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, (my_hash_get_key) get_var_key, (my_hash_free_key) free_user_var, HASH_THREAD_SPECIFIC); - my_hash_init(PSI_INSTRUMENT_ME, &sequences, system_charset_info, + my_hash_init(PSI_INSTRUMENT_ME, &sequences, Lex_ident_fs::charset_info(), SEQUENCES_HASH_SIZE, 0, 0, (my_hash_get_key) get_sequence_last_key, (my_hash_free_key) free_sequence_last, HASH_THREAD_SPECIFIC); @@ -1494,7 +1494,8 @@ void THD::change_user(void) my_hash_init(key_memory_user_var_entry, &user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, (my_hash_get_key) get_var_key, (my_hash_free_key) free_user_var, HASH_THREAD_SPECIFIC); - my_hash_init(key_memory_user_var_entry, &sequences, system_charset_info, + my_hash_init(key_memory_user_var_entry, &sequences, + Lex_ident_fs::charset_info(), SEQUENCES_HASH_SIZE, 0, 0, (my_hash_get_key) get_sequence_last_key, (my_hash_free_key) free_sequence_last, HASH_THREAD_SPECIFIC); @@ -2546,6 +2547,8 @@ bool THD::copy_with_error(CHARSET_INFO *dstcs, LEX_STRING *dst, CHARSET_INFO *srccs, const char *src, size_t src_length) const { + // Don't allow NULL to avoid UB in the called functions: nullptr+0 + DBUG_ASSERT(src); String_copier_with_error status; return copy_fix(dstcs, dst, srccs, src, src_length, &status) || status.check_errors(srccs, src, src_length); diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index f06a58a40e4..51f7a76e40b 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -509,7 +509,8 @@ extern "C" void free_table_stats(TABLE_STATS* table_stats) void init_global_table_stats(void) { - my_hash_init(PSI_INSTRUMENT_ME, &global_table_stats, system_charset_info, + my_hash_init(PSI_INSTRUMENT_ME, &global_table_stats, + Lex_ident_fs::charset_info(), max_connections, 0, 0, (my_hash_get_key) get_key_table_stats, (my_hash_free_key) free_table_stats, 0); } @@ -528,7 +529,8 @@ extern "C" void free_index_stats(INDEX_STATS* index_stats) void init_global_index_stats(void) { - my_hash_init(PSI_INSTRUMENT_ME, &global_index_stats, system_charset_info, + my_hash_init(PSI_INSTRUMENT_ME, &global_index_stats, + Lex_ident_fs::charset_info(), max_connections, 0, 0, (my_hash_get_key) get_key_index_stats, (my_hash_free_key) free_index_stats, 0); } @@ -1009,7 +1011,7 @@ static int check_connection(THD *thd) /* See RFC 5737, 192.0.2.0/24 is reserved. */ const char* fake= "192.0.2.4"; inet_pton(AF_INET,fake, ip4); - strcpy(ip, fake); + safe_strcpy(ip, sizeof(ip), fake); peer_rc= 0; } ); @@ -1039,7 +1041,7 @@ static int check_connection(THD *thd) ip6->s6_addr[13] = 0x06; ip6->s6_addr[14] = 0x00; ip6->s6_addr[15] = 0x06; - strcpy(ip, fake); + safe_strcpy(ip, sizeof(ip), fake); peer_rc= 0; } ); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 08441d9f067..a1198b538da 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1087,8 +1087,7 @@ mysql_rm_db_internal(THD *thd, const Lex_ident_db &db, bool if_exists, Disable drop of enabled log tables, must be done before name locking. This check is only needed if we are dropping the "mysql" database. */ - if ((rm_mysql_schema= - (my_strcasecmp(system_charset_info, MYSQL_SCHEMA_NAME.str, db.str) == 0))) + if ((rm_mysql_schema= MYSQL_SCHEMA_NAME.streq(db))) { for (table= tables; table; table= table->next_local) if (check_if_log_table(table, TRUE, "DROP")) diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index b8c9c87ce62..08d9159bb02 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -239,6 +239,9 @@ int Explain_query::send_explain(THD *thd, bool extended) int Explain_query::print_explain(select_result_sink *output, uint8 explain_flags, bool is_analyze) { + /* A sanity check for ANALYZE: */ + DBUG_ASSERT(timer_tracker_frequency() != 0.0); + if (upd_del_plan) { upd_del_plan->print_explain(this, output, explain_flags, is_analyze); @@ -1948,7 +1951,7 @@ static void trace_engine_stats(handler *file, Json_writer *writer) writer->add_member("pages_read_count").add_ull(hs->pages_read_count); if (hs->pages_read_time) writer->add_member("pages_read_time_ms"). - add_double(hs->pages_read_time / 1000.0); + add_double(hs->pages_read_time * 1000. / timer_tracker_frequency()); if (hs->undo_records_read) writer->add_member("old_rows_read").add_ull(hs->undo_records_read); writer->end_object(); diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 406f67ff955..2ad91fe4e08 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -1081,10 +1081,9 @@ static SQL_HANDLER *mysql_ha_find_match(THD *thd, TABLE_LIST *tables) if (tables->is_anonymous_derived_table()) continue; if ((! tables->db.str[0] || - ! my_strcasecmp(&my_charset_latin1, hash_tables->db.str, - tables->get_db_name())) && - ! my_strcasecmp(&my_charset_latin1, hash_tables->table_name.str, - tables->get_table_name())) + Lex_ident_db(tables->get_db_name()).streq(hash_tables->db)) && + Lex_ident_table(tables->get_table_name()). + streq(hash_tables->table_name)) { /* Link into hash_tables list */ hash_tables->next= head; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 03509846cd7..982372aef97 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3054,6 +3054,7 @@ void st_select_lex::init_query() is_correlated= 0; first_natural_join_processing= 1; first_cond_optimization= 1; + first_rownum_optimization= true; no_wrap_view_item= 0; exclude_from_table_unique_test= 0; in_tvc= 0; @@ -12247,10 +12248,33 @@ bool LEX::sp_create_set_password_instr(THD *thd, } +/* + Handle the SET NAMES statement variants, e.g.: + SET NAMES DEFAULT; + SET NAMES DEFAULT COLLATE DEFAULT; + SET NAMES DEFAULT COLLATE latin1_bin; + SET NAMES latin1; + SET NAMES latin1 COLLATE DEFAULT; + SET NAMES latin1 COLLATE latin1_bin; + SET NAMES utf8mb4 COLLATE uca1400_ai_ci; + + @param pos - The position of the keyword `NAMES` inside the query + @param cs - The character set part, or nullptr if DEFAULT + @param cl - The collation (explicit or contextually typed) + @param no_lookahead - The tokinizer lookahead state +*/ bool LEX::set_names(const char *pos, - const Lex_exact_charset_opt_extended_collate &cscl, + CHARSET_INFO *cs, + const Lex_extended_collation_st &cl, bool no_lookahead) { + CHARSET_INFO *def= global_system_variables.character_set_client; + Lex_exact_charset_opt_extended_collate cscl(cs ? cs : def, true); + if (cscl.merge_collation_override(thd, + thd->variables.character_set_collations, + cl)) + return true; + if (sp_create_assignment_lex(thd, pos)) return true; CHARSET_INFO *ci= cscl.collation().charset_info(); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 1740dbfa348..7b6414c0ef4 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1268,6 +1268,13 @@ public: bool is_correlated:1; bool first_natural_join_processing:1; bool first_cond_optimization:1; + /** + The purpose of this flag is to run initialization phase for rownum + only once. This flag is set on at st_select_lex::init_query and reset to + the value false after the method optimize_rownum() has been called + from the method JOIN::optimize_inner. + */ + bool first_rownum_optimization:1; /* do not wrap view fields with Item_ref */ bool no_wrap_view_item:1; /* exclude this select from check of unique_table() */ @@ -3907,7 +3914,8 @@ public: int case_stmt_action_then(); bool setup_select_in_parentheses(); bool set_names(const char *pos, - const Lex_exact_charset_opt_extended_collate &cs, + CHARSET_INFO *cs, + const Lex_extended_collation_st &coll, bool no_lookahead); bool set_trigger_new_row(const LEX_CSTRING *name, Item *val, const LEX_CSTRING &expr_str); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 84b253bad75..1509adc24b2 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -119,10 +119,8 @@ public: */ if (WSREP(thd) && wsrep_load_data_splitting) { - handlerton *ht= table->s->db_type(); // For partitioned tables find underlying hton - if (table->file->partition_ht()) - ht= table->file->partition_ht(); + handlerton *ht= table->file->partition_ht(); if (ht->db_type != DB_TYPE_INNODB) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc index bf32e99841b..426223d9585 100644 --- a/sql/sql_locale.cc +++ b/sql/sql_locale.cc @@ -970,9 +970,9 @@ MY_LOCALE my_locale_hu_HU /***** LOCALE BEGIN id_ID: Indonesian - Indonesia *****/ static const char *my_locale_month_names_id_ID[13] = - {"Januari","Pebruari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember", NullS }; + {"Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember", NullS }; static const char *my_locale_ab_month_names_id_ID[13] = - {"Jan","Peb","Mar","Apr","Mei","Jun","Jul","Agu","Sep","Okt","Nov","Des", NullS }; + {"Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agu","Sep","Okt","Nov","Des", NullS }; static const char *my_locale_day_names_id_ID[8] = {"Senin","Selasa","Rabu","Kamis","Jumat","Sabtu","Minggu", NullS }; static const char *my_locale_ab_day_names_id_ID[8] = diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 38cc723ce56..415816f34d3 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1131,8 +1131,9 @@ static bool wsrep_tables_accessible_when_detached(const TABLE_LIST *tables) { for (const TABLE_LIST *table= tables; table; table= table->next_global) { - LEX_CSTRING db= table->db, tn= table->table_name; - if (get_table_category(&db, &tn) < TABLE_CATEGORY_INFORMATION) + if (get_table_category(Lex_ident_db(table->db), + Lex_ident_table(table->table_name)) + < TABLE_CATEGORY_INFORMATION) return false; } return tables != NULL; @@ -4552,7 +4553,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) #ifdef WITH_WSREP if (wsrep && !first_table->view) { - bool is_innodb= (first_table->table->file->ht->db_type == DB_TYPE_INNODB); + bool is_innodb= first_table->table->file->partition_ht()->db_type == DB_TYPE_INNODB; // For consistency check inserted table needs to be InnoDB if (!is_innodb && thd->wsrep_consistency_check != NO_CONSISTENCY_CHECK) @@ -6239,15 +6240,15 @@ static TABLE *find_temporary_table_for_rename(THD *thd, { TABLE_LIST *next= table->next_local; - if (!strcmp(table->get_db_name(), cur_table->get_db_name()) && - !strcmp(table->get_table_name(), cur_table->get_table_name())) + if (!strcmp(table->get_db_name().str, cur_table->get_db_name().str) && + !strcmp(table->get_table_name().str, cur_table->get_table_name().str)) { /* Table was moved away, can't be same as 'table' */ found= 1; res= 0; // Table can't be a temporary table } - if (!strcmp(next->get_db_name(), cur_table->get_db_name()) && - !strcmp(next->get_table_name(), cur_table->get_table_name())) + if (!strcmp(next->get_db_name().str, cur_table->get_db_name().str) && + !strcmp(next->get_table_name().str, cur_table->get_table_name().str)) { /* Table has matching name with new name of this table. cur_table should @@ -6999,8 +7000,7 @@ check_table_access(THD *thd, privilege_t requirements, TABLE_LIST *tables, INSERT_ACL : SELECT_ACL); } - if (check_access(thd, want_access, - table_ref->get_db_name(), + if (check_access(thd, want_access, table_ref->get_db_name().str, &table_ref->grant.privilege, &table_ref->grant.m_internal, 0, no_errors)) @@ -9201,7 +9201,7 @@ sql_kill_user(THD *thd, LEX_USER *user, killed_state state) break; case ER_KILL_DENIED_ERROR: char buf[DEFINER_LENGTH+1]; - strxnmov(buf, sizeof(buf), user->user.str, "@", user->host.str, NULL); + strxnmov(buf, sizeof(buf)-1, user->user.str, "@", user->host.str, NULL); my_printf_error(ER_KILL_DENIED_ERROR, ER_THD(thd, ER_CANNOT_USER), MYF(0), "KILL USER", buf); break; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 5d3c7b35321..5757f780f32 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -2178,7 +2178,7 @@ static int add_keyword_path(String *str, const char *keyword, const char *path) { char temp_path[FN_REFLEN]; - strcpy(temp_path, path); + safe_strcpy(temp_path, sizeof(temp_path), path); #ifdef _WIN32 /* Convert \ to / to be able to create table on unix */ char *pos, *end; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 7f4cf2a8c58..5903fc810a8 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -379,9 +379,10 @@ static void fix_dl_name(MEM_ROOT *root, LEX_CSTRING *dl) my_strcasecmp(&my_charset_latin1, dl->str + dl->length - so_ext_len, SO_EXT)) { - char *s= (char*)alloc_root(root, dl->length + so_ext_len + 1); + size_t s_size= dl->length + so_ext_len + 1; + char *s= (char*)alloc_root(root, s_size); memcpy(s, dl->str, dl->length); - strcpy(s + dl->length, SO_EXT); + safe_strcpy(s + dl->length, s_size - dl->length, SO_EXT); dl->str= s; dl->length+= so_ext_len; } @@ -3864,7 +3865,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, DBUG_ENTER("construct_options"); plugin_name_ptr= (char*) alloc_root(mem_root, plugin_name_len + 1); - strcpy(plugin_name_ptr, plugin_name); + safe_strcpy(plugin_name_ptr, plugin_name_len + 1, plugin_name); my_casedn_str(&my_charset_latin1, plugin_name_ptr); convert_underscore_to_dash(plugin_name_ptr, plugin_name_len); plugin_name_with_prefix_ptr= (char*) alloc_root(mem_root, diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 8ca252c37c6..895ff090da6 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -3347,7 +3347,7 @@ err: info->error= ER_MASTER_FATAL_ERROR_READING_BINLOG; } else if (info->errmsg != NULL) - strcpy(info->error_text, info->errmsg); + safe_strcpy(info->error_text, sizeof(info->error_text), info->errmsg); my_message(info->error, info->error_text, MYF(0)); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 45cd5a30acb..e85680edb68 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2407,8 +2407,12 @@ JOIN::optimize_inner() DBUG_RETURN(1); } if (select_lex->with_rownum && ! order && ! group_list && - !select_distinct && conds && select_lex == unit->global_parameters()) + !select_distinct && conds && select_lex == unit->global_parameters() && + select_lex->first_rownum_optimization) + { optimize_rownum(thd, unit, conds); + select_lex->first_rownum_optimization= false; + } having= optimize_cond(this, having, join_list, TRUE, &having_value, &having_equal); @@ -3651,7 +3655,8 @@ bool JOIN::make_aggr_tables_info() { List *curr_all_fields= &all_fields; List *curr_fields_list= &fields_list; - JOIN_TAB *curr_tab= join_tab + const_tables; + // Avoid UB (applying .. offset to nullptr) when join_tab is nullptr + JOIN_TAB *curr_tab= join_tab ? join_tab + const_tables : nullptr; TABLE *exec_tmp_table= NULL; bool distinct= false; const bool has_group_by= this->group; @@ -4212,9 +4217,9 @@ bool JOIN::make_aggr_tables_info() - duplicate value removal Both of these operations are done after window function computation step. */ - curr_tab= join_tab + total_join_tab_cnt(); if (select_lex->window_funcs.elements) { + curr_tab= join_tab + total_join_tab_cnt(); if (!(curr_tab->window_funcs_step= new Window_funcs_computation)) DBUG_RETURN(true); if (curr_tab->window_funcs_step->setup(thd, &select_lex->window_funcs, diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index 10a32abe716..274d66597c1 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -133,9 +133,10 @@ struct close_cached_connection_tables_arg }; -static my_bool close_cached_connection_tables_callback( - TDC_element *element, close_cached_connection_tables_arg *arg) +static my_bool close_cached_connection_tables_callback(void *el, void *a) { + TDC_element *element= static_cast(el); + auto arg= static_cast(a); TABLE_LIST *tmp; mysql_mutex_lock(&element->LOCK_table_share); @@ -188,9 +189,7 @@ static bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection) close_cached_connection_tables_arg argument= { thd, connection, 0 }; DBUG_ENTER("close_cached_connections"); - if (tdc_iterate(thd, - (my_hash_walk_action) close_cached_connection_tables_callback, - &argument)) + if (tdc_iterate(thd, close_cached_connection_tables_callback, &argument)) DBUG_RETURN(true); DBUG_RETURN(argument.tables ? diff --git a/sql/sql_show.cc b/sql/sql_show.cc index cc7e7a2a5da..a9a8e303167 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1086,7 +1086,8 @@ public: ER_THD(thd, ER_TABLEACCESS_DENIED_ERROR), "SHOW VIEW", m_sctx->priv_user, m_sctx->host_or_ip, - m_top_view->get_db_name(), m_top_view->get_table_name()); + m_top_view->get_db_name().str, + m_top_view->get_table_name().str); } return m_view_access_denied_message_ptr; } @@ -1131,8 +1132,8 @@ public: push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_VIEW_INVALID, ER_THD(thd, ER_VIEW_INVALID), - m_top_view->get_db_name(), - m_top_view->get_table_name()); + m_top_view->get_db_name().str, + m_top_view->get_table_name().str); is_handled= TRUE; break; @@ -3900,7 +3901,7 @@ static bool show_status_array(THD *thd, const char *wild, */ for (var=variables; var->type == SHOW_FUNC || var->type == SHOW_SIMPLE_FUNC; var= &tmp) - ((mysql_show_var_func)(var->value))(thd, &tmp, buff, + ((mysql_show_var_func)(var->value))(thd, &tmp, (void *) buff, status_var, scope); SHOW_TYPE show_type=var->type; @@ -7318,8 +7319,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, Security_context *sctx= thd->security_ctx; if (!tables->allowed_show) { - if (!my_strcasecmp(system_charset_info, tables->definer.user.str, - sctx->priv_user) && + if (!strcmp(tables->definer.user.str, sctx->priv_user) && !my_strcasecmp(system_charset_info, tables->definer.host.str, sctx->priv_host)) tables->allowed_show= TRUE; @@ -8362,7 +8362,7 @@ int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond) TABLE *table= tables->table; CHARSET_INFO *cs= system_charset_info; OPEN_TABLE_LIST *open_list; - if (!(open_list= list_open_tables(thd, thd->lex->first_select_lex()->db.str, + if (!(open_list= list_open_tables(thd, thd->lex->first_select_lex()->db, wild)) && thd->is_fatal_error) DBUG_RETURN(1); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c46ed3c8eab..02e8756e802 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -916,7 +916,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) */ build_table_filename(path, sizeof(path) - 1, lpt->alter_info->db.str, lpt->alter_info->table_name.str, "", 0); - strxnmov(frm_name, sizeof(frm_name), path, reg_ext, NullS); + strxnmov(frm_name, sizeof(frm_name)-1, path, reg_ext, NullS); /* When we are changing to use new frm file we need to ensure that we don't collide with another thread in process to open the frm file. diff --git a/sql/sql_test.cc b/sql/sql_test.cc index cf34c996eba..24736007f08 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -88,9 +88,9 @@ print_where(COND *cond,const char *info, enum_query_type query_type) #ifdef EXTRA_DEBUG /* This is for debugging purposes */ -static my_bool print_cached_tables_callback(TDC_element *element, - void *arg __attribute__((unused))) +static my_bool print_cached_tables_callback(void *el, void*) { + TDC_element *element= static_cast(el); TABLE *entry; mysql_mutex_lock(&element->LOCK_table_share); @@ -117,7 +117,7 @@ static void print_cached_tables(void) /* purecov: begin tested */ puts("DB Table Version Thread Open Lock"); - tdc_iterate(0, (my_hash_walk_action) print_cached_tables_callback, NULL, true); + tdc_iterate(0, print_cached_tables_callback, NULL, true); fflush(stdout); /* purecov: end */ diff --git a/sql/sql_time.cc b/sql/sql_time.cc index 910d535f8bb..cf8e9047b83 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -614,7 +614,7 @@ void make_truncated_value_warning(THD *thd, bool date_add_interval(THD *thd, MYSQL_TIME *ltime, interval_type int_type, const INTERVAL &interval, bool push_warn) { - long period, sign; + long sign; sign= (interval.neg == (bool)ltime->neg ? 1 : -1); @@ -685,13 +685,17 @@ bool date_add_interval(THD *thd, MYSQL_TIME *ltime, interval_type int_type, break; } case INTERVAL_WEEK: - period= (calc_daynr(ltime->year,ltime->month,ltime->day) + - sign * (long) interval.day); + { + longlong period= calc_daynr(ltime->year, ltime->month, ltime->day) + + (longlong) sign * (longlong) interval.day; + if (period < 0 || period > 0x7FFFFFFF) + goto invalid_date; /* Daynumber from year 0 to 9999-12-31 */ if (get_date_from_daynr((long) period,<ime->year,<ime->month, <ime->day)) goto invalid_date; break; + } case INTERVAL_YEAR: ltime->year+= sign * (long) interval.year; if ((ulong) ltime->year >= 10000L) @@ -703,8 +707,9 @@ bool date_add_interval(THD *thd, MYSQL_TIME *ltime, interval_type int_type, case INTERVAL_YEAR_MONTH: case INTERVAL_QUARTER: case INTERVAL_MONTH: - period= (ltime->year*12 + sign * (long) interval.year*12 + - ltime->month-1 + sign * (long) interval.month); + { + long period= (ltime->year*12 + sign * (long) interval.year*12 + + ltime->month-1 + sign * (long) interval.month); if ((ulong) period >= 120000L) goto invalid_date; ltime->year= (uint) (period / 12); @@ -717,6 +722,7 @@ bool date_add_interval(THD *thd, MYSQL_TIME *ltime, interval_type int_type, ltime->day++; // Leap-year } break; + } default: goto null_date; } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index c9864e57fff..8ed2df8973f 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -470,7 +470,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) /* We don't allow creating triggers on tables in the 'mysql' schema */ - if (create && lex_string_eq(&tables->db, STRING_WITH_LEN("mysql"))) + if (create && Lex_ident_db(tables->db).streq(MYSQL_SCHEMA_NAME)) { my_error(ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA, MYF(0)); DBUG_RETURN(TRUE); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 715d83f1190..a5675fab31e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -16889,23 +16889,15 @@ option_value_no_option_type: } | NAMES_SYM charset_name_or_default { - CHARSET_INFO *def= global_system_variables.character_set_client; - Lex_exact_charset_opt_extended_collate tmp($2 ? $2 : def, false); - Lex_extended_collation_st cl; - cl.set_collate_default(); - if (tmp.merge_collation(thd, thd->variables. - character_set_collations, cl) || - Lex->set_names($1.pos(), tmp, yychar == YYEMPTY)) + if (Lex->set_names($1.pos(), $2, + Lex_extended_collation_st::collate_default(), + yychar == YYEMPTY)) MYSQL_YYABORT; } | NAMES_SYM charset_name_or_default COLLATE_SYM collation_name_or_default { - CHARSET_INFO *def= global_system_variables.character_set_client; - Lex_exact_charset_opt_extended_collate tmp($2 ? $2 : def, false); - if (tmp.merge_collation(thd, thd->variables. - character_set_collations, $4) || - Lex->set_names($1.pos(), tmp, yychar == YYEMPTY)) + if (Lex->set_names($1.pos(), $2, $4, yychar == YYEMPTY)) MYSQL_YYABORT; } | DEFAULT ROLE_SYM grant_role diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index b7d81fe07bd..a2705990736 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -841,7 +841,7 @@ static Sys_var_struct Sys_character_set_system( READ_ONLY GLOBAL_VAR(system_charset_info), NO_CMD_LINE, offsetof(CHARSET_INFO, cs_name.str), DEFAULT(0)); -static Sys_var_struct Sys_character_set_server( +static Sys_var_charset Sys_character_set_server( "character_set_server", "The default character set", SESSION_VAR(collation_server), NO_CMD_LINE, offsetof(CHARSET_INFO, cs_name.str), DEFAULT(&default_charset_info), @@ -855,7 +855,7 @@ static bool check_charset_db(sys_var *self, THD *thd, set_var *var) var->save_result.ptr= thd->db_charset; return false; } -static Sys_var_struct Sys_character_set_database( +static Sys_var_charset Sys_character_set_database( "character_set_database", "The character set used by the default database", SESSION_VAR(collation_database), NO_CMD_LINE, @@ -879,7 +879,8 @@ static bool fix_thd_charset(sys_var *self, THD *thd, enum_var_type type) thd->update_charset(); return false; } -static Sys_var_struct Sys_character_set_client( + +static Sys_var_charset Sys_character_set_client( "character_set_client", "The character set for statements " "that arrive from the client", NO_SET_STMT SESSION_VAR(character_set_client), NO_CMD_LINE, @@ -889,7 +890,7 @@ static Sys_var_struct Sys_character_set_client( // for check changing export sys_var *Sys_character_set_client_ptr= &Sys_character_set_client; -static Sys_var_struct Sys_character_set_connection( +static Sys_var_charset Sys_character_set_connection( "character_set_connection", "The character set used for " "literals that do not have a character set introducer and for " "number-to-string conversion", @@ -900,7 +901,7 @@ static Sys_var_struct Sys_character_set_connection( // for check changing export sys_var *Sys_character_set_connection_ptr= &Sys_character_set_connection; -static Sys_var_struct Sys_character_set_results( +static Sys_var_charset Sys_character_set_results( "character_set_results", "The character set used for returning " "query results to the client", SESSION_VAR(character_set_results), NO_CMD_LINE, @@ -4883,7 +4884,7 @@ bool is_set_timestamp_forbidden(THD *thd) break; } char buf[1024]; - strxnmov(buf, sizeof(buf), "--secure-timestamp=", + strxnmov(buf, sizeof(buf)-1, "--secure-timestamp=", secure_timestamp_levels[opt_secure_timestamp], NULL); my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), buf); return true; diff --git a/sql/sys_vars.inl b/sql/sys_vars.inl index 1d0722c7ae9..27f39806aa3 100644 --- a/sql/sys_vars.inl +++ b/sql/sys_vars.inl @@ -2286,6 +2286,31 @@ public: { return valptr(thd, *(uchar**)option.def_value); } }; + +/** + The class to store character sets. +*/ +class Sys_var_charset: public Sys_var_struct +{ +public: + using Sys_var_struct::Sys_var_struct; + void global_save_default(THD *thd, set_var *var) + { + /* + The default value can point to an arbitrary collation, + e.g. default_charset_info. + Let's convert it to the compiled default collation. + This makes the code easier in various places such as SET NAMES. + */ + void **default_value= reinterpret_cast(option.def_value); + var->save_result.ptr= + Lex_exact_charset_opt_extended_collate((CHARSET_INFO *) *default_value, + true). + find_compiled_default_collation(); + } +}; + + /** The class for variables that store time zones diff --git a/sql/table.cc b/sql/table.cc index c42f7443767..e97facec483 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -97,7 +97,7 @@ LEX_CSTRING INFORMATION_SCHEMA_NAME= {STRING_WITH_LEN("information_schema")}; LEX_CSTRING PERFORMANCE_SCHEMA_DB_NAME= {STRING_WITH_LEN("performance_schema")}; /* MYSQL_SCHEMA name */ -LEX_CSTRING MYSQL_SCHEMA_NAME= {STRING_WITH_LEN("mysql")}; +Lex_ident_db MYSQL_SCHEMA_NAME= {STRING_WITH_LEN("mysql")}; /* GENERAL_LOG name */ LEX_CSTRING GENERAL_LOG_NAME= {STRING_WITH_LEN("general_log")}; @@ -282,42 +282,38 @@ const char *fn_frm_ext(const char *name) } -TABLE_CATEGORY get_table_category(const LEX_CSTRING *db, - const LEX_CSTRING *name) +TABLE_CATEGORY get_table_category(const Lex_ident_db &db, + const Lex_ident_table &name) { - DBUG_ASSERT(db != NULL); - DBUG_ASSERT(name != NULL); - #ifdef WITH_WSREP - if (db->str && - my_strcasecmp(system_charset_info, db->str, WSREP_SCHEMA) == 0) + if (db.str && db.streq(MYSQL_SCHEMA_NAME)) { - if ((my_strcasecmp(system_charset_info, name->str, WSREP_STREAMING_TABLE) == 0 || - my_strcasecmp(system_charset_info, name->str, WSREP_CLUSTER_TABLE) == 0 || - my_strcasecmp(system_charset_info, name->str, WSREP_MEMBERS_TABLE) == 0)) + if (name.streq(Lex_ident_table{STRING_WITH_LEN(WSREP_STREAMING_TABLE)}) || + name.streq(Lex_ident_table{STRING_WITH_LEN(WSREP_CLUSTER_TABLE)}) || + name.streq(Lex_ident_table{STRING_WITH_LEN(WSREP_MEMBERS_TABLE)})) { return TABLE_CATEGORY_INFORMATION; } } #endif /* WITH_WSREP */ - if (is_infoschema_db(db)) + if (is_infoschema_db(&db)) return TABLE_CATEGORY_INFORMATION; - if (is_perfschema_db(db)) + if (is_perfschema_db(&db)) return TABLE_CATEGORY_PERFORMANCE; - if (lex_string_eq(&MYSQL_SCHEMA_NAME, db)) + if (db.streq(MYSQL_SCHEMA_NAME)) { - if (is_system_table_name(name->str, name->length)) + if (is_system_table_name(name.str, name.length)) return TABLE_CATEGORY_SYSTEM; - if (lex_string_eq(&GENERAL_LOG_NAME, name)) + if (name.streq(GENERAL_LOG_NAME)) return TABLE_CATEGORY_LOG; - if (lex_string_eq(&SLOW_LOG_NAME, name)) + if (name.streq(SLOW_LOG_NAME)) return TABLE_CATEGORY_LOG; - if (lex_string_eq(&TRANSACTION_REG_NAME, name)) + if (name.streq(TRANSACTION_REG_NAME)) return TABLE_CATEGORY_LOG; } @@ -370,7 +366,8 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name, strmov(path_buff, path); share->normalized_path.str= share->path.str; share->normalized_path.length= path_length; - share->table_category= get_table_category(&share->db, &share->table_name); + share->table_category= get_table_category(Lex_ident_db(share->db), + Lex_ident_table(share->table_name)); share->open_errno= ENOENT; /* The following will be updated in open_table_from_share */ share->can_do_row_logging= 1; diff --git a/sql/table.h b/sql/table.h index 9921537b217..5152017ac17 100644 --- a/sql/table.h +++ b/sql/table.h @@ -22,6 +22,7 @@ #include "datadict.h" #include "sql_string.h" /* String */ #include "lex_string.h" +#include "lex_ident.h" #ifndef MYSQL_CLIENT @@ -536,8 +537,8 @@ enum enum_table_category typedef enum enum_table_category TABLE_CATEGORY; -TABLE_CATEGORY get_table_category(const LEX_CSTRING *db, - const LEX_CSTRING *name); +TABLE_CATEGORY get_table_category(const Lex_ident_db &db, + const Lex_ident_table &name); typedef struct st_table_field_type @@ -3016,7 +3017,10 @@ struct TABLE_LIST @brief Returns the name of the database that the referenced table belongs to. */ - const char *get_db_name() const { return view != NULL ? view_db.str : db.str; } + const LEX_CSTRING get_db_name() const + { + return view != NULL ? view_db : db; + } /** @brief Returns the name of the table that this TABLE_LIST represents. @@ -3024,7 +3028,10 @@ struct TABLE_LIST @details The unqualified table name or view name for a table or view, respectively. */ - const char *get_table_name() const { return view != NULL ? view_name.str : table_name.str; } + const LEX_CSTRING get_table_name() const + { + return view != NULL ? view_name : table_name; + } bool is_active_sjm(); bool is_sjm_scan_table(); bool is_jtbm() { return MY_TEST(jtbm_subselect != NULL); } @@ -3428,7 +3435,7 @@ extern LEX_CSTRING TRANSACTION_REG_NAME; /* information schema */ extern LEX_CSTRING INFORMATION_SCHEMA_NAME; -extern LEX_CSTRING MYSQL_SCHEMA_NAME; +extern Lex_ident_db MYSQL_SCHEMA_NAME; /* table names */ extern LEX_CSTRING MYSQL_PROC_NAME; diff --git a/sql/table_cache.cc b/sql/table_cache.cc index 91292e18d72..1700185b8f3 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -303,9 +303,11 @@ static void tc_remove_all_unused_tables(TDC_element *element, periodicly flush all not used tables. */ -static my_bool tc_purge_callback(TDC_element *element, - Share_free_tables::List *purge_tables) +static my_bool tc_purge_callback(void *_element, void *_purge_tables) { + TDC_element *element= static_cast(_element); + Share_free_tables::List *purge_tables= + static_cast(_purge_tables); mysql_mutex_lock(&element->LOCK_table_share); tc_remove_all_unused_tables(element, purge_tables); mysql_mutex_unlock(&element->LOCK_table_share); @@ -317,7 +319,7 @@ void tc_purge() { Share_free_tables::List purge_tables; - tdc_iterate(0, (my_hash_walk_action) tc_purge_callback, &purge_tables); + tdc_iterate(0, tc_purge_callback, &purge_tables); while (auto table= purge_tables.pop_front()) intern_close_table(table); } @@ -576,17 +578,20 @@ static void lf_alloc_destructor(uchar *arg) static void tdc_hash_initializer(LF_HASH *, - TDC_element *element, LEX_STRING *key) + void *_element, const void *_key) { + TDC_element *element= static_cast(_element); + const LEX_STRING *key= static_cast(_key); memcpy(element->m_key, key->str, key->length); element->m_key_length= (uint)key->length; tdc_assert_clean_share(element); } -static uchar *tdc_hash_key(const TDC_element *element, size_t *length, +static uchar *tdc_hash_key(const unsigned char *_element, size_t *length, my_bool) { + const TDC_element *element= (const TDC_element *) _element; *length= element->m_key_length; return (uchar*) element->m_key; } @@ -1139,7 +1144,7 @@ struct eliminate_duplicates_arg static uchar *eliminate_duplicates_get_key(const uchar *element, size_t *length, - my_bool not_used __attribute__((unused))) + my_bool) { LEX_STRING *key= (LEX_STRING *) element; *length= key->length; @@ -1147,9 +1152,10 @@ static uchar *eliminate_duplicates_get_key(const uchar *element, size_t *length, } -static my_bool eliminate_duplicates(TDC_element *element, - eliminate_duplicates_arg *arg) +static my_bool eliminate_duplicates(void *el, void *a) { + TDC_element *element= static_cast(el); + eliminate_duplicates_arg *arg= static_cast(a); LEX_STRING *key= (LEX_STRING *) alloc_root(&arg->root, sizeof(LEX_STRING)); if (!key || !(key->str= (char*) memdup_root(&arg->root, element->m_key, @@ -1195,7 +1201,7 @@ int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument, hash_flags); no_dups_argument.action= action; no_dups_argument.argument= argument; - action= (my_hash_walk_action) eliminate_duplicates; + action= eliminate_duplicates; argument= &no_dups_argument; } diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc index cc7bd6c2fd7..e949386dd90 100644 --- a/sql/temporary_tables.cc +++ b/sql/temporary_tables.cc @@ -154,7 +154,8 @@ TABLE *THD::find_temporary_table(const TABLE_LIST *tl, Temporary_table_state state) { DBUG_ENTER("THD::find_temporary_table"); - TABLE *table= find_temporary_table(tl->get_db_name(), tl->get_table_name(), + TABLE *table= find_temporary_table(tl->get_db_name().str, + tl->get_table_name().str, state); DBUG_RETURN(table); } @@ -243,8 +244,8 @@ TMP_TABLE_SHARE *THD::find_tmp_table_share(const char *db, TMP_TABLE_SHARE *THD::find_tmp_table_share(const TABLE_LIST *tl) { DBUG_ENTER("THD::find_tmp_table_share"); - TMP_TABLE_SHARE *share= find_tmp_table_share(tl->get_db_name(), - tl->get_table_name()); + TMP_TABLE_SHARE *share= find_tmp_table_share(tl->get_db_name().str, + tl->get_table_name().str); DBUG_RETURN(share); } @@ -386,7 +387,7 @@ bool THD::open_temporary_table(TABLE_LIST *tl) */ if (!table && (share= find_tmp_table_share(tl))) { - table= open_temporary_table(share, tl->get_table_name()); + table= open_temporary_table(share, tl->get_table_name().str); /* Temporary tables are not safe for parallel replication. They were designed to be visible to one thread only, so have no table locking. @@ -1185,8 +1186,8 @@ bool THD::find_and_use_tmp_table(const TABLE_LIST *tl, TABLE **out_table) bool result; DBUG_ENTER("THD::find_and_use_tmp_table"); - key_length= create_tmp_table_def_key(key, tl->get_db_name(), - tl->get_table_name()); + key_length= create_tmp_table_def_key(key, tl->get_db_name().str, + tl->get_table_name().str); result= use_temporary_table(find_temporary_table(key, key_length, TMP_TABLE_NOT_IN_USE), out_table); diff --git a/sql/transaction.cc b/sql/transaction.cc index 1ae0928e2fd..8cdf1d0f7a5 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -191,7 +191,7 @@ bool trans_begin(THD *thd, uint flags) } #ifdef WITH_WSREP - if (wsrep_thd_is_local(thd)) + if (WSREP(thd) && wsrep_thd_is_local(thd)) { if (wsrep_sync_wait(thd)) DBUG_RETURN(TRUE); diff --git a/sql/xa.cc b/sql/xa.cc index 51375cae537..333ffb8f22b 100644 --- a/sql/xa.cc +++ b/sql/xa.cc @@ -126,10 +126,11 @@ public: } return true; } - static void lf_hash_initializer(LF_HASH *hash __attribute__((unused)), - XID_cache_element *element, - XID_cache_insert_element *new_element) + static void lf_hash_initializer(LF_HASH *, void *el, const void *ie) { + XID_cache_element *element= static_cast(el); + XID_cache_insert_element *new_element= + static_cast(const_cast(ie)); DBUG_ASSERT(!element->is_set(ACQUIRED | RECOVERED)); element->rm_error= 0; element->xa_state= new_element->xa_state; @@ -147,11 +148,11 @@ public: DBUG_ASSERT(!reinterpret_cast(ptr + LF_HASH_OVERHEAD) ->is_set(ACQUIRED)); } - static uchar *key(const XID_cache_element *element, size_t *length, - my_bool not_used __attribute__((unused))) + static uchar *key(const unsigned char *el, size_t *length, my_bool) { - *length= element->xid.key_length(); - return element->xid.key(); + const XID &xid= reinterpret_cast(el)->xid; + *length= xid.key_length(); + return xid.key(); } }; @@ -227,11 +228,10 @@ void xid_cache_init() { xid_cache_inited= true; lf_hash_init(&xid_cache, sizeof(XID_cache_element), LF_HASH_UNIQUE, 0, 0, - (my_hash_get_key) XID_cache_element::key, &my_charset_bin); + XID_cache_element::key, &my_charset_bin); xid_cache.alloc.constructor= XID_cache_element::lf_alloc_constructor; xid_cache.alloc.destructor= XID_cache_element::lf_alloc_destructor; - xid_cache.initializer= - (lf_hash_initializer) XID_cache_element::lf_hash_initializer; + xid_cache.initializer= XID_cache_element::lf_hash_initializer; } @@ -337,9 +337,10 @@ struct xid_cache_iterate_arg void *argument; }; -static my_bool xid_cache_iterate_callback(XID_cache_element *element, - xid_cache_iterate_arg *arg) +static my_bool xid_cache_iterate_callback(void *el, void *a) { + XID_cache_element *element= static_cast(el); + xid_cache_iterate_arg *arg= static_cast(a); my_bool res= FALSE; if (element->lock()) { @@ -354,8 +355,7 @@ static int xid_cache_iterate(THD *thd, my_hash_walk_action action, void *arg) xid_cache_iterate_arg argument= { action, arg }; return thd->fix_xid_hash_pins() ? -1 : lf_hash_iterate(&xid_cache, thd->xid_hash_pins, - (my_hash_walk_action) xid_cache_iterate_callback, - &argument); + xid_cache_iterate_callback, &argument); } @@ -1045,17 +1045,19 @@ static my_bool xa_recover_callback(XID_cache_element *xs, Protocol *protocol, } -static my_bool xa_recover_callback_short(XID_cache_element *xs, - Protocol *protocol) +static my_bool xa_recover_callback_short(void *x, void *p) { + XID_cache_element *xs= static_cast(x); + Protocol *protocol= static_cast(p); return xa_recover_callback(xs, protocol, xs->xid.data, xs->xid.gtrid_length + xs->xid.bqual_length, &my_charset_bin); } -static my_bool xa_recover_callback_verbose(XID_cache_element *xs, - Protocol *protocol) +static my_bool xa_recover_callback_verbose(void *x, void *p) { + XID_cache_element *xs= static_cast(x); + Protocol *protocol= static_cast(p); char buf[SQL_XIDSIZE]; uint len= get_sql_xid(&xs->xid, buf); return xa_recover_callback(xs, protocol, buf, len, @@ -1095,14 +1097,14 @@ void xa_recover_get_fields(THD *thd, List *field_list, len= SQL_XIDSIZE; cs= &my_charset_utf8mb3_general_ci; if (action) - *action= (my_hash_walk_action) xa_recover_callback_verbose; + *action= xa_recover_callback_verbose; } else { len= XIDDATASIZE; cs= &my_charset_bin; if (action) - *action= (my_hash_walk_action) xa_recover_callback_short; + *action= xa_recover_callback_short; } field_list->push_back(new (mem_root) diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index e705ff0e7c0..e9b7d84a703 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -184,7 +184,8 @@ static int tina_init_func(void *p) tina_hton= (handlerton *)p; mysql_mutex_init(csv_key_mutex_tina, &tina_mutex, MY_MUTEX_INIT_FAST); (void) my_hash_init(csv_key_memory_tina_share, &tina_open_tables, - system_charset_info, 32, 0, 0, (my_hash_get_key) + Lex_ident_table::charset_info(), + 32, 0, 0, (my_hash_get_key) tina_get_key, 0, 0); tina_hton->db_type= DB_TYPE_CSV_DB; tina_hton->create= tina_create_handler; diff --git a/storage/heap/hp_info.c b/storage/heap/hp_info.c index 41596d864a2..47b1ed6e846 100644 --- a/storage/heap/hp_info.c +++ b/storage/heap/hp_info.c @@ -40,6 +40,10 @@ int heap_info(reg1 HP_INFO *info,reg2 HEAPINFO *x, int flag ) x->errkey = info->errkey; x->create_time = info->s->create_time; if (flag & HA_STATUS_AUTO) - x->auto_increment= info->s->auto_increment + 1; + { + x->auto_increment= info->s->auto_increment+1; + if (!x->auto_increment) /* This shouldn't happen */ + x->auto_increment= ~(ulonglong) 0; + } DBUG_RETURN(0); } /* heap_info */ diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 799a8575a83..f0ba346dd0e 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -758,6 +758,7 @@ static bool btr_cur_need_opposite_intention(const buf_page_t &bpage, ulint compress_limit, const rec_t *rec) { + ut_ad(bpage.frame == page_align(rec)); if (UNIV_LIKELY_NULL(bpage.zip.data) && !page_zip_available(&bpage.zip, is_clust, node_ptr_max_size, 1)) return true; @@ -1332,11 +1333,6 @@ release_tree: !btr_block_get(*index(), btr_page_get_next(block->page.frame), RW_X_LATCH, mtr, &err)) goto func_exit; - if (btr_cur_need_opposite_intention(block->page, index()->is_clust(), - lock_intention, - node_ptr_max_size, compress_limit, - page_cur.rec)) - goto need_opposite_intention; } reached_latched_leaf: @@ -1358,6 +1354,13 @@ release_tree: ut_ad(up_match != ULINT_UNDEFINED || mode != PAGE_CUR_LE); ut_ad(low_match != ULINT_UNDEFINED || mode != PAGE_CUR_LE); + if (latch_mode == BTR_MODIFY_TREE && + btr_cur_need_opposite_intention(block->page, index()->is_clust(), + lock_intention, + node_ptr_max_size, compress_limit, + page_cur.rec)) + goto need_opposite_intention; + #ifdef BTR_CUR_HASH_ADAPT /* We do a dirty read of btr_search_enabled here. We will properly check btr_search_enabled again in diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index bdeaae23da9..436ac5ece32 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2332,6 +2332,12 @@ void buf_page_free(fil_space_t *space, uint32_t page, mtr_t *mtr) mtr->memo_push(block, MTR_MEMO_PAGE_X_MODIFY); } +static void buf_inc_get(ha_handler_stats *stats) +{ + mariadb_increment_pages_accessed(stats); + ++buf_pool.stat.n_page_gets; +} + /** Get read access to a compressed page (usually of type FIL_PAGE_TYPE_ZBLOB or FIL_PAGE_TYPE_ZBLOB2). The page must be released with unfix(). @@ -2347,8 +2353,8 @@ buf_page_t* buf_page_get_zip(const page_id_t page_id, ulint zip_size) { ut_ad(zip_size); ut_ad(ut_is_2pow(zip_size)); - ++buf_pool.stat.n_page_gets; - mariadb_increment_pages_accessed(); + ha_handler_stats *const stats= mariadb_stats; + buf_inc_get(stats); buf_pool_t::hash_chain &chain= buf_pool.page_hash.cell_get(page_id.fold()); page_hash_latch &hash_lock= buf_pool.page_hash.lock_get(chain); @@ -2450,7 +2456,7 @@ must_read_page: switch (dberr_t err= buf_read_page(page_id, zip_size, chain)) { case DB_SUCCESS: case DB_SUCCESS_LOCKED_REC: - mariadb_increment_pages_read(); + mariadb_increment_pages_read(stats); goto lookup; default: ib::error() << "Reading compressed page " << page_id @@ -2626,9 +2632,8 @@ buf_page_get_gen( } #endif /* UNIV_DEBUG */ - ++buf_pool.stat.n_page_gets; - mariadb_increment_pages_accessed(); - + ha_handler_stats* const stats = mariadb_stats; + buf_inc_get(stats); auto& chain= buf_pool.page_hash.cell_get(page_id.fold()); page_hash_latch& hash_lock = buf_pool.page_hash.lock_get(chain); loop: @@ -2687,7 +2692,7 @@ loop: switch (dberr_t local_err = buf_read_page(page_id, zip_size, chain)) { case DB_SUCCESS: case DB_SUCCESS_LOCKED_REC: - mariadb_increment_pages_read(); + mariadb_increment_pages_read(stats); buf_read_ahead_random(page_id, zip_size); break; default: @@ -3068,8 +3073,7 @@ buf_block_t *buf_page_try_get(const page_id_t page_id, mtr_t *mtr) ut_ad(block->page.buf_fix_count()); ut_ad(block->page.id() == page_id); - ++buf_pool.stat.n_page_gets; - mariadb_increment_pages_accessed(); + buf_inc_get(mariadb_stats); return block; } @@ -3589,15 +3593,13 @@ void buf_refresh_io_stats() All pages must be in a replaceable state (not modified or latched). */ void buf_pool_invalidate() { - mysql_mutex_lock(&buf_pool.mutex); - /* It is possible that a write batch that has been posted earlier is still not complete. For buffer pool invalidation to proceed we must ensure there is NO write activity happening. */ - ut_d(mysql_mutex_unlock(&buf_pool.mutex)); + os_aio_wait_until_no_pending_writes(false); ut_d(buf_pool.assert_all_freed()); - ut_d(mysql_mutex_lock(&buf_pool.mutex)); + mysql_mutex_lock(&buf_pool.mutex); while (UT_LIST_GET_LEN(buf_pool.LRU)) { buf_LRU_scan_and_free_block(); diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index a69877ba34f..494486d3ba2 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1220,9 +1220,21 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) static_assert(FIL_NULL > SRV_TMP_SPACE_ID, "consistency"); static_assert(FIL_NULL > SRV_SPACE_ID_UPPER_BOUND, "consistency"); + /* BUF_LRU_MIN_LEN (256) is too high value for low buffer pool(BP) size. For + example, for BP size lower than 80M and 16 K page size, the limit is more than + 5% of total BP and for lowest BP 5M, it is 80% of the BP. Non-data objects + like explicit locks could occupy part of the BP pool reducing the pages + available for LRU. If LRU reaches minimum limit and if no free pages are + available, server would hang with page cleaner not able to free any more + pages. To avoid such hang, we adjust the LRU limit lower than the limit for + data objects as checked in buf_LRU_check_size_of_non_data_objects() i.e. one + page less than 5% of BP. */ + size_t pool_limit= buf_pool.curr_size / 20 - 1; + auto buf_lru_min_len= std::min(pool_limit, BUF_LRU_MIN_LEN); + for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.LRU); bpage && - ((UT_LIST_GET_LEN(buf_pool.LRU) > BUF_LRU_MIN_LEN && + ((UT_LIST_GET_LEN(buf_pool.LRU) > buf_lru_min_len && UT_LIST_GET_LEN(buf_pool.free) < free_limit) || recv_recovery_is_on()); ++scanned, bpage= buf_pool.lru_hp.get()) @@ -2110,60 +2122,84 @@ ATTRIBUTE_COLD void buf_flush_ahead(lsn_t lsn, bool furious) /** Conduct checkpoint-related flushing for innodb_flush_sync=ON, and try to initiate checkpoints until the target is met. @param lsn minimum value of buf_pool.get_oldest_modification(LSN_MAX) */ -ATTRIBUTE_COLD static void buf_flush_sync_for_checkpoint(lsn_t lsn) +ATTRIBUTE_COLD ATTRIBUTE_NOINLINE +static void buf_flush_sync_for_checkpoint(lsn_t lsn) { ut_ad(!srv_read_only_mode); mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex); - for (;;) + /* During furious flush, we need to keep generating free pages. Otherwise + concurrent mtrs could be blocked holding latches for the pages to be flushed + causing deadlock in rare occasion. + + Ideally we should be acquiring buffer pool mutex for the check but it is more + expensive and we are not using the mutex while calling need_LRU_eviction() as + of today. It is a quick and dirty read of the LRU and free list length. + Atomic read of try_LRU_scan should eventually let us do the eviction. + Correcting the inaccuracy would need more consideration to avoid any possible + performance regression. */ + if (buf_pool.need_LRU_eviction()) { - if (ulint n_flushed= buf_flush_list(srv_max_io_capacity, lsn)) - { - MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_SYNC_TOTAL_PAGE, - MONITOR_FLUSH_SYNC_COUNT, - MONITOR_FLUSH_SYNC_PAGES, n_flushed); - } - - fil_flush_file_spaces(); - - log_sys.latch.wr_lock(SRW_LOCK_CALL); - const lsn_t newest_lsn= log_sys.get_lsn(); mysql_mutex_lock(&buf_pool.flush_list_mutex); - lsn_t measure= buf_pool.get_oldest_modification(0); - const lsn_t checkpoint_lsn= measure ? measure : newest_lsn; - - if (!recv_recovery_is_on() && - checkpoint_lsn > log_sys.last_checkpoint_lsn + SIZE_OF_FILE_CHECKPOINT) - { - mysql_mutex_unlock(&buf_pool.flush_list_mutex); - log_checkpoint_low(checkpoint_lsn, newest_lsn); - mysql_mutex_lock(&buf_pool.flush_list_mutex); - measure= buf_pool.get_oldest_modification(LSN_MAX); - } - else - { - log_sys.latch.wr_unlock(); - if (!measure) - measure= LSN_MAX; - } - - /* After attempting log checkpoint, check if we have reached our target. */ - const lsn_t target= buf_flush_sync_lsn; - - if (measure >= target) - buf_flush_sync_lsn= 0; - else if (measure >= buf_flush_async_lsn) - buf_flush_async_lsn= 0; - - /* wake up buf_flush_wait() */ - pthread_cond_broadcast(&buf_pool.done_flush_list); + buf_pool.page_cleaner_set_idle(false); + buf_pool.n_flush_inc(); mysql_mutex_unlock(&buf_pool.flush_list_mutex); - lsn= std::max(lsn, target); + mysql_mutex_lock(&buf_pool.mutex); + /* Confirm that eviction is needed after acquiring buffer pool mutex. */ + if (buf_pool.need_LRU_eviction()) + /* We intend to only evict pages keeping maximum flush bandwidth for + flush list pages advancing checkpoint. However, if the LRU tail is full + of dirty pages, we might need some flushing. */ + std::ignore= buf_flush_LRU(srv_io_capacity); + mysql_mutex_unlock(&buf_pool.mutex); - if (measure >= lsn) - return; + mysql_mutex_lock(&buf_pool.flush_list_mutex); + buf_pool.n_flush_dec(); + mysql_mutex_unlock(&buf_pool.flush_list_mutex); } + + if (ulint n_flushed= buf_flush_list(srv_max_io_capacity, lsn)) + { + MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_SYNC_TOTAL_PAGE, + MONITOR_FLUSH_SYNC_COUNT, + MONITOR_FLUSH_SYNC_PAGES, n_flushed); + } + + fil_flush_file_spaces(); + + log_sys.latch.wr_lock(SRW_LOCK_CALL); + const lsn_t newest_lsn= log_sys.get_lsn(); + mysql_mutex_lock(&buf_pool.flush_list_mutex); + lsn_t measure= buf_pool.get_oldest_modification(0); + const lsn_t checkpoint_lsn= measure ? measure : newest_lsn; + + if (!recv_recovery_is_on() && + checkpoint_lsn > log_sys.last_checkpoint_lsn + SIZE_OF_FILE_CHECKPOINT) + { + mysql_mutex_unlock(&buf_pool.flush_list_mutex); + log_checkpoint_low(checkpoint_lsn, newest_lsn); + mysql_mutex_lock(&buf_pool.flush_list_mutex); + measure= buf_pool.get_oldest_modification(LSN_MAX); + } + else + { + log_sys.latch.wr_unlock(); + if (!measure) + measure= LSN_MAX; + } + + /* After attempting log checkpoint, check if we have reached our target. */ + const lsn_t target= buf_flush_sync_lsn; + + if (measure >= target) + buf_flush_sync_lsn= 0; + else if (measure >= buf_flush_async_lsn) + buf_flush_async_lsn= 0; + + /* wake up buf_flush_wait() */ + pthread_cond_broadcast(&buf_pool.done_flush_list); + mysql_mutex_unlock(&buf_pool.flush_list_mutex); } /** Check if the adpative flushing threshold is recommended based on @@ -2377,6 +2413,10 @@ static void buf_flush_page_cleaner() for (;;) { + DBUG_EXECUTE_IF("ib_page_cleaner_sleep", + { + std::this_thread::sleep_for(std::chrono::seconds(1)); + }); lsn_limit= buf_flush_sync_lsn; if (UNIV_UNLIKELY(lsn_limit != 0) && UNIV_LIKELY(srv_flush_sync)) diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 41e3b4e7feb..d2ac0250226 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -407,17 +407,32 @@ got_block: ut_ad(LRU_size <= BUF_LRU_MIN_LEN || available >= scan_depth || buf_pool.need_LRU_eviction()); + ut_d(bool signalled = false); + if (UNIV_UNLIKELY(available < scan_depth) && LRU_size > BUF_LRU_MIN_LEN) { mysql_mutex_lock(&buf_pool.flush_list_mutex); if (!buf_pool.page_cleaner_active()) + { buf_pool.page_cleaner_wakeup(true); + ut_d(signalled = true); + } mysql_mutex_unlock(&buf_pool.flush_list_mutex); } if (UNIV_LIKELY(get != have_mutex)) mysql_mutex_unlock(&buf_pool.mutex); + DBUG_EXECUTE_IF("ib_free_page_sleep", + { + static bool do_sleep = true; + if (do_sleep && signalled) + { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + do_sleep = false; + } + }); + block->page.zip.clear(); return block; } @@ -458,7 +473,10 @@ got_block: mysql_mutex_unlock(&buf_pool.flush_list_mutex); if (my_cond_timedwait(&buf_pool.done_free, &buf_pool.mutex.m_mutex, &abstime)) + { buf_pool.LRU_warn(); + buf_LRU_check_size_of_non_data_objects(); + } } goto got_block; diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index 70e71845083..bb51fca6ef7 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -235,12 +235,15 @@ buf_read_page_low( } ut_ad(bpage->in_file()); - ulonglong mariadb_timer= 0; + ulonglong mariadb_timer = 0; if (sync) { thd_wait_begin(nullptr, THD_WAIT_DISKIO); - if (mariadb_stats_active()) - mariadb_timer= mariadb_measure(); + if (const ha_handler_stats *stats = mariadb_stats) { + if (stats->active) { + mariadb_timer = mariadb_measure(); + } + } } DBUG_LOG("ib_buf", @@ -259,15 +262,16 @@ buf_read_page_low( if (UNIV_UNLIKELY(fio.err != DB_SUCCESS)) { buf_pool.corrupted_evict(bpage, buf_page_t::READ_FIX); } else if (sync) { - thd_wait_end(NULL); + thd_wait_end(nullptr); /* The i/o was already completed in space->io() */ fio.err = bpage->read_complete(*fio.node); space->release(); if (fio.err == DB_FAIL) { fio.err = DB_PAGE_CORRUPTED; } - if (mariadb_timer) - mariadb_increment_pages_read_time(mariadb_timer); + if (mariadb_timer) { + mariadb_increment_pages_read_time(mariadb_timer); + } } return fio.err; diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index b16a4c54f5c..8ba1bf42aed 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -66,13 +66,16 @@ ATTRIBUTE_COLD void fil_space_t::set_corrupted() const } /** Try to close a file to adhere to the innodb_open_files limit. +@param ignore_space Ignore the tablespace which is acquired by caller @param print_info whether to diagnose why a file cannot be closed @return whether a file was closed */ -bool fil_space_t::try_to_close(bool print_info) +bool fil_space_t::try_to_close(fil_space_t *ignore_space, bool print_info) { mysql_mutex_assert_owner(&fil_system.mutex); for (fil_space_t &space : fil_system.space_list) { + if (&space == ignore_space) + continue; switch (space.purpose) { case FIL_TYPE_TEMPORARY: continue; @@ -324,7 +327,7 @@ fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle, clear_closing(); if (++fil_system.n_open >= srv_max_n_open_files) { reacquire(); - try_to_close(true); + try_to_close(this, true); release(); } } @@ -381,7 +384,7 @@ static bool fil_node_open_file_low(fil_node_t *node) /* The following call prints an error message */ if (os_file_get_last_error(true) == EMFILE + 100 && - fil_space_t::try_to_close(true)) + fil_space_t::try_to_close(nullptr, true)) continue; ib::warn() << "Cannot open '" << node->name << "'."; @@ -439,7 +442,7 @@ static bool fil_node_open_file(fil_node_t *node) for (ulint count= 0; fil_system.n_open >= srv_max_n_open_files; count++) { - if (fil_space_t::try_to_close(count > 1)) + if (fil_space_t::try_to_close(nullptr, count > 1)) count= 0; else if (count >= 2) { @@ -2900,12 +2903,12 @@ fil_io_t fil_space_t::io(const IORequest &type, os_offset_t offset, size_t len, } DBUG_EXECUTE_IF("intermittent_recovery_failure", - if (type.is_read() && !(~get_rnd_value() & 0x3ff0)) + if (type.is_read() && !(~my_timer_cycles() & 0x3ff0)) goto io_error;); DBUG_EXECUTE_IF("intermittent_read_failure", if (srv_was_started && type.is_read() && - !(~get_rnd_value() & 0x3ff0)) goto io_error;); + !(~my_timer_cycles() & 0x3ff0)) goto io_error;); if (UNIV_LIKELY_NULL(UT_LIST_GET_NEXT(chain, node))) { ut_ad(this == fil_system.sys_space diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 9555f0e6cfc..af5fd1305fc 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -966,6 +966,7 @@ corrupted: first = flst_get_first(FSP_HEADER_OFFSET + FSP_FREE + header->page.frame); if (first.page == FIL_NULL) { + *err = DB_OUT_OF_FILE_SPACE; return nullptr; /* No free extents left */ } if (first.page >= space->free_limit) { @@ -3472,10 +3473,10 @@ dberr_t fsp_traverse_extents( else { err= old_xdes_entry->insert(0, mtr); - if (err) return err; - if (threshold & (srv_page_size - 1)) + if (err == DB_SUCCESS && threshold & (srv_page_size - 1)) err= old_xdes_entry->insert( xdes_calc_descriptor_page(0, threshold), mtr); + if (err) return err; } buf_block_t *block= nullptr; diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 4d9a1d3a33f..e8fb7bbd5e4 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -2582,89 +2582,88 @@ fts_get_next_doc_id( return(DB_SUCCESS); } -/*********************************************************************//** -This function fetch the Doc ID from CONFIG table, and compare with +/** Read the synced document id from the fts configuration table +@param table fts table +@param doc_id document id to be read +@param trx transaction to read from config table +@return DB_SUCCESS in case of success */ +static +dberr_t fts_read_synced_doc_id(const dict_table_t *table, + doc_id_t *doc_id, + trx_t *trx) +{ + dberr_t error; + char table_name[MAX_FULL_NAME_LEN]; + + fts_table_t fts_table; + fts_table.suffix= "CONFIG"; + fts_table.table_id= table->id; + fts_table.type= FTS_COMMON_TABLE; + fts_table.table= table; + ut_a(table->fts->doc_col != ULINT_UNDEFINED); + + trx->op_info = "update the next FTS document id"; + pars_info_t *info= pars_info_create(); + pars_info_bind_function(info, "my_func", fts_fetch_store_doc_id, + doc_id); + + fts_get_table_name(&fts_table, table_name); + pars_info_bind_id(info, "config_table", table_name); + + que_t *graph= fts_parse_sql( + &fts_table, info, + "DECLARE FUNCTION my_func;\n" + "DECLARE CURSOR c IS SELECT value FROM $config_table" + " WHERE key = 'synced_doc_id' FOR UPDATE;\n" + "BEGIN\n" + "" + "OPEN c;\n" + "WHILE 1 = 1 LOOP\n" + " FETCH c INTO my_func();\n" + " IF c % NOTFOUND THEN\n" + " EXIT;\n" + " END IF;\n" + "END LOOP;\n" + "CLOSE c;"); + + *doc_id= 0; + error = fts_eval_sql(trx, graph); + que_graph_free(graph); + return error; +} + +/** This function fetch the Doc ID from CONFIG table, and compare with the Doc ID supplied. And store the larger one to the CONFIG table. +@param table fts table +@param cmp_doc_id Doc ID to compare +@param doc_id larger document id after comparing "cmp_doc_id" to + the one stored in CONFIG table +@param trx transaction @return DB_SUCCESS if OK */ -static MY_ATTRIBUTE((nonnull)) +static dberr_t fts_cmp_set_sync_doc_id( -/*====================*/ - const dict_table_t* table, /*!< in: table */ - doc_id_t cmp_doc_id, /*!< in: Doc ID to compare */ - ibool read_only, /*!< in: TRUE if read the - synced_doc_id only */ - doc_id_t* doc_id) /*!< out: larger document id - after comparing "cmp_doc_id" - to the one stored in CONFIG - table */ + const dict_table_t *table, + doc_id_t cmp_doc_id, + doc_id_t *doc_id, + trx_t *trx=nullptr) { if (srv_read_only_mode) { return DB_READ_ONLY; } - trx_t* trx; - pars_info_t* info; - dberr_t error; - fts_table_t fts_table; - que_t* graph = NULL; - fts_cache_t* cache = table->fts->cache; - char table_name[MAX_FULL_NAME_LEN]; - ut_a(table->fts->doc_col != ULINT_UNDEFINED); + fts_cache_t* cache= table->fts->cache; + dberr_t error = DB_SUCCESS; + const trx_t* const caller_trx = trx; - fts_table.suffix = "CONFIG"; - fts_table.table_id = table->id; - fts_table.type = FTS_COMMON_TABLE; - fts_table.table = table; - - trx= trx_create(); + if (trx == nullptr) { + trx = trx_create(); + trx_start_internal_read_only(trx); + } retry: - trx_start_internal(trx); + error = fts_read_synced_doc_id(table, doc_id, trx); - trx->op_info = "update the next FTS document id"; - - info = pars_info_create(); - - pars_info_bind_function( - info, "my_func", fts_fetch_store_doc_id, doc_id); - - fts_get_table_name(&fts_table, table_name); - pars_info_bind_id(info, "config_table", table_name); - - graph = fts_parse_sql( - &fts_table, info, - "DECLARE FUNCTION my_func;\n" - "DECLARE CURSOR c IS SELECT value FROM $config_table" - " WHERE key = 'synced_doc_id' FOR UPDATE;\n" - "BEGIN\n" - "" - "OPEN c;\n" - "WHILE 1 = 1 LOOP\n" - " FETCH c INTO my_func();\n" - " IF c % NOTFOUND THEN\n" - " EXIT;\n" - " END IF;\n" - "END LOOP;\n" - "CLOSE c;"); - - *doc_id = 0; - - error = fts_eval_sql(trx, graph); - - que_graph_free(graph); - - // FIXME: We need to retry deadlock errors - if (error != DB_SUCCESS) { - goto func_exit; - } - - if (read_only) { - /* InnoDB stores actual synced_doc_id value + 1 in - FTS_CONFIG table. Reduce the value by 1 while reading - after startup. */ - if (*doc_id) *doc_id -= 1; - goto func_exit; - } + if (error != DB_SUCCESS) goto func_exit; if (cmp_doc_id == 0 && *doc_id) { cache->synced_doc_id = *doc_id - 1; @@ -2689,6 +2688,10 @@ retry: func_exit: + if (caller_trx) { + return error; + } + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); } else { @@ -2696,6 +2699,7 @@ func_exit: ib::error() << "(" << error << ") while getting next doc id " "for table " << table->name; + fts_sql_rollback(trx); if (error == DB_DEADLOCK || error == DB_LOCK_WAIT_TIMEOUT) { @@ -4174,8 +4178,8 @@ fts_sync_commit( /* After each Sync, update the CONFIG table about the max doc id we just sync-ed to index table */ - error = fts_cmp_set_sync_doc_id(sync->table, sync->max_doc_id, FALSE, - &last_doc_id); + error = fts_cmp_set_sync_doc_id(sync->table, sync->max_doc_id, + &last_doc_id, trx); /* Get the list of deleted documents that are either in the cache or were headed there but were deleted before the add @@ -4195,6 +4199,7 @@ fts_sync_commit( mysql_mutex_unlock(&cache->lock); if (UNIV_LIKELY(error == DB_SUCCESS)) { + DEBUG_SYNC_C("fts_crash_before_commit_sync"); fts_sql_commit(trx); } else { fts_sql_rollback(trx); @@ -4856,7 +4861,7 @@ fts_init_doc_id( /* Then compare this value with the ID value stored in the CONFIG table. The larger one will be our new initial Doc ID */ - fts_cmp_set_sync_doc_id(table, 0, FALSE, &max_doc_id); + fts_cmp_set_sync_doc_id(table, 0, &max_doc_id); /* If DICT_TF2_FTS_ADD_DOC_ID is set, we are in the process of creating index (and add doc id column. No need to recovery @@ -6165,7 +6170,17 @@ fts_init_index( start_doc = cache->synced_doc_id; if (!start_doc) { - fts_cmp_set_sync_doc_id(table, 0, TRUE, &start_doc); + trx_t *trx = trx_create(); + trx_start_internal_read_only(trx); + dberr_t err= fts_read_synced_doc_id(table, &start_doc, trx); + fts_sql_commit(trx); + trx->free(); + if (err != DB_SUCCESS) { + goto func_exit; + } + if (start_doc) { + start_doc--; + } cache->synced_doc_id = start_doc; } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 89d41bfdbbb..a6e7e173817 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -107,8 +107,7 @@ extern my_bool opt_readonly; #include "ut0mem.h" #include "row0ext.h" #include "mariadb_stats.h" -thread_local ha_handler_stats mariadb_dummy_stats; -thread_local ha_handler_stats *mariadb_stats= &mariadb_dummy_stats; +simple_thread_local ha_handler_stats *mariadb_stats; #include "lz4.h" #include "lzo/lzo1x.h" @@ -1017,7 +1016,7 @@ static SHOW_VAR innodb_status_variables[]= { {"have_punch_hole", &innodb_have_punch_hole, SHOW_BOOL}, {"instant_alter_column", - &export_vars.innodb_instant_alter_column, SHOW_ULONG}, + &export_vars.innodb_instant_alter_column, SHOW_SIZE_T}, /* Online alter table status variables */ {"onlineddl_rowlog_rows", @@ -1053,6 +1052,9 @@ static SHOW_VAR innodb_status_variables[]= { {"encryption_num_key_requests", &export_vars.innodb_encryption_key_requests, SHOW_LONGLONG}, + /* InnoDB bulk operations */ + {"bulk_operations", &export_vars.innodb_bulk_operations, SHOW_SIZE_T}, + {NullS, NullS, SHOW_LONG} }; @@ -3963,6 +3965,21 @@ static int innodb_init_params() } } + ulint min_open_files_limit = srv_undo_tablespaces + + srv_sys_space.m_files.size() + + srv_tmp_space.m_files.size() + 1; + if (min_open_files_limit > innobase_open_files) { + sql_print_warning( + "InnoDB: innodb_open_files=%lu is not greater " + "than the number of system tablespace files, " + "temporary tablespace files, " + "innodb_undo_tablespaces=%lu; adjusting " + "to innodb_open_files=%zu", + innobase_open_files, srv_undo_tablespaces, + min_open_files_limit); + innobase_open_files = (ulong) min_open_files_limit; + } + srv_max_n_open_files = innobase_open_files; srv_innodb_status = (ibool) innobase_create_status_file; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 560840c53a0..4b168cc3314 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -7372,6 +7372,7 @@ error_handling_drop_uncached: ut_d(dict_table_check_for_dup_indexes(user_table, CHECK_PARTIAL_OK)); if (ctx->need_rebuild()) { + export_vars.innodb_bulk_operations++; ctx->new_table->acquire(); } @@ -8520,6 +8521,15 @@ field_changed: DBUG_RETURN(true); } + if ((ha_alter_info->handler_flags & ALTER_OPTIONS) + && ctx->page_compression_level + && !ctx->old_table->not_redundant()) { + my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), + table_type(), + "PAGE_COMPRESSED=1 ROW_FORMAT=REDUNDANT"); + DBUG_RETURN(true); + } + if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA) && alter_templ_needs_rebuild(altered_table, ha_alter_info, ctx->new_table) diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index b30763fa232..5c436c1092a 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -1366,7 +1366,7 @@ public: { return !recv_recovery_is_on() && UT_LIST_GET_LEN(free) + UT_LIST_GET_LEN(LRU) < - n_chunks_new / 4 * chunks->size; + (n_chunks_new * chunks->size) / 4; } /** @return whether the buffer pool is running low */ diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 41b6c59f2c4..6c93bf00cf5 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -616,9 +616,10 @@ public: /** Reopen all files on set_write_through() or set_buffered(). */ static void reopen_all(); /** Try to close a file to adhere to the innodb_open_files limit. + @param ignore_space Ignore the tablespace which is acquired by caller @param print_info whether to diagnose why a file cannot be closed @return whether a file was closed */ - static bool try_to_close(bool print_info); + static bool try_to_close(fil_space_t *ignore_space, bool print_info); /** Close all tablespace files at shutdown */ static void close_all(); diff --git a/storage/innobase/include/mariadb_stats.h b/storage/innobase/include/mariadb_stats.h index e9051c0c08b..3a2790d02f0 100644 --- a/storage/innobase/include/mariadb_stats.h +++ b/storage/innobase/include/mariadb_stats.h @@ -16,54 +16,67 @@ this program; if not, write to the Free Software Foundation, Inc., *****************************************************************************/ -#ifndef mariadb_stats_h -#define mariadb_stats_h - -/* Include file to handle mariadbd handler specific stats */ +#pragma once #include "ha_handler_stats.h" #include "my_rdtsc.h" -/* Not active threads are ponting to this structure */ -extern thread_local ha_handler_stats mariadb_dummy_stats; +/* We do not want a dynamic initialization function to be +conditionally invoked on each access to a C++11 extern thread_local. */ +#if __cplusplus >= 202002L +# define simple_thread_local constinit thread_local +#else +# define simple_thread_local IF_WIN(__declspec(thread),__thread) +#endif -/* Points to either THD->handler_stats or mariad_dummy_stats */ -extern thread_local ha_handler_stats *mariadb_stats; +/** Pointer to handler::active_handler_stats or nullptr (via .tbss) */ +extern simple_thread_local ha_handler_stats *mariadb_stats; /* - Returns 1 if MariaDB wants engine status + Returns nonzero if MariaDB wants engine status */ -inline bool mariadb_stats_active() +inline uint mariadb_stats_active() { - return mariadb_stats->active != 0; -} - -inline bool mariadb_stats_active(ha_handler_stats *stats) -{ - return stats->active != 0; + if (ha_handler_stats *stats= mariadb_stats) + return stats->active; + return 0; } /* The following functions increment different engine status */ +inline void mariadb_increment_pages_accessed(ha_handler_stats *stats) +{ + if (stats) + stats->pages_accessed++; +} + inline void mariadb_increment_pages_accessed() { - mariadb_stats->pages_accessed++; + mariadb_increment_pages_accessed(mariadb_stats); } inline void mariadb_increment_pages_updated(ulonglong count) { - mariadb_stats->pages_updated+= count; + if (ha_handler_stats *stats= mariadb_stats) + stats->pages_updated+= count; +} + +inline void mariadb_increment_pages_read(ha_handler_stats *stats) +{ + if (stats) + stats->pages_read_count++; } inline void mariadb_increment_pages_read() { - mariadb_stats->pages_read_count++; + mariadb_increment_pages_read(mariadb_stats); } inline void mariadb_increment_undo_records_read() { - mariadb_stats->undo_records_read++; + if (ha_handler_stats *stats= mariadb_stats) + stats->undo_records_read++; } /* @@ -92,7 +105,7 @@ inline void mariadb_increment_pages_read_time(ulonglong start_time) ulonglong end_time= mariadb_measure(); /* Check that we only call this if active, see example! */ DBUG_ASSERT(start_time); - DBUG_ASSERT(mariadb_stats_active(stats)); + DBUG_ASSERT(stats->active); stats->pages_read_time+= (end_time - start_time); } @@ -105,15 +118,12 @@ inline void mariadb_increment_pages_read_time(ulonglong start_time) class mariadb_set_stats { public: - uint flag; mariadb_set_stats(ha_handler_stats *stats) { - mariadb_stats= stats ? stats : &mariadb_dummy_stats; + mariadb_stats= stats; } ~mariadb_set_stats() { - mariadb_stats= &mariadb_dummy_stats; + mariadb_stats= nullptr; } }; - -#endif /* mariadb_stats_h */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index df25983acab..8d8a8cfad17 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -614,7 +614,10 @@ struct export_var_t{ ulong innodb_undo_truncations; /** Number of instant ALTER TABLE operations that affect columns */ - ulong innodb_instant_alter_column; + Atomic_counter innodb_instant_alter_column; + + /* Number of InnoDB bulk operations */ + Atomic_counter innodb_bulk_operations; ulint innodb_onlineddl_rowlog_rows; /*!< Online alter rows */ ulint innodb_onlineddl_rowlog_pct_used; /*!< Online alter percentage diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index e6e8eb6b156..b4a3decd1c5 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -437,10 +437,10 @@ class rw_trx_hash_t not accessible by concurrent threads. */ - static void rw_trx_hash_initializer(LF_HASH *, - rw_trx_hash_element_t *element, - trx_t *trx) + static void rw_trx_hash_initializer(LF_HASH *, void *el, const void *t) { + rw_trx_hash_element_t *element= static_cast(el); + trx_t *trx= static_cast(const_cast(t)); ut_ad(element->trx == 0); element->trx= trx; element->id= trx->id; @@ -454,7 +454,7 @@ class rw_trx_hash_t Pins are used to protect object from being destroyed or reused. They are normally stored in trx object for quick access. If caller doesn't have trx - available, we try to get it using currnet_trx(). If caller doesn't have trx + available, we try to get it using current_trx(). If caller doesn't have trx at all, temporary pins are allocated. */ @@ -480,9 +480,10 @@ class rw_trx_hash_t template - static my_bool eliminate_duplicates(rw_trx_hash_element_t *element, - eliminate_duplicates_arg *arg) + static my_bool eliminate_duplicates(void *el, void *a) { + rw_trx_hash_element_t *element= static_cast(el); + auto arg= static_cast*>(a); for (trx_ids_t::iterator it= arg->ids.begin(); it != arg->ids.end(); it++) { if (*it == element->id) @@ -508,17 +509,17 @@ class rw_trx_hash_t } - template struct debug_iterator_arg + struct debug_iterator_arg { - walk_action *action; - T *argument; + my_hash_walk_action action; + void *argument; }; - template - static my_bool debug_iterator(rw_trx_hash_element_t *element, - debug_iterator_arg *arg) + static my_bool debug_iterator(void *el, void *a) { + rw_trx_hash_element_t *element= static_cast(el); + debug_iterator_arg *arg= static_cast(a); element->mutex.wr_lock(); if (element->trx) validate_element(element->trx); @@ -725,7 +726,7 @@ public: @param caller_trx used to get/set pins @param action called for every element in hash - @param argument opque argument passed to action + @param argument opaque argument passed to action May return the same element multiple times if hash is under contention. If caller doesn't like to see the same transaction multiple times, it has @@ -748,28 +749,24 @@ public: @retval 1 iteration was interrupted (action returned 1) */ - template - int iterate(trx_t *caller_trx, walk_action *action, T *argument= nullptr) + int iterate(trx_t *caller_trx, my_hash_walk_action action, + void *argument= nullptr) { LF_PINS *pins= caller_trx ? get_pins(caller_trx) : lf_hash_get_pins(&hash); ut_a(pins); #ifdef UNIV_DEBUG - debug_iterator_arg debug_arg= { action, argument }; - action= reinterpret_cast(debug_iterator); - argument= reinterpret_cast(&debug_arg); + debug_iterator_arg debug_arg= { action, argument }; + action= debug_iterator; + argument= reinterpret_cast(&debug_arg); #endif - int res= lf_hash_iterate(&hash, pins, - reinterpret_cast(action), - const_cast(static_cast - (argument))); + int res= lf_hash_iterate(&hash, pins, action, argument); if (!caller_trx) lf_hash_put_pins(pins); return res; } - template - int iterate(walk_action *action, T *argument= nullptr) + int iterate(my_hash_walk_action action, void *argument= nullptr) { return iterate(current_trx(), action, argument); } @@ -1210,9 +1207,10 @@ public: @return error code */ inline dberr_t reset_page(mtr_t *mtr); private: - static my_bool find_same_or_older_callback(rw_trx_hash_element_t *element, - trx_id_t *id) + static my_bool find_same_or_older_callback(void *el, void *i) { + auto element= static_cast(el); + auto id= static_cast(i); return element->id <= *id; } @@ -1226,9 +1224,10 @@ private: }; - static my_bool copy_one_id(rw_trx_hash_element_t *element, - snapshot_ids_arg *arg) + static my_bool copy_one_id(void* el, void *a) { + auto element= static_cast(el); + auto arg= static_cast(a); if (element->id < arg->m_id) { trx_id_t no= element->no; diff --git a/storage/innobase/include/ut0counter.h b/storage/innobase/include/ut0counter.h index d6589cc4fd3..ecbad0c0dc0 100644 --- a/storage/innobase/include/ut0counter.h +++ b/storage/innobase/include/ut0counter.h @@ -31,30 +31,6 @@ Created 2012/04/12 by Sunny Bains #include "univ.i" #include "my_rdtsc.h" -/** Use the result of my_timer_cycles(), which mainly uses RDTSC for cycles -as a random value. See the comments for my_timer_cycles() */ -/** @return result from RDTSC or similar functions. */ -static inline size_t -get_rnd_value() -{ - size_t c = static_cast(my_timer_cycles()); - - if (c != 0) { - return c; - } - - /* We may go here if my_timer_cycles() returns 0, - so we have to have the plan B for the counter. */ -#if !defined(_WIN32) - return (size_t)pthread_self(); -#else - LARGE_INTEGER cnt; - QueryPerformanceCounter(&cnt); - - return static_cast(cnt.QuadPart); -#endif /* !_WIN32 */ -} - /** Atomic which occupies whole CPU cache line. Note: We rely on the default constructor of std::atomic and do not explicitly initialize the contents. This works for us, @@ -90,7 +66,7 @@ struct ib_counter_t { /** Add to the counter. @param[in] n amount to be added */ - void add(Type n) { add(get_rnd_value(), n); } + void add(Type n) { add(size_t(my_pseudo_random()), n); } /** Add to the counter. @param[in] index a reasonably thread-unique identifier diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 27a0d15482c..1b8d5953059 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1242,6 +1242,13 @@ lock_rec_create_low( type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP); } + /* Extra bitmap size in bytes over and above the current number of + records when a record lock is created. 8 x LOCK_PAGE_DEFAULT_BITMAP_SIZE + extra record locks of same type for newly inserted records can be added + without needing to create a new lock object. Useful when the number of + records in a page is growing. */ + static constexpr size_t LOCK_PAGE_DEFAULT_BITMAP_SIZE = 8; + if (UNIV_LIKELY(!(type_mode & (LOCK_PREDICATE | LOCK_PRDT_PAGE)))) { n_bytes = (page_dir_get_n_heap(page) + 7) / 8; } else { @@ -1270,13 +1277,19 @@ lock_rec_create_low( ut_ad(trx->mutex_is_owner()); ut_ad(trx->state != TRX_STATE_NOT_STARTED); + auto cached_bytes = sizeof *trx->lock.rec_pool - sizeof *lock; + if (trx->lock.rec_cached >= UT_ARR_SIZE(trx->lock.rec_pool) - || sizeof *lock + n_bytes > sizeof *trx->lock.rec_pool) { + || n_bytes > cached_bytes) { + n_bytes += LOCK_PAGE_DEFAULT_BITMAP_SIZE; lock = static_cast( mem_heap_alloc(trx->lock.lock_heap, sizeof *lock + n_bytes)); } else { lock = &trx->lock.rec_pool[trx->lock.rec_cached++].lock; + /* Use all the extra bytes for lock bitmap. */ + ut_ad(n_bytes <= cached_bytes); + n_bytes = cached_bytes; } lock->trx = trx; @@ -1404,6 +1417,11 @@ lock_rec_find_similar_on_page( const trx_t* trx) /*!< in: transaction */ { lock_sys.rec_hash.assert_locked(lock->un_member.rec_lock.page_id); + DBUG_EXECUTE_IF("innodb_skip_lock_bitmap", { + if (!trx->in_rollback) { + return nullptr; + } + }); for (/* No op */; lock != NULL; @@ -5427,8 +5445,10 @@ static void lock_rec_block_validate(const page_id_t page_id) } } -static my_bool lock_validate_table_locks(rw_trx_hash_element_t *element, void*) + +static my_bool lock_validate_table_locks(void *el, void*) { + rw_trx_hash_element_t *element= static_cast(el); lock_sys.assert_locked(); element->mutex.wr_lock(); if (element->trx) @@ -5636,10 +5656,10 @@ struct lock_rec_other_trx_holds_expl_arg }; -static my_bool lock_rec_other_trx_holds_expl_callback( - rw_trx_hash_element_t *element, - lock_rec_other_trx_holds_expl_arg *arg) +static my_bool lock_rec_other_trx_holds_expl_callback(void *el, void *a) { + auto element= static_cast(el); + auto arg= static_cast(a); element->mutex.wr_lock(); if (element->trx) { @@ -6455,13 +6475,14 @@ dberr_t lock_trx_handle_wait(trx_t *trx) /** Do an exhaustive check for any locks (table or rec) against the table. - @param[in] table check if there are any locks held on records in this table - or on the table itself + @param t check if there are any locks held on records in this table + or on the table itself */ -static my_bool lock_table_locks_lookup(rw_trx_hash_element_t *element, - const dict_table_t *table) +static my_bool lock_table_locks_lookup(void *el, void *t) { + auto element= static_cast(el); + const dict_table_t *table= static_cast(t); lock_sys.assert_locked(); element->mutex.wr_lock(); if (element->trx) @@ -6521,7 +6542,7 @@ bool lock_table_has_locks(dict_table_t *table) { LockMutexGuard g{SRW_LOCK_CALL}; trx_sys.rw_trx_hash.iterate(lock_table_locks_lookup, - const_cast(table)); + static_cast(table)); } #endif /* UNIV_DEBUG */ return false; diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 44ba50e5130..97bf3ec6393 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2677,8 +2677,7 @@ restart: case INIT_PAGE: last_offset= FIL_PAGE_TYPE; free_or_init_page: - if (store) - store_freed_or_init_rec(id, (b & 0x70) == FREE_PAGE); + store_freed_or_init_rec(id, (b & 0x70) == FREE_PAGE); if (UNIV_UNLIKELY(rlen != 0)) goto record_corrupted; copy_if_needed: @@ -2747,7 +2746,7 @@ restart: { if (UNIV_UNLIKELY(rlen + last_offset > srv_page_size)) goto record_corrupted; - if (store && UNIV_UNLIKELY(!page_no) && file_checkpoint) + if (UNIV_UNLIKELY(!page_no) && file_checkpoint) { const bool has_size= last_offset <= FSP_HEADER_OFFSET + FSP_SIZE && last_offset + rlen >= FSP_HEADER_OFFSET + FSP_SIZE + 4; @@ -3813,6 +3812,54 @@ void recv_sys_t::apply(bool last_batch) garbage_collect(); + if (truncated_sys_space.lsn) + { + trim({0, truncated_sys_space.pages}, truncated_sys_space.lsn); + fil_node_t *file= UT_LIST_GET_LAST(fil_system.sys_space->chain); + ut_ad(file->is_open()); + + /* Last file new size after truncation */ + uint32_t new_last_file_size= + truncated_sys_space.pages - + (srv_sys_space.get_min_size() + - srv_sys_space.m_files.at( + srv_sys_space.m_files.size() - 1). param_size()); + + os_file_truncate( + file->name, file->handle, + os_offset_t{new_last_file_size} << srv_page_size_shift, true); + mysql_mutex_lock(&fil_system.mutex); + fil_system.sys_space->size= truncated_sys_space.pages; + fil_system.sys_space->chain.end->size= new_last_file_size; + srv_sys_space.set_last_file_size(new_last_file_size); + truncated_sys_space={0, 0}; + mysql_mutex_unlock(&fil_system.mutex); + } + + for (auto id= srv_undo_tablespaces_open; id--;) + { + const trunc& t= truncated_undo_spaces[id]; + if (t.lsn) + { + /* The entire undo tablespace will be reinitialized by + innodb_undo_log_truncate=ON. Discard old log for all pages. + Even though we recv_sys_t::parse() already invoked trim(), + this will be needed in case recovery consists of multiple batches + (there was an invocation with !last_batch). */ + trim({id + srv_undo_space_id_start, 0}, t.lsn); + if (fil_space_t *space = fil_space_get(id + srv_undo_space_id_start)) + { + ut_ad(UT_LIST_GET_LEN(space->chain) == 1); + ut_ad(space->recv_size >= t.pages); + fil_node_t *file= UT_LIST_GET_FIRST(space->chain); + ut_ad(file->is_open()); + os_file_truncate(file->name, file->handle, + os_offset_t{space->recv_size} << + srv_page_size_shift, true); + } + } + } + if (!pages.empty()) { ut_ad(!last_batch || lsn == scanned_lsn); @@ -3821,54 +3868,6 @@ void recv_sys_t::apply(bool last_batch) apply_log_recs= true; - if (truncated_sys_space.lsn) - { - trim({0, truncated_sys_space.pages}, truncated_sys_space.lsn); - fil_node_t *file= UT_LIST_GET_LAST(fil_system.sys_space->chain); - ut_ad(file->is_open()); - - /* Last file new size after truncation */ - uint32_t new_last_file_size= - truncated_sys_space.pages - - (srv_sys_space.get_min_size() - - srv_sys_space.m_files.at( - srv_sys_space.m_files.size() - 1). param_size()); - - os_file_truncate( - file->name, file->handle, - os_offset_t{new_last_file_size} << srv_page_size_shift, true); - mysql_mutex_lock(&fil_system.mutex); - fil_system.sys_space->size= truncated_sys_space.pages; - fil_system.sys_space->chain.end->size= new_last_file_size; - srv_sys_space.set_last_file_size(new_last_file_size); - truncated_sys_space={0, 0}; - mysql_mutex_unlock(&fil_system.mutex); - } - - for (auto id= srv_undo_tablespaces_open; id--;) - { - const trunc& t= truncated_undo_spaces[id]; - if (t.lsn) - { - /* The entire undo tablespace will be reinitialized by - innodb_undo_log_truncate=ON. Discard old log for all pages. - Even though we recv_sys_t::parse() already invoked trim(), - this will be needed in case recovery consists of multiple batches - (there was an invocation with !last_batch). */ - trim({id + srv_undo_space_id_start, 0}, t.lsn); - if (fil_space_t *space = fil_space_get(id + srv_undo_space_id_start)) - { - ut_ad(UT_LIST_GET_LEN(space->chain) == 1); - ut_ad(space->recv_size >= t.pages); - fil_node_t *file= UT_LIST_GET_FIRST(space->chain); - ut_ad(file->is_open()); - os_file_truncate(file->name, file->handle, - os_offset_t{space->recv_size} << - srv_page_size_shift, true); - } - } - } - fil_system.extend_to_recv_size(); fil_space_t *space= nullptr; diff --git a/storage/innobase/log/log0sync.cc b/storage/innobase/log/log0sync.cc index 6b14d1d3591..0de283ca2bb 100644 --- a/storage/innobase/log/log0sync.cc +++ b/storage/innobase/log/log0sync.cc @@ -187,7 +187,7 @@ void group_commit_lock::set_pending(group_commit_lock::value_type num) } const unsigned int MAX_SPINS = 1; /** max spins in acquire */ -thread_local group_commit_waiter_t thread_local_waiter; +static thread_local group_commit_waiter_t thread_local_waiter; static inline void do_completion_callback(const completion_callback* cb) { diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 8db52ac1f47..7928942de8d 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -898,7 +898,7 @@ ATTRIBUTE_COLD static void log_overwrite_warning(lsn_t lsn) " last checkpoint LSN=" LSN_PF ", current LSN=" LSN_PF "%s.", lsn_t{log_sys.last_checkpoint_lsn}, lsn, - srv_shutdown_state != SRV_SHUTDOWN_INITIATED + srv_shutdown_state > SRV_SHUTDOWN_INITIATED ? ". Shutdown is in progress" : ""); } diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 952ccee4b24..3ec994ad095 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -2768,6 +2768,7 @@ avoid_bulk: goto avoid_bulk; } + export_vars.innodb_bulk_operations++; goto err_exit; } } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index e13bc77d99d..91809f020c9 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -680,13 +680,9 @@ err_exit: space_id= id; fsp_flags= mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); - if (buf_page_is_corrupted(false, page, fsp_flags)) - { - sql_print_error("InnoDB: Checksum mismatch in the first page of file %s", - name); - if (recv_sys.dblwr.restore_first_page(space_id, name, fh)) - goto err_exit; - } + if (buf_page_is_corrupted(false, page, fsp_flags) && + recv_sys.dblwr.restore_first_page(space_id, name, fh)) + goto err_exit; aligned_free(page); } diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index ff9d8c55119..626918eca61 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -538,6 +538,7 @@ TRANSACTIONAL_TARGET void trx_free_at_shutdown(trx_t *trx) DBUG_LOG("trx", "Free prepared: " << trx); trx->state = TRX_STATE_NOT_STARTED; ut_ad(!UT_LIST_GET_LEN(trx->lock.trx_locks)); + ut_d(*trx->detailed_error = '\0'); trx->free(); } @@ -2096,9 +2097,9 @@ static my_bool trx_recover_for_mysql_callback(rw_trx_hash_element_t *element, } -static my_bool trx_recover_reset_callback(rw_trx_hash_element_t *element, - void*) +static my_bool trx_recover_reset_callback(void *el, void*) { + rw_trx_hash_element_t *element= static_cast(el); element->mutex.wr_lock(); if (trx_t *trx= element->trx) { @@ -2150,9 +2151,10 @@ struct trx_get_trx_by_xid_callback_arg }; -static my_bool trx_get_trx_by_xid_callback(rw_trx_hash_element_t *element, - trx_get_trx_by_xid_callback_arg *arg) +static my_bool trx_get_trx_by_xid_callback(void *el, void *a) { + auto element= static_cast(el); + auto arg= static_cast(a); my_bool found= 0; element->mutex.wr_lock(); if (trx_t *trx= element->trx) diff --git a/storage/maria/ma_range.c b/storage/maria/ma_range.c index 442adc35858..525bf27b90c 100644 --- a/storage/maria/ma_range.c +++ b/storage/maria/ma_range.c @@ -191,8 +191,8 @@ static ha_rows _ma_record_pos(MARIA_HA *info, const uchar *key_data, info->s->state.key_root[inx], final_page); if (pos >= 0.0) { - DBUG_PRINT("exit",("pos: %ld",(ulong) (pos*info->state->records))); - DBUG_RETURN((ulong) (pos*info->state->records+0.5)); + DBUG_PRINT("exit",("pos: %lld",(longlong) (pos*info->state->records))); + DBUG_RETURN((ha_rows) (pos*info->state->records+0.5)); } DBUG_RETURN(HA_POS_ERROR); } @@ -214,7 +214,7 @@ static double _ma_search_pos(MARIA_HA *info, MARIA_KEY *key, { int flag; uint keynr, UNINIT_VAR(max_keynr); - my_bool after_key; + my_bool last_key_on_page; uchar *keypos; double offset; MARIA_KEYDEF *keyinfo= key->keyinfo; @@ -230,7 +230,7 @@ static double _ma_search_pos(MARIA_HA *info, MARIA_KEY *key, goto err; *final_page= pos; flag= (*keyinfo->bin_search)(key, &page, nextflag, &keypos, - info->lastkey_buff, &after_key); + info->lastkey_buff, &last_key_on_page); keynr= _ma_keynr(&page, keypos, &max_keynr); if (flag) @@ -274,7 +274,7 @@ static double _ma_search_pos(MARIA_HA *info, MARIA_KEY *key, There may be identical keys in the tree. Try to match on of those. Matches keynr + [0-1] */ - if ((offset= _ma_search_pos(info, key, SEARCH_FIND, + if ((offset= _ma_search_pos(info, key, nextflag, _ma_kpos(page.node,keypos), final_page)) < 0) DBUG_RETURN(offset); /* Read error */ @@ -290,9 +290,10 @@ err: /* - Get keynummer of current key and max number of keys in nod + Get keynumber of current key and max number of keys in nod - keynr >= 0 && key_nr <= max_key + @return key position on page (0 - (ret_max_key - 1)) + ret_max_key contains how many keys there was on the page */ static uint _ma_keynr(MARIA_PAGE *page, uchar *keypos, uint *ret_max_key) diff --git a/storage/mroonga/vendor/groonga/lib/CMakeLists.txt b/storage/mroonga/vendor/groonga/lib/CMakeLists.txt index 4f076458a36..1149458d523 100644 --- a/storage/mroonga/vendor/groonga/lib/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/lib/CMakeLists.txt @@ -188,3 +188,15 @@ IF(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "5") ADD_COMPILE_FLAGS(ts/ts_expr_node.c COMPILE_FLAGS "-fno-tree-loop-vectorize") ENDIF() + +# Workaround long compile times with GCC and sanitizers +IF(CMAKE_C_COMPILER_ID STREQUAL "GNU" + AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "11.99") + IF(WITH_UBSAN) + ADD_COMPILE_FLAGS(expr.c COMPILE_FLAGS "-fno-sanitize=undefined") + ENDIF() + IF(WITH_ASAN) + ADD_COMPILE_FLAGS(expr.c COMPILE_FLAGS "-fno-sanitize=address") + ENDIF() +ENDIF() + diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc index c6d2f23d653..8b7825f3816 100644 --- a/storage/perfschema/ha_perfschema.cc +++ b/storage/perfschema/ha_perfschema.cc @@ -133,7 +133,9 @@ static int pfs_done_func(void *p) DBUG_RETURN(0); } -static int show_func_mutex_instances_lost(THD *thd, SHOW_VAR *var, char *buff) +static int show_func_mutex_instances_lost(THD *thd, SHOW_VAR *var, void *buff, + struct system_status_var *status_var, + enum enum_var_type) { var->type= SHOW_LONG; var->value= buff; diff --git a/storage/perfschema/unittest/pfs_noop-t.cc b/storage/perfschema/unittest/pfs_noop-t.cc index 57e8cfd8a0a..6d5e4eb152f 100644 --- a/storage/perfschema/unittest/pfs_noop-t.cc +++ b/storage/perfschema/unittest/pfs_noop-t.cc @@ -240,6 +240,7 @@ int main(int, char **) MY_INIT("pfs_noop-t"); test_noop(); + my_end(MY_CHECK_ERROR); return (exit_status()); } diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index c2fbb77621d..7785542a58f 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -482,7 +482,8 @@ error_get_share: owner->wide_handler = NULL; owner->wide_handler_owner = FALSE; } - wide_handler = NULL; + if (!wide_handler_owner) + wide_handler = NULL; error_wide_handler_alloc: DBUG_RETURN(error_num); } @@ -6539,8 +6540,6 @@ int ha_spider::info( spider_init_error_table->init_error_time = (time_t) time((time_t*) 0); } - share->init_error = TRUE; - share->init = TRUE; } if (wide_handler->sql_command == SQLCOM_SHOW_CREATE || wide_handler->sql_command == SQLCOM_SHOW_FIELDS) @@ -6591,10 +6590,6 @@ int ha_spider::info( share, TRUE)) ) { spider_init_error_table->init_error = error_num; -/* - if (!thd->is_error()) - my_error(error_num, MYF(0), ""); -*/ if ((spider_init_error_table->init_error_with_message = thd->is_error())) strmov(spider_init_error_table->init_error_msg, @@ -6602,8 +6597,6 @@ int ha_spider::info( spider_init_error_table->init_error_time = (time_t) time((time_t*) 0); } - share->init_error = TRUE; - share->init = TRUE; } if (wide_handler->sql_command == SQLCOM_SHOW_CREATE || wide_handler->sql_command == SQLCOM_SHOW_FIELDS) @@ -6883,8 +6876,6 @@ ha_rows ha_spider::records_in_range( spider_init_error_table->init_error_time = (time_t) time((time_t*) 0); } - share->init_error = TRUE; - share->init = TRUE; } if (check_error_mode(error_num)) my_errno = error_num; @@ -7174,8 +7165,6 @@ int ha_spider::check_crd() spider_init_error_table->init_error_time = (time_t) time((time_t*) 0); } - share->init_error = TRUE; - share->init = TRUE; } DBUG_RETURN(check_error_mode(error_num)); } @@ -7562,18 +7551,6 @@ int ha_spider::update_auto_increment() DBUG_ENTER("ha_spider::update_auto_increment"); DBUG_PRINT("info",("spider this=%p", this)); force_auto_increment = TRUE; -/* - if ( - next_insert_id >= auto_inc_interval_for_cur_row.maximum() && - wide_handler->trx->thd->auto_inc_intervals_forced.get_current() - ) { - force_auto_increment = TRUE; - DBUG_PRINT("info",("spider force_auto_increment=TRUE")); - } else { - force_auto_increment = FALSE; - DBUG_PRINT("info",("spider force_auto_increment=FALSE")); - } -*/ DBUG_PRINT("info",("spider auto_increment_mode=%d", auto_increment_mode)); DBUG_PRINT("info",("spider next_number_field=%lld", @@ -7803,7 +7780,12 @@ int ha_spider::write_row( pthread_mutex_lock(&share->lgtm_tblhnd_share->auto_increment_mutex); if (!share->lgtm_tblhnd_share->auto_increment_init) { - info(HA_STATUS_AUTO); + if ((error_num= info(HA_STATUS_AUTO))) + { + pthread_mutex_unlock( + &share->lgtm_tblhnd_share->auto_increment_mutex); + DBUG_RETURN(error_num); + } share->lgtm_tblhnd_share->auto_increment_lclval = stats.auto_increment_value; share->lgtm_tblhnd_share->auto_increment_init = TRUE; diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h index 2e638269ef9..022f3c54321 100644 --- a/storage/spider/ha_spider.h +++ b/storage/spider/ha_spider.h @@ -78,6 +78,7 @@ public: SPIDER_POSITION *pushed_pos; SPIDER_POSITION pushed_pos_buf; SPIDER_PARTITION_HANDLER *partition_handler; + /* Whether this ha_spider is the owner of its wide_handler. */ bool wide_handler_owner = FALSE; SPIDER_WIDE_HANDLER *wide_handler = NULL; diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_27186.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_27186.result new file mode 100644 index 00000000000..9c2a7a60829 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_27186.result @@ -0,0 +1,32 @@ +INSTALL SONAME 'ha_spider'; +CREATE TABLE t (s INT) ENGINE=SPIDER PARTITION BY HASH (s); +LOAD INDEX INTO CACHE t PARTITION (p,p1); +Table Op Msg_type Msg_text +test.t preload_keys Error Unable to connect to foreign data source: localhost +test.t preload_keys Error Unable to connect to foreign data source: localhost +test.t preload_keys Error Unable to connect to foreign data source: localhost +test.t preload_keys Error Unable to connect to foreign data source: localhost +test.t preload_keys error Corrupt +DROP TABLE t; +CREATE TABLE t (c INT PRIMARY KEY) ENGINE=SPIDER PARTITION BY KEY() PARTITIONS 2; +HANDLER t OPEN AS h; +ERROR HY000: Unable to connect to foreign data source: localhost +DROP TABLE t; +CREATE TABLE t (c INT PRIMARY KEY) ENGINE=SPIDER PARTITION BY HASH (c) PARTITIONS 2; +CREATE TRIGGER t AFTER INSERT ON t FOR EACH ROW INSERT INTO t VALUES(0); +ERROR HY000: Unable to connect to foreign data source: localhost +DROP TABLE t; +CREATE TABLE t (b INT) ENGINE=InnoDB; +PREPARE s FROM 'SELECT * FROM t LIMIT 2'; +DROP TABLE t; +CREATE TABLE t (a INT) ENGINE=Spider PARTITION BY LIST (a) PARTITIONS 2 (PARTITION p1 VALUES IN (0,1),PARTITION p2 VALUES IN (2,3)); +EXECUTE s; +ERROR HY000: Unable to connect to foreign data source: localhost +DROP TABLE t; +CREATE TABLE t (c INT) ENGINE=InnoDB; +LOCK TABLES t WRITE; +CREATE OR REPLACE TABLE t (d INT) ENGINE=Spider PARTITION BY LIST COLUMNS (d) (PARTITION p VALUES IN (0)); +ERROR HY000: Unable to connect to foreign data source: localhost +drop table t; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_28105.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_28105.result new file mode 100644 index 00000000000..c142bbc7219 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_28105.result @@ -0,0 +1,8 @@ +install soname 'ha_spider'; +SET @@insert_id=128; +CREATE TABLE t(c TINYINT AUTO_INCREMENT KEY) ENGINE=Spider; +INSERT IGNORE INTO t VALUES(0); +ERROR HY000: Unable to connect to foreign data source: localhost +drop table t; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29027.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29027.result new file mode 100644 index 00000000000..1d9bc01fdb2 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29027.result @@ -0,0 +1,24 @@ +# +# MDEV-29027 ASAN errors in spider_db_free_result after partition DDL +# +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +CREATE DATABASE auto_test_local; +USE auto_test_local; +CREATE TABLE tbl_a ( +c INT +) ENGINE=Spider DEFAULT CHARSET=utf8 PARTITION BY HASH(c) ( +PARTITION pt1 +); +ALTER TABLE tbl_a ADD PARTITION (PARTITION pt2); +DROP DATABASE auto_test_local; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_29027_original.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_29027_original.result new file mode 100644 index 00000000000..b87d877a04f --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_29027_original.result @@ -0,0 +1,20 @@ +for master_1 +for child2 +for child3 +set spider_same_server_link= 1; +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +CREATE TABLE t1 (a INT); +CREATE TABLE t_spider (a INT) ENGINE=SPIDER PARTITION BY HASH(a) (PARTITION p1 COMMENT = "wrapper 'mysql', srv 'srv', table 't1'"); +Warnings: +Warning 138 Spider table params in COMMENT or CONNECTION strings have been deprecated and will be removed in a future release. Please use table options instead. +CREATE TABLE t2 (a INT); +ALTER TABLE t_spider ADD PARTITION (PARTITION p2 COMMENT = "wrapper 'mysql', srv 'srv', table 't2'"); +Warnings: +Warning 138 Spider table params in COMMENT or CONNECTION strings have been deprecated and will be removed in a future release. Please use table options instead. +Warning 138 Spider table params in COMMENT or CONNECTION strings have been deprecated and will be removed in a future release. Please use table options instead. +DROP TABLE t_spider, t1, t2; +drop server srv; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_31475.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_31475.result new file mode 100644 index 00000000000..93e1665d05b --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_31475.result @@ -0,0 +1,25 @@ +for master_1 +for child2 +for child3 +CREATE TABLE t3 (c1 MEDIUMINT NULL, c2 CHAR(5)) ENGINE=Spider PARTITION BY KEY(c1) PARTITIONS 2; +ALTER TABLE t3 DROP PRIMARY KEY; +ERROR 42000: Can't DROP INDEX `PRIMARY`; check that it exists +SELECT * FROM t3 WHERE c1 <=> '1000-00-01 00:00:00' ORDER BY c1,c2 LIMIT 2; +ERROR HY000: Unable to connect to foreign data source: localhost +CREATE TABLE t1 (a INT UNSIGNED NOT NULL PRIMARY KEY, b INT UNSIGNED NOT NULL, c INT UNSIGNED, UNIQUE (b, c) USING HASH) ENGINE=Spider; +SELECT t1.c1 FROM t3 RIGHT JOIN t1 ON t1.c1=current_date() UNION SELECT t1.c2 FROM t1 LEFT OUTER JOIN t3 ON t1.c2; +ERROR HY000: Unable to connect to foreign data source: localhost +drop table t1, t3; +set spider_same_server_link= 1; +CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +CREATE TABLE t1 (a INT, b VARCHAR(255), PRIMARY KEY(a)) ENGINE=Spider PARTITION BY RANGE (a) (PARTITION p1 VALUES LESS THAN (3), PARTITION p2 VALUES LESS THAN MAXVALUE COMMENT='srv "srv"'); +Warnings: +Warning 138 Spider table params in COMMENT or CONNECTION strings have been deprecated and will be removed in a future release. Please use table options instead. +DROP SERVER srv; +SELECT * FROM t1; +ERROR HY000: The foreign server name you are trying to reference does not exist. Data source error: srv +drop table t1; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_34002.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_34002.result new file mode 100644 index 00000000000..7e266156e0a --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_34002.result @@ -0,0 +1,9 @@ +INSTALL PLUGIN Spider SONAME 'ha_spider.so'; +CREATE TABLE t (c DATE, c2 VARCHAR(1025) CHARACTER SET utf8mb3, UNIQUE KEY k(c2)) ENGINE=SPIDER; +UPDATE t SET c='2'; +ERROR HY000: Unable to connect to foreign data source: localhost +drop table t; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown +Note 1305 PLUGIN SPIDER_ALLOC_MEM does not exist +Note 1305 PLUGIN SPIDER_WRAPPER_PROTOCOLS does not exist diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27186.opt b/storage/spider/mysql-test/spider/bugfix/t/mdev_27186.opt new file mode 100644 index 00000000000..789275fa25e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27186.opt @@ -0,0 +1 @@ +--skip-log-bin diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_27186.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_27186.test new file mode 100644 index 00000000000..67c038009ba --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_27186.test @@ -0,0 +1,37 @@ +INSTALL SONAME 'ha_spider'; + +# MDEV-27186 +CREATE TABLE t (s INT) ENGINE=SPIDER PARTITION BY HASH (s); +LOAD INDEX INTO CACHE t PARTITION (p,p1); +DROP TABLE t; + +# MDEV-27237 +CREATE TABLE t (c INT PRIMARY KEY) ENGINE=SPIDER PARTITION BY KEY() PARTITIONS 2; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +HANDLER t OPEN AS h; +DROP TABLE t; + +# MDEV-27334 +CREATE TABLE t (c INT PRIMARY KEY) ENGINE=SPIDER PARTITION BY HASH (c) PARTITIONS 2; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +CREATE TRIGGER t AFTER INSERT ON t FOR EACH ROW INSERT INTO t VALUES(0); +DROP TABLE t; + +# MDEV-28241 +CREATE TABLE t (b INT) ENGINE=InnoDB; +PREPARE s FROM 'SELECT * FROM t LIMIT 2'; +DROP TABLE t; +CREATE TABLE t (a INT) ENGINE=Spider PARTITION BY LIST (a) PARTITIONS 2 (PARTITION p1 VALUES IN (0,1),PARTITION p2 VALUES IN (2,3)); +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +EXECUTE s; +DROP TABLE t; + +# MDEV-34101 +CREATE TABLE t (c INT) ENGINE=InnoDB; +LOCK TABLES t WRITE; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +CREATE OR REPLACE TABLE t (d INT) ENGINE=Spider PARTITION BY LIST COLUMNS (d) (PARTITION p VALUES IN (0)); +drop table t; + +--disable_query_log +--source ../../include/clean_up_spider.inc diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28105.opt b/storage/spider/mysql-test/spider/bugfix/t/mdev_28105.opt new file mode 100644 index 00000000000..789275fa25e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28105.opt @@ -0,0 +1 @@ +--skip-log-bin diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_28105.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_28105.test new file mode 100644 index 00000000000..219835075ba --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_28105.test @@ -0,0 +1,8 @@ +install soname 'ha_spider'; +SET @@insert_id=128; # 127 does not crash +CREATE TABLE t(c TINYINT AUTO_INCREMENT KEY) ENGINE=Spider; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +INSERT IGNORE INTO t VALUES(0); +drop table t; +--disable_query_log +--source ../../include/clean_up_spider.inc diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29027.cnf b/storage/spider/mysql-test/spider/bugfix/t/mdev_29027.cnf new file mode 100644 index 00000000000..05dfd8a0bce --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29027.cnf @@ -0,0 +1,3 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29027.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29027.test new file mode 100644 index 00000000000..f18154a1d28 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29027.test @@ -0,0 +1,28 @@ +--echo # +--echo # MDEV-29027 ASAN errors in spider_db_free_result after partition DDL +--echo # + +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +CREATE DATABASE auto_test_local; +USE auto_test_local; + +eval CREATE TABLE tbl_a ( + c INT +) $MASTER_1_ENGINE $MASTER_1_CHARSET PARTITION BY HASH(c) ( + PARTITION pt1 +); + +ALTER TABLE tbl_a ADD PARTITION (PARTITION pt2); + +DROP DATABASE auto_test_local; + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_29027_original.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_29027_original.test new file mode 100644 index 00000000000..3a52c11c834 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_29027_original.test @@ -0,0 +1,22 @@ +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log +--source include/have_partition.inc +set spider_same_server_link= 1; +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); + +CREATE TABLE t1 (a INT); +CREATE TABLE t_spider (a INT) ENGINE=SPIDER PARTITION BY HASH(a) (PARTITION p1 COMMENT = "wrapper 'mysql', srv 'srv', table 't1'"); +CREATE TABLE t2 (a INT); +ALTER TABLE t_spider ADD PARTITION (PARTITION p2 COMMENT = "wrapper 'mysql', srv 'srv', table 't2'"); + +DROP TABLE t_spider, t1, t2; +drop server srv; +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_31475.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_31475.test new file mode 100644 index 00000000000..6794e9df19e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_31475.test @@ -0,0 +1,32 @@ +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +# test 1 +CREATE TABLE t3 (c1 MEDIUMINT NULL, c2 CHAR(5)) ENGINE=Spider PARTITION BY KEY(c1) PARTITIONS 2; +--error ER_CANT_DROP_FIELD_OR_KEY +ALTER TABLE t3 DROP PRIMARY KEY; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +SELECT * FROM t3 WHERE c1 <=> '1000-00-01 00:00:00' ORDER BY c1,c2 LIMIT 2; +CREATE TABLE t1 (a INT UNSIGNED NOT NULL PRIMARY KEY, b INT UNSIGNED NOT NULL, c INT UNSIGNED, UNIQUE (b, c) USING HASH) ENGINE=Spider; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +SELECT t1.c1 FROM t3 RIGHT JOIN t1 ON t1.c1=current_date() UNION SELECT t1.c2 FROM t1 LEFT OUTER JOIN t3 ON t1.c2; +drop table t1, t3; + +# test 2 +set spider_same_server_link= 1; +evalp CREATE SERVER srv FOREIGN DATA WRAPPER mysql +OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +CREATE TABLE t1 (a INT, b VARCHAR(255), PRIMARY KEY(a)) ENGINE=Spider PARTITION BY RANGE (a) (PARTITION p1 VALUES LESS THAN (3), PARTITION p2 VALUES LESS THAN MAXVALUE COMMENT='srv "srv"'); +DROP SERVER srv; +--error 1477 +SELECT * FROM t1; +drop table t1; + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_34002.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_34002.test new file mode 100644 index 00000000000..575a306589d --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_34002.test @@ -0,0 +1,7 @@ +INSTALL PLUGIN Spider SONAME 'ha_spider.so'; +CREATE TABLE t (c DATE, c2 VARCHAR(1025) CHARACTER SET utf8mb3, UNIQUE KEY k(c2)) ENGINE=SPIDER; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +UPDATE t SET c='2'; +drop table t; +--disable_query_log +--source ../../include/clean_up_spider.inc diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index 5f816d47b70..abb7f187de0 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -2857,7 +2857,7 @@ int spider_db_free_result( SPIDER_RESULT *result; SPIDER_RESULT *prev; SPIDER_SHARE *share = spider->share; - SPIDER_TRX *trx = spider->wide_handler->trx; + THD *thd= current_thd; SPIDER_POSITION *position; int roop_count, error_num; DBUG_ENTER("spider_db_free_result"); @@ -2873,10 +2873,10 @@ int spider_db_free_result( if ( final || - spider_param_reset_sql_alloc(trx->thd, share->reset_sql_alloc) == 1 + spider_param_reset_sql_alloc(thd, share->reset_sql_alloc) == 1 ) { int alloc_size = final ? 0 : - (spider_param_init_sql_alloc_size(trx->thd, share->init_sql_alloc_size)); + (spider_param_init_sql_alloc_size(thd, share->init_sql_alloc_size)); while (result) { position = result->first_position; @@ -2919,7 +2919,7 @@ int spider_db_free_result( { ulong realloced = 0; int init_sql_alloc_size = - spider_param_init_sql_alloc_size(trx->thd, share->init_sql_alloc_size); + spider_param_init_sql_alloc_size(thd, share->init_sql_alloc_size); for (roop_count = 0; roop_count < (int) share->use_dbton_count; roop_count++) { diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index 87985584b60..c65e27f2e64 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -1111,8 +1111,8 @@ public: spider_db_share *db_share; int first_link_idx; SPIDER_LINK_IDX_CHAIN *link_idx_chain; - bool strict_group_by; - bool no_where_cond; + bool strict_group_by= false; + bool no_where_cond= false; spider_db_handler(ha_spider *spider, spider_db_share *db_share) : dbton_id(db_share->dbton_id), spider(spider), db_share(db_share), first_link_idx(-1) {} diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 8ff45022153..1a44e4b89f8 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -320,7 +320,7 @@ SPIDER_DBTON spider_dbton_mysql = { spider_mysql_create_conn, spider_mysql_support_direct_join, &spider_db_mysql_utility, - "For communicating to MySQL using native protocol", + "For communication with MySQL using the native protocol", "3.4.0", SPIDER_MATURITY_STABLE }; @@ -337,7 +337,7 @@ SPIDER_DBTON spider_dbton_mariadb = { spider_mariadb_create_conn, spider_mariadb_support_direct_join, &spider_db_mariadb_utility, - "For communicating to MariaDB using native protocol", + "For communication with MariaDB using the native protocol", "3.4.0", SPIDER_MATURITY_STABLE }; diff --git a/storage/spider/spd_err.h b/storage/spider/spd_err.h index 823a367ba3a..67fcd0d5d9c 100644 --- a/storage/spider/spd_err.h +++ b/storage/spider/spd_err.h @@ -84,13 +84,13 @@ #define ER_SPIDER_XA_PREPARED_NUM 12604 #define ER_SPIDER_XA_PREPARED_STR "This xid is prepared" #define ER_SPIDER_XA_EXISTS_NUM 12605 -#define ER_SPIDER_XA_EXISTS_STR "This xid is already exist" +#define ER_SPIDER_XA_EXISTS_STR "This xid already exists" #define ER_SPIDER_XA_MEMBER_EXISTS_NUM 12606 -#define ER_SPIDER_XA_MEMBER_EXISTS_STR "This xid member is already exist" +#define ER_SPIDER_XA_MEMBER_EXISTS_STR "This xid member already exists" #define ER_SPIDER_XA_NOT_EXISTS_NUM 12607 -#define ER_SPIDER_XA_NOT_EXISTS_STR "This xid is not exist" +#define ER_SPIDER_XA_NOT_EXISTS_STR "This xid does not exist" #define ER_SPIDER_XA_MEMBER_NOT_EXISTS_NUM 12608 -#define ER_SPIDER_XA_MEMBER_NOT_EXISTS_STR "This xid member is not exist" +#define ER_SPIDER_XA_MEMBER_NOT_EXISTS_STR "This xid member does not exist" #define ER_SPIDER_SYS_TABLE_VERSION_NUM 12609 #define ER_SPIDER_SYS_TABLE_VERSION_STR "System table %s is different version" #define ER_SPIDER_WRONG_CHARACTER_IN_NAME_NUM 12611 diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index 33fd26af4b4..d829bb4ebfc 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -847,6 +847,10 @@ enum spider_hnd_stage { SPD_HND_STAGE_CLEAR_TOP_TABLE_FIELDS }; +/* + A wide handler is shared among ha_spider of partitions of the same + table. It is owned by the last partition. +*/ typedef struct st_spider_wide_handler { spider_hnd_stage stage; diff --git a/strings/ctype.c b/strings/ctype.c index 3d13fe55be8..a0b51c20b10 100644 --- a/strings/ctype.c +++ b/strings/ctype.c @@ -871,7 +871,7 @@ static void my_string_metadata_get_mb(MY_STRING_METADATA *metadata, CHARSET_INFO *cs, const char *str, ulong length) { - const char *strend= str + length; + const char *strend= str ? str + length : NULL; // Avoid UB nullptr+0 for (my_string_metadata_init(metadata) ; str < strend; metadata->char_length++) diff --git a/strings/my_strtoll10.c b/strings/my_strtoll10.c index 183829d7074..74baef080eb 100644 --- a/strings/my_strtoll10.c +++ b/strings/my_strtoll10.c @@ -241,7 +241,7 @@ end4: *endptr= (char*) s; if (negative) { - if (li > MAX_NEGATIVE_NUMBER) + if (li >= MAX_NEGATIVE_NUMBER) // Avoid undefined behavior goto overflow; return -((longlong) li); } diff --git a/tpool/tpool_generic.cc b/tpool/tpool_generic.cc index a4d6c405bdf..774576d5cde 100644 --- a/tpool/tpool_generic.cc +++ b/tpool/tpool_generic.cc @@ -244,7 +244,7 @@ class thread_pool_generic : public thread_pool unsigned int m_concurrency; /** True, if threadpool is being shutdown, false otherwise */ - bool m_in_shutdown; + bool m_in_shutdown= false; /** Maintenance timer state : true = active(ON),false = inactive(OFF)*/ enum class timer_state_t @@ -813,7 +813,6 @@ thread_pool_generic::thread_pool_generic(int min_threads, int max_threads) : m_wakeups(), m_spurious_wakeups(), m_timer_state(timer_state_t::ON), - m_in_shutdown(), m_timestamp(), m_long_tasks_count(), m_waiting_task_count(), diff --git a/wsrep-lib b/wsrep-lib index dfc4bdb8a5d..31db8476768 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit dfc4bdb8a5dcbd6fbea007ad3beff899a6b5b7bd +Subproject commit 31db8476768ba68296ad91b6785bb06a6a9abf71