diff options
871 files changed, 28550 insertions, 9724 deletions
diff --git a/.gitignore b/.gitignore index 92c58cc781e..4c7efe9a119 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,9 @@ include/mysql_version.h include/mysqld_ername.h include/mysqld_error.h include/sql_state.h +include/probes_mysql.d +include/probes_mysql_dtrace.h +include/probes_mysql_nodtrace.h info_macros.cmake libmysql*/libmysql*_exports_file.cc libmysql*/merge_archives_mysql*.cmake @@ -112,6 +115,8 @@ scripts/wsrep_sst_mysqldump scripts/wsrep_sst_rsync scripts/wsrep_sst_xtrabackup scripts/wsrep_sst_xtrabackup-v2 +scripts/maria_add_gis_sp.sql +scripts/maria_add_gis_sp_bootstrap.sql sql-bench/bench-count-distinct sql-bench/bench-init.pl sql-bench/compare-results diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index f443c5da680..36072ebaa7e 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -31,6 +31,7 @@ Usage: $0 [-h|-n] [configure-options] -h, --help Show this help message. -n, --just-print Don't actually run any commands; just print them. -c, --just-configure Stop after running configure. + Combined with --just-print shows configure options. --extra-configs=xxx Add this to configure options --extra-flags=xxx Add this C and CXX flags --extra-cflags=xxx Add this to C flags diff --git a/CMakeLists.txt b/CMakeLists.txt index 0584492def3..5f8ae5b2d9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -348,11 +348,9 @@ IF(WITH_UNIT_TESTS) ENDIF() ENDIF() -IF(NOT WITHOUT_SERVER) - SET (MYSQLD_STATIC_PLUGIN_LIBS "" CACHE INTERNAL "") - # Add storage engines and plugins. - CONFIGURE_PLUGINS() -ENDIF() +SET (MYSQLD_STATIC_PLUGIN_LIBS "" CACHE INTERNAL "") +# Add storage engines and plugins. +CONFIGURE_PLUGINS() ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(dbug) @@ -382,6 +380,10 @@ IF(NOT WITHOUT_SERVER) ADD_SUBDIRECTORY(mysql-test) ADD_SUBDIRECTORY(mysql-test/lib/My/SafeProcess) ADD_SUBDIRECTORY(sql-bench) + IF(WIN32) + ADD_SUBDIRECTORY(win/upgrade_wizard) + ADD_SUBDIRECTORY(win/packaging) + ENDIF() ENDIF() IF(UNIX) @@ -391,10 +393,7 @@ ENDIF() INCLUDE(cmake/abi_check.cmake) INCLUDE(cmake/tags.cmake) -IF(WIN32) - ADD_SUBDIRECTORY(win/upgrade_wizard) - ADD_SUBDIRECTORY(win/packaging) -ENDIF() + INCLUDE(for_clients) @@ -1,25 +1,30 @@ -MariaDB is brought to you by the MariaDB foundation, a USA non profit -organization. +MariaDB is brought to you by the MariaDB Foundation, a non profit +organization registered in the USA. -The current main members and sponsors of the MariaDB foundation are: +The current main members and sponsors of the MariaDB Foundation are: -Automattic http://automattic.com (2014) -SkySQL Ab http://www.skysql.com (2013, 2014) -Booking.com http://www.booking.com (2013) -Parallels http://www.parallels.com/products/plesk (2013) +MariaDB Corporation http://www.mariadb.com (2013 - 2016) +Booking.com http://www.booking.com (2013 - 2016) +Parallels http://www.parallels.com/products/plesk (2013 - 2016) +Automattic http://automattic.com (2014 - 2016) +Verkkokauppa.com http://verkkokauppa.com (2015 - 2016) +Visma http://visma.com/ (2015 - 2016) +Webyog http://webyog.com (2015 - 2016) +Wikimedia Foundation http://wikimedia.org (2015 - 2016) +Acronis http://acronis.com (2016) For a full list of supporters and sponsors see -https://mariadb.org/en/supporters/ +https://mariadb.org/about/supporters/ -You can also do this by doing SHOW CONTRIBUTORS. +You can also do this by running SHOW CONTRIBUTORS. For all corporate memberships and sponsorships please contact the -MariaDB foundation Board via foundation@mariadb.org. +MariaDB Foundation Board via foundation@mariadb.org. -The MariaDB foundation is responsible for the MariaDB source +The MariaDB Foundation is responsible for the MariaDB source repository, the official MariaDB binaries and http://mariadb.org. -The MariaDB foundation provides also, among other things, the +The MariaDB Foundation also provides, among other things, the following services to the MariaDB community: - Code reviews and applying patches for MariaDB @@ -28,17 +33,19 @@ following services to the MariaDB community: - Bug fixing in MariaDB (for bugs that affects a large part of the community) - Building the official MariaDB binaries - Maintaining http://mariadb.org +- Documenting MariaDB in the MariaDB Knowledge Base http://mariadb.com/kb -To be able to do the above we need help from cooperations and individuals! +To be able to do the above we need help from corporations and individuals! -You can help support MariaDB by be becoming a MariaDB developer or a -member or sponsor of the MariaDB foundation! +You can help support MariaDB by becoming a MariaDB developer or a +member or sponsor of the MariaDB Foundation. To donate or sponsor, +go to https://mariadb.org/donate/ -You can get a list of all main authors of MariaDB / MySQL by doing +You can get a list of all the main authors of MariaDB / MySQL by running SHOW AUTHORS; -You can get a list sponsors and contributors by doing +You can get a list sponsors and contributors by running SHOW CONTRIBUTORS; -You can read more about the MariaDB foundation at: -https://mariadb.org/en/foundation/ +You can read more about the MariaDB Foundation at: +https://mariadb.org/about/ diff --git a/Docs/mysql.info b/Docs/mysql.info index 684c0d23437..02692f341d3 100644 --- a/Docs/mysql.info +++ b/Docs/mysql.info @@ -1,11 +1,11 @@ MariaDB is in most aspects identical to MySQL. Differences between MySQL and MariaDB can be found at: -http://kb.askmonty.org/en/mariadb-versus-mysql-features/ -http://kb.askmonty.org/en/mariadb-versus-mysql-compatibility/ +https://mariadb.com/kb/en/mariadb-vs-mysql-features/ +https://mariadb.com/kb/en/mariadb-vs-mysql-compatibility/ The MariaDB manual can be found at: -http://kb.askmonty.org/ +https://mariadb.com/kb/ The MySQL Reference Manual is available in various formats on http://dev.mysql.com/doc. diff --git a/Docs/sp-imp-spec.txt b/Docs/sp-imp-spec.txt index 9795dd72252..259d76ab5bb 100644 --- a/Docs/sp-imp-spec.txt +++ b/Docs/sp-imp-spec.txt @@ -243,7 +243,7 @@ in the caller's frame is set in the new context as well. 4) For each instruction, call its execute() method. The result is a pointer to the next instruction to execute (or NULL) - if an error occured. + if an error occurred. 5) On success, set the new values of the OUT and INOUT parameters in the caller's frame. @@ -853,7 +853,7 @@ // '*nextp' will be set to the index of the next instruction // to execute. (For most instruction this will be the // instruction following this one.) - // Returns 0 on success, non-zero if some error occured. + // Returns 0 on success, non-zero if some error occurred. virtual int execute(THD *, uint *nextp) } diff --git a/INSTALL-SOURCE b/INSTALL-SOURCE index 32cfa9792a7..93c985f2c1d 100644 --- a/INSTALL-SOURCE +++ b/INSTALL-SOURCE @@ -1,3 +1,3 @@ Instructions for building MariaDB can be found at: -https://kb.askmonty.org/en/compiling-mariadb-from-source/ +https://mariadb.com/kb/en/compiling-mariadb-from-source diff --git a/INSTALL-WIN-SOURCE b/INSTALL-WIN-SOURCE index 269bc2c3d1c..f10d13aa93b 100644 --- a/INSTALL-WIN-SOURCE +++ b/INSTALL-WIN-SOURCE @@ -1,3 +1,3 @@ Up-to-date instructions about building MariaDB on Windows can be found -at: http://kb.askmonty.org/en/building-mariadb-on-windows +at: https://mariadb.com/kb/en/Building_MariaDB_on_Windows @@ -1,17 +1,17 @@ MariaDB is designed as a drop-in replacement of MySQL(R) with more features, new storage engines, fewer bugs, and better performance. -MariaDB is brought to you by the MariaDB foundation. -Please read the file CREDITS for details about the MariaDB foundation, +MariaDB is brought to you by the MariaDB Foundation. +Please read the CREDITS file for details about the MariaDB Foundation, and who is developing MariaDB. MariaDB is developed by many of the original developers of MySQL who -now work for MariadB foundation and SkySQL Ab, and by many people in +now work for the MariadB Foundation and the MariaDB Corporation, and by many people in the community. MySQL, which is the base of MariaDB, is a product and trademark of Oracle Corporation, Inc. For a list of developers and other contributors, -see the Credits appendix. You can also do 'SHOW authors' to get a +see the Credits appendix. You can also run 'SHOW authors' to get a list of active contributors. A description of the MariaDB project and a manual can be found at: @@ -1,4 +1,3 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=2 MYSQL_VERSION_PATCH=0 -MYSQL_VERSION_EXTRA= diff --git a/client/mysql.cc b/client/mysql.cc index 3e08c87aea1..9c6320fe10a 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1344,6 +1344,44 @@ sig_handler mysql_end(int sig) exit(status.exit_status); } +/* + set connection-specific options and call mysql_real_connect +*/ +static bool do_connect(MYSQL *mysql, const char *host, const char *user, + const char *password, const char *database, ulong flags) +{ + if (opt_secure_auth) + mysql_options(mysql, MYSQL_SECURE_AUTH, (char *) &opt_secure_auth); +#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) + if (opt_use_ssl) + { + mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, + opt_ssl_capath, opt_ssl_cipher); + mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); + } + mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, + (char*)&opt_ssl_verify_server_cert); +#endif + if (opt_protocol) + mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); +#ifdef HAVE_SMEM + if (shared_memory_base_name) + mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); +#endif + if (opt_plugin_dir && *opt_plugin_dir) + mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir); + + if (opt_default_auth && *opt_default_auth) + mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth); + + mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0); + mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, + "program_name", "mysql"); + return mysql_real_connect(mysql, host, user, password, database, + opt_mysql_port, opt_mysql_unix_port, flags); +} + /* This function handles sigint calls @@ -1365,11 +1403,7 @@ sig_handler handle_sigint(int sig) } kill_mysql= mysql_init(kill_mysql); - mysql_options(kill_mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0); - mysql_options4(kill_mysql, MYSQL_OPT_CONNECT_ATTR_ADD, - "program_name", "mysql"); - if (!mysql_real_connect(kill_mysql,current_host, current_user, opt_password, - "", opt_mysql_port, opt_mysql_unix_port,0)) + if (!do_connect(kill_mysql,current_host, current_user, opt_password, "", 0)) { tee_fprintf(stdout, "Ctrl-C -- sorry, cannot connect to server to kill query, giving up ...\n"); goto err; @@ -1921,7 +1955,7 @@ static int get_options(int argc, char **argv) connect_flag|= CLIENT_IGNORE_SPACE; if (opt_progress_reports) - connect_flag|= CLIENT_PROGRESS; + connect_flag|= CLIENT_PROGRESS_OBSOLETE; return(0); } @@ -3320,7 +3354,7 @@ com_go(String *buffer,char *line __attribute__((unused))) end: - /* Show warnings if any or error occured */ + /* Show warnings if any or error occurred */ if (show_warnings == 1 && (warnings >= 1 || error)) print_warnings(); @@ -4575,27 +4609,8 @@ sql_real_connect(char *host,char *database,char *user,char *password, } if (opt_compress) mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS); - if (opt_secure_auth) - mysql_options(&mysql, MYSQL_SECURE_AUTH, (char *) &opt_secure_auth); if (using_opt_local_infile) mysql_options(&mysql,MYSQL_OPT_LOCAL_INFILE, (char*) &opt_local_infile); -#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) - if (opt_use_ssl) - { - mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, - opt_ssl_capath, opt_ssl_cipher); - mysql_options(&mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); - mysql_options(&mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); - } - mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT, - (char*)&opt_ssl_verify_server_cert); -#endif - if (opt_protocol) - mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); -#ifdef HAVE_SMEM - if (shared_memory_base_name) - mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); -#endif if (safe_updates) { char init_command[100]; @@ -4607,18 +4622,8 @@ sql_real_connect(char *host,char *database,char *user,char *password, mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); - if (opt_plugin_dir && *opt_plugin_dir) - mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir); - - if (opt_default_auth && *opt_default_auth) - mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth); - - mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0); - mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD, - "program_name", "mysql"); - if (!mysql_real_connect(&mysql, host, user, password, - database, opt_mysql_port, opt_mysql_unix_port, - connect_flag | CLIENT_MULTI_STATEMENTS)) + if (!do_connect(&mysql, host, user, password, database, + connect_flag | CLIENT_MULTI_STATEMENTS)) { if (!silent || (mysql_errno(&mysql) != CR_CONN_HOST_ERROR && @@ -4638,10 +4643,10 @@ sql_real_connect(char *host,char *database,char *user,char *password, mysql.reconnect= debug_info_flag; // We want to know if this happens /* - CLIENT_PROGRESS is set only if we requsted it in mysql_real_connect() - and the server also supports it + CLIENT_PROGRESS_OBSOLETE is set only if we requested it in + mysql_real_connect() and the server also supports it */ - if (mysql.client_flag & CLIENT_PROGRESS) + if (mysql.client_flag & CLIENT_PROGRESS_OBSOLETE) mysql_options(&mysql, MYSQL_PROGRESS_CALLBACK, (void*) report_progress); #else mysql.reconnect= 1; diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 1062c6bd45d..cdeaebf478f 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -184,7 +184,8 @@ static const char *load_default_groups[]= static void free_used_memory(void) { /* Free memory allocated by 'load_defaults' */ - free_defaults(defaults_argv); + if (defaults_argv) + free_defaults(defaults_argv); dynstr_free(&ds_args); dynstr_free(&conn_args); @@ -657,7 +658,7 @@ static int get_upgrade_info_file_name(char* name) /* Read the content of mysql_upgrade_info file and compare the version number form file against - version number wich mysql_upgrade was compiled for + version number which mysql_upgrade was compiled for NOTE This is an optimization to avoid running mysql_upgrade @@ -1110,7 +1111,6 @@ int main(int argc, char **argv) if (opt_systables_only && !opt_silent) printf("The --upgrade-system-tables option was used, user tables won't be touched.\n"); - /* Read the mysql_upgrade_info file to check if mysql_upgrade already has been run for this installation of MySQL diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 59912d0c91d..0463a9857bc 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -73,6 +73,8 @@ ulong opt_binlog_rows_event_max_size; uint test_flags = 0; static uint opt_protocol= 0; static FILE *result_file; +static char *result_file_name= 0; +static const char *output_prefix= ""; #ifndef DBUG_OFF static const char* default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace"; @@ -96,6 +98,8 @@ static char* database= 0; static my_bool force_opt= 0, short_form= 0, remote_opt= 0; static my_bool debug_info_flag, debug_check_flag; static my_bool force_if_open_opt= 1; +static my_bool opt_raw_mode= 0, opt_stop_never= 0; +static ulong opt_stop_never_slave_server_id= 0; static my_bool opt_verify_binlog_checksum= 1; static ulonglong offset = 0; static char* host = 0; @@ -120,7 +124,6 @@ static ulonglong start_position, stop_position; static char *start_datetime_str, *stop_datetime_str; static my_time_t start_datetime= 0, stop_datetime= MY_TIME_T_MAX; static ulonglong rec_count= 0; -static short binlog_flags = 0; static MYSQL* mysql = NULL; static const char* dirname_for_local_load= 0; static bool opt_skip_annotate_row_events= 0; @@ -142,7 +145,9 @@ enum Exit_status { /** An error occurred and execution should stop. */ ERROR_STOP, /** No error occurred but execution should stop. */ - OK_STOP + OK_STOP, + /** No error occurred - end of file reached. */ + OK_EOF, }; /** @@ -1368,8 +1373,14 @@ static struct my_option my_options[] = {"read-from-remote-server", 'R', "Read binary logs from a MySQL server.", &remote_opt, &remote_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"raw", 0, "Requires -R. Output raw binlog data instead of SQL " + "statements. Output files named after server logs.", + &opt_raw_mode, &opt_raw_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + 0, 0}, + {"result-file", 'r', "Direct output to a given file. With --raw this is a " + "prefix for the file names.", + &result_file_name, &result_file_name, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, {"server-id", 0, "Extract only binlog entries created by the server having the given id.", &server_id, &server_id, 0, GET_ULONG, @@ -1418,6 +1429,14 @@ static struct my_option my_options[] = "(you should probably use quotes for your shell to set it properly).", &stop_datetime_str, &stop_datetime_str, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"stop-never", 0, "Wait for more data from the server " + "instead of stopping at the end of the last log. Implies --to-last-log.", + &opt_stop_never, &opt_stop_never, 0, + GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"stop-never-slave-server-id", 0, + "The slave server_id used for --read-from-remote-server --stop-never.", + &opt_stop_never_slave_server_id, &opt_stop_never_slave_server_id, 0, + GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"stop-position", OPT_STOP_POSITION, "Stop reading the binlog at position N. Applies to the last binlog " "passed on the command line.", @@ -1620,10 +1639,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), else tty_password=1; break; - case 'r': - if (!(result_file = my_fopen(argument, O_WRONLY | O_BINARY, MYF(MY_WME)))) - exit(1); - break; case 'R': remote_opt= 1; break; @@ -1719,7 +1734,6 @@ static int parse_args(int *argc, char*** argv) { int ho_error; - result_file = stdout; if ((ho_error=handle_options(argc, argv, my_options, get_one_option))) exit(ho_error); if (debug_info_flag) @@ -1809,7 +1823,8 @@ static Exit_status dump_log_entries(const char* logname) Set safe delimiter, to dump things like CREATE PROCEDURE safely */ - fprintf(result_file, "DELIMITER /*!*/;\n"); + if (!opt_raw_mode) + fprintf(result_file, "DELIMITER /*!*/;\n"); strmov(print_event_info.delimiter, "/*!*/;"); print_event_info.verbose= short_form ? 0 : verbose; @@ -1818,7 +1833,8 @@ static Exit_status dump_log_entries(const char* logname) dump_local_log_entries(&print_event_info, logname)); /* Set delimiter back to semicolon */ - fprintf(result_file, "DELIMITER ;\n"); + if (!opt_raw_mode) + fprintf(result_file, "DELIMITER ;\n"); strmov(print_event_info.delimiter, ";"); return rc; } @@ -1924,6 +1940,247 @@ err: } +static Exit_status handle_event_text_mode(PRINT_EVENT_INFO *print_event_info, + ulong *len, + const char* logname, + uint logname_len, my_off_t old_off) +{ + const char *error_msg; + Log_event *ev; + NET *net= &mysql->net; + DBUG_ENTER("handle_event_text_mode"); + + if (net->read_pos[5] == ANNOTATE_ROWS_EVENT) + { + if (!(ev= read_remote_annotate_event(net->read_pos + 1, *len - 1, + &error_msg))) + { + error("Could not construct annotate event object: %s", error_msg); + DBUG_RETURN(ERROR_STOP); + } + } + else + { + if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 , + *len - 1, &error_msg, + glob_description_event, + opt_verify_binlog_checksum))) + { + error("Could not construct log event object: %s", error_msg); + DBUG_RETURN(ERROR_STOP); + } + /* + If reading from a remote host, ensure the temp_buf for the + Log_event class is pointing to the incoming stream. + */ + ev->register_temp_buf((char *) net->read_pos + 1, FALSE); + } + + Log_event_type type= ev->get_type_code(); + if (glob_description_event->binlog_version >= 3 || + (type != LOAD_EVENT && type != CREATE_FILE_EVENT)) + { + /* + If this is a Rotate event, maybe it's the end of the requested binlog; + in this case we are done (stop transfer). + This is suitable for binlogs, not relay logs (but for now we don't read + relay logs remotely because the server is not able to do that). If one + day we read relay logs remotely, then we will have a problem with the + detection below: relay logs contain Rotate events which are about the + binlogs, so which would trigger the end-detection below. + */ + if (type == ROTATE_EVENT) + { + Rotate_log_event *rev= (Rotate_log_event *)ev; + /* + If this is a fake Rotate event, and not about our log, we can stop + transfer. If this a real Rotate event (so it's not about our log, + it's in our log describing the next log), we print it (because it's + part of our log) and then we will stop when we receive the fake one + soon. + */ + if (rev->when == 0) + { + *len= 1; // fake Rotate, so don't increment old_off + if (!to_last_remote_log) + { + if ((rev->ident_len != logname_len) || + memcmp(rev->new_log_ident, logname, logname_len)) + { + delete ev; + DBUG_RETURN(OK_EOF); + } + /* + Otherwise, this is a fake Rotate for our log, at the very + beginning for sure. Skip it, because it was not in the original + log. If we are running with to_last_remote_log, we print it, + because it serves as a useful marker between binlogs then. + */ + delete ev; + DBUG_RETURN(OK_CONTINUE); + } + } + } + else if (type == FORMAT_DESCRIPTION_EVENT) + { + /* + This could be an fake Format_description_log_event that server + (5.0+) automatically sends to a slave on connect, before sending + a first event at the requested position. If this is the case, + don't increment old_off. Real Format_description_log_event always + starts from BIN_LOG_HEADER_SIZE position. + */ + if (old_off != BIN_LOG_HEADER_SIZE) + *len= 1; // fake event, don't increment old_off + } + Exit_status retval= process_event(print_event_info, ev, old_off, logname); + if (retval != OK_CONTINUE) + DBUG_RETURN(retval); + } + else + { + Load_log_event *le= (Load_log_event*)ev; + const char *old_fname= le->fname; + uint old_len= le->fname_len; + File file; + Exit_status retval; + char fname[FN_REFLEN+1]; + + if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0) + { + DBUG_RETURN(ERROR_STOP); + } + + retval= process_event(print_event_info, ev, old_off, logname); + if (retval != OK_CONTINUE) + { + my_close(file,MYF(MY_WME)); + DBUG_RETURN(retval); + } + retval= load_processor.load_old_format_file(net,old_fname,old_len,file); + my_close(file,MYF(MY_WME)); + if (retval != OK_CONTINUE) + DBUG_RETURN(retval); + } + + DBUG_RETURN(OK_CONTINUE); +} + + +static char out_file_name[FN_REFLEN + 1]; + +static Exit_status handle_event_raw_mode(PRINT_EVENT_INFO *print_event_info, + ulong *len, + const char* logname, uint logname_len) +{ + const char *error_msg; + const unsigned char *read_pos= mysql->net.read_pos + 1; + Log_event_type type; + DBUG_ENTER("handle_event_raw_mode"); + DBUG_ASSERT(opt_raw_mode && remote_opt); + + type= (Log_event_type) read_pos[EVENT_TYPE_OFFSET]; + + if (type == HEARTBEAT_LOG_EVENT) + DBUG_RETURN(OK_CONTINUE); + + if (type == ROTATE_EVENT || type == FORMAT_DESCRIPTION_EVENT) + { + Log_event *ev; + if (!(ev= Log_event::read_log_event((const char*) read_pos , + *len - 1, &error_msg, + glob_description_event, + opt_verify_binlog_checksum))) + { + error("Could not construct %s event object: %s", + type == ROTATE_EVENT ? "rotate" : "format description", error_msg); + DBUG_RETURN(ERROR_STOP); + } + /* + If reading from a remote host, ensure the temp_buf for the + Log_event class is pointing to the incoming stream. + */ + ev->register_temp_buf((char *) read_pos, FALSE); + + if (type == ROTATE_EVENT) + { + Exit_status ret_val= OK_CONTINUE; + Rotate_log_event *rev= (Rotate_log_event *)ev; + char *pe= strmake(out_file_name, output_prefix, sizeof(out_file_name)-1); + strmake(pe, rev->new_log_ident, sizeof(out_file_name) - (pe-out_file_name)); + + /* + If this is a fake Rotate event, and not about our log, we can stop + transfer. If this a real Rotate event (so it's not about our log, + it's in our log describing the next log), we print it (because it's + part of our log) and then we will stop when we receive the fake one + soon. + */ + if (rev->when == 0) + { + if (!to_last_remote_log) + { + if ((rev->ident_len != logname_len) || + memcmp(rev->new_log_ident, logname, logname_len)) + { + ret_val= OK_EOF; + } + /* + Otherwise, this is a fake Rotate for our log, at the very + beginning for sure. Skip it, because it was not in the original + log. If we are running with to_last_remote_log, we print it, + because it serves as a useful marker between binlogs then. + */ + } + *len= 1; // fake Rotate, so don't increment old_off + ev->temp_buf= 0; + delete ev; + DBUG_RETURN(ret_val); + } + ev->temp_buf= 0; + delete ev; + } + else /* if (type == FORMAT_DESCRIPTION_EVENT) */ + { + DBUG_ASSERT(type == FORMAT_DESCRIPTION_EVENT); + + if (result_file) + my_fclose(result_file, MYF(0)); + + if (!(result_file= my_fopen(out_file_name, + O_WRONLY | O_BINARY, MYF(MY_WME)))) + { + error("Could not create output log file: %s", out_file_name); + DBUG_RETURN(ERROR_STOP); + } + /* TODO - add write error simulation here */ + + if (my_fwrite(result_file, (const uchar *) BINLOG_MAGIC, + BIN_LOG_HEADER_SIZE, MYF(MY_NABP))) + { + error("Could not write into log file '%s'", out_file_name); + DBUG_RETURN(ERROR_STOP); + } + + delete glob_description_event; + glob_description_event= (Format_description_log_event*) ev; + print_event_info->common_header_len= + glob_description_event->common_header_len; + ev->temp_buf= 0; + /* We do not want to delete the event here. */ + } + } + + if (my_fwrite(result_file, read_pos, *len - 1, MYF(MY_NABP))) + { + error("Could not write into log file '%s'", out_file_name); + DBUG_RETURN(ERROR_STOP); + } + + DBUG_RETURN(OK_CONTINUE); +} + + /** Requests binlog dump from a remote server and prints the events it receives. @@ -1946,8 +2203,9 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, uint logname_len; NET* net; my_off_t old_off= start_position_mot; - char fname[FN_REFLEN+1]; Exit_status retval= OK_CONTINUE; + short binlog_flags = 0; + ulong slave_id; DBUG_ENTER("dump_remote_log_entries"); /* @@ -1970,6 +2228,9 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, int4store(buf, (uint32)start_position); if (!opt_skip_annotate_row_events) binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT; + if (!opt_stop_never) + binlog_flags|= BINLOG_DUMP_NON_BLOCK; + int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags); size_t tlen = strlen(logname); @@ -1979,7 +2240,15 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, DBUG_RETURN(ERROR_STOP); } logname_len = (uint) tlen; - int4store(buf + 6, 0); + if (opt_stop_never) + { + DBUG_ASSERT(to_last_remote_log); + slave_id= (opt_stop_never_slave_server_id == 0) ? + 1 : opt_stop_never_slave_server_id; + } + else + slave_id= 0; + int4store(buf + 6, slave_id); memcpy(buf + 10, logname, logname_len); if (simple_command(mysql, COM_BINLOG_DUMP, buf, logname_len + 10, 1)) { @@ -1989,9 +2258,6 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, for (;;) { - const char *error_msg; - Log_event *ev; - len= cli_safe_read(mysql); if (len == packet_error) { @@ -2002,117 +2268,23 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info, break; // end of data DBUG_PRINT("info",( "len: %lu net->read_pos[5]: %d\n", len, net->read_pos[5])); - if (net->read_pos[5] == ANNOTATE_ROWS_EVENT) + if (opt_raw_mode) { - if (!(ev= read_remote_annotate_event(net->read_pos + 1, len - 1, - &error_msg))) - { - error("Could not construct annotate event object: %s", error_msg); - DBUG_RETURN(ERROR_STOP); - } + retval= handle_event_raw_mode(print_event_info, &len, + logname, logname_len); } else { - if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 , - len - 1, &error_msg, - glob_description_event, - opt_verify_binlog_checksum))) - { - error("Could not construct log event object: %s", error_msg); - DBUG_RETURN(ERROR_STOP); - } - /* - If reading from a remote host, ensure the temp_buf for the - Log_event class is pointing to the incoming stream. - */ - ev->register_temp_buf((char *) net->read_pos + 1, FALSE); + retval= handle_event_text_mode(print_event_info, &len, + logname, logname_len, old_off); } - - Log_event_type type= ev->get_type_code(); - if (glob_description_event->binlog_version >= 3 || - (type != LOAD_EVENT && type != CREATE_FILE_EVENT)) + if (retval != OK_CONTINUE) { - /* - If this is a Rotate event, maybe it's the end of the requested binlog; - in this case we are done (stop transfer). - This is suitable for binlogs, not relay logs (but for now we don't read - relay logs remotely because the server is not able to do that). If one - day we read relay logs remotely, then we will have a problem with the - detection below: relay logs contain Rotate events which are about the - binlogs, so which would trigger the end-detection below. - */ - if (type == ROTATE_EVENT) - { - Rotate_log_event *rev= (Rotate_log_event *)ev; - /* - If this is a fake Rotate event, and not about our log, we can stop - transfer. If this a real Rotate event (so it's not about our log, - it's in our log describing the next log), we print it (because it's - part of our log) and then we will stop when we receive the fake one - soon. - */ - if (rev->when == 0) - { - if (!to_last_remote_log) - { - if ((rev->ident_len != logname_len) || - memcmp(rev->new_log_ident, logname, logname_len)) - { - delete ev; - DBUG_RETURN(OK_CONTINUE); - } - /* - Otherwise, this is a fake Rotate for our log, at the very - beginning for sure. Skip it, because it was not in the original - log. If we are running with to_last_remote_log, we print it, - because it serves as a useful marker between binlogs then. - */ - delete ev; - continue; - } - len= 1; // fake Rotate, so don't increment old_off - } - } - else if (type == FORMAT_DESCRIPTION_EVENT) - { - /* - This could be an fake Format_description_log_event that server - (5.0+) automatically sends to a slave on connect, before sending - a first event at the requested position. If this is the case, - don't increment old_off. Real Format_description_log_event always - starts from BIN_LOG_HEADER_SIZE position. - */ - if (old_off != BIN_LOG_HEADER_SIZE) - len= 1; // fake event, don't increment old_off - } - Exit_status retval= process_event(print_event_info, ev, old_off, logname); - if (retval != OK_CONTINUE) - DBUG_RETURN(retval); + if (retval == OK_EOF) + break; + DBUG_RETURN(retval); } - else - { - Load_log_event *le= (Load_log_event*)ev; - const char *old_fname= le->fname; - uint old_len= le->fname_len; - File file; - Exit_status retval; - - if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0) - { - DBUG_RETURN(ERROR_STOP); - } - retval= process_event(print_event_info, ev, old_off, logname); - if (retval != OK_CONTINUE) - { - my_close(file,MYF(MY_WME)); - DBUG_RETURN(retval); - } - retval= load_processor.load_old_format_file(net,old_fname,old_len,file); - my_close(file,MYF(MY_WME)); - if (retval != OK_CONTINUE) - DBUG_RETURN(retval); - } /* Let's adjust offset for remote log as for local log to produce similar text and to have --stop-position to work identically. @@ -2449,6 +2621,7 @@ end: return retval; } + int main(int argc, char** argv) { char **defaults_argv; @@ -2495,6 +2668,43 @@ int main(int argc, char** argv) my_set_max_open_files(open_files_limit); + if (opt_stop_never) + to_last_remote_log= TRUE; + + if (opt_raw_mode) + { + if (!remote_opt) + { + error("The --raw mode only works with --read-from-remote-server"); + exit(1); + } + if (one_database) + warning("The --database option is ignored in raw mode"); + + if (stop_position != (ulonglong)(~(my_off_t)0)) + warning("The --stop-position option is ignored in raw mode"); + + if (stop_datetime != MY_TIME_T_MAX) + warning("The --stop-datetime option is ignored in raw mode"); + result_file= 0; + if (result_file_name) + output_prefix= result_file_name; + } + else + { + if (result_file_name) + { + if (!(result_file= my_fopen(result_file_name, + O_WRONLY | O_BINARY, MYF(MY_WME)))) + { + error("Could not create log file '%s'", result_file_name); + exit(1); + } + } + else + result_file= stdout; + } + MY_TMPDIR tmpdir; tmpdir.list= 0; if (!dirname_for_local_load) @@ -2517,29 +2727,32 @@ int main(int argc, char** argv) else load_processor.init_by_cur_dir(); - fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;\n"); - - fprintf(result_file, - "/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n"); + if (!opt_raw_mode) + { + fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;\n"); - if (disable_log_bin) fprintf(result_file, - "/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n"); + "/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n"); - /* - In mysqlbinlog|mysql, don't want mysql to be disconnected after each - transaction (which would be the case with GLOBAL.COMPLETION_TYPE==2). - */ - fprintf(result_file, - "/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE," - "COMPLETION_TYPE=0*/;\n"); + if (disable_log_bin) + fprintf(result_file, + "/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n"); - if (charset) + /* + In mysqlbinlog|mysql, don't want mysql to be disconnected after each + transaction (which would be the case with GLOBAL.COMPLETION_TYPE==2). + */ fprintf(result_file, - "\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;" - "\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;" - "\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;" - "\n/*!40101 SET NAMES %s */;\n", charset); + "/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE," + "COMPLETION_TYPE=0*/;\n"); + + if (charset) + fprintf(result_file, + "\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;" + "\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;" + "\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;" + "\n/*!40101 SET NAMES %s */;\n", charset); + } for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ; (--argc >= 0) ; ) @@ -2553,27 +2766,30 @@ int main(int argc, char** argv) start_position= BIN_LOG_HEADER_SIZE; } - /* - Issue a ROLLBACK in case the last printed binlog was crashed and had half - of transaction. - */ - fprintf(result_file, - "# End of log file\nROLLBACK /* added by mysqlbinlog */;\n" - "/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n"); - if (disable_log_bin) - fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n"); - - if (charset) + if (!opt_raw_mode) + { + /* + Issue a ROLLBACK in case the last printed binlog was crashed and had half + of transaction. + */ fprintf(result_file, - "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n" - "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n" - "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n"); - - fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;\n"); + "# End of log file\nROLLBACK /* added by mysqlbinlog */;\n" + "/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n"); + if (disable_log_bin) + fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n"); + + if (charset) + fprintf(result_file, + "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n" + "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n" + "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n"); + + fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;\n"); + } if (tmpdir.list) free_tmpdir(&tmpdir); - if (result_file != stdout) + if (result_file && result_file != stdout) my_fclose(result_file, MYF(0)); cleanup(); free_annotate_event(); diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 9b7e1b6c8d4..627fbcb1873 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -277,8 +277,8 @@ static void usage(void) printf("Usage: %s [OPTIONS] database [tables]\n", my_progname); printf("OR %s [OPTIONS] --databases DB1 [DB2 DB3...]\n", my_progname); - puts("Please consult the MariaDB/MySQL knowledgebase at"); - puts("http://kb.askmonty.org/v/mysqlcheck for latest information about"); + puts("Please consult the MariaDB Knowledge Base at"); + puts("https://mariadb.com/kb/en/mysqlcheck for latest information about"); puts("this program."); print_defaults("my", load_default_groups); puts(""); @@ -523,7 +523,6 @@ static int is_view(const char *table) { fprintf(stderr, "Failed to %s\n", query); fprintf(stderr, "Error: %s\n", mysql_error(sock)); - my_free(query); DBUG_RETURN(-1); } res= mysql_store_result(sock); diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 3bbfc70eaed..8fc8f30a9e4 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1104,7 +1104,7 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query, Run query and dump the result to stderr in vertical format NOTE! This function should be safe to call when an error - has occured and thus any further errors will be ignored(although logged) + has occurred and thus any further errors will be ignored (although logged) SYNOPSIS show_query @@ -1170,7 +1170,7 @@ static void show_query(MYSQL* mysql, const char* query) is added to the warning stack, only print @@warning_count-1 warnings. NOTE! This function should be safe to call when an error - has occured and this any further errors will be ignored(although logged) + has occurred and this any further errors will be ignored(although logged) SYNOPSIS show_warnings_before_error @@ -4699,7 +4699,7 @@ void do_sync_with_master2(struct st_command *command, long offset, master_pos_wait returned NULL. This indicates that slave SQL thread is not started, the slave's master information is not initialized, the arguments are - incorrect, or an error has occured + incorrect, or an error has occurred */ die("%.*s failed: '%s' returned NULL " \ "indicating slave SQL thread failure", @@ -4977,12 +4977,13 @@ static int my_kill(int pid, int sig) { #ifdef __WIN__ HANDLE proc; - if ((proc= OpenProcess(PROCESS_TERMINATE, FALSE, pid)) == NULL) + if ((proc= OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pid)) == NULL) return -1; if (sig == 0) { + DWORD wait_result= WaitForSingleObject(proc, 0); CloseHandle(proc); - return 0; + return wait_result == WAIT_OBJECT_0?-1:0; } (void)TerminateProcess(proc, 201); CloseHandle(proc); diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake index 75ce57e45e0..ef9713e0556 100644 --- a/cmake/build_configurations/mysql_release.cmake +++ b/cmake/build_configurations/mysql_release.cmake @@ -94,6 +94,7 @@ ELSEIF(DEB) ELSE() SET(WITH_SSL bundled CACHE STRING "") SET(WITH_ZLIB bundled CACHE STRING "") + SET(WITH_JEMALLOC static CACHE STRING "") ENDIF() IF(NOT COMPILATION_COMMENT) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index f40a38ec775..0e0a121dbb8 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -43,8 +43,8 @@ SET(CPACK_RPM_PACKAGE_DESCRIPTION "${CPACK_RPM_PACKAGE_SUMMARY} It is GPL v2 licensed, which means you can use the it free of charge under the conditions of the GNU General Public License Version 2 (http://www.gnu.org/licenses/). -MariaDB documentation can be found at http://kb.askmonty.org/ -MariaDB bug reports should be submitted through https://mariadb.atlassian.net/ +MariaDB documentation can be found at https://mariadb.com/kb +MariaDB bug reports should be submitted through https://jira.mariadb.org ") @@ -78,14 +78,17 @@ SET(ignored "%ignore ${CMAKE_INSTALL_PREFIX}/bin" "%ignore ${CMAKE_INSTALL_PREFIX}/include" "%ignore ${CMAKE_INSTALL_PREFIX}/lib" + "%ignore ${CMAKE_INSTALL_PREFIX}/lib/systemd" + "%ignore ${CMAKE_INSTALL_PREFIX}/lib/systemd/system" "%ignore ${CMAKE_INSTALL_PREFIX}/lib64" "%ignore ${CMAKE_INSTALL_PREFIX}/sbin" "%ignore ${CMAKE_INSTALL_PREFIX}/share" "%ignore ${CMAKE_INSTALL_PREFIX}/share/aclocal" "%ignore ${CMAKE_INSTALL_PREFIX}/share/doc" "%ignore ${CMAKE_INSTALL_PREFIX}/share/man" - "%ignore ${CMAKE_INSTALL_PREFIX}/share/man/man1*" - "%ignore ${CMAKE_INSTALL_PREFIX}/share/man/man8*" + "%ignore ${CMAKE_INSTALL_PREFIX}/share/man/man1" + "%ignore ${CMAKE_INSTALL_PREFIX}/share/man/man8" + "%ignore ${CMAKE_INSTALL_PREFIX}/share/pkgconfig" ) SET(CPACK_RPM_server_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*") @@ -122,6 +125,7 @@ SETA(CPACK_RPM_server_PACKAGE_OBSOLETES "MySQL" "mysql-server" "MySQL-server" + "MariaDB-Galera-server" "MySQL-OurDelta-server") SETA(CPACK_RPM_server_PACKAGE_PROVIDES "MariaDB" @@ -175,7 +179,7 @@ MACRO(ALTERNATIVE_NAME real alt) SET(p "CPACK_RPM_${real}_PACKAGE_PROVIDES") SET(${p} "${${p}} ${alt} = ${ver} ${alt}%{?_isa} = ${ver} config(${alt}) = ${ver}") SET(o "CPACK_RPM_${real}_PACKAGE_OBSOLETES") - SET(${o} "${${o}} ${alt} ${alt}%{_isa}") + SET(${o} "${${o}} ${alt} ${alt}%{?_isa}") ENDMACRO(ALTERNATIVE_NAME) ALTERNATIVE_NAME("devel" "mysql-devel") diff --git a/cmake/dtrace.cmake b/cmake/dtrace.cmake index 5d0bb7ff8c9..3edcdc4c1c5 100644 --- a/cmake/dtrace.cmake +++ b/cmake/dtrace.cmake @@ -86,6 +86,9 @@ IF(ENABLE_DTRACE) ${CMAKE_BINARY_DIR}/include/probes_mysql_dtrace.h ${CMAKE_BINARY_DIR}/include/probes_mysql_nodtrace.h ) +ELSE() + CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/include/probes_mysql_nodtrace.h.in + ${CMAKE_BINARY_DIR}/include/probes_mysql_nodtrace.h COPYONLY) ENDIF() FUNCTION(DTRACE_INSTRUMENT target) diff --git a/cmake/for_clients.cmake b/cmake/for_clients.cmake index 01b4c0a84f7..dd79ea1039d 100644 --- a/cmake/for_clients.cmake +++ b/cmake/for_clients.cmake @@ -25,7 +25,7 @@ MACRO(EXTRACT_LINK_LIBRARIES target var) # Filter out "general", it is not a library, just CMake hint # Also, remove duplicates IF(NOT lib STREQUAL "general" AND NOT ${var} MATCHES "-l${lib} ") - IF (lib MATCHES "^\\-l") + IF (lib MATCHES "^\\-") SET(${var} "${${var}} ${lib} ") ELSEIF(lib MATCHES "^/") IF (lib MATCHES "\\.(a|so([0-9.]*)|lib|dll|dylib)$") diff --git a/cmake/install_layout.cmake b/cmake/install_layout.cmake index 757166b7c50..d1a261f8cef 100644 --- a/cmake/install_layout.cmake +++ b/cmake/install_layout.cmake @@ -137,7 +137,7 @@ SET(INSTALL_SCRIPTDIR_RPM "bin") SET(INSTALL_SYSCONFDIR_RPM "/etc") SET(INSTALL_SYSCONF2DIR_RPM "/etc/my.cnf.d") # -IF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") +IF(CMAKE_SIZEOF_VOID_P EQUAL 8) SET(INSTALL_LIBDIR_RPM "lib64") SET(INSTALL_PLUGINDIR_RPM "lib64/mysql/plugin") ELSE() diff --git a/cmake/install_macros.cmake b/cmake/install_macros.cmake index 62ccca8deb4..17ee3c61554 100644 --- a/cmake/install_macros.cmake +++ b/cmake/install_macros.cmake @@ -44,11 +44,10 @@ FUNCTION (INSTALL_DEBUG_SYMBOLS) ENDIF() set(comp "") - IF(ARG_COMPONENT STREQUAL "Server") - IF(target MATCHES "mysqld" OR type MATCHES "MODULE") - #MESSAGE("PDB: ${targets}") - SET(comp Server) - ENDIF() + + IF(target MATCHES "mysqld" OR type MATCHES "MODULE") + #MESSAGE("PDB: ${targets}") + SET(comp Server) ENDIF() IF(NOT comp MATCHES Server) diff --git a/cmake/jemalloc.cmake b/cmake/jemalloc.cmake index 05402668c7d..5ad636d0e6c 100644 --- a/cmake/jemalloc.cmake +++ b/cmake/jemalloc.cmake @@ -3,20 +3,6 @@ INCLUDE (CheckLibraryExists) SET(WITH_JEMALLOC auto CACHE STRING "Build with jemalloc. Possible values are 'yes', 'no', 'static', 'auto'") -MACRO(JEMALLOC_TRY_STATIC) - SET(libname jemalloc_pic) - SET(CMAKE_REQUIRED_LIBRARIES pthread dl m) - SET(what bundled) - CHECK_LIBRARY_EXISTS(${libname} malloc_stats_print "" HAVE_STATIC_JEMALLOC) - SET(CMAKE_REQUIRED_LIBRARIES) -ENDMACRO() - -MACRO(JEMALLOC_TRY_DYNAMIC) - SET(libname jemalloc) - SET(what system) - CHECK_LIBRARY_EXISTS(${libname} malloc_stats_print "" HAVE_DYNAMIC_JEMALLOC) -ENDMACRO() - MACRO (CHECK_JEMALLOC) # compatibility with old WITH_JEMALLOC values IF(WITH_JEMALLOC STREQUAL "bundled") @@ -26,21 +12,30 @@ MACRO (CHECK_JEMALLOC) SET(WITH_JEMALLOC "yes") ENDIF() - IF (WITH_JEMALLOC STREQUAL "yes" OR WITH_JEMALLOC STREQUAL "auto") - JEMALLOC_TRY_DYNAMIC() - ENDIF() + IF(WITH_JEMALLOC STREQUAL "yes" OR WITH_JEMALLOC STREQUAL "auto" OR + WITH_JEMALLOC STREQUAL "static") - IF (WITH_JEMALLOC STREQUAL "static" OR WITH_JEMALLOC STREQUAL "auto" - AND NOT HAVE_DYNAMIC_JEMALLOC) - JEMALLOC_TRY_STATIC() - ENDIF() + IF(WITH_JEMALLOC STREQUAL "static") + SET(libname jemalloc_pic) + SET(CMAKE_REQUIRED_LIBRARIES pthread dl m) + SET(what bundled) + ELSE() + SET(libname jemalloc c) + SET(what system) + ENDIF() + + FOREACH(lib ${libname}) + CHECK_LIBRARY_EXISTS(${lib} malloc_stats_print "" HAVE_JEMALLOC_IN_${lib}) + IF (HAVE_JEMALLOC_IN_${lib}) + SET(LIBJEMALLOC ${lib}) + SET(MALLOC_LIBRARY "${what} jemalloc") + BREAK() + ENDIF() + ENDFOREACH() + SET(CMAKE_REQUIRED_LIBRARIES) - IF (libname) - IF (HAVE_DYNAMIC_JEMALLOC OR HAVE_STATIC_JEMALLOC) - SET(LIBJEMALLOC ${libname}) - SET(MALLOC_LIBRARY "${what} jemalloc") - ELSEIF (NOT WITH_JEMALLOC STREQUAL "auto") - MESSAGE(FATAL_ERROR "${libname} is not found") + IF (NOT LIBJEMALLOC AND NOT WITH_JEMALLOC STREQUAL "auto") + MESSAGE(FATAL_ERROR "jemalloc is not found") ENDIF() ENDIF() ENDMACRO() diff --git a/cmake/libutils.cmake b/cmake/libutils.cmake index 1eb782a9078..bcba924dfa8 100644 --- a/cmake/libutils.cmake +++ b/cmake/libutils.cmake @@ -87,6 +87,11 @@ MACRO(CREATE_EXPORT_FILE VAR TARGET API_FUNCTIONS) ENDFOREACH() SET(CONTENT "${CONTENT} (void *)0\n}\;") CONFIGURE_FILE_CONTENT(${CONTENT} ${EXPORTS}) + # Avoid "function redeclared as variable" error + # when using gcc/clang option -flto(link time optimization) + IF(" ${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS} " MATCHES " -flto") + SET_SOURCE_FILES_PROPERTIES(${EXPORTS} PROPERTIES COMPILE_FLAGS "-fno-lto") + ENDIF() SET(${VAR} ${EXPORTS}) ENDIF() ENDMACRO() diff --git a/cmake/maintainer.cmake b/cmake/maintainer.cmake index 82cfda6f6eb..bb7c8862dc7 100644 --- a/cmake/maintainer.cmake +++ b/cmake/maintainer.cmake @@ -56,3 +56,10 @@ ELSEIF(MYSQL_MAINTAINER_MODE MATCHES "AUTO") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${MY_MAINTAINER_C_WARNINGS}") SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${MY_MAINTAINER_CXX_WARNINGS}") ENDIF() + +IF(CMAKE_C_COMPILER_ID MATCHES "GNU") + STRING(REPLACE " -E " " -E -dDI " CMAKE_C_CREATE_PREPROCESSED_SOURCE ${CMAKE_C_CREATE_PREPROCESSED_SOURCE}) +ENDIF() +IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + STRING(REPLACE " -E " " -E -dDI " CMAKE_CXX_CREATE_PREPROCESSED_SOURCE ${CMAKE_CXX_CREATE_PREPROCESSED_SOURCE}) +ENDIF() diff --git a/cmake/plugin.cmake b/cmake/plugin.cmake index 7b91f0b5747..c4edd585a8d 100644 --- a/cmake/plugin.cmake +++ b/cmake/plugin.cmake @@ -18,6 +18,7 @@ INCLUDE(CMakeParseArguments) # MYSQL_ADD_PLUGIN(plugin_name source1...sourceN # [STORAGE_ENGINE] +# [CLIENT] # [MANDATORY|DEFAULT] # [STATIC_ONLY|DYNAMIC_ONLY] # [MODULE_OUTPUT_NAME module_name] @@ -28,11 +29,12 @@ INCLUDE(CMakeParseArguments) MACRO(MYSQL_ADD_PLUGIN) CMAKE_PARSE_ARGUMENTS(ARG - "STORAGE_ENGINE;STATIC_ONLY;MODULE_ONLY;MANDATORY;DEFAULT;DISABLED;RECOMPILE_FOR_EMBEDDED" + "STORAGE_ENGINE;STATIC_ONLY;MODULE_ONLY;MANDATORY;DEFAULT;DISABLED;RECOMPILE_FOR_EMBEDDED;CLIENT" "MODULE_OUTPUT_NAME;STATIC_OUTPUT_NAME;COMPONENT;CONFIG" "LINK_LIBRARIES;DEPENDENCIES" ${ARGN} ) + IF(NOT WITHOUT_SERVER OR ARG_CLIENT) # Add common include directories INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include @@ -72,7 +74,9 @@ MACRO(MYSQL_ADD_PLUGIN) SET(compat "with${compat}") ENDIF() - IF (compat STREQUAL ".") + IF (ARG_DISABLED) + SET(howtobuild NO) + ELSEIF (compat STREQUAL ".") SET(howtobuild DYNAMIC) ELSEIF (compat STREQUAL "with.") IF (NOT ARG_MODULE_ONLY) @@ -120,7 +124,7 @@ MACRO(MYSQL_ADD_PLUGIN) # Build either static library or module IF (PLUGIN_${plugin} MATCHES "(STATIC|AUTO|YES)" AND NOT ARG_MODULE_ONLY - AND NOT ARG_DISABLED) + AND NOT ARG_CLIENT) IF(CMAKE_GENERATOR MATCHES "Makefiles|Ninja") # If there is a shared library from previous shared build, @@ -176,8 +180,7 @@ MACRO(MYSQL_ADD_PLUGIN) SET (mysql_optional_plugins ${mysql_optional_plugins} PARENT_SCOPE) ENDIF() ELSEIF(PLUGIN_${plugin} MATCHES "(DYNAMIC|AUTO|YES)" - AND NOT ARG_STATIC_ONLY AND NOT WITHOUT_DYNAMIC_PLUGINS - AND NOT ARG_DISABLED) + AND NOT ARG_STATIC_ONLY AND NOT WITHOUT_DYNAMIC_PLUGINS) ADD_VERSION_INFO(${target} MODULE SOURCES) ADD_LIBRARY(${target} MODULE ${SOURCES}) @@ -188,14 +191,14 @@ MACRO(MYSQL_ADD_PLUGIN) TARGET_LINK_LIBRARIES (${target} mysqlservices ${ARG_LINK_LIBRARIES}) - # Plugin uses symbols defined in mysqld executable. + # Server plugins use symbols defined in mysqld executable. # Some operating systems like Windows and OSX and are pretty strict about # unresolved symbols. Others are less strict and allow unresolved symbols # in shared libraries. On Linux for example, CMake does not even add # executable to the linker command line (it would result into link error). # Thus we skip TARGET_LINK_LIBRARIES on Linux, as it would only generate # an additional dependency. - IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") + IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" AND NOT ARG_CLIENT) TARGET_LINK_LIBRARIES (${target} mysqld) ENDIF() ADD_DEPENDENCIES(${target} GenError ${ARG_DEPENDENCIES}) @@ -206,19 +209,22 @@ MACRO(MYSQL_ADD_PLUGIN) IF(ARG_COMPONENT) IF(CPACK_COMPONENTS_ALL AND NOT CPACK_COMPONENTS_ALL MATCHES ${ARG_COMPONENT}) - SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} ${ARG_COMPONENT} PARENT_SCOPE) - SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_REQUIRES "MariaDB" PARENT_SCOPE) - IF (NOT ARG_CONFIG) - SET(ARG_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/${target}.cnf") - FILE(WRITE ${ARG_CONFIG} "[mariadb]\nplugin-load-add=${ARG_MODULE_OUTPUT_NAME}.so\n") + SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} ${ARG_COMPONENT}) + SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} PARENT_SCOPE) + IF (NOT ARG_CLIENT) + SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_REQUIRES "MariaDB" PARENT_SCOPE) ENDIF() - INSTALL(FILES ${ARG_CONFIG} COMPONENT ${ARG_COMPONENT} DESTINATION ${INSTALL_SYSCONF2DIR}) - # workarounds for cmake issues #13248 and #12864: SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_PROVIDES "cmake_bug_13248" PARENT_SCOPE) SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_OBSOLETES "cmake_bug_13248" PARENT_SCOPE) - SET(CPACK_RPM_${ARG_COMPONENT}_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*" PARENT_SCOPE) + SET(CPACK_RPM_${ARG_COMPONENT}_USER_FILELIST ${ignored} PARENT_SCOPE) + IF(NOT ARG_CLIENT AND NOT ARG_CONFIG AND UNIX) + SET(ARG_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/${target}.cnf") + FILE(WRITE ${ARG_CONFIG} "[mariadb]\nplugin-load-add=${ARG_MODULE_OUTPUT_NAME}.so\n") + INSTALL(FILES ${ARG_CONFIG} COMPONENT ${ARG_COMPONENT} DESTINATION ${INSTALL_SYSCONF2DIR}) + SET(CPACK_RPM_${ARG_COMPONENT}_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*" PARENT_SCOPE) + ENDIF() ENDIF() ELSE() SET(ARG_COMPONENT Server) @@ -232,13 +238,17 @@ MACRO(MYSQL_ADD_PLUGIN) INSTALL_MYSQL_TEST("${CMAKE_CURRENT_SOURCE_DIR}/mysql-test/" "plugin/${subpath}") ENDIF() + ENDIF(NOT WITHOUT_SERVER OR ARG_CLIENT) ENDMACRO() # Add all CMake projects under storage and plugin # subdirectories, configure sql_builtins.cc MACRO(CONFIGURE_PLUGINS) - FILE(GLOB dirs_storage ${CMAKE_SOURCE_DIR}/storage/*) + IF(NOT WITHOUT_SERVER) + FILE(GLOB dirs_storage ${CMAKE_SOURCE_DIR}/storage/*) + ENDIF() + FILE(GLOB dirs_plugin ${CMAKE_SOURCE_DIR}/plugin/*) FOREACH(dir ${dirs_storage} ${dirs_plugin}) IF (EXISTS ${dir}/CMakeLists.txt) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 64266811811..de7fb5eb946 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -26,7 +26,7 @@ ENDIF() OPTION(WITH_WSREP "WSREP replication API (to use, e.g. Galera Replication library)" ${with_wsrep_default}) # Set the patch version -SET(WSREP_PATCH_VERSION "11") +SET(WSREP_PATCH_VERSION "13") # Obtain wsrep API version FILE(STRINGS "${MySQL_SOURCE_DIR}/wsrep/wsrep_api.h" WSREP_API_VERSION diff --git a/config.h.cmake b/config.h.cmake index 6b072806019..048ce816a43 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -88,6 +88,7 @@ #cmakedefine HAVE_SYS_UN_H 1 #cmakedefine HAVE_SYS_VADVISE_H 1 #cmakedefine HAVE_SYS_STATVFS_H 1 +#cmakedefine HAVE_UCONTEXT_H 1 #cmakedefine HAVE_TERM_H 1 #cmakedefine HAVE_TERMBITS_H 1 #cmakedefine HAVE_TERMIOS_H 1 @@ -236,7 +237,6 @@ #cmakedefine HAVE_THR_YIELD 1 #cmakedefine HAVE_TIME 1 #cmakedefine HAVE_TIMES 1 -#cmakedefine HAVE_UCONTEXT 1 #cmakedefine HAVE_VIDATTR 1 #define HAVE_VIO_READ_BUFF 1 #cmakedefine HAVE_VASPRINTF 1 diff --git a/configure.cmake b/configure.cmake index ca9d36eace3..294c5e24ca8 100644 --- a/configure.cmake +++ b/configure.cmake @@ -196,6 +196,7 @@ CHECK_INCLUDE_FILES (ndir.h HAVE_NDIR_H) CHECK_INCLUDE_FILES (netinet/in.h HAVE_NETINET_IN_H) CHECK_INCLUDE_FILES (paths.h HAVE_PATHS_H) CHECK_INCLUDE_FILES (poll.h HAVE_POLL_H) +CHECK_INCLUDE_FILES (sys/poll.h HAVE_SYS_POLL_H) CHECK_INCLUDE_FILES (pwd.h HAVE_PWD_H) CHECK_INCLUDE_FILES (sched.h HAVE_SCHED_H) CHECK_INCLUDE_FILES (select.h HAVE_SELECT_H) @@ -727,16 +728,36 @@ ENDIF() # # Test for how the C compiler does inline, if at all # +# SunPro is weird, apparently it only supports inline at -xO3 or -xO4. +# And if CMAKE_C_FLAGS has -xO4 but CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE} has -xO2 +# then CHECK_C_SOURCE_COMPILES will succeed but the built will fail. +# We must test all flags here. +# XXX actually, we can do this for all compilers, not only SunPro +IF (CMAKE_CXX_COMPILER_ID MATCHES "SunPro" AND + CMAKE_GENERATOR MATCHES "Makefiles") + STRING(TOUPPER "CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE}" flags) + SET(CMAKE_REQUIRED_FLAGS "${${flags}}") +ENDIF() CHECK_C_SOURCE_COMPILES(" -static inline int foo(){return 0;} +extern int bar(int x); +static inline int foo(){return bar(1);} int main(int argc, char *argv[]){return 0;}" C_HAS_inline) IF(NOT C_HAS_inline) CHECK_C_SOURCE_COMPILES(" - static __inline int foo(){return 0;} + extern int bar(int x); + static __inline int foo(){return bar(1);} int main(int argc, char *argv[]){return 0;}" C_HAS___inline) - SET(C_INLINE __inline) + IF(C_HAS___inline) + SET(C_INLINE __inline) + ElSE() + SET(C_INLINE) + MESSAGE(WARNING "C compiler does not support funcion inlining") + IF(NOT NOINLINE) + MESSAGE(FATAL_ERROR "Use -DNOINLINE=TRUE to allow compilation without inlining") + ENDIF() + ENDIF() ENDIF() IF(NOT CMAKE_CROSSCOMPILING AND NOT MSVC) @@ -977,6 +998,11 @@ CHECK_STRUCT_HAS_MEMBER("struct sockaddr_in6" sin6_len SET(CMAKE_EXTRA_INCLUDE_FILES) +CHECK_INCLUDE_FILE(ucontext.h HAVE_UCONTEXT_H) +IF(NOT HAVE_UCONTEXT_H) + CHECK_INCLUDE_FILE(sys/ucontext.h HAVE_UCONTEXT_H) +ENDIF() + CHECK_STRUCT_HAS_MEMBER("struct timespec" tv_sec "time.h" STRUCT_TIMESPEC_HAS_TV_SEC) CHECK_STRUCT_HAS_MEMBER("struct timespec" tv_nsec "time.h" STRUCT_TIMESPEC_HAS_TV_NSEC) @@ -997,4 +1023,3 @@ IF(NOT MSVC) HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE ) ENDIF() - diff --git a/debian/additions/innotop/innotop b/debian/additions/innotop/innotop index 646f0d7f0fb..9179a0d7a81 100644 --- a/debian/additions/innotop/innotop +++ b/debian/additions/innotop/innotop @@ -1503,7 +1503,7 @@ my %exprs = ( my %columns = ( active_secs => { hdr => 'SecsActive', num => 1, label => 'Seconds transaction has been active', }, - add_pool_alloc => { hdr => 'Add\'l Pool', num => 1, label => 'Additonal pool allocated' }, + add_pool_alloc => { hdr => 'Add\'l Pool', num => 1, label => 'Additional pool allocated' }, attempted_op => { hdr => 'Action', num => 0, label => 'The action that caused the error' }, awe_mem_alloc => { hdr => 'AWE Memory', num => 1, label => '[Windows] AWE memory allocated' }, binlog_cache_overflow => { hdr => 'Binlog Cache', num => 1, label => 'Transactions too big for binlog cache that went to disk' }, @@ -10365,7 +10365,7 @@ show you something like this: pages_modified Dirty Pages Pages modified (dirty IB_bp_pages_m buf_pool_hit_rate Hit Rate Buffer pool hit rate IB_bp_buf_poo total_mem_alloc Memory Total memory allocate IB_bp_total_m - add_pool_alloc Add'l Pool Additonal pool alloca IB_bp_add_poo + add_pool_alloc Add'l Pool Additional pool alloca IB_bp_add_poo The first line shows which table you're editing, and reminds you again to press '?' for a list of key mappings. The rest is a tabular representation of the diff --git a/debian/additions/innotop/innotop.1 b/debian/additions/innotop/innotop.1 index b2e7fce084e..fbb481f9b94 100644 --- a/debian/additions/innotop/innotop.1 +++ b/debian/additions/innotop/innotop.1 @@ -1579,7 +1579,7 @@ show you something like this: \& pages_modified Dirty Pages Pages modified (dirty IB_bp_pages_m \& buf_pool_hit_rate Hit Rate Buffer pool hit rate IB_bp_buf_poo \& total_mem_alloc Memory Total memory allocate IB_bp_total_m -\& add_pool_alloc Add\*(Aql Pool Additonal pool alloca IB_bp_add_poo +\& add_pool_alloc Add\*(Aql Pool Additional pool alloca IB_bp_add_poo .Ve .PP The first line shows which table you're editing, and reminds you again to press diff --git a/debian/additions/my.cnf b/debian/additions/my.cnf index 4645e7c557a..d30ec182c8b 100644 --- a/debian/additions/my.cnf +++ b/debian/additions/my.cnf @@ -177,7 +177,7 @@ quote-names max_allowed_packet = 16M [mysql] -#no-auto-rehash # faster start of mysql but no tab completition +#no-auto-rehash # faster start of mysql but no tab completion [isamchk] key_buffer = 16M diff --git a/debian/additions/mysqlreport b/debian/additions/mysqlreport index 402a5be835d..3e116bf4a43 100755 --- a/debian/additions/mysqlreport +++ b/debian/additions/mysqlreport @@ -1,10 +1,11 @@ #!/usr/bin/perl -w -# mysqlreport v3.5 Apr 16 2008 +# mysqlreport v4.0 Oct 23 2015 # http://hackmysql.com/mysqlreport -# mysqlreport makes an easy-to-read report of important MySQL status values. +# mysqlreport makes an easy-to-read report of important MySQL/MariaDB status values. # Copyright 2006-2008 Daniel Nichter +# Copyright 2012-2015 Jean Weisbuch # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -36,16 +37,19 @@ my ($stat_name, $stat_val, $stat_label); my $MySQL_version; my (%stats, %vars); # SHOW STATUS, SHOW VARIABLES my (%DMS_vals, %Com_vals, %ib_vals); -my ($dbh, $query); +my $dbh; my ($questions, $key_read_ratio, $key_write_ratio, $dms, $slow_query_t); my ($key_cache_block_size, $key_buffer_used, $key_buffer_usage); my ($qc_mem_used, $qc_hi_r, $qc_ip_r); # Query Cache -my $have_innodb_vals; my ($ib_bp_used, $ib_bp_total, $ib_bp_read_ratio); my ($relative_live, $relative_infiles); my $real_uptime; my (%stats_present, %stats_past); # For relative reports - +my ($pagecache_read_ratio, $pagecache_write_ratio, $pagecache_block_size, $pagecache_buffer_used, $pagecache_buffer_usage); # AriaDB pagecache stats +my ($binlog_cache_ratio, $binlog_stmt_cache_ratio); # binary log cache +my $dbms; +my ($rows, $rows_using_indexes); + GetOptions ( \%op, "user=s", @@ -127,13 +131,19 @@ $| = 1 if ($op{'detach'} || $relative_live); print "tmp file: $tmpfile\n" if $op{debug}; -# Connect to MySQL +# Connect to MySQL/MariaDB if(!$op{'infile'} && !$relative_infiles) { connect_to_MySQL(); } -$have_innodb_vals = 1; # This might be set to 0 later in get_MySQL_version() +my $have_innodb_vals = 1; # This might be set to 0 later in get_MySQL_version() +my $have_aria_vals = 0; +my $have_subquerycache_vals = 0; +my $have_binlog_vals = 0; +my $have_tokudb_engine = 0; +my $use_thread_pool = 0; +my $use_xtradb = 0; if(defined $op{'r'}) { @@ -163,6 +173,9 @@ else set_myisam_vals(); set_ib_vals() if $have_innodb_vals; + set_aria_vals() if $have_aria_vals; + set_subquerycache_vals() if $have_subquerycache_vals; + set_binlog_vals() if $have_binlog_vals; write_report(); } @@ -177,8 +190,8 @@ exit; sub show_help_and_exit { print <<"HELP"; -mysqlreport v3.5 Apr 16 2008 -mysqlreport makes an easy-to-read report of important MySQL status values. +mysqlreport v4.0 Oct 23 2015 +mysqlreport makes an easy-to-read report of important MySQL/MariaDB status values. Command line options (abbreviations work): --user USER Connect to MySQL as USER @@ -264,6 +277,9 @@ sub collect_reports set_myisam_vals(); set_ib_vals() if $have_innodb_vals; + set_aria_vals() if $have_aria_vals; + set_subquerycache_vals() if $have_subquerycache_vals; + set_binlog_vals() if $have_binlog_vals; print "#\n# Beginning report, 0 0:0:0\n#\n"; @@ -350,7 +366,7 @@ sub read_relative_infiles # The infile must begin with the system variable values. # Therefore, the first occurance of Aborted_clients indicates the beginning - # of the first set of status values if no sets have occured yet ($stat_n == 0). + # of the first set of status values if no sets have occurred yet ($stat_n == 0). # In this case, the following status values are printed to the current fh, # along with the system variable values read thus far, until Aborted_clients # occurs again. Then begins the second and subsequent sets of status values. @@ -403,6 +419,9 @@ sub relative_infile_report set_myisam_vals(); set_ib_vals() if $have_innodb_vals; + set_aria_vals() if $have_aria_vals; + set_subquerycache_vals() if $have_subquerycache_vals; + set_binlog_vals() if $have_binlog_vals; print "#\n# Beginning report, 0 0:0:0\n#\n"; @@ -422,7 +441,7 @@ sub get_vals { print "get_vals\n" if $op{debug}; - my @row; + my (@row, $query); # Get status values if($MySQL_version >= 50002) @@ -434,7 +453,9 @@ sub get_vals $query = $dbh->prepare("SHOW STATUS;"); } $query->execute(); - while(@row = $query->fetchrow_array()) { $stats{$row[0]} = $row[1]; } + # To avoid problems if the variable capitalization would change (eg. TokuDB on MariaDB 5.5 => 10.0), the $stats index is forced to have its first char uppercase and the rest lowercase + while(@row = $query->fetchrow_array()) { $stats{ucfirst(lc($row[0]))} = $row[1]; } + $query->finish(); $real_uptime = $stats{'Uptime'}; } @@ -443,18 +464,23 @@ sub get_vars { print "get_vars\n" if $op{debug}; - my @row; + my (@row, $query); # Get server system variables $query = $dbh->prepare("SHOW VARIABLES;"); $query->execute(); while(@row = $query->fetchrow_array()) { $vars{$row[0]} = $row[1]; } - + $query->finish(); # table_cache was renamed to table_open_cache in MySQL 5.1.3 if($MySQL_version >= 50103) { $vars{'table_cache'} = $vars{'table_open_cache'}; } + # log_slow_queries was renamed to slow_query_log in MySQL 5.1.29 + if($MySQL_version >= 50129) + { + $vars{'log_slow_queries'} = $vars{'slow_query_log'}; + } } sub read_infile @@ -507,10 +533,10 @@ sub read_infile else { print "read_infile: ignore '$_'\n" if $op{debug}; } last if $1 eq 'Uptime'; # exit while() if end of status values - $_ = <INFILE>; # otherwise, read next line of status values + $_ = <INFILE>; # otherwise, read next line of status values } } - elsif($1 eq 'back_log') # system variable values + elsif($1 eq 'back_log') # system variable values { print "read_infile: start vars\n" if $op{debug}; @@ -525,7 +551,7 @@ sub read_infile else { print "read_infile: ignore '$_'\n" if $op{debug}; } last if $1 eq 'wait_timeout'; # exit while() if end of vars - $_ = <INFILE>; # otherwise, read next line of vars + $_ = <INFILE>; # otherwise, read next line of vars } } elsif($1 eq '=') # old style, manually added system variable values @@ -542,7 +568,7 @@ sub read_infile } else { print "read_infile: ignore '$_'\n" if $op{debug}; } - $_ = <INFILE>; # otherwise, read next line of old vars + $_ = <INFILE>; # otherwise, read next line of old vars } redo; @@ -572,25 +598,116 @@ sub get_MySQL_version if($op{'infile'} || $relative_infiles) { - ($major, $minor, $patch) = ($vars{'version'} =~ /(\d{1,2})\.(\d{1,2})\.(\d{1,2})/); + ($major, $minor, $patch) = ($vars{'version'} =~ /^(\d{1,2})\.(\d{1,2})\.(\d{1,2})/); + if($vars{'version'} =~ /^\d{1,2}\.\d{1,2}\.\d{1,2}-MariaDB/) { + print "MariaDB detected\n" if $op{debug}; + $dbms = "MariaDB"; + } else { + $dbms = "MySQL"; + } } else { - my @row; + my (@row, $query); $query = $dbh->prepare("SHOW VARIABLES LIKE 'version';"); $query->execute(); @row = $query->fetchrow_array(); - ($major, $minor, $patch) = ($row[1] =~ /(\d{1,2})\.(\d{1,2})\.(\d{1,2})/); + $query->finish(); + ($major, $minor, $patch) = ($row[1] =~ /^(\d{1,2})\.(\d{1,2})\.(\d{1,2})/); + if($row[1] =~ /^\d{1,2}\.\d{1,2}\.\d{1,2}-MariaDB/) + { + print "MariaDB detected\n" if $op{debug}; + $dbms = "MariaDB"; + } + else + { + $dbms = "MySQL"; + } } + # The major version number is kept as is while the minor version and the revision number are forced to 2 digits + # e.g.: 5.5.9 will be 50509, 10.0.5 will be 100005 and 10.1.23 will be 100123 $MySQL_version = sprintf("%d%02d%02d", $major, $minor, $patch); + print "Version $MySQL_version\n" if $op{debug}; # Innodb_ status values were added in 5.0.2 if($MySQL_version < 50002) { $have_innodb_vals = 0; print "get_MySQL_version: no InnoDB reports because MySQL version is older than 5.0.2\n" if $op{debug}; + } else { + $have_innodb_vals = $dbh->selectall_arrayref("SELECT SUPPORT FROM information_schema.engines WHERE ENGINE = 'InnoDB';", undef)->[0][0]; + if(defined($have_innodb_vals) && ($have_innodb_vals eq "YES" || $have_innodb_vals eq "DEFAULT")) + { + print "InnoDB detected\n" if $op{debug}; + $have_innodb_vals = 1; + } else { + print "InnoDB is not activated\n" if $op{debug}; + $have_innodb_vals = 0; + } + } + + if($dbms eq "MariaDB") { + $have_aria_vals = $dbh->selectall_arrayref("SELECT SUPPORT FROM information_schema.engines WHERE ENGINE = 'Aria';", undef)->[0][0]; + if(defined($have_aria_vals) && $have_aria_vals eq "YES") + { + print "Aria engine detected\n" if $op{debug}; + $have_aria_vals = 1; + } else { + $have_aria_vals = 0; + } + + # MariaDB 5.3+, activated by default since 5.3.2 + $have_subquerycache_vals = $dbh->selectall_arrayref("SELECT VARIABLE_VALUE REGEXP ',subquery_cache=on,|^subquery_cache=on,|,subquery_cache=on\$' AS SUBQUERY_CACHE FROM information_schema.global_variables WHERE VARIABLE_NAME = 'optimizer_switch';", undef)->[0][0]; + if(defined($have_subquerycache_vals) && $have_subquerycache_vals eq "1") + { + print "Subquery cache is activated\n" if $op{debug}; + $have_subquerycache_vals = 1; + } else { + $have_subquerycache_vals = 0; + } + } + + if($MySQL_version >= 50000) + { + # These checks use the 'information_schema' virtual database that has been added on MySQL 5.0 + + # MariaDB 5.5.21+ and Percona Server 5.5.30+ use the same thread pool implementation + $use_thread_pool = $dbh->selectall_arrayref("SELECT VARIABLE_VALUE FROM information_schema.global_variables WHERE VARIABLE_NAME = 'thread_handling';", undef)->[0][0]; + if(defined($use_thread_pool) && $use_thread_pool eq "pool-of-threads") { + print "Thread pool is used\n" if $op{debug}; + $use_thread_pool = 1; + } else { + $use_thread_pool = 0; + } + + $have_binlog_vals = $dbh->selectall_arrayref("SELECT VARIABLE_VALUE FROM information_schema.global_variables WHERE VARIABLE_NAME = 'log_bin';", undef)->[0][0]; + if(defined($have_binlog_vals) && $have_binlog_vals eq "ON") + { + print "Binary log is activated\n" if $op{debug}; + $have_binlog_vals = 1; + } else { + $have_binlog_vals = 0; + } + + $have_tokudb_engine = $dbh->selectall_arrayref("SELECT SUPPORT FROM information_schema.engines WHERE ENGINE = 'TokuDB';", undef)->[0][0]; + if(defined($have_tokudb_engine) && ($have_tokudb_engine eq "YES" || $have_tokudb_engine eq "DEFAULT")) + { + print "TokuDB detected\n" if $op{debug}; + $have_tokudb_engine = 1; + } else { + $have_tokudb_engine = 0; + } + + $use_xtradb = $dbh->selectall_arrayref("SELECT 1 FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE = 'InnoDB' AND COMMENT LIKE 'Percona-XtraDB%';", undef)->[0][0]; + if(defined($use_xtradb) && $use_xtradb eq "1") + { + print "XtraDB detected\n" if $op{debug}; + $use_xtradb = 1; + } else { + $use_xtradb = 0; + } } } @@ -598,6 +715,7 @@ sub set_myisam_vals { print "set_myisam_vals\n" if $op{debug}; +# should be moved elsewere $questions = $stats{'Questions'}; $key_read_ratio = sprintf "%.2f", @@ -638,7 +756,6 @@ sub set_myisam_vals $dms = $DMS_vals{SELECT} + $DMS_vals{INSERT} + $DMS_vals{REPLACE} + $DMS_vals{UPDATE} + $DMS_vals{DELETE}; $slow_query_t = format_u_time($vars{long_query_time}); - } sub set_ib_vals @@ -658,6 +775,46 @@ sub set_ib_vals 0); } +sub set_aria_vals +{ + print "set_aria_vals\n" if $op{debug}; + + $pagecache_read_ratio = sprintf "%.2f", + ($stats{'Aria_pagecache_read_requests'} ? + 100 - ($stats{'Aria_pagecache_reads'} / $stats{'Aria_pagecache_read_requests'}) * 100 : + 0); + + $pagecache_write_ratio = sprintf "%.2f", + ($stats{'Aria_pagecache_write_requests'} ? + 100 - ($stats{'Aria_pagecache_writes'} / $stats{'Aria_pagecache_write_requests'}) * 100 : + 0); + + $pagecache_block_size = (defined $vars{'aria_block_size'} ? + $vars{'aria_block_size'} : + 1024); + + $pagecache_buffer_used = $stats{'Aria_pagecache_blocks_used'} * $pagecache_block_size; + + $pagecache_buffer_usage = $vars{'aria_pagecache_buffer_size'} - + ($stats{'Aria_pagecache_blocks_unused'} * $pagecache_block_size); +} + +sub set_subquerycache_vals +{ + print "set_subquerycache_vals\n" if $op{debug}; +} + +sub set_binlog_vals +{ + print "set_binlog_vals\n" if $op{debug}; + + if($stats{'Binlog_cache_use'} gt 0) { $binlog_cache_ratio = $stats{'Binlog_cache_disk_use'} / $stats{'Binlog_cache_use'}; } + else { $binlog_cache_ratio = 0; } + + if(defined($stats{'Binlog_stmt_cache_use'}) && $stats{'Binlog_stmt_cache_use'} gt 0) { $binlog_stmt_cache_ratio = $stats{'Binlog_stmt_cache_disk_use'} / $stats{'Binlog_stmt_cache_use'}; } + else { $binlog_stmt_cache_ratio = 0; } +} + sub write_relative_report { print "write_relative_report\n" if $op{debug}; @@ -708,6 +865,10 @@ sub write_relative_report $stats{'Innodb_row_lock_time_max'} = $stats_present{'Innodb_row_lock_time_max'}; } } + if($have_aria_vals) + { + $stats{'Aria_pagecache_blocks_used'} = $stats_present{'Aria_pagecache_blocks_used'}; + } get_Com_values(); @@ -715,6 +876,9 @@ sub write_relative_report set_myisam_vals(); set_ib_vals() if $have_innodb_vals; + set_aria_vals() if $have_aria_vals; + set_subquerycache_vals() if $have_subquerycache_vals; + set_binlog_vals() if $have_binlog_vals; write_report(); } @@ -731,15 +895,27 @@ sub write_report $~ = 'SLOW_DMS', write; write_DMS(); write_Com(); + write_Rows(); $~ = 'SAS', write; write_qcache(); $~ = 'REPORT_END', write; + $~ = 'THREADS', write; + if($use_thread_pool) + { + $~ = 'THREADPOOL', write; + } else { + $~ = 'THREADPERCONNECTION', write; + } $~ = 'TAB', write; write_InnoDB() if $have_innodb_vals; + write_Aria() if $have_aria_vals; + write_Subquerycache() if $have_subquerycache_vals; + write_Binlog() if $have_binlog_vals; + write_TokuDB() if $have_tokudb_engine; } -sub sec_to_dhms # Seconds to days hours:minutes:seconds +sub sec_to_dhms # Seconds to days+hours:minutes:seconds { my $s = shift; my ($d, $h, $m) = (0, 0, 0); @@ -761,7 +937,7 @@ sub sec_to_dhms # Seconds to days hours:minutes:seconds $m = int $s / 60; $s -= $m * 60; - return "$d $h:$m:$s"; + return "$d+$h:$m:$s"; } sub make_short @@ -782,12 +958,11 @@ sub make_short } # What began as a simple but great idea has become the new standard: -# long_query_time in microseconds. For MySQL 5.1.21+ and 6.0.4+ this -# is now standard. For 4.1 and 5.0 patches, the architects of this -# idea provide: http://www.mysqlperformanceblog.com/mysql-patches/ +# long_query_time in microseconds. For MySQL 5.1.21+ this is now +# standard. For 4.1 and 5.0 patches, the architects of this idea +# provide: http://www.mysqlperformanceblog.com/mysql-patches/ # Relevant notes in MySQL manual: # http://dev.mysql.com/doc/refman/5.1/en/slow-query-log.html -# http://dev.mysql.com/doc/refman/6.0/en/slow-query-log.html # # The format_u_time sub simply beautifies long_query_time. @@ -848,7 +1023,7 @@ sub email_report # Email given report to $op{'email'} open SENDMAIL, "|/usr/sbin/sendmail -t"; print SENDMAIL "From: mysqlreport\n"; print SENDMAIL "To: $op{email}\n"; - print SENDMAIL "Subject: MySQL status report on " . ($mycnf{'host'} || 'localhost') . "\n\n"; + print SENDMAIL "Subject: $dbms status report on " . ($mycnf{'host'} || 'localhost') . "\n\n"; print SENDMAIL `cat $report`; close SENDMAIL; } @@ -979,6 +1154,7 @@ sub write_qcache # ergo this method is slightly more reliable return if not exists $vars{'query_cache_size'}; return if $vars{'query_cache_size'} == 0; + return if defined($vars{'query_cache_type'}) and $vars{'query_cache_type'} eq 'OFF'; $qc_mem_used = $vars{'query_cache_size'} - $stats{'Qcache_free_memory'}; $qc_hi_r = sprintf "%.2f", $stats{'Qcache_hits'} / ($stats{'Qcache_inserts'} ||= 1); @@ -988,6 +1164,36 @@ sub write_qcache write; } +sub write_Subquerycache +{ + print "write_Subquerycache\n" if $op{debug}; + + return if not defined $stats{'Subquery_cache_hit'}; + return if $stats{'Subquery_cache_hit'} == 0 && $stats{'Subquery_cache_miss'} == 0; + + $~ = 'SUBQUERYCACHE'; + write; +} + +sub write_Binlog +{ + print "write_Binlog\n" if $op{debug}; + + return if $binlog_cache_ratio == 0 && $binlog_stmt_cache_ratio == 0; + $~ = 'BINLOG'; + write; +} + +sub write_TokuDB +{ + print "write_TokuDB\n" if $op{debug}; + + return if $stats{'Tokudb_cachetable_size_current'} == 0; + + $~ = 'TOKUDB'; + write; +} + sub write_InnoDB { print "write_InnoDB\n" if $op{debug}; @@ -998,6 +1204,11 @@ sub write_InnoDB $~ = 'IB'; write; + if($use_xtradb) + { + $~ = 'IB_XTRADB'; + write; + } # Innodb_row_lock_ values were added in MySQL 5.0.3 if($MySQL_version >= 50003) @@ -1005,12 +1216,44 @@ sub write_InnoDB $~ = 'IB_LOCK'; write; } + if($use_xtradb) + { + $~ = 'IB_LOCK_XTRADB'; + write; + } # Data, Pages, Rows $~ = 'IB_DPR'; write; } + +sub write_Aria +{ + print "write_Aria\n" if $op{debug}; + + return if not defined $stats{'Aria_pagecache_blocks_used'}; + + $~ = 'PAGECACHE_BUFF_MAX'; + write; + + if($pagecache_buffer_usage != -1) { $~ = 'PAGECACHE_BUFF_USAGE', write } + + $~ = 'PAGECACHE_RATIOS'; + write; +} + +sub write_Rows +{ + print "write_Rows\n" if $op{debug}; + + $rows_using_indexes = $stats{'Handler_read_first'} + $stats{'Handler_read_key'} + $stats{'Handler_read_next'} + $stats{'Handler_read_prev'}; + $rows = $rows_using_indexes + $stats{'Handler_read_rnd'} + $stats{'Handler_read_rnd_next'} + $stats{'Sort_rows'}; + + $~ = 'ROWS'; + write; +} + sub have_op { my $key = shift; @@ -1043,19 +1286,17 @@ sub exit_tasks_and_cleanup } else { - if($WIN) { `del $tmpfile`; } - else { `rm -f $tmpfile`; } + unlink $tmpfile; } if(!$op{'infile'} && !$relative_infiles) { if($op{'flush-status'}) { - $query = $dbh->prepare("FLUSH STATUS;"); + my $query = $dbh->prepare("FLUSH STATUS;"); $query->execute(); + $query->finish(); } - - $query->finish(); $dbh->disconnect(); } } @@ -1065,19 +1306,19 @@ sub exit_tasks_and_cleanup # format MYSQL_TIME = -MySQL @<<<<<<<<<<<<<<<< uptime @<<<<<<<<<<< @>>>>>>>>>>>>>>>>>>>>>>>> -$vars{'version'}, sec_to_dhms($real_uptime), (($op{infile} || $relative_infiles) ? '' : scalar localtime) +@<<<<<< @<<<<<<<<<<<<<<<<<< uptime @<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<< +$dbms, $vars{'version'}, sec_to_dhms($real_uptime), (($op{infile} || $relative_infiles) ? '' : scalar localtime) . format KEY_BUFF_MAX = __ Key _________________________________________________________________ -Buffer used @>>>>>> of @>>>>>> %Used: @>>>>> +Buffer used @>>>>>> of @>>>>>> %Used: @>>>>> make_short($key_buffer_used, 1), make_short($vars{'key_buffer_size'}, 1), perc($key_buffer_used, $vars{'key_buffer_size'}) . format KEY_BUFF_USAGE = - Current @>>>>>> %Usage: @>>>>> + Current @>>>>>> %Usage: @>>>>> make_short($key_buffer_usage, 1), perc($key_buffer_usage, $vars{'key_buffer_size'}) . @@ -1088,166 +1329,197 @@ Read hit @>>>>>% $key_read_ratio __ Questions ___________________________________________________________ -Total @>>>>>>>> @>>>>>/s +Total @>>>>>>>> @>>>>>/s make_short($questions), t($questions) . format DTQ = - @<<<<<<< @>>>>>>>> @>>>>>/s @>>>>>> @>>>>> + @<<<<<<< @>>>>>>>> @>>>>>/s @>>>>>> @>>>>> $stat_name, make_short($stat_val), t($stat_val), $stat_label, perc($stat_val, $questions) . format SLOW_DMS = -Slow @<<<<<<< @>>>>>> @>>>>>/s @>>>>> %DMS: @>>>>> Log: @>> +Slow @<<<<<<< @>>>>>> @>>>>>/s @>>>>> %DMS: @>>>>> Log: @>> $slow_query_t, make_short($stats{'Slow_queries'}), t($stats{'Slow_queries'}), perc($stats{'Slow_queries'}, $questions), perc($stats{'Slow_queries'}, $dms), $vars{'log_slow_queries'} -DMS @>>>>>>>> @>>>>>/s @>>>>> +DMS @>>>>>>>> @>>>>>/s @>>>>> make_short($dms), t($dms), perc($dms, $questions) . format DMS = - @<<<<<<< @>>>>>>>> @>>>>>/s @>>>>> @>>>>> + @<<<<<<< @>>>>>>>> @>>>>>/s @>>>>> @>>>>> $stat_name, make_short($stat_val), t($stat_val), perc($stat_val, $questions), perc($stat_val, $dms) . format COM_1 = -Com_ @>>>>>>>> @>>>>>/s @>>>>> +Com_ @>>>>>>>> @>>>>>/s @>>>>> make_short($stat_val), t($stat_val), perc($stat_val, $questions) . format COM_2 = - @<<<<<<<<<< @>>>>>> @>>>>>/s @>>>>> + @<<<<<<<<<< @>>>>>> @>>>>>/s @>>>>> $stat_name, make_short($stat_val), t($stat_val), perc($stat_val, $questions) . format SAS = __ SELECT and Sort _____________________________________________________ -Scan @>>>>>> @>>>>/s %SELECT: @>>>>> +Scan @>>>>>> @>>>>>/s %SELECT: @>>>>> make_short($stats{'Select_scan'}), t($stats{'Select_scan'}), perc($stats{'Select_scan'}, $stats{'Com_select'}) -Range @>>>>>> @>>>>/s @>>>>> +Range @>>>>>> @>>>>>/s @>>>>> make_short($stats{'Select_range'}), t($stats{'Select_range'}), perc($stats{'Select_range'}, $stats{'Com_select'}) -Full join @>>>>>> @>>>>/s @>>>>> +Full join @>>>>>> @>>>>>/s @>>>>> make_short($stats{'Select_full_join'}), t($stats{'Select_full_join'}), perc($stats{'Select_full_join'}, $stats{'Com_select'}) -Range check @>>>>>> @>>>>/s @>>>>> +Range check @>>>>>> @>>>>>/s @>>>>> make_short($stats{'Select_range_check'}), t($stats{'Select_range_check'}), perc($stats{'Select_range_check'}, $stats{'Com_select'}) -Full rng join @>>>>>> @>>>>/s @>>>>> +Full rng join @>>>>>> @>>>>>/s @>>>>> make_short($stats{'Select_full_range_join'}), t($stats{'Select_full_range_join'}), perc($stats{'Select_full_range_join'}, $stats{'Com_select'}) -Sort scan @>>>>>> @>>>>/s +Sort scan @>>>>>> @>>>>>/s make_short($stats{'Sort_scan'}), t($stats{'Sort_scan'}) -Sort range @>>>>>> @>>>>/s +Sort range @>>>>>> @>>>>>/s make_short($stats{'Sort_range'}), t($stats{'Sort_range'}) -Sort mrg pass @>>>>>> @>>>>/s +Sort mrg pass @>>>>>> @>>>>>/s make_short($stats{'Sort_merge_passes'}), t($stats{'Sort_merge_passes'}) . format QCACHE = __ Query Cache _________________________________________________________ -Memory usage @>>>>>> of @>>>>>> %Used: @>>>>> +Memory usage @>>>>>> of @>>>>>> %Usage: @>>>>> make_short($qc_mem_used, 1), make_short($vars{'query_cache_size'}, 1), perc($qc_mem_used, $vars{'query_cache_size'}) Block Fragmnt @>>>>>% perc($stats{'Qcache_free_blocks'}, $stats{'Qcache_total_blocks'}) -Hits @>>>>>> @>>>>/s +Hits @>>>>>> @>>>>>/s make_short($stats{'Qcache_hits'}), t($stats{'Qcache_hits'}) -Inserts @>>>>>> @>>>>/s +Inserts @>>>>>> @>>>>>/s make_short($stats{'Qcache_inserts'}), t($stats{'Qcache_inserts'}) -Insrt:Prune @>>>>>>:1 @>>>>/s +Insrt:Prune @>>>>>>:1 @>>>>>/s make_short($qc_ip_r), t($stats{'Qcache_inserts'} - $stats{'Qcache_lowmem_prunes'}) Hit:Insert @>>>>>>:1 $qc_hi_r, t($qc_hi_r) . +format SUBQUERYCACHE = + +__ Subquery Cache ______________________________________________________ +Hit ratio @>>>>>% +perc($stats{'Subquery_cache_hit'} / ($stats{'Subquery_cache_hit'} + $stats{'Subquery_cache_miss'})) +Hits @>>>>>> @>>>>>/s +make_short($stats{'Subquery_cache_hit'}), t($stats{'Subquery_cache_hit'}) +Miss @>>>>>> @>>>>>/s +make_short($stats{'Subquery_cache_miss'}), t($stats{'Subquery_cache_miss'}) +. + # Not really the end... format REPORT_END = __ Table Locks _________________________________________________________ -Waited @>>>>>>>> @>>>>>/s %Total: @>>>>> +Waited @>>>>>>>> @>>>>>/s %Total: @>>>>> make_short($stats{'Table_locks_waited'}), t($stats{'Table_locks_waited'}), perc($stats{'Table_locks_waited'}, $stats{'Table_locks_waited'} + $stats{'Table_locks_immediate'}); -Immediate @>>>>>>>> @>>>>>/s +Immediate @>>>>>>>> @>>>>>/s make_short($stats{'Table_locks_immediate'}), t($stats{'Table_locks_immediate'}) __ Tables ______________________________________________________________ -Open @>>>>>>>> of @>>> %Cache: @>>>>> +Open @>>>>>>>> of @>>>>> %Cache: @>>>>> $stats{'Open_tables'}, $vars{'table_cache'}, perc($stats{'Open_tables'}, $vars{'table_cache'}) -Opened @>>>>>>>> @>>>>>/s +Opened @>>>>>>>> @>>>>>/s make_short($stats{'Opened_tables'}), t($stats{'Opened_tables'}) __ Connections _________________________________________________________ -Max used @>>>>>>>> of @>>> %Max: @>>>>> +Max used @>>>>>>>> of @>>>>> %Max: @>>>>> $stats{'Max_used_connections'}, $vars{'max_connections'}, perc($stats{'Max_used_connections'}, $vars{'max_connections'}) -Total @>>>>>>>> @>>>>>/s +Total @>>>>>>>> @>>>>>/s make_short($stats{'Connections'}), t($stats{'Connections'}) __ Created Temp ________________________________________________________ -Disk table @>>>>>>>> @>>>>>/s -make_short($stats{'Created_tmp_disk_tables'}), t($stats{'Created_tmp_disk_tables'}) -Table @>>>>>>>> @>>>>>/s Size: @>>>>> +Disk table @>>>>>>>> @>>>>>/s %Disk: @>>>>> +make_short($stats{'Created_tmp_disk_tables'}), t($stats{'Created_tmp_disk_tables'}), perc($stats{'Created_tmp_disk_tables'}, $stats{'Created_tmp_tables'}) +Table @>>>>>>>> @>>>>>/s Size: @>>>>> make_short($stats{'Created_tmp_tables'}), t($stats{'Created_tmp_tables'}), make_short($vars{'tmp_table_size'}, 1, 1) -File @>>>>>>>> @>>>>>/s +File @>>>>>>>> @>>>>>/s make_short($stats{'Created_tmp_files'}), t($stats{'Created_tmp_files'}) . -format TAB = +format THREADS = __ Threads _____________________________________________________________ -Running @>>>>>>>> of @>>> +Running @>>>>>>>> of @>>>>> $stats{'Threads_running'}, $stats{'Threads_connected'} -Cached @>>>>>>>> of @>>> %Hit: @>>>>> -$stats{'Threads_cached'}, $vars{'thread_cache_size'}, make_short(100 - perc($stats{'Threads_created'}, $stats{'Connections'})) -Created @>>>>>>>> @>>>>>/s +Created @>>>>>>>> @>>>>>/s make_short($stats{'Threads_created'}), t($stats{'Threads_created'}) -Slow @>>>>>>>> @>>>>>/s +Slow @>>>>>>>> @>>>>>/s $stats{'Slow_launch_threads'}, t($stats{'Slow_launch_threads'}) +. + +format THREADPERCONNECTION = +Cached @>>>>>>>> of @>>>>> %Hit: @>>>>> +$stats{'Threads_cached'}, $vars{'thread_cache_size'}, make_short(100 - perc($stats{'Threads_created'}, $stats{'Connections'})) +. + +format THREADPOOL = +Threadpool @>>>>>>>> of @>>>>> %Used: @>>>>> +$stats{'Threadpool_threads'} + $stats{'Threadpool_idle_threads'}, $vars{'thread_pool_max_threads'}, make_short(perc($stats{'Threadpool_threads'} + $stats{'Threadpool_idle_threads'}, $vars{'thread_pool_max_threads'})) + Running @>>>>>>>> of @>>>>> %Running: @>>>>> +$stats{'Threadpool_threads'}, $vars{'thread_pool_max_threads'}, make_short(perc($stats{'Threadpool_threads'}, $vars{'thread_pool_max_threads'})) + Idle @>>>>>>>> of @>>>>> %Idle: @>>>>> +$stats{'Threadpool_idle_threads'}, $vars{'thread_pool_max_threads'}, make_short(perc($stats{'Threadpool_idle_threads'}, $vars{'thread_pool_max_threads'})) +. + +format TAB = __ Aborted _____________________________________________________________ -Clients @>>>>>>>> @>>>>>/s +Clients @>>>>>>>> @>>>>>/s make_short($stats{'Aborted_clients'}), t($stats{'Aborted_clients'}) -Connects @>>>>>>>> @>>>>>/s +Connects @>>>>>>>> @>>>>>/s make_short($stats{'Aborted_connects'}), t($stats{'Aborted_connects'}) __ Bytes _______________________________________________________________ -Sent @>>>>>>>> @>>>>>/s +Sent @>>>>>>>> @>>>>>/s make_short($stats{'Bytes_sent'}), t($stats{'Bytes_sent'}) -Received @>>>>>>>> @>>>>>/s +Received @>>>>>>>> @>>>>>/s make_short($stats{'Bytes_received'}), t($stats{'Bytes_received'}) . format IB = __ InnoDB Buffer Pool __________________________________________________ -Usage @>>>>>> of @>>>>>> %Used: @>>>>> +Usage @>>>>>> of @>>>>>> %Usage: @>>>>> make_short($ib_bp_used, 1), make_short($ib_bp_total, 1), perc($ib_bp_used, $ib_bp_total) Read hit @>>>>>% $ib_bp_read_ratio; Pages - Free @>>>>>>>> %Total: @>>>>> + Free @>>>>>>>> %Total: @>>>>> make_short($stats{'Innodb_buffer_pool_pages_free'}), perc($stats{'Innodb_buffer_pool_pages_free'}, $stats{'Innodb_buffer_pool_pages_total'}) - Data @>>>>>>>> @>>>>> %Drty: @>>>>> + Data @>>>>>>>> @>>>>> %Drty: @>>>>> make_short($stats{'Innodb_buffer_pool_pages_data'}), perc($stats{'Innodb_buffer_pool_pages_data'}, $stats{'Innodb_buffer_pool_pages_total'}), perc($stats{'Innodb_buffer_pool_pages_dirty'}, $stats{'Innodb_buffer_pool_pages_data'}) - Misc @>>>>>>>> @>>>>> + Misc @>>>>>>>> @>>>>> $stats{'Innodb_buffer_pool_pages_misc'}, perc($stats{'Innodb_buffer_pool_pages_misc'}, $stats{'Innodb_buffer_pool_pages_total'}) - Latched @>>>>>>>> @>>>>> + Latched @>>>>>>>> @>>>>> $stats{'Innodb_buffer_pool_pages_latched'}, perc($stats{'Innodb_buffer_pool_pages_latched'}, $stats{'Innodb_buffer_pool_pages_total'}) -Reads @>>>>>>>> @>>>>>/s +Reads @>>>>>>>> @>>>>>/s make_short($stats{'Innodb_buffer_pool_read_requests'}), t($stats{'Innodb_buffer_pool_read_requests'}) - From file @>>>>>>>> @>>>>>/s @>>>>> + From disk @>>>>>>>> @>>>>>/s %Disk: @>>>>> make_short($stats{'Innodb_buffer_pool_reads'}), t($stats{'Innodb_buffer_pool_reads'}), perc($stats{'Innodb_buffer_pool_reads'}, $stats{'Innodb_buffer_pool_read_requests'}) - Ahead Rnd @>>>>>>>> @>>>>>/s + Ahead Rnd @>>>>>>>> @>>>>>/s $stats{'Innodb_buffer_pool_read_ahead_rnd'}, t($stats{'Innodb_buffer_pool_read_ahead_rnd'}) - Ahead Sql @>>>>>>>> @>>>>>/s -$stats{'Innodb_buffer_pool_read_ahead_seq'}, t($stats{'Innodb_buffer_pool_read_ahead_seq'}) -Writes @>>>>>>>> @>>>>>/s +# Ahead Sql @>>>>>>>> @>>>>>/s +#$stats{'Innodb_buffer_pool_read_ahead_seq'}, t($stats{'Innodb_buffer_pool_read_ahead_seq'}) +Writes @>>>>>>>> @>>>>>/s make_short($stats{'Innodb_buffer_pool_write_requests'}), t($stats{'Innodb_buffer_pool_write_requests'}) -Flushes @>>>>>>>> @>>>>>/s +Wait Free @>>>>>>>> @>>>>>/s %Wait: @>>>>> +$stats{'Innodb_buffer_pool_wait_free'}, t($stats{'Innodb_buffer_pool_wait_free'}), perc($stats{'Innodb_buffer_pool_wait_free'}, $stats{'Innodb_buffer_pool_write_requests'}) +Flushes @>>>>>>>> @>>>>>/s make_short($stats{'Innodb_buffer_pool_pages_flushed'}), t($stats{'Innodb_buffer_pool_pages_flushed'}) -Wait Free @>>>>>>>> @>>>>>/s -$stats{'Innodb_buffer_pool_wait_free'}, t($stats{'Innodb_buffer_pool_wait_free'}) +. + +format IB_XTRADB = + LRU @>>>>>>>> @>>>>>/s %LRU: @>>>>> +make_short($stats{'Innodb_buffer_pool_pages_lru_flushed'}), t($stats{'Innodb_buffer_pool_pages_lru_flushed'}), perc($stats{'Innodb_buffer_pool_pages_lru_flushed'}, $stats{'Innodb_buffer_pool_pages_flushed'}) . format IB_LOCK = __ InnoDB Lock _________________________________________________________ -Waits @>>>>>>>> @>>>>>/s +Waits @>>>>>>>> @>>>>>/s $stats{'Innodb_row_lock_waits'}, t($stats{'Innodb_row_lock_waits'}) Current @>>>>>>>> $stats{'Innodb_row_lock_current_waits'} @@ -1260,15 +1532,20 @@ $stats{'Innodb_row_lock_time_avg'} $stats{'Innodb_row_lock_time_max'} . +format IB_LOCK_XTRADB = +Trx history @>>>>>>>> +make_short($stats{'Innodb_history_list_length'}) +. + format IB_DPR = __ InnoDB Data, Pages, Rows ____________________________________________ Data - Reads @>>>>>>>> @>>>>>/s + Reads @>>>>>>>> @>>>>>/s make_short($stats{'Innodb_data_reads'}), t($stats{'Innodb_data_reads'}) - Writes @>>>>>>>> @>>>>>/s + Writes @>>>>>>>> @>>>>>/s make_short($stats{'Innodb_data_writes'}), t($stats{'Innodb_data_writes'}) - fsync @>>>>>>>> @>>>>>/s + fsync @>>>>>>>> @>>>>>/s make_short($stats{'Innodb_data_fsyncs'}), t($stats{'Innodb_data_fsyncs'}) Pending Reads @>>>>>>>> @@ -1279,20 +1556,71 @@ $stats{'Innodb_data_pending_writes'}, t($stats{'Innodb_data_pending_writes'}) $stats{'Innodb_data_pending_fsyncs'}, t($stats{'Innodb_data_pending_fsyncs'}) Pages - Created @>>>>>>>> @>>>>>/s + Created @>>>>>>>> @>>>>>/s make_short($stats{'Innodb_pages_created'}), t($stats{'Innodb_pages_created'}) - Read @>>>>>>>> @>>>>>/s + Read @>>>>>>>> @>>>>>/s make_short($stats{'Innodb_pages_read'}), t($stats{'Innodb_pages_read'}) - Written @>>>>>>>> @>>>>>/s + Written @>>>>>>>> @>>>>>/s make_short($stats{'Innodb_pages_written'}), t($stats{'Innodb_pages_written'}) Rows - Deleted @>>>>>>>> @>>>>>/s + Deleted @>>>>>>>> @>>>>>/s make_short($stats{'Innodb_rows_deleted'}), t($stats{'Innodb_rows_deleted'}) - Inserted @>>>>>>>> @>>>>>/s + Inserted @>>>>>>>> @>>>>>/s make_short($stats{'Innodb_rows_inserted'}), t($stats{'Innodb_rows_inserted'}) - Read @>>>>>>>> @>>>>>/s + Read @>>>>>>>> @>>>>>/s make_short($stats{'Innodb_rows_read'}), t($stats{'Innodb_rows_read'}) - Updated @>>>>>>>> @>>>>>/s + Updated @>>>>>>>> @>>>>>/s make_short($stats{'Innodb_rows_updated'}), t($stats{'Innodb_rows_updated'}) . + +format PAGECACHE_BUFF_MAX = + +__ Aria Pagecache ______________________________________________________ +Buffer used @>>>>>> of @>>>>>> %Used: @>>>>> +make_short($pagecache_buffer_used, 1), make_short($vars{'aria_pagecache_buffer_size'}, 1), perc($pagecache_buffer_used, $vars{'aria_pagecache_buffer_size'}) +. + +format PAGECACHE_BUFF_USAGE = + Current @>>>>>> %Usage: @>>>>> +make_short($pagecache_buffer_usage, 1), perc($pagecache_buffer_usage, $vars{'aria_pagecache_buffer_size'}) +. + +format PAGECACHE_RATIOS = +Write hit @>>>>>% +$pagecache_write_ratio +Read hit @>>>>>% +$pagecache_read_ratio +. + +format BINLOG = + +__ Binary Log Cache _____________________________________________________ +Disk use + Transactional @>>>>>% +perc($binlog_cache_ratio) + Non transactional @>>>>>% +perc($binlog_stmt_cache_ratio) +. + +format TOKUDB = + +__ TokuDB ______________________________________________________________ +Cachetable @>>>>>> of @>>>>>> %Usage: @>>>>> +make_short($stats{Tokudb_cachetable_size_current}, 1), make_short($vars{tokudb_cache_size}, 1), perc($stats{Tokudb_cachetable_size_current}, $vars{tokudb_cache_size}) + Miss @>>>>>> @>>>>>/s +make_short($stats{'Tokudb_cachetable_miss'}), t($stats{'Tokudb_cachetable_miss'}) + Evictions @>>>>>> @>>>>>/s +make_short($stats{'Tokudb_cachetable_evictions'}), t($stats{'Tokudb_cachetable_evictions'}) +. + +format ROWS = + +__ Rows ________________________________________________________________ +Rows @>>>>>>>> @>>>>>/s +make_short($rows), t($rows) + Using idx @>>>>>>>> @>>>>>/s %Index: @>>>>> +make_short($rows_using_indexes), t($rows_using_indexes), perc($rows_using_indexes,$rows) +Rows/question @>>>>>> +make_short($rows/$questions) +. diff --git a/debian/control b/debian/control index 2e706e6b548..e88325b49a6 100644 --- a/debian/control +++ b/debian/control @@ -12,6 +12,7 @@ Build-Depends: bison, libaio-dev, libboost-dev, libjudy-dev, + libkrb5-dev, libncurses5-dev (>= 5.0-6~), libpam0g-dev, libreadline-gplv2-dev, @@ -441,3 +442,15 @@ Depends: libcrack2 (>= 2.9.0), mariadb-server-10.2 Description: CrackLib Password Validation Plugin for MariaDB This password validation plugin uses cracklib to allow only sufficiently secure (as defined by cracklib) user passwords in MariaDB. + +Package: mariadb-gssapi-server-10.1 +Section: database +Architecture: any +Depends: libgssapi-krb5-2, mariadb-server-10.1 +Description: GSSAPI authentication plugin for MariaDB server + +Package: mariadb-gssapi-client-10.1 +Section: database +Architecture: any +Depends: libgssapi-krb5-2, mariadb-client-10.1 +Description: GSSAPI authentication plugin for MariaDB client diff --git a/debian/copyright b/debian/copyright index 5207620b411..1a31a958b99 100644 --- a/debian/copyright +++ b/debian/copyright @@ -9,7 +9,7 @@ The MariaDB packages were initally made by http://ourdelta.org/, and are now managed by the MariaDB development team, maria-developers@lists.launchpad.net -MariaDB can be downloaded from http://downloads.askmonty.org/mariadb/ +MariaDB can be downloaded from https://downloads.mariadb.org/ Copyright: diff --git a/debian/mariadb-client-10.2.README.Debian b/debian/mariadb-client-10.2.README.Debian index b245638f9c9..64f0f509951 100644 --- a/debian/mariadb-client-10.2.README.Debian +++ b/debian/mariadb-client-10.2.README.Debian @@ -1,4 +1,4 @@ FAQ: -Q: My <tab> completition is gone, why? +Q: My <tab> completion is gone, why? A: You have "no-auto-rehash" in the "[mysql]" section of /etc/mysql/my.cnf! diff --git a/debian/mariadb-gssapi-client-10.1.files b/debian/mariadb-gssapi-client-10.1.files new file mode 100644 index 00000000000..5a089e9352e --- /dev/null +++ b/debian/mariadb-gssapi-client-10.1.files @@ -0,0 +1 @@ +usr/lib/mysql/plugin/auth_gssapi_client.so diff --git a/debian/mariadb-gssapi-server-10.1.files b/debian/mariadb-gssapi-server-10.1.files new file mode 100644 index 00000000000..d5e7b362a74 --- /dev/null +++ b/debian/mariadb-gssapi-server-10.1.files @@ -0,0 +1 @@ +usr/lib/mysql/plugin/auth_gssapi.so diff --git a/debian/mariadb-server-10.2.files.in b/debian/mariadb-server-10.2.files.in index 633722ccb35..d562d285994 100644 --- a/debian/mariadb-server-10.2.files.in +++ b/debian/mariadb-server-10.2.files.in @@ -6,6 +6,7 @@ usr/lib/mysql/plugin/ha_blackhole.so usr/lib/mysql/plugin/ha_federated.so usr/lib/mysql/plugin/ha_federatedx.so usr/lib/mysql/plugin/ha_innodb.so +usr/lib/mysql/plugin/ha_mroonga.so usr/lib/mysql/plugin/ha_sphinx.so usr/lib/mysql/plugin/handlersocket.so usr/lib/mysql/plugin/locales.so @@ -18,6 +19,7 @@ usr/lib/mysql/plugin/server_audit.so usr/lib/mysql/plugin/simple_password_check.so usr/lib/mysql/plugin/sql_errlog.so usr/lib/mysql/plugin/wsrep_info.so +usr/lib/mysql/plugin/user_variables.so usr/lib/libhsclient.so.* etc/apparmor.d/usr.sbin.mysqld usr/share/apport/package-hooks/source_mariadb-10.2.py @@ -83,6 +85,8 @@ usr/share/mysql/echo_stderr usr/share/mysql/errmsg-utf8.txt usr/share/mysql/fill_help_tables.sql usr/share/mysql/maria_add_gis_sp_bootstrap.sql +usr/share/mysql/mroonga/install.sql +usr/share/mysql/mroonga/uninstall.sql usr/share/mysql/mysql_system_tables_data.sql usr/share/mysql/mysql_system_tables.sql usr/share/mysql/mysql_performance_tables.sql diff --git a/debian/mariadb-server-10.2.mysql-server.logrotate b/debian/mariadb-server-10.2.mysql-server.logrotate index 789ad353e43..a19e9ec46a2 100644 --- a/debian/mariadb-server-10.2.mysql-server.logrotate +++ b/debian/mariadb-server-10.2.mysql-server.logrotate @@ -10,18 +10,11 @@ compress sharedscripts postrotate - test -x /usr/bin/mysqladmin || exit 0 + test -x /usr/bin/mysqladmin || exit 0 - # If this fails, check debian.conf! - MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf" - if [ -z "`$MYADMIN ping 2>/dev/null`" ]; then - # Really no mysqld or rather a missing debian-sys-maint user? - # If this occurs and is not a error please report a bug. - if ps cax | grep -q mysqld; then - exit 1 - fi - else - $MYADMIN flush-logs - fi + if [ -f `my_print_defaults --mysqld | grep -oP "pid-file=\K[^$]+"` ]; then + # If this fails, check debian.conf! + mysqladmin --defaults-file=/etc/mysql/debian.cnf flush-logs + fi endscript } diff --git a/debian/mariadb-server-10.2.mysql.init b/debian/mariadb-server-10.2.mysql.init index ba92317c1cd..d5d0ab4ba93 100644 --- a/debian/mariadb-server-10.2.mysql.init +++ b/debian/mariadb-server-10.2.mysql.init @@ -37,6 +37,9 @@ umask 077 # so break my scripts. export HOME=/etc/mysql/ +# Source default config file. +[ -r /etc/default/mariadb ] && . /etc/default/mariadb + ## Fetch a particular option from mysql's invocation. # # Usage: void mysqld_get_param option @@ -109,7 +112,7 @@ case "${1:-''}" in /usr/bin/mysqld_safe "${@:2}" > /dev/null 2>&1 & # 6s was reported in #352070 to be too little - for i in $(seq 1 "${MYSQLD_STARTUP_TIMEOUT:-30}"); do + for i in $(seq 1 "${MYSQLD_STARTUP_TIMEOUT:-60}"); do sleep 1 if mysqld_status check_alive nowarn ; then break; fi log_progress_msg "." diff --git a/debian/mariadb-server-10.2.postinst b/debian/mariadb-server-10.2.postinst index 50b1000a26a..83f5d5e3cd0 100644 --- a/debian/mariadb-server-10.2.postinst +++ b/debian/mariadb-server-10.2.postinst @@ -240,7 +240,10 @@ db_stop # in case invoke failes # Thus MariaDB server is started via init.d script, which in turn redirects to # systemctl. If we upgrade from MySQL mysql.service may be masked, which also # means init.d script is disabled. Unmask mysql service explicitely. -deb-systemd-helper unmask mysql.service >/dev/null || true +# Check first that the command exists, to avoid emitting any warning messages. +if [ -x "$(command -v deb-systemd-helper)" ]; then + deb-systemd-helper unmask mysql.service > /dev/null +fi #DEBHELPER# diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index f3ba4234d2e..1ebcbf198ef 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -694,14 +694,14 @@ int main(int argc, char **argv) if (*filename == '\0') { fprintf(stderr, "Error; File name missing\n"); - goto error; + goto error_out; } /* stat the file to get size and page count */ if (stat(filename, &st)) { fprintf(stderr, "Error; %s cannot be found\n", filename); - goto error; + goto error_out; } size= st.st_size; @@ -711,7 +711,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Error; %s cannot be opened", filename); perror(" "); - goto error; + goto error_out; } big_buf = (unsigned char *)malloc(2 * UNIV_PAGE_SIZE_MAX); @@ -719,7 +719,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Error; failed to allocate memory\n"); perror(""); - goto error; + goto error_f; } /* Make sure the page is aligned */ @@ -731,7 +731,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Error; failed to allocate memory\n"); perror(""); - return 1; + goto error_big_buf; } /* Make sure the page is aligned */ @@ -983,12 +983,17 @@ ok: print_stats(); free(big_xdes); free(big_buf); + fclose(f); my_end(0); exit(0); error: free(big_xdes); +error_big_buf: free(big_buf); +error_f: + fclose(f); +error_out: my_end(0); exit(1); } diff --git a/extra/yassl/README b/extra/yassl/README index bf0e1c9f40f..81d573d0b20 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -12,6 +12,17 @@ before calling SSL_new(); *** end Note *** +yaSSL Release notes, version 2.3.9 (12/01/2015) + This release of yaSSL fixes two client side Diffie-Hellman problems. + yaSSL was only handling the cases of zero or one leading zeros for the key + agreement instead of potentially any number. This caused about 1 in 50,000 + connections to fail when using DHE cipher suites. The second problem was + the case where a server would send a public value shorter than the prime + value, causing about 1 in 128 client connections to fail, and also + caused the yaSSL client to read off the end of memory. All client side + DHE cipher suite users should update. + Thanks to Adam Langely (agl@imperialviolet.org) for the detailed report! + yaSSL Release notes, version 2.3.8 (9/17/2015) This release of yaSSL fixes a high security vulnerability. All users SHOULD update. If using yaSSL for TLS on the server side with private diff --git a/extra/yassl/include/crypto_wrapper.hpp b/extra/yassl/include/crypto_wrapper.hpp index b09b662c88c..0472b304679 100644 --- a/extra/yassl/include/crypto_wrapper.hpp +++ b/extra/yassl/include/crypto_wrapper.hpp @@ -378,6 +378,7 @@ public: uint get_agreedKeyLength() const; const byte* get_agreedKey() const; + uint get_publicKeyLength() const; const byte* get_publicKey() const; void makeAgreement(const byte*, unsigned int); diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index bec22427332..84ce40b8415 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -34,7 +34,7 @@ #include "rsa.h" -#define YASSL_VERSION "2.3.8" +#define YASSL_VERSION "2.3.9" #if defined(__cplusplus) diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp index 269976a6eaa..55b4b34f9c6 100644 --- a/extra/yassl/include/yassl_int.hpp +++ b/extra/yassl/include/yassl_int.hpp @@ -342,6 +342,7 @@ private: Sessions& GetSessions(); // forward singletons sslFactory& GetSSL_Factory(); Errors& GetErrors(); +bool HasErrors(); // openSSL method and context types diff --git a/extra/yassl/src/crypto_wrapper.cpp b/extra/yassl/src/crypto_wrapper.cpp index d8bc7a75ae3..031f7560801 100644 --- a/extra/yassl/src/crypto_wrapper.cpp +++ b/extra/yassl/src/crypto_wrapper.cpp @@ -751,9 +751,10 @@ struct DiffieHellman::DHImpl { byte* publicKey_; byte* privateKey_; byte* agreedKey_; + uint pubKeyLength_; DHImpl(TaoCrypt::RandomNumberGenerator& r) : ranPool_(r), publicKey_(0), - privateKey_(0), agreedKey_(0) {} + privateKey_(0), agreedKey_(0), pubKeyLength_(0) {} ~DHImpl() { ysArrayDelete(agreedKey_); @@ -762,7 +763,7 @@ struct DiffieHellman::DHImpl { } DHImpl(const DHImpl& that) : dh_(that.dh_), ranPool_(that.ranPool_), - publicKey_(0), privateKey_(0), agreedKey_(0) + publicKey_(0), privateKey_(0), agreedKey_(0), pubKeyLength_(0) { uint length = dh_.GetByteLength(); AllocKeys(length, length, length); @@ -810,7 +811,7 @@ DiffieHellman::DiffieHellman(const byte* p, unsigned int pSz, const byte* g, using TaoCrypt::Integer; pimpl_->dh_.Initialize(Integer(p, pSz).Ref(), Integer(g, gSz).Ref()); - pimpl_->publicKey_ = NEW_YS opaque[pubSz]; + pimpl_->publicKey_ = NEW_YS opaque[pimpl_->pubKeyLength_ = pubSz]; memcpy(pimpl_->publicKey_, pub, pubSz); } @@ -869,6 +870,10 @@ const byte* DiffieHellman::get_agreedKey() const return pimpl_->agreedKey_; } +uint DiffieHellman::get_publicKeyLength() const +{ + return pimpl_->pubKeyLength_; +} const byte* DiffieHellman::get_publicKey() const { diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index ccc1ad24b39..5603430a677 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -1493,7 +1493,8 @@ int SSLeay_add_ssl_algorithms() // compatibility only void ERR_remove_state(unsigned long) { - GetErrors().Remove(); + if (HasErrors()) + GetErrors().Remove(); } diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp index fec6a3394ca..f339655be3d 100644 --- a/extra/yassl/src/yassl_error.cpp +++ b/extra/yassl/src/yassl_error.cpp @@ -121,11 +121,11 @@ void SetErrorString(YasslError error, char* buffer) break; case certificate_error : - strncpy(buffer, "unable to proccess cerificate", max); + strncpy(buffer, "unable to process cerificate", max); break; case privateKey_error : - strncpy(buffer, "unable to proccess private key, bad format", max); + strncpy(buffer, "unable to process private key, bad format", max); break; case badVersion_error : diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp index 48d0e01b1fa..a481812b3e0 100644 --- a/extra/yassl/src/yassl_imp.cpp +++ b/extra/yassl/src/yassl_imp.cpp @@ -109,15 +109,12 @@ void ClientDiffieHellmanPublic::build(SSL& ssl) uint keyLength = dhClient.get_agreedKeyLength(); // pub and agree same alloc(keyLength, true); - dhClient.makeAgreement(dhServer.get_publicKey(), keyLength); + dhClient.makeAgreement(dhServer.get_publicKey(), + dhServer.get_publicKeyLength()); c16toa(keyLength, Yc_); memcpy(Yc_ + KEY_OFFSET, dhClient.get_publicKey(), keyLength); - // because of encoding first byte might be zero, don't use it for preMaster - if (*dhClient.get_agreedKey() == 0) - ssl.set_preMaster(dhClient.get_agreedKey() + 1, keyLength - 1); - else - ssl.set_preMaster(dhClient.get_agreedKey(), keyLength); + ssl.set_preMaster(dhClient.get_agreedKey(), keyLength); } @@ -321,11 +318,7 @@ void ClientDiffieHellmanPublic::read(SSL& ssl, input_buffer& input) } dh.makeAgreement(Yc_, keyLength); - // because of encoding, first byte might be 0, don't use for preMaster - if (*dh.get_agreedKey() == 0) - ssl.set_preMaster(dh.get_agreedKey() + 1, dh.get_agreedKeyLength() - 1); - else - ssl.set_preMaster(dh.get_agreedKey(), dh.get_agreedKeyLength()); + ssl.set_preMaster(dh.get_agreedKey(), dh.get_agreedKeyLength()); ssl.makeMasterSecret(); } diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp index 8dad9ce052c..9b447547c56 100644 --- a/extra/yassl/src/yassl_int.cpp +++ b/extra/yassl/src/yassl_int.cpp @@ -807,6 +807,19 @@ void SSL::set_random(const opaque* random, ConnectionEnd sender) // store client pre master secret void SSL::set_preMaster(const opaque* pre, uint sz) { + uint i(0); // trim leading zeros + uint fullSz(sz); + + while (i++ < fullSz && *pre == 0) { + sz--; + pre++; + } + + if (sz == 0) { + SetError(bad_input); + return; + } + secure_.use_connection().AllocPreSecret(sz); memcpy(secure_.use_connection().pre_master_secret_, pre, sz); } @@ -924,6 +937,8 @@ void SSL::order_error() // Create and store the master secret see page 32, 6.1 void SSL::makeMasterSecret() { + if (GetError()) return; + if (isTLS()) makeTLSMasterSecret(); else { @@ -1673,6 +1688,11 @@ Errors& GetErrors() return *errorsInstance; } +bool HasErrors() +{ + return (errorsInstance != 0); +} + typedef Mutex::Lock Lock; diff --git a/include/byte_order_generic_x86_64.h b/include/byte_order_generic_x86_64.h index 877c1574dfa..05c144f83cb 100644 --- a/include/byte_order_generic_x86_64.h +++ b/include/byte_order_generic_x86_64.h @@ -16,6 +16,7 @@ /* Optimized function-like macros for the x86 architecture (_WIN32 included). */ + #define sint2korr(A) (int16) (*((int16 *) (A))) #define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \ (((uint32) 255L << 24) | \ @@ -31,7 +32,7 @@ Attention: Please, note, uint3korr reads 4 bytes (not 3)! It means, that you have to provide enough allocated space. */ -#if defined(HAVE_purify) && !defined(_WIN32) +#if defined(HAVE_valgrind) && !defined(_WIN32) #define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\ (((uint32) ((uchar) (A)[1])) << 8) +\ (((uint32) ((uchar) (A)[2])) << 16)) @@ -39,17 +40,21 @@ #define uint3korr(A) (uint32) (*((unsigned int *) (A)) & 0xFFFFFF) #endif #define uint4korr(A) (uint32) (*((uint32 *) (A))) -#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\ - (((uint32) ((uchar) (A)[1])) << 8) +\ - (((uint32) ((uchar) (A)[2])) << 16) +\ - (((uint32) ((uchar) (A)[3])) << 24)) +\ - (((ulonglong) ((uchar) (A)[4])) << 32)) -#define uint6korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) + \ - (((uint32) ((uchar) (A)[1])) << 8) + \ - (((uint32) ((uchar) (A)[2])) << 16) + \ - (((uint32) ((uchar) (A)[3])) << 24)) + \ - (((ulonglong) ((uchar) (A)[4])) << 32) + \ - (((ulonglong) ((uchar) (A)[5])) << 40)) + + +static inline ulonglong uint5korr(const void *p) +{ + ulonglong a= *(uint32 *) p; + ulonglong b= *(4 + (uchar *) p); + return a | (b << 32); +} +static inline ulonglong uint6korr(const void *p) +{ + ulonglong a= *(uint32 *) p; + ulonglong b= *(uint16 *) (4 + (char *) p); + return a | (b << 32); +} + #define uint8korr(A) (ulonglong) (*((ulonglong *) (A))) #define sint8korr(A) (longlong) (*((longlong *) (A))) @@ -61,23 +66,67 @@ *(T+1)=(uchar) (((uint) (A) >> 8));\ *(T+2)=(uchar) (((A) >> 16));\ } while (0) + #define int4store(T,A) do { uchar *pT= (uchar*)(T);\ *((uint32 *) (pT))= (uint32) (A); \ } while (0) -#define int5store(T,A) do { *(T)= (uchar)((A));\ - *((T)+1)=(uchar) (((A) >> 8));\ - *((T)+2)=(uchar) (((A) >> 16));\ - *((T)+3)=(uchar) (((A) >> 24));\ - *((T)+4)=(uchar) (((A) >> 32));\ - } while(0) -#define int6store(T,A) do { *(T)= (uchar)((A)); \ - *((T)+1)=(uchar) (((A) >> 8)); \ - *((T)+2)=(uchar) (((A) >> 16)); \ - *((T)+3)=(uchar) (((A) >> 24)); \ - *((T)+4)=(uchar) (((A) >> 32)); \ - *((T)+5)=(uchar) (((A) >> 40)); \ - } while(0) +#define int5store(T,A) do { uchar *pT= (uchar*)(T);\ + *((uint32 *) (pT))= (uint32) (A); \ + *((pT)+4)=(uchar) (((A) >> 32));\ + } while (0) + +#define int6store(T,A) do { uchar *pT= (uchar*)(T);\ + *((uint32 *) (pT))= (uint32) (A); \ + *((uint16*)(pT+4))= (uint16) (A >> 32);\ + } while (0) + #define int8store(T,A) do { uchar *pT= (uchar*)(T);\ *((ulonglong *) (pT))= (ulonglong) (A);\ } while(0) + +#if defined(__GNUC__) + +#define HAVE_mi_uint5korr +#define HAVE_mi_uint6korr +#define HAVE_mi_uint7korr +#define HAVE_mi_uint78orr + +/* Read numbers stored in high-bytes-first order */ + +static inline ulonglong mi_uint5korr(const void *p) +{ + ulonglong a= *(uint32 *) p; + ulonglong b= *(4 + (uchar *) p); + ulonglong v= (a | (b << 32)) << 24; + asm ("bswapq %0" : "=r" (v) : "0" (v)); + return v; +} + +static inline ulonglong mi_uint6korr(const void *p) +{ + ulonglong a= *(uint32 *) p; + ulonglong b= *(uint16 *) (4 + (char *) p); + ulonglong v= (a | (b << 32)) << 16; + asm ("bswapq %0" : "=r" (v) : "0" (v)); + return v; +} + +static inline ulonglong mi_uint7korr(const void *p) +{ + ulonglong a= *(uint32 *) p; + ulonglong b= *(uint16 *) (4 + (char *) p); + ulonglong c= *(6 + (uchar *) p); + ulonglong v= (a | (b << 32) | (c << 48)) << 8; + asm ("bswapq %0" : "=r" (v) : "0" (v)); + return v; +} + +static inline ulonglong mi_uint8korr(const void *p) +{ + ulonglong v= *(ulonglong *) p; + asm ("bswapq %0" : "=r" (v) : "0" (v)); + return v; +} + +#endif diff --git a/include/m_ctype.h b/include/m_ctype.h index a55222682b0..615ee6ac1c6 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -400,7 +400,6 @@ struct my_charset_handler_st { my_bool (*init)(struct charset_info_st *, MY_CHARSET_LOADER *loader); /* Multibyte routines */ - uint (*ismbchar)(CHARSET_INFO *, const char *, const char *); uint (*mbcharlen)(CHARSET_INFO *, uint c); size_t (*numchars)(CHARSET_INFO *, const char *b, const char *e); size_t (*charpos)(CHARSET_INFO *, const char *b, const char *e, @@ -533,6 +532,7 @@ struct my_charset_handler_st extern MY_CHARSET_HANDLER my_charset_8bit_handler; extern MY_CHARSET_HANDLER my_charset_ucs2_handler; +extern MY_CHARSET_HANDLER my_charset_utf8_handler; /* @@ -800,16 +800,6 @@ uint my_instr_mb(CHARSET_INFO *, const char *s, size_t s_length, my_match_t *match, uint nmatch); -int my_strnncoll_mb_bin(CHARSET_INFO * cs, - const uchar *s, size_t slen, - const uchar *t, size_t tlen, - my_bool t_is_prefix); - -int my_strnncollsp_mb_bin(CHARSET_INFO *cs, - const uchar *a, size_t a_length, - const uchar *b, size_t b_length, - my_bool diff_if_only_endspace_difference); - int my_wildcmp_mb_bin(CHARSET_INFO *cs, const char *str,const char *str_end, const char *wildstr,const char *wildend, @@ -889,6 +879,18 @@ uint32 my_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, const char *from, uint32 from_length, CHARSET_INFO *from_cs, uint *errors); +/** + An extended version of my_convert(), to pass non-default mb_wc() and wc_mb(). + For example, String::copy_printable() which is used in + Protocol::store_warning() uses this to escape control + and non-convertable characters. +*/ +uint32 my_convert_using_func(char *to, uint32 to_length, CHARSET_INFO *to_cs, + my_charset_conv_wc_mb mb_wc, + const char *from, uint32 from_length, + CHARSET_INFO *from_cs, + my_charset_conv_mb_wc wc_mb, + uint *errors); /* Convert a string between two character sets. Bad byte sequences as well as characters that cannot be @@ -959,8 +961,42 @@ size_t my_convert_fix(CHARSET_INFO *dstcs, char *dst, size_t dst_length, #define my_strcasecmp(s, a, b) ((s)->coll->strcasecmp((s), (a), (b))) #define my_charpos(cs, b, e, num) (cs)->cset->charpos((cs), (const char*) (b), (const char *)(e), (num)) -#define use_mb(s) ((s)->cset->ismbchar != NULL) -#define my_ismbchar(s, a, b) ((s)->cset->ismbchar((s), (a), (b))) +#define use_mb(s) ((s)->mbmaxlen > 1) +/** + Detect if the leftmost character in a string is a valid multi-byte character + and return its length, or return 0 otherwise. + @param cs - character set + @param str - the beginning of the string + @param end - the string end (the next byte after the string) + @return >0, for a multi-byte character + @rerurn 0, for a single byte character, broken sequence, empty string. +*/ +static inline +uint my_ismbchar(CHARSET_INFO *cs, const char *str, const char *end) +{ + int char_length= (cs->cset->charlen)(cs, (const uchar *) str, + (const uchar *) end); + return char_length > 1 ? (uint) char_length : 0U; +} + + +/** + Return length of the leftmost character in a string. + @param cs - character set + @param str - the beginning of the string + @param end - the string end (the next byte after the string) + @return <=0 on errors (EOL, wrong byte sequence) + @return 1 on a single byte character + @return >1 on a multi-byte character + + Note, inlike my_ismbchar(), 1 is returned for a single byte character. +*/ +static inline +int my_charlen(CHARSET_INFO *cs, const char *str, const char *end) +{ + return (cs->cset->charlen)(cs, (const uchar *) str, + (const uchar *) end); +} #ifdef USE_MB #define my_mbcharlen(s, a) ((s)->cset->mbcharlen((s),(a))) #else diff --git a/include/my_atomic.h b/include/my_atomic.h index c75b65db38d..2034bf48987 100644 --- a/include/my_atomic.h +++ b/include/my_atomic.h @@ -280,6 +280,12 @@ make_atomic_store(32) make_atomic_store(64) make_atomic_store(ptr) +#if SIZEOF_LONG == 4 +#define my_atomic_addlong(A,B) my_atomic_add32((int32*) (A), (B)) +#else +#define my_atomic_addlong(A,B) my_atomic_add64((int64*) (A), (B)) +#endif + #ifdef _atomic_h_cleanup_ #include _atomic_h_cleanup_ #undef _atomic_h_cleanup_ diff --git a/include/my_bit.h b/include/my_bit.h index 174e0f70083..a50403c312d 100644 --- a/include/my_bit.h +++ b/include/my_bit.h @@ -121,6 +121,15 @@ static inline uint32 my_reverse_bits(uint32 key) _my_bits_reverse_table[(key>>24) ]; } +/* + a number with the n lowest bits set + an overflow-safe version of (1 << n) - 1 +*/ +static inline uint32 my_set_bits(int n) +{ + return (((1UL << (n - 1)) - 1) << 1) | 1; +} + C_MODE_END #endif /* MY_BIT_INCLUDED */ diff --git a/include/my_context.h b/include/my_context.h index 5de9f2882c5..ea0e3496887 100644 --- a/include/my_context.h +++ b/include/my_context.h @@ -31,7 +31,7 @@ #define MY_CONTEXT_USE_X86_64_GCC_ASM #elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__i386__) #define MY_CONTEXT_USE_I386_GCC_ASM -#elif defined(HAVE_UCONTEXT) +#elif defined(HAVE_UCONTEXT_H) #define MY_CONTEXT_USE_UCONTEXT #else #define MY_CONTEXT_DISABLE @@ -178,7 +178,7 @@ struct mysql_async_context { resumed, eg. whether we woke up due to connection completed or timeout in mysql_real_connect_cont(). */ - unsigned int events_occured; + unsigned int events_occurred; /* This is set to the result of the whole asynchronous operation when it completes. It uses a union, as different calls have different return diff --git a/include/my_global.h b/include/my_global.h index befc3bf4672..7ed306b8b56 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -198,20 +198,6 @@ #define likely(x) __builtin_expect(((x) != 0),1) #define unlikely(x) __builtin_expect(((x) != 0),0) -/* - now let's figure out if inline functions are supported - autoconf defines 'inline' to be empty, if not -*/ -#define inline_test_1(X) X ## 1 -#define inline_test_2(X) inline_test_1(X) -#if inline_test_2(inline) != 1 -#define HAVE_INLINE -#else -#error Compiler does not support inline! -#endif -#undef inline_test_2 -#undef inline_test_1 - /* Fix problem with S_ISLNK() on Linux */ #if defined(TARGET_OS_LINUX) || defined(__GLIBC__) #undef _GNU_SOURCE @@ -452,7 +438,7 @@ extern "C" int madvise(void *addr, size_t len, int behav); #endif #ifndef STDERR_FILENO -#define STDERR_FILENO 2 +#define STDERR_FILENO fileno(stderr) #endif #ifndef SO_EXT @@ -823,6 +809,9 @@ inline unsigned long long my_double2ulonglong(double d) #else #define finite(x) (1.0 / fabs(x) > 0.0) #endif /* HAVE_FINITE */ +#elif (__cplusplus >= 201103L) +#include <cmath> +static inline bool isfinite(double x) { return std::isfinite(x); } #endif /* isfinite */ #ifndef HAVE_ISNAN diff --git a/include/my_net.h b/include/my_net.h index 1ebb71ead23..91d780a276d 100644 --- a/include/my_net.h +++ b/include/my_net.h @@ -36,9 +36,11 @@ C_MODE_START #ifdef HAVE_ARPA_INET_H #include <arpa/inet.h> #endif -#ifdef HAVE_POLL +#if defined(HAVE_POLL_H) +#include <poll.h> +#elif defined(HAVE_SYS_POLL_H) #include <sys/poll.h> -#endif +#endif /* defined(HAVE_POLL_H) */ #ifdef HAVE_SYS_IOCTL_H #include <sys/ioctl.h> #endif diff --git a/include/my_pthread.h b/include/my_pthread.h index b18b9d824a2..991bc76c1ec 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -672,7 +672,7 @@ extern pthread_mutexattr_t my_errorcheck_mutexattr; #define ESRCH 1 #endif -typedef ulong my_thread_id; +typedef int64 my_thread_id; extern void my_threadattr_global_init(void); extern my_bool my_thread_global_init(void); @@ -694,7 +694,7 @@ extern void my_mutex_end(void); We need to have at least 256K stack to handle calls to myisamchk_init() with the current number of keys and key parts. */ -#define DEFAULT_THREAD_STACK (288*1024L) +#define DEFAULT_THREAD_STACK (290*1024L) #endif #define MY_PTHREAD_LOCK_READ 0 diff --git a/include/myisampack.h b/include/myisampack.h index 0795455dc3e..cfe1fcbc24a 100644 --- a/include/myisampack.h +++ b/include/myisampack.h @@ -52,11 +52,16 @@ (((uint32) (((const uchar*) (A))[2])) << 8) +\ (((uint32) (((const uchar*) (A))[1])) << 16) +\ (((uint32) (((const uchar*) (A))[0])) << 24))) + +#ifndef HAVE_mi_uint5korr #define mi_uint5korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[4])) +\ (((uint32) (((const uchar*) (A))[3])) << 8) +\ (((uint32) (((const uchar*) (A))[2])) << 16) +\ (((uint32) (((const uchar*) (A))[1])) << 24)) +\ (((ulonglong) (((const uchar*) (A))[0])) << 32)) +#endif /* HAVE_mi_uint5korr */ + +#ifndef HAVE_mi_uint6korr #define mi_uint6korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[5])) +\ (((uint32) (((const uchar*) (A))[4])) << 8) +\ (((uint32) (((const uchar*) (A))[3])) << 16) +\ @@ -64,6 +69,9 @@ (((ulonglong) (((uint32) (((const uchar*) (A))[1])) +\ (((uint32) (((const uchar*) (A))[0]) << 8)))) <<\ 32)) +#endif /* HAVE_mi_uint6korr */ + +#ifndef HAVE_mi_uint7korr #define mi_uint7korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[6])) +\ (((uint32) (((const uchar*) (A))[5])) << 8) +\ (((uint32) (((const uchar*) (A))[4])) << 16) +\ @@ -72,6 +80,9 @@ (((uint32) (((const uchar*) (A))[1])) << 8) +\ (((uint32) (((const uchar*) (A))[0])) << 16))) <<\ 32)) +#endif /* HAVE_mi_uint7korr */ + +#ifndef HAVE_mi_uint8korr #define mi_uint8korr(A) ((ulonglong)(((uint32) (((const uchar*) (A))[7])) +\ (((uint32) (((const uchar*) (A))[6])) << 8) +\ (((uint32) (((const uchar*) (A))[5])) << 16) +\ @@ -81,6 +92,7 @@ (((uint32) (((const uchar*) (A))[1])) << 16) +\ (((uint32) (((const uchar*) (A))[0])) << 24))) <<\ 32)) +#endif /* HAVE_mi_uint8korr */ /* This one is for uniformity */ #define mi_int1store(T,A) *((uchar*)(T))= (uchar) (A) diff --git a/include/mysql.h.pp b/include/mysql.h.pp index 5c3a9210ce8..0c06141df6c 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -9,6 +9,9 @@ enum enum_server_command COM_TABLE_DUMP, COM_CONNECT_OUT, COM_REGISTER_SLAVE, COM_STMT_PREPARE, COM_STMT_EXECUTE, COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE, COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH, COM_DAEMON, + COM_MDB_GAP_BEG, + COM_MDB_GAP_END=253, + COM_MULTI, COM_END }; struct st_vio; diff --git a/include/mysql/plugin_audit.h b/include/mysql/plugin_audit.h index 31589f071f0..7fb6e816181 100644 --- a/include/mysql/plugin_audit.h +++ b/include/mysql/plugin_audit.h @@ -56,7 +56,7 @@ struct mysql_event_general unsigned int general_command_length; const char *general_query; unsigned int general_query_length; - struct charset_info_st *general_charset; + const struct charset_info_st *general_charset; unsigned long long general_time; unsigned long long general_rows; /* Added in version 0x302 */ diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index f4df16afa67..8fc935262e2 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -422,7 +422,7 @@ struct mysql_event_general unsigned int general_command_length; const char *general_query; unsigned int general_query_length; - struct charset_info_st *general_charset; + const struct charset_info_st *general_charset; unsigned long long general_time; unsigned long long general_rows; unsigned long long query_id; diff --git a/include/mysql/psi/mysql_socket.h b/include/mysql/psi/mysql_socket.h index 202dc636eee..619f600a776 100644 --- a/include/mysql/psi/mysql_socket.h +++ b/include/mysql/psi/mysql_socket.h @@ -19,8 +19,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA #ifndef MYSQL_SOCKET_H #define MYSQL_SOCKET_H -/* For strlen() */ -#include <string.h> /* For MY_STAT */ #include <my_dir.h> /* For my_chsize */ diff --git a/include/mysql/psi/mysql_thread.h b/include/mysql/psi/mysql_thread.h index 0afbe6052f5..54a0eaabef7 100644 --- a/include/mysql/psi/mysql_thread.h +++ b/include/mysql/psi/mysql_thread.h @@ -1240,7 +1240,7 @@ static inline int inline_mysql_thread_create( return result; } -static inline void inline_mysql_thread_set_psi_id(ulong id) +static inline void inline_mysql_thread_set_psi_id(my_thread_id id) { struct PSI_thread *psi= PSI_THREAD_CALL(get_thread)(); PSI_THREAD_CALL(set_thread_id)(psi, id); diff --git a/include/mysql/service_progress_report.h b/include/mysql/service_progress_report.h index 670b1c37630..7ec3aa4c946 100644 --- a/include/mysql/service_progress_report.h +++ b/include/mysql/service_progress_report.h @@ -22,7 +22,7 @@ if requested. The functions are documented at - http://kb.askmonty.org/en/progress-reporting#how-to-add-support-for-progress-reporting-to-a-storage-engine + https://mariadb.com/kb/en/progress-reporting/#how-to-add-support-for-progress-reporting-to-a-storage-engine */ #ifdef __cplusplus diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h index 6b332f89958..bc5b2c67cdc 100644 --- a/include/mysql/service_wsrep.h +++ b/include/mysql/service_wsrep.h @@ -104,7 +104,7 @@ extern struct wsrep_service_st { const char * (*wsrep_thd_query_state_str_func)(THD *thd); int (*wsrep_thd_retry_counter_func)(THD *thd); void (*wsrep_thd_set_conflict_state_func)(THD *thd, enum wsrep_conflict_state state); - bool (*wsrep_thd_skip_append_keys_func)(THD *thd); + bool (*wsrep_thd_ignore_table_func)(THD *thd); long long (*wsrep_thd_trx_seqno_func)(THD *thd); struct wsrep_ws_handle * (*wsrep_thd_ws_handle_func)(THD *thd); int (*wsrep_trx_is_aborting_func)(MYSQL_THD thd); @@ -145,7 +145,7 @@ extern struct wsrep_service_st { #define wsrep_thd_query_state_str(T) wsrep_service->wsrep_thd_query_state_str_func(T) #define wsrep_thd_retry_counter(T) wsrep_service->wsrep_thd_retry_counter_func(T) #define wsrep_thd_set_conflict_state(T,S) wsrep_service->wsrep_thd_set_conflict_state_func(T,S) -#define wsrep_thd_skip_append_keys(T) wsrep_service->wsrep_thd_skip_append_keys_func(T) +#define wsrep_thd_ignore_table(T) wsrep_service->wsrep_thd_ignore_table_func(T) #define wsrep_thd_trx_seqno(T) wsrep_service->wsrep_thd_trx_seqno_func(T) #define wsrep_thd_ws_handle(T) wsrep_service->wsrep_thd_ws_handle_func(T) #define wsrep_trx_is_aborting(T) wsrep_service->wsrep_trx_is_aborting_func(T) @@ -206,7 +206,7 @@ void wsrep_thd_LOCK(THD *thd); void wsrep_thd_UNLOCK(THD *thd); void wsrep_thd_awake(THD *thd, my_bool signal); void wsrep_thd_set_conflict_state(THD *thd, enum wsrep_conflict_state state); -bool wsrep_thd_skip_append_keys(THD *thd); +bool wsrep_thd_ignore_table(THD *thd); void wsrep_unlock_rollback(); #endif diff --git a/include/mysql_com.h b/include/mysql_com.h index aa6ab0f0d0a..c13999a1028 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -102,7 +102,9 @@ enum enum_server_command COM_STMT_PREPARE, COM_STMT_EXECUTE, COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE, COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH, COM_DAEMON, /* don't forget to update const char *command_name[] in sql_parse.cc */ - + COM_MDB_GAP_BEG, + COM_MDB_GAP_END=253, + COM_MULTI, /* Must be last */ COM_END }; @@ -188,7 +190,8 @@ enum enum_server_command #define REFRESH_GENERIC (1ULL << 30) #define REFRESH_FAST (1ULL << 31) /* Intern flag */ -#define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */ +#define CLIENT_LONG_PASSWORD 0 /* obsolete flag */ +#define CLIENT_MYSQL 1 /* mysql/old mariadb server/client */ #define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */ #define CLIENT_LONG_FLAG 4 /* Get all column flags */ #define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */ @@ -215,7 +218,7 @@ enum enum_server_command /* Don't close the connection for a connection with expired password. */ #define CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS (1UL << 22) -#define CLIENT_PROGRESS (1UL << 29) /* Client support progress indicator */ +#define CLIENT_PROGRESS_OBSOLETE (1UL << 29) #define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30) /* It used to be that if mysql_real_connect() failed, it would delete any @@ -228,14 +231,25 @@ enum enum_server_command */ #define CLIENT_REMEMBER_OPTIONS (1UL << 31) +/* MariaDB extended capability flags */ +#define MARIADB_CLIENT_FLAGS_MASK 0xffffffff00000000ULL +/* Client support progress indicator */ +#define MARIADB_CLIENT_PROGRESS (1ULL << 32) +/* support COM_MULTI */ +#define MARIADB_CLIENT_COM_MULTI (1ULL << 33) + #ifdef HAVE_COMPRESS #define CAN_CLIENT_COMPRESS CLIENT_COMPRESS #else #define CAN_CLIENT_COMPRESS 0 #endif -/* Gather all possible capabilites (flags) supported by the server */ -#define CLIENT_ALL_FLAGS (CLIENT_LONG_PASSWORD | \ +/* + Gather all possible capabilites (flags) supported by the server + + MARIADB_* flags supported only by MariaDB connector(s). +*/ +#define CLIENT_ALL_FLAGS (\ CLIENT_FOUND_ROWS | \ CLIENT_LONG_FLAG | \ CLIENT_CONNECT_WITH_DB | \ @@ -256,10 +270,11 @@ enum enum_server_command CLIENT_PS_MULTI_RESULTS | \ CLIENT_SSL_VERIFY_SERVER_CERT | \ CLIENT_REMEMBER_OPTIONS | \ - CLIENT_PROGRESS | \ + MARIADB_CLIENT_PROGRESS | \ CLIENT_PLUGIN_AUTH | \ CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | \ - CLIENT_CONNECT_ATTRS) + CLIENT_CONNECT_ATTRS |\ + MARIADB_CLIENT_COM_MULTI) /* To be added later: diff --git a/include/probes_mysql_nodtrace.h b/include/probes_mysql_nodtrace.h.in index 2155e8489da..2155e8489da 100644 --- a/include/probes_mysql_nodtrace.h +++ b/include/probes_mysql_nodtrace.h.in diff --git a/include/thread_pool_priv.h b/include/thread_pool_priv.h index 4270c32c826..afa2848ae88 100644 --- a/include/thread_pool_priv.h +++ b/include/thread_pool_priv.h @@ -100,8 +100,6 @@ bool thd_is_connection_alive(THD *thd); void close_connection(THD *thd, uint errcode); /* End the connection before closing it */ void end_connection(THD *thd); -/* Cleanup the THD object */ -void thd_cleanup(THD *thd); /* Decrement connection counter */ void dec_connection_count(); /* Destroy THD object */ diff --git a/include/violite.h b/include/violite.h index d5ce66c3061..a7165ca91a9 100644 --- a/include/violite.h +++ b/include/violite.h @@ -208,7 +208,7 @@ void vio_end(void); /* shutdown(2) flags */ #ifndef SHUT_RD -#define SHUT_RD SD_BOTH +#define SHUT_RD SD_RECEIVE #endif /* diff --git a/include/welcome_copyright_notice.h b/include/welcome_copyright_notice.h index 096d42446bc..e9891856221 100644 --- a/include/welcome_copyright_notice.h +++ b/include/welcome_copyright_notice.h @@ -1,5 +1,5 @@ -/* Copyright (c) 2011, 2015, Oracle and/or its affiliates. - Copyright (c) 2011, 2015, MariaDB +/* Copyright (c) 2011, 2016, Oracle and/or its affiliates. + Copyright (c) 2011, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ #ifndef _welcome_copyright_notice_h_ #define _welcome_copyright_notice_h_ -#define COPYRIGHT_NOTICE_CURRENT_YEAR "2015" +#define COPYRIGHT_NOTICE_CURRENT_YEAR "2016" /* This define specifies copyright notice which is displayed by every MySQL diff --git a/include/wsrep.h b/include/wsrep.h index a91f312d0a6..0f5455c8d50 100644 --- a/include/wsrep.h +++ b/include/wsrep.h @@ -31,6 +31,14 @@ if (WSREP_ON && (WSREP(thd) || (thd && thd->wsrep_exec_mode==TOTAL_ORDER))) \ wsrep_to_isolation_end(thd); +/* + Checks if lex->no_write_to_binlog is set for statements that use LOCAL or + NO_WRITE_TO_BINLOG. +*/ +#define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_) \ + if (WSREP(thd) && !thd->lex->no_write_to_binlog \ + && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto error; + #define WSREP_DEBUG(...) \ if (wsrep_debug) WSREP_LOG(sql_print_information, ##__VA_ARGS__) #define WSREP_INFO(...) WSREP_LOG(sql_print_information, ##__VA_ARGS__) @@ -46,6 +54,7 @@ #define WSREP_ERROR(...) #define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) #define WSREP_TO_ISOLATION_END +#define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_) #endif #endif /* WSERP_INCLUDED */ diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index b233614fa1e..2577870bfa3 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -27,7 +27,7 @@ extern char * mysql_unix_port; When adding capabilities here, consider if they should be also added to the server's version. */ -#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | \ +#define CLIENT_CAPABILITIES (CLIENT_MYSQL | \ CLIENT_LONG_FLAG | \ CLIENT_TRANSACTIONS | \ CLIENT_PROTOCOL_41 | \ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 8af5a284b9a..d5d673bb895 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -47,9 +47,11 @@ #include <sys/select.h> #endif #endif /* !defined(__WIN__) */ -#ifdef HAVE_POLL +#if defined(HAVE_POLL_H) +#include <poll.h> +#elif defined(HAVE_SYS_POLL_H) #include <sys/poll.h> -#endif +#endif /* defined(HAVE_POLL_H) */ #ifdef HAVE_SYS_UN_H #include <sys/un.h> #endif @@ -2231,7 +2233,7 @@ static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row) /* Read one row from network: unbuffered non-cursor fetch. - If last row was read, or error occured, erase this statement + If last row was read, or error occurred, erase this statement from record pointing to object unbuffered fetch is performed from. SYNOPSIS diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 2bdbc41a347..ad16584ec0e 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -110,6 +110,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ../sql/item_inetfunc.cc ../sql/wsrep_dummy.cc ../sql/encryption.cc ../sql/item_windowfunc.cc ../sql/sql_window.cc + ../sql/sql_cte.cc ${GEN_SOURCES} ${MYSYS_LIBWRAP_SOURCE} ) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 5035064b8e0..476981023fd 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -165,7 +165,8 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, arg_length= header_length; } - result= dispatch_command(command, thd, (char *) arg, arg_length); + result= dispatch_command(command, thd, (char *) arg, arg_length, FALSE, + FALSE); thd->cur_data= 0; thd->mysys_var= NULL; @@ -428,8 +429,8 @@ static void emb_free_embedded_thd(MYSQL *mysql) thread_count--; thd->store_globals(); thd->unlink(); - delete thd; mysql_mutex_unlock(&LOCK_thread_count); + delete thd; my_pthread_setspecific_ptr(THR_THD, 0); mysql->thd=0; } @@ -664,7 +665,7 @@ void init_embedded_mysql(MYSQL *mysql, int client_flag) void *create_embedded_thd(int client_flag) { THD * thd= new THD; - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; + thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id(); thd->thread_stack= (char*) &thd; if (thd->store_globals()) diff --git a/man/comp_err.1 b/man/comp_err.1 index da1cf031636..c566e2d11e0 100644 --- a/man/comp_err.1 +++ b/man/comp_err.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBCOMP_ERR\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBCOMP_ERR\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/innochecksum.1 b/man/innochecksum.1 index c4c02647211..72614ad1617 100644 --- a/man/innochecksum.1 +++ b/man/innochecksum.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBINNOCHECKSUM\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBINNOCHECKSUM\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/make_win_bin_dist.1 b/man/make_win_bin_dist.1 index a49641868b6..32043390059 100644 --- a/man/make_win_bin_dist.1 +++ b/man/make_win_bin_dist.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMAKE_WIN_BIN_DIST" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMAKE_WIN_BIN_DIST" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/msql2mysql.1 b/man/msql2mysql.1 index d7c37afe830..dfe5ebf4d89 100644 --- a/man/msql2mysql.1 +++ b/man/msql2mysql.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMSQL2MYSQL\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMSQL2MYSQL\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/my_print_defaults.1 b/man/my_print_defaults.1 index 814db1db336..857566133e3 100644 --- a/man/my_print_defaults.1 +++ b/man/my_print_defaults.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMY_PRINT_DEFAULTS" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMY_PRINT_DEFAULTS" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/myisam_ftdump.1 b/man/myisam_ftdump.1 index fbcafd0b255..eb383605084 100644 --- a/man/myisam_ftdump.1 +++ b/man/myisam_ftdump.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYISAM_FTDUMP\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYISAM_FTDUMP\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/myisamchk.1 b/man/myisamchk.1 index 0582b92cdc0..e13df134882 100644 --- a/man/myisamchk.1 +++ b/man/myisamchk.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYISAMCHK\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYISAMCHK\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/myisamlog.1 b/man/myisamlog.1 index 043f974d535..25e4b5d8640 100644 --- a/man/myisamlog.1 +++ b/man/myisamlog.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYISAMLOG\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYISAMLOG\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/myisampack.1 b/man/myisampack.1 index a9a50d5b939..e3f301df156 100644 --- a/man/myisampack.1 +++ b/man/myisampack.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYISAMPACK\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYISAMPACK\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql-stress-test.pl.1 b/man/mysql-stress-test.pl.1 index 4f20384c0cf..0e47538efbe 100644 --- a/man/mysql-stress-test.pl.1 +++ b/man/mysql-stress-test.pl.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL\-STRESS\-TE" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL\-STRESS\-TE" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql-test-run.pl.1 b/man/mysql-test-run.pl.1 index 883aef4d5ad..784e62a3c66 100644 --- a/man/mysql-test-run.pl.1 +++ b/man/mysql-test-run.pl.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL\-TEST\-RUN\" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL\-TEST\-RUN\" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- @@ -1583,7 +1583,7 @@ may fail in total, as each repetition is considered a new test case, which may i \fB\-\-retry\-failure=\fR\fB\fIN\fR\fR .sp When using the \fB-\-retry\fR option to retry failed tests, -stop when N failures have occured (default 2)\&. Setting it to 0 or 1 effectively turns off retries\&. +stop when N failures have occurred (default 2)\&. Setting it to 0 or 1 effectively turns off retries\&. .RE .sp .RS 4 diff --git a/man/mysql.1 b/man/mysql.1 index ec11f050c7e..e4c0727d1ae 100644 --- a/man/mysql.1 +++ b/man/mysql.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql.server.1 b/man/mysql.server.1 index 3aed4452eec..252d8002ca2 100644 --- a/man/mysql.server.1 +++ b/man/mysql.server.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL\&.SERVER\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL\&.SERVER\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql_client_test.1 b/man/mysql_client_test.1 index fc5f2a9d4e2..21da6397b2b 100644 --- a/man/mysql_client_test.1 +++ b/man/mysql_client_test.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL_CLIENT_TEST" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL_CLIENT_TEST" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql_config.1 b/man/mysql_config.1 index 47e8a3a0ee4..91b04b65f75 100644 --- a/man/mysql_config.1 +++ b/man/mysql_config.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL_CONFIG\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL_CONFIG\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql_convert_table_format.1 b/man/mysql_convert_table_format.1 index bd4ce64ea03..0d46fa44151 100644 --- a/man/mysql_convert_table_format.1 +++ b/man/mysql_convert_table_format.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL_CONVERT_TAB" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL_CONVERT_TAB" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql_find_rows.1 b/man/mysql_find_rows.1 index 8d42bffdc93..0c38b91f523 100644 --- a/man/mysql_find_rows.1 +++ b/man/mysql_find_rows.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL_FIND_ROWS\F" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL_FIND_ROWS\F" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql_fix_extensions.1 b/man/mysql_fix_extensions.1 index c7057cce03a..04d96fd9058 100644 --- a/man/mysql_fix_extensions.1 +++ b/man/mysql_fix_extensions.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL_FIX_EXTENSI" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL_FIX_EXTENSI" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql_install_db.1 b/man/mysql_install_db.1 index 9fb775f2099..716fb56956d 100644 --- a/man/mysql_install_db.1 +++ b/man/mysql_install_db.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL_INSTALL_DB\" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL_INSTALL_DB\" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql_plugin.1 b/man/mysql_plugin.1 index b3feb3f19ca..0326a7ddb09 100644 --- a/man/mysql_plugin.1 +++ b/man/mysql_plugin.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL_PLUGIN\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL_PLUGIN\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff --git a/man/mysql_secure_installation.1 b/man/mysql_secure_installation.1 index 4b24588ef26..19522042e87 100644 --- a/man/mysql_secure_installation.1 +++ b/man/mysql_secure_installation.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL_SECURE_INST" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL_SECURE_INST" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql_setpermission.1 b/man/mysql_setpermission.1 index d3697c2c95f..0ca22ca27dd 100644 --- a/man/mysql_setpermission.1 +++ b/man/mysql_setpermission.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL_SETPERMISSI" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL_SETPERMISSI" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql_tzinfo_to_sql.1 b/man/mysql_tzinfo_to_sql.1 index 8f96d3f659a..ece013dd40f 100644 --- a/man/mysql_tzinfo_to_sql.1 +++ b/man/mysql_tzinfo_to_sql.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL_TZINFO_TO_S" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL_TZINFO_TO_S" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql_upgrade.1 b/man/mysql_upgrade.1 index 48ea44a5ac9..62e39393240 100644 --- a/man/mysql_upgrade.1 +++ b/man/mysql_upgrade.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL_UPGRADE\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL_UPGRADE\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysql_waitpid.1 b/man/mysql_waitpid.1 index c5f0c9d0c93..ae645be872f 100644 --- a/man/mysql_waitpid.1 +++ b/man/mysql_waitpid.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQL_WAITPID\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQL_WAITPID\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysqlaccess.1 b/man/mysqlaccess.1 index 0262870e68e..02b5169b50d 100644 --- a/man/mysqlaccess.1 +++ b/man/mysqlaccess.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLACCESS\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLACCESS\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysqladmin.1 b/man/mysqladmin.1 index 14e34ed2f84..3fb78d33f14 100644 --- a/man/mysqladmin.1 +++ b/man/mysqladmin.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLADMIN\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLADMIN\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysqlbinlog.1 b/man/mysqlbinlog.1 index 12fc8925949..34cf246ff1b 100644 --- a/man/mysqlbinlog.1 +++ b/man/mysqlbinlog.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLBINLOG\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLBINLOG\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- @@ -708,6 +708,22 @@ entries in the log\&. .sp -1 .IP \(bu 2.3 .\} +.\" mysqlbinlog: open-files-limit option +.\" open-files-limit option: mysqlbinlog +\fB\-\-open\-files\-limit=\fR\fB\fINUM\fR\fR +.sp +Sets the open_files_limit variable, which is used to reserve file descriptors for +\fBmysqlbinlog\fR\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} .\" mysqlbinlog: password option .\" password option: mysqlbinlog \fB\-\-password[=\fR\fB\fIpassword\fR\fR\fB]\fR, @@ -800,12 +816,11 @@ The connection protocol to use for connecting to the server\&. It is useful when .sp -1 .IP \(bu 2.3 .\} -.\" mysqlbinlog: open-files-limit option -.\" open-files-limit option: mysqlbinlog -\fB\-\-open\-files\-limit=\fR\fB\fINUM\fR\fR +.\" mysqlbinlog: raw option +.\" raw option: mysqlbinlog +\fB\-\-raw\fR .sp -Sets the open_files_limit variable, which is used to reserve file descriptors for -\fBmysqlbinlog\fR\&. +Requires \fB-R\fR\&. Output raw binlog data instead of SQL statements\&. Output files named after server logs\&. .RE .sp .RS 4 @@ -845,7 +860,7 @@ This option requires that the remote server be running\&. It works only for bina \fB\-\-result\-file=\fR\fB\fIname\fR\fR, \fB\-r \fR\fB\fIname\fR\fR .sp -Direct output to the given file\&. +Direct output to the given file\&. With --raw this is a prefix for the file names\&. .RE .sp .RS 4 @@ -1028,6 +1043,36 @@ This option is useful for point\-in\-time recovery\&. .sp -1 .IP \(bu 2.3 .\} +.\" mysqlbinlog: stop-never option +.\" stop-never option: mysqlbinlog +\fB\-\-stop\-never\fR +.sp +Wait for more data from the server instead of stopping at the end of the last log\&. Implies \fB--to-last-log\fR\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +.\" mysqlbinlog: stop-never-slave-server-id option +.\" stop-never-slave-server-id option: mysqlbinlog +\fB\-\-stop\-never-slave-server-id\fR +.sp +The slave server_id used for \fB--read-from-remote-server --stop-never\fR\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} .\" mysqlbinlog: stop-position option .\" stop-position option: mysqlbinlog \fB\-\-stop\-position=\fR\fB\fIN\fR\fR diff --git a/man/mysqlcheck.1 b/man/mysqlcheck.1 index 914a6f8952e..abc8d64c2af 100644 --- a/man/mysqlcheck.1 +++ b/man/mysqlcheck.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLCHECK\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLCHECK\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- @@ -179,6 +179,7 @@ supports the following options, which can be specified on the command line or in and [client] option file groups\&. +The \fB-c\fR, \fB-r\fR, \fB-a\fR and \fB-o\fR options are exclusive to each other\&. .sp .RS 4 .ie n \{\ diff --git a/man/mysqld.8 b/man/mysqld.8 index 37cdbb3e1f2..b77b551bd48 100644 --- a/man/mysqld.8 +++ b/man/mysqld.8 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLD\FR" "8" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLD\FR" "8" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysqld_multi.1 b/man/mysqld_multi.1 index d40ecfff3db..fdb073a68bf 100644 --- a/man/mysqld_multi.1 +++ b/man/mysqld_multi.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLD_MULTI\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLD_MULTI\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysqld_safe.1 b/man/mysqld_safe.1 index a70fb0cd439..eb31d05d4ef 100644 --- a/man/mysqld_safe.1 +++ b/man/mysqld_safe.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLD_SAFE\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLD_SAFE\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysqldump.1 b/man/mysqldump.1 index 6242f40a9bc..a734d5eeb70 100644 --- a/man/mysqldump.1 +++ b/man/mysqldump.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLDUMP\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLDUMP\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysqldumpslow.1 b/man/mysqldumpslow.1 index c33f86c0479..47dffef7edd 100644 --- a/man/mysqldumpslow.1 +++ b/man/mysqldumpslow.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLDUMPSLOW\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLDUMPSLOW\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysqlhotcopy.1 b/man/mysqlhotcopy.1 index c06858b6fb3..bb6f83ac810 100644 --- a/man/mysqlhotcopy.1 +++ b/man/mysqlhotcopy.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLHOTCOPY\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLHOTCOPY\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysqlimport.1 b/man/mysqlimport.1 index d14d6a03edf..4c4ed342d7a 100644 --- a/man/mysqlimport.1 +++ b/man/mysqlimport.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLIMPORT\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLIMPORT\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysqlshow.1 b/man/mysqlshow.1 index c4ee9f40c45..1790978144a 100644 --- a/man/mysqlshow.1 +++ b/man/mysqlshow.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLSHOW\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLSHOW\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysqlslap.1 b/man/mysqlslap.1 index 7bf08e29122..e3246e811bf 100644 --- a/man/mysqlslap.1 +++ b/man/mysqlslap.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLSLAP\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLSLAP\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/mysqltest.1 b/man/mysqltest.1 index 4e75c7450e4..772702e4091 100644 --- a/man/mysqltest.1 +++ b/man/mysqltest.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLTEST\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBMYSQLTEST\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/perror.1 b/man/perror.1 index 2108a6b76d3..3a680c96201 100644 --- a/man/perror.1 +++ b/man/perror.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBPERROR\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBPERROR\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/replace.1 b/man/replace.1 index f6bb858e67d..5c63027535e 100644 --- a/man/replace.1 +++ b/man/replace.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBREPLACE\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBREPLACE\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/resolve_stack_dump.1 b/man/resolve_stack_dump.1 index f12726d01f2..693c84e8da0 100644 --- a/man/resolve_stack_dump.1 +++ b/man/resolve_stack_dump.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBRESOLVE_STACK_DUM" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBRESOLVE_STACK_DUM" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/man/resolveip.1 b/man/resolveip.1 index 07f344ebcf3..2f1c4a1a290 100644 --- a/man/resolveip.1 +++ b/man/resolveip.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBRESOLVEIP\FR" "1" "14/12/2015" "MariaDB 10\&.1" "MariaDB Database System" +.TH "\FBRESOLVEIP\FR" "1" "22/3/2016" "MariaDB 10\&.2" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- diff --git a/mysql-test/README b/mysql-test/README index 162551ad69c..0fba1cc07e3 100644 --- a/mysql-test/README +++ b/mysql-test/README @@ -11,7 +11,7 @@ All tests must pass. If one or more of them fail on your system, please read the following manual section for instructions on how to report the problem: -http://kb.askmonty.org/v/reporting-bugs +https://mariadb.com/kb/en/reporting-bugs If you want to use an already running MySQL server for specific tests, use the --extern option to mysql-test-run. Please note that in this mode, diff --git a/mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test b/mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test index e1faec8440b..0f46b00f683 100644 --- a/mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test +++ b/mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test @@ -375,7 +375,7 @@ source include/start_slave.inc; CALL mtr.add_suppression("Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage.*"); CALL mtr.add_suppression("Multi-statement transaction required more than 'max_binlog_stmt_cache_size' bytes of storage.*"); CALL mtr.add_suppression("Writing one row to the row-based binary log failed.*"); -CALL mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occured on the master. Message: error writing to the binary log"); +CALL mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occurred on the master. Message: error writing to the binary log"); connection master; TRUNCATE t1; diff --git a/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test b/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test index 5cbda2d591f..a8cec3d2a1a 100644 --- a/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test +++ b/mysql-test/extra/rpl_tests/rpl_flsh_tbls.test @@ -45,7 +45,13 @@ drop table t1; connection slave; flush tables with read lock; start slave; -source include/wait_for_slave_to_start.inc; + +# The IO thread will not be able to read the GTID because of flush tables +let $slave_param= Slave_IO_Running; +let $slave_param_value= Preparing; +source include/wait_for_slave_param.inc; + +--source include/wait_for_slave_sql_to_start.inc --error 1192 stop slave; diff --git a/mysql-test/include/galera_clear_sync_point.inc b/mysql-test/include/galera_clear_sync_point.inc new file mode 100644 index 00000000000..589522a55b0 --- /dev/null +++ b/mysql-test/include/galera_clear_sync_point.inc @@ -0,0 +1 @@ +SET GLOBAL wsrep_provider_options = 'dbug='; diff --git a/mysql-test/include/galera_set_sync_point.inc b/mysql-test/include/galera_set_sync_point.inc new file mode 100644 index 00000000000..5fe4e8c38c0 --- /dev/null +++ b/mysql-test/include/galera_set_sync_point.inc @@ -0,0 +1 @@ +--eval SET GLOBAL wsrep_provider_options = 'dbug=d,$galera_sync_point' diff --git a/mysql-test/include/galera_signal_sync_point.inc b/mysql-test/include/galera_signal_sync_point.inc new file mode 100644 index 00000000000..eaa5cdd43f5 --- /dev/null +++ b/mysql-test/include/galera_signal_sync_point.inc @@ -0,0 +1 @@ +--eval SET GLOBAL wsrep_provider_options = 'signal=$galera_sync_point' diff --git a/mysql-test/include/galera_wait_sync_point.inc b/mysql-test/include/galera_wait_sync_point.inc new file mode 100644 index 00000000000..cf3a4980186 --- /dev/null +++ b/mysql-test/include/galera_wait_sync_point.inc @@ -0,0 +1,6 @@ +--let $wait_timeout = 10 +--let $wsrep_on_orig = `SELECT @@wsrep_on` +SET SESSION wsrep_on = 0; +--let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters' AND VARIABLE_VALUE = '$galera_sync_point' +--source include/wait_condition.inc +--eval SET SESSION wsrep_on = $wsrep_on_orig diff --git a/mysql-test/include/mtr_check.sql b/mysql-test/include/mtr_check.sql index e54041da1bc..6b25c75276c 100644 --- a/mysql-test/include/mtr_check.sql +++ b/mysql-test/include/mtr_check.sql @@ -40,6 +40,11 @@ BEGIN -- except those that was created during bootstrap SELECT * FROM INFORMATION_SCHEMA.SCHEMATA; + -- and the mtr_wsrep_notify schema which is populated by the std_data/wsrep_notify.sh script + -- and the suite/galera/t/galera_var_notify_cmd.test + -- and the wsrep_schema schema that may be created by Galera + SELECT * FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME NOT IN ('mtr_wsrep_notify', 'wsrep_schema'); + -- The test database should not contain any tables SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql index 1ee0658204d..278add92ba5 100644 --- a/mysql-test/include/mtr_warnings.sql +++ b/mysql-test/include/mtr_warnings.sql @@ -133,7 +133,7 @@ INSERT INTO global_suppressions VALUES ("Slave: Query caused different errors on master and slave"), ("Slave: Table .* doesn't exist"), ("Slave: Table width mismatch"), - ("Slave: The incident LOST_EVENTS occured on the master"), + ("Slave: The incident LOST_EVENTS occurred on the master"), ("Slave: Unknown error.* 1105"), ("Slave: Can't drop database.* database doesn't exist"), ("Warning:\s+One can only use the --user.*root"), diff --git a/mysql-test/lib/My/SafeProcess.pm b/mysql-test/lib/My/SafeProcess.pm index e7917f8fb16..a9b4f9a4ecc 100644 --- a/mysql-test/lib/My/SafeProcess.pm +++ b/mysql-test/lib/My/SafeProcess.pm @@ -34,7 +34,7 @@ package My::SafeProcess; # will zap the "monitored process" and exit # - the "monitored process" to exit, in which case it will exit # itself with same exit code as the "monitored process" -# - the parent process to send the "shutdown" signal in wich case +# - the parent process to send the "shutdown" signal in which case # monitor will kill the "monitored process" hard and exit # # diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 0537c9623fc..8c2b67c2fda 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -496,6 +496,7 @@ sub process_suite { # disabled.def parse_disabled($suite->{dir} .'/disabled.def', $suitename); + parse_disabled($suite->{dir} .'/t/disabled.def', $suitename); # combinations if (@::opt_combinations) diff --git a/mysql-test/lib/v1/mtr_report.pl b/mysql-test/lib/v1/mtr_report.pl index e2556d17093..738236a731e 100644 --- a/mysql-test/lib/v1/mtr_report.pl +++ b/mysql-test/lib/v1/mtr_report.pl @@ -306,7 +306,7 @@ sub mtr_report_stats ($) { /Slave: Query caused different errors on master and slave/ or /Slave: Table .* doesn't exist/ or /Slave: Table width mismatch/ or - /Slave: The incident LOST_EVENTS occured on the master/ or + /Slave: The incident LOST_EVENTS occurred on the master/ or /Slave: Unknown error.* 1105/ or /Slave: Can't drop database.* database doesn't exist/ or /Slave SQL:.*(?:error.* \d+|Query:.*)/ or diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 1575d6368ae..7e5292c1a8e 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -6183,7 +6183,7 @@ Misc options failures before stopping, set with the --retry-failure option retry-failure=N When using the --retry option to retry failed tests, - stop when N failures have occured (default $opt_retry_failure) + stop when N failures have occurred (default $opt_retry_failure) reorder Reorder tests to get fewer server restarts help Get this help text diff --git a/mysql-test/r/alter_table_online.result b/mysql-test/r/alter_table_online.result index 537614c710b..05d03aeae11 100644 --- a/mysql-test/r/alter_table_online.result +++ b/mysql-test/r/alter_table_online.result @@ -2,15 +2,9 @@ drop table if exists t1,t2,t3; create table t1 (a int not null primary key, b int, c varchar(80), e enum('a','b')); insert into t1 (a) values (1),(2),(3); alter online table t1 modify b int default 5; -ERROR 0A000: LOCK=NONE/SHARED is not supported for this operation. Try LOCK=EXCLUSIVE. alter online table t1 change b new_name int; -ERROR 0A000: LOCK=NONE/SHARED is not supported for this operation. Try LOCK=EXCLUSIVE. alter online table t1 modify e enum('a','b','c'); -ERROR 0A000: LOCK=NONE/SHARED is not supported for this operation. Try LOCK=EXCLUSIVE. alter online table t1 comment "new comment"; -ERROR 0A000: LOCK=NONE/SHARED is not supported for this operation. Try LOCK=EXCLUSIVE. -alter online table t1 rename to t2; -ERROR 0A000: LOCK=NONE/SHARED is not supported for this operation. Try LOCK=EXCLUSIVE. alter online table t1 algorithm=INPLACE, lock=NONE; alter online table t1; alter table t1 algorithm=INPLACE; @@ -40,10 +34,13 @@ alter online table t1 add f int; ERROR 0A000: LOCK=NONE is not supported for this operation. Try LOCK=SHARED. alter online table t1 engine=memory; ERROR 0A000: LOCK=NONE is not supported. Reason: COPY algorithm requires a lock. Try LOCK=SHARED. +alter online table t1 rename to t2; +ERROR 0A000: LOCK=NONE/SHARED is not supported for this operation. Try LOCK=EXCLUSIVE. alter table t1 engine=innodb; alter table t1 add index (b); alter online table t1 add index c (c); alter online table t1 drop index b; +alter online table t1 comment "new comment"; drop table t1; create temporary table t1 (a int not null primary key, b int, c varchar(80), e enum('a','b')); insert into t1 (a) values (1),(2),(3); diff --git a/mysql-test/r/alter_user.result b/mysql-test/r/alter_user.result new file mode 100644 index 00000000000..ac668bba8fa --- /dev/null +++ b/mysql-test/r/alter_user.result @@ -0,0 +1,93 @@ +select * from mysql.user where user = 'root' and host = 'localhost'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 +# Test syntax +# +# These 2 selects should have no changes from the first one. +alter user CURRENT_USER; +select * from mysql.user where user = 'root' and host = 'localhost'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 +alter user CURRENT_USER(); +select * from mysql.user where user = 'root' and host = 'localhost'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +localhost root Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 N N 0.000000 +create user foo; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +alter user foo; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +# Test super privilege works correctly with a read only database. +SET @start_read_only = @@global.read_only; +SET GLOBAL read_only=1; +grant create user on *.* to foo; +# Currently no super privileges. +connect a, localhost, foo; +select @@global.read_only; +@@global.read_only +1 +alter user foo; +ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement +# Grant super privilege to the user. +connection default; +grant super on *.* to foo; +# We now have super privilege. We should be able to run alter user. +connect b, localhost, foo; +alter user foo; +connection default; +SET GLOBAL read_only = @start_read_only; +# Test inexistant user. +alter user boo; +ERROR HY000: Operation ALTER USER failed for 'boo' +#--warning ER_CANNOT_USER +alter if exists user boo; +Warnings: +Error 1133 Can't find any matching row in the user table +Note 1396 Operation ALTER USER failed for 'boo' +# Test password related altering. +alter user foo identified by 'something'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 N N 0.000000 +alter user foo identified by 'something2'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *9CD58369E930E28C8996A89DB18B63294E6DC10C N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 N N 0.000000 +alter user foo identified by password '*88C89BE093D4ECF72D039F62EBB7477EA1FD4D63'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 N N 0.000000 +alter user foo identified with 'somecoolplugin'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 somecoolplugin N N 0.000000 +alter user foo identified with 'somecoolplugin' using 'somecoolpassphrase'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N 0 0 0 0 somecoolplugin somecoolpassphrase N N 0.000000 +# Test ssl related altering. +alter user foo identified by 'something' require SSL; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N ANY 0 0 0 0 N N 0.000000 +alter user foo identified by 'something' require X509; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N X509 0 0 0 0 N N 0.000000 +alter user foo identified by 'something' +require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N SPECIFIED text foo_issuer foo_subject 0 0 0 0 N N 0.000000 +# Test resource limits altering. +alter user foo with MAX_QUERIES_PER_HOUR 10 +MAX_UPDATES_PER_HOUR 20 +MAX_CONNECTIONS_PER_HOUR 30 +MAX_USER_CONNECTIONS 40; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *88C89BE093D4ECF72D039F62EBB7477EA1FD4D63 N N N N N N N N N N N N N N N Y N N N N N N N N N Y N N N SPECIFIED text foo_issuer foo_subject 10 20 30 40 N N 0.000000 +drop user foo; diff --git a/mysql-test/r/auth_named_pipe.result b/mysql-test/r/auth_named_pipe.result new file mode 100644 index 00000000000..3268b760a22 --- /dev/null +++ b/mysql-test/r/auth_named_pipe.result @@ -0,0 +1,10 @@ +INSTALL SONAME 'auth_named_pipe'; +CREATE USER 'USERNAME' IDENTIFIED WITH named_pipe; +SELECT USER(),CURRENT_USER(); +USER() CURRENT_USER() +USERNAME@localhost USERNAME@% +DROP USER 'USERNAME'; +CREATE USER nosuchuser IDENTIFIED WITH named_pipe; +ERROR 28000: Access denied for user 'nosuchuser'@'localhost' +DROP USER nosuchuser; +UNINSTALL SONAME 'auth_named_pipe'; diff --git a/mysql-test/r/compound.result b/mysql-test/r/compound.result index 92d3226ec00..1d412e671a4 100644 --- a/mysql-test/r/compound.result +++ b/mysql-test/r/compound.result @@ -162,3 +162,10 @@ a begin not atomic select a from t1 having a > 1; end| a drop table t1| +# +# MDEV-8615: Assertion `m_cpp_buf <= begin_ptr && +# begin_ptr <= m_cpp_buf + m_buf_length' failed in +# Lex_input_stream::body_utf8_start +# +b'| +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'b'' at line 1 diff --git a/mysql-test/r/connect2.result b/mysql-test/r/connect2.result new file mode 100644 index 00000000000..eecb6455162 --- /dev/null +++ b/mysql-test/r/connect2.result @@ -0,0 +1,46 @@ +call mtr.add_suppression("Allocation failed"); +SET @old_debug= @@session.debug; +set @old_thread_cache_size=@@global.thread_cache_size; +select 1; +1 +1 +set global debug_dbug='+d,simulate_failed_connection_1'; +connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET); +Got one of the listed errors +set global debug_dbug=@old_debug; +set global debug_dbug='+d,simulate_failed_connection_2'; +connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET); +Got one of the listed errors +set global debug_dbug=@old_debug; +select 1; +1 +1 +select 1; +1 +1 +set global debug_dbug='+d,simulate_failed_connection_1'; +connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET); +Got one of the listed errors +set global debug_dbug=@old_debug; +set global debug_dbug='+d,simulate_failed_connection_2'; +connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET); +Got one of the listed errors +set global debug_dbug=@old_debug; +select 1; +1 +1 +set @@global.thread_cache_size=2; +select 1; +1 +1 +select 1; +1 +1 +set global debug_dbug='+d,simulate_failed_connection_2'; +connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET); +Got one of the listed errors +show status like "Threads_connected"; +Variable_name Value +Threads_connected 1 +set global debug_dbug=@old_debug; +set global thread_cache_size=@old_thread_cache_size; diff --git a/mysql-test/r/contributors.result b/mysql-test/r/contributors.result index d578d43cb62..1820c0a5f06 100644 --- a/mysql-test/r/contributors.result +++ b/mysql-test/r/contributors.result @@ -1,16 +1,14 @@ SHOW CONTRIBUTORS; Name Location Comment -Booking.com http://www.booking.com Founding member of the MariaDB foundation -SkySQL Ab http://www.skysql.com Founding member of the MariaDB foundation -Auttomatic http://automattic.com Member of the MariaDB foundation -Parallels http://www.parallels.com/products/plesk Founding member of the MariaDB foundation -Verkkokauppa.com Finland Sponsor of the MariaDB foundation -Webyog Bangalor Sponsor of the MariaDB foundation -Percona USA Sponsor of the MariaDB foundation -Jelastic.com Russia Sponsor of the MariaDB foundation -Planetta.net Finland Sponsor of the MariaDB foundation -Open query Australia Sponsor of the MariaDB foundation -Google USA Sponsoring parallel replication and GTID +Booking.com http://www.booking.com Founding member of the MariaDB Foundation +MariaDB Corporation https://mariadb.com Founding member of the MariaDB Foundation +Auttomattic http://automattic.com Member of the MariaDB Foundation +Visma http://visma.com Member of the MariaDB Foundation +Nexedi http://www.nexedi.com Member of the MariaDB Foundation +Acronis http://www.acronis.com Member of the MariaDB Foundation +Verkkokauppa.com Finland Sponsor of the MariaDB Foundation +Webyog Bangalore Sponsor of the MariaDB Foundation +Google USA Sponsoring encryption, parallel replication and GTID Facebook USA Sponsoring non-blocking API, LIMIT ROWS EXAMINED etc Ronald Bradford Brisbane, Australia EFF contribution for UC2006 Auction Sheeri Kritzer Boston, Mass. USA EFF contribution for UC2006 Auction diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 6f664d306a1..cad46f34c75 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1889,5 +1889,21 @@ Warnings: Note 1291 Column 'a' has duplicated value '' in ENUM drop table t1; set @@session.collation_server=default; +# +# MDEV-7765: Crash (Assertion `!table || (!table->write_set || +# bitmap_is_set(table->write_set, field_index) || +# bitmap_is_set(table->vcol_set, field_index))' fails) +# on using function over not created table +# +CREATE function f1() returns int +BEGIN +declare n int; +set n:= (select count(*) from t1); +return n; +end| +create table t1 as select f1(); +ERROR 42S02: Table 'test.t1' doesn't exist +drop function f1; +End of 5.5 tests create table t1; ERROR 42000: A table must have at least 1 column diff --git a/mysql-test/r/create_user.result b/mysql-test/r/create_user.result new file mode 100644 index 00000000000..1411f2e8792 --- /dev/null +++ b/mysql-test/r/create_user.result @@ -0,0 +1,72 @@ +create user foo; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require SSL; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N ANY 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require X509; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N X509 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require CIPHER 'cipher'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require ISSUER 'issuer'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED issuer 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require SUBJECT 'subject'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED subject 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require CIPHER 'cipher' + SUBJECT 'subject'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher subject 0 0 0 0 N N 0.000000 +drop user foo; +create user foo identified by 'password' require CIPHER 'cipher' +AND SUBJECT 'subject' + AND ISSUER 'issuer'; +select * from mysql.user where user = 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 +drop user foo; +create user foo, foo2 identified by 'password' require CIPHER 'cipher' +AND SUBJECT 'subject' + AND ISSUER 'issuer'; +select * from mysql.user where user like 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 +#--warning ER_USER_CREATE_EXISTS +create user if not exists foo, foo2 identified by 'password2' + require CIPHER 'cipher2' AND SUBJECT 'subject2' AND ISSUER 'issuer2'; +Warnings: +Note 1973 Can't create user 'foo'@'%'; it already exists +Note 1973 Can't create user 'foo2'@'%'; it already exists +select * from mysql.user where user like 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N SPECIFIED cipher issuer subject 0 0 0 0 N N 0.000000 +drop user foo, foo2; +create user foo with MAX_QUERIES_PER_HOUR 10 +MAX_UPDATES_PER_HOUR 20 +MAX_CONNECTIONS_PER_HOUR 30 +MAX_USER_CONNECTIONS 40; +select * from mysql.user where user like 'foo'; +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time +% foo N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 10 20 30 40 N N 0.000000 +drop user foo; diff --git a/mysql-test/r/cte_grant.result b/mysql-test/r/cte_grant.result new file mode 100644 index 00000000000..4b067f42ff2 --- /dev/null +++ b/mysql-test/r/cte_grant.result @@ -0,0 +1,54 @@ +create database mysqltest; +create user mysqltest_1@localhost; +create table mysqltest.t1 (a int, b int); +insert into mysqltest.t1 values (2,10), (1,30); +create table mysqltest.t2 (c int, d char(32)); +insert into mysqltest.t2 values (1,'xxx'), (1,'zzz'); +grant select on mysqltest.t1 to mysqltest_1@localhost; +grant select (c) on mysqltest.t2 to mysqltest_1@localhost; +with t as (select c from mysqltest.t2 where c < 2) +select t.c,t1.b from t,mysqltest.t1 where t.c=t1.a; +c b +1 30 +1 30 +select t.c,t.d,t1.b +from (select c,d from mysqltest.t2 where c < 2) as t, mysqltest.t1 +where t.c=t1.a; +ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'd' in table 't2' +with t as (select c,d from mysqltest.t2 where c < 2) +select t.c,t.d,t1.b from t,mysqltest.t1 where t.c=t1.a; +ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'd' in table 't2' +create view mysqltest.v1(f1,f2) as +with t as (select c from mysqltest.t2 where c < 2) +select t.c,t1.b from t,mysqltest.t1 where t.c=t1.a; +create view mysqltest.v2(c,d) as +with t as (select a from mysqltest.t1 where a>=3) +select t.a,b from t,mysqltest.t1 where mysqltest.t1.a = t.a; +grant select on mysqltest.v1 to mysqltest_1@localhost; +grant select (c) on mysqltest.v2 to mysqltest_1@localhost; +grant create view on mysqltest.* to mysqltest_1@localhost; +create view mysqltest.v3(c,d) as +with t as (select c from mysqltest.t2 where c < 2) +select t.c,t1.b from t,mysqltest.t1 where t.c=t1.a; +create view mysqltest.v4(f1,f2,f3) as +with t as (select c,d from mysqltest.t2 where c < 2) +select t.c,t.d,t1.b from t,mysqltest.t1 where t.c=t1.a; +ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'd' in table 't2' +select * from mysqltest.v1; +f1 f2 +1 30 +1 30 +select c from mysqltest.v2; +c +select d from mysqltest.v2; +ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for column 'd' in table 'v2' +select * from mysqltest.v3; +ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'v3' +grant select on mysqltest.v3 to mysqltest_1@localhost; +select * from mysqltest.v3; +c d +1 30 +1 30 +revoke all privileges on mysqltest.v1 from mysqltest_1@localhost; +drop user mysqltest_1@localhost; +drop database mysqltest; diff --git a/mysql-test/r/cte_nonrecursive.result b/mysql-test/r/cte_nonrecursive.result new file mode 100644 index 00000000000..df641156e61 --- /dev/null +++ b/mysql-test/r/cte_nonrecursive.result @@ -0,0 +1,748 @@ +create table t1 (a int, b varchar(32)); +insert into t1 values +(4,'aaaa' ), (7,'bb'), (1,'ccc'), (4,'dd'); +insert into t1 values +(3,'eee'), (7,'bb'), (1,'fff'), (4,'ggg'); +create table t2 (c int); +insert into t2 values +(2), (4), (5), (3); +# select certain field in the specification of t +with t as (select a from t1 where b >= 'c') +select * from t2,t where t2.c=t.a; +c a +4 4 +3 3 +4 4 +select * from t2, (select a from t1 where b >= 'c') as t +where t2.c=t.a; +c a +4 4 +3 3 +4 4 +explain +with t as (select a from t1 where b >= 'c') +select * from t2,t where t2.c=t.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +explain +select * from t2, (select a from t1 where b >= 'c') as t +where t2.c=t.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +# select '*' in the specification of t +with t as (select * from t1 where b >= 'c') +select * from t2,t where t2.c=t.a; +c a b +4 4 dd +3 3 eee +4 4 ggg +select * from t2, (select * from t1 where b >= 'c') as t +where t2.c=t.a; +c a b +4 4 dd +3 3 eee +4 4 ggg +explain +with t as (select * from t1 where b >= 'c') +select * from t2,t where t2.c=t.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +explain +select * from t2, (select * from t1 where b >= 'c') as t +where t2.c=t.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +# rename fields returned by the specication when defining t +with t(f1,f2) as (select * from t1 where b >= 'c') +select * from t2,t where t2.c=t.f1; +c f1 f2 +4 4 dd +3 3 eee +4 4 ggg +explain +with t(f1,f2) as (select * from t1 where b >= 'c') +select * from t2,t where t2.c=t.f1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +# materialized query specifying t +with t as (select a, count(*) from t1 where b >= 'c' group by a) +select * from t2,t where t2.c=t.a; +c a count(*) +4 4 2 +3 3 1 +select * from t2, (select a, count(*) from t1 where b >= 'c' group by a) as t +where t2.c=t.a; +c a count(*) +4 4 2 +3 3 1 +explain +with t as (select a, count(*) from t1 where b >= 'c' group by a) +select * from t2,t where t2.c=t.a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where +1 PRIMARY <derived2> ref key0 key0 5 test.t2.c 2 +2 SUBQUERY t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort +explain +select * from t2, (select a, count(*) from t1 where b >= 'c' group by a) as t +where t2.c=t.a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where +1 PRIMARY <derived2> ref key0 key0 5 test.t2.c 2 +2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort +# specivication of t contains having +with t as (select a, count(*) from t1 where b >= 'c' + group by a having count(*)=1 ) +select * from t2,t where t2.c=t.a; +c a count(*) +3 3 1 +select * from t2, (select a, count(*) from t1 where b >= 'c' + group by a having count(*)=1) t +where t2.c=t.a; +c a count(*) +3 3 1 +# main query contains having +with t as (select * from t2 where c <= 4) +select a, count(*) from t1,t where t1.a=t.c group by a having count(*)=1; +a count(*) +3 1 +select a, count(*) from t1, (select * from t2 where c <= 4) t +where t1.a=t.c group by a having count(*)=1; +a count(*) +3 1 +# main query contains group by + order by +with t as (select * from t2 where c <= 4 ) +select a, count(*) from t1,t where t1.a=t.c group by a order by count(*); +a count(*) +3 1 +4 3 +select a, count(*) from t1, (select * from t2 where c <= 4 ) t +where t1.a=t.c group by a order by count(*); +a count(*) +3 1 +4 3 +# main query contains group by + order by + limit +with t as (select * from t2 where c <= 4 ) +select a, count(*) from t1,t +where t1.a=t.c group by a order by count(*) desc limit 1; +a count(*) +4 3 +select a, count(*) from t1, (select * from t2 where c <= 4 ) t +where t1.a=t.c group by a order by count(*) desc limit 1; +a count(*) +4 3 +# t is used in a subquery +with t as (select a from t1 where a<5) +select * from t2 where c in (select a from t); +c +4 +3 +select * from t2 +where c in (select a from (select a from t1 where a<5) as t); +c +4 +3 +explain +with t as (select a from t1 where a<5) +select * from t2 where c in (select a from t); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 +1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 +3 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where +explain +select * from t2 +where c in (select a from (select a from t1 where a<5) as t); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where +# materialized t is used in a subquery +with t as (select count(*) as c from t1 where b >= 'c' group by a) +select * from t2 where c in (select c from t); +c +2 +select * from t2 +where c in (select c from (select count(*) as c from t1 +where b >= 'c' group by a) as t); +c +2 +explain +with t as (select count(*) as c from t1 where b >= 'c' group by a) +select * from t2 where c in (select c from t); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where +1 PRIMARY <derived2> ref key0 key0 8 test.t2.c 2 Using where; FirstMatch(t2) +2 SUBQUERY t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort +explain +select * from t2 +where c in (select c from (select count(*) as c from t1 +where b >= 'c' group by a) as t); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where +1 PRIMARY <derived3> ref key0 key0 8 test.t2.c 2 Using where; FirstMatch(t2) +3 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort +# two references to t specified by a query +# selecting a field: both in main query +with t as (select a from t1 where b >= 'c') +select * from t as r1, t as r2 where r1.a=r2.a; +a a +1 1 +1 1 +4 4 +4 4 +3 3 +1 1 +1 1 +4 4 +4 4 +select * from (select a from t1 where b >= 'c') as r1, +(select a from t1 where b >= 'c') as r2 +where r1.a=r2.a; +a a +1 1 +1 1 +4 4 +4 4 +3 3 +1 1 +1 1 +4 4 +4 4 +explain +with t as (select a from t1 where b >= 'c') +select * from t as r1, t as r2 where r1.a=r2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +explain +select * from (select a from t1 where b >= 'c') as r1, +(select a from t1 where b >= 'c') as r2 +where r1.a=r2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +# two references to materialized t: both in main query +with t as (select distinct a from t1 where b >= 'c') +select * from t as r1, t as r2 where r1.a=r2.a; +a a +1 1 +4 4 +3 3 +select * from (select distinct a from t1 where b >= 'c') as r1, +(select distinct a from t1 where b >= 'c') as r2 +where r1.a=r2.a; +a a +1 1 +4 4 +3 3 +explain +with t as (select distinct a from t1 where b >= 'c') +select * from t as r1, t as r2 where r1.a=r2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8 Using where +1 PRIMARY <derived3> ref key0 key0 5 r1.a 2 +3 SUBQUERY t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary +2 SUBQUERY t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary +explain +select * from (select distinct a from t1 where b >= 'c') as r1, +(select distinct a from t1 where b >= 'c') as r2 +where r1.a=r2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8 Using where +1 PRIMARY <derived3> ref key0 key0 5 r1.a 2 +3 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary +2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary +# two references to t specified by a query +# selecting all fields: both in main query +with t as (select * from t1 where b >= 'c') +select * from t as r1, t as r2 where r1.a=r2.a; +a b a b +1 ccc 1 ccc +1 fff 1 ccc +4 dd 4 dd +4 ggg 4 dd +3 eee 3 eee +1 ccc 1 fff +1 fff 1 fff +4 dd 4 ggg +4 ggg 4 ggg +select * from (select * from t1 where b >= 'c') as r1, +(select * from t1 where b >= 'c') as r2 +where r1.a=r2.a; +a b a b +1 ccc 1 ccc +1 fff 1 ccc +4 dd 4 dd +4 ggg 4 dd +3 eee 3 eee +1 ccc 1 fff +1 fff 1 fff +4 dd 4 ggg +4 ggg 4 ggg +explain +with t as (select * from t1 where b >= 'c') +select * from t as r1, t as r2 where r1.a=r2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +explain +select * from (select * from t1 where b >= 'c') as r1, +(select * from t1 where b >= 'c') as r2 +where r1.a=r2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +# two references to t specifying explicitly column names +with t(c) as (select a from t1 where b >= 'c') +select * from t r1, t r2 where r1.c=r2.c; +c c +1 1 +1 1 +4 4 +4 4 +3 3 +1 1 +1 1 +4 4 +4 4 +# specification of t contains union +with t as (select a from t1 where b >= 'f' +union +select c as a from t2 where c < 4) +select * from t2,t where t2.c=t.a; +c a +2 2 +4 4 +3 3 +select * from t2, +(select a from t1 where b >= 'f' +union +select c as a from t2 where c < 4) as t +where t2.c=t.a; +c a +2 2 +4 4 +3 3 +explain +with t as (select a from t1 where b >= 'f' +union +select c as a from t2 where c < 4) +select * from t2,t where t2.c=t.a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where +1 PRIMARY <derived2> ref key0 key0 5 test.t2.c 2 +2 SUBQUERY t1 ALL NULL NULL NULL NULL 8 Using where +3 UNION t2 ALL NULL NULL NULL NULL 4 Using where +NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL +explain +select * from t2, +(select a from t1 where b >= 'f' +union +select c as a from t2 where c < 4) as t +where t2.c=t.a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where +1 PRIMARY <derived2> ref key0 key0 5 test.t2.c 2 +2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where +3 UNION t2 ALL NULL NULL NULL NULL 4 Using where +NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL +# t is defined in the with clause of a subquery +select t1.a,t1.b from t1,t2 +where t1.a>t2.c and +t2.c in (with t as (select * from t1 where t1.a<5) +select t2.c from t2,t where t2.c=t.a); +a b +4 aaaa +7 bb +7 bb +4 dd +7 bb +7 bb +4 ggg +select t1.a,t1.b from t1,t2 +where t1.a>t2.c and +t2.c in (select t2.c +from t2,(select * from t1 where t1.a<5) as t +where t2.c=t.a); +a b +4 aaaa +7 bb +7 bb +4 dd +7 bb +7 bb +4 ggg +explain +select t1.a,t1.b from t1,t2 +where t1.a>t2.c and +t2.c in (with t as (select * from t1 where t1.a<5) +select t2.c from t2,t where t2.c=t.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where +2 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +explain +select t1.a,t1.b from t1,t2 +where t1.a>t2.c and +t2.c in (select t2.c +from t2,(select * from t1 where t1.a<5) as t +where t2.c=t.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where +2 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +# two different definitions of t: one in the with clause of the main query, +# the other in the with clause of a subquery +with t as (select c from t2 where c >= 4) +select t1.a,t1.b from t1,t +where t1.a=t.c and +t.c in (with t as (select * from t1 where t1.a<5) +select t2.c from t2,t where t2.c=t.a); +a b +4 aaaa +4 dd +4 ggg +select t1.a,t1.b from t1, (select c from t2 where c >= 4) as t +where t1.a=t.c and +t.c in (select t2.c from t2, (select * from t1 where t1.a<5) as t +where t2.c=t.a); +a b +4 aaaa +4 dd +4 ggg +explain +with t as (select c from t2 where c >= 4) +select t1.a,t1.b from t1,t +where t1.a=t.c and +t.c in (with t as (select * from t1 where t1.a<5) +select t2.c from t2,t where t2.c=t.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where +1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 +1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +3 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where +3 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +explain +select t1.a,t1.b from t1, (select c from t2 where c >= 4) as t +where t1.a=t.c and +t.c in (select t2.c from t2, (select * from t1 where t1.a<5) as t +where t2.c=t.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where +1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 +1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +3 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where +3 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +# another with table tt is defined in the with clause of a subquery +# from the specification of t +with t as (select * from t1 +where a>2 and +b in (with tt as (select * from t2 where t2.c<5) +select t1.b from t1,tt where t1.a=tt.c)) +select t.a, count(*) from t1,t where t1.a=t.a group by t.a; +a count(*) +3 1 +4 9 +select t.a, count(*) +from t1, +(select * from t1 +where a>2 and +b in (select t1.b +from t1, +(select * from t2 where t2.c<5) as tt +where t1.a=tt.c)) as t +where t1.a=t.a group by t.a; +a count(*) +3 1 +4 9 +explain +with t as (select * from t1 +where a>2 and +b in (with tt as (select * from t2 where t2.c<5) +select t1.b from t1,tt where t1.a=tt.c)) +select t.a, count(*) from t1,t where t1.a=t.a group by t.a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort +1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +3 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where +3 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +explain +select t.a, count(*) +from t1, +(select * from t1 +where a>2 and +b in (select t1.b +from t1, +(select * from t2 where t2.c<5) as tt +where t1.a=tt.c)) as t +where t1.a=t.a group by t.a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort +1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +3 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where +3 MATERIALIZED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +# with clause in the specification of a derived table +select * +from t1, +(with t as (select a from t1 where b >= 'c') +select * from t2,t where t2.c=t.a) as tt +where t1.b > 'f' and tt.a=t1.a; +a b c a +4 ggg 4 4 +4 ggg 4 4 +select * +from t1, +(select * from t2, +(select a from t1 where b >= 'c') as t +where t2.c=t.a) as tt +where t1.b > 'f' and tt.a=t1.a; +a b c a +4 ggg 4 4 +4 ggg 4 4 +explain +select * +from t1, +(with t as (select a from t1 where b >= 'c') +select * from t2,t where t2.c=t.a) as tt +where t1.b > 'f' and tt.a=t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (incremental, BNL join) +explain +select * +from t1, +(select * from t2, +(select a from t1 where b >= 'c') as t +where t2.c=t.a) as tt +where t1.b > 'f' and tt.a=t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (incremental, BNL join) +# with claused in the specification of a view +create view v1 as +with t as (select a from t1 where b >= 'c') +select * from t2,t where t2.c=t.a; +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 WITH t AS (select `t1`.`a` AS `a` from `t1` where (`t1`.`b` >= 'c'))select `t2`.`c` AS `c`,`t`.`a` AS `a` from (`t2` join `t`) where (`t2`.`c` = `t`.`a`) latin1 latin1_swedish_ci +select * from v1; +c a +4 4 +3 3 +4 4 +explain +select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 32 +2 DERIVED t2 ALL NULL NULL NULL NULL 4 +2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +# with claused in the specification of a materialized view +create view v2 as +with t as (select a, count(*) from t1 where b >= 'c' group by a) +select * from t2,t where t2.c=t.a; +show create view v2; +View Create View character_set_client collation_connection +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS WITH t AS (select `t1`.`a` AS `a`,count(0) AS `count(*)` from `t1` where (`t1`.`b` >= 'c') group by `t1`.`a`)select `t2`.`c` AS `c`,`t`.`a` AS `a`,`t`.`count(*)` AS `count(*)` from (`t2` join `t`) where (`t2`.`c` = `t`.`a`) latin1 latin1_swedish_ci +select * from v2; +c a count(*) +4 4 2 +3 3 1 +explain +select * from v2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8 +2 DERIVED t2 ALL NULL NULL NULL NULL 4 Using where +2 DERIVED <derived3> ref key0 key0 5 test.t2.c 2 +3 SUBQUERY t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort +# with clause in the specification of a view that whose definition +# table alias for a with table +create view v3 as +with t(c) as (select a from t1 where b >= 'c') +select * from t r1 where r1.c=4; +show create view v3; +View Create View character_set_client collation_connection +v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS WITH t AS (select `t1`.`a` AS `c` from `t1` where (`t1`.`b` >= 'c'))select `r1`.`c` AS `c` from `t` `r1` where (`r1`.`c` = 4) latin1 latin1_swedish_ci +select * from v3; +c +4 +4 +# with clause in the specification of a view that whose definition +# two table aliases for for the same with table +create view v4(c,d) as +with t(c) as (select a from t1 where b >= 'c') +select * from t r1, t r2 where r1.c=r2.c and r2.c=4; +show create view v4; +View Create View character_set_client collation_connection +v4 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v4` AS WITH t AS (select `t1`.`a` AS `c` from `t1` where (`t1`.`b` >= 'c'))select `r1`.`c` AS `c`,`r2`.`c` AS `d` from (`t` `r1` join `t` `r2`) where ((`r1`.`c` = `r2`.`c`) and (`r2`.`c` = 4)) latin1 latin1_swedish_ci +select * from v4; +c d +4 4 +4 4 +4 4 +4 4 +explain +select * from v4; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 64 +2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where +2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +drop view v1,v2,v3,v4; +# currently any views containing with clause are not updatable +create view v1(a) as +with t as (select a from t1 where b >= 'c') +select t.a from t2,t where t2.c=t.a; +update v1 set a=0 where a > 4; +ERROR HY000: The target table v1 of the UPDATE is not updatable +drop view v1; +# prepare of a query containing a definition of a with table t +prepare stmt1 from " +with t as (select a from t1 where b >= 'c') + select * from t2,t where t2.c=t.a; +"; +execute stmt1; +c a +4 4 +3 3 +4 4 +execute stmt1; +c a +4 4 +3 3 +4 4 +deallocate prepare stmt1; +# prepare of a query containing a definition of a materialized t +prepare stmt1 from " +with t as (select a, count(*) from t1 where b >= 'c' group by a) + select * from t2,t where t2.c=t.a; +"; +execute stmt1; +c a count(*) +4 4 2 +3 3 1 +execute stmt1; +c a count(*) +4 4 2 +3 3 1 +deallocate prepare stmt1; +# prepare of a query containing two references to with table t +prepare stmt1 from " +with t as (select * from t1 where b >= 'c') + select * from t as r1, t as r2 where r1.a=r2.a; +"; +execute stmt1; +a b a b +1 ccc 1 ccc +1 fff 1 ccc +4 dd 4 dd +4 ggg 4 dd +3 eee 3 eee +1 ccc 1 fff +1 fff 1 fff +4 dd 4 ggg +4 ggg 4 ggg +execute stmt1; +a b a b +1 ccc 1 ccc +1 fff 1 ccc +4 dd 4 dd +4 ggg 4 dd +3 eee 3 eee +1 ccc 1 fff +1 fff 1 fff +4 dd 4 ggg +4 ggg 4 ggg +deallocate prepare stmt1; +with t(f) as (select * from t1 where b >= 'c') +select * from t2,t where t2.c=t.f1; +ERROR HY000: WITH column list and SELECT field list have different column counts +with t(f1,f1) as (select * from t1 where b >= 'c') +select * from t2,t where t2.c=t.f1; +ERROR 42S21: Duplicate column name 'f1' +with t as (select * from t2 where c>3), +t as (select a from t1 where a>2) +select * from t,t1 where t1.a=t.c; +ERROR HY000: Duplicate query name in WITH clause +with t as (select a from s where a<5), +s as (select a from t1 where b>='d') +select * from t,s where t.a=s.a; +ERROR HY000: The definition of the table 't' refers to the table 's' defined later in a non-recursive WITH clause +with recursive +t as (select a from s where a<5), +s as (select a from t1 where b>='d') +select * from t,s where t.a=s.a; +a a +4 4 +4 4 +3 3 +1 1 +4 4 +4 4 +with recursive t as (select * from s where a>2), +s as (select a from t1,r where t1.a>r.c), +r as (select c from t,t2 where t.a=t2.c) +select * from r where r.c<7; +ERROR HY000: Recursive queries in WITH clause are not supported yet +with t as (select * from s where a>2), +s as (select a from t1,r where t1.a>r.c), +r as (select c from t,t2 where t.a=t2.c) +select * from r where r.c<7; +ERROR HY000: Recursive queries in WITH clause are not supported yet +with t as (select * from t1 +where a in (select c from s where b<='ccc') and b>'b'), +s as (select * from t1,t2 +where t1.a=t2.c and t1.c in (select a from t where a<5)) +select * from s where s.b>'aaa'; +ERROR HY000: Recursive queries in WITH clause are not supported yet +with t as (select * from t1 where b>'aaa' and b <='d') +select t.b from t,t2 +where t.a=t2.c and +t2.c in (with s as (select t1.a from s,t1 where t1.a=s.a and t1.b<'c') +select * from s); +ERROR HY000: Recursive queries in WITH clause are not supported yet +#erroneous definition of unreferenced with table t +with t as (select count(*) from t1 where d>='f' group by a) +select t1.b from t2,t1 where t1.a = t2.c; +ERROR 42S22: Unknown column 'd' in 'where clause' +with t as (select count(*) from t1 where b>='f' group by a) +select t1.b from t2,t1 where t1.a = t2.c; +b +aaaa +dd +eee +ggg +#erroneous definition of s referring to unreferenced t +with t(d) as (select count(*) from t1 where b<='ccc' group by b), +s as (select * from t1 where a in (select t2.d from t2,t where t2.c=t.d)) +select t1.b from t1,t2 where t1.a=t2.c; +ERROR 42S22: Unknown column 't2.d' in 'field list' +with t(d) as (select count(*) from t1 where b<='ccc' group by b), +s as (select * from t1 where a in (select t2.c from t2,t where t2.c=t.c)) +select t1.b from t1,t2 where t1.a=t2.c; +ERROR 42S22: Unknown column 't.c' in 'where clause' +with t(d) as (select count(*) from t1 where b<='ccc' group by b), +s as (select * from t1 where a in (select t2.c from t2,t where t2.c=t.d)) +select t1.b from t1,t2 where t1.a=t2.c; +b +aaaa +dd +eee +ggg +#erroneous definition of unreferenced with table t +with t(f) as (select * from t1 where b >= 'c') +select t1.b from t2,t1 where t1.a = t2.c; +ERROR HY000: WITH column list and SELECT field list have different column counts +#erroneous definition of unreferenced with table t +with t(f1,f1) as (select * from t1 where b >= 'c') +select t1.b from t2,t1 where t1.a = t2.c; +ERROR 42S21: Duplicate column name 'f1' +drop table t1,t2; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index d95b506f247..816fe654028 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -116,7 +116,7 @@ hex(a) STRCMP(a,'a') STRCMP(a,'a ') DROP TABLE t1; select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es'); insert('txs',2,1,'hi') insert('is ',4,0,'a') insert('txxxxt',2,4,'es') -this is a test +this is test select insert("aa",100,1,"b"),insert("aa",1,3,"b"); insert("aa",100,1,"b") insert("aa",1,3,"b") aa b @@ -5365,14 +5365,16 @@ DROP TABLE t1; SET sql_mode=default; # # Bug#57687 crash when reporting duplicate group_key error and utf8 -# Make sure to modify this when Bug#58081 is fixed. +# Bug#58081 Duplicate entry error when doing GROUP BY +# MDEV-9332 Bug after upgrade to 10.1.10 # SET NAMES utf8; CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (0), (0), (1), (0), (0); -SELECT COUNT(*) FROM t1, t1 t2 +SELECT COUNT(*) FROM t1, t1 t2 GROUP BY INSERT('', t2.a, t1.a, (@@global.max_binlog_size)); -ERROR 23000: Duplicate entry '107374182410737418241' for key 'group_key' +COUNT(*) +25 DROP TABLE t1; # # Bug#11764503 (Bug#57341) Query in EXPLAIN EXTENDED shows wrong characters @@ -10256,5 +10258,146 @@ Warnings: Note 1003 select `test`.`t1`.`c` AS `c` from `test`.`t1` where (`test`.`t1`.`c` = 'A') DROP TABLE t1; # +# MDEV-7231 Field ROUTINE_DEFINITION in INFORMATION_SCHEMA.`ROUTINES` contains broken procedure body when used shielding quotes inside. +# +CREATE PROCEDURE p1() +BEGIN +SELECT CONCAT('ABC = ''',1,''''), CONCAT('ABC = ',2); +SELECT '''', """", '\'', "\""; +SELECT '<tab> <tab>\t<tab>'; +SELECT '<nl> +<nl>\n<nl>'; +SELECT 'test'; +SELECT 'tëst'; +SELECT 'test\0'; +SELECT 'tëst\0'; +SELECT _binary'test'; +SELECT _binary'test\0'; +SELECT N'''', N"""", N'\'', N"\""; +SELECT N'<tab> <tab>\t<tab>'; +SELECT N'<nl> +<nl>\n<nl>'; +SELECT N'test'; +SELECT N'tëst'; +SELECT N'test\0'; +SELECT N'tëst\0'; +END$$ +SELECT ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA='test' AND SPECIFIC_NAME ='p1'; +ROUTINE_DEFINITION +BEGIN +SELECT CONCAT('ABC = ''',1,''''), CONCAT('ABC = ',2); +SELECT '''', """", '''', """"; +SELECT '<tab>\t<tab>\t<tab>'; +SELECT '<nl>\n<nl>\n<nl>'; +SELECT 'test'; +SELECT 'tëst'; +SELECT 'test\0'; +SELECT 'tëst\0'; +SELECT 'test'; +SELECT 'test\0'; +SELECT N'''', N"""", N'''', N""""; +SELECT N'<tab>\t<tab>\t<tab>'; +SELECT N'<nl>\n<nl>\n<nl>'; +SELECT N'test'; +SELECT N'tëst'; +SELECT N'test\0'; +SELECT N'tëst\0'; +END +SELECT body_utf8 FROM mysql.proc WHERE name='p1'; +body_utf8 +BEGIN +SELECT CONCAT('ABC = ''',1,''''), CONCAT('ABC = ',2); +SELECT '''', """", '''', """"; +SELECT '<tab>\t<tab>\t<tab>'; +SELECT '<nl>\n<nl>\n<nl>'; +SELECT 'test'; +SELECT 'tëst'; +SELECT 'test\0'; +SELECT 'tëst\0'; +SELECT 'test'; +SELECT 'test\0'; +SELECT N'''', N"""", N'''', N""""; +SELECT N'<tab>\t<tab>\t<tab>'; +SELECT N'<nl>\n<nl>\n<nl>'; +SELECT N'test'; +SELECT N'tëst'; +SELECT N'test\0'; +SELECT N'tëst\0'; +END +DROP PROCEDURE p1; +SET @@SQL_MODE='NO_BACKSLASH_ESCAPES'; +CREATE PROCEDURE p1() +BEGIN +SELECT CONCAT('ABC = ''',1,''''), CONCAT('ABC = ',2); +SELECT '''', """"; +SELECT '<tab> <tab>\t<tab>'; +SELECT '<nl> +<nl>\n<nl>'; +SELECT 'test'; +SELECT 'tëst'; +SELECT 'test\0'; +SELECT 'tëst\0'; +SELECT _binary'test'; +SELECT _binary'test\0'; +SELECT N'''', N""""; +SELECT N'<tab> <tab>\t<tab>'; +SELECT N'<nl> +<nl>\n<nl>'; +SELECT N'test'; +SELECT N'tëst'; +SELECT N'test\0'; +SELECT N'tëst\0'; +END$$ +SELECT ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA='test' AND SPECIFIC_NAME ='p1'; +ROUTINE_DEFINITION +BEGIN +SELECT CONCAT('ABC = ''',1,''''), CONCAT('ABC = ',2); +SELECT '''', """"; +SELECT '<tab> <tab>\t<tab>'; +SELECT '<nl> +<nl>\n<nl>'; +SELECT 'test'; +SELECT 'tëst'; +SELECT 'test\0'; +SELECT 'tëst\0'; +SELECT 'test'; +SELECT 'test\0'; +SELECT N'''', N""""; +SELECT N'<tab> <tab>\t<tab>'; +SELECT N'<nl> +<nl>\n<nl>'; +SELECT N'test'; +SELECT N'tëst'; +SELECT N'test\0'; +SELECT N'tëst\0'; +END +SELECT body_utf8 FROM mysql.proc WHERE name='p1'; +body_utf8 +BEGIN +SELECT CONCAT('ABC = ''',1,''''), CONCAT('ABC = ',2); +SELECT '''', """"; +SELECT '<tab> <tab>\t<tab>'; +SELECT '<nl> +<nl>\n<nl>'; +SELECT 'test'; +SELECT 'tëst'; +SELECT 'test\0'; +SELECT 'tëst\0'; +SELECT 'test'; +SELECT 'test\0'; +SELECT N'''', N""""; +SELECT N'<tab> <tab>\t<tab>'; +SELECT N'<nl> +<nl>\n<nl>'; +SELECT N'test'; +SELECT N'tëst'; +SELECT N'test\0'; +SELECT N'tëst\0'; +END +DROP PROCEDURE p1; +SET @@SQL_MODE=default; +# # End of 10.1 tests # diff --git a/mysql-test/r/ctype_utf8mb4.result b/mysql-test/r/ctype_utf8mb4.result index ac53a7e5a4e..10d77ae1502 100644 --- a/mysql-test/r/ctype_utf8mb4.result +++ b/mysql-test/r/ctype_utf8mb4.result @@ -116,7 +116,7 @@ hex(a) STRCMP(a,'a') STRCMP(a,'a ') DROP TABLE t1; select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es'); insert('txs',2,1,'hi') insert('is ',4,0,'a') insert('txxxxt',2,4,'es') -this is a test +this is test select insert("aa",100,1,"b"),insert("aa",1,3,"b"); insert("aa",100,1,"b") insert("aa",1,3,"b") aa b @@ -3382,5 +3382,19 @@ SET NAMES utf8mb4; SELECT * FROM `testðŸ˜ðŸ˜test`; ERROR HY000: Invalid utf8mb4 character string: 'test\xF0\x9F\x98\x81\xF0\x9F\x98\x81test' # +# MDEV-7231 Field ROUTINE_DEFINITION in INFORMATION_SCHEMA.`ROUTINES` contains broken procedure body when used shielding quotes inside. +# +SET NAMES utf8mb4; +CREATE FUNCTION f1() RETURNS TEXT CHARACTER SET utf8mb4 +RETURN CONCAT('😎','x😎','😎y','x😎y'); +SELECT ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA='test' AND SPECIFIC_NAME ='f1'; +ROUTINE_DEFINITION +RETURN CONCAT('?','x?','?y','x?y') +SELECT body_utf8 FROM mysql.proc WHERE name='f1'; +body_utf8 +RETURN CONCAT('?','x?','?y','x?y') +DROP FUNCTION f1; +# # End of 10.1 tests # diff --git a/mysql-test/r/ctype_utf8mb4_heap.result b/mysql-test/r/ctype_utf8mb4_heap.result index 5f77d417fe5..d70e009228e 100644 --- a/mysql-test/r/ctype_utf8mb4_heap.result +++ b/mysql-test/r/ctype_utf8mb4_heap.result @@ -116,7 +116,7 @@ hex(a) STRCMP(a,'a') STRCMP(a,'a ') DROP TABLE t1; select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es'); insert('txs',2,1,'hi') insert('is ',4,0,'a') insert('txxxxt',2,4,'es') -this is a test +this is test select insert("aa",100,1,"b"),insert("aa",1,3,"b"); insert("aa",100,1,"b") insert("aa",1,3,"b") aa b diff --git a/mysql-test/r/ctype_utf8mb4_innodb.result b/mysql-test/r/ctype_utf8mb4_innodb.result index fc1d2b9d315..7d193f397ac 100644 --- a/mysql-test/r/ctype_utf8mb4_innodb.result +++ b/mysql-test/r/ctype_utf8mb4_innodb.result @@ -116,7 +116,7 @@ hex(a) STRCMP(a,'a') STRCMP(a,'a ') DROP TABLE t1; select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es'); insert('txs',2,1,'hi') insert('is ',4,0,'a') insert('txxxxt',2,4,'es') -this is a test +this is test select insert("aa",100,1,"b"),insert("aa",1,3,"b"); insert("aa",100,1,"b") insert("aa",1,3,"b") aa b diff --git a/mysql-test/r/ctype_utf8mb4_myisam.result b/mysql-test/r/ctype_utf8mb4_myisam.result index a033138a6fe..28cf36c7492 100644 --- a/mysql-test/r/ctype_utf8mb4_myisam.result +++ b/mysql-test/r/ctype_utf8mb4_myisam.result @@ -116,7 +116,7 @@ hex(a) STRCMP(a,'a') STRCMP(a,'a ') DROP TABLE t1; select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es'); insert('txs',2,1,'hi') insert('is ',4,0,'a') insert('txxxxt',2,4,'es') -this is a test +this is test select insert("aa",100,1,"b"),insert("aa",1,3,"b"); insert("aa",100,1,"b") insert("aa",1,3,"b") aa b diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result index 0eb0661b0e2..98c8b599e88 100644 --- a/mysql-test/r/delayed.result +++ b/mysql-test/r/delayed.result @@ -379,7 +379,7 @@ SELECT * FROM t1 WHERE a=0; a # Connection con1 # Sending: -ALTER TABLE t1 COMMENT 'test'; +ALTER TABLE t1 MODIFY a INT UNSIGNED;; # Connection default # Wait until ALTER TABLE is blocked on table 't1'. INSERT DELAYED INTO t1 VALUES (3); diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index a59f8a6dfee..1d643333424 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -603,6 +603,351 @@ select x.id, message from (select id from t1) x left join where coalesce(message,0) <> 0; id message drop table t1,t2; +# +# MDEV-7827: Assertion `!table || (!table->read_set || +# bitmap_is_set(table->read_set, field_index))' failed +# in Field_long::val_str on EXPLAIN EXTENDED +# +CREATE TABLE t1 (f1 INT, f2 INT, KEY(f2)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (6,9); +CREATE TABLE t2 (f3 INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (2),(0); +EXPLAIN EXTENDED +SELECT f1 FROM ( SELECT * FROM t1 ) AS sq +WHERE f1 IN ( +SELECT f3 FROM t2 WHERE f2 IN ( +SELECT f3 FROM t2 HAVING f3 >= 8 +) +); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY <derived2> system NULL NULL NULL NULL 1 100.00 +1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 4 sq.f2 1 100.00 +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; FirstMatch(<subquery4>); Using join buffer (flat, BNL join) +4 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00 +2 DERIVED t1 system NULL NULL NULL NULL 1 100.00 +Warnings: +Note 1276 Field or reference 'sq.f2' of SELECT #3 was resolved in SELECT #1 +Note 1003 select 6 AS `f1` from <materialize> (select `test`.`t2`.`f3` from `test`.`t2` having (`test`.`t2`.`f3` >= 8)) semi join (`test`.`t2`) where ((`test`.`t2`.`f3` = 6) and (9 = `<subquery4>`.`f3`)) +DROP TABLE t2,t1; +# +# MDEV-9462: Out of memory using explain on 2 empty tables +# +CREATE TABLE `t1` ( +`REC_GROUP` char(2) DEFAULT NULL, +`CLIENT_INFO` text CHARACTER SET utf8, +`NAME` text, +`PHONE_NUMBER` text, +`ATTENTION_NAME` text, +`PAYMENT_TERM` text CHARACTER SET utf8, +`CREDIT_LIMIT` decimal(12,2) DEFAULT NULL, +`LAST_PAY_DATE` text CHARACTER SET utf8, +`TOTAL` double DEFAULT NULL, +`TOTAL_MCL` double DEFAULT NULL, +`TOTAL_MFS` double DEFAULT NULL, +`TOTAL_MIS` double DEFAULT NULL, +`BEFORE_DUE_7_MCL` double DEFAULT NULL, +`BEFORE_DUE_7_MFS` double DEFAULT NULL, +`BEFORE_DUE_7_MIS` double DEFAULT NULL, +`PER1_MCL` double DEFAULT NULL, +`PER1_MFS` double DEFAULT NULL, +`PER1_MIS` double DEFAULT NULL, +`PER2_MCL` double DEFAULT NULL, +`PER2_MFS` double DEFAULT NULL, +`PER2_MIS` double DEFAULT NULL, +`PER3_MCL` double DEFAULT NULL, +`PER3_MFS` double DEFAULT NULL, +`PER3_MIS` double DEFAULT NULL, +`PER4_MCL` double DEFAULT NULL, +`PER4_MFS` double DEFAULT NULL, +`PER4_MIS` double DEFAULT NULL, +`PER5_MCL` double DEFAULT NULL, +`PER5_MFS` double DEFAULT NULL, +`PER5_MIS` double DEFAULT NULL, +`PER6_MCL` double DEFAULT NULL, +`PER6_MFS` double DEFAULT NULL, +`PER6_MIS` double DEFAULT NULL, +`PER7_MCL` double DEFAULT NULL, +`PER7_MFS` double DEFAULT NULL, +`PER7_MIS` double DEFAULT NULL, +`BEFORE_DUE_7` double DEFAULT NULL, +`PER1` double DEFAULT NULL, +`PER2` double DEFAULT NULL, +`PER3` double DEFAULT NULL, +`PER4` double DEFAULT NULL, +`PER5` double DEFAULT NULL, +`PER6` double DEFAULT NULL, +`PER7` double DEFAULT NULL, +`REF` varchar(30) DEFAULT NULL, +`TYPE` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL +); +CREATE TABLE `t2` ( +`RECEIVABLE_GROUP` char(2) DEFAULT NULL, +`CLIENT_NUMBER` varchar(35) DEFAULT NULL, +`CLIENT_NAME` varchar(73) DEFAULT NULL, +`PHONE_NUMBER` char(12) DEFAULT NULL, +`ATTENTION_NAME` char(26) DEFAULT NULL, +`PAYMENT_TERM` varchar(26) CHARACTER SET utf8 DEFAULT NULL, +`CREDIT_LIMIT` decimal(12,2) DEFAULT NULL, +`LAST_PAY_DATE` varchar(42) CHARACTER SET utf8 DEFAULT NULL, +`TOTAL` decimal(12,2) DEFAULT NULL, +`BEFORE_DUE_7` decimal(12,2) DEFAULT NULL, +`PER1` decimal(12,2) DEFAULT NULL, +`PER2` decimal(12,2) DEFAULT NULL, +`PER3` decimal(12,2) DEFAULT NULL, +`PER4` decimal(12,2) DEFAULT NULL, +`PER5` decimal(12,2) DEFAULT NULL, +`PER6` decimal(12,2) DEFAULT NULL, +`PER7` decimal(12,2) DEFAULT NULL, +`DIVISION` varchar(3) CHARACTER SET utf8 NOT NULL, +`CLIENT_INFO` varchar(294) CHARACTER SET utf8 DEFAULT NULL, +`EXCHANGE_RATE` double NOT NULL, +`REF` varchar(30) DEFAULT NULL +); +explain +SELECT A.RECEIVABLE_GROUP,A.CLIENT_INFO,A.CLIENT_NAME,A.PHONE_NUMBER,A.ATTENTION_NAME,A.PAYMENT_TERM,A.CREDIT_LIMIT,A.LAST_PAY_DATE,A.TOTAL, +COALESCE(B.TOTAL_MCL,0) AS TOTAL_MCL, +COALESCE(C.TOTAL_MFS,0) AS TOTAL_MFS, +COALESCE(D.TOTAL_MIS,0) AS TOTAL_MIS, +COALESCE(F.BEFORE_DUE_7_MCL,0) AS BEFORE_DUE_7_MCL, +COALESCE(G.BEFORE_DUE_7_MFS,0) AS BEFORE_DUE_7_MFS, +COALESCE(H.BEFORE_DUE_7_MIS,0) AS BEFORE_DUE_7_MIS, +COALESCE(I.PER1_MCL,0) AS PER1_MCL, +COALESCE(J.PER1_MFS,0) AS PER1_MFS, +COALESCE(K.PER1_MIS,0) AS PER1_MIS, +COALESCE(L.PER2_MCL,0) AS PER2_MCL, +COALESCE(M.PER2_MFS,0) AS PER2_MFS, +COALESCE(N.PER2_MIS,0) AS PER2_MIS, +COALESCE(O.PER3_MCL,0) AS PER3_MCL, +COALESCE(P.PER3_MFS,0) AS PER3_MFS, +COALESCE(R.PER3_MIS,0) AS PER3_MIS, +COALESCE(S.PER4_MCL,0) AS PER4_MCL, +COALESCE(T.PER4_MFS,0) AS PER4_MFS, +COALESCE(U.PER4_MIS,0) AS PER4_MIS, +COALESCE(V.PER5_MCL,0) AS PER5_MCL, +COALESCE(X.PER5_MFS,0) AS PER5_MFS, +COALESCE(Z.PER5_MIS,0) AS PER5_MIS, +COALESCE(Q.PER6_MCL,0) AS PER6_MCL, +COALESCE(Y.PER6_MFS,0) AS PER6_MFS, +COALESCE(W.PER6_MIS,0) AS PER6_MIS, +COALESCE(A1.PER7_MCL,0) AS PER7_MCL, +COALESCE(B1.PER7_MFS,0) AS PER7_MFS, +COALESCE(C1.PER7_MIS,0) AS PER7_MIS, +A.BEFORE_DUE_7,A.PER1,A.PER2,A.PER3,A.PER4,A.PER5,A.PER6,A.PER7, +CONCAT(A.DIVISION,'-',A.CLIENT_NUMBER) AS REF,"2" AS TYPE FROM +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER, +GROUP_CONCAT(DISTINCT CLIENT_INFO SEPARATOR '<br>') AS CLIENT_INFO, +GROUP_CONCAT(DISTINCT CLIENT_NAME SEPARATOR '<br>') AS CLIENT_NAME, +GROUP_CONCAT( DISTINCT `PHONE_NUMBER` SEPARATOR '<br>' ) AS PHONE_NUMBER , +GROUP_CONCAT( DISTINCT `ATTENTION_NAME` SEPARATOR '<br>' ) AS ATTENTION_NAME, +GROUP_CONCAT( DISTINCT `PAYMENT_TERM` SEPARATOR '<br>' ) AS PAYMENT_TERM, +CREDIT_LIMIT , +GROUP_CONCAT( `LAST_PAY_DATE` SEPARATOR '<br>' ) AS LAST_PAY_DATE, +SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL, +SUM( `BEFORE_DUE_7`*EXCHANGE_RATE ) AS BEFORE_DUE_7, +SUM( `PER1`*EXCHANGE_RATE ) AS PER1, +SUM( `PER2`*EXCHANGE_RATE ) AS PER2, +SUM( `PER3`*EXCHANGE_RATE ) AS PER3, +SUM( `PER4`*EXCHANGE_RATE ) AS PER4, +SUM( `PER5`*EXCHANGE_RATE ) AS PER5, +SUM( `PER6`*EXCHANGE_RATE ) AS PER6, +SUM( `PER7`*EXCHANGE_RATE ) AS PER7 +FROM `t2` +WHERE REF IS NULL GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS A +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS B ON A.CLIENT_NUMBER=B.CLIENT_NUMBER AND +A.DIVISION=B.DIVISION AND A.RECEIVABLE_GROUP=B.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=B.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS C ON A.CLIENT_NUMBER=C.CLIENT_NUMBER +AND +A.DIVISION=C.DIVISION AND A.RECEIVABLE_GROUP=C.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=C.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS D ON A.CLIENT_NUMBER=D.CLIENT_NUMBER AND +A.DIVISION=D.DIVISION AND A.RECEIVABLE_GROUP=D.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=D.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( BEFORE_DUE_7*EXCHANGE_RATE ) AS BEFORE_DUE_7_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS F ON A.CLIENT_NUMBER=F.CLIENT_NUMBER AND +A.DIVISION=F.DIVISION AND A.RECEIVABLE_GROUP=F.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=F.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( BEFORE_DUE_7*EXCHANGE_RATE ) AS BEFORE_DUE_7_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS G ON A.CLIENT_NUMBER=G.CLIENT_NUMBER AND +A.DIVISION=G.DIVISION AND A.RECEIVABLE_GROUP=G.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=G.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( BEFORE_DUE_7*EXCHANGE_RATE ) AS BEFORE_DUE_7_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS H ON A.CLIENT_NUMBER=H.CLIENT_NUMBER AND +A.DIVISION=H.DIVISION AND A.RECEIVABLE_GROUP=H.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=H.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER1*EXCHANGE_RATE ) AS PER1_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS I ON A.CLIENT_NUMBER=I.CLIENT_NUMBER AND +A.DIVISION=I.DIVISION AND A.RECEIVABLE_GROUP=I.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=I.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER1*EXCHANGE_RATE ) AS PER1_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS J ON A.CLIENT_NUMBER=J.CLIENT_NUMBER AND +A.DIVISION=J.DIVISION AND A.RECEIVABLE_GROUP=J.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=J.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER1*EXCHANGE_RATE ) AS PER1_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS K ON A.CLIENT_NUMBER=K.CLIENT_NUMBER AND +A.DIVISION=K.DIVISION AND A.RECEIVABLE_GROUP=K.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=K.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER2*EXCHANGE_RATE ) AS PER2_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS L ON A.CLIENT_NUMBER=L.CLIENT_NUMBER AND +A.DIVISION=L.DIVISION AND A.RECEIVABLE_GROUP=L.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=L.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER2*EXCHANGE_RATE ) AS PER2_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS M ON A.CLIENT_NUMBER=M.CLIENT_NUMBER AND +A.DIVISION=M.DIVISION AND A.RECEIVABLE_GROUP=M.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=M.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER2*EXCHANGE_RATE ) AS PER2_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS N ON A.CLIENT_NUMBER=N.CLIENT_NUMBER AND +A.DIVISION=N.DIVISION AND A.RECEIVABLE_GROUP=N.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=N.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER3*EXCHANGE_RATE ) AS PER3_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS O ON A.CLIENT_NUMBER=O.CLIENT_NUMBER AND +A.DIVISION=O.DIVISION AND A.RECEIVABLE_GROUP=O.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=O.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER3*EXCHANGE_RATE ) AS PER3_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS P ON A.CLIENT_NUMBER=P.CLIENT_NUMBER AND +A.DIVISION=P.DIVISION AND A.RECEIVABLE_GROUP=P.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=P.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER3*EXCHANGE_RATE ) AS PER3_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS R ON A.CLIENT_NUMBER=R.CLIENT_NUMBER AND +A.DIVISION=R.DIVISION AND A.RECEIVABLE_GROUP=R.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=R.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER4*EXCHANGE_RATE ) AS PER4_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS S ON A.CLIENT_NUMBER=S.CLIENT_NUMBER AND +A.DIVISION=S.DIVISION AND A.RECEIVABLE_GROUP=S.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=S.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER4*EXCHANGE_RATE ) AS PER4_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS T ON A.CLIENT_NUMBER=T.CLIENT_NUMBER AND +A.DIVISION=T.DIVISION AND A.RECEIVABLE_GROUP=T.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=T.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER4*EXCHANGE_RATE ) AS PER4_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS U ON A.CLIENT_NUMBER=U.CLIENT_NUMBER AND +A.DIVISION=U.DIVISION AND A.RECEIVABLE_GROUP=U.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=U.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER5*EXCHANGE_RATE ) AS PER5_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS V ON A.CLIENT_NUMBER=V.CLIENT_NUMBER AND +A.DIVISION=V.DIVISION AND A.RECEIVABLE_GROUP=V.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=V.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER5*EXCHANGE_RATE ) AS PER5_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS X ON A.CLIENT_NUMBER=X.CLIENT_NUMBER AND +A.DIVISION=X.DIVISION AND A.RECEIVABLE_GROUP=X.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=X.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER5*EXCHANGE_RATE ) AS PER5_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS Z ON A.CLIENT_NUMBER=Z.CLIENT_NUMBER AND +A.DIVISION=Z.DIVISION AND A.RECEIVABLE_GROUP=Z.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=Z.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER6*EXCHANGE_RATE ) AS PER6_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS Q ON A.CLIENT_NUMBER=Q.CLIENT_NUMBER AND +A.DIVISION=Q.DIVISION AND A.RECEIVABLE_GROUP=Q.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=Q.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER6*EXCHANGE_RATE ) AS PER6_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS Y ON A.CLIENT_NUMBER=Y.CLIENT_NUMBER AND +A.DIVISION=Y.DIVISION AND A.RECEIVABLE_GROUP=Y.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=Y.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER6*EXCHANGE_RATE ) AS PER6_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS W ON A.CLIENT_NUMBER=W.CLIENT_NUMBER AND +A.DIVISION=W.DIVISION AND A.RECEIVABLE_GROUP=W.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=W.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER7*EXCHANGE_RATE ) AS PER7_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS A1 ON A.CLIENT_NUMBER=A1.CLIENT_NUMBER AND +A.DIVISION=A1.DIVISION AND A.RECEIVABLE_GROUP=A1.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=A1.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER7*EXCHANGE_RATE ) AS PER7_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS B1 ON A.CLIENT_NUMBER=B1.CLIENT_NUMBER AND +A.DIVISION=B1.DIVISION AND A.RECEIVABLE_GROUP=B1.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=B1.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER7*EXCHANGE_RATE ) AS PER7_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS C1 ON A.CLIENT_NUMBER=C1.CLIENT_NUMBER AND +A.DIVISION=C1.DIVISION AND A.RECEIVABLE_GROUP=C1.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=C1.CREDIT_LIMIT +ORDER BY TOTAL DESC; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived3> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived4> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived5> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived6> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived7> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived8> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived9> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived10> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived11> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived12> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived13> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived14> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived15> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived16> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived17> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived18> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived19> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived20> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived21> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived22> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived23> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived24> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived25> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived26> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived27> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived28> system NULL NULL NULL NULL 0 const row not found +1 PRIMARY <derived29> system NULL NULL NULL NULL 0 const row not found +29 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +28 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +27 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +26 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +25 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +24 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +23 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +22 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +21 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +20 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +19 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +18 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +17 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +16 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +15 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +14 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +13 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +12 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +11 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +10 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +9 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +8 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +7 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +6 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +5 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +4 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +3 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +DROP TABLES t1,t2; set optimizer_switch=@save_derived_optimizer_switch; # # Start of 10.1 tests diff --git a/mysql-test/r/events_2.result b/mysql-test/r/events_2.result index 9a1f9d954e8..c57893ccf6f 100644 --- a/mysql-test/r/events_2.result +++ b/mysql-test/r/events_2.result @@ -2,10 +2,10 @@ set sql_mode=""; drop database if exists events_test; create database events_test; use events_test; -create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5; +create event e_26 on schedule at '2027-01-01 00:00:00' disable do set @a = 5; select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event; db name body definer convert_tz(execute_at, 'UTC', 'SYSTEM') on_completion -events_test e_26 set @a = 5 root@localhost 2017-01-01 00:00:00 DROP +events_test e_26 set @a = 5 root@localhost 2027-01-01 00:00:00 DROP drop event e_26; create event e_26 on schedule at NULL disable do set @a = 5; ERROR HY000: Incorrect AT value: 'NULL' diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result index 3de6a6e48fc..bde4f1c785b 100644 --- a/mysql-test/r/events_bugs.result +++ b/mysql-test/r/events_bugs.result @@ -91,7 +91,7 @@ create table events_smode_test(ev_name char(10), a date); "This should never insert something" create event ee_16407_2 on schedule every 60 second do begin -select get_lock('ee_16407_2', 60) /*ee_16407_2*/; +select get_lock('ee_16407_2', 60); /*ee_16407_2*/ select release_lock('ee_16407_2'); insert into events_test.events_smode_test values('ee_16407_2','1980-19-02'); end| @@ -100,7 +100,7 @@ ERROR 22007: Incorrect date value: '1980-19-02' for column 'a' at row 1 "This is ok" create event ee_16407_3 on schedule every 60 second do begin -select get_lock('ee_16407_2', 60) /*ee_16407_3*/; +select get_lock('ee_16407_2', 60); /*ee_16407_3*/ select release_lock('ee_16407_2'); insert into events_test.events_smode_test values ('ee_16407_3','1980-02-19'); insert into events_test.events_smode_test values ('ee_16407_3','1980-02-29'); @@ -109,7 +109,7 @@ set sql_mode=""| "This will insert rows but they will be truncated" create event ee_16407_4 on schedule every 60 second do begin -select get_lock('ee_16407_2', 60) /*ee_16407_4*/; +select get_lock('ee_16407_2', 60); /*ee_16407_4*/ select release_lock('ee_16407_2'); insert into events_test.events_smode_test values ('ee_16407_4','10-11-1956'); end| @@ -157,13 +157,13 @@ create procedure ee_16407_5_pendant() begin insert into events_test.events_smode create procedure ee_16407_6_pendant() begin insert into events_test.events_smode_test values('ee_16407_6','2004-02-29'); end| create event ee_16407_5 on schedule every 60 second do begin -select get_lock('ee_16407_5', 60) /*ee_16407_5*/; +select get_lock('ee_16407_5', 60); /*ee_16407_5*/ select release_lock('ee_16407_5'); call events_test.ee_16407_5_pendant(); end| create event ee_16407_6 on schedule every 60 second do begin -select get_lock('ee_16407_5', 60) /*ee_16407_6*/; +select get_lock('ee_16407_5', 60); /*ee_16407_6*/ select release_lock('ee_16407_5'); call events_test.ee_16407_6_pendant(); end| @@ -603,7 +603,7 @@ INSERT INTO events_test.event_log VALUES (NULL,@evname,@cnt+1,current_timestamp( ROLLBACK; END IF; END;| -Sleep till the first INSERT into events_test.event_log occured +Sleep till the first INSERT into events_test.event_log occurred SELECT COUNT(*) > 0 AS "Expect 1" FROM events_test.event_log; Expect 1 1 diff --git a/mysql-test/r/explain_json.result b/mysql-test/r/explain_json.result index 975d0fddf38..89df0209073 100644 --- a/mysql-test/r/explain_json.result +++ b/mysql-test/r/explain_json.result @@ -1536,3 +1536,43 @@ ANALYZE set optimizer_switch=@tmp_optimizer_switch; set join_cache_level=@tmp_join_cache_level; drop table t1,t2,t3,t4; +# +# MDEV-9652: EXPLAIN FORMAT=JSON should show outer_ref_cond +# +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (a int, b int); +insert into t1 select a,a from t0; +explain format=json +select a, (select max(a) from t1 where t0.a<5 and t1.b<t0.a) from t0; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t0", + "access_type": "ALL", + "rows": 10, + "filtered": 100 + }, + "subqueries": [ + { + "expression_cache": { + "state": "uninitialized", + "query_block": { + "select_id": 2, + "outer_ref_condition": "(t0.a < 5)", + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 10, + "filtered": 100, + "attached_condition": "((t0.a < 5) and (t1.b < t0.a))" + } + } + } + } + ] + } +} +drop table t0,t1; diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 0bc31a5e85b..9014450bef3 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -1119,3 +1119,84 @@ GROUP_CONCAT(t1a.a ORDER BY 1, t1a.a=0) 1,1 2,2 DROP TABLE t1; +# +# WL#6098 Eliminate GROUP_CONCAT intermediate result limitation. +# Bug#13387020 GROUP_CONCAT WITH ORDER BY RESULTS ARE TRUNCATED. +# +SET group_concat_max_len= 9999999; +CREATE TABLE t1 (f1 LONGTEXT , f2 INTEGER); +INSERT INTO t1 VALUES (REPEAT('a', 500000), 0), (REPEAT('b', 500000), 1), (REPEAT('c', 500000), 2); +SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1; +LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) +1500002 +SELECT LENGTH(GROUP_CONCAT(DISTINCT f1 ORDER BY f1 DESC)) FROM t1; +LENGTH(GROUP_CONCAT(DISTINCT f1 ORDER BY f1 DESC)) +1500002 +SELECT SUBSTRING(GROUP_CONCAT(DISTINCT f1 ORDER BY f1 DESC), 1, 5) FROM t1; +SUBSTRING(GROUP_CONCAT(DISTINCT f1 ORDER BY f1 DESC), 1, 5) +ccccc +SELECT LENGTH(GROUP_CONCAT(DISTINCT f1)) FROM t1; +LENGTH(GROUP_CONCAT(DISTINCT f1)) +1500002 +SELECT LENGTH(GROUP_CONCAT(UPPER(f1) ORDER BY f2)) FROM t1; +LENGTH(GROUP_CONCAT(UPPER(f1) ORDER BY f2)) +1500002 +SELECT LENGTH(GROUP_CONCAT(DISTINCT UPPER(f1) ORDER BY f1)) FROM t1; +LENGTH(GROUP_CONCAT(DISTINCT UPPER(f1) ORDER BY f1)) +1500002 +SELECT SUBSTRING(GROUP_CONCAT(DISTINCT UPPER(f1) ORDER BY f1), 1, 5) FROM t1; +SUBSTRING(GROUP_CONCAT(DISTINCT UPPER(f1) ORDER BY f1), 1, 5) +AAAAA +SELECT LENGTH(GROUP_CONCAT(DISTINCT UPPER(f1))) FROM t1; +LENGTH(GROUP_CONCAT(DISTINCT UPPER(f1))) +1500002 +CREATE TABLE t2 SELECT GROUP_CONCAT(f1 order by f2) FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `GROUP_CONCAT(f1 order by f2)` mediumtext +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +CREATE TABLE t2 SELECT GROUP_CONCAT(UPPER(f1) ORDER BY f2) FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `GROUP_CONCAT(UPPER(f1) ORDER BY f2)` mediumtext +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t2; +SET group_concat_max_len= DEFAULT; +SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1; +LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) +1024 +Warnings: +Warning 1260 Row 2 was cut by GROUP_CONCAT() +SET group_concat_max_len= 499999; +SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1 WHERE f2 = 0; +LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) +499999 +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1 GROUP BY f2; +LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) +499999 +499999 +499999 +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() +INSERT INTO t1 VALUES (REPEAT('a', 499999), 3), (REPEAT('b', 500000), 4); +SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1 GROUP BY f2; +LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) +499999 +499999 +499999 +499999 +499999 +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() +Warning 1260 Row 5 was cut by GROUP_CONCAT() +DROP TABLE t1; +SET group_concat_max_len= DEFAULT; diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index aa12100e0dc..4b3d3ed2e39 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -2298,6 +2298,15 @@ id avg cast_avg 2 9223372036854775807.0000 9223372036854775807 DROP TABLE t1; # +# MDEV-9656 Assertion `0' failed in Item_sum_field::get_tmp_table_field() +# +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT DISTINCT VAR_POP(1) FROM t1 GROUP BY @a := 's'; +VAR_POP(1) +0.0000 +DROP TABLE t1; +# # MDEV-8921 Wrong result for CAST(AVG(double_column) AS SIGNED) # CREATE TABLE t1 (id INT, a DOUBLE); diff --git a/mysql-test/r/func_hybrid_type.result b/mysql-test/r/func_hybrid_type.result index 95a8a8235d4..eeaa79e7dce 100644 --- a/mysql-test/r/func_hybrid_type.result +++ b/mysql-test/r/func_hybrid_type.result @@ -2175,10 +2175,10 @@ def case_____a_b 12 19 19 Y 128 0 63 def case_____b_a 12 19 19 Y 128 0 63 def coalesce_a_b 12 19 19 Y 128 0 63 def coalesce_b_a 12 19 19 Y 128 0 63 -def if_______a_b 12 10 19 Y 128 0 63 -def if_______b_a 12 10 19 Y 128 0 63 -def ifnull___a_b 12 10 19 Y 128 0 63 -def ifnull___b_a 12 10 19 Y 128 0 63 +def if_______a_b 12 19 19 Y 128 0 63 +def if_______b_a 12 19 19 Y 128 0 63 +def ifnull___a_b 12 19 19 Y 128 0 63 +def ifnull___b_a 12 19 19 Y 128 0 63 def least____a_b 12 10 19 Y 128 0 63 def least____b_a 12 10 19 Y 128 0 63 def greatest_a_b 12 10 19 Y 128 0 63 @@ -3396,5 +3396,36 @@ c1 DROP TABLE t2; DROP TABLE t1; # +# MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool) +# +SELECT CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END; +CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END +NULL +SELECT CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END; +CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END +NULL +SELECT CASE WHEN TRUE THEN COALESCE(NULL) ELSE 4 END; +CASE WHEN TRUE THEN COALESCE(NULL) ELSE 4 END +NULL +SELECT COALESCE(COALESCE(NULL), 1.1) AS c0, IF(0, COALESCE(NULL), 1.1) AS c1; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def c0 246 4 3 Y 32896 1 63 +def c1 246 4 3 Y 32896 1 63 +c0 c1 +1.1 1.1 +# +# MDEV-9752 Wrong data type for COALEASCE(?,1) in prepared statements +# +PREPARE stmt FROM "CREATE TABLE t1 AS SELECT CONCAT(COALESCE(?,1)) AS a, CONCAT(CASE WHEN TRUE THEN ? ELSE 1 END) AS b"; +SET @a=1; +EXECUTE stmt USING @a,@a; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(21) DEFAULT NULL, + `b` varchar(21) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +# # End of 10.1 tests # diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 9bc80613710..f196571218f 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -204,7 +204,7 @@ CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),repeat(' "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es'); insert('txs',2,1,'hi') insert('is ',4,0,'a') insert('txxxxt',2,4,'es') -this is a test +this is test select replace('aaaa','a','b'),replace('aaaa','aa','b'),replace('aaaa','a','bb'),replace('aaaa','','b'),replace('bbbb','a','c'); replace('aaaa','a','b') replace('aaaa','aa','b') replace('aaaa','a','bb') replace('aaaa','','b') replace('bbbb','a','c') bbbb bb bbbbbbbb aaaa bbbb @@ -2343,7 +2343,7 @@ INSERT('abc', 3, 3, '1234') ab1234 SELECT INSERT('abc', 4, 3, '1234'); INSERT('abc', 4, 3, '1234') -abc1234 +abc SELECT INSERT('abc', 5, 3, '1234'); INSERT('abc', 5, 3, '1234') abc @@ -2633,7 +2633,7 @@ CREATE TABLE t1 ( a TEXT ); SELECT 'aaaaaaaaaaaaaa' INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug58165.txt';; SELECT insert( substring_index( 'a', 'a', 'b' ), 1, 0, 'x' ); insert( substring_index( 'a', 'a', 'b' ), 1, 0, 'x' ) -x + Warnings: Warning 1292 Truncated incorrect INTEGER value: 'b' LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug58165.txt' INTO TABLE t1;; @@ -4571,5 +4571,16 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = 18446744073709551615) and (format(`test`.`t1`.`a`,0) = '18,446,744,073,709,551,615')) DROP TABLE t1; # +# Bug#58081 Duplicate entry error when doing GROUP BY +# MDEV-9332 Bug after upgrade to 10.1.10 +# +SET NAMES latin1; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0),(0),(1),(0),(0); +SELECT COUNT(*) FROM t1, t1 t2 GROUP BY INSERT('', t2.a, t1.a, @@global.max_binlog_size); +COUNT(*) +25 +DROP TABLE t1; +# # End of 10.1 tests # diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 994fa8580eb..ad51010de30 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -1729,6 +1729,45 @@ Warnings: Warning 1292 Incorrect datetime value: '1' drop table t1; SET timestamp=DEFAULT; +# +# Bug #21564557: INCONSISTENT OUTPUT FROM 5.5 AND 5.6 +# UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%M" +# +SELECT UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m")); +UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m")) +NULL +Warnings: +Warning 1411 Incorrect datetime value: '201506' for function str_to_date +SELECT UNIX_TIMESTAMP('2015-06-00'); +UNIX_TIMESTAMP('2015-06-00') +NULL +Warnings: +Warning 1292 Incorrect datetime value: '2015-06-00' +SELECT UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s')); +UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s')) +NULL +Warnings: +Warning 1411 Incorrect datetime value: '0000-00-00 10:30:30' for function str_to_date +set sql_mode= 'TRADITIONAL'; +SELECT @@sql_mode; +@@sql_mode +STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION +SELECT UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m")); +UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m")) +NULL +Warnings: +Warning 1411 Incorrect datetime value: '201506' for function str_to_date +SELECT UNIX_TIMESTAMP('2015-06-00'); +UNIX_TIMESTAMP('2015-06-00') +NULL +Warnings: +Warning 1292 Incorrect datetime value: '2015-06-00' +SELECT UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s')); +UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s')) +NULL +Warnings: +Warning 1411 Incorrect datetime value: '0000-00-00 10:30:30' for function str_to_date +set sql_mode= default; select time('10:10:10') > 10; time('10:10:10') > 10 1 diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index f55489b7d93..40d72db8ab3 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -2671,3 +2671,41 @@ field1 field2 DROP TABLE t1; DROP TABLE where_subselect; # End of Bug #58782 +# +# MDEV-8988: Apparently valid SQL query gives wrong result (nested WHERE) +# +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (a int, b int, c int); +insert into t1 select A.a + 10*B.a, A.a, A.a + 10*B.a from t0 A, t0 B; +insert into t1 values (NULL, NULL, NULL); +create table t2 (c int, col1 int, key(c)); +insert into t2 select t1.a, 100000 from t1; +analyze table t2; +Table Op Msg_type Msg_text +test.t2 analyze status Table is already up to date +explain +select +max(a)+ (select col1 from t2 where t2.c=t1.c) +from t1 +group by t1.b; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 101 Using temporary; Using filesort +2 DEPENDENT SUBQUERY t2 ref c c 5 func 1 +select +max(a) + (select col1 from t2 where t2.c=t1.c) +from t1 +group by t1.b; +max(a) + (select col1 from t2 where t2.c=t1.c) +NULL +100090 +100091 +100092 +100093 +100094 +100095 +100096 +100097 +100098 +100099 +drop table t0,t1,t2; diff --git a/mysql-test/r/index_merge_myisam.result b/mysql-test/r/index_merge_myisam.result index 9820170aa59..a857e2a21ff 100644 --- a/mysql-test/r/index_merge_myisam.result +++ b/mysql-test/r/index_merge_myisam.result @@ -1595,7 +1595,7 @@ explain select * from t1 where a=10 and b=10 or c=10; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index_merge a,b,c a,c 5,5 NULL 54 Using union(a,c); Using where This will switch to sort-union (intersection will be gone, too, -thats a known limitation: +that's a known limitation: set optimizer_switch='default,index_merge_union=off'; explain select * from t1 where a=10 and b=10 or c=10; id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/r/information_schema_inno.result b/mysql-test/r/information_schema_inno.result index 838a7ad5162..7755d112f8e 100644 --- a/mysql-test/r/information_schema_inno.result +++ b/mysql-test/r/information_schema_inno.result @@ -101,3 +101,8 @@ SELECT * FROM information_schema.partitions WHERE table_schema= 'test' AND table_name= 'v1'; DROP TABLE t1; DROP VIEW v1; +CREATE TABLE t1(i int) ENGINE=Innodb ROW_FORMAT=REDUNDANT DATA DIRECTORY='MYSQLTEST_VARDIR/tmp'; +SELECT CREATE_OPTIONS FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME='t1'; +CREATE_OPTIONS +row_format=REDUNDANT DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' +DROP TABLE t1; diff --git a/mysql-test/r/log_slow.result b/mysql-test/r/log_slow.result index f7670f3d3db..6a3f48506e3 100644 --- a/mysql-test/r/log_slow.result +++ b/mysql-test/r/log_slow.result @@ -9,8 +9,10 @@ select @@log_slow_verbosity; show variables like "log_slow%"; Variable_name Value +log_slow_admin_statements OFF log_slow_filter admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk log_slow_rate_limit 1 +log_slow_slave_statements OFF log_slow_verbosity set @org_slow_query_log= @@global.slow_query_log; set @@log_slow_filter= "filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk,admin"; diff --git a/mysql-test/r/mdev375.result b/mysql-test/r/mdev375.result index 32580804686..426336e5939 100644 --- a/mysql-test/r/mdev375.result +++ b/mysql-test/r/mdev375.result @@ -10,5 +10,8 @@ ERROR HY000: Too many connections SELECT 0; 0 0 +show status like "Threads_connected"; +Variable_name Value +Threads_connected 3 SET GLOBAL log_warnings=default; SET GLOBAL max_connections=default; diff --git a/mysql-test/r/merge_innodb.result b/mysql-test/r/merge_innodb.result index f6057d279b1..5aa344a9391 100644 --- a/mysql-test/r/merge_innodb.result +++ b/mysql-test/r/merge_innodb.result @@ -35,3 +35,36 @@ c1 Ann Alice DROP TABLE t1, t2, t3, t4, t5; +create table t1 (c1 varchar(100)); +create table t2 (c1 varchar(100)); +create view t3 as select * from t1; +insert into t1 values ('ann'), ('alice'); +insert into t2 values ('bob'), ('brian'); +create temporary table t4 (c1 varchar(100)) engine=MERGE union=(t2, t1); +create temporary table t5 (c1 varchar(100)) engine=MERGE union=(t3, t1); +select * from t5; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +lock tables t1 read, t2 read, t3 read, t4 read; +select * from t5; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +select * from t4; +c1 +bob +brian +ann +alice +unlock tables; +drop table t2; +create view t2 as select * from t1; +select * from t4; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +lock tables t1 read, t2 read, t3 read; +select * from t4; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +select * from t4; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +select * from t4; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +unlock tables; +drop view t2, t3; +drop table t1; diff --git a/mysql-test/r/mysql_upgrade_view.result b/mysql-test/r/mysql_upgrade_view.result index ef54ab6c9a5..f43f42f97fd 100644 --- a/mysql-test/r/mysql_upgrade_view.result +++ b/mysql-test/r/mysql_upgrade_view.result @@ -319,4 +319,64 @@ master-bin.000001 # Gtid # # GTID #-#-# master-bin.000001 # Query # # use `test`; REPAIR VIEW `v4` FROM MYSQL drop table if exists kv; drop view v1,v2,v3,v4; +rename table mysql.event to mysql.ev_bk; +flush tables; +The --upgrade-system-tables option was used, user tables won't be touched. +MySQL upgrade detected +Phase 1/6: Checking and upgrading mysql database +Processing databases +mysql +mysql.column_stats OK +mysql.columns_priv OK +mysql.db OK +mysql.ev_bk OK +mysql.event OK +mysql.func OK +mysql.gtid_slave_pos OK +mysql.help_category OK +mysql.help_keyword OK +mysql.help_relation OK +mysql.help_topic OK +mysql.host OK +mysql.index_stats OK +mysql.innodb_index_stats +Error : Unknown storage engine 'InnoDB' +error : Corrupt +mysql.innodb_table_stats +Error : Unknown storage engine 'InnoDB' +error : Corrupt +mysql.plugin OK +mysql.proc OK +mysql.procs_priv OK +mysql.proxies_priv OK +mysql.roles_mapping OK +mysql.servers OK +mysql.table_stats OK +mysql.tables_priv OK +mysql.time_zone OK +mysql.time_zone_leap_second OK +mysql.time_zone_name OK +mysql.time_zone_transition OK +mysql.time_zone_transition_type OK +mysql.user OK + +Repairing tables +mysql.innodb_index_stats +Error : Unknown storage engine 'InnoDB' +error : Corrupt +mysql.innodb_table_stats +Error : Unknown storage engine 'InnoDB' +error : Corrupt +Phase 2/6: Fixing views from mysql +test.v1 OK +test.v2 OK +test.v3 OK +Phase 3/6: Running 'mysql_fix_privilege_tables' +Phase 4/6: Fixing table and database names ... Skipped +Phase 5/6: Checking and upgrading tables... Skipped +Phase 6/6: Running 'FLUSH PRIVILEGES' +OK +drop table mysql.event; +rename table mysql.ev_bk to mysql.event; +drop view v1,v2,v3; drop table t1; diff --git a/mysql-test/r/mysqlbinlog_raw_mode.result b/mysql-test/r/mysqlbinlog_raw_mode.result new file mode 100644 index 00000000000..b64a2148a82 --- /dev/null +++ b/mysql-test/r/mysqlbinlog_raw_mode.result @@ -0,0 +1,274 @@ +reset master; +set timestamp=1000000000; +drop table if exists t1; +CREATE TABLE t1 (c01 BIT); +INSERT INTO t1 VALUES (0); +INSERT INTO t1 VALUES (1); +DROP TABLE t1; +CREATE TABLE t1 (c01 BIT(7)); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (16); +INSERT INTO t1 VALUES (32); +INSERT INTO t1 VALUES (64); +INSERT INTO t1 VALUES (127); +DELETE FROM t1 WHERE c01=127; +UPDATE t1 SET c01=15 WHERE c01=16; +DROP TABLE t1; +CREATE TABLE t1 (a BIT(20), b CHAR(2)); +INSERT INTO t1 VALUES (b'00010010010010001001', 'ab'); +DROP TABLE t1; +CREATE TABLE t1 (c02 BIT(64)); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (128); +INSERT INTO t1 VALUES (b'1111111111111111111111111111111111111111111111111111111111111111'); +DROP TABLE t1; +CREATE TABLE t1 (c03 TINYINT); +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t1 VALUES (-128); +UPDATE t1 SET c03=2 WHERE c03=1; +DELETE FROM t1 WHERE c03=-128; +DROP TABLE t1; +CREATE TABLE t1 (c04 TINYINT UNSIGNED); +INSERT INTO t1 VALUES (128), (255); +UPDATE t1 SET c04=2 WHERE c04=1; +DELETE FROM t1 WHERE c04=255; +DROP TABLE t1; +CREATE TABLE t1 (c06 BOOL); +INSERT INTO t1 VALUES (TRUE); +DELETE FROM t1 WHERE c06=TRUE; +DROP TABLE t1; +CREATE TABLE t1 (c07 SMALLINT); +INSERT INTO t1 VALUES (1234); +DELETE FROM t1 WHERE c07=1234; +DROP TABLE t1; +CREATE TABLE t1 (c08 SMALLINT UNSIGNED); +INSERT INTO t1 VALUES (32768), (65535); +UPDATE t1 SET c08=2 WHERE c08=32768; +DELETE FROM t1 WHERE c08=65535; +DROP TABLE t1; +CREATE TABLE t1 (c10 MEDIUMINT); +INSERT INTO t1 VALUES (12345); +DELETE FROM t1 WHERE c10=12345; +DROP TABLE t1; +CREATE TABLE t1 (c11 MEDIUMINT UNSIGNED); +INSERT INTO t1 VALUES (8388608), (16777215); +UPDATE t1 SET c11=2 WHERE c11=8388608; +DELETE FROM t1 WHERE c11=16777215; +DROP TABLE t1; +CREATE TABLE t1 (c13 INT); +INSERT INTO t1 VALUES (123456); +DELETE FROM t1 WHERE c13=123456; +DROP TABLE t1; +CREATE TABLE t1 (c14 INT UNSIGNED); +INSERT INTO t1 VALUES (2147483648), (4294967295); +UPDATE t1 SET c14=2 WHERE c14=2147483648; +DELETE FROM t1 WHERE c14=4294967295; +DROP TABLE t1; +CREATE TABLE t1 (c16 BIGINT); +INSERT INTO t1 VALUES (1234567890); +DELETE FROM t1 WHERE c16=1234567890; +DROP TABLE t1; +CREATE TABLE t1 (c17 BIGINT UNSIGNED); +INSERT INTO t1 VALUES (9223372036854775808), (18446744073709551615); +UPDATE t1 SET c17=2 WHERE c17=9223372036854775808; +DELETE FROM t1 WHERE c17=18446744073709551615; +DROP TABLE t1; +CREATE TABLE t1 (c19 FLOAT); +INSERT INTO t1 VALUES (123.2234); +DELETE FROM t1 WHERE c19>123; +DROP TABLE t1; +CREATE TABLE t1 (c22 DOUBLE); +INSERT INTO t1 VALUES (123434.22344545); +DELETE FROM t1 WHERE c22>123434; +DROP TABLE t1; +CREATE TABLE t1 (c25 DECIMAL(10,5)); +INSERT INTO t1 VALUES (124.45); +INSERT INTO t1 VALUES (-543.21); +DELETE FROM t1 WHERE c25=124.45; +DROP TABLE t1; +CREATE TABLE t1 (c28 DATE); +INSERT INTO t1 VALUES ('2001-02-03'); +DELETE FROM t1 WHERE c28='2001-02-03'; +DROP TABLE t1; +CREATE TABLE t1 (c29 DATETIME); +INSERT INTO t1 VALUES ('2001-02-03 10:20:30'); +DELETE FROM t1 WHERE c29='2001-02-03 10:20:30'; +DROP TABLE t1; +CREATE TABLE t1 (c30 TIMESTAMP); +INSERT INTO t1 VALUES ('2001-02-03 10:20:30'); +DELETE FROM t1 WHERE c30='2001-02-03 10:20:30'; +DROP TABLE t1; +CREATE TABLE t1 (c31 TIME); +INSERT INTO t1 VALUES ('11:22:33'); +DELETE FROM t1 WHERE c31='11:22:33'; +DROP TABLE t1; +CREATE TABLE t1 (c32 YEAR); +INSERT INTO t1 VALUES ('2001'); +DELETE FROM t1 WHERE c32=2001; +DROP TABLE t1; +CREATE TABLE t1 (c33 CHAR); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c33='a'; +DROP TABLE t1; +CREATE TABLE t1 (c34 CHAR(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c34=''; +DROP TABLE t1; +CREATE TABLE t1 (c35 CHAR(1)); +INSERT INTO t1 VALUES ('b'); +DELETE FROM t1 WHERE c35='b'; +DROP TABLE t1; +CREATE TABLE t1 (c36 CHAR(255)); +INSERT INTO t1 VALUES (repeat('c',255)); +DELETE FROM t1 WHERE c36>'c'; +DROP TABLE t1; +CREATE TABLE t1 (c37 NATIONAL CHAR); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c37='a'; +DROP TABLE t1; +CREATE TABLE t1 (c38 NATIONAL CHAR(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c38=''; +DROP TABLE t1; +CREATE TABLE t1 (c39 NATIONAL CHAR(1)); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c39='a'; +DROP TABLE t1; +CREATE TABLE t1 (c40 NATIONAL CHAR(255)); +INSERT INTO t1 VALUES (repeat('a', 255)); +INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255)); +DELETE FROM t1 WHERE c40>'a'; +DROP TABLE t1; +CREATE TABLE t1 (c45 VARCHAR(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c45=''; +DROP TABLE t1; +CREATE TABLE t1 (c46 VARCHAR(1)); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c46='a'; +DROP TABLE t1; +CREATE TABLE t1 (c47 VARCHAR(255)); +INSERT INTO t1 VALUES (repeat('a',255)); +DELETE FROM t1 WHERE c47>'a'; +DROP TABLE t1; +CREATE TABLE t1 (c48 VARCHAR(261)); +INSERT INTO t1 VALUES (repeat('a',261)); +DELETE FROM t1 WHERE c48>'a'; +DROP TABLE t1; +CREATE TABLE t1 (c49 NATIONAL VARCHAR(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c49=''; +DROP TABLE t1; +CREATE TABLE t1 (c50 NATIONAL VARCHAR(1)); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c50='a'; +DROP TABLE t1; +CREATE TABLE t1 (c51 NATIONAL VARCHAR(255)); +INSERT INTO t1 VALUES (repeat('a',255)); +INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255)); +DELETE FROM t1 WHERE c51>'a'; +DROP TABLE t1; +CREATE TABLE t1 (c52 NATIONAL VARCHAR(261)); +INSERT INTO t1 VALUES (repeat('a',261)); +INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 261)); +DELETE FROM t1 WHERE c52>'a'; +DROP TABLE t1; +CREATE TABLE t1 (c57 BINARY); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c57='a'; +DROP TABLE t1; +CREATE TABLE t1 (c58 BINARY(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c58=''; +DROP TABLE t1; +CREATE TABLE t1 (c59 BINARY(1)); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c59='a'; +DROP TABLE t1; +CREATE TABLE t1 (c60 BINARY(255)); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES (repeat('a\0',120)); +DELETE FROM t1 WHERE c60<0x02; +DROP TABLE t1; +CREATE TABLE t1 (c61 VARBINARY(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c61=''; +DROP TABLE t1; +CREATE TABLE t1 (c62 VARBINARY(1)); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c62=0x02; +DROP TABLE t1; +CREATE TABLE t1 (c63 VARBINARY(255)); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES (repeat('a\0',120)); +DELETE FROM t1 WHERE c63=0x02; +DROP TABLE t1; +flush logs; +CREATE TABLE t1 (c65 TINYBLOB); +INSERT INTO t1 VALUES ('tinyblob1'); +DELETE FROM t1 WHERE c65='tinyblob1'; +DROP TABLE t1; +CREATE TABLE t1 (c68 BLOB); +INSERT INTO t1 VALUES ('blob1'); +DELETE FROM t1 WHERE c68='blob1'; +DROP TABLE t1; +CREATE TABLE t1 (c71 MEDIUMBLOB); +INSERT INTO t1 VALUES ('mediumblob1'); +DELETE FROM t1 WHERE c71='mediumblob1'; +DROP TABLE t1; +CREATE TABLE t1 (c74 LONGBLOB); +INSERT INTO t1 VALUES ('longblob1'); +DELETE FROM t1 WHERE c74='longblob1'; +DROP TABLE t1; +CREATE TABLE t1 (c66 TINYTEXT); +INSERT INTO t1 VALUES ('tinytext1'); +DELETE FROM t1 WHERE c66='tinytext1'; +DROP TABLE t1; +CREATE TABLE t1 (c69 TEXT); +INSERT INTO t1 VALUES ('text1'); +DELETE FROM t1 WHERE c69='text1'; +DROP TABLE t1; +CREATE TABLE t1 (c72 MEDIUMTEXT); +INSERT INTO t1 VALUES ('mediumtext1'); +DELETE FROM t1 WHERE c72='mediumtext1'; +DROP TABLE t1; +CREATE TABLE t1 (c75 LONGTEXT); +INSERT INTO t1 VALUES ('longtext1'); +DELETE FROM t1 WHERE c75='longtext1'; +DROP TABLE t1; +CREATE TABLE t1 (c77 ENUM('a','b','c')); +INSERT INTO t1 VALUES ('b'); +DELETE FROM t1 WHERE c77='b'; +DROP TABLE t1; +CREATE TABLE t1 (c78 SET('a','b','c','d','e','f')); +INSERT INTO t1 VALUES ('a,b'); +INSERT INTO t1 VALUES ('a,c'); +INSERT INTO t1 VALUES ('b,c'); +INSERT INTO t1 VALUES ('a,b,c'); +INSERT INTO t1 VALUES ('a,b,c,d'); +INSERT INTO t1 VALUES ('a,b,c,d,e'); +INSERT INTO t1 VALUES ('a,b,c,d,e,f'); +DELETE FROM t1 WHERE c78='a,b'; +DROP TABLE t1; +CREATE TABLE t1 (a int NOT NULL DEFAULT 0, b int NOT NULL DEFAULT 0); +CREATE TABLE t2 (a int NOT NULL DEFAULT 0, b int NOT NULL DEFAULT 0); +INSERT INTO t1 SET a=1; +INSERT INTO t1 SET b=1; +INSERT INTO t2 SET a=1; +INSERT INTO t2 SET b=1; +UPDATE t1, t2 SET t1.a=10, t2.a=20; +DROP TABLE t1,t2; +flush logs; +End of tests diff --git a/mysql-test/r/mysqld--help,win.rdiff b/mysql-test/r/mysqld--help,win.rdiff index 57adfd7a2f6..a3bf5c55ee8 100644 --- a/mysql-test/r/mysqld--help,win.rdiff +++ b/mysql-test/r/mysqld--help,win.rdiff @@ -1,6 +1,6 @@ --- mysqld--help.result +++ mysqld--help,win.reject -@@ -321,7 +321,6 @@ The following options may be given as the first argument: +@@ -321,7 +321,6 @@ The number of segments in a key cache -L, --language=name Client error messages in given language. May be given as a full path. Deprecated. Use --lc-messages-dir instead. @@ -8,7 +8,7 @@ --lc-messages=name Set the language used for the error messages. -L, --lc-messages-dir=name Directory where error messages are -@@ -517,6 +516,7 @@ The following options may be given as the first argument: +@@ -517,6 +516,7 @@ Use MySQL-5.6 (instead of MariaDB-5.3) format for TIME, DATETIME, TIMESTAMP columns. (Defaults to on; use --skip-mysql56-temporal-format to disable.) @@ -16,7 +16,7 @@ --net-buffer-length=# Buffer length for TCP/IP and socket communication --net-read-timeout=# -@@ -906,6 +906,9 @@ The following options may be given as the first argument: +@@ -903,6 +903,9 @@ files within specified directory --server-id=# Uniquely identifies the server instance in the community of replication partners @@ -26,7 +26,7 @@ --show-slave-auth-info Show user and password in SHOW SLAVE HOSTS on this master. -@@ -1016,6 +1019,10 @@ The following options may be given as the first argument: +@@ -1015,6 +1018,10 @@ Log slow queries to given log file. Defaults logging to 'hostname'-slow.log. Must be enabled to activate other slow log options @@ -37,7 +37,7 @@ --socket=name Socket file to use for connection --sort-buffer-size=# Each thread that needs to do a sort allocates a buffer of -@@ -1034,6 +1041,7 @@ The following options may be given as the first argument: +@@ -1033,6 +1040,7 @@ NO_ENGINE_SUBSTITUTION, PAD_CHAR_TO_FULL_LENGTH --stack-trace Print a symbolic stack trace on failure (Defaults to on; use --skip-stack-trace to disable.) @@ -45,10 +45,10 @@ --stored-program-cache=# The soft upper limit for number of cached stored routines for one connection. -@@ -1070,25 +1078,11 @@ The following options may be given as the first argument: - COMMIT, ROLLBACK +@@ -1070,25 +1078,11 @@ --thread-cache-size=# - How many threads we should keep in a cache for reuse + How many threads we should keep in a cache for reuse. + These are freed after 5 minutes of idle time - --thread-pool-idle-timeout=# - Timeout in seconds for an idle thread in the thread - pool.Worker thread will be shut down after timeout @@ -73,7 +73,7 @@ --thread-stack=# The stack size for each thread --time-format=name The TIME format (ignored) --timed-mutexes Specify whether to time mutexes. Deprecated, has no -@@ -1097,8 +1091,8 @@ The following options may be given as the first argument: +@@ -1097,8 +1091,8 @@ size, MySQL will automatically convert it to an on-disk MyISAM or Aria table -t, --tmpdir=name Path for temporary files. Several paths may be specified, @@ -84,7 +84,7 @@ --transaction-alloc-block-size=# Allocation block size for transactions to be stored in binary log -@@ -1224,7 +1218,6 @@ key-cache-block-size 1024 +@@ -1225,7 +1219,6 @@ key-cache-division-limit 100 key-cache-file-hash-size 512 key-cache-segments 0 @@ -92,7 +92,7 @@ lc-messages en_US lc-messages-dir MYSQL_SHAREDIR/ lc-time-names en_US -@@ -1290,6 +1283,7 @@ myisam-sort-buffer-size 134216704 +@@ -1291,6 +1284,7 @@ myisam-stats-method NULLS_UNEQUAL myisam-use-mmap FALSE mysql56-temporal-format TRUE @@ -100,7 +100,7 @@ net-buffer-length 16384 net-read-timeout 30 net-retry-count 10 -@@ -1386,6 +1380,8 @@ safe-user-create FALSE +@@ -1387,6 +1381,8 @@ secure-auth TRUE secure-file-priv (No default value) server-id 0 @@ -109,7 +109,7 @@ show-slave-auth-info FALSE silent-startup FALSE skip-grant-tables TRUE -@@ -1409,6 +1405,7 @@ slave-transaction-retries 10 +@@ -1411,6 +1407,7 @@ slave-type-conversions slow-launch-time 2 slow-query-log FALSE @@ -117,7 +117,7 @@ sort-buffer-size 2097152 sql-mode NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION stack-trace TRUE -@@ -1421,15 +1418,13 @@ sync-master-info 10000 +@@ -1423,15 +1420,13 @@ sync-relay-log 10000 sync-relay-log-info 10000 sysdate-is-now FALSE @@ -127,12 +127,12 @@ -table-open-cache 431 +table-open-cache 2000 tc-heuristic-recover COMMIT - thread-cache-size 0 + thread-cache-size 151 -thread-pool-idle-timeout 60 thread-pool-max-threads 1000 -thread-pool-oversubscribe 3 -thread-pool-stall-limit 500 +thread-pool-min-threads 1 - thread-stack 294912 + thread-stack 296960 time-format %H:%i:%s timed-mutexes FALSE diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 5e02b92b98c..a35693eb93e 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -974,6 +974,8 @@ The following options may be given as the first argument: replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave + --slave-parallel-workers=# + Alias for slave_parallel_threads --slave-run-triggers-for-rbr=name Modes for how triggers in row-base replication on slave side will be executed. Legal values are NO (default), YES @@ -1066,7 +1068,8 @@ The following options may be given as the first argument: Decision to use in heuristic recover process. One of: COMMIT, ROLLBACK --thread-cache-size=# - How many threads we should keep in a cache for reuse + How many threads we should keep in a cache for reuse. + These are freed after 5 minutes of idle time --thread-pool-idle-timeout=# Timeout in seconds for an idle thread in the thread pool.Worker thread will be shut down after timeout @@ -1338,7 +1341,7 @@ performance-schema-max-rwlock-instances -1 performance-schema-max-socket-classes 10 performance-schema-max-socket-instances -1 performance-schema-max-stage-classes 150 -performance-schema-max-statement-classes 178 +performance-schema-max-statement-classes 181 performance-schema-max-table-handles -1 performance-schema-max-table-instances -1 performance-schema-max-thread-classes 50 @@ -1400,6 +1403,7 @@ slave-net-timeout 3600 slave-parallel-max-queued 131072 slave-parallel-mode conservative slave-parallel-threads 0 +slave-parallel-workers 0 slave-run-triggers-for-rbr NO slave-skip-errors (No default value) slave-sql-verify-checksum TRUE @@ -1423,12 +1427,12 @@ table-cache 431 table-definition-cache 400 table-open-cache 431 tc-heuristic-recover COMMIT -thread-cache-size 0 +thread-cache-size 151 thread-pool-idle-timeout 60 thread-pool-max-threads 1000 thread-pool-oversubscribe 3 thread-pool-stall-limit 500 -thread-stack 294912 +thread-stack 296960 time-format %H:%i:%s timed-mutexes FALSE tmp-table-size 16777216 diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 3646618cb1d..559f8885b0d 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1821,7 +1821,7 @@ a b Osnabrück Köln drop table t1; # -# Bug#15328 Segmentation fault occured if my.cnf is invalid for escape sequence +# Bug#15328 Segmentation fault occurred if my.cnf is invalid for escape sequence # --fields-optionally-enclosed-by=" # @@ -3715,7 +3715,7 @@ CREATE TEMPORARY TABLE `TABLES` ( `CHECK_TIME` datetime DEFAULT NULL, `TABLE_COLLATION` varchar(32) DEFAULT NULL, `CHECKSUM` bigint(21) unsigned DEFAULT NULL, - `CREATE_OPTIONS` varchar(255) DEFAULT NULL, + `CREATE_OPTIONS` varchar(2048) DEFAULT NULL, `TABLE_COMMENT` varchar(2048) NOT NULL DEFAULT '' ) ENGINE=MEMORY DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result index b4cebac661f..3da7e4805c2 100644 --- a/mysql-test/r/null.result +++ b/mysql-test/r/null.result @@ -1465,5 +1465,112 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = 2020) and ((case when 2020 = 2010 then NULL else `test`.`t1`.`a` end) = concat('2020',rand()))) DROP TABLE t1; # +# MDEV-9181 (NULLIF(count(table.col)), 0) gives wrong result on 10.1.x +# +CREATE TABLE t1 (c1 varchar(50) DEFAULT NULL); +INSERT INTO t1 (c1) VALUES ('hello'), ('hello\r\n'), ('hello'),('hello'); +SELECT NULLIF(COUNT(c1),0) FROM t1; +NULLIF(COUNT(c1),0) +4 +SELECT CASE WHEN COUNT(c1)=0 THEN NULL ELSE COUNT(c1) END FROM t1; +CASE WHEN COUNT(c1)=0 THEN NULL ELSE COUNT(c1) END +4 +SELECT NULLIF(COUNT(c1)+0,0) AS c1,NULLIF(CAST(COUNT(c1) AS SIGNED),0) AS c2,NULLIF(CONCAT(COUNT(c1)),0) AS c3 FROM t1; +c1 c2 c3 +4 4 4 +SELECT NULLIF(COUNT(DISTINCT c1),0) FROM t1; +NULLIF(COUNT(DISTINCT c1),0) +2 +SELECT CASE WHEN COUNT(DISTINCT c1)=0 THEN NULL ELSE COUNT(DISTINCT c1) END FROM t1; +CASE WHEN COUNT(DISTINCT c1)=0 THEN NULL ELSE COUNT(DISTINCT c1) END +2 +DROP TABLE t1; +CREATE TABLE t1 ( +id INT NOT NULL, +c1 INT DEFAULT NULL +); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3),(2,4); +SELECT NULLIF(COUNT(c1),0) AS c1,NULLIF(COUNT(c1)+0,0) AS c1_wrapped,CASE WHEN COUNT(c1) IS NULL THEN 0 ELSE COUNT(c1) END AS c1_case FROM t1 GROUP BY id; +c1 c1_wrapped c1_case +2 2 2 +2 2 2 +DROP TABLE t1; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SET @a=0; +SELECT NULLIF(LAST_VALUE(@a:=@a+1,a),0) FROM t1; +NULLIF(LAST_VALUE(@a:=@a+1,a),0) +1 +2 +3 +SELECT @a; +@a +6 +SET @a=0; +SELECT NULLIF(AVG(a),0), NULLIF(AVG(LAST_VALUE(@a:=@a+1,a)),0) FROM t1; +NULLIF(AVG(a),0) NULLIF(AVG(LAST_VALUE(@a:=@a+1,a)),0) +2.0000 2.0000 +SELECT @a; +@a +3 +EXPLAIN EXTENDED SELECT NULLIF(a,0) FROM t1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select nullif(`test`.`t1`.`a`,0) AS `NULLIF(a,0)` from `test`.`t1` +EXPLAIN EXTENDED SELECT NULLIF(AVG(a),0) FROM t1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select nullif(<cache>(avg(`test`.`t1`.`a`)),0) AS `NULLIF(AVG(a),0)` from `test`.`t1` +DROP TABLE t1; +create table t1 (col1 varchar(50)); +create view v1 AS select nullif(count(distinct col1),0) from t1; +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 nullif(count(distinct `t1`.`col1`),0) AS `nullif(count(distinct col1),0)` from `t1` latin1 latin1_swedish_ci +drop view v1; +drop table t1; +create table t1 (col1 varchar(50) default null); +insert into t1 (col1) values ('hello'), ('hello'), ('hello'); +create view v1 as select nullif(count(col1),0) from t1; +select * from v1; +nullif(count(col1),0) +3 +select nullif(count(col1),0) from t1; +nullif(count(col1),0) +3 +drop view v1; +drop table t1; +select nullif((select 1), (select 2)); +nullif((select 1), (select 2)) +1 +create table t1 (f int); +insert into t1 values (1),(2); +select nullif( not f, 1 ) from t1; +nullif( not f, 1 ) +0 +0 +drop table t1; +set names utf8; +create table t1 (f1 varchar(10)); +insert into t1 values ('2015-12-31'); +select power( timestamp( nullif( '2002-09-08', f1 ) ), 24 ) from t1; +ERROR 22003: DOUBLE value is out of range in 'pow(cast((case when '2002-09-08' = '2015-12-31' then NULL else '2002-09-08' end) as datetime(6)),24)' +drop table t1; +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1),(2); +PREPARE stmt FROM "SELECT * FROM t1 WHERE NULLIF( ( 1, 2 ) IN ( SELECT 3, 4 ), 1 )"; +EXECUTE stmt; +f1 +EXECUTE stmt; +f1 +DROP TABLE t1; +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT * FROM t1 WHERE NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(i = ROUND(0), 14), 13), 12), 11), 10), 9), 8), 7), 6), 5), 4), 3), 2), 1); +i +DROP TABLE t1; +# # End of 10.1 tests # diff --git a/mysql-test/r/order_by_innodb.result b/mysql-test/r/order_by_innodb.result index 3c6c4053741..4f59a2f8c20 100644 --- a/mysql-test/r/order_by_innodb.result +++ b/mysql-test/r/order_by_innodb.result @@ -11,3 +11,40 @@ a b c d 8 NULL 9 NULL 8 NULL 10 NULL DROP TABLE t1; +# +# MDEV-9457: Poor query plan chosen for ORDER BY query by a recent 10.1 +# +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 ( +pk int primary key, +key1 int, +key2 int, +col1 char(255), +key(key1), +key(key2) +) engine=innodb; +set @a=-1; +insert into t1 +select +@a:=@a+1, +@a, +@a, +repeat('abcd', 63) +from t0 A, t0 B, t0 C, t0 D; +# The following must NOT use 'index' on PK. +# It should use index_merge(key1,key2) + filesort +explain +select * +from t1 +where key1<3 or key2<3 +order by pk; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL # Using sort_union(key1,key2); Using where; Using filesort +explain +select * +from t1 +where key1<3 or key2<3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL # Using sort_union(key1,key2); Using where +drop table t0, t1; diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result index c6d7c383ce7..fe19473f8e4 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -3466,3 +3466,21 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 PRIMARY t2 p_1000 ref PRIMARY PRIMARY 8 const 2 Using index 1 PRIMARY t1 p_1000 ALL PRIMARY NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join) drop table t1,t2; +# +# MDEV-9505: Valgrind failure in SEL_ARG::store_min,find_used_partitions,... +# +create table t1 (a int, b char(10), c varchar(5), d int) +partition by range columns(a,b,c) +subpartition by key (c,d) +subpartitions 3 +( partition p0 values less than (1,'abc','abc'), +partition p1 values less than (2,'abc','abc'), +partition p2 values less than (3,'abc','abc'), +partition p3 values less than (4,'abc','abc') +); +insert into t1 values (1,'a','b',1),(2,'a','b',2),(3,'a','b',3); +select * from t1 where (a = 1 AND b < 'd' AND (c = 'b' OR (c = 'c' AND d = 1)) OR +(a = 1 AND b >= 'a' AND (c = 'c' OR (c = 'd' AND d = 2)))); +a b c d +1 a b 1 +drop table t1; diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result index 59a606128f5..9a19c3b0604 100644 --- a/mysql-test/r/row.result +++ b/mysql-test/r/row.result @@ -50,6 +50,12 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 select ((1,2,(3,4)) in ((3,2,(3,4)),(1,2,(3,NULL)))) AS `row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)))` +select row(1,2,row(3,null)) IN (row(3,2,row(3,4)), row(1,2,row(4,5))); +row(1,2,row(3,null)) IN (row(3,2,row(3,4)), row(1,2,row(4,5))) +0 +select row(1,2,row(3,null)) IN (row(3,2,row(3,4)), row(1,2,row(3,5))); +row(1,2,row(3,null)) IN (row(3,2,row(3,4)), row(1,2,row(3,5))) +NULL SELECT (1,2,3)=(0,NULL,3); (1,2,3)=(0,NULL,3) 0 @@ -130,7 +136,7 @@ ROW(c,2,3) IN(row(1,b,a), row(2,3,1)) 0 0 1 -NULL +0 select ROW(a,b,c) IN(row(1,2,3), row(3,2,1)) from t1; ROW(a,b,c) IN(row(1,2,3), row(3,2,1)) 1 @@ -509,5 +515,11 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 10) and (`test`.`t1`.`b` = 10)) DROP TABLE t1; # +# MDEV-9369 IN operator with ( num, NULL ) gives inconsistent result +# +SELECT (1,null) NOT IN ((2,2),(3,3)), (1,null) NOT IN ((2,2)), (1,null) NOT IN ((3,3)); +(1,null) NOT IN ((2,2),(3,3)) (1,null) NOT IN ((2,2)) (1,null) NOT IN ((3,3)) +1 1 1 +# # End of 10.1 tests # diff --git a/mysql-test/r/second_frac-9175.result b/mysql-test/r/second_frac-9175.result new file mode 100644 index 00000000000..dbf268b5c3b --- /dev/null +++ b/mysql-test/r/second_frac-9175.result @@ -0,0 +1,13 @@ +select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456'); +timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456') +31622400123456 +explain extended select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456'); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select timestampdiff(MICROSECOND,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456') AS `timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456')` +create view v1 as select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456'); +select * from v1; +Name_exp_1 +31622400123456 +drop view v1; diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result index 238a9414ead..8462e19fda8 100644 --- a/mysql-test/r/select_found.result +++ b/mysql-test/r/select_found.result @@ -348,3 +348,18 @@ select found_rows(); found_rows() 75 drop table t1; +create table t1(c1 int); +insert into t1 values(1),(2),(3),(4),(5); +select * from t1 order by c1 limit 2,1; +c1 +3 +select found_rows(); +found_rows() +3 +select sql_calc_found_rows * from t1 order by c1 limit 2,1; +c1 +3 +select found_rows(); +found_rows() +5 +drop table t1; diff --git a/mysql-test/r/show.result b/mysql-test/r/show.result new file mode 100644 index 00000000000..3dd7af5de05 --- /dev/null +++ b/mysql-test/r/show.result @@ -0,0 +1,12 @@ +show statistics; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'statistics' at line 1 +show spatial_ref_sys +--error ER_PARSE_ERROR +show system_variables; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'spatial_ref_sys +--error ER_PARSE_ERROR +show system_variables' at line 2 +show geometry_columns; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'geometry_columns' at line 1 +show nonexistent; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'nonexistent' at line 1 diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 6d1cbb21ac7..654b00d68ae 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -133,7 +133,7 @@ def information_schema TABLES TABLES UPDATE_TIME Update_time 12 19 0 Y 128 0 63 def information_schema TABLES TABLES CHECK_TIME Check_time 12 19 0 Y 128 0 63 def information_schema TABLES TABLES TABLE_COLLATION Collation 253 32 0 Y 0 0 8 def information_schema TABLES TABLES CHECKSUM Checksum 8 21 0 Y 32800 0 63 -def information_schema TABLES TABLES CREATE_OPTIONS Create_options 253 255 0 Y 0 0 8 +def information_schema TABLES TABLES CREATE_OPTIONS Create_options 253 2048 0 Y 0 0 8 def information_schema TABLES TABLES TABLE_COMMENT Comment 253 2048 0 N 1 0 8 Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment show databases; @@ -935,7 +935,7 @@ def information_schema TABLES TABLES TABLE_TYPE TABLE_TYPE 253 192 10 N 1 0 33 def information_schema TABLES TABLES ENGINE ENGINE 253 192 6 Y 0 0 33 def information_schema TABLES TABLES ROW_FORMAT ROW_FORMAT 253 30 5 Y 0 0 33 def information_schema TABLES TABLES TABLE_COLLATION TABLE_COLLATION 253 96 17 Y 0 0 33 -def information_schema TABLES TABLES CREATE_OPTIONS CREATE_OPTIONS 253 765 0 Y 0 0 33 +def information_schema TABLES TABLES CREATE_OPTIONS CREATE_OPTIONS 253 6144 0 Y 0 0 33 def information_schema TABLES TABLES TABLE_COMMENT TABLE_COMMENT 253 6144 0 N 1 0 33 TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE ROW_FORMAT TABLE_COLLATION CREATE_OPTIONS TABLE_COMMENT def test t1 BASE TABLE MyISAM Fixed latin1_swedish_ci diff --git a/mysql-test/r/show_create_user.result b/mysql-test/r/show_create_user.result new file mode 100644 index 00000000000..63013eca074 --- /dev/null +++ b/mysql-test/r/show_create_user.result @@ -0,0 +1,39 @@ +create user foo; +show create user foo; +CREATE USER for foo@% +CREATE USER 'foo'@'%' +create user foo@test; +show create user foo@test; +CREATE USER for foo@test +CREATE USER 'foo'@'test' +create user foo2@test identified by 'password'; +show create user foo2@test; +CREATE USER for foo2@test +CREATE USER 'foo2'@'test' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19' +alter user foo2@test identified with 'someplugin' as 'somepassword'; +show create user foo2@test; +CREATE USER for foo2@test +CREATE USER 'foo2'@'test' IDENTIFIED VIA someplugin USING 'somepassword' +create user foo3@test require SSL; +show create user foo3@test; +CREATE USER for foo3@test +CREATE USER 'foo3'@'test' REQUIRE SSL +create user foo4@test require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; +show create user foo4@test; +CREATE USER for foo4@test +CREATE USER 'foo4'@'test' REQUIRE ISSUER 'foo_issuer' SUBJECT 'foo_subject' CIPHER 'text' +create user foo5@test require SSL +with MAX_QUERIES_PER_HOUR 10 +MAX_UPDATES_PER_HOUR 20 +MAX_CONNECTIONS_PER_HOUR 30 +MAX_USER_CONNECTIONS 40 +MAX_STATEMENT_TIME 0.5; +show create user foo5@test; +CREATE USER for foo5@test +CREATE USER 'foo5'@'test' REQUIRE SSL WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30 MAX_USER_CONNECTIONS 40 MAX_STATEMENT_TIME 0.500000 +drop user foo5@test; +drop user foo4@test; +drop user foo3@test; +drop user foo2@test; +drop user foo@test; +drop user foo; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 51c1b1924d1..9453a1da3ca 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4326,57 +4326,57 @@ test.t1 repair status OK test.t2 repair status OK test.t3 repair status OK test.v1 repair Error 'test.v1' is not BASE TABLE -test.v1 repair error Corrupt +test.v1 repair status Operation failed Table Op Msg_type Msg_text test.t1 optimize status OK test.t2 optimize status OK test.t3 optimize status OK test.v1 optimize Error 'test.v1' is not BASE TABLE -test.v1 optimize error Corrupt +test.v1 optimize status Operation failed Table Op Msg_type Msg_text test.t1 analyze status Table is already up to date test.t2 analyze status Table is already up to date test.t3 analyze status Table is already up to date test.v1 analyze Error 'test.v1' is not BASE TABLE -test.v1 analyze error Corrupt +test.v1 analyze status Operation failed call bug13012()| Table Op Msg_type Msg_text test.t1 repair status OK test.t2 repair status OK test.t3 repair status OK test.v1 repair Error 'test.v1' is not BASE TABLE -test.v1 repair error Corrupt +test.v1 repair status Operation failed Table Op Msg_type Msg_text test.t1 optimize status OK test.t2 optimize status OK test.t3 optimize status OK test.v1 optimize Error 'test.v1' is not BASE TABLE -test.v1 optimize error Corrupt +test.v1 optimize status Operation failed Table Op Msg_type Msg_text test.t1 analyze status Table is already up to date test.t2 analyze status Table is already up to date test.t3 analyze status Table is already up to date test.v1 analyze Error 'test.v1' is not BASE TABLE -test.v1 analyze error Corrupt +test.v1 analyze status Operation failed call bug13012()| Table Op Msg_type Msg_text test.t1 repair status OK test.t2 repair status OK test.t3 repair status OK test.v1 repair Error 'test.v1' is not BASE TABLE -test.v1 repair error Corrupt +test.v1 repair status Operation failed Table Op Msg_type Msg_text test.t1 optimize status OK test.t2 optimize status OK test.t3 optimize status OK test.v1 optimize Error 'test.v1' is not BASE TABLE -test.v1 optimize error Corrupt +test.v1 optimize status Operation failed Table Op Msg_type Msg_text test.t1 analyze status Table is already up to date test.t2 analyze status Table is already up to date test.t3 analyze status Table is already up to date test.v1 analyze Error 'test.v1' is not BASE TABLE -test.v1 analyze error Corrupt +test.v1 analyze status Operation failed drop procedure bug13012| drop view v1| select * from t1 order by data| diff --git a/mysql-test/r/ssl_cert_verify.result b/mysql-test/r/ssl_cert_verify.result new file mode 100644 index 00000000000..1da77329509 --- /dev/null +++ b/mysql-test/r/ssl_cert_verify.result @@ -0,0 +1,5 @@ +#T1: Host name (/CN=localhost/) as OU name in the server certificate, server certificate verification should fail. +#T2: Host name (localhost) as common name in the server certificate, server certificate verification should pass. +Variable_name Value +Ssl_version TLS_VERSION +# restart server using restart diff --git a/mysql-test/r/statistics.result b/mysql-test/r/statistics.result index bd6a0849e3d..be2e39665b3 100644 --- a/mysql-test/r/statistics.result +++ b/mysql-test/r/statistics.result @@ -1212,6 +1212,7 @@ test t2 PRIMARY 1 1.0000 ANALYZE TABLE t1; Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b' test.t1 analyze status OK SELECT * FROM mysql.column_stats; db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram @@ -1225,7 +1226,6 @@ test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL -test t1 b NULL NULL 0.2000 17.1250 NULL NULL NULL NULL SELECT * FROM mysql.index_stats; db_name table_name index_name prefix_arity avg_frequency test t1 idx2 1 7.0000 @@ -1265,6 +1265,7 @@ set use_stat_tables='never'; ANALYZE TABLE t1 PERSISTENT FOR ALL; Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b' test.t1 analyze status Table is already up to date SELECT * FROM mysql.table_stats; db_name table_name cardinality @@ -1276,7 +1277,6 @@ test t1 c aaaa dddddddd 0.1250 6.6571 7.0000 0 NULL NULL test t1 d 1989-03-12 1999-07-23 0.1500 3.0000 8.5000 0 NULL NULL test t1 e 0.01 0.112 0.2250 8.0000 6.2000 0 NULL NULL test t1 f 1 5 0.2000 1.0000 6.4000 0 NULL NULL -test t1 b NULL NULL 0.2000 17.1250 NULL NULL NULL NULL SELECT * FROM mysql.index_stats; db_name table_name index_name prefix_arity avg_frequency test t1 PRIMARY 1 1.0000 @@ -1291,6 +1291,28 @@ test t1 idx4 3 NULL DELETE FROM mysql.table_stats; DELETE FROM mysql.column_stats; DELETE FROM mysql.index_stats; +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b' +test.t1 analyze status Table is already up to date +ANALYZE TABLE t1 PERSISTENT FOR columns(a,b) INDEXES(); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b' +test.t1 analyze status Table is already up to date +ANALYZE TABLE t1 PERSISTENT FOR columns(b) indexes(idx2); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'b' +test.t1 analyze status Table is already up to date +ANALYZE TABLE t1 PERSISTENT FOR columns() indexes(idx2); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +DELETE FROM mysql.table_stats; +DELETE FROM mysql.column_stats; +DELETE FROM mysql.index_stats; DROP TABLE t1,t2; set names utf8; CREATE DATABASE world; @@ -1641,3 +1663,17 @@ FROM mysql.column_stats; db_name table_name column_name HEX(min_value) HEX(max_value) nulls_ratio avg_frequency hist_size hist_type HEX(histogram) test t1 a D879626AF872675F73E662F8 D879626AF872675F73E662F8 0.0000 1.0000 0 NULL NULL drop table t1; +# +# MDEV-9590: Always print "Engine-independent statistic" warnings and +# might be filtering columns unintentionally from engines +# +set use_stat_tables='NEVER'; +create table t1 (test blob); +show variables like 'use_stat_tables'; +Variable_name Value +use_stat_tables NEVER +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Table is already up to date +drop table t1; +set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/r/statistics_index_crash-7362.result b/mysql-test/r/statistics_index_crash-7362.result index 99f65d7e1b7..c213fa49afe 100644 --- a/mysql-test/r/statistics_index_crash-7362.result +++ b/mysql-test/r/statistics_index_crash-7362.result @@ -3,6 +3,7 @@ INSERT INTO t1 VALUES (unhex('3E0D0A4141414142334E7A6143317963324541414141424977 ANALYZE TABLE t1 PERSISTENT FOR ALL; Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'a' test.t1 analyze status OK SELECT * FROM mysql.index_stats WHERE index_name='a' AND table_name='t1'; db_name table_name index_name prefix_arity avg_frequency @@ -13,6 +14,7 @@ INSERT INTO t1 VALUES (unhex('3E0D0A4141414142334E7A6143317963324541414141424977 ANALYZE TABLE t1 PERSISTENT FOR ALL; Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 'a' test.t1 analyze status OK SELECT * FROM mysql.index_stats WHERE index_name='a' AND table_name='t1'; db_name table_name index_name prefix_arity avg_frequency diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 75c8597590a..ac874f9943c 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -7110,6 +7110,20 @@ NULL deallocate prepare stmt; drop table t1,t2,t3,t4; # +# MDEV-7122 +# Assertion `0' failed in subselect_hash_sj_engine::init +# +SET SESSION big_tables=1; +CREATE TABLE t1(a char(255) DEFAULT '', KEY(a(10))) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +INSERT INTO t1 VALUES(0),(0),(0); +SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1); +a +0 +0 +0 +DROP TABLE t1; +SET SESSION big_tables=0; +# # MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || # m_lock_type != 2' failed in handler::ha_index_read_map # diff --git a/mysql-test/r/subselect_extra_no_semijoin.result b/mysql-test/r/subselect_extra_no_semijoin.result index e5b36055c91..79bca388181 100644 --- a/mysql-test/r/subselect_extra_no_semijoin.result +++ b/mysql-test/r/subselect_extra_no_semijoin.result @@ -349,9 +349,9 @@ WHERE t.a IN (SELECT b FROM t1); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where -3 MATERIALIZED t1 system NULL NULL NULL NULL 1 100.00 +3 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 1 100.00 Warnings: -Note 1003 select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,0 in ( <materialize> (select 0 from dual ), <primary_index_lookup>(0 in <temporary table> on distinct_key where ((0 = `<subquery3>`.`b`)))))) +Note 1003 select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,<exists>(select 0 from dual where (<cache>(0) = 0)))) SELECT * FROM t2 RIGHT JOIN v1 AS t ON t.a != 0 WHERE t.a IN (SELECT b FROM t1); a a b @@ -362,9 +362,9 @@ WHERE t.a IN (SELECT b FROM t1); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where -2 MATERIALIZED t1 system NULL NULL NULL NULL 1 100.00 +2 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 1 100.00 Warnings: -Note 1003 select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,0 in ( <materialize> (select 0 from dual ), <primary_index_lookup>(0 in <temporary table> on distinct_key where ((0 = `<subquery2>`.`b`)))))) +Note 1003 select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,<exists>(select 0 from dual where (<cache>(0) = 0)))) DROP VIEW v1; DROP TABLE t1,t2; # diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result index 976d03946e6..c9fa7c0c672 100644 --- a/mysql-test/r/subselect_mat.result +++ b/mysql-test/r/subselect_mat.result @@ -762,6 +762,10 @@ select left(a1,7), left(a2,7) from t1_512 where a1 in (select group_concat(b1) from t2_512 group by b2); left(a1,7) left(a2,7) +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() set @@group_concat_max_len = 256; explain extended select left(a1,7), left(a2,7) from t1_512 @@ -775,6 +779,10 @@ select left(a1,7), left(a2,7) from t1_512 where a1 in (select group_concat(b1) from t2_512 group by b2); left(a1,7) left(a2,7) +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() drop table t1_512, t2_512, t3_512; set @blob_len = 1024; set @suffix_len = @blob_len - @prefix_len; @@ -855,6 +863,10 @@ select left(a1,7), left(a2,7) from t1_1024 where a1 in (select group_concat(b1) from t2_1024 group by b2); left(a1,7) left(a2,7) +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() set @@group_concat_max_len = 256; explain extended select left(a1,7), left(a2,7) from t1_1024 @@ -868,6 +880,10 @@ select left(a1,7), left(a2,7) from t1_1024 where a1 in (select group_concat(b1) from t2_1024 group by b2); left(a1,7) left(a2,7) +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() drop table t1_1024, t2_1024, t3_1024; set @blob_len = 1025; set @suffix_len = @blob_len - @prefix_len; @@ -948,6 +964,10 @@ select left(a1,7), left(a2,7) from t1_1025 where a1 in (select group_concat(b1) from t2_1025 group by b2); left(a1,7) left(a2,7) +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() set @@group_concat_max_len = 256; explain extended select left(a1,7), left(a2,7) from t1_1025 @@ -961,6 +981,10 @@ select left(a1,7), left(a2,7) from t1_1025 where a1 in (select group_concat(b1) from t2_1025 group by b2); left(a1,7) left(a2,7) +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() drop table t1_1025, t2_1025, t3_1025; create table t1bit (a1 bit(3), a2 bit(3)); create table t2bit (b1 bit(3), b2 bit(3)); @@ -2518,3 +2542,18 @@ a b sq 4 4 1 4 2 1 drop table t1, t2; +# +# MDEV-9489: Assertion `0' failed in Protocol::end_statement() on +# UNION ALL +# +CREATE TABLE t1 (f1 INT); +CREATE TABLE t2 (f2 INT); +INSERT INTO t1 VALUES (1),(2); +( SELECT 1 FROM t1 WHERE f1 NOT IN ( SELECT f2 FROM t2 ) LIMIT 0 ) +UNION ALL +( SELECT 1 FROM t1 WHERE f1 NOT IN ( SELECT f2 FROM t2 ) ) +; +1 +1 +1 +drop table t1, t2; diff --git a/mysql-test/r/subselect_no_exists_to_in.result b/mysql-test/r/subselect_no_exists_to_in.result index e6238af4cdc..6a5bec062c7 100644 --- a/mysql-test/r/subselect_no_exists_to_in.result +++ b/mysql-test/r/subselect_no_exists_to_in.result @@ -7110,6 +7110,20 @@ NULL deallocate prepare stmt; drop table t1,t2,t3,t4; # +# MDEV-7122 +# Assertion `0' failed in subselect_hash_sj_engine::init +# +SET SESSION big_tables=1; +CREATE TABLE t1(a char(255) DEFAULT '', KEY(a(10))) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +INSERT INTO t1 VALUES(0),(0),(0); +SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1); +a +0 +0 +0 +DROP TABLE t1; +SET SESSION big_tables=0; +# # MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || # m_lock_type != 2' failed in handler::ha_index_read_map # diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index 70edc6463c4..a574319b175 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -7103,6 +7103,20 @@ NULL deallocate prepare stmt; drop table t1,t2,t3,t4; # +# MDEV-7122 +# Assertion `0' failed in subselect_hash_sj_engine::init +# +SET SESSION big_tables=1; +CREATE TABLE t1(a char(255) DEFAULT '', KEY(a(10))) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +INSERT INTO t1 VALUES(0),(0),(0); +SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1); +a +0 +0 +0 +DROP TABLE t1; +SET SESSION big_tables=0; +# # MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || # m_lock_type != 2' failed in handler::ha_index_read_map # diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result index c89fd132b35..62eecd568f0 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -7101,6 +7101,20 @@ NULL deallocate prepare stmt; drop table t1,t2,t3,t4; # +# MDEV-7122 +# Assertion `0' failed in subselect_hash_sj_engine::init +# +SET SESSION big_tables=1; +CREATE TABLE t1(a char(255) DEFAULT '', KEY(a(10))) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +INSERT INTO t1 VALUES(0),(0),(0); +SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1); +a +0 +0 +0 +DROP TABLE t1; +SET SESSION big_tables=0; +# # MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || # m_lock_type != 2' failed in handler::ha_index_read_map # diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result index b12bf216327..174c791489c 100644 --- a/mysql-test/r/subselect_no_scache.result +++ b/mysql-test/r/subselect_no_scache.result @@ -7116,6 +7116,20 @@ NULL deallocate prepare stmt; drop table t1,t2,t3,t4; # +# MDEV-7122 +# Assertion `0' failed in subselect_hash_sj_engine::init +# +SET SESSION big_tables=1; +CREATE TABLE t1(a char(255) DEFAULT '', KEY(a(10))) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +INSERT INTO t1 VALUES(0),(0),(0); +SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1); +a +0 +0 +0 +DROP TABLE t1; +SET SESSION big_tables=0; +# # MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || # m_lock_type != 2' failed in handler::ha_index_read_map # diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index 54f145d5c5e..e0d62ac6d14 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -7101,6 +7101,20 @@ NULL deallocate prepare stmt; drop table t1,t2,t3,t4; # +# MDEV-7122 +# Assertion `0' failed in subselect_hash_sj_engine::init +# +SET SESSION big_tables=1; +CREATE TABLE t1(a char(255) DEFAULT '', KEY(a(10))) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +INSERT INTO t1 VALUES(0),(0),(0); +SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1); +a +0 +0 +0 +DROP TABLE t1; +SET SESSION big_tables=0; +# # MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || # m_lock_type != 2' failed in handler::ha_index_read_map # diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index 18a79333e10..be252802c15 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -3003,4 +3003,69 @@ explain select 1 from t1 where _cp932 "1" in (select '1' from t1); ERROR HY000: Illegal mix of collations (cp932_japanese_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation '=' drop table t1; +# +# MDEV-7823: Server crashes in next_depth_first_tab on nested IN clauses with SQ inside +# +set @tmp_mdev7823=@@optimizer_switch; +set optimizer_switch=default; +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (f2 INT, KEY(f2)); +INSERT INTO t2 VALUES (8),(0); +CREATE TABLE t3 (f3 INT); +INSERT INTO t3 VALUES (1),(2); +CREATE TABLE t4 (f4 INT); +INSERT INTO t4 VALUES (0),(5); +explain +SELECT * FROM t1, t2, t3 WHERE f2 IN ( f1 IN ( SELECT f4 FROM t4 ) ); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 1 +1 PRIMARY t2 ref f2 f2 5 const 0 Using where; Using index +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t4 ALL NULL NULL NULL NULL 2 Using where +SELECT * FROM t1, t2, t3 WHERE f2 IN ( f1 IN ( SELECT f4 FROM t4 ) ); +f1 f2 f3 +1 0 1 +1 0 2 +drop table t1,t2,t3,t4; +set optimizer_switch= @tmp_mdev7823; +# +# MDEV-6859: scalar subqueries in a comparison produced unexpected result +# +set @tmp_mdev6859=@@optimizer_switch; +set optimizer_switch=default; +CREATE TABLE t1 ( +project_number varchar(50) NOT NULL, +PRIMARY KEY (project_number) +) ENGINE=MyISAM; +INSERT INTO t1 (project_number) VALUES ('aaa'),('bbb'); +CREATE TABLE t2 ( +id int(10) unsigned NOT NULL AUTO_INCREMENT, +project_number varchar(50) NOT NULL, +history_date date NOT NULL, +country varchar(50) NOT NULL, +PRIMARY KEY (id) +) ENGINE=MyISAM; +INSERT INTO t2 (id, project_number, history_date, country) VALUES +(1, 'aaa', '2014-08-09', 'france'),(2, 'aaa', '2014-09-09', 'singapore'); +CREATE TABLE t3 ( +region varchar(50) NOT NULL, +country varchar(50) NOT NULL +) ENGINE=MyISAM; +INSERT INTO t3 (region, country) VALUES ('apac', 'singapore'),('eame', 'france'); +SELECT SQL_NO_CACHE a.project_number +FROM t1 a +WHERE ( SELECT z.country +FROM t2 z +WHERE z.project_number = a.project_number AND z.history_date <= '2014-09-01' +ORDER BY z.id DESC LIMIT 1 +) IN ( +SELECT r.country +FROM t3 r +WHERE r.region = 'eame' + ); +project_number +aaa +drop table t1, t2, t3; +set optimizer_switch= @tmp_mdev6859; set optimizer_switch=@subselect_sj_tmp; diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result index 13dc990b806..8e95b963971 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -3017,6 +3017,71 @@ explain select 1 from t1 where _cp932 "1" in (select '1' from t1); ERROR HY000: Illegal mix of collations (cp932_japanese_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation '=' drop table t1; +# +# MDEV-7823: Server crashes in next_depth_first_tab on nested IN clauses with SQ inside +# +set @tmp_mdev7823=@@optimizer_switch; +set optimizer_switch=default; +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (f2 INT, KEY(f2)); +INSERT INTO t2 VALUES (8),(0); +CREATE TABLE t3 (f3 INT); +INSERT INTO t3 VALUES (1),(2); +CREATE TABLE t4 (f4 INT); +INSERT INTO t4 VALUES (0),(5); +explain +SELECT * FROM t1, t2, t3 WHERE f2 IN ( f1 IN ( SELECT f4 FROM t4 ) ); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 1 +1 PRIMARY t2 ref f2 f2 5 const 0 Using where; Using index +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join) +2 DEPENDENT SUBQUERY t4 ALL NULL NULL NULL NULL 2 Using where +SELECT * FROM t1, t2, t3 WHERE f2 IN ( f1 IN ( SELECT f4 FROM t4 ) ); +f1 f2 f3 +1 0 1 +1 0 2 +drop table t1,t2,t3,t4; +set optimizer_switch= @tmp_mdev7823; +# +# MDEV-6859: scalar subqueries in a comparison produced unexpected result +# +set @tmp_mdev6859=@@optimizer_switch; +set optimizer_switch=default; +CREATE TABLE t1 ( +project_number varchar(50) NOT NULL, +PRIMARY KEY (project_number) +) ENGINE=MyISAM; +INSERT INTO t1 (project_number) VALUES ('aaa'),('bbb'); +CREATE TABLE t2 ( +id int(10) unsigned NOT NULL AUTO_INCREMENT, +project_number varchar(50) NOT NULL, +history_date date NOT NULL, +country varchar(50) NOT NULL, +PRIMARY KEY (id) +) ENGINE=MyISAM; +INSERT INTO t2 (id, project_number, history_date, country) VALUES +(1, 'aaa', '2014-08-09', 'france'),(2, 'aaa', '2014-09-09', 'singapore'); +CREATE TABLE t3 ( +region varchar(50) NOT NULL, +country varchar(50) NOT NULL +) ENGINE=MyISAM; +INSERT INTO t3 (region, country) VALUES ('apac', 'singapore'),('eame', 'france'); +SELECT SQL_NO_CACHE a.project_number +FROM t1 a +WHERE ( SELECT z.country +FROM t2 z +WHERE z.project_number = a.project_number AND z.history_date <= '2014-09-01' +ORDER BY z.id DESC LIMIT 1 +) IN ( +SELECT r.country +FROM t3 r +WHERE r.region = 'eame' + ); +project_number +aaa +drop table t1, t2, t3; +set optimizer_switch= @tmp_mdev6859; set optimizer_switch=@subselect_sj_tmp; # # BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off diff --git a/mysql-test/r/subselect_sj_mat.result b/mysql-test/r/subselect_sj_mat.result index d5e9fc776f8..2f3777a47fd 100644 --- a/mysql-test/r/subselect_sj_mat.result +++ b/mysql-test/r/subselect_sj_mat.result @@ -787,6 +787,10 @@ select left(a1,7), left(a2,7) from t1_512 where a1 in (select group_concat(b1) from t2_512 group by b2); left(a1,7) left(a2,7) +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() set @@group_concat_max_len = 256; explain extended select left(a1,7), left(a2,7) from t1_512 @@ -801,6 +805,10 @@ select left(a1,7), left(a2,7) from t1_512 where a1 in (select group_concat(b1) from t2_512 group by b2); left(a1,7) left(a2,7) +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() drop table t1_512, t2_512, t3_512; set @blob_len = 1024; set @suffix_len = @blob_len - @prefix_len; @@ -882,6 +890,10 @@ select left(a1,7), left(a2,7) from t1_1024 where a1 in (select group_concat(b1) from t2_1024 group by b2); left(a1,7) left(a2,7) +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() set @@group_concat_max_len = 256; explain extended select left(a1,7), left(a2,7) from t1_1024 @@ -896,6 +908,10 @@ select left(a1,7), left(a2,7) from t1_1024 where a1 in (select group_concat(b1) from t2_1024 group by b2); left(a1,7) left(a2,7) +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() drop table t1_1024, t2_1024, t3_1024; set @blob_len = 1025; set @suffix_len = @blob_len - @prefix_len; @@ -977,6 +993,10 @@ select left(a1,7), left(a2,7) from t1_1025 where a1 in (select group_concat(b1) from t2_1025 group by b2); left(a1,7) left(a2,7) +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() set @@group_concat_max_len = 256; explain extended select left(a1,7), left(a2,7) from t1_1025 @@ -991,6 +1011,10 @@ select left(a1,7), left(a2,7) from t1_1025 where a1 in (select group_concat(b1) from t2_1025 group by b2); left(a1,7) left(a2,7) +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +Warning 1260 Row 3 was cut by GROUP_CONCAT() drop table t1_1025, t2_1025, t3_1025; create table t1bit (a1 bit(3), a2 bit(3)); create table t2bit (b1 bit(3), b2 bit(3)); diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index 279af1e44d2..b02c9a0c6f5 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -202,6 +202,9 @@ t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, PRIMARY KEY (`a`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' INDEX DIRECTORY='MYSQLTEST_VARDIR/run/' +select create_options from information_schema.tables where table_name='t1'; +create_options +DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/' INDEX DIRECTORY='MYSQLTEST_VARDIR/run/' # CREATE TABLE LIKE statement on table with INDEX/DATA DIRECTORY # options should not fail. Per documentation newly created table # should not inherit value of these options from the original table. diff --git a/mysql-test/r/trigger_null-8605.result b/mysql-test/r/trigger_null-8605.result index 79627eac455..e024bc6b7d2 100644 --- a/mysql-test/r/trigger_null-8605.result +++ b/mysql-test/r/trigger_null-8605.result @@ -309,3 +309,49 @@ a b c 1 1 1 2 5 3 drop table t1; +set session sql_mode ='no_auto_value_on_zero'; +create table t1 (id int unsigned auto_increment primary key); +insert t1 values (0); +select * from t1; +id +0 +delete from t1; +create trigger t1_bi before insert on t1 for each row begin end; +insert t1 values (0); +select * from t1; +id +0 +drop table t1; +create table t1 (a int not null, b int); +create trigger trgi before update on t1 for each row do 1; +insert t1 values (1,1),(2,2),(3,3),(1,4); +create table t2 select a as c, b as d from t1; +update t1 set a=(select count(c) from t2 where c+1=a+1 group by a); +select * from t1; +a b +2 1 +1 2 +1 3 +2 4 +drop table t1, t2; +create table t1 (a int not null); +create table t2 (f1 int unsigned not null, f2 int); +insert into t2 values (1, null); +create trigger tr1 before update on t1 for each row do 1; +create trigger tr2 after update on t2 for each row update t1 set a=new.f2; +update t2 set f2=1 where f1=1; +drop table t1, t2; +create table t1 (a int not null, primary key (a)); +insert into t1 (a) values (1); +show columns from t1; +Field Type Null Key Default Extra +a int(11) NO PRI NULL +create trigger t1bu before update on t1 for each row begin end; +show columns from t1; +Field Type Null Key Default Extra +a int(11) NO PRI NULL +insert into t1 (a) values (3); +show columns from t1; +Field Type Null Key Default Extra +a int(11) NO PRI NULL +drop table t1; diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index 1de9b989887..54f2aa91f2c 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -439,6 +439,15 @@ select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1; 1 drop table t1; # +# MDEV-9511 Valgrind warnings 'Invalid read' in Field_newdate::cmp and Field_newdate::val_str +# +CREATE TABLE t1 (f1 DATE, f2 VARCHAR(1)); +INSERT INTO t1 VALUES ('2003-04-27','a'),('1900-01-01','a'); +SELECT GROUP_CONCAT(f2, IF(f1, f2, f1), f1 ORDER BY 2,1,3) FROM t1; +GROUP_CONCAT(f2, IF(f1, f2, f1), f1 ORDER BY 2,1,3) +aa1900-01-01,aa2003-04-27 +DROP TABLE t1; +# # Start of 10.1 tests # # @@ -511,12 +520,6 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = DATE'2001-01-01') DROP TABLE t1; # -# End of 10.1 tests -# -# -# Start of 10.1 tests -# -# # MDEV-8699 Wrong result for SELECT..WHERE HEX(date_column)!='323030312D30312D3031' AND date_column='2001-01-01x' # CREATE TABLE t1 (a DATE); diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index d0cd2c97510..bf3b6a6b7da 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -747,7 +747,7 @@ EXPLAIN EXTENDED SELECT * FROM t1 FORCE INDEX(attime) WHERE AtTime = '2010-02-22 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ref AtTime AtTime 6 const 1 100.00 Warnings: -Note 1003 select `test`.`t1`.`Id` AS `Id`,`test`.`t1`.`AtTime` AS `AtTime` from `test`.`t1` FORCE INDEX (`attime`) where (`test`.`t1`.`AtTime` = '2010-02-22 18:40:07') +Note 1003 select `test`.`t1`.`Id` AS `Id`,`test`.`t1`.`AtTime` AS `AtTime` from `test`.`t1` FORCE INDEX (`attime`) where (`test`.`t1`.`AtTime` = TIMESTAMP'2010-02-22 18:40:07') DROP TABLE t1; SET NAMES latin1; # @@ -963,21 +963,20 @@ a 2001-01-01 00:00:00 Warnings: Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x' -Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x' EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a) != 20 AND a='2001-01-01 00:00:00x'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x' -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = '2001-01-01 00:00:00x') +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)!=30+RAND() AND a='2001-01-01 00:00:00x'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x' -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = '2001-01-01 00:00:00x') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) <> (30 + rand()))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) <> (30 + rand()))) DROP TABLE t1; CREATE TABLE t1 (a DATETIME);; INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01'); @@ -993,20 +992,20 @@ SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=' 2001-01-01 00:00:00'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = ' 2001-01-01 00:00:00') +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=' 2001-01-01 00:00:00'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' 2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (19 + rand()))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (19 + rand()))) EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' garbage '; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: Warning 1292 Incorrect datetime value: ' garbage ' -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' garbage ') and (length(`test`.`t1`.`a`) = (30 + rand()))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'0000-00-00 00:00:00') and (<cache>(length(TIMESTAMP'0000-00-00 00:00:00')) = (30 + rand()))) DROP TABLE t1; CREATE TABLE t1 (a DATETIME);; INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01'); @@ -1076,13 +1075,13 @@ SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIME'00:00:00'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIME'00:00:00') +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIME'00:00:00'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIME'00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (40 + rand()))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (40 + rand()))) DROP TABLE t1; # # MDEV-8795 Equal expression propagation does not work for temporal literals diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index e7267f012ae..e6f02d50f4c 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -638,3 +638,90 @@ DROP TABLE t1; # # End of 10.1 tests # +# +# Start of 10.2 tests +# +# +# MDEV-4102 Limitation on DOUBLE or REAL length is ignored with INSERT .. SELECT +# +CREATE TABLE t1 (d1 DOUBLE(5,2), d2 DOUBLE(10,2)); +INSERT INTO t1 VALUES (10000000.55, 10000000.55); +Warnings: +Warning 1264 Out of range value for column 'd1' at row 1 +INSERT INTO t1 SELECT d2, d2 FROM t1; +Warnings: +Warning 1264 Out of range value for column 'd1' at row 1 +SELECT * FROM t1; +d1 d2 +999.99 10000000.55 +999.99 10000000.55 +DROP TABLE t1; +# +# MDEV-9709 Unexpected modification of value and warning about out of range value upon ALTER +# +CREATE TABLE t1 ( +f FLOAT, +d10_10 DOUBLE PRECISION (10,10), +d53_10 DOUBLE(53,10) +); +INSERT INTO t1 (f,d10_10,d53_10) VALUES ( +-9999999999999999999999999999999999999999999.9999999999, +-9999999999999999999999999999999999999999999.9999999999, +-9999999999999999999999999999999999999999999.9999999999 +); +Warnings: +Warning 1264 Out of range value for column 'f' at row 1 +Warning 1264 Out of range value for column 'd10_10' at row 1 +SELECT * FROM t1; +f -3.40282e38 +d10_10 -0.9999999999 +d53_10 -10000000000000000000000000000000000000000000.0000000000 +INSERT INTO t1 (f,d10_10,d53_10) SELECT d53_10, d53_10, d53_10 FROM t1; +Warnings: +Level Warning +Code 1264 +Message Out of range value for column 'f' at row 1 +Level Warning +Code 1264 +Message Out of range value for column 'd10_10' at row 1 +SELECT * FROM t1; +f -3.40282e38 +d10_10 -0.9999999999 +d53_10 -10000000000000000000000000000000000000000000.0000000000 +f -3.40282e38 +d10_10 -0.9999999999 +d53_10 -10000000000000000000000000000000000000000000.0000000000 +ALTER TABLE t1 ADD COLUMN i INT; +SELECT * FROM t1; +f -3.40282e38 +d10_10 -0.9999999999 +d53_10 -10000000000000000000000000000000000000000000.0000000000 +i NULL +f -3.40282e38 +d10_10 -0.9999999999 +d53_10 -10000000000000000000000000000000000000000000.0000000000 +i NULL +DROP TABLE t1; +CREATE TABLE t1 (d10_10 DOUBLE (10,10)); +CREATE TABLE t2 (d53_10 DOUBLE (53,10)); +INSERT INTO t2 VALUES (-9999999999999999999999999999999999999999999.9999999999); +INSERT INTO t1 (d10_10) SELECT d53_10 FROM t2; +Warnings: +Warning 1264 Out of range value for column 'd10_10' at row 1 +SELECT * FROM t1; +d10_10 +-0.9999999999 +DROP TABLE t1,t2; +CREATE TABLE t1 (d2_2 FLOAT (2,2)); +CREATE TABLE t2 (d4_2 FLOAT (4,2)); +INSERT INTO t2 VALUES (99.99); +INSERT INTO t1 (d2_2) SELECT d4_2 FROM t2; +Warnings: +Warning 1264 Out of range value for column 'd2_2' at row 1 +SELECT * FROM t1; +d2_2 +0.99 +DROP TABLE t1,t2; +# +# End of 10.2 tests +# diff --git a/mysql-test/r/type_num.result b/mysql-test/r/type_num.result index cbac7b6f445..9ee67ac8f33 100644 --- a/mysql-test/r/type_num.result +++ b/mysql-test/r/type_num.result @@ -1220,3 +1220,31 @@ Warning 1292 Truncated incorrect DOUBLE value: '1E+' # # End of 10.0 tests # +# +# Start of 10.1 tests +# +# +# MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool) +# +SELECT NULL+1 AS c0, +COALESCE(NULL)+1 AS c2, +COALESCE(COALESCE(NULL))+1 AS c3, +''+1 AS c4, +COALESCE('')+1 AS c5, +COALESCE(COALESCE(''))+1 AS c6; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def c0 5 17 0 Y 32896 0 63 +def c2 5 17 0 Y 32896 0 63 +def c3 5 17 0 Y 32896 0 63 +def c4 5 23 1 N 32897 31 63 +def c5 5 17 1 N 32897 0 63 +def c6 5 17 1 N 32897 0 63 +c0 c2 c3 c4 c5 c6 +NULL NULL NULL 1 1 1 +Warnings: +Warning 1292 Truncated incorrect DOUBLE value: '' +Warning 1292 Truncated incorrect DOUBLE value: '' +Warning 1292 Truncated incorrect DOUBLE value: '' +# +# Start of 10.1 tests +# diff --git a/mysql-test/r/type_temporal_innodb.result b/mysql-test/r/type_temporal_innodb.result new file mode 100644 index 00000000000..425e499a5d3 --- /dev/null +++ b/mysql-test/r/type_temporal_innodb.result @@ -0,0 +1,156 @@ +# +# MDEV-9604 crash in Item::save_in_field with empty enum value +# +SELECT TIME'00:00:00'=''; +TIME'00:00:00'='' +1 +Warnings: +Warning 1292 Truncated incorrect time value: '' +CREATE TABLE t1 (a ENUM('a'), b TIME, c INT, KEY(b)) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('','00:00:00',0); +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +SELECT * FROM t1 WHERE b=''; +a b c + 00:00:00 0 +Warnings: +Warning 1292 Truncated incorrect time value: '' +SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; +a b c + 00:00:00 0 +Warnings: +Warning 1292 Truncated incorrect time value: '' +SELECT * FROM t1 WHERE a=b; +a b c + 00:00:00 0 +Warnings: +Warning 1292 Truncated incorrect time value: '' +SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; +1 +1 +Warnings: +Warning 1292 Truncated incorrect time value: '' +ALTER TABLE t1 ENGINE=MyISAM; +SELECT * FROM t1 WHERE b=''; +a b c + 00:00:00 0 +Warnings: +Warning 1292 Truncated incorrect time value: '' +SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; +a b c + 00:00:00 0 +Warnings: +Warning 1292 Truncated incorrect time value: '' +SELECT * FROM t1 WHERE a=b; +a b c + 00:00:00 0 +Warnings: +Warning 1292 Truncated incorrect time value: '' +SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; +1 +1 +Warnings: +Warning 1292 Truncated incorrect time value: '' +DROP TABLE t1; +SELECT DATE'0000-00-00'=''; +DATE'0000-00-00'='' +1 +Warnings: +Warning 1292 Incorrect datetime value: '' +CREATE TABLE t1 (a ENUM('a'), b DATE, c INT, KEY(b)) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('','0000-00-00',0); +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +SELECT * FROM t1 WHERE b=''; +a b c + 0000-00-00 0 +Warnings: +Warning 1292 Incorrect datetime value: '' +SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; +a b c + 0000-00-00 0 +Warnings: +Warning 1292 Incorrect datetime value: '' +SELECT * FROM t1 WHERE a=b; +a b c + 0000-00-00 0 +Warnings: +Warning 1292 Incorrect datetime value: '' +SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; +1 +1 +Warnings: +Warning 1292 Incorrect datetime value: '' +ALTER TABLE t1 ENGINE=MyISAM; +SELECT * FROM t1 WHERE b=''; +a b c + 0000-00-00 0 +Warnings: +Warning 1292 Incorrect datetime value: '' +SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; +a b c + 0000-00-00 0 +Warnings: +Warning 1292 Incorrect datetime value: '' +SELECT * FROM t1 WHERE a=b; +a b c + 0000-00-00 0 +Warnings: +Warning 1292 Incorrect datetime value: '' +SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; +1 +1 +Warnings: +Warning 1292 Incorrect datetime value: '' +DROP TABLE t1; +SELECT TIMESTAMP'0000-00-00 00:00:00'=''; +TIMESTAMP'0000-00-00 00:00:00'='' +1 +Warnings: +Warning 1292 Incorrect datetime value: '' +CREATE TABLE t1 (a ENUM('a'), b DATETIME, c INT, KEY(b)) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('','0000-00-00 00:00:00',0); +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +SELECT * FROM t1 WHERE b=''; +a b c + 0000-00-00 00:00:00 0 +Warnings: +Warning 1292 Incorrect datetime value: '' +SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; +a b c + 0000-00-00 00:00:00 0 +Warnings: +Warning 1292 Incorrect datetime value: '' +SELECT * FROM t1 WHERE a=b; +a b c + 0000-00-00 00:00:00 0 +Warnings: +Warning 1292 Incorrect datetime value: '' +SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; +1 +1 +Warnings: +Warning 1292 Incorrect datetime value: '' +ALTER TABLE t1 ENGINE=MyISAM; +SELECT * FROM t1 WHERE b=''; +a b c + 0000-00-00 00:00:00 0 +Warnings: +Warning 1292 Incorrect datetime value: '' +SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; +a b c + 0000-00-00 00:00:00 0 +Warnings: +Warning 1292 Incorrect datetime value: '' +SELECT * FROM t1 WHERE a=b; +a b c + 0000-00-00 00:00:00 0 +Warnings: +Warning 1292 Incorrect datetime value: '' +SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; +1 +1 +Warnings: +Warning 1292 Incorrect datetime value: '' +DROP TABLE t1; diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result index e4347509d5e..e4525f34ab4 100644 --- a/mysql-test/r/type_time.result +++ b/mysql-test/r/type_time.result @@ -989,7 +989,7 @@ SELECT * FROM t1 WHERE COALESCE(a)=TIME('00:00:00') AND COALESCE(a)=DATE('2015-0 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (coalesce(`test`.`t1`.`a`) = <cache>(00:00:00)) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (coalesce(`test`.`t1`.`a`) = 00:00:00) # TIME cast + DATE literal SELECT * FROM t1 WHERE COALESCE(a)=TIME('00:00:00') AND COALESCE(a)=DATE'2015-09-11'; a @@ -999,7 +999,7 @@ SELECT * FROM t1 WHERE COALESCE(a)=TIME('00:00:00') AND COALESCE(a)=DATE'2015-09 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (coalesce(`test`.`t1`.`a`) = <cache>(00:00:00)) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (coalesce(`test`.`t1`.`a`) = 00:00:00) # TIME literal + DATE cast SELECT * FROM t1 WHERE COALESCE(a)=TIME'00:00:00' AND COALESCE(a)=DATE('2015-09-11'); a @@ -1029,7 +1029,7 @@ SELECT * FROM t1 WHERE COALESCE(a)='00:00:00' AND COALESCE(a)=DATE('2015-09-11') id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((coalesce(`test`.`t1`.`a`) = '00:00:00') and (coalesce(`test`.`t1`.`a`) = <cache>(2015-09-11 00:00:00))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((coalesce(`test`.`t1`.`a`) = '00:00:00') and (coalesce(`test`.`t1`.`a`) = 2015-09-11 00:00:00)) # TIME-alike string literal + DATE literal SELECT * FROM t1 WHERE COALESCE(a)='00:00:00' AND COALESCE(a)=DATE'2015-09-11'; a @@ -1049,7 +1049,7 @@ SELECT * FROM t1 WHERE COALESCE(a)=0 AND COALESCE(a)=DATE('2015-09-11'); id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((coalesce(`test`.`t1`.`a`) = 0) and (coalesce(`test`.`t1`.`a`) = <cache>(2015-09-11 00:00:00))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((coalesce(`test`.`t1`.`a`) = 0) and (coalesce(`test`.`t1`.`a`) = 2015-09-11 00:00:00)) # TIME-alike integer literal + DATE literal SELECT * FROM t1 WHERE COALESCE(a)=0 AND COALESCE(a)=DATE'2015-09-11'; a @@ -1069,7 +1069,7 @@ SELECT * FROM t1 WHERE COALESCE(a)=DATE('2015-09-11') AND COALESCE(a)=TIME('00:0 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (coalesce(`test`.`t1`.`a`) = <cache>(2015-09-11 00:00:00)) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (coalesce(`test`.`t1`.`a`) = 2015-09-11 00:00:00) # DATE cast + TIME literal SELECT * FROM t1 WHERE COALESCE(a)=DATE('2015-09-11') AND COALESCE(a)=TIME'00:00:00'; a @@ -1079,7 +1079,7 @@ SELECT * FROM t1 WHERE COALESCE(a)=DATE('2015-09-11') AND COALESCE(a)=TIME'00:00 id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (coalesce(`test`.`t1`.`a`) = <cache>(2015-09-11 00:00:00)) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (coalesce(`test`.`t1`.`a`) = 2015-09-11 00:00:00) # DATE cast + TIME-alike string literal SELECT * FROM t1 WHERE COALESCE(a)=DATE('2015-09-11') AND COALESCE(a)='00:00:00'; a @@ -1089,7 +1089,7 @@ SELECT * FROM t1 WHERE COALESCE(a)=DATE('2015-09-11') AND COALESCE(a)='00:00:00' id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((coalesce(`test`.`t1`.`a`) = <cache>(2015-09-11 00:00:00)) and (coalesce(`test`.`t1`.`a`) = '00:00:00')) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((coalesce(`test`.`t1`.`a`) = 2015-09-11 00:00:00) and (coalesce(`test`.`t1`.`a`) = '00:00:00')) # DATE cast + TIME-alike integer literal SELECT * FROM t1 WHERE COALESCE(a)=DATE('2015-09-11') AND COALESCE(a)=0; a @@ -1099,7 +1099,7 @@ SELECT * FROM t1 WHERE COALESCE(a)=DATE('2015-09-11') AND COALESCE(a)=0; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((coalesce(`test`.`t1`.`a`) = <cache>(2015-09-11 00:00:00)) and (coalesce(`test`.`t1`.`a`) = 0)) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((coalesce(`test`.`t1`.`a`) = 2015-09-11 00:00:00) and (coalesce(`test`.`t1`.`a`) = 0)) # DATE literal + TIME cast SELECT * FROM t1 WHERE COALESCE(a)=DATE'2015-09-11' AND COALESCE(a)=TIME('00:00:00'); a diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result index fcdef627ded..a579f6930a0 100644 --- a/mysql-test/r/type_timestamp.result +++ b/mysql-test/r/type_timestamp.result @@ -818,21 +818,20 @@ a 2001-01-01 00:00:00 Warnings: Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x' -Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x' EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a) != 20 AND a='2001-01-01 00:00:00x'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x' -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = '2001-01-01 00:00:00x') +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)!=30+RAND() AND a='2001-01-01 00:00:00x'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x' -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = '2001-01-01 00:00:00x') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) <> (30 + rand()))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) <> (30 + rand()))) DROP TABLE t1; CREATE TABLE t1 (a TIMESTAMP);; INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01'); @@ -848,20 +847,20 @@ SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=' 2001-01-01 00:00:00'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = ' 2001-01-01 00:00:00') +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=' 2001-01-01 00:00:00'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' 2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (19 + rand()))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (19 + rand()))) EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' garbage '; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: Warning 1292 Incorrect datetime value: ' garbage ' -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' garbage ') and (length(`test`.`t1`.`a`) = (30 + rand()))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'0000-00-00 00:00:00') and (<cache>(length(TIMESTAMP'0000-00-00 00:00:00')) = (30 + rand()))) DROP TABLE t1; CREATE TABLE t1 (a TIMESTAMP);; INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01'); @@ -931,13 +930,13 @@ SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIME'00:00:00'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIME'00:00:00') +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIME'00:00:00'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIME'00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (40 + rand()))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (40 + rand()))) DROP TABLE t1; # # End of 10.1 tests diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 01a06fad00d..4a295762530 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -826,6 +826,9 @@ drop table t2; create table t1 (a int); insert into t1 values (1), (2); create view v1 as select 5 from t1 order by 1; +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 5 AS `5` from `t1` order by 1 latin1 latin1_swedish_ci select * from v1; 5 5 @@ -2425,28 +2428,28 @@ CREATE VIEW v1 AS SELECT id FROM t1; OPTIMIZE TABLE v1; Table Op Msg_type Msg_text test.v1 optimize Error 'test.v1' is not BASE TABLE -test.v1 optimize error Corrupt +test.v1 optimize status Operation failed ANALYZE TABLE v1; Table Op Msg_type Msg_text test.v1 analyze Error 'test.v1' is not BASE TABLE -test.v1 analyze error Corrupt +test.v1 analyze status Operation failed REPAIR TABLE v1; Table Op Msg_type Msg_text test.v1 repair Error 'test.v1' is not BASE TABLE -test.v1 repair error Corrupt +test.v1 repair status Operation failed DROP TABLE t1; OPTIMIZE TABLE v1; Table Op Msg_type Msg_text test.v1 optimize Error 'test.v1' is not BASE TABLE -test.v1 optimize error Corrupt +test.v1 optimize status Operation failed ANALYZE TABLE v1; Table Op Msg_type Msg_text test.v1 analyze Error 'test.v1' is not BASE TABLE -test.v1 analyze error Corrupt +test.v1 analyze status Operation failed REPAIR TABLE v1; Table Op Msg_type Msg_text test.v1 repair Error 'test.v1' is not BASE TABLE -test.v1 repair error Corrupt +test.v1 repair status Operation failed DROP VIEW v1; create definer = current_user() sql security invoker view v1 as select 1; show create view v1; @@ -5540,6 +5543,14 @@ execute stmt; deallocate prepare stmt; drop view v1,v2; drop table `t1`; +create table t1 (a int, b int); +create view v1 as select a+b from t1; +alter table v1 check partition p1; +Table Op Msg_type Msg_text +test.v1 check Error 'test.v1' is not BASE TABLE +test.v1 check status Operation failed +drop view v1; +drop table t1; # ----------------------------------------------------------------- # -- End of 5.5 tests. # ----------------------------------------------------------------- @@ -5876,6 +5887,22 @@ a DROP VIEW v1; DROP TABLE t1; # +# MDEV-9701: CREATE VIEW with GROUP BY or ORDER BY and constant +# produces invalid definition +# +CREATE TABLE t1 ( i INT ); +INSERT INTO t1 VALUES (1),(2); +CREATE VIEW v1 AS +SELECT 3 AS three, COUNT(*) FROM t1 GROUP BY three; +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 3 AS `three`,count(0) AS `COUNT(*)` from `t1` group by '' latin1 latin1_swedish_ci +SELECT * FROM v1; +three COUNT(*) +3 2 +drop view v1; +drop table t1; +# # End of 10.1 tests # # diff --git a/mysql-test/std_data/ca-cert-verify.pem b/mysql-test/std_data/ca-cert-verify.pem new file mode 100644 index 00000000000..21d6264a0ad --- /dev/null +++ b/mysql-test/std_data/ca-cert-verify.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDWzCCAkOgAwIBAgIJAO/QdKLEDQdXMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNV +BAYTAklOMREwDwYDVQQIDAhLYXJuYXRrYTESMBAGA1UEBwwJQmFuZ2Fsb3JlMQ4w +DAYDVQQKDAVNeVNRTDAeFw0xNjAxMDUxMDA1MDhaFw0yNTExMTMxMDA1MDhaMEQx +CzAJBgNVBAYTAklOMREwDwYDVQQIDAhLYXJuYXRrYTESMBAGA1UEBwwJQmFuZ2Fs +b3JlMQ4wDAYDVQQKDAVNeVNRTDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAKdOCuS2CzfBTJ2x8SAzY0J7cYJfNJvMDF1cvANnhkIhtnkWt/HZ5DJ9NxeX +q5h7FJLAi4gddqdk/tvQJw0V6gZepJr/mKVnMPivF5+oHPc9ZJQMX6B3FBNwWylm +ACd5GKx8I/H/MXyuhQTcoV//Ab+2pI8RHeYbBsm3lHH+tX7bRU6mUFjneqMpiCkb +JHt6BWZiWR10O6pMuGQ9+dDdsLhEV1fj3CctEPwW6rs4IZzD8xl5n+8cy7qu6eYH +Wt/snwsTzkrufeMRqTtqelxON9eoQwYOR1oH3vNEVlcbuoJAvaWOqBROUBdf12SP +TYSdP9nlRh7lTKQOywN4kYt6LqUCAwEAAaNQME4wHQYDVR0OBBYEFJ4c9tKaUU0P +EjBq5G207jjXI7RAMB8GA1UdIwQYMBaAFJ4c9tKaUU0PEjBq5G207jjXI7RAMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABRnUyj21oFi0SGJg/K5+8Lc +4n6OwVU/NgLOysIB0baIP/Rqeaze59xG/v9FPQgBlWcJK3RabOywx5bxAxdcus+1 +yp5j4h37Qq1/qkgqmevvdSAPa0OBQbLb+58/naV+ywUpCYZ6flLdCMH3fXuDSlSq +qrCznextjojtWbnzrBmCmJmXWGd2gSaJDvb90ZZp/Elt3vN1sgjW0M/JEkb4MJ1r +6nfD/FHr2lUwBHm2yk7Blovx7x4d/Ip3pglk63cNO/Rn0SBTdoVDS2LB9du3Phq2 +TZiL3NrRMGUNwmdaavyrJxaPq5D+Sfa4LYP3MMYD4KhLogNzIl299n5joyizlJw= +-----END CERTIFICATE----- diff --git a/mysql-test/std_data/empty_file b/mysql-test/std_data/empty_file new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/mysql-test/std_data/empty_file diff --git a/mysql-test/std_data/server-cert-verify-fail.pem b/mysql-test/std_data/server-cert-verify-fail.pem new file mode 100644 index 00000000000..4203425a344 --- /dev/null +++ b/mysql-test/std_data/server-cert-verify-fail.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDJzCCAg8CAQEwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCSU4xETAPBgNV +BAgMCEthcm5hdGthMRIwEAYDVQQHDAlCYW5nYWxvcmUxDjAMBgNVBAoMBU15U1FM +MB4XDTE2MDEwNTEwMDgyN1oXDTI1MTExMzEwMDgyN1owbzELMAkGA1UEBhMCSU4x +EjAQBgNVBAgMCTpLYXJuYXRrYTETMBEGA1UEBwwKOkJhbmdhbG9yZTEPMA0GA1UE +CgwGOk15U1FMMRcwFQYDVQQLDA4vQ049bG9jYWxob3N0LzENMAsGA1UEAwwEZmFp +bDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3wnWuJodzZYq9TAJRm +HU7995FA3TEWdUinYTgGP79aTVQ4M9aeINlB6whWXOI8seh9Ja7C6kMzqOgYbgCl +WlDPAVJWktFYeWXOLxbpzh1KWkS6jBkWT02t7H7JcYbil7xjlJUxLz4UOOUDUDIP +6yqdA9VE3osESttjzj57Zm2xPqzbIHVJfORn7EexH4pryS7439p6i4XtfL31NJ8V +07M3j3a8GqbcEqXYvcUCrLnywDQ1igP817b6ta52nbgYWiqdn0mJs535UJ/p/rSl +D4Ae/6G3BSEY7whir6xY6vsd4KJ6w+wRCHnY0ky6OdDJVJLH1iqh7si7P3RBGkxw +Y7MCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAggbw1jj2b7H5KDdeGJGIoOGkQAcs +GNSJussCfdk7qnzYXKmjyNppC86jjaOrXona5f+SNCuujdu86Tv8V69EH57k4lUc +DW7J4AD3vUb/tBzB0tsI/76Z4gm1XoCsnCGGpWd8GQAg/QNn/ZfJB2Vb/9ObN6rH +0HV7ouB6OGZSsb71+grKiN6mDyB1lZynCGvqBxOCKFISfcRbCNFHo/pONlHaNGPE +vjDH1bPZbEHj8owYgkdcQe0a8EbJYeQfm6fH8V8bmUcG7N60DrCnq4l1qwwVkh1S +7RpIDgrWkU+esIIdYZIIbtDxQP1Sm7kUh++7b+bcHnyw3KtDVSCw7MIedA== +-----END CERTIFICATE----- diff --git a/mysql-test/std_data/server-cert-verify-pass.pem b/mysql-test/std_data/server-cert-verify-pass.pem new file mode 100644 index 00000000000..f8780f1f94e --- /dev/null +++ b/mysql-test/std_data/server-cert-verify-pass.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDEzCCAfsCAQEwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCSU4xETAPBgNV +BAgMCEthcm5hdGthMRIwEAYDVQQHDAlCYW5nYWxvcmUxDjAMBgNVBAoMBU15U1FM +MB4XDTE2MDEwNTEwMDU1OVoXDTI1MTExMzEwMDU1OVowWzELMAkGA1UEBhMCSU4x +EjAQBgNVBAgMCTpLYXJuYXRrYTETMBEGA1UEBwwKOkJhbmdhbG9yZTEPMA0GA1UE +CgwGOk15U1FMMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQDAmkbUwDe+nrqL8A8uwlIZk74HHCDjUAWrskKF9leEIQsB +5exFZ8JEo1u6mdR4laQWsxizGdTPqIEidkDyyEMh4+joHgyQEPD/G3rFVW8yEFHb +42O04O96BEPFXNPDRuX3MxI+lGbYDjxTS/WhVub4/3SqLjC28FJmEUXIHA0/A+c5 +hlYXK0u+aPAqXxHIjBgB4BxxHXZKqecmvR3LhXoVmhJmndsVfKajB27nDKc8/OTI +H2SXb6h3nRPDXRfwB/C5i+004tEsVeIgkYshcCgLSyDdeVieUP2pm3EAmDSjmtLF +6CgY/EBSfH+JCKFUk75bA4k8CCGzBfIeOcsKHwgFAgMBAAEwDQYJKoZIhvcNAQEL +BQADggEBAInDuHtDkeT6dkWmRJCP56c4xiQqib2QuYUuMSrAhf07xlLHc6iHnD2X +hCWCrja6uwF90DnPjeouKMAUe5txq/uKA8/Y/NfXN6nPiAeHLI0qnTv7Mr9TQ8zU +DNDwRz6onlI2cS4GhrwAnlpiaxu7AjMUWHtfBFGFrgn3PawjDQpsBZNcxw1QsLc0 +E0hFrWLOd0vDETEhoRge88N7a0jqK0Rd9cvRWnvjI+IsjQMLZzKufivIHPzI9K+9 +Wtp8iRHcaBr5DpsBjgsO7dqVRbsNyaWsdHdLt+CQSGXpv7P6fq3K6nJFTBeIgSfS +gflrHVKYZRkKDDDpX4yHNdnIqrvy4RU= +-----END CERTIFICATE----- diff --git a/mysql-test/std_data/server-key-verify-fail.pem b/mysql-test/std_data/server-key-verify-fail.pem new file mode 100644 index 00000000000..af1ae1e3ae1 --- /dev/null +++ b/mysql-test/std_data/server-key-verify-fail.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAvfCda4mh3Nlir1MAlGYdTv33kUDdMRZ1SKdhOAY/v1pNVDgz +1p4g2UHrCFZc4jyx6H0lrsLqQzOo6BhuAKVaUM8BUlaS0Vh5Zc4vFunOHUpaRLqM +GRZPTa3sfslxhuKXvGOUlTEvPhQ45QNQMg/rKp0D1UTeiwRK22POPntmbbE+rNsg +dUl85GfsR7EfimvJLvjf2nqLhe18vfU0nxXTszePdrwaptwSpdi9xQKsufLANDWK +A/zXtvq1rnaduBhaKp2fSYmznflQn+n+tKUPgB7/obcFIRjvCGKvrFjq+x3gonrD +7BEIedjSTLo50MlUksfWKqHuyLs/dEEaTHBjswIDAQABAoIBAQCSUyNzDPydXvsf +hhoUOParPAvU4tuETYDdD9Vdi7Lgf3jDQOjulbNIq/ec3KuBvrBwIrk9APvn+YxO +AUP9S2Vgi5jBDeDdVgNv4n90b3pSJk2UVQJI8V72wN5Ibnf/KeErSKvWo6V5daq/ +AuZtKsZIdd3WFtA62HuyuBjTGc23Alj1C0EKnN0Rx1uBwDvx/OVQ266Us/x8jJqW +ZxIOfcvfNzBQEa5hAzbQCReVaC+rBLRAcMM2yGP7aDa+8cRkwuVlSqpX8CXBdLoU +PqmU49etcW72Rb1AFt9WgEu1Oh9UYbHFSB+FEbO8IGcGBsuYHf9zkxQyjpy/iKyT +H5dTu7YBAoGBAOWqEGepZVrfB+P6X18n3vbJhgYmF0sa0mCmwkFYgk36yNqsZ8at +lQjm5mbn4wjEKHIcQ/T1taq73W471M+PxMnn0WTwoG5jsyarZGgy6/95YXiyZtQe +qgA4P3aKkCteRP22DjG7uxmm9Hoqx8Z31vfRTLAHN1IEHPHHkg/J3gPTAoGBANO4 +aqKeY4vcDvVkvxVbADrw++tZGwA+RuxfO4HKKru59VdA2PsAxhXwb3Dfejwj7hYW +yE9edHjGpMr1+dpf8YJYs7qjajHe1HxBOYqQGHycIdw+Gv56R4HpaS9eW3x8l/Pi +b4xnAodv2qIriACOe7br+rll4wKX46Wt64zdvpShAoGAT0r3HQM0Vjp4u/J+qRjX +9za+yjKuiiS5i9snaG5JlujGHhG2Rrc5pHgsBk17alRnbnZp1BJdZZQ1MFEB+aO2 +mssp1YLqsRJFEU3NfdhO+MaMq6JUtFnd8fN5ndDbU83ZXgtUPUGGqKWm9OL+VHyd +wLQHmSL0q6F16Ngxirf0qjcCgYEAtSmiJVA+gdhk/FmeoBlkEwtNpM50Kjsf2PaM +Jrzk4Al5A5Y7lFvPI8q+sOio4XklKsWH1VJPe2EOdZUQnGlocE6SS+u03MN9Mm1l +XUl7inTXDGwgEQx0z5b4KE4nHlhGdauWI5+pLFbrz8RL9Z32AkneGnIyU2/AnW46 +lijQAMECgYEAmgp/88ndIw49RCtMhYhtXQ87AsEAP6kzXQyKppDkn0os+xI5igIL +i/UDxB33hx3yjrUZwoGDV9MwlMhZNX5Tf5bwjPmmh1NR6KdEpPt5AkklX4s6uil2 +Bxl1P5l1jl/PbEYtv5LDZKIPANWRzViMSIWqjUWlbdqE7/vjx+Oo+cc= +-----END RSA PRIVATE KEY----- diff --git a/mysql-test/std_data/server-key-verify-pass.pem b/mysql-test/std_data/server-key-verify-pass.pem new file mode 100644 index 00000000000..7ecc44f6d48 --- /dev/null +++ b/mysql-test/std_data/server-key-verify-pass.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAwJpG1MA3vp66i/APLsJSGZO+Bxwg41AFq7JChfZXhCELAeXs +RWfCRKNbupnUeJWkFrMYsxnUz6iBInZA8shDIePo6B4MkBDw/xt6xVVvMhBR2+Nj +tODvegRDxVzTw0bl9zMSPpRm2A48U0v1oVbm+P90qi4wtvBSZhFFyBwNPwPnOYZW +FytLvmjwKl8RyIwYAeAccR12SqnnJr0dy4V6FZoSZp3bFXymowdu5wynPPzkyB9k +l2+od50Tw10X8AfwuYvtNOLRLFXiIJGLIXAoC0sg3XlYnlD9qZtxAJg0o5rSxego +GPxAUnx/iQihVJO+WwOJPAghswXyHjnLCh8IBQIDAQABAoIBAHPQUSc9LkgBSks7 +XuXPE28t1+aOk3gcdkx4NGg5aQaal/PcPea+LaL4WAAs4AZidPjxWLjZn43+1SfT +09opcbS/Rx3Mc+FtTn0YGQrwBJ0mExMV+K6bU2Ubi2TyHKQfzciHfUEEG5Nve/ba +hikuCFVRxuVOQRzABcw6NqvNsmlg892lfw6/+RDwMBcz7ocwzmiOUoIxgjyFo9G4 +aJvRmHLij5892H6qveik+A/Xr+8leGQHiQET2wW/F9MFP5ypIT7aeE6remeZH7fG +f4/Zfei/TE4xK2ElNR/91byzeKIVY4vjtTndAiBuqpfYuICb40MC02LNW5Oe6VN2 +3mQ6EgECgYEA7O4ndBnbs/00gyTGyNg6I+3wRTibhNH4R8RZFJiLfKRKOlUiLhUo ++bQeO4bCQ6YY++TYDvMEXTlA3jow9R9Mj2AWc6bNmQmJd/065QyFHftywT66I+V4 +rz1ohSJyHXcv4DxqNk3o3Vb4N8GFjZKcodSgTv2Lk+9ipDYFcQiZop0CgYEA0BrF +SIyLTnjoVht/7RbIGEqhMQUiz5mx7qQ1TPB+YTG77G2xXJNg5d6S7WT4LN+cqbxN +YdndIbW4NdV7bH7FlG9q7jfkuZ+AY2BPU047tcDeyO0HYYEhVY+EyZqHci/26mvt +JrawdqS5HQS1y/rKfytm7YBGTvqoNZHvOHc6aokCgYEAxcjlbJkte+pyzMuFmiJP +HrFBczeXM+BoJ9j0GCpjvvAS+vEYsGl/pDvFRSHwx7I/hv/5kTkzOnNSAHGJbwbq +zYGEHJVxakC43k6pvI2gDnBa0pD/qHmmLnvP5dvkcU6Oy90DOUP+kc9JNJo7V/y8 +/qdWD7q+qwcaTETAdCSexE0CgYA/DN1Y7bwHOnqqHArWOmDFe1b7EyNI4rgWJYpA +lVy09eyJ5XInKj/hZV3+rujCL723b2XCj89/tx7osJWEeaRDJL6xDh4uXzT25uch +xkIw/w6Asc/aqtT+p00EB92hqwaUX76qTA+K4r1zHUo3UvSnMu8sZgDnTOpJ0L05 +zmXUgQKBgDT+IFrAzOty4B0mJncTCC/TulpW704bEZwNJfQSdtiBQr/vqoXygBQc +bHfpncpSfhzHB5lhRUv02TqXgl53D70nM7JD5nx98WYTTBxsbvxPlt4gBRZkfgq5 +tHKclAArc1SbfW5Z8oYyl7h33LQJK116QSyiIIGieH5VXNPwnqUs +-----END RSA PRIVATE KEY----- diff --git a/mysql-test/suite.pm b/mysql-test/suite.pm index a7c0b2d4ff1..ea07af7376c 100644 --- a/mysql-test/suite.pm +++ b/mysql-test/suite.pm @@ -58,7 +58,7 @@ sub skip_combinations { return 0 unless socket my $sock, PF_INET6, SOCK_STREAM, getprotobyname('tcp'); # eval{}, if there's no Socket::sockaddr_in6 at all, old Perl installation eval { connect $sock, sockaddr_in6(7, Socket::IN6ADDR_LOOPBACK) }; - return $! != 101; + return $@ eq ""; } $skip{'include/check_ipv6.inc'} = 'No IPv6' unless ipv6_ok(); diff --git a/mysql-test/suite/archive/partition_archive.result b/mysql-test/suite/archive/partition_archive.result index eb1fca46522..c4cccc03a04 100644 --- a/mysql-test/suite/archive/partition_archive.result +++ b/mysql-test/suite/archive/partition_archive.result @@ -153,3 +153,9 @@ t1 CREATE TABLE `t1` ( PARTITIONS 5 */ #Cleanup. DROP TABLE t1; +create database mysqltest1; +create table mysqltest1.t1 (a int not null, b int not null) engine=archive +partition by list(a) subpartition by hash(b) +(partition p1 values in (1), +partition p2 values in (2)); +drop database mysqltest1; diff --git a/mysql-test/suite/archive/partition_archive.test b/mysql-test/suite/archive/partition_archive.test index 899f266c09c..aa2adb7e44d 100644 --- a/mysql-test/suite/archive/partition_archive.test +++ b/mysql-test/suite/archive/partition_archive.test @@ -147,3 +147,10 @@ SHOW CREATE TABLE t1; --echo #Cleanup. DROP TABLE t1; + +create database mysqltest1; +create table mysqltest1.t1 (a int not null, b int not null) engine=archive + partition by list(a) subpartition by hash(b) + (partition p1 values in (1), + partition p2 values in (2)); +drop database mysqltest1; diff --git a/mysql-test/suite/binlog/r/binlog_reset_master.result b/mysql-test/suite/binlog/r/binlog_reset_master.result deleted file mode 100644 index b3d605560ff..00000000000 --- a/mysql-test/suite/binlog/r/binlog_reset_master.result +++ /dev/null @@ -1 +0,0 @@ -RESET MASTER; diff --git a/mysql-test/suite/binlog/t/binlog_reset_master.test b/mysql-test/suite/binlog/t/binlog_reset_master.test deleted file mode 100644 index 33b549ad357..00000000000 --- a/mysql-test/suite/binlog/t/binlog_reset_master.test +++ /dev/null @@ -1,26 +0,0 @@ -# ==== Purpose ==== -# -# Test bugs in RESET MASTER. - ---source include/have_debug.inc ---source include/have_log_bin.inc - -####################################################################### -# BUG#12574820: binlog.binlog_tmp_table timing out in daily and weekly trunk run -# Problem: MYSQL_BIN_LOG::reset_logs acquired LOCK_thread_count and -# LOCK_log in the wrong order. This could cause a deadlock when -# RESET MASTER was run concurrently with a disconnecting thread. -####################################################################### - -# We use sleep, not debug_sync, because the sync point needs to be in -# the thread shut down code after the debug sync facility has been -# shut down. ---let $write_var= SET debug_dbug="+d,sleep_after_lock_thread_count_before_delete_thd"; CREATE TEMPORARY TABLE test.t1 (a INT); ---let $write_to_file= GENERATE ---disable_query_log ---source include/write_var_to_file.inc ---enable_query_log - ---exec $MYSQL < $write_to_file -RESET MASTER; ---remove_file $write_to_file diff --git a/mysql-test/suite/encryption/r/filekeys_emptyfile.result b/mysql-test/suite/encryption/r/filekeys_emptyfile.result new file mode 100644 index 00000000000..f94f11d9f08 --- /dev/null +++ b/mysql-test/suite/encryption/r/filekeys_emptyfile.result @@ -0,0 +1,10 @@ +call mtr.add_suppression("System key id 1 is missing at"); +call mtr.add_suppression("Plugin 'file_key_management' init function returned error"); +call mtr.add_suppression("Plugin 'file_key_management' registration.*failed"); +FOUND /System key id 1 is missing at/ in mysqld.1.err +create table t1(c1 bigint not null, b char(200)) engine=innodb encrypted=yes encryption_key_id=1; +ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") +select plugin_status from information_schema.plugins +where plugin_name = 'file_key_management'; +plugin_status +# Test checks if opening an empty filekeys does not crash the server. diff --git a/mysql-test/suite/encryption/r/innodb-encryption-disable.result b/mysql-test/suite/encryption/r/innodb-encryption-disable.result new file mode 100644 index 00000000000..63ff1dcda71 --- /dev/null +++ b/mysql-test/suite/encryption/r/innodb-encryption-disable.result @@ -0,0 +1,32 @@ +SET GLOBAL innodb_file_format = `Barracuda`; +SET GLOBAL innodb_file_per_table = ON; +call mtr.add_suppression("InnoDB: Block in space_id .* in file test/.* encrypted"); +call mtr.add_suppression("InnoDB: However key management plugin or used key_id 1 is not found or used encryption algorithm or method does not match."); +call mtr.add_suppression("InnoDB: Marking tablespace as missing. You may drop this table or install correct key management plugin and key file."); +call mtr.add_suppression(".*InnoDB: Cannot open table test/.* from the internal data dictionary of InnoDB though the .frm file for the table exists. See .* for how you can resolve the problem."); +call mtr.add_suppression("InnoDB: .ibd file is missing for table test/.*"); +call mtr.add_suppression("Couldn't load plugins from 'file_key_management*"); +call mtr.add_suppression("InnoDB: Tablespace id.* is encrypted but encryption service or used key_id .* is not available. Can't continue opening tablespace."); +create table t5 ( +`intcol1` int(32) DEFAULT NULL, +`intcol2` int(32) DEFAULT NULL, +`charcol1` varchar(128) DEFAULT NULL, +`charcol2` varchar(128) DEFAULT NULL, +`charcol3` varchar(128) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +insert into t5 values (1,2,'maria','db','encryption'); +CREATE TABLE `t1` ( +`intcol1` int(32) DEFAULT NULL, +`intcol2` int(32) DEFAULT NULL, +`charcol1` varchar(128) DEFAULT NULL, +`charcol2` varchar(128) DEFAULT NULL, +`charcol3` varchar(128) DEFAULT NULL +) ENGINE=InnoDB; +insert into t1 values (1,2,'maria','db','encryption'); +alter table t1 encrypted='yes' `encryption_key_id`=1; +select * from t1; +ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB +select * from t5; +ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB +drop table t1; +drop table t5; diff --git a/mysql-test/suite/encryption/r/innodb-log-encrypt-crash.result b/mysql-test/suite/encryption/r/innodb-log-encrypt-crash.result new file mode 100644 index 00000000000..5310fb6ace2 --- /dev/null +++ b/mysql-test/suite/encryption/r/innodb-log-encrypt-crash.result @@ -0,0 +1,19 @@ +call mtr.add_suppression("InnoDB: New log files created, LSN=.*"); +call mtr.add_suppression("InnoDB: Creating foreign key constraint system tables."); +call mtr.add_suppression("InnoDB: Error: Table .*"); +CREATE TABLE t1 ( +pk bigint auto_increment, +col_int int, +col_int_key int, +col_char char(12), +col_char_key char(12), +primary key (pk), +key (`col_int_key` ), +key (`col_char_key` ) +) ENGINE=InnoDB; +CREATE TABLE t2 LIKE t1; +INSERT INTO t1 VALUES (NULL,1,1,'foo','foo'),(NULL,2,2,'bar','bar'),(NULL,3,3,'baz','baz'),(NULL,4,4,'qux','qux'); +INSERT INTO t2 +SELECT NULL, a1.col_int, a1.col_int_key, a1.col_char, a1.col_char_key +FROM t1 a1, t1 a2, t1 a3, t1 a4, t1 a5, t1 a6, t1 a7, t1 a8, t1 a9, t1 a10; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/encryption/r/innodb-log-encrypt.result b/mysql-test/suite/encryption/r/innodb-log-encrypt.result index 3e281efd08a..655e3023f7a 100644 --- a/mysql-test/suite/encryption/r/innodb-log-encrypt.result +++ b/mysql-test/suite/encryption/r/innodb-log-encrypt.result @@ -8,7 +8,7 @@ begin declare current_num int; set current_num = 0; while current_num < repeat_count do -insert into t1 values(current_num, substring(MD5(RAND()), -64), REPEAT('secredsecredsecred',10)); +insert into t1 values(current_num, substring(MD5(RAND()), -64), REPEAT('privatejanprivate',10)); set current_num = current_num + 1; end while; end// @@ -22,34 +22,34 @@ select count(*) from t1; count(*) 2000 # ibdata1 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in ibdata1 +NOT FOUND /privatejanprivate/ in ibdata1 # t1 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in t1.ibd +NOT FOUND /privatejanprivate/ in t1.ibd # log0 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in ib_logfile0 +NOT FOUND /privatejanprivate/ in ib_logfile0 # log1 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in ib_logfile1 +NOT FOUND /privatejanprivate/ in ib_logfile1 # Restart mysqld --innodb_encrypt_log=0 -insert into t1 values(5000, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5001, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5002, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5003, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5004, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); +insert into t1 values(5000, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5001, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5002, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5003, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5004, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); # ibdata1 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in ibdata1 +NOT FOUND /privatejanprivate/ in ibdata1 # t1 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in t1.ibd +NOT FOUND /privatejanprivate/ in t1.ibd # log0 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in ib_logfile0 +NOT FOUND /privatejanprivate/ in ib_logfile0 # log1 yes on expecting NOT FOUND -NOT FOUND /secredsecred/ in ib_logfile1 +NOT FOUND /privatejanprivate/ in ib_logfile1 # ibdata1 yes on expecting NOT FOUND -NOT FOUND /notsecred/ in ibdata1 +NOT FOUND /publicmessage/ in ibdata1 # t1 yes on expecting NOT FOUND -NOT FOUND /notsecred/ in t1.ibd +NOT FOUND /publicmessage/ in t1.ibd # log0 no on expecting FOUND/NOTFOUND depending where insert goes -FOUND /notsecred/ in ib_logfile0 +FOUND /publicmessage/ in ib_logfile0 # log1 no on expecting FOUND/NOTFOUND depending where insert goes -NOT FOUND /notsecred/ in ib_logfile1 +NOT FOUND /publicmessage/ in ib_logfile1 drop procedure innodb_insert_proc; drop table t1; diff --git a/mysql-test/suite/encryption/r/innodb_encryption.result b/mysql-test/suite/encryption/r/innodb_encryption.result index 283c78e33d3..9b762bbba11 100644 --- a/mysql-test/suite/encryption/r/innodb_encryption.result +++ b/mysql-test/suite/encryption/r/innodb_encryption.result @@ -16,6 +16,7 @@ MIN_KEY_VERSION int(11) unsigned NO 0 CURRENT_KEY_VERSION int(11) unsigned NO 0 KEY_ROTATION_PAGE_NUMBER bigint(21) unsigned YES NULL KEY_ROTATION_MAX_PAGE_NUMBER bigint(21) unsigned YES NULL +CURRENT_KEY_ID int(11) unsigned NO 0 # Wait max 5 min for key encryption threads to encrypt one space # Success! # Wait max 10 min for key encryption threads to encrypt all space diff --git a/mysql-test/suite/encryption/r/innodb_encryption_is.result b/mysql-test/suite/encryption/r/innodb_encryption_is.result new file mode 100644 index 00000000000..5bbcbbe6bb6 --- /dev/null +++ b/mysql-test/suite/encryption/r/innodb_encryption_is.result @@ -0,0 +1,14 @@ +SET GLOBAL innodb_file_format = `Barracuda`; +SET GLOBAL innodb_file_per_table = ON; +CREATE TABLE t1 (c VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=1; +CREATE TABLE t2 (c VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=2; +INSERT INTO t1 VALUES ('foobar'); +INSERT INTO t2 VALUES ('foobar'); +SELECT NAME, ENCRYPTION_SCHEME, MIN_KEY_VERSION, CURRENT_KEY_VERSION, +CURRENT_KEY_ID +FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION +WHERE NAME LIKE '%t1' OR NAME LIKE '%t2'; +NAME ENCRYPTION_SCHEME MIN_KEY_VERSION CURRENT_KEY_VERSION CURRENT_KEY_ID +test/t1 1 1 1 1 +test/t2 1 1 1 2 +DROP TABLE t1, t2; diff --git a/mysql-test/suite/encryption/t/filekeys_emptyfile.opt b/mysql-test/suite/encryption/t/filekeys_emptyfile.opt new file mode 100644 index 00000000000..7c5f6d05dde --- /dev/null +++ b/mysql-test/suite/encryption/t/filekeys_emptyfile.opt @@ -0,0 +1 @@ +--loose-file-key-management-filename=$MYSQL_TEST_DIR/std_data/empty_file diff --git a/mysql-test/suite/encryption/t/filekeys_emptyfile.test b/mysql-test/suite/encryption/t/filekeys_emptyfile.test new file mode 100644 index 00000000000..39f2ccf260a --- /dev/null +++ b/mysql-test/suite/encryption/t/filekeys_emptyfile.test @@ -0,0 +1,4 @@ +let SEARCH_PATTERN=System key id 1 is missing at; +source filekeys_badtest.inc; + +--echo # Test checks if opening an empty filekeys does not crash the server. diff --git a/mysql-test/suite/encryption/t/innodb-encryption-disable.test b/mysql-test/suite/encryption/t/innodb-encryption-disable.test new file mode 100644 index 00000000000..42d8008d1aa --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-encryption-disable.test @@ -0,0 +1,92 @@ +-- source include/have_innodb.inc +# embedded does not support restart +-- source include/not_embedded.inc +-- source include/not_valgrind.inc +# Avoid CrashReporter popup on Mac +-- source include/not_crashrep.inc +-- source filekeys_plugin_exists.inc + +--disable_query_log +let $innodb_file_format_orig = `SELECT @@innodb_file_format`; +let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; +--enable_query_log + +SET GLOBAL innodb_file_format = `Barracuda`; +SET GLOBAL innodb_file_per_table = ON; + +# +# MDEV-9559: Server without encryption configs crashes if selecting from an implicitly encrypted table +# +call mtr.add_suppression("InnoDB: Block in space_id .* in file test/.* encrypted"); +call mtr.add_suppression("InnoDB: However key management plugin or used key_id 1 is not found or used encryption algorithm or method does not match."); +call mtr.add_suppression("InnoDB: Marking tablespace as missing. You may drop this table or install correct key management plugin and key file."); +call mtr.add_suppression(".*InnoDB: Cannot open table test/.* from the internal data dictionary of InnoDB though the .frm file for the table exists. See .* for how you can resolve the problem."); +call mtr.add_suppression("InnoDB: .ibd file is missing for table test/.*"); +# Suppression for builds where file_key_management plugin is linked statically +call mtr.add_suppression("Couldn't load plugins from 'file_key_management*"); +call mtr.add_suppression("InnoDB: Tablespace id.* is encrypted but encryption service or used key_id .* is not available. Can't continue opening tablespace."); + +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +--write_file $MYSQLTEST_VARDIR/keys1.txt +1;770A8A65DA156D24EE2A093277530142 +4;770A8A65DA156D24EE2A093277530143 +EOF + +--exec echo "restart:--innodb-encrypt-tables --plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +create table t5 ( + `intcol1` int(32) DEFAULT NULL, + `intcol2` int(32) DEFAULT NULL, + `charcol1` varchar(128) DEFAULT NULL, + `charcol2` varchar(128) DEFAULT NULL, + `charcol3` varchar(128) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +insert into t5 values (1,2,'maria','db','encryption'); + +CREATE TABLE `t1` ( + `intcol1` int(32) DEFAULT NULL, + `intcol2` int(32) DEFAULT NULL, + `charcol1` varchar(128) DEFAULT NULL, + `charcol2` varchar(128) DEFAULT NULL, + `charcol3` varchar(128) DEFAULT NULL +) ENGINE=InnoDB; + +insert into t1 values (1,2,'maria','db','encryption'); +alter table t1 encrypted='yes' `encryption_key_id`=1; + +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +--exec echo "restart:--innodb-encrypt-tables=OFF" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +--error 1296 +select * from t1; +--error 1296 +select * from t5; + +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +--exec echo "restart:--innodb-encrypt-tables --plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +drop table t1; +drop table t5; + +--disable_query_log +EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; +EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; +--enable_query_log + +--remove_file $MYSQLTEST_VARDIR/keys1.txt diff --git a/mysql-test/suite/encryption/t/innodb-log-encrypt-crash.opt b/mysql-test/suite/encryption/t/innodb-log-encrypt-crash.opt new file mode 100644 index 00000000000..e76aa060879 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-log-encrypt-crash.opt @@ -0,0 +1,6 @@ +--innodb-encrypt-log=ON +--plugin-load-add=$FILE_KEY_MANAGEMENT_SO +--loose-file-key-management +--loose-file-key-management-filename=$MYSQL_TEST_DIR/std_data/logkey.txt +--file-key-management-encryption-algorithm=aes_cbc +--innodb-buffer-pool-size=128M diff --git a/mysql-test/suite/encryption/t/innodb-log-encrypt-crash.test b/mysql-test/suite/encryption/t/innodb-log-encrypt-crash.test new file mode 100644 index 00000000000..8bb5f9f2c49 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-log-encrypt-crash.test @@ -0,0 +1,38 @@ +-- source include/have_innodb.inc +-- source include/not_embedded.inc +-- source filekeys_plugin.inc + +call mtr.add_suppression("InnoDB: New log files created, LSN=.*"); +call mtr.add_suppression("InnoDB: Creating foreign key constraint system tables."); +call mtr.add_suppression("InnoDB: Error: Table .*"); + +# +# MDEV-9422: Checksum errors on restart when killing busy instance that uses encrypted XtraDB tables +# + +CREATE TABLE t1 ( + pk bigint auto_increment, + col_int int, + col_int_key int, + col_char char(12), + col_char_key char(12), + primary key (pk), + key (`col_int_key` ), + key (`col_char_key` ) +) ENGINE=InnoDB; +CREATE TABLE t2 LIKE t1; + +INSERT INTO t1 VALUES (NULL,1,1,'foo','foo'),(NULL,2,2,'bar','bar'),(NULL,3,3,'baz','baz'),(NULL,4,4,'qux','qux'); +INSERT INTO t2 + SELECT NULL, a1.col_int, a1.col_int_key, a1.col_char, a1.col_char_key + FROM t1 a1, t1 a2, t1 a3, t1 a4, t1 a5, t1 a6, t1 a7, t1 a8, t1 a9, t1 a10; + +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server 0 +--source include/wait_until_disconnected.inc + +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +DROP TABLE t1, t2; diff --git a/mysql-test/suite/encryption/t/innodb-log-encrypt.test b/mysql-test/suite/encryption/t/innodb-log-encrypt.test index b2abfadccc2..7c2e6f847b1 100644 --- a/mysql-test/suite/encryption/t/innodb-log-encrypt.test +++ b/mysql-test/suite/encryption/t/innodb-log-encrypt.test @@ -28,7 +28,7 @@ begin declare current_num int; set current_num = 0; while current_num < repeat_count do - insert into t1 values(current_num, substring(MD5(RAND()), -64), REPEAT('secredsecredsecred',10)); + insert into t1 values(current_num, substring(MD5(RAND()), -64), REPEAT('privatejanprivate',10)); set current_num = current_num + 1; end while; end// @@ -43,13 +43,15 @@ set autocommit=1; update t1 set c1 = c1 +1; select count(*) from t1; +-- source include/restart_mysqld.inc + --let $MYSQLD_DATADIR=`select @@datadir` --let ib1_IBD = $MYSQLD_DATADIR/ibdata1 --let t1_IBD = $MYSQLD_DATADIR/test/t1.ibd --let log0 = $MYSQLD_DATADIR/ib_logfile0 --let log1 = $MYSQLD_DATADIR/ib_logfile1 --let SEARCH_RANGE = 10000000 ---let SEARCH_PATTERN=secredsecred +--let SEARCH_PATTERN=privatejanprivate --echo # ibdata1 yes on expecting NOT FOUND -- let SEARCH_FILE=$ib1_IBD @@ -68,13 +70,13 @@ select count(*) from t1; -- let $restart_parameters=--innodb_encrypt_log=0 -- source include/restart_mysqld.inc -insert into t1 values(5000, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5001, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5002, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5003, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); -insert into t1 values(5004, substring(MD5(RAND()), -64), REPEAT('notsecred',10)); +insert into t1 values(5000, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5001, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5002, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5003, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); +insert into t1 values(5004, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); ---let SEARCH_PATTERN=secredsecred +--let SEARCH_PATTERN=privatejanprivate --echo # ibdata1 yes on expecting NOT FOUND -- let SEARCH_FILE=$ib1_IBD -- source include/search_pattern_in_file.inc @@ -88,7 +90,7 @@ insert into t1 values(5004, substring(MD5(RAND()), -64), REPEAT('notsecred',10)) -- let SEARCH_FILE=$log1 -- source include/search_pattern_in_file.inc ---let SEARCH_PATTERN=notsecred +--let SEARCH_PATTERN=publicmessage --echo # ibdata1 yes on expecting NOT FOUND -- let SEARCH_FILE=$ib1_IBD -- source include/search_pattern_in_file.inc diff --git a/mysql-test/suite/encryption/t/innodb_encryption_is.opt b/mysql-test/suite/encryption/t/innodb_encryption_is.opt new file mode 100644 index 00000000000..26c706840e8 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb_encryption_is.opt @@ -0,0 +1 @@ +--loose-innodb-tablespaces-encryption diff --git a/mysql-test/suite/encryption/t/innodb_encryption_is.test b/mysql-test/suite/encryption/t/innodb_encryption_is.test new file mode 100644 index 00000000000..333bb84c634 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb_encryption_is.test @@ -0,0 +1,31 @@ +-- source include/have_innodb.inc +-- source include/have_file_key_management_plugin.inc + +--disable_query_log +let $innodb_file_format_orig = `SELECT @@innodb_file_format`; +let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; +--enable_query_log + +SET GLOBAL innodb_file_format = `Barracuda`; +SET GLOBAL innodb_file_per_table = ON; + +CREATE TABLE t1 (c VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=1; +CREATE TABLE t2 (c VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=2; +INSERT INTO t1 VALUES ('foobar'); +INSERT INTO t2 VALUES ('foobar'); + +# +# MDEV-9640: Add used key_id to INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION +# +SELECT NAME, ENCRYPTION_SCHEME, MIN_KEY_VERSION, CURRENT_KEY_VERSION, +CURRENT_KEY_ID +FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION +WHERE NAME LIKE '%t1' OR NAME LIKE '%t2'; + +DROP TABLE t1, t2; + +# reset system +--disable_query_log +EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; +EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; +--enable_query_log diff --git a/mysql-test/suite/federated/federatedx.result b/mysql-test/suite/federated/federatedx.result index 0b0b39f0abd..4d5d94443f3 100644 --- a/mysql-test/suite/federated/federatedx.result +++ b/mysql-test/suite/federated/federatedx.result @@ -2164,6 +2164,12 @@ DROP TABLE federated.t1; End of 5.1 tests SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MASTER_CONCURRENT_INSERT; SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT; +# +# MDEV-9346 - The federatedx and spider engine make mysqld crash when +# they are configured withtout username +# +CREATE TABLE t1 (a INT) ENGINE=FEDERATED CONNECTION='mysql://@127.0.0.1:SLAVE_PORT/federated/t1'; +ERROR HY000: Can't create federated table. Foreign data src error: database: 'federated' username: '' hostname: '127.0.0.1' DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; diff --git a/mysql-test/suite/federated/federatedx.test b/mysql-test/suite/federated/federatedx.test index 87ef49e66e8..29d1eaddc26 100644 --- a/mysql-test/suite/federated/federatedx.test +++ b/mysql-test/suite/federated/federatedx.test @@ -2001,4 +2001,13 @@ SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT; connection default; +--echo # +--echo # MDEV-9346 - The federatedx and spider engine make mysqld crash when +--echo # they are configured withtout username +--echo # +connection master; +--replace_result $SLAVE_MYPORT SLAVE_PORT +--error ER_CANT_CREATE_FEDERATED_TABLE +eval CREATE TABLE t1 (a INT) ENGINE=FEDERATED CONNECTION='mysql://@127.0.0.1:$SLAVE_MYPORT/federated/t1'; + source include/federated_cleanup.inc; diff --git a/mysql-test/suite/funcs_1/r/is_columns_is.result b/mysql-test/suite/funcs_1/r/is_columns_is.result index 66a90f1dc87..e992b79321e 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is.result @@ -363,7 +363,7 @@ def information_schema TABLES AUTO_INCREMENT 14 NULL YES bigint NULL NULL 20 0 N def information_schema TABLES AVG_ROW_LENGTH 9 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select def information_schema TABLES CHECKSUM 19 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select def information_schema TABLES CHECK_TIME 17 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select -def information_schema TABLES CREATE_OPTIONS 20 NULL YES varchar 255 765 NULL NULL NULL utf8 utf8_general_ci varchar(255) select +def information_schema TABLES CREATE_OPTIONS 20 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select def information_schema TABLES CREATE_TIME 15 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select def information_schema TABLES DATA_FREE 13 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select def information_schema TABLES DATA_LENGTH 10 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select @@ -906,7 +906,7 @@ NULL information_schema TABLES UPDATE_TIME datetime NULL NULL NULL NULL datetime NULL information_schema TABLES CHECK_TIME datetime NULL NULL NULL NULL datetime 3.0000 information_schema TABLES TABLE_COLLATION varchar 32 96 utf8 utf8_general_ci varchar(32) NULL information_schema TABLES CHECKSUM bigint NULL NULL NULL NULL bigint(21) unsigned -3.0000 information_schema TABLES CREATE_OPTIONS varchar 255 765 utf8 utf8_general_ci varchar(255) +3.0000 information_schema TABLES CREATE_OPTIONS varchar 2048 6144 utf8 utf8_general_ci varchar(2048) 3.0000 information_schema TABLES TABLE_COMMENT varchar 2048 6144 utf8 utf8_general_ci varchar(2048) 3.0000 information_schema TABLESPACES TABLESPACE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema TABLESPACES ENGINE varchar 64 192 utf8 utf8_general_ci varchar(64) diff --git a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result index 810157494d9..87eecaf41e9 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result @@ -363,7 +363,7 @@ def information_schema TABLES AUTO_INCREMENT 14 NULL YES bigint NULL NULL 20 0 N def information_schema TABLES AVG_ROW_LENGTH 9 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned def information_schema TABLES CHECKSUM 19 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned def information_schema TABLES CHECK_TIME 17 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime -def information_schema TABLES CREATE_OPTIONS 20 NULL YES varchar 255 765 NULL NULL NULL utf8 utf8_general_ci varchar(255) +def information_schema TABLES CREATE_OPTIONS 20 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) def information_schema TABLES CREATE_TIME 15 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime def information_schema TABLES DATA_FREE 13 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned def information_schema TABLES DATA_LENGTH 10 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned @@ -906,7 +906,7 @@ NULL information_schema TABLES UPDATE_TIME datetime NULL NULL NULL NULL datetime NULL information_schema TABLES CHECK_TIME datetime NULL NULL NULL NULL datetime 3.0000 information_schema TABLES TABLE_COLLATION varchar 32 96 utf8 utf8_general_ci varchar(32) NULL information_schema TABLES CHECKSUM bigint NULL NULL NULL NULL bigint(21) unsigned -3.0000 information_schema TABLES CREATE_OPTIONS varchar 255 765 utf8 utf8_general_ci varchar(255) +3.0000 information_schema TABLES CREATE_OPTIONS varchar 2048 6144 utf8 utf8_general_ci varchar(2048) 3.0000 information_schema TABLES TABLE_COMMENT varchar 2048 6144 utf8 utf8_general_ci varchar(2048) 3.0000 information_schema TABLESPACES TABLESPACE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema TABLESPACES ENGINE varchar 64 192 utf8 utf8_general_ci varchar(64) diff --git a/mysql-test/suite/funcs_1/r/is_tables.result b/mysql-test/suite/funcs_1/r/is_tables.result index 1b4ad503b29..53fb95680e9 100644 --- a/mysql-test/suite/funcs_1/r/is_tables.result +++ b/mysql-test/suite/funcs_1/r/is_tables.result @@ -47,7 +47,7 @@ UPDATE_TIME datetime YES NULL CHECK_TIME datetime YES NULL TABLE_COLLATION varchar(32) YES NULL CHECKSUM bigint(21) unsigned YES NULL -CREATE_OPTIONS varchar(255) YES NULL +CREATE_OPTIONS varchar(2048) YES NULL TABLE_COMMENT varchar(2048) NO SHOW CREATE TABLE information_schema.TABLES; Table Create Table @@ -71,7 +71,7 @@ TABLES CREATE TEMPORARY TABLE `TABLES` ( `CHECK_TIME` datetime DEFAULT NULL, `TABLE_COLLATION` varchar(32) DEFAULT NULL, `CHECKSUM` bigint(21) unsigned DEFAULT NULL, - `CREATE_OPTIONS` varchar(255) DEFAULT NULL, + `CREATE_OPTIONS` varchar(2048) DEFAULT NULL, `TABLE_COMMENT` varchar(2048) NOT NULL DEFAULT '' ) ENGINE=MEMORY DEFAULT CHARSET=utf8 SHOW COLUMNS FROM information_schema.TABLES; @@ -95,7 +95,7 @@ UPDATE_TIME datetime YES NULL CHECK_TIME datetime YES NULL TABLE_COLLATION varchar(32) YES NULL CHECKSUM bigint(21) unsigned YES NULL -CREATE_OPTIONS varchar(255) YES NULL +CREATE_OPTIONS varchar(2048) YES NULL TABLE_COMMENT varchar(2048) NO SELECT table_catalog, table_schema, table_name FROM information_schema.tables WHERE table_catalog IS NULL OR table_catalog <> 'def'; diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 85d8614c91f..25f20e01521 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -20,10 +20,11 @@ galera_parallel_simple : Failing sporadically galera_bf_abort : Failing sporadically galera_log_output_csv : Failing sporadically galera_as_slave_preordered : wsrep-preordered is not available in MariaDB Galera cluster -galera_forced_binlog_format : TODO: investigate galera_gra_log : TODO: investigate galera_as_slave_replication_bundle : TODO: investigate galera_ssl_upgrade : TODO: investigate mysql-wsrep#90 : TODO: investigate galera_flush : mysql-wsrep/issues/229 galera_transaction_read_only : mysql-wsrep/issues/229 +galera_gcs_fragment : Incorrect arguments to SET +galera_flush_local : Fails sporadically diff --git a/mysql-test/suite/galera/galera_2nodes.cnf b/mysql-test/suite/galera/galera_2nodes.cnf index f9e5be1901e..1dbaad4f699 100644 --- a/mysql-test/suite/galera/galera_2nodes.cnf +++ b/mysql-test/suite/galera/galera_2nodes.cnf @@ -17,7 +17,7 @@ wsrep-sync-wait=7 #ist_port=@OPT.port #sst_port=@OPT.port wsrep-cluster-address=gcomm:// -wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=10M' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;gcache.size=10M' wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' @@ -26,7 +26,7 @@ wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port' #ist_port=@OPT.port #sst_port=@OPT.port wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port' -wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=10M' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;gcache.size=10M' wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port' diff --git a/mysql-test/suite/galera/r/galera_create_function.result b/mysql-test/suite/galera/r/galera_create_function.result index 10020712286..8e4a823d00f 100644 --- a/mysql-test/suite/galera/r/galera_create_function.result +++ b/mysql-test/suite/galera/r/galera_create_function.result @@ -24,6 +24,9 @@ f1 NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`user1`@`%` FUNCTIO MODIFIES SQL DATA COMMENT 'f1_comment' RETURN 'abc' latin1 latin1_swedish_ci latin1_swedish_ci +SELECT 1 FROM DUAL; +1 +1 SHOW CREATE FUNCTION f1; Function sql_mode Create Function character_set_client collation_connection Database Collation f1 NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`user1`@`%` FUNCTION `f1`(param INTEGER) RETURNS varchar(200) CHARSET latin1 diff --git a/mysql-test/suite/galera/r/galera_defaults.result b/mysql-test/suite/galera/r/galera_defaults.result index a0fe1b622e6..6879ecf67fc 100644 --- a/mysql-test/suite/galera/r/galera_defaults.result +++ b/mysql-test/suite/galera/r/galera_defaults.result @@ -50,7 +50,7 @@ WSREP_SST_DONOR WSREP_SST_DONOR_REJECTS_QUERIES OFF WSREP_SST_METHOD rsync WSREP_SYNC_WAIT 7 -<BASE_HOST>; <BASE_PORT>; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT15S; evs.info_log_mask = 0; evs.install_timeout = PT7.5S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT5S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 0; evs.view_forget_timeout = P1D; <GCACHE_DIR>; gcache.keep_pages_size = 0; gcache.mem_size = 0; <GCACHE_NAME>; gcache.page_size = 128M; gcache.size = 10M; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; <GCS_RECV_Q_HARD_LIMIT>; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; <GMCAST_LISTEN_ADDR>; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; <IST_RECV_ADDR>; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = P30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT30S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; repl.proto_max = 7; socket.checksum = 2; +<BASE_HOST>; <BASE_PORT>; cert.log_conflicts = no; debug = no; evs.auto_evict = 0; evs.causal_keepalive_period = PT1S; evs.debug_log_mask = 0x1; evs.delay_margin = PT1S; evs.delayed_keep_period = PT30S; evs.inactive_check_period = PT0.5S; evs.inactive_timeout = PT15S; evs.info_log_mask = 0; evs.install_timeout = PT7.5S; evs.join_retrans_period = PT1S; evs.keepalive_period = PT1S; evs.max_install_timeouts = 3; evs.send_window = 4; evs.stats_report_period = PT1M; evs.suspect_timeout = PT5S; evs.use_aggregate = true; evs.user_send_window = 2; evs.version = 0; evs.view_forget_timeout = P1D; <GCACHE_DIR>; gcache.keep_pages_size = 0; gcache.mem_size = 0; <GCACHE_NAME>; gcache.page_size = 128M; gcache.size = 10M; gcs.fc_debug = 0; gcs.fc_factor = 1.0; gcs.fc_limit = 16; gcs.fc_master_slave = no; gcs.max_packet_size = 64500; gcs.max_throttle = 0.25; <GCS_RECV_Q_HARD_LIMIT>; gcs.recv_q_soft_limit = 0.25; gcs.sync_donor = no; <GMCAST_LISTEN_ADDR>; gmcast.mcast_addr = ; gmcast.mcast_ttl = 1; gmcast.peer_timeout = PT3S; gmcast.segment = 0; gmcast.time_wait = PT5S; gmcast.version = 0; <IST_RECV_ADDR>; pc.announce_timeout = PT3S; pc.checksum = false; pc.ignore_quorum = false; pc.ignore_sb = false; pc.linger = PT20S; pc.npvo = false; pc.recovery = true; pc.version = 0; pc.wait_prim = true; pc.wait_prim_timeout = P30S; pc.weight = 1; protonet.backend = asio; protonet.version = 0; repl.causal_read_timeout = PT90S; repl.commit_order = 3; repl.key_format = FLAT8; repl.max_ws_size = 2147483647; repl.proto_max = 7; socket.checksum = 2; SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME LIKE 'wsrep_%' AND VARIABLE_NAME != 'wsrep_debug_sync_waiters'; diff --git a/mysql-test/suite/galera/r/galera_flush.result b/mysql-test/suite/galera/r/galera_flush.result index 8ff32fdfff4..71226432eda 100644 --- a/mysql-test/suite/galera/r/galera_flush.result +++ b/mysql-test/suite/galera/r/galera_flush.result @@ -1,3 +1,4 @@ +DROP TABLE IF EXISTS t1, t2; FLUSH DES_KEY_FILE; wsrep_last_committed_diff 1 @@ -26,6 +27,37 @@ CREATE TABLE t2 (f1 INTEGER); FLUSH TABLES t2; wsrep_last_committed_diff 1 +FLUSH ERROR LOGS; +wsrep_last_committed_diff +1 +FLUSH SLOW LOGS; +wsrep_last_committed_diff +1 +FLUSH GENERAL LOGS; +wsrep_last_committed_diff +1 +FLUSH ENGINE LOGS; +wsrep_last_committed_diff +1 +FLUSH RELAY LOGS; +wsrep_last_committed_diff +1 +SET @userstat_old= @@userstat; +SET GLOBAL userstat=ON; +FLUSH CLIENT_STATISTICS; +FLUSH INDEX_STATISTICS; +FLUSH TABLE_STATISTICS; +FLUSH USER_STATISTICS; +wsrep_last_committed_diff +1 +SET @old_thread_statistics= @@global.thread_statistics; +SET GLOBAL thread_statistics= ON; +FLUSH THREAD_STATISTICS; +wsrep_last_committed_diff +1 +FLUSH CHANGED_PAGE_BITMAPS; +wsrep_last_committed_diff +1 CREATE TABLE t1 (f1 INTEGER); FLUSH LOGS; FLUSH TABLES WITH READ LOCK; @@ -52,3 +84,5 @@ wsrep_last_committed_diff 1 DROP TABLE t1; DROP TABLE t2; +SET GLOBAL userstat= @userstat_old; +SET GLOBAL thread_statistics= @old_thread_statistics; diff --git a/mysql-test/suite/galera/r/galera_flush_local.result b/mysql-test/suite/galera/r/galera_flush_local.result new file mode 100644 index 00000000000..3fdd541b513 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_flush_local.result @@ -0,0 +1,145 @@ +DROP TABLE IF EXISTS t1, t2, x1, x2; +CREATE TABLE t1 (f1 INTEGER); +CREATE TABLE t2 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER); +CREATE TABLE x1 (f1 INTEGER) ENGINE=MyISAM; +CREATE TABLE x2 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +INSERT INTO x1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +INSERT INTO t2 (f2) SELECT 1 FROM t1 AS a1, t1 AS a2, t1 AS a3, t1 AS a4; +INSERT INTO x2 (f2) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +FLUSH LOCAL DES_KEY_FILE; +FLUSH LOCAL HOSTS; +FLUSH LOCAL QUERY CACHE; +FLUSH LOCAL STATUS; +FLUSH LOCAL PRIVILEGES; +FLUSH LOCAL USER_RESOURCES; +FLUSH LOCAL TABLES; +FLUSH LOCAL TABLES t2; +FLUSH LOCAL ERROR LOGS; +FLUSH LOCAL SLOW LOGS; +FLUSH LOCAL GENERAL LOGS; +FLUSH LOCAL ENGINE LOGS; +FLUSH LOCAL RELAY LOGS; +FLUSH LOCAL CLIENT_STATISTICS; +FLUSH LOCAL INDEX_STATISTICS; +FLUSH LOCAL TABLE_STATISTICS; +FLUSH LOCAL USER_STATISTICS; +FLUSH LOCAL LOGS; +FLUSH LOCAL BINARY LOGS; +FLUSH LOCAL TABLES WITH READ LOCK; +UNLOCK TABLES; +FLUSH LOCAL TABLES t1 WITH READ LOCK; +UNLOCK TABLES; +FLUSH LOCAL TABLES t1 FOR EXPORT; +UNLOCK TABLES; +LOCK TABLES t1 WRITE; +FLUSH LOCAL TABLES t1; +UNLOCK TABLES; +LOCK TABLES t1 READ; +FLUSH LOCAL TABLES t1; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +UNLOCK TABLES; +FLUSH LOCAL TABLES t1; +ANALYZE LOCAL TABLE t1, t2; +Table Op Msg_type Msg_text +test.t1 analyze status OK +test.t2 analyze status OK +OPTIMIZE LOCAL TABLE t1, t2; +Table Op Msg_type Msg_text +test.t1 optimize note Table does not support optimize, doing recreate + analyze instead +test.t1 optimize status OK +test.t2 optimize note Table does not support optimize, doing recreate + analyze instead +test.t2 optimize status OK +REPAIR LOCAL TABLE x1, x2; +Table Op Msg_type Msg_text +test.x1 repair status OK +test.x2 repair status OK +wsrep_last_committed_diff +1 +SELECT COUNT(*) = 10 FROM t1; +COUNT(*) = 10 +1 +SELECT COUNT(*) = 10 FROM x1; +COUNT(*) = 10 +1 +SELECT COUNT(*) = 10000 FROM t2; +COUNT(*) = 10000 +1 +SELECT COUNT(*) = 10 FROM x2; +COUNT(*) = 10 +1 +DROP TABLE t1, t2, x1, x2; +CREATE TABLE t1 (f1 INTEGER); +CREATE TABLE t2 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER); +CREATE TABLE x1 (f1 INTEGER) ENGINE=MyISAM; +CREATE TABLE x2 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +INSERT INTO x1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +INSERT INTO t2 (f2) SELECT 1 FROM t1 AS a1, t1 AS a2, t1 AS a3, t1 AS a4; +INSERT INTO x2 (f2) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +set wsrep_on=0; +FLUSH DES_KEY_FILE; +FLUSH HOSTS; +FLUSH QUERY CACHE; +FLUSH STATUS; +FLUSH PRIVILEGES; +FLUSH USER_RESOURCES; +FLUSH TABLES; +FLUSH TABLES t2; +FLUSH ERROR LOGS; +FLUSH SLOW LOGS; +FLUSH GENERAL LOGS; +FLUSH ENGINE LOGS; +FLUSH RELAY LOGS; +FLUSH CLIENT_STATISTICS; +FLUSH INDEX_STATISTICS; +FLUSH TABLE_STATISTICS; +FLUSH USER_STATISTICS; +FLUSH LOGS; +FLUSH BINARY LOGS; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +FLUSH TABLES t1 WITH READ LOCK; +UNLOCK TABLES; +FLUSH TABLES t1 FOR EXPORT; +UNLOCK TABLES; +LOCK TABLES t1 WRITE; +FLUSH TABLES t1; +UNLOCK TABLES; +LOCK TABLES t1 READ; +FLUSH TABLES t1; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +UNLOCK TABLES; +FLUSH TABLES t1; +ANALYZE TABLE t1, t2; +Table Op Msg_type Msg_text +test.t1 analyze status OK +test.t2 analyze status OK +OPTIMIZE TABLE t1, t2; +Table Op Msg_type Msg_text +test.t1 optimize note Table does not support optimize, doing recreate + analyze instead +test.t1 optimize status OK +test.t2 optimize note Table does not support optimize, doing recreate + analyze instead +test.t2 optimize status OK +REPAIR TABLE x1, x2; +Table Op Msg_type Msg_text +test.x1 repair status OK +test.x2 repair status OK +wsrep_last_committed_diff +1 +wsrep_last_committed_diff2 +1 +SELECT COUNT(*) = 10 FROM t1; +COUNT(*) = 10 +1 +SELECT COUNT(*) = 10 FROM x1; +COUNT(*) = 10 +1 +SELECT COUNT(*) = 10000 FROM t2; +COUNT(*) = 10000 +1 +SELECT COUNT(*) = 10 FROM x2; +COUNT(*) = 10 +1 +set wsrep_on=1; +DROP TABLE t1, t2, x1, x2; diff --git a/mysql-test/suite/galera/r/galera_forced_binlog_format.result b/mysql-test/suite/galera/r/galera_forced_binlog_format.result index 857e44d2dfc..92e78685b58 100644 --- a/mysql-test/suite/galera/r/galera_forced_binlog_format.result +++ b/mysql-test/suite/galera/r/galera_forced_binlog_format.result @@ -1,18 +1,43 @@ RESET MASTER; SET SESSION binlog_format = 'STATEMENT'; +Warnings: +Warning 1105 MariaDB Galera does not support binlog format: STATEMENT CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); SET SESSION binlog_format = 'MIXED'; +Warnings: +Warning 1105 MariaDB Galera does not support binlog format: MIXED INSERT INTO t1 VALUES (2); -SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120; +SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 249; Log_name Pos Event_type Server_id End_log_pos Info +mysqld-bin.000001 <Pos> Gtid_list 1 <End_log_pos> [] +mysqld-bin.000001 <Pos> Binlog_checkpoint 1 <End_log_pos> mysqld-bin.000001 +mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> GTID 0-1-1 mysqld-bin.000001 <Pos> Query 1 <End_log_pos> use `test`; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB -mysqld-bin.000001 <Pos> Query 1 <End_log_pos> BEGIN +mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-2 mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) -mysqld-bin.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ -mysqld-bin.000001 <Pos> Query 1 <End_log_pos> BEGIN +mysqld-bin.000001 <Pos> Gtid 1 <End_log_pos> BEGIN GTID 0-1-3 mysqld-bin.000001 <Pos> Table_map 1 <End_log_pos> table_id: ### (test.t1) -mysqld-bin.000001 <Pos> Write_rows 1 <End_log_pos> table_id: ### flags: STMT_END_F +mysqld-bin.000001 <Pos> Write_rows_v1 1 <End_log_pos> table_id: ### flags: STMT_END_F mysqld-bin.000001 <Pos> Xid 1 <End_log_pos> COMMIT /* xid=### */ DROP TABLE t1; +# +# MDEV-9401: wsrep_forced_binlog_format with binlog causes crash +# +SET SESSION binlog_format = 'ROW'; +CREATE DATABASE testdb_9401; +USE testdb_9401; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +CREATE USER dummy@localhost; +GRANT ALL PRIVILEGES ON testdb_9401.t1 TO dummy@localhost; +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +Grants for dummy@localhost +GRANT USAGE ON *.* TO 'dummy'@'localhost' +GRANT ALL PRIVILEGES ON `testdb_9401`.`t1` TO 'dummy'@'localhost' +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE testdb_9401; +# End of tests diff --git a/mysql-test/suite/galera/r/galera_ftwrl_drain.result b/mysql-test/suite/galera/r/galera_ftwrl_drain.result index a4879838d11..d704699925b 100644 --- a/mysql-test/suite/galera/r/galera_ftwrl_drain.result +++ b/mysql-test/suite/galera/r/galera_ftwrl_drain.result @@ -2,6 +2,8 @@ CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; INSERT INTO t1 VALUES (1); SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; SELECT COUNT(*) = 0 FROM t1; COUNT(*) = 0 1 diff --git a/mysql-test/suite/galera/r/galera_gcs_fragment.result b/mysql-test/suite/galera/r/galera_gcs_fragment.result new file mode 100644 index 00000000000..0c9c1819f60 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_gcs_fragment.result @@ -0,0 +1,24 @@ +CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 TEXT); +SET GLOBAL wsrep_cluster_address=''; +SET SESSION wsrep_sync_wait=0; +SET GLOBAL wsrep_provider_options = 'dbug=d,gcs_core_after_frag_send'; +SET SESSION wsrep_retry_autocommit=0; +INSERT INTO t1 VALUES (1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +SET GLOBAL wsrep_provider_options = 'dbug='; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; +INSERT INTO t1 VALUES (2, "bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); +SET GLOBAL wsrep_provider_options = 'signal=gcs_core_after_frag_send'; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +INSERT INTO t1 VALUES (3, "cccccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); +SELECT * FROM t1; +f1 f2 +2 bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +3 cccccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +SELECT * FROM t1; +f1 f2 +2 bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +3 cccccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/galera_log_bin.result b/mysql-test/suite/galera/r/galera_log_bin.result index 6411a1e3043..4772f347375 100644 --- a/mysql-test/suite/galera/r/galera_log_bin.result +++ b/mysql-test/suite/galera/r/galera_log_bin.result @@ -16,19 +16,19 @@ Log_name Pos Event_type Server_id End_log_pos Info mysqld-bin.000002 # Gtid # # GTID 0-1-1 mysqld-bin.000002 # Query # # use `test`; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB mysqld-bin.000002 # Gtid # # BEGIN GTID 0-1-2 -mysqld-bin.000002 # Table_map # # table_id: 48 (test.t1) -mysqld-bin.000002 # Write_rows_v1 # # table_id: 48 flags: STMT_END_F -mysqld-bin.000002 # Xid # # COMMIT /* xid=2 */ +mysqld-bin.000002 # Table_map # # table_id: # (test.t1) +mysqld-bin.000002 # Write_rows_v1 # # table_id: # flags: STMT_END_F +mysqld-bin.000002 # Xid # # COMMIT /* xid=# */ mysqld-bin.000002 # Gtid # # GTID 0-1-3 mysqld-bin.000002 # Query # # use `test`; CREATE TABLE t2 (id INT) ENGINE=InnoDB mysqld-bin.000002 # Gtid # # BEGIN GTID 0-1-4 -mysqld-bin.000002 # Table_map # # table_id: 49 (test.t2) -mysqld-bin.000002 # Write_rows_v1 # # table_id: 49 flags: STMT_END_F -mysqld-bin.000002 # Xid # # COMMIT /* xid=4 */ +mysqld-bin.000002 # Table_map # # table_id: # (test.t2) +mysqld-bin.000002 # Write_rows_v1 # # table_id: # flags: STMT_END_F +mysqld-bin.000002 # Xid # # COMMIT /* xid=# */ mysqld-bin.000002 # Gtid # # BEGIN GTID 0-1-5 -mysqld-bin.000002 # Table_map # # table_id: 49 (test.t2) -mysqld-bin.000002 # Write_rows_v1 # # table_id: 49 flags: STMT_END_F -mysqld-bin.000002 # Xid # # COMMIT /* xid=5 */ +mysqld-bin.000002 # Table_map # # table_id: # (test.t2) +mysqld-bin.000002 # Write_rows_v1 # # table_id: # flags: STMT_END_F +mysqld-bin.000002 # Xid # # COMMIT /* xid=# */ mysqld-bin.000002 # Gtid # # GTID 0-1-6 mysqld-bin.000002 # Query # # use `test`; ALTER TABLE t1 ADD COLUMN f2 INTEGER SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; @@ -39,20 +39,21 @@ Log_name Pos Event_type Server_id End_log_pos Info mysqld-bin.000003 # Gtid # # GTID 0-1-1 mysqld-bin.000003 # Query # # use `test`; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB mysqld-bin.000003 # Gtid # # BEGIN GTID 0-1-2 -mysqld-bin.000003 # Table_map # # table_id: 30 (test.t1) -mysqld-bin.000003 # Write_rows_v1 # # table_id: 30 flags: STMT_END_F -mysqld-bin.000003 # Xid # # COMMIT /* xid=2 */ +mysqld-bin.000003 # Table_map # # table_id: # (test.t1) +mysqld-bin.000003 # Write_rows_v1 # # table_id: # flags: STMT_END_F +mysqld-bin.000003 # Xid # # COMMIT /* xid=# */ mysqld-bin.000003 # Gtid # # GTID 0-1-3 mysqld-bin.000003 # Query # # use `test`; CREATE TABLE t2 (id INT) ENGINE=InnoDB mysqld-bin.000003 # Gtid # # BEGIN GTID 0-1-4 -mysqld-bin.000003 # Table_map # # table_id: 31 (test.t2) -mysqld-bin.000003 # Write_rows_v1 # # table_id: 31 flags: STMT_END_F -mysqld-bin.000003 # Xid # # COMMIT /* xid=4 */ +mysqld-bin.000003 # Table_map # # table_id: # (test.t2) +mysqld-bin.000003 # Write_rows_v1 # # table_id: # flags: STMT_END_F +mysqld-bin.000003 # Xid # # COMMIT /* xid=# */ mysqld-bin.000003 # Gtid # # BEGIN GTID 0-1-5 -mysqld-bin.000003 # Table_map # # table_id: 31 (test.t2) -mysqld-bin.000003 # Write_rows_v1 # # table_id: 31 flags: STMT_END_F -mysqld-bin.000003 # Xid # # COMMIT /* xid=5 */ +mysqld-bin.000003 # Table_map # # table_id: # (test.t2) +mysqld-bin.000003 # Write_rows_v1 # # table_id: # flags: STMT_END_F +mysqld-bin.000003 # Xid # # COMMIT /* xid=# */ mysqld-bin.000003 # Gtid # # GTID 0-1-6 mysqld-bin.000003 # Query # # use `test`; ALTER TABLE t1 ADD COLUMN f2 INTEGER DROP TABLE t1; DROP TABLE t2; +RESET MASTER; diff --git a/mysql-test/suite/galera/r/galera_mdl_race.result b/mysql-test/suite/galera/r/galera_mdl_race.result new file mode 100644 index 00000000000..535f20de7f1 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_mdl_race.result @@ -0,0 +1,38 @@ +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); +SET AUTOCOMMIT=ON; +START TRANSACTION; +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; +LOCK TABLE t2 WRITE; +SET GLOBAL DEBUG = "d,sync.wsrep_before_mdl_wait"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SELECT * FROM t2;; +SET GLOBAL DEBUG = "d,sync.wsrep_after_BF_victim_lock"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +UPDATE t1 SET f2 = 'c' WHERE f1 = 1; +SET GLOBAL DEBUG = ""; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_before_mdl_wait"; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_after_BF_victim_lock"; +UNLOCK TABLES; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'a'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'a'; +COUNT(*) = 1 +1 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; +COUNT(*) = 1 +1 +DROP TABLE t1; +DROP TABLE t2; +SET DEBUG_SYNC = "RESET"; diff --git a/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result b/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result new file mode 100644 index 00000000000..856abbb43be --- /dev/null +++ b/mysql-test/suite/galera/r/galera_query_cache_sync_wait.result @@ -0,0 +1,58 @@ +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT1S"; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SET SESSION wsrep_sync_wait = 7; +SELECT MAX(id) FROM t1; +MAX(id) +1 +INSERT INTO t1 VALUES (2); +SELECT MAX(id) FROM t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SET GLOBAL DEBUG = ""; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +FLUSH QUERY CACHE; +SET SESSION wsrep_sync_wait = 7; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SET DEBUG_SYNC = "RESET"; +INSERT INTO t1 VALUES (3); +SELECT MAX(id) FROM t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SET GLOBAL DEBUG = ""; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +INSERT INTO t1 VALUES (4); +SET SESSION wsrep_sync_wait = 7; +SELECT MAX(id) FROM t1; +MAX(id) +4 +SET SESSION wsrep_sync_wait = 7; +FLUSH STATUS; +SELECT MAX(id) FROM t1; +MAX(id) +4 +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; +VARIABLE_VALUE = 1 +1 +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +INSERT INTO t1 VALUES (5); +SET SESSION wsrep_sync_wait = 7; +SELECT MAX(id) FROM t1 ; +SET GLOBAL DEBUG = ""; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +MAX(id) +5 +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; +VARIABLE_VALUE = 1 +1 diff --git a/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result b/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result new file mode 100644 index 00000000000..62e327ffdee --- /dev/null +++ b/mysql-test/suite/galera/r/galera_rsu_wsrep_desync.result @@ -0,0 +1,42 @@ +CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; +SET GLOBAL wsrep_desync=1; +SET wsrep_OSU_method=RSU; +SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +ALTER TABLE t1 ADD COLUMN f2 INTEGER;; +SET GLOBAL wsrep_desync=0; +SET DEBUG_SYNC= 'now SIGNAL continue'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW VARIABLES LIKE 'wsrep_desync'; +Variable_name Value +wsrep_desync OFF +SET wsrep_OSU_method=TOI; +DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; +CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; +SET GLOBAL wsrep_desync=0; +Warnings: +Warning 1231 'wsrep_desync' is already OFF. +SET wsrep_OSU_method=RSU; +SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +ALTER TABLE t1 ADD COLUMN f2 INTEGER;; +SET GLOBAL wsrep_desync=1; +ERROR HY000: Operation 'desync' failed for SET GLOBAL wsrep_desync=1 +SET GLOBAL wsrep_desync=0; +SET DEBUG_SYNC= 'now SIGNAL continue'; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `f2` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SET wsrep_OSU_method=TOI; +DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; +CALL mtr.add_suppression("Protocol violation"); +CALL mtr.add_suppression("desync failed"); +CALL mtr.add_suppression("Protocol violation"); diff --git a/mysql-test/suite/galera/r/galera_server.result b/mysql-test/suite/galera/r/galera_server.result new file mode 100644 index 00000000000..ef81bf376b0 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_server.result @@ -0,0 +1,20 @@ +# On node_1 +CREATE SERVER s1 +FOREIGN DATA WRAPPER mysql +OPTIONS (HOST 'foo'); +# On node_2 +SELECT * FROM mysql.servers; +Server_name Host Db Username Password Port Socket Wrapper Owner +s1 foo 3306 mysql +ALTER SERVER s1 +OPTIONS (HOST 'bar'); +# On node_1 +SELECT * FROM mysql.servers; +Server_name Host Db Username Password Port Socket Wrapper Owner +s1 bar 3306 mysql +DROP SERVER s1; +# On node_2 +SELECT COUNT(*)=0 FROM mysql.servers; +COUNT(*)=0 +1 +# End of test diff --git a/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key.result b/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key.result index 93557cc91d4..7d30b356aa9 100644 --- a/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key.result +++ b/mysql-test/suite/galera/r/galera_sst_mysqldump_with_key.result @@ -104,3 +104,5 @@ CALL mtr.add_suppression("Can't open and lock privilege tables"); CALL mtr.add_suppression("Info table is not ready to be used"); CALL mtr.add_suppression("Native table .* has the wrong structure"); DROP USER sslsst; +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; diff --git a/mysql-test/suite/galera/r/galera_sync_wait_show.result b/mysql-test/suite/galera/r/galera_sync_wait_show.result new file mode 100644 index 00000000000..2f030c26bb8 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_sync_wait_show.result @@ -0,0 +1,39 @@ +SET SESSION wsrep_sync_wait = 1; +CREATE DATABASE db1; +SHOW CREATE DATABASE db1; +Database Create Database +db1 CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET latin1 */ +DROP DATABASE db1; +CREATE PROCEDURE p1 () SELECT 1 FROM DUAL; +SHOW CREATE PROCEDURE p1; +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +p1 NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() +SELECT 1 FROM DUAL latin1 latin1_swedish_ci latin1_swedish_ci +DROP PROCEDURE p1; +CREATE PROCEDURE p1 () SELECT 1 FROM DUAL; +SHOW PROCEDURE CODE p1; +Pos Instruction +0 stmt 0 "SELECT 1 FROM DUAL" +DROP PROCEDURE p1; +CREATE FUNCTION f1 () RETURNS INTEGER RETURN 123; +SHOW CREATE FUNCTION f1; +Function sql_mode Create Function character_set_client collation_connection Database Collation +f1 NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) +RETURN 123 latin1 latin1_swedish_ci latin1_swedish_ci +DROP FUNCTION f1; +CREATE FUNCTION f1 () RETURNS INTEGER RETURN 123; +SHOW FUNCTION CODE f1; +Pos Instruction +0 freturn 3 123 +DROP FUNCTION f1; +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.f1 = 'a'; +SHOW CREATE TRIGGER tr1; +Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation +tr1 NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.f1 = 'a' latin1 latin1_swedish_ci latin1_swedish_ci +DROP TABLE t1; +CREATE EVENT event1 ON SCHEDULE AT '2038-01-01 23:59:59' DO SELECT 1; +SHOW CREATE EVENT event1; +Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation +event1 NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION SYSTEM CREATE DEFINER=`root`@`localhost` EVENT `event1` ON SCHEDULE AT '2038-01-01 23:59:59' ON COMPLETION NOT PRESERVE DISABLE ON SLAVE DO SELECT 1 latin1 latin1_swedish_ci latin1_swedish_ci +DROP EVENT event1; diff --git a/mysql-test/suite/galera/r/galera_transaction_replay.result b/mysql-test/suite/galera/r/galera_transaction_replay.result index 54ea8db699d..bfafa506fe6 100644 --- a/mysql-test/suite/galera/r/galera_transaction_replay.result +++ b/mysql-test/suite/galera/r/galera_transaction_replay.result @@ -10,6 +10,8 @@ f1 f2 SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_enter_sync'; COMMIT;; SET SESSION wsrep_sync_wait = 0; +SET SESSION wsrep_on = 0; +SET SESSION wsrep_on = 1; UPDATE t1 SET f2 = 'c' WHERE f1 = 2; SET GLOBAL wsrep_provider_options = 'dbug='; SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_enter_sync'; diff --git a/mysql-test/suite/galera/r/mysql-wsrep#198.result b/mysql-test/suite/galera/r/mysql-wsrep#198.result new file mode 100644 index 00000000000..25ba2cb615c --- /dev/null +++ b/mysql-test/suite/galera/r/mysql-wsrep#198.result @@ -0,0 +1,18 @@ +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB; +LOCK TABLE t2 WRITE; +OPTIMIZE TABLE t1,t2;; +REPAIR TABLE t1,t2;; +SET SESSION wsrep_sync_wait = 0; +INSERT INTO t2 VALUES (1); +UNLOCK TABLES; +Table Op Msg_type Msg_text +test.t1 optimize note Table does not support optimize, doing recreate + analyze instead +test.t1 optimize status OK +test.t2 optimize note Table does not support optimize, doing recreate + analyze instead +test.t2 optimize status OK +Table Op Msg_type Msg_text +test.t1 repair note The storage engine for the table doesn't support repair +test.t2 repair note The storage engine for the table doesn't support repair +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/r/mysql-wsrep#201.result b/mysql-test/suite/galera/r/mysql-wsrep#201.result new file mode 100644 index 00000000000..1c0998e35ac --- /dev/null +++ b/mysql-test/suite/galera/r/mysql-wsrep#201.result @@ -0,0 +1,4 @@ +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (DEFAULT); +SET GLOBAL query_cache_size=1355776; +SET SESSION wsrep_sync_wait = 7; diff --git a/mysql-test/suite/galera/r/mysql-wsrep#237.result b/mysql-test/suite/galera/r/mysql-wsrep#237.result new file mode 100644 index 00000000000..3fd9aed1480 --- /dev/null +++ b/mysql-test/suite/galera/r/mysql-wsrep#237.result @@ -0,0 +1,10 @@ +CREATE TABLE t (f1 INTEGER PRIMARY KEY) Engine=InnoDB; +SET DEBUG_SYNC = 'wsrep_before_replication WAIT_FOR continue'; +INSERT INTO t values (1);; +SET SESSION wsrep_sync_wait = 0; +FLUSH TABLES; +SELECT SLEEP(1); +SLEEP(1) +0 +SET DEBUG_SYNC= 'now SIGNAL continue'; +DROP TABLE t; diff --git a/mysql-test/suite/galera/r/mysql-wsrep#247.result b/mysql-test/suite/galera/r/mysql-wsrep#247.result new file mode 100644 index 00000000000..1b00f511f03 --- /dev/null +++ b/mysql-test/suite/galera/r/mysql-wsrep#247.result @@ -0,0 +1,11 @@ +SET GLOBAL wsrep_desync=1; +SET wsrep_OSU_method=RSU; +CREATE TABLE t1 (i int primary key); +SHOW VARIABLES LIKE 'wsrep_desync'; +Variable_name Value +wsrep_desync ON +SET GLOBAL wsrep_desync=0; +DROP TABLE t1; +SHOW VARIABLES LIKE 'wsrep_desync'; +Variable_name Value +wsrep_desync OFF diff --git a/mysql-test/suite/galera/r/mysql-wsrep#31.result b/mysql-test/suite/galera/r/mysql-wsrep#31.result new file mode 100644 index 00000000000..a21bb3eccfd --- /dev/null +++ b/mysql-test/suite/galera/r/mysql-wsrep#31.result @@ -0,0 +1,10 @@ +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +INSERT INTO t1 VALUES('test'); +CREATE DATABASE db; +Shutting down server 2 ... +Recovering server 2 ... +Performing --wsrep-recover ... +Restarting server ... +Using --wsrep-start-position when starting mysqld ... +DROP TABLE t1; +DROP DATABASE db; diff --git a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test index b7b656383fd..5914e52d851 100644 --- a/mysql-test/suite/galera/t/galera_as_slave_nonprim.test +++ b/mysql-test/suite/galera/t/galera_as_slave_nonprim.test @@ -26,6 +26,7 @@ SET SESSION wsrep_sync_wait = 0; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; --connection node_2 +--sleep 1 --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1'; --source include/wait_condition.inc diff --git a/mysql-test/suite/galera/t/galera_create_function.test b/mysql-test/suite/galera/t/galera_create_function.test index fd4903a7b83..0d7cec0114f 100644 --- a/mysql-test/suite/galera/t/galera_create_function.test +++ b/mysql-test/suite/galera/t/galera_create_function.test @@ -33,6 +33,8 @@ RETURN 123; SHOW CREATE FUNCTION f1; --connection node_2 +# Work around codership/mysql-wsrep#228 - SHOW CREATE FUNCTION not covered by wsrep_sync_wait +SELECT 1 FROM DUAL; SHOW CREATE FUNCTION f1; --connection node_1 @@ -49,9 +51,3 @@ DROP FUNCTION f1; DROP FUNCTION f2; DROP USER 'user1'; - - - - - - diff --git a/mysql-test/suite/galera/t/galera_flush.test b/mysql-test/suite/galera/t/galera_flush.test index 3ba5edbae6f..77e95f62fda 100644 --- a/mysql-test/suite/galera/t/galera_flush.test +++ b/mysql-test/suite/galera/t/galera_flush.test @@ -7,6 +7,9 @@ --source include/have_perfschema.inc --source include/have_query_cache.inc +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings # # The following FLUSH statements should be replicated # @@ -101,6 +104,101 @@ FLUSH TABLES t2; --enable_query_log +--connection node_2 +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--connection node_1 +FLUSH ERROR LOGS; +--connection node_2 +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--disable_query_log +--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff; +--enable_query_log + + +--connection node_2 +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--connection node_1 +FLUSH SLOW LOGS; +--connection node_2 +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--disable_query_log +--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff; +--enable_query_log + +--connection node_2 +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--connection node_1 +FLUSH GENERAL LOGS; +--connection node_2 +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--disable_query_log +--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff; +--enable_query_log + +--connection node_2 +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--connection node_1 +FLUSH ENGINE LOGS; +--connection node_2 +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--disable_query_log +--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff; +--enable_query_log + +--connection node_2 +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--connection node_1 +FLUSH RELAY LOGS; +--connection node_2 +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--disable_query_log +--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff; +--enable_query_log + +--connection node_1 +SET @userstat_old= @@userstat; +SET GLOBAL userstat=ON; + +--connection node_2 +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--connection node_1 +FLUSH CLIENT_STATISTICS; +FLUSH INDEX_STATISTICS; +FLUSH TABLE_STATISTICS; +FLUSH USER_STATISTICS; +--connection node_2 +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--disable_query_log +--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 4 AS wsrep_last_committed_diff; +--enable_query_log + + +--connection node_1 +SET @old_thread_statistics= @@global.thread_statistics; +SET GLOBAL thread_statistics= ON; + +--connection node_2 +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--connection node_1 +FLUSH THREAD_STATISTICS; +--connection node_2 +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--disable_query_log +--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff; +--enable_query_log + + +--connection node_2 +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--connection node_1 +FLUSH CHANGED_PAGE_BITMAPS; +--connection node_2 +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--disable_query_log +--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 1 AS wsrep_last_committed_diff; +--enable_query_log + + # # The following statements should not be replicated: FLUSH LOGS, FLUSH TABLES WITH LOCKS # @@ -171,3 +269,5 @@ FLUSH TABLES t1; --connection node_1 DROP TABLE t1; DROP TABLE t2; +SET GLOBAL userstat= @userstat_old; +SET GLOBAL thread_statistics= @old_thread_statistics; diff --git a/mysql-test/suite/galera/t/galera_flush_local.opt b/mysql-test/suite/galera/t/galera_flush_local.opt new file mode 100644 index 00000000000..45a0ca24dc7 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_flush_local.opt @@ -0,0 +1 @@ +--query_cache_type=1 --query_cache_size=1000000 --userstat=1 --wsrep_replicate_myisam=true diff --git a/mysql-test/suite/galera/t/galera_flush_local.test b/mysql-test/suite/galera/t/galera_flush_local.test new file mode 100644 index 00000000000..768f4ea4f1b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_flush_local.test @@ -0,0 +1,142 @@ +# +# Test that various FLUSH LOCAL commands are replicated. Whenever possible, check the slave for the effects. +# PXC-391 + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_query_cache.inc + +--disable_warnings +DROP TABLE IF EXISTS t1, t2, x1, x2; +--enable_warnings +# +# The following FLUSH LOCAL statements should *not* be replicated +# +--connection node_1 +CREATE TABLE t1 (f1 INTEGER); +CREATE TABLE t2 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER); +CREATE TABLE x1 (f1 INTEGER) ENGINE=MyISAM; +CREATE TABLE x2 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +INSERT INTO x1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +INSERT INTO t2 (f2) SELECT 1 FROM t1 AS a1, t1 AS a2, t1 AS a3, t1 AS a4; +INSERT INTO x2 (f2) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); + +--connection node_2 +--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--connection node_1 +FLUSH LOCAL DES_KEY_FILE; +FLUSH LOCAL HOSTS; +FLUSH LOCAL QUERY CACHE; +FLUSH LOCAL STATUS; +FLUSH LOCAL PRIVILEGES; +FLUSH LOCAL USER_RESOURCES; +FLUSH LOCAL TABLES; +FLUSH LOCAL TABLES t2; +FLUSH LOCAL ERROR LOGS; +FLUSH LOCAL SLOW LOGS; +FLUSH LOCAL GENERAL LOGS; +FLUSH LOCAL ENGINE LOGS; +FLUSH LOCAL RELAY LOGS; +FLUSH LOCAL CLIENT_STATISTICS; +FLUSH LOCAL INDEX_STATISTICS; +FLUSH LOCAL TABLE_STATISTICS; +FLUSH LOCAL USER_STATISTICS; +FLUSH LOCAL LOGS; +FLUSH LOCAL BINARY LOGS; +FLUSH LOCAL TABLES WITH READ LOCK; +UNLOCK TABLES; +FLUSH LOCAL TABLES t1 WITH READ LOCK; +UNLOCK TABLES; +FLUSH LOCAL TABLES t1 FOR EXPORT; +UNLOCK TABLES; +LOCK TABLES t1 WRITE; +FLUSH LOCAL TABLES t1; +UNLOCK TABLES; +LOCK TABLES t1 READ; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +FLUSH LOCAL TABLES t1; +UNLOCK TABLES; +FLUSH LOCAL TABLES t1; +ANALYZE LOCAL TABLE t1, t2; +OPTIMIZE LOCAL TABLE t1, t2; +REPAIR LOCAL TABLE x1, x2; +--connection node_2 +--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--disable_query_log +--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before AS wsrep_last_committed_diff; +--enable_query_log + +SELECT COUNT(*) = 10 FROM t1; +SELECT COUNT(*) = 10 FROM x1; +SELECT COUNT(*) = 10000 FROM t2; +SELECT COUNT(*) = 10 FROM x2; + + +--connection node_1 +DROP TABLE t1, t2, x1, x2; +CREATE TABLE t1 (f1 INTEGER); +CREATE TABLE t2 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER); +CREATE TABLE x1 (f1 INTEGER) ENGINE=MyISAM; +CREATE TABLE x2 (f1 INT PRIMARY KEY AUTO_INCREMENT, f2 INTEGER) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +INSERT INTO x1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +INSERT INTO t2 (f2) SELECT 1 FROM t1 AS a1, t1 AS a2, t1 AS a3, t1 AS a4; +INSERT INTO x2 (f2) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); + + +--connection node_2 +--let $wsrep_last_committed_before2 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--connection node_1 +set wsrep_on=0; +FLUSH DES_KEY_FILE; +FLUSH HOSTS; +FLUSH QUERY CACHE; +FLUSH STATUS; +FLUSH PRIVILEGES; +FLUSH USER_RESOURCES; +FLUSH TABLES; +FLUSH TABLES t2; +FLUSH ERROR LOGS; +FLUSH SLOW LOGS; +FLUSH GENERAL LOGS; +FLUSH ENGINE LOGS; +FLUSH RELAY LOGS; +FLUSH CLIENT_STATISTICS; +FLUSH INDEX_STATISTICS; +FLUSH TABLE_STATISTICS; +FLUSH USER_STATISTICS; +FLUSH LOGS; +FLUSH BINARY LOGS; +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +FLUSH TABLES t1 WITH READ LOCK; +UNLOCK TABLES; +FLUSH TABLES t1 FOR EXPORT; +UNLOCK TABLES; +LOCK TABLES t1 WRITE; +FLUSH TABLES t1; +UNLOCK TABLES; +LOCK TABLES t1 READ; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +FLUSH TABLES t1; +UNLOCK TABLES; +FLUSH TABLES t1; +ANALYZE TABLE t1, t2; +OPTIMIZE TABLE t1, t2; +REPAIR TABLE x1, x2; +--connection node_2 +--let $wsrep_last_committed_after2 = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` +--disable_query_log +--eval SELECT $wsrep_last_committed_after2 = $wsrep_last_committed_before2 AS wsrep_last_committed_diff; +--eval SELECT $wsrep_last_committed_after2 = $wsrep_last_committed_before + 9 AS wsrep_last_committed_diff2; +--enable_query_log + +SELECT COUNT(*) = 10 FROM t1; +SELECT COUNT(*) = 10 FROM x1; +SELECT COUNT(*) = 10000 FROM t2; +SELECT COUNT(*) = 10 FROM x2; + +--connection node_1 +set wsrep_on=1; +DROP TABLE t1, t2, x1, x2; diff --git a/mysql-test/suite/galera/t/galera_forced_binlog_format.test b/mysql-test/suite/galera/t/galera_forced_binlog_format.test index 934c15399e0..982276cc317 100644 --- a/mysql-test/suite/galera/t/galera_forced_binlog_format.test +++ b/mysql-test/suite/galera/t/galera_forced_binlog_format.test @@ -20,6 +20,26 @@ INSERT INTO t1 VALUES (2); --replace_regex /xid=[0-9]+/xid=###/ /table_id: [0-9]+/table_id: ###/ --replace_column 2 <Pos> 5 <End_log_pos> -SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 120; +SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 249; DROP TABLE t1; + +--echo # +--echo # MDEV-9401: wsrep_forced_binlog_format with binlog causes crash +--echo # +SET SESSION binlog_format = 'ROW'; +CREATE DATABASE testdb_9401; +USE testdb_9401; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +CREATE USER dummy@localhost; +GRANT ALL PRIVILEGES ON testdb_9401.t1 TO dummy@localhost; +FLUSH PRIVILEGES; +SHOW GRANTS FOR dummy@localhost; +# Cleanup +REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; +DROP USER dummy@localhost; +DROP DATABASE testdb_9401; + +--source include/galera_end.inc +--echo # End of tests + diff --git a/mysql-test/suite/galera/t/galera_ftwrl_drain.test b/mysql-test/suite/galera/t/galera_ftwrl_drain.test index f022a9437c2..690e890cdea 100644 --- a/mysql-test/suite/galera/t/galera_ftwrl_drain.test +++ b/mysql-test/suite/galera/t/galera_ftwrl_drain.test @@ -18,7 +18,9 @@ CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; --connection node_2 -SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync'; + +--let $galera_sync_point = apply_monitor_slave_enter_sync +--source include/galera_set_sync_point.inc --connection node_1 INSERT INTO t1 VALUES (1); @@ -27,8 +29,7 @@ INSERT INTO t1 VALUES (1); SET SESSION wsrep_sync_wait = 0; # Wait until applier has blocked ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters' AND VARIABLE_VALUE = 'apply_monitor_slave_enter_sync' ---source include/wait_condition.inc +--source include/galera_wait_sync_point.inc SELECT COUNT(*) = 0 FROM t1; @@ -41,8 +42,8 @@ SELECT COUNT(*) = 0 FROM t1; --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'Init' AND INFO = 'FLUSH TABLES WITH READ LOCK' --source include/wait_condition.inc -SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync'; +--source include/galera_clear_sync_point.inc +--source include/galera_signal_sync_point.inc --connection node_2a --reap diff --git a/mysql-test/suite/galera/t/galera_gcs_fragment.cnf b/mysql-test/suite/galera/t/galera_gcs_fragment.cnf new file mode 100644 index 00000000000..aae3fee5904 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_gcs_fragment.cnf @@ -0,0 +1,5 @@ +!include ../galera_2nodes.cnf +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcs.max_packet_size=64' +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcs.max_packet_size=64' diff --git a/mysql-test/suite/galera/t/galera_gcs_fragment.test b/mysql-test/suite/galera/t/galera_gcs_fragment.test new file mode 100644 index 00000000000..ae1e0d8bab0 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_gcs_fragment.test @@ -0,0 +1,66 @@ +# Test fragmentation over configuration changes +--source include/galera_cluster.inc +--source include/have_innodb.inc + +# Prepare table +CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 TEXT); + +# Stop node2 + +# Disconnect node_2 from group +--connection node_2 +--let $wsrep_cluster_address_orig = `select @@wsrep_cluster_address` +SET GLOBAL wsrep_cluster_address=''; + +# Connection for sync points +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +SET SESSION wsrep_sync_wait=0; + +# Set breakpoint in gcs after first fragment send + +--let $galera_sync_point = gcs_core_after_frag_send +--source include/galera_set_sync_point.inc + +--connection node_1 +SET SESSION wsrep_retry_autocommit=0; +--send INSERT INTO t1 VALUES (1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + +--connection node_1a +--source include/galera_wait_sync_point.inc +--source include/galera_clear_sync_point.inc + + +# Restart node_2, wait until it joins the group and then make INSERT +--connection node_2 +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig' +--enable_query_log +SET SESSION wsrep_on = 0; +--source include/galera_wait_ready.inc +SET SESSION wsrep_on = 1; + +INSERT INTO t1 VALUES (2, "bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + +# Signal node_1 to continue +--connection node_1a +--source include/galera_signal_sync_point.inc + +# Deadlock error should be returned since write set send was +# interrupted by gcs +--connection node_1 +--error ER_LOCK_DEADLOCK +--reap + +# Do additional insert to verify that node_1 remain operational +INSERT INTO t1 VALUES (3, "cccccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + + +# Nodes node_1 and node_2 should now contain rows 2 and 3 +SELECT * FROM t1; + +--connection node_2 +SELECT * FROM t1; + +--connection node_1 + +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/galera_ist_restart_joiner.test b/mysql-test/suite/galera/t/galera_ist_restart_joiner.test index 69446f0f86a..eae28bdbcd7 100644 --- a/mysql-test/suite/galera/t/galera_ist_restart_joiner.test +++ b/mysql-test/suite/galera/t/galera_ist_restart_joiner.test @@ -27,7 +27,9 @@ UPDATE t1 SET f2 = 'c' WHERE f1 > 2; --connection node_2 # Make sure IST will block ... -SET GLOBAL wsrep_provider_options = 'dbug=d,recv_IST_after_apply_trx'; +--let $galera_sync_point = recv_IST_after_apply_trx +--source include/galera_set_sync_point.inc + SET SESSION wsrep_sync_wait = 0; diff --git a/mysql-test/suite/galera/t/galera_log_bin.test b/mysql-test/suite/galera/t/galera_log_bin.test index e36bd7e6025..d2d3987d711 100644 --- a/mysql-test/suite/galera/t/galera_log_bin.test +++ b/mysql-test/suite/galera/t/galera_log_bin.test @@ -23,13 +23,17 @@ ALTER TABLE t1 ADD COLUMN f2 INTEGER; FLUSH LOGS; --replace_column 2 # 4 # 5 # +--replace_regex /table_id: [0-9]+/table_id: #/ /xid=[0-9]+/xid=#/ SHOW BINLOG EVENTS IN 'mysqld-bin.000002' LIMIT 4,18; --connection node_2 SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; --replace_column 2 # 4 # 5 # +--replace_regex /table_id: [0-9]+/table_id: #/ /xid=[0-9]+/xid=#/ SHOW BINLOG EVENTS IN 'mysqld-bin.000003' LIMIT 3,18; DROP TABLE t1; DROP TABLE t2; +--connection node_1 +RESET MASTER; diff --git a/mysql-test/suite/galera/t/galera_mdl_race.test b/mysql-test/suite/galera/t/galera_mdl_race.test new file mode 100644 index 00000000000..508b85add4b --- /dev/null +++ b/mysql-test/suite/galera/t/galera_mdl_race.test @@ -0,0 +1,79 @@ +# +# This test tests a potential race condition in MDL locking +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc + +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); +CREATE TABLE t2 (f1 INTEGER PRIMARY KEY, f2 CHAR(1)); +INSERT INTO t1 VALUES (1, 'a'); +INSERT INTO t1 VALUES (2, 'a'); + +--connection node_1 +SET AUTOCOMMIT=ON; +START TRANSACTION; + +UPDATE t1 SET f2 = 'b' WHERE f1 = 1; + +# block access to t2 +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +LOCK TABLE t2 WRITE; + +# Block before MLD lock wait +--connection node_1 + SET GLOBAL DEBUG = "d,sync.wsrep_before_mdl_wait"; +--send SELECT * FROM t2; + +# Wait for SELECT to be blocked +--connection node_1a +#--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIS WHERE STATE = 'System lock'; +#--source include/wait_condition.inc +#--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'init' AND INFO = 'COMMIT'; +#--source include/wait_condition.inc + +# block applier to wait after BF victim is locked +SET GLOBAL DEBUG = "d,sync.wsrep_after_BF_victim_lock"; + +# Issue a conflicting update on node #2 +--connection node_2 +UPDATE t1 SET f2 = 'c' WHERE f1 = 1; + +--sleep 3 + +# Unblock the SELECT, to enter wsrep_thd_is_BF +--connection node_1a +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_before_mdl_wait"; + +--sleep 3 + +# unblock applier to try to BF the SELECT +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_after_BF_victim_lock"; + + +# table lock is not needed anymore +--sleep 3 +UNLOCK TABLES; + +# SELECT succeeds +--connection node_1 + +--error ER_LOCK_DEADLOCK +--reap + +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'a'; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; + +--connection node_2 +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'a'; +SELECT COUNT(*) = 1 FROM t1 WHERE f2 = 'c'; + +DROP TABLE t1; +DROP TABLE t2; + +--connection node_1a +SET DEBUG_SYNC = "RESET"; + diff --git a/mysql-test/suite/galera/t/galera_query_cache-master.opt b/mysql-test/suite/galera/t/galera_query_cache-master.opt index cb983993b91..915a36c0937 100644 --- a/mysql-test/suite/galera/t/galera_query_cache-master.opt +++ b/mysql-test/suite/galera/t/galera_query_cache-master.opt @@ -1,3 +1 @@ --query_cache_type=1 --query_cache_size=1355776 - - diff --git a/mysql-test/suite/galera/t/galera_query_cache_sync_wait-master.opt b/mysql-test/suite/galera/t/galera_query_cache_sync_wait-master.opt new file mode 100644 index 00000000000..915a36c0937 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_query_cache_sync_wait-master.opt @@ -0,0 +1 @@ +--query_cache_type=1 --query_cache_size=1355776 diff --git a/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test b/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test new file mode 100644 index 00000000000..6b14118d5fc --- /dev/null +++ b/mysql-test/suite/galera/t/galera_query_cache_sync_wait.test @@ -0,0 +1,94 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc +--source include/have_query_cache.inc + +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +--connection node_2 +--let $wsrep_provider_options_orig = `SELECT @@wsrep_provider_options` +SET GLOBAL wsrep_provider_options = "repl.causal_read_timeout=PT1S"; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; +SET SESSION wsrep_sync_wait = 7; +SELECT MAX(id) FROM t1; # first lookup miss + +# +# Query cache hit, wait timeout +# + +--connection node_1 +INSERT INTO t1 VALUES (2); + +--connection node_2 +--error ER_LOCK_WAIT_TIMEOUT +SELECT MAX(id) FROM t1; +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; + +FLUSH QUERY CACHE; +SET SESSION wsrep_sync_wait = 7; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; +SET DEBUG_SYNC = "RESET"; + +# +# Query cache miss, wait timeout +# + +--connection node_1 +INSERT INTO t1 VALUES (3); + +--connection node_2 +--error ER_LOCK_WAIT_TIMEOUT +SELECT MAX(id) FROM t1; +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; + +# +# Query cache miss +# + +--connection node_1 +INSERT INTO t1 VALUES (4); + +--connection node_2 +SET SESSION wsrep_sync_wait = 7; +SELECT MAX(id) FROM t1; +SET SESSION wsrep_sync_wait = 7; + +# +# Query cache hit +# + +FLUSH STATUS; +SELECT MAX(id) FROM t1; +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; +SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; + +# +# Query cache invalidated +# + +--connection node_1 +INSERT INTO t1 VALUES (5); + +--connection node_2 +SET SESSION wsrep_sync_wait = 7; +--send SELECT MAX(id) FROM t1 + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +SET GLOBAL DEBUG = ""; +SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; + +--connection node_2 +--reap +SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'Qcache_hits'; + + +--disable_query_log +--eval SET GLOBAL wsrep_provider_options = "$wsrep_provider_options_orig" +DROP TABLE t1; + +--connection node_2a +SET DEBUG_SYNC = "RESET"; diff --git a/mysql-test/suite/galera/t/galera_rsu_wsrep_desync.test b/mysql-test/suite/galera/t/galera_rsu_wsrep_desync.test new file mode 100644 index 00000000000..36ec8563cbe --- /dev/null +++ b/mysql-test/suite/galera/t/galera_rsu_wsrep_desync.test @@ -0,0 +1,78 @@ +# +# Test manipulating wsrep_desync while an RSU operation is in progress +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc + +# First, test wsrep_desync 1 > 0 during DDL + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; + +SET GLOBAL wsrep_desync=1; +SET wsrep_OSU_method=RSU; + +SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +--send ALTER TABLE t1 ADD COLUMN f2 INTEGER; + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a + +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: alter_table_before_open_tables' +--source include/wait_condition.inc + +SET GLOBAL wsrep_desync=0; +SET DEBUG_SYNC= 'now SIGNAL continue'; + +--connection node_1 +--reap + +SHOW CREATE TABLE t1; +SHOW VARIABLES LIKE 'wsrep_desync'; +SET wsrep_OSU_method=TOI; + +DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; + +# Next, test wsrep_desync 0 > 1 during DDL, currently not allowed + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; + +SET GLOBAL wsrep_desync=0; +SET wsrep_OSU_method=RSU; + +SET DEBUG_SYNC = 'alter_table_before_open_tables WAIT_FOR continue'; +--send ALTER TABLE t1 ADD COLUMN f2 INTEGER; + +--connection node_1a + +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: alter_table_before_open_tables' +--source include/wait_condition.inc + +# This transition is currently not allowed +--error ER_CANNOT_USER +SET GLOBAL wsrep_desync=1; +SET GLOBAL wsrep_desync=0; + +SET DEBUG_SYNC= 'now SIGNAL continue'; + +--connection node_1 +--reap + +SHOW CREATE TABLE t1; + +# Restore old state +SET wsrep_OSU_method=TOI; +DROP TABLE t1; +SET DEBUG_SYNC= 'RESET'; + +CALL mtr.add_suppression("Protocol violation"); +CALL mtr.add_suppression("desync failed"); + +--connection node_2 +CALL mtr.add_suppression("Protocol violation"); + + diff --git a/mysql-test/suite/galera/t/galera_server.test b/mysql-test/suite/galera/t/galera_server.test new file mode 100644 index 00000000000..30b39028b96 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_server.test @@ -0,0 +1,28 @@ +# Test for CREATE/ALTER/DROP SERVER in Galera cluster + +--source include/galera_cluster.inc + +--connection node_1 +--echo # On node_1 +CREATE SERVER s1 + FOREIGN DATA WRAPPER mysql + OPTIONS (HOST 'foo'); + +--connection node_2 +--echo # On node_2 +SELECT * FROM mysql.servers; +ALTER SERVER s1 + OPTIONS (HOST 'bar'); + +--connection node_1 +--echo # On node_1 +SELECT * FROM mysql.servers; +DROP SERVER s1; + +--connection node_2 +--echo # On node_2 +SELECT COUNT(*)=0 FROM mysql.servers; + +--source include/galera_end.inc +--echo # End of test + diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.test b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.test index 0b3edeb75ff..c813e04169f 100644 --- a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.test +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.test @@ -20,3 +20,10 @@ SET GLOBAL wsrep_sst_auth = 'sslsst:'; --source suite/galera/include/galera_sst_restore.inc DROP USER sslsst; + +--connection node_2 +# We have to manually restore global_log and slow_query_log due to mysql-wsrep#108 +# Otherwise MTR's check_testcases complains + +SET GLOBAL general_log = ON; +SET GLOBAL slow_query_log = ON; diff --git a/mysql-test/suite/galera/t/galera_sync_wait_show.test b/mysql-test/suite/galera/t/galera_sync_wait_show.test new file mode 100644 index 00000000000..250b1f76e98 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_sync_wait_show.test @@ -0,0 +1,69 @@ +# +# Test that the various SHOW commands obey wsrep_sync_wait - codership/mysql-wsrep#228 +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug.inc + +--connection node_2 +SET SESSION wsrep_sync_wait = 1; + + +--connection node_1 +CREATE DATABASE db1; + +--connection node_2 +SHOW CREATE DATABASE db1; +DROP DATABASE db1; + + +--connection node_1 +CREATE PROCEDURE p1 () SELECT 1 FROM DUAL; + +--connection node_2 +SHOW CREATE PROCEDURE p1; +DROP PROCEDURE p1; + + + +--connection node_1 +CREATE PROCEDURE p1 () SELECT 1 FROM DUAL; + +--connection node_2 +SHOW PROCEDURE CODE p1; +DROP PROCEDURE p1; + + + +--connection node_1 +CREATE FUNCTION f1 () RETURNS INTEGER RETURN 123; + +--connection node_2 +SHOW CREATE FUNCTION f1; +DROP FUNCTION f1; + + +--connection node_1 +CREATE FUNCTION f1 () RETURNS INTEGER RETURN 123; + +--connection node_2 +SHOW FUNCTION CODE f1; +DROP FUNCTION f1; + + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; +CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.f1 = 'a'; + +--connection node_2 +SHOW CREATE TRIGGER tr1; +DROP TABLE t1; + + +--connection node_1 +CREATE EVENT event1 ON SCHEDULE AT '2038-01-01 23:59:59' DO SELECT 1; + +--connection node_2 +SHOW CREATE EVENT event1; +DROP EVENT event1; diff --git a/mysql-test/suite/galera/t/galera_transaction_replay.test b/mysql-test/suite/galera/t/galera_transaction_replay.test index 632aa5cc0d5..bd5288a51c6 100644 --- a/mysql-test/suite/galera/t/galera_transaction_replay.test +++ b/mysql-test/suite/galera/t/galera_transaction_replay.test @@ -23,7 +23,8 @@ SELECT * FROM t1 WHERE f1 = 2 FOR UPDATE; # Block the commit --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 -SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_enter_sync'; +--let $galera_sync_point = commit_monitor_enter_sync +--source include/galera_set_sync_point.inc --connection node_1 --send COMMIT; @@ -31,8 +32,7 @@ SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_enter_sync'; # Wait until commit is blocked --connection node_1a SET SESSION wsrep_sync_wait = 0; ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_debug_sync_waiters' AND VARIABLE_VALUE = 'commit_monitor_enter_sync' ---source include/wait_condition.inc +--source include/galera_wait_sync_point.inc # Issue a conflicting update on node #2 --connection node_2 @@ -48,8 +48,8 @@ UPDATE t1 SET f2 = 'c' WHERE f1 = 2; # Unblock the commit --connection node_1a -SET GLOBAL wsrep_provider_options = 'dbug='; -SET GLOBAL wsrep_provider_options = 'signal=commit_monitor_enter_sync'; +--source include/galera_clear_sync_point.inc +--source include/galera_signal_sync_point.inc # Commit succeeds --connection node_1 diff --git a/mysql-test/suite/galera/t/mysql-wsrep#198.test b/mysql-test/suite/galera/t/mysql-wsrep#198.test new file mode 100644 index 00000000000..2b05c4ff4d9 --- /dev/null +++ b/mysql-test/suite/galera/t/mysql-wsrep#198.test @@ -0,0 +1,36 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB; + +--connection node_2 +LOCK TABLE t2 WRITE; + +--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2a +--send OPTIMIZE TABLE t1,t2; + +--connect node_2b, 127.0.0.1, root, , test, $NODE_MYPORT_2 +--connection node_2b +--send REPAIR TABLE t1,t2; + +--connection node_2 +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_1 +INSERT INTO t2 VALUES (1); + +--connection node_2 +UNLOCK TABLES; + +--connection node_2a +--reap + +--connection node_2b +--reap + +DROP TABLE t1; +DROP TABLE t2; diff --git a/mysql-test/suite/galera/t/mysql-wsrep#201-master.opt b/mysql-test/suite/galera/t/mysql-wsrep#201-master.opt new file mode 100644 index 00000000000..a00258bc48c --- /dev/null +++ b/mysql-test/suite/galera/t/mysql-wsrep#201-master.opt @@ -0,0 +1 @@ +--query_cache_type=1 diff --git a/mysql-test/suite/galera/t/mysql-wsrep#201.test b/mysql-test/suite/galera/t/mysql-wsrep#201.test new file mode 100644 index 00000000000..e9327540195 --- /dev/null +++ b/mysql-test/suite/galera/t/mysql-wsrep#201.test @@ -0,0 +1,33 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_query_cache.inc + +CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (DEFAULT); + +--connection node_2 +--let $qcache_size_orig = `SELECT @@GLOBAL.query_cache_size` +SET GLOBAL query_cache_size=1355776; +SET SESSION wsrep_sync_wait = 7; + +--disable_query_log + +--let $count = 500 +while ($count) +{ + --connection node_1 + INSERT INTO t1 VALUES (DEFAULT); + --let $val1 = `SELECT LAST_INSERT_ID()` + --connection node_2 + --let $val2 = `SELECT MAX(id) FROM t1` + --let $val3 = `SELECT $val1 != $val2` + if ($val3) + { + --echo $val1 $val2 + --die wsrep_sync_wait failed + } + --dec $count +} + +--eval SET GLOBAL query_cache_size = $qcache_size_orig +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/mysql-wsrep#237.test b/mysql-test/suite/galera/t/mysql-wsrep#237.test new file mode 100644 index 00000000000..7a65cb52ae9 --- /dev/null +++ b/mysql-test/suite/galera/t/mysql-wsrep#237.test @@ -0,0 +1,31 @@ +# hang because of replicated FLUSH TABLE command + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_debug_sync.inc + +CREATE TABLE t (f1 INTEGER PRIMARY KEY) Engine=InnoDB; + +--connection node_1 +SET DEBUG_SYNC = 'wsrep_before_replication WAIT_FOR continue'; +--send INSERT INTO t values (1); + +--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 +--connection node_1a +SET SESSION wsrep_sync_wait = 0; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE = 'debug sync point: wsrep_before_replication' +--source include/wait_condition.inc + +--connection node_2 +FLUSH TABLES; + + +--connection node_1a +SELECT SLEEP(1); + +SET DEBUG_SYNC= 'now SIGNAL continue'; + +--connection node_1 +--reap + +DROP TABLE t; diff --git a/mysql-test/suite/galera/t/mysql-wsrep#247.test b/mysql-test/suite/galera/t/mysql-wsrep#247.test new file mode 100644 index 00000000000..8bcd58607a1 --- /dev/null +++ b/mysql-test/suite/galera/t/mysql-wsrep#247.test @@ -0,0 +1,23 @@ +# +# codership/mysql-wsrep/247 MW-246 - +# DDL with RSU fails if node is desynced upfont +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 + +SET GLOBAL wsrep_desync=1; + +SET wsrep_OSU_method=RSU; + +CREATE TABLE t1 (i int primary key); + +SHOW VARIABLES LIKE 'wsrep_desync'; + +SET GLOBAL wsrep_desync=0; +--sleep 1 +DROP TABLE t1; +SHOW VARIABLES LIKE 'wsrep_desync'; + diff --git a/mysql-test/suite/galera/t/mysql-wsrep#31.test b/mysql-test/suite/galera/t/mysql-wsrep#31.test new file mode 100644 index 00000000000..eaace5d50dd --- /dev/null +++ b/mysql-test/suite/galera/t/mysql-wsrep#31.test @@ -0,0 +1,39 @@ +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--connection node_1 + +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +INSERT INTO t1 VALUES('test'); +CREATE DATABASE db; + +--connection node_2 +--let $expected_position_uuid = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_uuid'` +--let $expected_position_seqno = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'` + +--let $expected_position = $expected_position_uuid:$expected_position_seqno + +--echo Shutting down server 2 ... +--source include/shutdown_mysqld.inc + +--echo Recovering server 2 ... +--let $galera_wsrep_recover_server_id=2 +--source suite/galera/include/galera_wsrep_recover.inc + +if ($galera_wsrep_start_position != $expected_position) +{ + die(Expected position: $expected_position, found $galera_wsrep_start_position); +} + +--echo Restarting server ... +--source include/start_mysqld.inc + +--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size' +--source include/wait_condition.inc +--source include/wait_until_ready.inc + +--connection node_1 +DROP TABLE t1; +DROP DATABASE db; + + diff --git a/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result b/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result index 1ecea5db5ab..6c66bf4a891 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result @@ -16,8 +16,8 @@ CREATE TABLE t2 (f1 LONGTEXT); INSERT INTO t2 VALUES (REPEAT('x', 512 * 1024)); INSERT INTO t2 VALUES (REPEAT('x', 512 * 1024)); INSERT INTO t2 VALUES (REPEAT('x', 512 * 1024)); -SET GLOBAL wsrep_provider_options = 'signal=ist_sender_send_after_get_buffers'; SET GLOBAL wsrep_provider_options = 'dbug='; +SET GLOBAL wsrep_provider_options = 'signal=ist_sender_send_after_get_buffers'; INSERT INTO t1 VALUES (51), (52), (53), (54), (55); SELECT COUNT(*) = 30 FROM t1; COUNT(*) = 30 diff --git a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test index 0668c246624..7d8bbb39e35 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test @@ -38,7 +38,8 @@ INSERT INTO t1 VALUES (11), (12), (13), (14), (15); INSERT INTO t1 VALUES (21), (22), (23), (24), (25); # Make sure IST will block ... -SET GLOBAL wsrep_provider_options = 'dbug=d,ist_sender_send_after_get_buffers'; +--let $galera_sync_point = ist_sender_send_after_get_buffers +--source include/galera_set_sync_point.inc # ... and restart providers to force IST --connection node_2 @@ -70,8 +71,8 @@ INSERT INTO t2 VALUES (REPEAT('x', 512 * 1024)); INSERT INTO t2 VALUES (REPEAT('x', 512 * 1024)); # Unlock IST and wait for it to complete -SET GLOBAL wsrep_provider_options = 'signal=ist_sender_send_after_get_buffers'; -SET GLOBAL wsrep_provider_options = 'dbug='; +--source include/galera_clear_sync_point.inc +--source include/galera_signal_sync_point.inc INSERT INTO t1 VALUES (51), (52), (53), (54), (55); diff --git a/mysql-test/suite/innodb/r/innodb-agregate.result b/mysql-test/suite/innodb/r/innodb-agregate.result new file mode 100644 index 00000000000..d3e096c7eb0 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-agregate.result @@ -0,0 +1,21 @@ +create table t2 (a smallint(6) not null, b int(10) not null, name varchar(20), primary key(a,b), key(name)) engine=InnoDB; +insert into t2 values (8355,3,"sanja"),(8355,4,"wlad"),(8366,5, "lawrin"),(8366,6,"markusjm"); +select count(distinct name) from t2 where a=8366 and b>=5 and b<=5; +count(distinct name) +1 +select count(distinct name) from t2 where a=8366 and b=5; +count(distinct name) +1 +select count(distinct name) from t2 where a=8366 and b between 5 and 5.5; +count(distinct name) +1 +select sum(distinct a) from t2 where a=8366 and b>=5 and b<=5; +sum(distinct a) +8366 +select sum(distinct a) from t2 where a=8366 and b=5; +sum(distinct a) +8366 +select sum(distinct a) from t2 where a=8366 and b between 5 and 5.5; +sum(distinct a) +8366 +drop table t2; diff --git a/mysql-test/suite/innodb/r/innodb-alter-filewrite.result b/mysql-test/suite/innodb/r/innodb-alter-filewrite.result deleted file mode 100644 index 444b09ad440..00000000000 --- a/mysql-test/suite/innodb/r/innodb-alter-filewrite.result +++ /dev/null @@ -1,30 +0,0 @@ -CREATE TABLE `test_wo_keys` ( -`f01` int AUTO_INCREMENT, -`f02` bigint, `f03` bigint, `f04` enum('a','b'), -`f05` date, `f06` int, `f07` int, `f08` double, `f09` int, -`f10` bigint, `f11` double, `f12` enum('a','b','c','d','e'), -`f13` int, `f14` int, `f15` varchar(255), `f16` int, `f17` int, `f18` int, -`f19` double, `f20` double, `f21` double, `f22` double, `f23` double, `f24` tinyint, -`f25` double, `f26` double, `f27` double, `f28` double, `f29` int unsigned, -`f30` int unsigned, `f31` bigint, `f32` int unsigned, `f33` bigint, -`f34` int unsigned, `f35` int unsigned, -PRIMARY KEY `f01` (`f01`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; -show status like '%merge_buffers%'; -Variable_name Value -Innodb_os_merge_buffers_written 0 -Innodb_os_merge_buffers_read 0 -Innodb_os_merge_buffers_merged 0 -ALTER TABLE test_wo_keys -ADD KEY `f06` (`f06`), ADD KEY `f05` (`f05`), ADD KEY `f04` (`f04`), ADD KEY `f23` (`f23`), -ADD KEY `f10` (`f10`), ADD KEY `f11` (`f11`), ADD KEY `f09` (`f09`), ADD KEY `f22` (`f22`), -ADD KEY `f21` (`f21`), ADD KEY `f07` (`f07`), ADD KEY `f08` (`f08`), ADD KEY `f18` (`f18`), -ADD KEY `f19` (`f19`), ADD KEY `f20` (`f20`), ADD KEY `f29` (`f29`,`f31`,`f33`), -ADD KEY `f35` (`f35`), ADD KEY `f25` (`f25`), ADD KEY `f26` (`f26`), -ADD KEY `f27` (`f27`), ADD KEY `f28` (`f28`); -show status like '%merge_buffers%'; -Variable_name Value -Innodb_os_merge_buffers_written 0 -Innodb_os_merge_buffers_read 0 -Innodb_os_merge_buffers_merged 0 -DROP TABLE test_wo_keys; diff --git a/mysql-test/suite/innodb/r/innodb-alter-table.result b/mysql-test/suite/innodb/r/innodb-alter-table.result index 2c76a2640e0..514b8b7935f 100644 --- a/mysql-test/suite/innodb/r/innodb-alter-table.result +++ b/mysql-test/suite/innodb/r/innodb-alter-table.result @@ -43,3 +43,95 @@ KEY `mdl_courmodu_gro_ix` (`groupingid`) # Inserting 2701 rows into the table... ALTER TABLE moodle19.mdl_course_modules ADD stefantest LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci AFTER showdescription; drop database moodle19; +use test; +CREATE TABLE `w_findispmon05u` ( +`atpkey` INT(11) NOT NULL DEFAULT '0', +`atzo05` INT(11) NULL DEFAULT NULL, +`pos` BIGINT(21) NULL DEFAULT NULL, +`f5BnvB` INT(9) NULL DEFAULT NULL, +`f5atbvb` INT(11) NULL DEFAULT NULL, +`f5atbwmg` INT(11) NULL DEFAULT NULL, +`f5pBneu` BIGINT(12) NULL DEFAULT NULL, +`atbwdt` INT(11) NULL DEFAULT NULL, +`atbwzt` INT(11) NULL DEFAULT NULL, +`atbart` VARCHAR(10) NULL DEFAULT NULL +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; +ALTER TABLE `w_findispmon05u` +CHANGE COLUMN `atpkey` `f5atpkey` INT(11) NOT NULL DEFAULT '0' FIRST, +CHANGE COLUMN `atzo05` `f5atzo05` INT(11) NULL DEFAULT NULL AFTER `f5atpkey`, +CHANGE COLUMN `atbwdt` `f5atbwdt` INT(11) NULL DEFAULT NULL AFTER `f5pBneu`, +CHANGE COLUMN `atbwzt` `f5atbwzt` INT(11) NULL DEFAULT NULL AFTER `f5atbwdt`, +CHANGE COLUMN `atbart` `f5atbart` VARCHAR(10) NULL DEFAULT NULL AFTER `f5atbwzt`, +ADD INDEX `atpkey` (`f5atpkey`), +ADD INDEX `inatkey` (`f5atzo05`, `pos`), +ADD INDEX `pos` (`pos`, `f5atzo05`); +SHOW WARNINGS; +Level Code Message +SHOW CREATE TABLE `w_findispmon05u`; +Table Create Table +w_findispmon05u CREATE TABLE `w_findispmon05u` ( + `f5atpkey` int(11) NOT NULL DEFAULT '0', + `f5atzo05` int(11) DEFAULT NULL, + `pos` bigint(21) DEFAULT NULL, + `f5BnvB` int(9) DEFAULT NULL, + `f5atbvb` int(11) DEFAULT NULL, + `f5atbwmg` int(11) DEFAULT NULL, + `f5pBneu` bigint(12) DEFAULT NULL, + `f5atbwdt` int(11) DEFAULT NULL, + `f5atbwzt` int(11) DEFAULT NULL, + `f5atbart` varchar(10) DEFAULT NULL, + KEY `atpkey` (`f5atpkey`), + KEY `inatkey` (`f5atzo05`,`pos`), + KEY `pos` (`pos`,`f5atzo05`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 +DROP TABLE `w_findispmon05u`; +CREATE TABLE t ( +a INT NOT NULL, +b INT NOT NULL, +PRIMARY KEY (a) +) ENGINE=INNODB; +ALTER TABLE t +CHANGE COLUMN b c INT NOT NULL, +ADD UNIQUE INDEX (c); +SHOW WARNINGS; +Level Code Message +SHOW CREATE TABLE t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) NOT NULL, + `c` int(11) NOT NULL, + PRIMARY KEY (`a`), + UNIQUE KEY `c` (`c`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +ALTER TABLE t +CHANGE COLUMN c b INT NOT NULL, +ADD UNIQUE INDEX (c); +ERROR 42000: Key column 'c' doesn't exist in table +DROP TABLE t; +CREATE TABLE parent ( +a INT NOT NULL, +b INT NOT NULL, +PRIMARY KEY (a) +) ENGINE=INNODB; +CREATE TABLE child ( +a INT NOT NULL, +b INT NOT NULL, +PRIMARY KEY (a) +) ENGINE=INNODB; +ALTER TABLE child +CHANGE COLUMN b c INT NOT NULL, +ADD FOREIGN KEY (c) REFERENCES parent(a); +SHOW WARNINGS; +Level Code Message +SHOW CREATE TABLE child; +Table Create Table +child CREATE TABLE `child` ( + `a` int(11) NOT NULL, + `c` int(11) NOT NULL, + PRIMARY KEY (`a`), + KEY `c` (`c`), + CONSTRAINT `child_ibfk_1` FOREIGN KEY (`c`) REFERENCES `parent` (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE child, parent; diff --git a/mysql-test/suite/innodb/r/innodb_monitor.result b/mysql-test/suite/innodb/r/innodb_monitor.result index 31c6123c964..8c580348e1a 100644 --- a/mysql-test/suite/innodb/r/innodb_monitor.result +++ b/mysql-test/suite/innodb/r/innodb_monitor.result @@ -130,9 +130,6 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -281,9 +278,6 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -322,9 +316,6 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result index f6e35699d39..3280726729f 100644 --- a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result +++ b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result @@ -165,9 +165,6 @@ os_log_bytes_written os 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL di os_log_fsyncs os 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of fsync log writes (innodb_os_log_fsyncs) os_log_pending_fsyncs os 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of pending fsync write (innodb_os_log_pending_fsyncs) os_log_pending_writes os 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of pending log file writes (innodb_os_log_pending_writes) -os_merge_blocks_written os 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of merge blocks written (innodb_os_merge_blocks_written) -os_merge_blocks_read os 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of merge blocks read (innodb_os_merge_blocks_read) -os_merge_blocks_merged os 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of merge blocks merged (innodb_os_merge_blocks_merged) trx_rw_commits transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of read-write transactions committed trx_ro_commits transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of read-only transactions committed trx_nl_ro_commits transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of non-locking auto-commit read-only transactions committed @@ -379,7 +376,7 @@ space_id page_id start_lsn end_lsn Warnings: Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_changed_pages but the InnoDB storage engine is not installed select * from information_schema.innodb_tablespaces_encryption; -SPACE NAME ENCRYPTION_SCHEME KEYSERVER_REQUESTS MIN_KEY_VERSION CURRENT_KEY_VERSION KEY_ROTATION_PAGE_NUMBER KEY_ROTATION_MAX_PAGE_NUMBER +SPACE NAME ENCRYPTION_SCHEME KEYSERVER_REQUESTS MIN_KEY_VERSION CURRENT_KEY_VERSION KEY_ROTATION_PAGE_NUMBER KEY_ROTATION_MAX_PAGE_NUMBER CURRENT_KEY_ID Warnings: Warning 1012 InnoDB: SELECTing from INFORMATION_SCHEMA.innodb_tablespaces_encryption but the InnoDB storage engine is not installed select * from information_schema.innodb_tablespaces_scrubbing; diff --git a/mysql-test/suite/innodb/r/tmpdir.result b/mysql-test/suite/innodb/r/tmpdir.result new file mode 100644 index 00000000000..f9475c1b7f8 --- /dev/null +++ b/mysql-test/suite/innodb/r/tmpdir.result @@ -0,0 +1,51 @@ +# +# Bug #19183565 CREATE DYNAMIC INNODB_TMPDIR VARIABLE TO CONTROL +# WHERE INNODB WRITES TEMP FILES +# +# If innodb_tmpdir is NULL or "", temporary file will be created in +# server configuration variable location(--tmpdir) +create table t1(a int primary key)engine=innodb; +show session variables like 'innodb_tmpdir'; +Variable_name Value +innodb_tmpdir +alter table t1 add column b int not null; +set global innodb_tmpdir=NULL; +# Connection con1 +show session variables like 'innodb_tmpdir'; +Variable_name Value +innodb_tmpdir +alter table t1 add key(b); +drop table t1; +# innodb_tmpdir with invalid path. +create table t1(a int primary key)engine=innodb; +set global innodb_tmpdir='wrong_value'; +ERROR 42000: Variable 'innodb_tmpdir' can't be set to the value of 'wrong_value' +show warnings; +Level Code Message +Warning 1210 InnoDB: Path doesn't exist. +Error 1231 Variable 'innodb_tmpdir' can't be set to the value of 'wrong_value' +drop table t1; +# innodb_tmpdir with mysql data directory path. +create table t1(a text, b text, fulltext(a,b))engine=innodb; +insert into t1 values('test1', 'test2'); +insert into t1 values('text1', 'text2'); +set global innodb_tmpdir = @@global.datadir; +ERROR 42000: Variable 'innodb_tmpdir' can't be set to the value of 'MYSQL_DATADIR' +show warnings; +Level Code Message +Warning 1210 InnoDB: Path Location should not be same as mysql data directory location. +Error 1231 DATADIR/data/' +drop table t1; +# innodb_tmpdir with valid location. +create table t1(a text, b text, fulltext(a,b))engine=innodb; +insert into t1 values('test1', 'test2'); +insert into t1 values('text1', 'text2'); +set @tmpdir = @@global.tmpdir; +set global innodb_tmpdir = @tmpdir; +show session variables like 'innodb_tmpdir'; +Variable_name Value +innodb_tmpdir +# Connection con3 +alter table t1 add fulltext(b); +set global innodb_tmpdir=NULL; +drop table t1; diff --git a/mysql-test/suite/innodb/t/innodb-agregate.test b/mysql-test/suite/innodb/t/innodb-agregate.test new file mode 100644 index 00000000000..e15548c087a --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-agregate.test @@ -0,0 +1,18 @@ +--source include/have_innodb.inc + +# +# MDEV-9667: Server hangs after select count(distinct name) from t2 where a=8366 and b>=5 and b<=5; +# + +create table t2 (a smallint(6) not null, b int(10) not null, name varchar(20), primary key(a,b), key(name)) engine=InnoDB; + +insert into t2 values (8355,3,"sanja"),(8355,4,"wlad"),(8366,5, "lawrin"),(8366,6,"markusjm"); + +select count(distinct name) from t2 where a=8366 and b>=5 and b<=5; +select count(distinct name) from t2 where a=8366 and b=5; +select count(distinct name) from t2 where a=8366 and b between 5 and 5.5; +select sum(distinct a) from t2 where a=8366 and b>=5 and b<=5; +select sum(distinct a) from t2 where a=8366 and b=5; +select sum(distinct a) from t2 where a=8366 and b between 5 and 5.5; + +drop table t2; diff --git a/mysql-test/suite/innodb/t/innodb-alter-filewrite.test b/mysql-test/suite/innodb/t/innodb-alter-filewrite.test deleted file mode 100644 index d0372056937..00000000000 --- a/mysql-test/suite/innodb/t/innodb-alter-filewrite.test +++ /dev/null @@ -1,32 +0,0 @@ ---source include/have_innodb.inc - -# -# MDEV-8696: Adding indexes on empty table is slow with large innodb_sort_buffer_size. -# - -CREATE TABLE `test_wo_keys` ( -`f01` int AUTO_INCREMENT, -`f02` bigint, `f03` bigint, `f04` enum('a','b'), -`f05` date, `f06` int, `f07` int, `f08` double, `f09` int, -`f10` bigint, `f11` double, `f12` enum('a','b','c','d','e'), -`f13` int, `f14` int, `f15` varchar(255), `f16` int, `f17` int, `f18` int, -`f19` double, `f20` double, `f21` double, `f22` double, `f23` double, `f24` tinyint, -`f25` double, `f26` double, `f27` double, `f28` double, `f29` int unsigned, -`f30` int unsigned, `f31` bigint, `f32` int unsigned, `f33` bigint, -`f34` int unsigned, `f35` int unsigned, -PRIMARY KEY `f01` (`f01`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -show status like '%merge_buffers%'; - -ALTER TABLE test_wo_keys -ADD KEY `f06` (`f06`), ADD KEY `f05` (`f05`), ADD KEY `f04` (`f04`), ADD KEY `f23` (`f23`), -ADD KEY `f10` (`f10`), ADD KEY `f11` (`f11`), ADD KEY `f09` (`f09`), ADD KEY `f22` (`f22`), -ADD KEY `f21` (`f21`), ADD KEY `f07` (`f07`), ADD KEY `f08` (`f08`), ADD KEY `f18` (`f18`), -ADD KEY `f19` (`f19`), ADD KEY `f20` (`f20`), ADD KEY `f29` (`f29`,`f31`,`f33`), -ADD KEY `f35` (`f35`), ADD KEY `f25` (`f25`), ADD KEY `f26` (`f26`), -ADD KEY `f27` (`f27`), ADD KEY `f28` (`f28`); - -show status like '%merge_buffers%'; - -DROP TABLE test_wo_keys; diff --git a/mysql-test/suite/innodb/t/innodb-alter-table.test b/mysql-test/suite/innodb/t/innodb-alter-table.test index 2be2a30194d..2ad9c8791cb 100644 --- a/mysql-test/suite/innodb/t/innodb-alter-table.test +++ b/mysql-test/suite/innodb/t/innodb-alter-table.test @@ -57,3 +57,84 @@ while ($num) ALTER TABLE moodle19.mdl_course_modules ADD stefantest LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci AFTER showdescription; drop database moodle19; + +# +# Mdev-9469: Incorrect key file on alter table +# +use test; + +CREATE TABLE `w_findispmon05u` ( +`atpkey` INT(11) NOT NULL DEFAULT '0', +`atzo05` INT(11) NULL DEFAULT NULL, +`pos` BIGINT(21) NULL DEFAULT NULL, +`f5BnvB` INT(9) NULL DEFAULT NULL, +`f5atbvb` INT(11) NULL DEFAULT NULL, +`f5atbwmg` INT(11) NULL DEFAULT NULL, +`f5pBneu` BIGINT(12) NULL DEFAULT NULL, +`atbwdt` INT(11) NULL DEFAULT NULL, +`atbwzt` INT(11) NULL DEFAULT NULL, +`atbart` VARCHAR(10) NULL DEFAULT NULL +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; +ALTER TABLE `w_findispmon05u` +CHANGE COLUMN `atpkey` `f5atpkey` INT(11) NOT NULL DEFAULT '0' FIRST, +CHANGE COLUMN `atzo05` `f5atzo05` INT(11) NULL DEFAULT NULL AFTER `f5atpkey`, +CHANGE COLUMN `atbwdt` `f5atbwdt` INT(11) NULL DEFAULT NULL AFTER `f5pBneu`, +CHANGE COLUMN `atbwzt` `f5atbwzt` INT(11) NULL DEFAULT NULL AFTER `f5atbwdt`, +CHANGE COLUMN `atbart` `f5atbart` VARCHAR(10) NULL DEFAULT NULL AFTER `f5atbwzt`, +ADD INDEX `atpkey` (`f5atpkey`), +ADD INDEX `inatkey` (`f5atzo05`, `pos`), +ADD INDEX `pos` (`pos`, `f5atzo05`); + +SHOW WARNINGS; +SHOW CREATE TABLE `w_findispmon05u`; + +DROP TABLE `w_findispmon05u`; + +CREATE TABLE t ( + a INT NOT NULL, + b INT NOT NULL, + PRIMARY KEY (a) +) ENGINE=INNODB; + +ALTER TABLE t + CHANGE COLUMN b c INT NOT NULL, + ADD UNIQUE INDEX (c); + +SHOW WARNINGS; +SHOW CREATE TABLE t; + +# this should fail +--error 1072 +ALTER TABLE t + CHANGE COLUMN c b INT NOT NULL, + ADD UNIQUE INDEX (c); + +DROP TABLE t; + +# +# Check Foreign Keys +# +CREATE TABLE parent ( + a INT NOT NULL, + b INT NOT NULL, + PRIMARY KEY (a) +) ENGINE=INNODB; + +CREATE TABLE child ( + a INT NOT NULL, + b INT NOT NULL, + PRIMARY KEY (a) +) ENGINE=INNODB; + +ALTER TABLE child + CHANGE COLUMN b c INT NOT NULL, + ADD FOREIGN KEY (c) REFERENCES parent(a); + +SHOW WARNINGS; + +SHOW CREATE TABLE child; + +DROP TABLE child, parent; + diff --git a/mysql-test/suite/innodb/t/tmpdir.test b/mysql-test/suite/innodb/t/tmpdir.test new file mode 100644 index 00000000000..abe455adda5 --- /dev/null +++ b/mysql-test/suite/innodb/t/tmpdir.test @@ -0,0 +1,68 @@ +--source include/have_innodb.inc +--source include/count_sessions.inc + +if (`select plugin_auth_version <= "5.6.28-MariaDB-76.1" from information_schema.plugins where plugin_name='innodb'`) +{ + --skip Not fixed in XtraDB as of 5.6.28-MariaDB-76.1 or earlier +} + +--echo # +--echo # Bug #19183565 CREATE DYNAMIC INNODB_TMPDIR VARIABLE TO CONTROL +--echo # WHERE INNODB WRITES TEMP FILES +--echo # + +--echo # If innodb_tmpdir is NULL or "", temporary file will be created in +--echo # server configuration variable location(--tmpdir) + +create table t1(a int primary key)engine=innodb; +show session variables like 'innodb_tmpdir'; +alter table t1 add column b int not null; +set global innodb_tmpdir=NULL; +--echo # Connection con1 +connect (con1,localhost,root); +show session variables like 'innodb_tmpdir'; +alter table t1 add key(b); +connection default; +disconnect con1; +drop table t1; + +--echo # innodb_tmpdir with invalid path. + +create table t1(a int primary key)engine=innodb; +--error ER_WRONG_VALUE_FOR_VAR +set global innodb_tmpdir='wrong_value'; +show warnings; +drop table t1; + + +--echo # innodb_tmpdir with mysql data directory path. + +let $MYSQLD_DATADIR= `select @@datadir`; +create table t1(a text, b text, fulltext(a,b))engine=innodb; +insert into t1 values('test1', 'test2'); +insert into t1 values('text1', 'text2'); +--replace_result $MYSQLD_DATADIR MYSQL_DATADIR +--error ER_WRONG_VALUE_FOR_VAR +set global innodb_tmpdir = @@global.datadir; +--replace_regex /.*mysqld.1/DATADIR/ +show warnings; +drop table t1; + +--echo # innodb_tmpdir with valid location. +let $MYSQL_TMP_DIR= `select @@tmpdir`; +create table t1(a text, b text, fulltext(a,b))engine=innodb; +insert into t1 values('test1', 'test2'); +insert into t1 values('text1', 'text2'); +set @tmpdir = @@global.tmpdir; +set global innodb_tmpdir = @tmpdir; +show session variables like 'innodb_tmpdir'; +--echo # Connection con3 +connect (con3,localhost,root); +# Following alter using innodb_tmpdir as a path to create temporary files +alter table t1 add fulltext(b); +disconnect con3; +connection default; +set global innodb_tmpdir=NULL; +drop table t1; + +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/maria/encrypt-wrong-key.result b/mysql-test/suite/maria/encrypt-wrong-key.result new file mode 100644 index 00000000000..bc22481296d --- /dev/null +++ b/mysql-test/suite/maria/encrypt-wrong-key.result @@ -0,0 +1,16 @@ +call mtr.add_suppression("file_key_management"); +call mtr.add_suppression("System key id 1 is missing"); +call mtr.add_suppression("Unknown key id 1"); +call mtr.add_suppression("Failed to decrypt"); +CREATE TABLE t1 (i INT, KEY(i)) ENGINE=Aria; +INSERT INTO t1 VALUES (1); +repair table t1; +Table Op Msg_type Msg_text +test.t1 repair info Wrong CRC on datapage at 1 +test.t1 repair warning Number of rows changed from 1 to 0 +test.t1 repair status OK +INSERT INTO t1 VALUES (2); +select * from t1; +ERROR HY000: failed to decrypt './test/t1' rc: -1 dstlen: 0 size: 8172 + +drop table t1; diff --git a/mysql-test/suite/maria/encrypt-wrong-key.test b/mysql-test/suite/maria/encrypt-wrong-key.test new file mode 100644 index 00000000000..6f59952c1fa --- /dev/null +++ b/mysql-test/suite/maria/encrypt-wrong-key.test @@ -0,0 +1,54 @@ +--source include/not_embedded.inc + +# +# Test what happens if one removes a decryption key for Aria +# + +call mtr.add_suppression("file_key_management"); +call mtr.add_suppression("System key id 1 is missing"); +call mtr.add_suppression("Unknown key id 1"); +call mtr.add_suppression("Failed to decrypt"); + +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +--write_file $MYSQLTEST_VARDIR/keys1.txt +1;770A8A65DA156D24EE2A093277530142 +EOF + +--exec echo "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +CREATE TABLE t1 (i INT, KEY(i)) ENGINE=Aria; +INSERT INTO t1 VALUES (1); + +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +--write_file $MYSQLTEST_VARDIR/keys2.txt +2;770A8A65DA156D24EE2A093277530143 +EOF + +--exec echo "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys2.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +repair table t1; + +INSERT INTO t1 VALUES (2); + +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +--exec echo "restart:--aria-encrypt-tables=1 --plugin-load-add=file_key_management.so --file-key-management --file-key-management-filename=$MYSQLTEST_VARDIR/keys1.txt" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +--replace_result \\ / +--error 192 +select * from t1; +drop table t1; diff --git a/mysql-test/suite/multi_source/gtid_ignore_duplicates.test b/mysql-test/suite/multi_source/gtid_ignore_duplicates.test index 1eea038f8c9..4d98b5c2ee7 100644 --- a/mysql-test/suite/multi_source/gtid_ignore_duplicates.test +++ b/mysql-test/suite/multi_source/gtid_ignore_duplicates.test @@ -337,7 +337,7 @@ START SLAVE; --source include/wait_for_slave_to_start.inc --replace_result $gtid GTID eval SELECT MASTER_GTID_WAIT("$gtid", 30); -# The bug occured here, the slave would get an out-of-order binlog error +# The bug occurred here, the slave would get an out-of-order binlog error # due to trying to re-apply the 100-x-x transaction. # Restart stopped multi-source connections, and sync up. diff --git a/mysql-test/suite/parts/t/partition_debug_innodb-master.opt b/mysql-test/suite/parts/t/partition_debug_innodb-master.opt index 6daff4c7c6b..5253df4563a 100644 --- a/mysql-test/suite/parts/t/partition_debug_innodb-master.opt +++ b/mysql-test/suite/parts/t/partition_debug_innodb-master.opt @@ -1 +1 @@ ---loose-innodb-file-format-check --loose-innodb-file-per-table=1 --skip-stack-trace --skip-core-file +--loose-innodb-file-format-check --loose-innodb-file-per-table=1 --skip-stack-trace --skip-core-file --loose-innodb-buffer-pool-size=32M diff --git a/mysql-test/suite/perfschema/r/start_server_low_digest.result b/mysql-test/suite/perfschema/r/start_server_low_digest.result index ba71e4ea6b0..0e9632eac4b 100644 --- a/mysql-test/suite/perfschema/r/start_server_low_digest.result +++ b/mysql-test/suite/perfschema/r/start_server_low_digest.result @@ -6,7 +6,7 @@ SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 #################################### # QUERYING PS STATEMENT DIGEST #################################### -SELECT event_name, digest, digest_text, sql_text FROM events_statements_history_long; -event_name digest digest_text sql_text -statement/sql/truncate 9d8bb20bae9d3c7cdfd36bc9d78b1d63 TRUNCATE TABLE truncate table events_statements_history_long -statement/sql/select d4c5d748dcc95f29805e3c04d47d7f64 SELECT ? + ? + SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 +SELECT event_name, digest_text, sql_text FROM events_statements_history_long; +event_name digest_text sql_text +statement/sql/truncate TRUNCATE TABLE truncate table events_statements_history_long +statement/sql/select SELECT ? + ? + SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 diff --git a/mysql-test/suite/perfschema/r/view_table_io.result b/mysql-test/suite/perfschema/r/view_table_io.result index 5f17b5ae9e1..db6acf65c73 100644 --- a/mysql-test/suite/perfschema/r/view_table_io.result +++ b/mysql-test/suite/perfschema/r/view_table_io.result @@ -52,7 +52,7 @@ insert into marker set a = 1; optimize table test.v1; Table Op Msg_type Msg_text test.v1 optimize Error 'test.v1' is not BASE TABLE -test.v1 optimize error Corrupt +test.v1 optimize status Operation failed insert into marker set a = 1; select * from test.v1; a b diff --git a/mysql-test/suite/perfschema/t/dml_setup_instruments.test b/mysql-test/suite/perfschema/t/dml_setup_instruments.test index 8a4f11ba51f..6b4fe89a1cf 100644 --- a/mysql-test/suite/perfschema/t/dml_setup_instruments.test +++ b/mysql-test/suite/perfschema/t/dml_setup_instruments.test @@ -88,3 +88,10 @@ UNLOCK TABLES; --echo UPDATE performance_schema.setup_instruments SET timed='NO' ORDER BY RAND(); + +# MTR is configured to start with everything set to ON, +# so we need to restore it after the previous update +--disable_query_log +update performance_schema.setup_instruments set timed='YES'; +--enable_query_log + diff --git a/mysql-test/suite/perfschema/t/socket_summary_by_instance_func.test b/mysql-test/suite/perfschema/t/socket_summary_by_instance_func.test index bf04e62e1b5..99f89bd3225 100644 --- a/mysql-test/suite/perfschema/t/socket_summary_by_instance_func.test +++ b/mysql-test/suite/perfschema/t/socket_summary_by_instance_func.test @@ -1653,7 +1653,7 @@ if($print_details) --enable_result_log --horizontal_results --echo # Dump detailed differences after - before statement execution - --echo # 1. The statement executing connection and hopefully noone else + --echo # 1. The statement executing connection and hopefully no one else SELECT @default_object_instance_begin; SELECT EVENT_NAME, OBJECT_INSTANCE_BEGIN, COUNT_READ, SUM_NUMBER_OF_BYTES_READ, diff --git a/mysql-test/suite/perfschema/t/socket_summary_by_instance_func_win.test b/mysql-test/suite/perfschema/t/socket_summary_by_instance_func_win.test index cefaf1de549..0ecb51af203 100644 --- a/mysql-test/suite/perfschema/t/socket_summary_by_instance_func_win.test +++ b/mysql-test/suite/perfschema/t/socket_summary_by_instance_func_win.test @@ -1663,7 +1663,7 @@ if($print_details) --enable_result_log --horizontal_results --echo # Dump detailed differences after - before statement execution - --echo # 1. The statement executing connection and hopefully noone else + --echo # 1. The statement executing connection and hopefully no one else SELECT @default_object_instance_begin; SELECT EVENT_NAME, OBJECT_INSTANCE_BEGIN, COUNT_READ, SUM_NUMBER_OF_BYTES_READ, diff --git a/mysql-test/suite/perfschema/t/start_server_low_digest.test b/mysql-test/suite/perfschema/t/start_server_low_digest.test index 6f06def169b..f1ff90d2413 100644 --- a/mysql-test/suite/perfschema/t/start_server_low_digest.test +++ b/mysql-test/suite/perfschema/t/start_server_low_digest.test @@ -18,4 +18,4 @@ SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 --echo #################################### --echo # QUERYING PS STATEMENT DIGEST --echo #################################### -SELECT event_name, digest, digest_text, sql_text FROM events_statements_history_long; +SELECT event_name, digest_text, sql_text FROM events_statements_history_long; diff --git a/mysql-test/suite/perfschema/t/threads_mysql-master.opt b/mysql-test/suite/perfschema/t/threads_mysql-master.opt index f93413a61e5..00efa80d41e 100644 --- a/mysql-test/suite/perfschema/t/threads_mysql-master.opt +++ b/mysql-test/suite/perfschema/t/threads_mysql-master.opt @@ -1 +1 @@ ---event-scheduler +--event-scheduler --thread-cache-size=0 diff --git a/mysql-test/suite/plugins/r/cracklib_password_check.result b/mysql-test/suite/plugins/r/cracklib_password_check.result index 62f0e32b66a..638f138b986 100644 --- a/mysql-test/suite/plugins/r/cracklib_password_check.result +++ b/mysql-test/suite/plugins/r/cracklib_password_check.result @@ -11,15 +11,15 @@ PLUGIN_AUTHOR Sergei Golubchik PLUGIN_DESCRIPTION Password validation via CrackLib PLUGIN_LICENSE GPL LOAD_OPTION ON -PLUGIN_MATURITY Alpha +PLUGIN_MATURITY Gamma PLUGIN_AUTH_VERSION 1.0 -grant select on *.* to foobar identified by 'foobar'; +grant select on *.* to foocar identified by 'foocar'; ERROR HY000: Your password does not satisfy the current policy requirements show warnings; Level Code Message Warning 1819 cracklib: it is based on your username Error 1819 Your password does not satisfy the current policy requirements -grant select on *.* to foobar identified by 'raboof'; +grant select on *.* to foocar identified by 'racoof'; ERROR HY000: Your password does not satisfy the current policy requirements show warnings; Level Code Message diff --git a/mysql-test/suite/plugins/r/feedback_plugin_install.result b/mysql-test/suite/plugins/r/feedback_plugin_install.result index c52fdb8f85b..ee74435e05a 100644 --- a/mysql-test/suite/plugins/r/feedback_plugin_install.result +++ b/mysql-test/suite/plugins/r/feedback_plugin_install.result @@ -8,6 +8,7 @@ select * from information_schema.feedback where variable_name like 'feed%' VARIABLE_NAME VARIABLE_VALUE FEEDBACK used 1 FEEDBACK version 1.1 +FEEDBACK_HTTP_PROXY FEEDBACK_SEND_RETRY_WAIT 60 FEEDBACK_SEND_TIMEOUT 60 FEEDBACK_URL http://mariadb.org/feedback_plugin/post diff --git a/mysql-test/suite/plugins/r/server_audit.result b/mysql-test/suite/plugins/r/server_audit.result index bf71e518f97..2577a36cad4 100644 --- a/mysql-test/suite/plugins/r/server_audit.result +++ b/mysql-test/suite/plugins/r/server_audit.result @@ -8,6 +8,7 @@ server_audit_file_rotate_now OFF server_audit_file_rotate_size 1000000 server_audit_file_rotations 9 server_audit_incl_users +server_audit_loc_info server_audit_logging OFF server_audit_mode 0 server_audit_output_type file @@ -71,6 +72,7 @@ server_audit_file_rotate_now OFF server_audit_file_rotate_size 1000000 server_audit_file_rotations 9 server_audit_incl_users odin, root, dva, tri +server_audit_loc_info server_audit_logging ON server_audit_mode 0 server_audit_output_type file @@ -216,6 +218,7 @@ server_audit_file_rotate_now OFF server_audit_file_rotate_size 1000000 server_audit_file_rotations 9 server_audit_incl_users odin, root, dva, tri +server_audit_loc_info server_audit_logging ON server_audit_mode 1 server_audit_output_type file @@ -289,7 +292,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,proc, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0 -TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,sa_db,,0 +TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, diff --git a/mysql-test/suite/plugins/r/simple_password_check.result b/mysql-test/suite/plugins/r/simple_password_check.result index c74471a651a..a0b43a94137 100644 --- a/mysql-test/suite/plugins/r/simple_password_check.result +++ b/mysql-test/suite/plugins/r/simple_password_check.result @@ -11,7 +11,7 @@ PLUGIN_AUTHOR Sergei Golubchik PLUGIN_DESCRIPTION Simple password strength checks PLUGIN_LICENSE GPL LOAD_OPTION ON -PLUGIN_MATURITY Alpha +PLUGIN_MATURITY Gamma PLUGIN_AUTH_VERSION 1.0 select * from information_schema.system_variables where variable_name like 'simple_password_check%' order by 1; VARIABLE_NAME SIMPLE_PASSWORD_CHECK_DIGITS @@ -79,6 +79,7 @@ ERROR HY000: Your password does not satisfy the current policy requirements grant select on *.* to `BarFoo1!` identified by 'FooBar1!'; drop user `BarFoo1!`; create user foo1 identified by 'aA.12345'; +grant select on *.* to foo1; drop user foo1; set global simple_password_check_digits=3; set global simple_password_check_letters_same_case=3; @@ -129,7 +130,7 @@ ERROR HY000: The MariaDB server is running with the --strict-password-validation create user foo2 identified with mysql_native_password using ''; ERROR HY000: Your password does not satisfy the current policy requirements grant select on *.* to foo2 identified with mysql_old_password; -ERROR HY000: Your password does not satisfy the current policy requirements +ERROR 28000: Can't find any matching row in the user table update mysql.user set password='xxx' where user='foo1'; set global strict_password_validation=0; set password for foo1 = ''; diff --git a/mysql-test/suite/plugins/r/sql_error_log.result b/mysql-test/suite/plugins/r/sql_error_log.result index 3086b1f2d1f..a583cf91a83 100644 --- a/mysql-test/suite/plugins/r/sql_error_log.result +++ b/mysql-test/suite/plugins/r/sql_error_log.result @@ -35,6 +35,15 @@ SET SQL_MODE = ''; drop table t1; SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'not_exists' AND TABLE_NAME = 'not_exists'; TABLE_NAME +CREATE procedure e1() +BEGIN +START TRANSACTION; +INSERT INTO test.non_exists VALUES (0,0,0) /* e1 */; +COMMIT; +END| +CALL e1(); +ERROR 42S02: Table 'test.non_exists' doesn't exist +DROP PROCEDURE e1; uninstall plugin SQL_ERROR_LOG; Warnings: Warning 1620 Plugin is busy and will be uninstalled on shutdown @@ -45,3 +54,4 @@ TIME HOSTNAME ERROR 1000: new message : RESIGNAL SQLSTATE '40000' SET MYSQL_ERRNO = 1000, MESSAGE_TEXT = 'new message' TIME HOSTNAME ERROR 1366: Incorrect integer value: 'aa' for column 'id' at row 1 : insert into t1 values ('aa') +TIME HOSTNAME ERROR 1146: Table 'test.non_exists' doesn't exist : INSERT INTO test.non_exists VALUES (0,0,0) /* e1 */ diff --git a/mysql-test/suite/plugins/r/thread_pool_server_audit.result b/mysql-test/suite/plugins/r/thread_pool_server_audit.result index bf71e518f97..2577a36cad4 100644 --- a/mysql-test/suite/plugins/r/thread_pool_server_audit.result +++ b/mysql-test/suite/plugins/r/thread_pool_server_audit.result @@ -8,6 +8,7 @@ server_audit_file_rotate_now OFF server_audit_file_rotate_size 1000000 server_audit_file_rotations 9 server_audit_incl_users +server_audit_loc_info server_audit_logging OFF server_audit_mode 0 server_audit_output_type file @@ -71,6 +72,7 @@ server_audit_file_rotate_now OFF server_audit_file_rotate_size 1000000 server_audit_file_rotations 9 server_audit_incl_users odin, root, dva, tri +server_audit_loc_info server_audit_logging ON server_audit_mode 0 server_audit_output_type file @@ -216,6 +218,7 @@ server_audit_file_rotate_now OFF server_audit_file_rotate_size 1000000 server_audit_file_rotations 9 server_audit_incl_users odin, root, dva, tri +server_audit_loc_info server_audit_logging ON server_audit_mode 1 server_audit_output_type file @@ -289,7 +292,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,READ,mysql,proc, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proc, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,event, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop database sa_db',0 -TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,sa_db,,0 +TIME,HOSTNAME,root,localhost,ID,0,DISCONNECT,,,0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'create database sa_db',0 TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'use sa_db',0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,user, diff --git a/mysql-test/suite/plugins/t/cracklib_password_check.test b/mysql-test/suite/plugins/t/cracklib_password_check.test index a8f404009d0..d0e05fed926 100644 --- a/mysql-test/suite/plugins/t/cracklib_password_check.test +++ b/mysql-test/suite/plugins/t/cracklib_password_check.test @@ -12,11 +12,11 @@ select * from information_schema.plugins where plugin_name='cracklib_password_ch --horizontal_results --error ER_NOT_VALID_PASSWORD -grant select on *.* to foobar identified by 'foobar'; +grant select on *.* to foocar identified by 'foocar'; show warnings; --error ER_NOT_VALID_PASSWORD -grant select on *.* to foobar identified by 'raboof'; +grant select on *.* to foocar identified by 'racoof'; show warnings; --error ER_NOT_VALID_PASSWORD diff --git a/mysql-test/suite/plugins/t/simple_password_check.test b/mysql-test/suite/plugins/t/simple_password_check.test index c31e31154e3..9854f93efe8 100644 --- a/mysql-test/suite/plugins/t/simple_password_check.test +++ b/mysql-test/suite/plugins/t/simple_password_check.test @@ -26,6 +26,7 @@ grant select on *.* to `BarFoo1!` identified by 'FooBar1!'; drop user `BarFoo1!`; create user foo1 identified by 'aA.12345'; +grant select on *.* to foo1; drop user foo1; set global simple_password_check_digits=3; @@ -78,7 +79,7 @@ create user foo2 identified with mysql_native_password using '111111111111111111 grant select on *.* to foo2 identified with mysql_old_password using '2222222222222222'; --error ER_NOT_VALID_PASSWORD create user foo2 identified with mysql_native_password using ''; ---error ER_NOT_VALID_PASSWORD +--error ER_PASSWORD_NO_MATCH grant select on *.* to foo2 identified with mysql_old_password; # direct updates are not protected diff --git a/mysql-test/suite/plugins/t/sql_error_log.test b/mysql-test/suite/plugins/t/sql_error_log.test index a28e2d2e259..6c83e9655ce 100644 --- a/mysql-test/suite/plugins/t/sql_error_log.test +++ b/mysql-test/suite/plugins/t/sql_error_log.test @@ -48,6 +48,24 @@ drop table t1; SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'not_exists' AND TABLE_NAME = 'not_exists'; +# +# MDEV-6421 SQL_ERROR_LOG doesn't log comments in Events +# actually testing SP call is enough for that. + +DELIMITER |; + +CREATE procedure e1() +BEGIN + START TRANSACTION; + INSERT INTO test.non_exists VALUES (0,0,0) /* e1 */; + COMMIT; +END| + +DELIMITER ;| +--error ER_NO_SUCH_TABLE +CALL e1(); +DROP PROCEDURE e1; + uninstall plugin SQL_ERROR_LOG; let $MYSQLD_DATADIR= `SELECT @@datadir`; diff --git a/mysql-test/suite/roles/prepare_stmt_with_role.result b/mysql-test/suite/roles/prepare_stmt_with_role.result new file mode 100644 index 00000000000..e859b2e304b --- /dev/null +++ b/mysql-test/suite/roles/prepare_stmt_with_role.result @@ -0,0 +1,107 @@ +# +# Test user to check if we can grant the created role to it. +# +create user test_user; +# +# First create the role. +# +SET @createRole = 'CREATE ROLE developers'; +PREPARE stmtCreateRole FROM @createRole; +EXECUTE stmtCreateRole; +# +# Test to see if the role is created. +# +SELECT user, host,is_role FROM mysql.user +WHERE user = 'developers'; +user host is_role +developers Y +SHOW GRANTS; +Grants for root@localhost +GRANT developers TO 'root'@'localhost' WITH ADMIN OPTION +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION +# Test reexecution. +EXECUTE stmtCreateRole; +ERROR HY000: Operation CREATE ROLE failed for 'developers' +# +# Now grant the role to the test user. +# +SET @grantRole = 'GRANT developers to test_user'; +PREPARE stmtGrantRole FROM @grantRole; +EXECUTE stmtGrantRole; +# Test reexecution. +EXECUTE stmtGrantRole; +# +# We should see 2 entries in the roles_mapping table. +# +SELECT * FROM mysql.roles_mapping; +Host User Role Admin_option +% test_user developers N +localhost root developers Y +SHOW GRANTS FOR test_user; +Grants for test_user@% +GRANT developers TO 'test_user'@'%' +GRANT USAGE ON *.* TO 'test_user'@'%' +# +# Test revoking a role. +# +SET @revokeRole = 'REVOKE developers FROM test_user'; +PREPARE stmtRevokeRole FROM @revokeRole; +EXECUTE stmtRevokeRole; +EXECUTE stmtRevokeRole; +ERROR HY000: Cannot revoke role 'developers' from: 'test_user'@'%'. +SHOW GRANTS FOR test_user; +Grants for test_user@% +GRANT USAGE ON *.* TO 'test_user'@'%' +EXECUTE stmtGrantRole; +SHOW GRANTS FOR test_user; +Grants for test_user@% +GRANT developers TO 'test_user'@'%' +GRANT USAGE ON *.* TO 'test_user'@'%' +EXECUTE stmtRevokeRole; +SHOW GRANTS FOR test_user; +Grants for test_user@% +GRANT USAGE ON *.* TO 'test_user'@'%' +# +# Now drop the role. +# +SET @dropRole = 'DROP ROLE developers'; +PREPARE stmtDropRole FROM @dropRole; +EXECUTE stmtDropRole; +# +# Check both user and roles_mapping table for traces of our role. +# +SELECT user, host,is_role FROM mysql.user +WHERE user = 'developers'; +user host is_role +SELECT * FROM mysql.roles_mapping; +Host User Role Admin_option +SHOW GRANTS; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION +SHOW GRANTS FOR test_user; +Grants for test_user@% +GRANT USAGE ON *.* TO 'test_user'@'%' +# +# Test reexecution. +# +EXECUTE stmtCreateRole; +SELECT user, host,is_role FROM mysql.user +WHERE user = 'developers'; +user host is_role +developers Y +SELECT * FROM mysql.roles_mapping; +Host User Role Admin_option +localhost root developers Y +SHOW GRANTS; +Grants for root@localhost +GRANT developers TO 'root'@'localhost' WITH ADMIN OPTION +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION +SHOW GRANTS FOR test_user; +Grants for test_user@% +GRANT USAGE ON *.* TO 'test_user'@'%' +EXECUTE stmtDropRole; +# Cleanup. +DROP USER test_user; diff --git a/mysql-test/suite/roles/prepare_stmt_with_role.test b/mysql-test/suite/roles/prepare_stmt_with_role.test new file mode 100644 index 00000000000..516e9ddab34 --- /dev/null +++ b/mysql-test/suite/roles/prepare_stmt_with_role.test @@ -0,0 +1,85 @@ +--source include/not_embedded.inc + + +--echo # +--echo # Test user to check if we can grant the created role to it. +--echo # +create user test_user; +--echo # +--echo # First create the role. +--echo # +SET @createRole = 'CREATE ROLE developers'; +PREPARE stmtCreateRole FROM @createRole; +EXECUTE stmtCreateRole; +--echo # +--echo # Test to see if the role is created. +--echo # +SELECT user, host,is_role FROM mysql.user +WHERE user = 'developers'; +SHOW GRANTS; + +--echo # Test reexecution. +--error ER_CANNOT_USER +EXECUTE stmtCreateRole; + +--echo # +--echo # Now grant the role to the test user. +--echo # +SET @grantRole = 'GRANT developers to test_user'; +PREPARE stmtGrantRole FROM @grantRole; +EXECUTE stmtGrantRole; +--echo # Test reexecution. +EXECUTE stmtGrantRole; + +--echo # +--echo # We should see 2 entries in the roles_mapping table. +--echo # +--sorted_result +SELECT * FROM mysql.roles_mapping; +SHOW GRANTS FOR test_user; + +--echo # +--echo # Test revoking a role. +--echo # +SET @revokeRole = 'REVOKE developers FROM test_user'; +PREPARE stmtRevokeRole FROM @revokeRole; +EXECUTE stmtRevokeRole; +--error ER_CANNOT_REVOKE_ROLE +EXECUTE stmtRevokeRole; +SHOW GRANTS FOR test_user; + +EXECUTE stmtGrantRole; +SHOW GRANTS FOR test_user; +EXECUTE stmtRevokeRole; +SHOW GRANTS FOR test_user; + +--echo # +--echo # Now drop the role. +--echo # +SET @dropRole = 'DROP ROLE developers'; +PREPARE stmtDropRole FROM @dropRole; +EXECUTE stmtDropRole; + +--echo # +--echo # Check both user and roles_mapping table for traces of our role. +--echo # +SELECT user, host,is_role FROM mysql.user +WHERE user = 'developers'; +SELECT * FROM mysql.roles_mapping; +SHOW GRANTS; +SHOW GRANTS FOR test_user; + +--echo # +--echo # Test reexecution. +--echo # +EXECUTE stmtCreateRole; +SELECT user, host,is_role FROM mysql.user +WHERE user = 'developers'; +SELECT * FROM mysql.roles_mapping; + +SHOW GRANTS; +SHOW GRANTS FOR test_user; +EXECUTE stmtDropRole; + +--echo # Cleanup. +DROP USER test_user; diff --git a/mysql-test/suite/rpl/r/ignore_table_autoinc-9737.result b/mysql-test/suite/rpl/r/ignore_table_autoinc-9737.result new file mode 100644 index 00000000000..b036bde349a --- /dev/null +++ b/mysql-test/suite/rpl/r/ignore_table_autoinc-9737.result @@ -0,0 +1,19 @@ +include/master-slave.inc +[connection master] +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +create table t1(id int auto_increment primary key); +create table t2(id int auto_increment primary key); +create table slave_only(id int auto_increment primary key); +insert into slave_only values(NULL); +create trigger t1i after insert on t1 for each row insert into slave_only values(NULL); +stop slave; +set global replicate_ignore_table="test.t2"; +start slave; +insert into t2 values(NULL); +insert into t1 values(NULL); +drop table t1, t2, slave_only; +stop slave; +set global replicate_ignore_table=""; +start slave; +drop table t1, t2; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_autogen_query_multi_byte_char.result b/mysql-test/suite/rpl/r/rpl_autogen_query_multi_byte_char.result new file mode 100644 index 00000000000..b03c0057a69 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_autogen_query_multi_byte_char.result @@ -0,0 +1,29 @@ +include/master-slave.inc +[connection master] +Test case 1:- table name with one character latin name. +SET @s:=CONCAT("CREATE TABLE `",REPEAT(CHAR(131),1),"` (a INT)"); +PREPARE STMT FROM @s; +EXECUTE stmt; +SET @s:=CONCAT("INSERT INTO `",REPEAT(CHAR(131),1),"` VALUES (1)"); +PREPARE STMT FROM @s; +EXECUTE stmt; +SET @s:=CONCAT("DROP TABLE `",REPEAT(CHAR(131),1), "`"); +PREPARE STMT FROM @s; +EXECUTE stmt; +Test case 2:- table name and database names with one character latin name. +SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(131),1),"`"); +PREPARE STMT FROM @s; +EXECUTE stmt; +SET @s:=CONCAT("CREATE TABLE `",REPEAT(CHAR(131),1),"`.`",REPEAT(CHAR(131),1),"` (a INT)"); +PREPARE STMT FROM @s; +EXECUTE stmt; +SET @s:=CONCAT("INSERT INTO `",REPEAT(CHAR(131),1),"`.`",REPEAT(CHAR(131),1),"` VALUES (1)"); +PREPARE STMT FROM @s; +EXECUTE stmt; +SET @s:=CONCAT("DROP TABLE `",REPEAT(CHAR(131),1),"`.`",REPEAT(CHAR(131),1), "`"); +PREPARE STMT FROM @s; +EXECUTE stmt; +SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(131),1),"`"); +PREPARE STMT FROM @s; +EXECUTE stmt; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_checksum.result b/mysql-test/suite/rpl/r/rpl_checksum.result index b8c718ff821..bd5b23c2228 100644 --- a/mysql-test/suite/rpl/r/rpl_checksum.result +++ b/mysql-test/suite/rpl/r/rpl_checksum.result @@ -142,8 +142,8 @@ ERROR HY000: Can't generate a unique log-filename master-bin.(1-999) SET debug_dbug= @old_dbug; INSERT INTO t4 VALUES (2); include/wait_for_slave_sql_error.inc [errno=1590] -Last_SQL_Error = 'The incident LOST_EVENTS occured on the master. Message: error writing to the binary log' -FOUND /Slave SQL: The incident LOST_EVENTS occured on the master\. Message: error writing to the binary log, Internal MariaDB error code: 1590/ in mysqld.2.err +Last_SQL_Error = 'The incident LOST_EVENTS occurred on the master. Message: error writing to the binary log' +FOUND /Slave SQL: The incident LOST_EVENTS occurred on the master\. Message: error writing to the binary log, Internal MariaDB error code: 1590/ in mysqld.2.err SELECT * FROM t4 ORDER BY a; a 1 diff --git a/mysql-test/suite/rpl/r/rpl_gtid_errorlog.result b/mysql-test/suite/rpl/r/rpl_gtid_errorlog.result index ab615d0510a..e247ea9c2a7 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_errorlog.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_errorlog.result @@ -39,6 +39,6 @@ a 4 5 FOUND /Slave SQL: Error 'Duplicate entry .* on query\. .*Query: '.*', Gtid 0-1-100, Internal MariaDB error code:|Slave SQL: Could not execute Write_rows.*table test.t1; Duplicate entry.*, Gtid 0-1-100, Internal MariaDB error/ in mysqld.2.err -FOUND /Slave SQL: The incident LOST_EVENTS occured on the master\. Message: <none>, Internal MariaDB error code: 1590/ in mysqld.2.err +FOUND /Slave SQL: The incident LOST_EVENTS occurred on the master\. Message: <none>, Internal MariaDB error code: 1590/ in mysqld.2.err DROP TABLE t1; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_incident.result b/mysql-test/suite/rpl/r/rpl_incident.result index 5e725e36389..7cb8168c6a9 100644 --- a/mysql-test/suite/rpl/r/rpl_incident.result +++ b/mysql-test/suite/rpl/r/rpl_incident.result @@ -16,9 +16,9 @@ a 2 3 4 -call mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occured on the master.* 1590"); +call mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occurred on the master.* 1590"); include/wait_for_slave_sql_error.inc [errno=1590] -Last_SQL_Error = 'The incident LOST_EVENTS occured on the master. Message: <none>' +Last_SQL_Error = 'The incident LOST_EVENTS occurred on the master. Message: <none>' **** On Slave **** SELECT * FROM t1; a diff --git a/mysql-test/suite/rpl/r/rpl_mixed_binlog_max_cache_size.result b/mysql-test/suite/rpl/r/rpl_mixed_binlog_max_cache_size.result index 06f9f5617b5..80f76169472 100644 --- a/mysql-test/suite/rpl/r/rpl_mixed_binlog_max_cache_size.result +++ b/mysql-test/suite/rpl/r/rpl_mixed_binlog_max_cache_size.result @@ -151,7 +151,7 @@ include/start_slave.inc CALL mtr.add_suppression("Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage.*"); CALL mtr.add_suppression("Multi-statement transaction required more than 'max_binlog_stmt_cache_size' bytes of storage.*"); CALL mtr.add_suppression("Writing one row to the row-based binary log failed.*"); -CALL mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occured on the master. Message: error writing to the binary log"); +CALL mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occurred on the master. Message: error writing to the binary log"); TRUNCATE t1; SET GLOBAL max_binlog_cache_size= ORIGINAL_VALUE; SET GLOBAL binlog_cache_size= ORIGINAL_VALUE; diff --git a/mysql-test/suite/rpl/r/rpl_parallel.result b/mysql-test/suite/rpl/r/rpl_parallel.result index 6c904aefa92..631b071136b 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel.result +++ b/mysql-test/suite/rpl/r/rpl_parallel.result @@ -930,6 +930,8 @@ a 31 32 SET sql_slave_skip_counter= 1; +ERROR HY000: When using parallel replication and GTID with multiple replication domains, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position. +include/stop_slave_io.inc include/start_slave.inc include/sync_with_master_gtid.inc SELECT * FROM t2 WHERE a >= 30 ORDER BY a; diff --git a/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result b/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result index a4f76da1872..71edcd749e5 100644 --- a/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result +++ b/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result @@ -152,7 +152,7 @@ include/start_slave.inc CALL mtr.add_suppression("Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage.*"); CALL mtr.add_suppression("Multi-statement transaction required more than 'max_binlog_stmt_cache_size' bytes of storage.*"); CALL mtr.add_suppression("Writing one row to the row-based binary log failed.*"); -CALL mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occured on the master. Message: error writing to the binary log"); +CALL mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occurred on the master. Message: error writing to the binary log"); TRUNCATE t1; SET GLOBAL max_binlog_cache_size= ORIGINAL_VALUE; SET GLOBAL binlog_cache_size= ORIGINAL_VALUE; diff --git a/mysql-test/suite/rpl/r/rpl_row_flsh_tbls.result b/mysql-test/suite/rpl/r/rpl_row_flsh_tbls.result index 6aca4282ccd..27b23739831 100644 --- a/mysql-test/suite/rpl/r/rpl_row_flsh_tbls.result +++ b/mysql-test/suite/rpl/r/rpl_row_flsh_tbls.result @@ -22,7 +22,8 @@ include/wait_for_slave_to_stop.inc drop table t1; flush tables with read lock; start slave; -include/wait_for_slave_to_start.inc +include/wait_for_slave_param.inc [Slave_IO_Running] +include/wait_for_slave_sql_to_start.inc stop slave; ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction unlock tables; diff --git a/mysql-test/suite/rpl/r/rpl_row_triggers.result b/mysql-test/suite/rpl/r/rpl_row_triggers.result index 7f37805b635..b4ae9861633 100644 --- a/mysql-test/suite/rpl/r/rpl_row_triggers.result +++ b/mysql-test/suite/rpl/r/rpl_row_triggers.result @@ -237,4 +237,50 @@ a b 3 30 set global slave_run_triggers_for_rbr = @slave_run_triggers_for_rbr.saved; drop table t1, tlog; +# +# MDEV-8411 Assertion `is_stat_field || !table || (!table->write_set || +# bitmap_is_set(table->write_set, field_index) || +# bitmap_is_set(table->vcol_set, field_index))' +# failed in Field_timestamp::store_TIME_with_warning +# +# +# Create table on master, replicate it on slave. +# +connection master; +set @binlog_row_image.saved = @@binlog_row_image; +set binlog_row_image = MINIMAL; +create table t1 (pk int primary key, f int); +connection slave; +# +# Create a trigger on the slave. +# +create trigger tr before update on t1 for each row set new.f = 1000; +set @old_slave_run_triggers_for_rbr = @@global.slave_run_triggers_for_rbr; +set global slave_run_triggers_for_rbr = YES; +connection master; +# +# Update the table to have the trigger fire on the slave., +# +insert into t1 values (1,1),(2,2); +update t1 set pk=pk+10; +select * from t1; +pk f +11 1 +12 2 +connection slave; +# +# Check to see if slave has the table updated. +# +select * from t1; +pk f +11 1000 +12 1000 +# +# Cleanup +# +set global slave_run_triggers_for_rbr = @old_slave_run_triggers_for_rbr; +connection master; +set binlog_row_image = @binlog_row_image.saved; +drop table t1; +connection slave; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result b/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result index 0809af5f943..36d862dedce 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result @@ -14,6 +14,10 @@ DROP TABLE t1; [connection slave] include/install_semisync.inc [connection slave] +show global status like "Slave%_running"; +Variable_name Value +Slave_running ON +Slaves_running 1 UNINSTALL PLUGIN rpl_semi_sync_slave; Warnings: Warning 1620 Plugin is busy and will be uninstalled on shutdown @@ -21,6 +25,10 @@ select plugin_name,plugin_status from information_schema.plugins where plugin_na plugin_name plugin_status rpl_semi_sync_slave DELETED [connection master] +show global status like "Slave%_connect%"; +Variable_name Value +Slave_connections 2 +Slaves_connected 1 UNINSTALL PLUGIN rpl_semi_sync_master; Warnings: Warning 1620 Plugin is busy and will be uninstalled on shutdown diff --git a/mysql-test/suite/rpl/r/rpl_slow_query_log.result b/mysql-test/suite/rpl/r/rpl_slow_query_log.result index 79b83b4ceb9..2de0f5ccd82 100644 --- a/mysql-test/suite/rpl/r/rpl_slow_query_log.result +++ b/mysql-test/suite/rpl/r/rpl_slow_query_log.result @@ -76,6 +76,21 @@ ALTER TABLE t1 ADD INDEX id1(a); INSERT INTO t1 values(1, sleep(3)); ### Assertion is good. Both Master and Slave exhibit the ### same number of queries in slow log: 1 +******************************************************************** +**** TRUNCATE the slow log then check whether runtime changes of +**** log_slow_slave_statements work without slave restart. +******************************************************************** +SET @old_log_slow_slave_statements= @@global.log_slow_slave_statements; +SET @@global.log_slow_slave_statements = off; +TRUNCATE mysql.slow_log; +INSERT INTO t1 values(1, sleep(3));; +SELECT sql_text FROM mysql.slow_log WHERE sql_text like 'INSERT INTO t1 values(1, sleep(3))'; +sql_text +SET @@global.log_slow_slave_statements = on; +INSERT INTO t1 values(1, sleep(3));; +SELECT sql_text FROM mysql.slow_log WHERE sql_text like 'INSERT INTO t1 values(1, sleep(3))'; +sql_text +INSERT INTO t1 values(1, sleep(3)) SET @@global.log_output= @old_log_output; SET @@global.long_query_time= @old_long_query_time; DROP TABLE t1; diff --git a/mysql-test/suite/rpl/r/rpl_stm_binlog_max_cache_size.result b/mysql-test/suite/rpl/r/rpl_stm_binlog_max_cache_size.result index 06f9f5617b5..80f76169472 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_binlog_max_cache_size.result +++ b/mysql-test/suite/rpl/r/rpl_stm_binlog_max_cache_size.result @@ -151,7 +151,7 @@ include/start_slave.inc CALL mtr.add_suppression("Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage.*"); CALL mtr.add_suppression("Multi-statement transaction required more than 'max_binlog_stmt_cache_size' bytes of storage.*"); CALL mtr.add_suppression("Writing one row to the row-based binary log failed.*"); -CALL mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occured on the master. Message: error writing to the binary log"); +CALL mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occurred on the master. Message: error writing to the binary log"); TRUNCATE t1; SET GLOBAL max_binlog_cache_size= ORIGINAL_VALUE; SET GLOBAL binlog_cache_size= ORIGINAL_VALUE; diff --git a/mysql-test/suite/rpl/r/rpl_stm_flsh_tbls.result b/mysql-test/suite/rpl/r/rpl_stm_flsh_tbls.result index 6aca4282ccd..27b23739831 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_flsh_tbls.result +++ b/mysql-test/suite/rpl/r/rpl_stm_flsh_tbls.result @@ -22,7 +22,8 @@ include/wait_for_slave_to_stop.inc drop table t1; flush tables with read lock; start slave; -include/wait_for_slave_to_start.inc +include/wait_for_slave_param.inc [Slave_IO_Running] +include/wait_for_slave_sql_to_start.inc stop slave; ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction unlock tables; diff --git a/mysql-test/suite/rpl/r/rpl_unsafe_statements.result b/mysql-test/suite/rpl/r/rpl_unsafe_statements.result new file mode 100644 index 00000000000..2efb3eba2b1 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_unsafe_statements.result @@ -0,0 +1,53 @@ +include/master-slave.inc +[connection master] +CREATE TABLE t1(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TRIGGER trig1 AFTER INSERT ON t1 +FOR EACH ROW +INSERT INTO t2(i) VALUES(new.i); +START TRANSACTION; +INSERT INTO t2(i) VALUES (1); +ROLLBACK; +INSERT INTO t1(i) VALUES(2); +START TRANSACTION; +LOCK TABLES t1 WRITE, t2 WRITE; +INSERT INTO t1(i) VALUES(3); +UNLOCK TABLES; +COMMIT; +include/diff_tables.inc [master:t1, slave:t1] +include/diff_tables.inc [master:t2, slave:t2] +DROP TABLE t1,t2; +CREATE TABLE t1(i INT) ENGINE=INNODB; +CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB; +INSERT INTO t1 values (1), (2), (3); +START TRANSACTION; +INSERT INTO t2(i) VALUES (1); +ROLLBACK; +INSERT INTO t2(i) SELECT i FROM t1; +START TRANSACTION; +LOCK TABLES t2 WRITE, t1 READ; +INSERT INTO t2(i) SELECT i FROM t1; +UNLOCK TABLES; +COMMIT; +include/diff_tables.inc [master:t1, slave:t1] +include/diff_tables.inc [master:t2, slave:t2] +DROP TABLE t1,t2; +CREATE TABLE t1(i int, id INT AUTO_INCREMENT, PRIMARY KEY (i, id)) ENGINE=MYISAM; +INSERT INTO t1 (i) values (1); +START TRANSACTION; +LOCK TABLES t1 WRITE; +INSERT INTO t1 (i) values (2); +UNLOCK TABLES; +COMMIT; +include/diff_tables.inc [master:t1, slave:t1] +DROP TABLE t1; +CREATE TABLE t1(i INT, j INT, UNIQUE KEY(i), UNIQUE KEY(j)) ENGINE=INNODB; +INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1; +START TRANSACTION; +LOCK TABLES t1 WRITE; +INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1; +UNLOCK TABLES; +COMMIT; +include/diff_tables.inc [master:t1, slave:t1] +DROP TABLE t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/temporal_row-9560,old2new.rdiff b/mysql-test/suite/rpl/r/temporal_row-9560,old2new.rdiff new file mode 100644 index 00000000000..550f64173a7 --- /dev/null +++ b/mysql-test/suite/rpl/r/temporal_row-9560,old2new.rdiff @@ -0,0 +1,11 @@ +--- suite/rpl/r/temporal_row-9560.result ++++ suite/rpl/r/temporal_row-9560.reject +@@ -7,7 +7,7 @@ + insert into t1 values ('2016-02-15 12:50:06.123'); + select @@mysql56_temporal_format; + @@mysql56_temporal_format +-0 ++1 + select * from t1; + ts + 2016-02-15 12:50:06.123 diff --git a/mysql-test/suite/rpl/r/temporal_row-9560.result b/mysql-test/suite/rpl/r/temporal_row-9560.result new file mode 100644 index 00000000000..c6a57d43fd0 --- /dev/null +++ b/mysql-test/suite/rpl/r/temporal_row-9560.result @@ -0,0 +1,15 @@ +include/master-slave.inc +[connection master] +select @@mysql56_temporal_format; +@@mysql56_temporal_format +0 +create table t1 (ts timestamp(3), t time(3), dt datetime(3)); +insert into t1 values ('2016-02-15 12:50:06.123', '12:50:06.123', '2016-02-15 12:50:06.123'); +select @@mysql56_temporal_format; +@@mysql56_temporal_format +0 +select * from t1; +ts t dt +2016-02-15 12:50:06.123 12:50:06.123 2016-02-15 12:50:06.123 +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/ignore_table_autoinc-9737.test b/mysql-test/suite/rpl/t/ignore_table_autoinc-9737.test new file mode 100644 index 00000000000..405d1a929f1 --- /dev/null +++ b/mysql-test/suite/rpl/t/ignore_table_autoinc-9737.test @@ -0,0 +1,35 @@ +# +# MDEV-9737 Duplicate error in replication with slave triggers and auto increment +# +source include/master-slave.inc; +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); + + +create table t1(id int auto_increment primary key); +create table t2(id int auto_increment primary key); + +sync_slave_with_master; +create table slave_only(id int auto_increment primary key); +insert into slave_only values(NULL); +create trigger t1i after insert on t1 for each row insert into slave_only values(NULL); + +stop slave; +set global replicate_ignore_table="test.t2"; +start slave; + +connection master; +insert into t2 values(NULL); +insert into t1 values(NULL); + +sync_slave_with_master; + +drop table t1, t2, slave_only; +stop slave; +set global replicate_ignore_table=""; +start slave; + +connection master; +drop table t1, t2; + +source include/rpl_end.inc; + diff --git a/mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test b/mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test new file mode 100644 index 00000000000..a93fcbac82f --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_autogen_query_multi_byte_char.test @@ -0,0 +1,87 @@ +############################################################################### +# Bug#21205695 DROP TABLE MAY CAUSE SLAVES TO BREAK +# +# Problem: +# ======== +# 1) Drop table queries are re-generated by server +# before writing the events(queries) into binlog +# for various reasons. If table name/db name contains +# a non regular characters (like latin characters), +# the generated query is wrong. Hence it breaks the +# replication. +# 2) In the edge case, when table name contains +# 64 latin characters (latin takes 2 bytes), server is +# throwing an assert (M_TBLLEN < 128) +# +# 3) In the edge case, when db name contains 64 latin +# characters, binlog contents are interpreted wrongly +# which is leading to replication issues. +# +############################################################################### + +--source include/not_windows.inc +--source include/master-slave.inc + +--let iter=1 +# Change iteration to 4 after fixing Bug #22280214 +while ($iter <= 2) +{ + --connection master + if ($iter == 1) + { + --echo Test case 1:- table name with one character latin name. + --let $tblname= REPEAT(CHAR(131),1) + } + if ($iter == 2) + { + --echo Test case 2:- table name and database names with one character latin name. + --let $tblname= REPEAT(CHAR(131),1),"`.`",REPEAT(CHAR(131),1) + --eval SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(131),1),"`") + PREPARE STMT FROM @s; EXECUTE stmt; + } + # After fixing Bug #22280214 DATADIR LOCATION IS LIMITING + # IDENTIFIER MAX LENGTH, the following two tests (iter 3 and 4) can be + # uncommented. + #if ($iter == 3) + #{ + # --echo Test case 3:- table name and database names with 64 latin characters name. + # --let $tblname= REPEAT(CHAR(131),64),"`.`", REPEAT(CHAR(131),64) + # --eval SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(131),64),"`") + # PREPARE STMT FROM @s; EXECUTE stmt; + #} + #if ($iter == 4) + #{ + # --echo Test case 4:- table name and database names with 64 Euro(€) characters. + # --let $tblname= REPEAT(CHAR(226,130,172),64),"`.`", REPEAT(CHAR(226,130,172),64) + # --eval SET @s:=CONCAT("CREATE DATABASE `",REPEAT(CHAR(226,130,172),64),"`") + # PREPARE STMT FROM @s; EXECUTE stmt; + #} + --eval SET @s:=CONCAT("CREATE TABLE `",$tblname,"` (a INT)") + PREPARE STMT FROM @s; EXECUTE stmt; + --eval SET @s:=CONCAT("INSERT INTO `",$tblname,"` VALUES (1)") + PREPARE STMT FROM @s; EXECUTE stmt; + --eval SET @s:=CONCAT("DROP TABLE `",$tblname, "`") + PREPARE STMT FROM @s; EXECUTE stmt; + if ($iter == 2) + { + --eval SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(131),1),"`") + PREPARE STMT FROM @s; EXECUTE stmt; + } + # After fixing Bug #22280214 DATADIR LOCATION IS LIMITING + # IDENTIFIER MAX LENGTH, the following two tests (iter 3 and 4) can be + # uncommented. + #if ($iter == 3) + #{ + # --eval SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(131),64),"`") + # PREPARE STMT FROM @s; EXECUTE stmt; + #} + #if ($iter == 4) + #{ + # --eval SET @s:=CONCAT("DROP DATABASE `",REPEAT(CHAR(226,130,172),64),"`") + # PREPARE STMT FROM @s; EXECUTE stmt; + #} + --sync_slave_with_master + --inc $iter +} + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_checksum.test b/mysql-test/suite/rpl/t/rpl_checksum.test index ff7d2801911..50b6e712b90 100644 --- a/mysql-test/suite/rpl/t/rpl_checksum.test +++ b/mysql-test/suite/rpl/t/rpl_checksum.test @@ -299,7 +299,7 @@ if(!$log_error_) } --let SEARCH_FILE= $log_error_ --let SEARCH_RANGE=-50000 ---let SEARCH_PATTERN= Slave SQL: The incident LOST_EVENTS occured on the master\. Message: error writing to the binary log, Internal MariaDB error code: 1590 +--let SEARCH_PATTERN= Slave SQL: The incident LOST_EVENTS occurred on the master\. Message: error writing to the binary log, Internal MariaDB error code: 1590 --source include/search_pattern_in_file.inc SELECT * FROM t4 ORDER BY a; diff --git a/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test b/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test index 24298e9893a..137ac6c0f5d 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_errorlog.test @@ -66,7 +66,7 @@ if(!$log_error_) --let SEARCH_RANGE=-50000 --let SEARCH_PATTERN=Slave SQL: Error 'Duplicate entry .* on query\. .*Query: '.*', Gtid 0-1-100, Internal MariaDB error code:|Slave SQL: Could not execute Write_rows.*table test.t1; Duplicate entry.*, Gtid 0-1-100, Internal MariaDB error --source include/search_pattern_in_file.inc ---let SEARCH_PATTERN=Slave SQL: The incident LOST_EVENTS occured on the master\. Message: <none>, Internal MariaDB error code: 1590 +--let SEARCH_PATTERN=Slave SQL: The incident LOST_EVENTS occurred on the master\. Message: <none>, Internal MariaDB error code: 1590 --source include/search_pattern_in_file.inc diff --git a/mysql-test/suite/rpl/t/rpl_incident.test b/mysql-test/suite/rpl/t/rpl_incident.test index c591a8261c4..adf20953b0f 100644 --- a/mysql-test/suite/rpl/t/rpl_incident.test +++ b/mysql-test/suite/rpl/t/rpl_incident.test @@ -22,7 +22,7 @@ eval SET GLOBAL debug_dbug= '$debug_save'; connection slave; # Wait until SQL thread stops with error LOST_EVENT on master -call mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occured on the master.* 1590"); +call mtr.add_suppression("Slave SQL.*The incident LOST_EVENTS occurred on the master.* 1590"); let $slave_sql_errno= 1590; let $show_slave_sql_error= 1; source include/wait_for_slave_sql_error.inc; diff --git a/mysql-test/suite/rpl/t/rpl_parallel.test b/mysql-test/suite/rpl/t/rpl_parallel.test index 8a512848145..a7e5353a9fc 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel.test +++ b/mysql-test/suite/rpl/t/rpl_parallel.test @@ -1422,6 +1422,7 @@ SELECT * FROM t6 ORDER BY a; --connection server_1 INSERT INTO t2 VALUES (31); +--let $gtid1= `SELECT @@LAST_GTID` --source include/save_master_gtid.inc --connection server_2 @@ -1437,6 +1438,7 @@ SET sql_log_bin= 1; --connection server_1 INSERT INTO t2 VALUES (32); +--let $gtid2= `SELECT @@LAST_GTID` # Rotate the binlog; the bug is triggered when the master binlog file changes # after the event group that causes the duplicate key error. FLUSH LOGS; @@ -1469,7 +1471,12 @@ START SLAVE SQL_THREAD; SELECT * FROM t2 WHERE a >= 30 ORDER BY a; # Skip the duplicate error, so we can proceed. +--error ER_SLAVE_SKIP_NOT_IN_GTID SET sql_slave_skip_counter= 1; +--source include/stop_slave_io.inc +--disable_query_log +eval SET GLOBAL gtid_slave_pos = REPLACE(@@gtid_slave_pos, "$gtid1", "$gtid2"); +--enable_query_log --source include/start_slave.inc --source include/sync_with_master_gtid.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_triggers.test b/mysql-test/suite/rpl/t/rpl_row_triggers.test index e3c90d874f0..173ddebba12 100644 --- a/mysql-test/suite/rpl/t/rpl_row_triggers.test +++ b/mysql-test/suite/rpl/t/rpl_row_triggers.test @@ -276,5 +276,54 @@ drop table t1, tlog; sync_slave_with_master; +--echo # +--echo # MDEV-8411 Assertion `is_stat_field || !table || (!table->write_set || +--echo # bitmap_is_set(table->write_set, field_index) || +--echo # bitmap_is_set(table->vcol_set, field_index))' +--echo # failed in Field_timestamp::store_TIME_with_warning +--echo # +--enable_connect_log +--echo # +--echo # Create table on master, replicate it on slave. +--echo # +--connection master +set @binlog_row_image.saved = @@binlog_row_image; +set binlog_row_image = MINIMAL; +create table t1 (pk int primary key, f int); + +--sync_slave_with_master +--echo # +--echo # Create a trigger on the slave. +--echo # +create trigger tr before update on t1 for each row set new.f = 1000; +set @old_slave_run_triggers_for_rbr = @@global.slave_run_triggers_for_rbr; +set global slave_run_triggers_for_rbr = YES; + +--connection master +--echo # +--echo # Update the table to have the trigger fire on the slave., +--echo # +insert into t1 values (1,1),(2,2); +update t1 set pk=pk+10; +select * from t1; + +--sync_slave_with_master +--echo # +--echo # Check to see if slave has the table updated. +--echo # +select * from t1; + +--echo # +--echo # Cleanup +--echo # + +set global slave_run_triggers_for_rbr = @old_slave_run_triggers_for_rbr; + +--connection master +set binlog_row_image = @binlog_row_image.saved; +drop table t1; + +--sync_slave_with_master +--disable_connect_log --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test b/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test index 4ee345e54ba..0f86789cced 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test @@ -57,6 +57,8 @@ DROP TABLE t1; # possible at this state --connection slave --echo [connection slave] +show global status like "Slave%_running"; + UNINSTALL PLUGIN rpl_semi_sync_slave; select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%'; @@ -64,6 +66,10 @@ select plugin_name,plugin_status from information_schema.plugins where plugin_na # possible at this state --connection master --echo [connection master] + +# The following is to catch errors if the next uninstall plugin would succeed +show global status like "Slave%_connect%"; + UNINSTALL PLUGIN rpl_semi_sync_master; select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%'; diff --git a/mysql-test/suite/rpl/t/rpl_slow_query_log.test b/mysql-test/suite/rpl/t/rpl_slow_query_log.test index faf037a9dff..3505883c58e 100644 --- a/mysql-test/suite/rpl/t/rpl_slow_query_log.test +++ b/mysql-test/suite/rpl/t/rpl_slow_query_log.test @@ -299,6 +299,39 @@ if ($master_slow_query == $slave_slow_query) -- echo ### same number of queries in slow log: $master_slow_query } +-- echo ******************************************************************** +-- echo **** TRUNCATE the slow log then check whether runtime changes of +-- echo **** log_slow_slave_statements work without slave restart. +-- echo ******************************************************************** + +SET @old_log_slow_slave_statements= @@global.log_slow_slave_statements; +SET @@global.log_slow_slave_statements = off; +TRUNCATE mysql.slow_log; + +-- connection master + +--disable_warnings +-- eval $slow_query; +--enable_warnings +sync_slave_with_master; + +-- connection slave + +eval SELECT sql_text FROM mysql.slow_log WHERE sql_text like '$slow_query'; + +SET @@global.log_slow_slave_statements = on; + +-- connection master + +--disable_warnings +-- eval $slow_query; +--enable_warnings +sync_slave_with_master; + +-- connection slave + +eval SELECT sql_text FROM mysql.slow_log WHERE sql_text like '$slow_query'; + -- connection master SET @@global.log_output= @old_log_output; SET @@global.long_query_time= @old_long_query_time; diff --git a/mysql-test/suite/rpl/t/rpl_unsafe_statements.test b/mysql-test/suite/rpl/t/rpl_unsafe_statements.test new file mode 100644 index 00000000000..cbb4b54a220 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_unsafe_statements.test @@ -0,0 +1,176 @@ +################################################################################ +# Bug#17047208 REPLICATION DIFFERENCE FOR MULTIPLE TRIGGERS +# Problem: If DML invokes a trigger or a stored function that inserts into an +# AUTO_INCREMENT column, that DML has to be marked as 'unsafe' statement. If the +# tables are locked in the transaction prior to DML statement (using LOCK +# TABLES), then the DML statement is not marked as 'unsafe' statement. + +# Steps to reproduce the reported test case (BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS) +# Case-1: +# > Create a trigger on a table and do a insert in the trigger that updates +# auto increment column +# > A DML that executes the trigger in step.1 and check that DML is marked +# as unsafe and DML is written into binlog using row format (in MBR) +# > Execute the step 2 by locking the required tables prior to DML and check +# that DML is marked as unsafe and DML is written into binlog using row +# format (in MBR) +# +# This test script also adds test cases to cover few other unsafe statements. +# Case-2: BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT +# Case-3: BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST +# Case-4: BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS +################################################################################ + +--source include/have_innodb.inc +--source include/have_binlog_format_mixed.inc +--source include/master-slave.inc + +# Case-1: BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS +# Statement is unsafe because it invokes a trigger or a +# stored function that inserts into an AUTO_INCREMENT column. + +# Step-1.1: Create two tables, one with AUTO_INCREMENT column. +CREATE TABLE t1(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB; + +# Step-1.2: Create a trigger that inserts into an AUTO_INCREMENT column. +CREATE TRIGGER trig1 AFTER INSERT ON t1 +FOR EACH ROW + INSERT INTO t2(i) VALUES(new.i); + +# Step-1.3: Create some gap in auto increment value on master's t2 table +# but not on slave (by doing rollback). Just in case if the unsafe statements +# are written in statement format, diff tables will fail. +START TRANSACTION; +INSERT INTO t2(i) VALUES (1); +ROLLBACK; + +# Step-1.4: Insert a tuple into table t1 that triggers trig1 which inserts +# into an AUTO_INCREMENT column. +INSERT INTO t1(i) VALUES(2); + +# Step-1.5: Repeat step 1.4 but using 'LOCK TABLES' logic. +START TRANSACTION; +LOCK TABLES t1 WRITE, t2 WRITE; +INSERT INTO t1(i) VALUES(3); +UNLOCK TABLES; +COMMIT; + +# Step-1.6: Sync slave with master +--sync_slave_with_master + +# Step-1.7: Diff master-slave tables to make sure everything is in sync. +--let $diff_tables=master:t1, slave:t1 +--source include/diff_tables.inc + +--let $diff_tables=master:t2, slave:t2 +--source include/diff_tables.inc + +# Step-1.8: Cleanup +--connection master +DROP TABLE t1,t2; + +# Case-2: BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT +# Statements writing to a table with an auto-increment column after selecting +# from another table are unsafe because the order in which rows are retrieved +# determines what (if any) rows will be written. This order cannot be +# predicted and may differ on master and the slave. + +# Step-2.1: Create two tables, one with AUTO_INCREMENT column. +CREATE TABLE t1(i INT) ENGINE=INNODB; +CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB; + +# Step-2.2: Create some tuples in table t1. +INSERT INTO t1 values (1), (2), (3); + +# Step-2.3: Create some gap in auto increment value on master's t2 table +# but not on slave (by doing rollback). Just in case if the unsafe statements +# are written in statement format, diff tables will fail. +START TRANSACTION; +INSERT INTO t2(i) VALUES (1); +ROLLBACK; + +# Step-2.4: Insert into t2 (table with an auto-increment) by selecting tuples +# from table t1. +INSERT INTO t2(i) SELECT i FROM t1; + +# Step-2.5: Repeat step 2.4 but now with 'LOCK TABLES' logic. +START TRANSACTION; +LOCK TABLES t2 WRITE, t1 READ; +INSERT INTO t2(i) SELECT i FROM t1; +UNLOCK TABLES; +COMMIT; + +# Step-2.6: Sync slave with master +--sync_slave_with_master + +# Step-2.7: Diff master-slave tables to make sure everything is in sync. +--let $diff_tables=master:t1, slave:t1 +--source include/diff_tables.inc + +--let $diff_tables=master:t2, slave:t2 +--source include/diff_tables.inc + +# Step-2.8: Cleanup +--connection master +DROP TABLE t1,t2; + +# Case-3: BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST +# INSERT into autoincrement field which is not the first part in the +# composed primary key is unsafe +# +# Step-3.1: Create a table with auto increment column and a composed primary key +# (second column is auto increment column). Such a definition is allowed only +# with 'myisam' engine. +CREATE TABLE t1(i int, id INT AUTO_INCREMENT, PRIMARY KEY (i, id)) ENGINE=MYISAM; + +# Step-3.2: Inserting into such a table is unsafe. +INSERT INTO t1 (i) values (1); + +# Step-3.3: Repeat step 3.2, now with 'LOCK TABLES' logic. +START TRANSACTION; +LOCK TABLES t1 WRITE; +INSERT INTO t1 (i) values (2); +UNLOCK TABLES; +COMMIT; + +# Step-3.4: Sync slave with master +--sync_slave_with_master + +# Step-3.5: Diff master-slave tables to make sure everything is in sync. +--let $diff_tables=master:t1, slave:t1 +--source include/diff_tables.inc + +# Step-3.6: Cleanup +--connection master +DROP TABLE t1; + +# Case-4: BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS +# INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY +# is unsafe Statement + +# Step-4.1: Create a table with two unique keys +CREATE TABLE t1(i INT, j INT, UNIQUE KEY(i), UNIQUE KEY(j)) ENGINE=INNODB; + +# Step-4.2: Inserting into such a table is unsafe. +INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1; + +# Step-4.3: Repeat step 3.2, now with 'LOCK TABLES' logic. +START TRANSACTION; +LOCK TABLES t1 WRITE; +INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1; +UNLOCK TABLES; +COMMIT; + +# Step-4.4: Sync slave with master +--sync_slave_with_master + +# Step-4.5: Diff master-slave tables to make sure everything is in sync. +--let $diff_tables=master:t1, slave:t1 +--source include/diff_tables.inc + +# Step-4.6: Cleanup +--connection master +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/temporal_row-9560-master.opt b/mysql-test/suite/rpl/t/temporal_row-9560-master.opt new file mode 100644 index 00000000000..07c4494e8b6 --- /dev/null +++ b/mysql-test/suite/rpl/t/temporal_row-9560-master.opt @@ -0,0 +1 @@ +--disable-mysql56-temporal-format diff --git a/mysql-test/suite/rpl/t/temporal_row-9560.combinations b/mysql-test/suite/rpl/t/temporal_row-9560.combinations new file mode 100644 index 00000000000..b1c360f8615 --- /dev/null +++ b/mysql-test/suite/rpl/t/temporal_row-9560.combinations @@ -0,0 +1,6 @@ +[old2old] +--disable-mysql56-temporal-format + +[old2new] +--enable-mysql56-temporal-format + diff --git a/mysql-test/suite/rpl/t/temporal_row-9560.test b/mysql-test/suite/rpl/t/temporal_row-9560.test new file mode 100644 index 00000000000..00fb59bc088 --- /dev/null +++ b/mysql-test/suite/rpl/t/temporal_row-9560.test @@ -0,0 +1,20 @@ +# +# MDEV-9560 Mariadb 10.1 Crashes when replicating from 10.0 +# +source include/have_binlog_format_row.inc; +source include/master-slave.inc; + +select @@mysql56_temporal_format; +create table t1 (ts timestamp(3), t time(3), dt datetime(3)); +insert into t1 values ('2016-02-15 12:50:06.123', '12:50:06.123', '2016-02-15 12:50:06.123'); + +sync_slave_with_master; + +select @@mysql56_temporal_format; +select * from t1; + +connection master; +drop table t1; + +source include/rpl_end.inc; + diff --git a/mysql-test/suite/stress/include/ddl1.inc b/mysql-test/suite/stress/include/ddl1.inc index 96adadc5af5..00e64cee395 100644 --- a/mysql-test/suite/stress/include/ddl1.inc +++ b/mysql-test/suite/stress/include/ddl1.inc @@ -111,10 +111,10 @@ # # 6. Hints for analysis of test failures: # 1. Look into the protocol and check in which ddl*.inc -# script the difference to the expected result occured. +# script the difference to the expected result occurred. # 2. Comment the sourcing of all other ddl*.inc scripts # out. -# 3. Edit the ddl*.inc script where the error occured and +# 3. Edit the ddl*.inc script where the error occurred and # remove all # - "--disable_query_log", "--disable_result_log" # - successful passed subtests. diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result index d3d36b2d40e..6c7051dc3d0 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result @@ -130,9 +130,6 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -281,9 +278,6 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -322,9 +316,6 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result index d3d36b2d40e..6c7051dc3d0 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result @@ -130,9 +130,6 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -281,9 +278,6 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -322,9 +316,6 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result index d3d36b2d40e..6c7051dc3d0 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result @@ -130,9 +130,6 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -281,9 +278,6 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -322,9 +316,6 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result index d3d36b2d40e..6c7051dc3d0 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result @@ -130,9 +130,6 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs disabled os_log_pending_writes disabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled trx_rw_commits disabled trx_ro_commits disabled trx_nl_ro_commits disabled @@ -281,9 +278,6 @@ lock_row_lock_time disabled lock_row_lock_time_max disabled lock_row_lock_waits disabled lock_row_lock_time_avg disabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled innodb_rwlock_s_spin_waits disabled innodb_rwlock_x_spin_waits disabled innodb_rwlock_s_spin_rounds disabled @@ -322,9 +316,6 @@ os_log_bytes_written disabled os_log_fsyncs disabled os_log_pending_fsyncs enabled os_log_pending_writes enabled -os_merge_blocks_written disabled -os_merge_blocks_read disabled -os_merge_blocks_merged disabled set global innodb_monitor_enable=""; ERROR 42000: Variable 'innodb_monitor_enable' can't be set to the value of '' set global innodb_monitor_enable="_"; diff --git a/mysql-test/suite/sys_vars/r/innodb_thread_sleep_delay_basic.result b/mysql-test/suite/sys_vars/r/innodb_thread_sleep_delay_basic.result index 0335db8e859..ebb99559255 100644 --- a/mysql-test/suite/sys_vars/r/innodb_thread_sleep_delay_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_thread_sleep_delay_basic.result @@ -42,7 +42,9 @@ ERROR 42000: Incorrect argument type to variable 'innodb_thread_sleep_delay' set global innodb_thread_sleep_delay="foo"; ERROR 42000: Incorrect argument type to variable 'innodb_thread_sleep_delay' set global innodb_thread_sleep_delay=18446744073709551616; -ERROR 42000: Incorrect argument type to variable 'innodb_thread_sleep_delay' +Warnings: +Warning 1916 Got overflow when converting '18446744073709551616' to INT. Value truncated. +Warning 1292 Truncated incorrect innodb_thread_sleep_delay value: '9223372036854775807' set global innodb_thread_sleep_delay=-7; Warnings: Warning 1292 Truncated incorrect innodb_thread_sleep_delay value: '-7' diff --git a/mysql-test/suite/sys_vars/r/innodb_tmpdir_basic.result b/mysql-test/suite/sys_vars/r/innodb_tmpdir_basic.result new file mode 100644 index 00000000000..be10c93b56b --- /dev/null +++ b/mysql-test/suite/sys_vars/r/innodb_tmpdir_basic.result @@ -0,0 +1,35 @@ +SET @start_global_value = @@global.innodb_tmpdir; +SELECT @start_global_value; +@start_global_value +NULL +select @@session.innodb_tmpdir; +@@session.innodb_tmpdir +NULL +show global variables like 'innodb_tmpdir'; +Variable_name Value +innodb_tmpdir +show session variables like 'innodb_tmpdir'; +Variable_name Value +innodb_tmpdir +select * from information_schema.global_variables where variable_name='innodb_tmpdir'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_TMPDIR +select * from information_schema.session_variables where variable_name='innodb_tmpdir'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_TMPDIR +set global innodb_tmpdir=@@global.tmpdir; +set session innodb_tmpdir=@@global.tmpdir; +set global innodb_tmpdir=1.1; +ERROR 42000: Incorrect argument type to variable 'innodb_tmpdir' +set global innodb_tmpdir=1e1; +ERROR 42000: Incorrect argument type to variable 'innodb_tmpdir' +set global innodb_tmpdir=repeat('a',1000); +ERROR 42000: Variable 'innodb_tmpdir' can't be set to the value of 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +show warnings; +Level Code Message +Warning 1210 Path length should not exceed 512 bytes +Error 1231 Variable 'innodb_tmpdir' can't be set to the value of 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +SET @@global.innodb_tmpdir = @start_global_value; +SELECT @@global.innodb_tmpdir; +@@global.innodb_tmpdir +NULL diff --git a/mysql-test/suite/sys_vars/r/log_slow_admin_statements_func.result b/mysql-test/suite/sys_vars/r/log_slow_admin_statements_func.result new file mode 100644 index 00000000000..daddc4af627 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/log_slow_admin_statements_func.result @@ -0,0 +1,46 @@ +SET @old_log_output= @@global.log_output; +SET @old_slow_query_log= @@global.slow_query_log; +SET @old_long_query_time= @@session.long_query_time; +SET @old_log_slow_admin_statements= @@global.log_slow_admin_statements; +USE test; +CREATE TABLE log_slow_admin_statements ( +i INT PRIMARY KEY AUTO_INCREMENT, +j VARCHAR(255) +) ENGINE=InnoDB; +SET GLOBAL log_output = 'file,table'; +SET GLOBAL slow_query_log = on; +SET SESSION long_query_time = 0; +SET GLOBAL log_slow_admin_statements = on; +ALTER TABLE log_slow_admin_statements ADD COLUMN k INT DEFAULT 17; +CREATE PROCEDURE add_rows() +BEGIN +DECLARE count INT; +SET count = 1; +INSERT INTO log_slow_admin_statements(j) values (REPEAT('A', 255)); +WHILE count <= 15 DO +INSERT INTO log_slow_admin_statements(j) SELECT j FROM log_slow_admin_statements; +SET count = count + 1; +END WHILE; +END +$ +CALL add_rows(); +OPTIMIZE TABLE log_slow_admin_statements; +Table Op Msg_type Msg_text +test.log_slow_admin_statements optimize note Table does not support optimize, doing recreate + analyze instead +test.log_slow_admin_statements optimize status OK +CHECK TABLE log_slow_admin_statements EXTENDED; +Table Op Msg_type Msg_text +test.log_slow_admin_statements check status OK +DROP TABLE log_slow_admin_statements; +SELECT sql_text FROM mysql.slow_log WHERE sql_text LIKE '%TABLE log_slow_admin_statements%'; +sql_text +ALTER TABLE log_slow_admin_statements ADD COLUMN k INT DEFAULT 17 +OPTIMIZE TABLE log_slow_admin_statements +CHECK TABLE log_slow_admin_statements EXTENDED +DROP TABLE log_slow_admin_statements +SET @@global.log_output= @old_log_output; +SET @@global.slow_query_log= @old_slow_query_log; +SET @@session.long_query_time= @old_long_query_time; +SET @@global.log_slow_admin_statements= @old_log_slow_admin_statements; +DROP PROCEDURE add_rows; +TRUNCATE TABLE mysql.slow_log; diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff index 4ac8b9fb53b..cad46e36f42 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff @@ -1119,14 +1119,21 @@ VARIABLE_COMMENT Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1000000 -@@ -2203,6 +2637,34 @@ +@@ -2203,14 +2637,28 @@ ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +-VARIABLE_NAME INNODB_TMPDIR +-SESSION_VALUE +-GLOBAL_VALUE +VARIABLE_NAME INNODB_TRACK_CHANGED_PAGES +SESSION_VALUE NULL +GLOBAL_VALUE OFF -+GLOBAL_VALUE_ORIGIN COMPILE-TIME + GLOBAL_VALUE_ORIGIN COMPILE-TIME +-DEFAULT_VALUE +-VARIABLE_SCOPE SESSION +-VARIABLE_TYPE VARCHAR +-VARIABLE_COMMENT Directory for temporary non-tablespace files. +DEFAULT_VALUE OFF +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN @@ -1145,16 +1152,10 @@ +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Force log tracker to catch up with checkpoint now -+NUMERIC_MIN_VALUE NULL -+NUMERIC_MAX_VALUE NULL -+NUMERIC_BLOCK_SIZE NULL -+ENUM_VALUE_LIST NULL -+READ_ONLY NO -+COMMAND_LINE_ARGUMENT OPTIONAL - VARIABLE_NAME INNODB_TRX_PURGE_VIEW_UPDATE_ONLY_DEBUG - SESSION_VALUE NULL - GLOBAL_VALUE OFF -@@ -2251,7 +2713,7 @@ + NUMERIC_MIN_VALUE NULL + NUMERIC_MAX_VALUE NULL + NUMERIC_BLOCK_SIZE NULL +@@ -2265,7 +2713,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 128 VARIABLE_SCOPE GLOBAL @@ -1163,7 +1164,7 @@ VARIABLE_COMMENT Number of undo logs to use. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 128 -@@ -2265,7 +2727,7 @@ +@@ -2279,7 +2727,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -1172,7 +1173,7 @@ VARIABLE_COMMENT Number of undo tablespaces to use. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 126 -@@ -2280,7 +2742,7 @@ +@@ -2294,7 +2742,7 @@ DEFAULT_VALUE OFF VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN @@ -1181,7 +1182,7 @@ NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -@@ -2301,6 +2763,20 @@ +@@ -2315,6 +2763,20 @@ ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT NONE @@ -1202,7 +1203,7 @@ VARIABLE_NAME INNODB_USE_MTFLUSH SESSION_VALUE NULL GLOBAL_VALUE OFF -@@ -2315,6 +2791,20 @@ +@@ -2329,6 +2791,20 @@ ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT NONE @@ -1223,12 +1224,12 @@ VARIABLE_NAME INNODB_USE_SYS_MALLOC SESSION_VALUE NULL GLOBAL_VALUE ON -@@ -2345,12 +2835,12 @@ +@@ -2359,12 +2835,12 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_VERSION SESSION_VALUE NULL --GLOBAL_VALUE 5.6.27 -+GLOBAL_VALUE 5.6.26-76.0 +-GLOBAL_VALUE 5.6.29 ++GLOBAL_VALUE 5.6.28-76.1 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE NULL VARIABLE_SCOPE GLOBAL @@ -1238,7 +1239,7 @@ NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -@@ -2363,7 +2853,7 @@ +@@ -2377,7 +2853,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 4 VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff index 520728d3def..a9e975313db 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff @@ -571,14 +571,21 @@ NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -@@ -2203,6 +2637,34 @@ +@@ -2203,14 +2637,28 @@ ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +-VARIABLE_NAME INNODB_TMPDIR +-SESSION_VALUE +-GLOBAL_VALUE +VARIABLE_NAME INNODB_TRACK_CHANGED_PAGES +SESSION_VALUE NULL +GLOBAL_VALUE OFF -+GLOBAL_VALUE_ORIGIN COMPILE-TIME + GLOBAL_VALUE_ORIGIN COMPILE-TIME +-DEFAULT_VALUE +-VARIABLE_SCOPE SESSION +-VARIABLE_TYPE VARCHAR +-VARIABLE_COMMENT Directory for temporary non-tablespace files. +DEFAULT_VALUE OFF +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN @@ -597,16 +604,10 @@ +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Force log tracker to catch up with checkpoint now -+NUMERIC_MIN_VALUE NULL -+NUMERIC_MAX_VALUE NULL -+NUMERIC_BLOCK_SIZE NULL -+ENUM_VALUE_LIST NULL -+READ_ONLY NO -+COMMAND_LINE_ARGUMENT OPTIONAL - VARIABLE_NAME INNODB_TRX_PURGE_VIEW_UPDATE_ONLY_DEBUG - SESSION_VALUE NULL - GLOBAL_VALUE OFF -@@ -2280,7 +2742,7 @@ + NUMERIC_MIN_VALUE NULL + NUMERIC_MAX_VALUE NULL + NUMERIC_BLOCK_SIZE NULL +@@ -2294,7 +2742,7 @@ DEFAULT_VALUE OFF VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN @@ -615,7 +616,7 @@ NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -@@ -2301,6 +2763,20 @@ +@@ -2315,6 +2763,20 @@ ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT NONE @@ -636,7 +637,7 @@ VARIABLE_NAME INNODB_USE_MTFLUSH SESSION_VALUE NULL GLOBAL_VALUE OFF -@@ -2315,6 +2791,20 @@ +@@ -2329,6 +2791,20 @@ ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT NONE @@ -657,12 +658,12 @@ VARIABLE_NAME INNODB_USE_SYS_MALLOC SESSION_VALUE NULL GLOBAL_VALUE ON -@@ -2345,12 +2835,12 @@ +@@ -2359,12 +2835,12 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_VERSION SESSION_VALUE NULL --GLOBAL_VALUE 5.6.27 -+GLOBAL_VALUE 5.6.26-76.0 +-GLOBAL_VALUE 5.6.29 ++GLOBAL_VALUE 5.6.28-76.1 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE NULL VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index b2e31ab3979..0ddc401e618 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -2203,6 +2203,20 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME INNODB_TMPDIR +SESSION_VALUE +GLOBAL_VALUE +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE +VARIABLE_SCOPE SESSION +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Directory for temporary non-tablespace files. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_TRX_PURGE_VIEW_UPDATE_ONLY_DEBUG SESSION_VALUE NULL GLOBAL_VALUE OFF @@ -2345,7 +2359,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_VERSION SESSION_VALUE NULL -GLOBAL_VALUE 5.6.27 +GLOBAL_VALUE 5.6.29 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE NULL VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff index 986531a6dd4..d2b99e23514 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff @@ -296,7 +296,7 @@ VARIABLE_COMMENT Timeout in seconds to wait for a lock before returning an error. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -1681,7 +1681,7 @@ +@@ -1695,7 +1695,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -305,7 +305,7 @@ VARIABLE_COMMENT Write to slow log every #th slow query. Set to 1 to log everything. Increase it to reduce the size of the slow or the performance impact of slow logging NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1709,7 +1709,7 @@ +@@ -1737,7 +1737,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -314,7 +314,7 @@ VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1751,7 +1751,7 @@ +@@ -1779,7 +1779,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4194304 VARIABLE_SCOPE SESSION @@ -323,7 +323,7 @@ VARIABLE_COMMENT Max packet length to send to or receive from the server NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -1761,14 +1761,14 @@ +@@ -1789,14 +1789,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_BINLOG_CACHE_SIZE SESSION_VALUE NULL @@ -341,7 +341,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1779,7 +1779,7 @@ +@@ -1807,7 +1807,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1073741824 VARIABLE_SCOPE GLOBAL @@ -350,7 +350,7 @@ VARIABLE_COMMENT Binary log will be rotated automatically when the size exceeds this value. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 1073741824 -@@ -1789,14 +1789,14 @@ +@@ -1817,14 +1817,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_BINLOG_STMT_CACHE_SIZE SESSION_VALUE NULL @@ -368,7 +368,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1807,7 +1807,7 @@ +@@ -1835,7 +1835,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 151 VARIABLE_SCOPE GLOBAL @@ -377,7 +377,7 @@ VARIABLE_COMMENT The number of simultaneous clients allowed NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 100000 -@@ -1821,7 +1821,7 @@ +@@ -1849,7 +1849,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -386,7 +386,7 @@ VARIABLE_COMMENT If there is more than this number of interrupted connections from a host this host will be blocked from further connections NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1835,7 +1835,7 @@ +@@ -1863,7 +1863,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 20 VARIABLE_SCOPE SESSION @@ -395,7 +395,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -1863,7 +1863,7 @@ +@@ -1891,7 +1891,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 64 VARIABLE_SCOPE SESSION @@ -404,7 +404,7 @@ VARIABLE_COMMENT Max number of errors/warnings to store for a statement NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -1880,7 +1880,7 @@ +@@ -1908,7 +1908,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't allow creation of heap tables bigger than this NUMERIC_MIN_VALUE 16384 @@ -413,7 +413,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1891,7 +1891,7 @@ +@@ -1919,7 +1919,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 20 VARIABLE_SCOPE SESSION @@ -422,7 +422,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -1919,7 +1919,7 @@ +@@ -1947,7 +1947,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE SESSION @@ -431,7 +431,7 @@ VARIABLE_COMMENT Max number of bytes in sorted records NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -1933,7 +1933,7 @@ +@@ -1961,7 +1961,7 @@ GLOBAL_VALUE_ORIGIN AUTO DEFAULT_VALUE 1048576 VARIABLE_SCOPE GLOBAL @@ -440,7 +440,7 @@ VARIABLE_COMMENT The maximum BLOB length to send to server from mysql_send_long_data API. Deprecated option; use max_allowed_packet instead. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -1947,7 +1947,7 @@ +@@ -1975,7 +1975,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16382 VARIABLE_SCOPE GLOBAL @@ -449,7 +449,7 @@ VARIABLE_COMMENT Maximum number of prepared statements in the server NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -1961,7 +1961,7 @@ +@@ -1989,7 +1989,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4294967295 VARIABLE_SCOPE SESSION @@ -458,7 +458,7 @@ VARIABLE_COMMENT Limit assumed max number of seeks when looking up rows based on a key NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1975,7 +1975,7 @@ +@@ -2003,7 +2003,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE SESSION @@ -467,7 +467,7 @@ VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -1989,7 +1989,7 @@ +@@ -2017,7 +2017,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -476,7 +476,7 @@ VARIABLE_COMMENT Maximum stored procedure recursion depth NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -2017,7 +2017,7 @@ +@@ -2045,7 +2045,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32 VARIABLE_SCOPE SESSION @@ -485,7 +485,7 @@ VARIABLE_COMMENT Unused, will be removed. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2045,7 +2045,7 @@ +@@ -2073,7 +2073,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4294967295 VARIABLE_SCOPE GLOBAL @@ -494,7 +494,7 @@ VARIABLE_COMMENT After this many write locks, allow some read locks to run in between NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2059,7 +2059,7 @@ +@@ -2087,7 +2087,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -503,7 +503,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -2073,7 +2073,7 @@ +@@ -2101,7 +2101,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8 VARIABLE_SCOPE GLOBAL @@ -512,7 +512,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -2087,7 +2087,7 @@ +@@ -2115,7 +2115,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -521,7 +521,7 @@ VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2101,7 +2101,7 @@ +@@ -2129,7 +2129,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 262144 VARIABLE_SCOPE SESSION @@ -530,7 +530,7 @@ VARIABLE_COMMENT Size of buffer to use when using MRR with range access NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2115,10 +2115,10 @@ +@@ -2143,10 +2143,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 256 VARIABLE_SCOPE SESSION @@ -543,7 +543,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2129,7 +2129,7 @@ +@@ -2157,7 +2157,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -552,7 +552,7 @@ VARIABLE_COMMENT Block size to be used for MyISAM index pages NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 16384 -@@ -2143,7 +2143,7 @@ +@@ -2171,7 +2171,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 6 VARIABLE_SCOPE GLOBAL @@ -561,7 +561,7 @@ VARIABLE_COMMENT Default pointer size to be used for MyISAM tables NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 7 -@@ -2153,9 +2153,9 @@ +@@ -2181,9 +2181,9 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_MAX_SORT_FILE_SIZE SESSION_VALUE NULL @@ -573,7 +573,7 @@ VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't use the fast sort index method to created index if the temporary file would get bigger than this -@@ -2167,14 +2167,14 @@ +@@ -2195,14 +2195,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_MMAP_SIZE SESSION_VALUE NULL @@ -591,7 +591,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES -@@ -2199,10 +2199,10 @@ +@@ -2227,10 +2227,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -604,7 +604,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2216,7 +2216,7 @@ +@@ -2244,7 +2244,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE NUMERIC_MIN_VALUE 4096 @@ -613,7 +613,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2269,7 +2269,7 @@ +@@ -2297,7 +2297,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION @@ -622,7 +622,7 @@ VARIABLE_COMMENT Buffer length for TCP/IP and socket communication NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1048576 -@@ -2283,7 +2283,7 @@ +@@ -2311,7 +2311,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 30 VARIABLE_SCOPE SESSION @@ -631,7 +631,7 @@ VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2297,7 +2297,7 @@ +@@ -2325,7 +2325,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE SESSION @@ -640,7 +640,7 @@ VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2311,7 +2311,7 @@ +@@ -2339,7 +2339,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 60 VARIABLE_SCOPE SESSION @@ -649,7 +649,7 @@ VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2381,7 +2381,7 @@ +@@ -2409,7 +2409,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -658,7 +658,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1 -@@ -2395,7 +2395,7 @@ +@@ -2423,7 +2423,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 62 VARIABLE_SCOPE SESSION @@ -667,7 +667,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2409,7 +2409,7 @@ +@@ -2437,7 +2437,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE SESSION @@ -676,7 +676,7 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2437,7 +2437,7 @@ +@@ -2465,7 +2465,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -685,7 +685,7 @@ VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2465,7 +2465,7 @@ +@@ -2493,7 +2493,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -694,7 +694,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2479,7 +2479,7 @@ +@@ -2507,7 +2507,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -703,7 +703,7 @@ VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 200 -@@ -2493,7 +2493,7 @@ +@@ -2521,7 +2521,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -712,7 +712,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2507,7 +2507,7 @@ +@@ -2535,7 +2535,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -721,7 +721,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2521,7 +2521,7 @@ +@@ -2549,7 +2549,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -730,7 +730,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2535,7 +2535,7 @@ +@@ -2563,7 +2563,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -739,7 +739,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2549,7 +2549,7 @@ +@@ -2577,7 +2577,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -748,7 +748,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2563,7 +2563,7 @@ +@@ -2591,7 +2591,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -757,7 +757,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2577,7 +2577,7 @@ +@@ -2605,7 +2605,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -766,7 +766,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2591,7 +2591,7 @@ +@@ -2619,7 +2619,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 80 VARIABLE_SCOPE GLOBAL @@ -775,7 +775,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2605,7 +2605,7 @@ +@@ -2633,7 +2633,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -784,7 +784,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2619,7 +2619,7 @@ +@@ -2647,7 +2647,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -793,7 +793,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2633,7 +2633,7 @@ +@@ -2661,7 +2661,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE GLOBAL @@ -802,7 +802,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2647,7 +2647,7 @@ +@@ -2675,7 +2675,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32768 VARIABLE_SCOPE GLOBAL @@ -811,7 +811,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2661,7 +2661,7 @@ +@@ -2689,7 +2689,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -820,7 +820,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2675,7 +2675,7 @@ +@@ -2703,7 +2703,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 200 VARIABLE_SCOPE GLOBAL @@ -829,7 +829,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2689,7 +2689,7 @@ +@@ -2717,7 +2717,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -838,7 +838,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2703,7 +2703,7 @@ +@@ -2731,7 +2731,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 40 VARIABLE_SCOPE GLOBAL @@ -847,7 +847,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2717,7 +2717,7 @@ +@@ -2745,7 +2745,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -856,7 +856,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2731,7 +2731,7 @@ +@@ -2759,7 +2759,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -865,7 +865,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2745,7 +2745,7 @@ +@@ -2773,7 +2773,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -874,7 +874,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2759,7 +2759,7 @@ +@@ -2787,7 +2787,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 150 VARIABLE_SCOPE GLOBAL @@ -883,16 +883,16 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2773,7 +2773,7 @@ +@@ -2801,7 +2801,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 178 + DEFAULT_VALUE 181 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2787,7 +2787,7 @@ +@@ -2815,7 +2815,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -901,7 +901,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2801,7 +2801,7 @@ +@@ -2829,7 +2829,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -910,7 +910,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2815,7 +2815,7 @@ +@@ -2843,7 +2843,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE GLOBAL @@ -919,7 +919,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2829,7 +2829,7 @@ +@@ -2857,7 +2857,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -928,7 +928,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2843,7 +2843,7 @@ +@@ -2871,7 +2871,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -937,7 +937,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2857,7 +2857,7 @@ +@@ -2885,7 +2885,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -946,7 +946,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -2871,7 +2871,7 @@ +@@ -2899,7 +2899,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -955,7 +955,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2885,7 +2885,7 @@ +@@ -2913,7 +2913,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -964,7 +964,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2955,7 +2955,7 @@ +@@ -2983,7 +2983,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32768 VARIABLE_SCOPE SESSION @@ -973,7 +973,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -2983,7 +2983,7 @@ +@@ -3011,7 +3011,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 15 VARIABLE_SCOPE SESSION @@ -982,7 +982,7 @@ VARIABLE_COMMENT Limit of query profiling memory NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -2997,7 +2997,7 @@ +@@ -3025,7 +3025,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 5 VARIABLE_SCOPE SESSION @@ -991,7 +991,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3053,10 +3053,10 @@ +@@ -3081,10 +3081,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION ONLY @@ -1004,7 +1004,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3067,7 +3067,7 @@ +@@ -3095,7 +3095,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION @@ -1013,7 +1013,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3081,7 +3081,7 @@ +@@ -3109,7 +3109,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1048576 VARIABLE_SCOPE GLOBAL @@ -1022,7 +1022,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3095,7 +3095,7 @@ +@@ -3123,7 +3123,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE GLOBAL @@ -1031,7 +1031,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3112,7 +3112,7 @@ +@@ -3140,7 +3140,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1040,7 +1040,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3165,7 +3165,7 @@ +@@ -3193,7 +3193,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 24576 VARIABLE_SCOPE SESSION @@ -1049,7 +1049,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3179,7 +3179,7 @@ +@@ -3207,7 +3207,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE SESSION @@ -1058,7 +1058,7 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -3193,7 +3193,7 @@ +@@ -3221,7 +3221,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 131072 VARIABLE_SCOPE SESSION @@ -1067,7 +1067,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -3221,7 +3221,7 @@ +@@ -3249,7 +3249,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 262144 VARIABLE_SCOPE SESSION @@ -1076,7 +1076,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -3235,10 +3235,10 @@ +@@ -3263,10 +3263,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8388608 VARIABLE_SCOPE SESSION @@ -1089,7 +1089,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3277,7 +3277,7 @@ +@@ -3305,7 +3305,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -1098,7 +1098,7 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3375,7 +3375,7 @@ +@@ -3403,7 +3403,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1073741824 VARIABLE_SCOPE GLOBAL @@ -1107,7 +1107,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3389,7 +3389,7 @@ +@@ -3417,7 +3417,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2 VARIABLE_SCOPE GLOBAL @@ -1116,7 +1116,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -3448,7 +3448,7 @@ +@@ -3476,7 +3476,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1125,7 +1125,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3725,7 +3725,7 @@ +@@ -3753,7 +3753,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 256 VARIABLE_SCOPE GLOBAL @@ -1134,7 +1134,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -3795,7 +3795,7 @@ +@@ -3823,7 +3823,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 400 VARIABLE_SCOPE GLOBAL @@ -1143,7 +1143,7 @@ VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 NUMERIC_MAX_VALUE 524288 -@@ -3809,7 +3809,7 @@ +@@ -3837,7 +3837,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2000 VARIABLE_SCOPE GLOBAL @@ -1152,16 +1152,16 @@ VARIABLE_COMMENT The number of cached open tables NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 524288 -@@ -3823,7 +3823,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 0 +@@ -3851,7 +3851,7 @@ + GLOBAL_VALUE_ORIGIN AUTO + DEFAULT_VALUE 256 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT How many threads we should keep in a cache for reuse + VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -3837,7 +3837,7 @@ +@@ -3865,7 +3865,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -1170,7 +1170,7 @@ VARIABLE_COMMENT Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.This variable has no effect, and is deprecated. It will be removed in a future release. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 512 -@@ -3952,7 +3952,7 @@ +@@ -3980,7 +3980,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MySQL will automatically convert it to an on-disk MyISAM or Aria table NUMERIC_MIN_VALUE 1024 @@ -1179,7 +1179,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3963,7 +3963,7 @@ +@@ -3991,7 +3991,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8192 VARIABLE_SCOPE SESSION @@ -1188,7 +1188,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -3977,7 +3977,7 @@ +@@ -4005,7 +4005,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE SESSION @@ -1197,7 +1197,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4075,7 +4075,7 @@ +@@ -4103,7 +4103,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 28800 VARIABLE_SCOPE SESSION @@ -1206,7 +1206,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -4179,7 +4179,7 @@ +@@ -4207,7 +4207,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL @@ -1215,7 +1215,7 @@ VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -4192,7 +4192,7 @@ +@@ -4220,7 +4220,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1224,7 +1224,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4202,7 +4202,7 @@ +@@ -4230,7 +4230,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1233,7 +1233,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4287,7 +4287,7 @@ +@@ -4315,7 +4315,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 91ff7c62d47..6d1579e77eb 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -1661,6 +1661,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME LOG_SLOW_ADMIN_STATEMENTS +SESSION_VALUE NULL +GLOBAL_VALUE OFF +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE OFF +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to the slow log if it is open. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME LOG_SLOW_FILTER SESSION_VALUE admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk GLOBAL_VALUE admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk @@ -1689,6 +1703,20 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME LOG_SLOW_SLAVE_STATEMENTS +SESSION_VALUE NULL +GLOBAL_VALUE OFF +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE OFF +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Log slow statements executed by slave thread to the slow log if it is open. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME LOG_SLOW_VERBOSITY SESSION_VALUE GLOBAL_VALUE @@ -2769,9 +2797,9 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES SESSION_VALUE NULL -GLOBAL_VALUE 178 +GLOBAL_VALUE 181 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 178 +DEFAULT_VALUE 181 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. @@ -3819,12 +3847,12 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME THREAD_CACHE_SIZE SESSION_VALUE NULL -GLOBAL_VALUE 0 -GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 0 +GLOBAL_VALUE 151 +GLOBAL_VALUE_ORIGIN AUTO +DEFAULT_VALUE 256 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT How many threads we should keep in a cache for reuse +VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 NUMERIC_BLOCK_SIZE 1 @@ -3861,9 +3889,9 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME THREAD_STACK SESSION_VALUE NULL -GLOBAL_VALUE 294912 +GLOBAL_VALUE 296960 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 294912 +DEFAULT_VALUE 296960 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The stack size for each thread diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff index c5fb97a5d46..650bdc24681 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff @@ -1,5 +1,5 @@ --- suite/sys_vars/r/sysvars_server_notembedded.result -+++ suite/sys_vars/r/sysvars_server_notembedded,32bit.reject ++++ suite/sys_vars/r/sysvars_server_notembedded.reject @@ -57,7 +57,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 1 @@ -296,7 +296,7 @@ VARIABLE_COMMENT Timeout in seconds to wait for a lock before returning an error. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -1849,7 +1849,7 @@ +@@ -1863,7 +1863,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -305,7 +305,7 @@ VARIABLE_COMMENT Write to slow log every #th slow query. Set to 1 to log everything. Increase it to reduce the size of the slow or the performance impact of slow logging NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1877,7 +1877,7 @@ +@@ -1905,7 +1905,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -314,7 +314,7 @@ VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1933,7 +1933,7 @@ +@@ -1961,7 +1961,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4194304 VARIABLE_SCOPE SESSION @@ -323,7 +323,7 @@ VARIABLE_COMMENT Max packet length to send to or receive from the server NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -1943,14 +1943,14 @@ +@@ -1971,14 +1971,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_BINLOG_CACHE_SIZE SESSION_VALUE NULL @@ -341,7 +341,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1961,7 +1961,7 @@ +@@ -1989,7 +1989,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1073741824 VARIABLE_SCOPE GLOBAL @@ -350,7 +350,7 @@ VARIABLE_COMMENT Binary log will be rotated automatically when the size exceeds this value. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 1073741824 -@@ -1971,14 +1971,14 @@ +@@ -1999,14 +1999,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_BINLOG_STMT_CACHE_SIZE SESSION_VALUE NULL @@ -368,7 +368,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1989,7 +1989,7 @@ +@@ -2017,7 +2017,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 151 VARIABLE_SCOPE GLOBAL @@ -377,7 +377,7 @@ VARIABLE_COMMENT The number of simultaneous clients allowed NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 100000 -@@ -2003,7 +2003,7 @@ +@@ -2031,7 +2031,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -386,7 +386,7 @@ VARIABLE_COMMENT If there is more than this number of interrupted connections from a host this host will be blocked from further connections NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2017,7 +2017,7 @@ +@@ -2045,7 +2045,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 20 VARIABLE_SCOPE SESSION @@ -395,7 +395,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -2045,7 +2045,7 @@ +@@ -2073,7 +2073,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 64 VARIABLE_SCOPE SESSION @@ -404,7 +404,7 @@ VARIABLE_COMMENT Max number of errors/warnings to store for a statement NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -2062,7 +2062,7 @@ +@@ -2090,7 +2090,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't allow creation of heap tables bigger than this NUMERIC_MIN_VALUE 16384 @@ -413,7 +413,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2073,7 +2073,7 @@ +@@ -2101,7 +2101,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 20 VARIABLE_SCOPE SESSION @@ -422,7 +422,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -2101,7 +2101,7 @@ +@@ -2129,7 +2129,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE SESSION @@ -431,7 +431,7 @@ VARIABLE_COMMENT Max number of bytes in sorted records NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -2115,7 +2115,7 @@ +@@ -2143,7 +2143,7 @@ GLOBAL_VALUE_ORIGIN AUTO DEFAULT_VALUE 1048576 VARIABLE_SCOPE GLOBAL @@ -440,7 +440,7 @@ VARIABLE_COMMENT The maximum BLOB length to send to server from mysql_send_long_data API. Deprecated option; use max_allowed_packet instead. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -2129,7 +2129,7 @@ +@@ -2157,7 +2157,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16382 VARIABLE_SCOPE GLOBAL @@ -449,7 +449,7 @@ VARIABLE_COMMENT Maximum number of prepared statements in the server NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2157,7 +2157,7 @@ +@@ -2185,7 +2185,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4294967295 VARIABLE_SCOPE SESSION @@ -458,7 +458,7 @@ VARIABLE_COMMENT Limit assumed max number of seeks when looking up rows based on a key NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2171,7 +2171,7 @@ +@@ -2199,7 +2199,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE SESSION @@ -467,7 +467,7 @@ VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -2185,7 +2185,7 @@ +@@ -2213,7 +2213,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -476,7 +476,7 @@ VARIABLE_COMMENT Maximum stored procedure recursion depth NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -2213,7 +2213,7 @@ +@@ -2241,7 +2241,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32 VARIABLE_SCOPE SESSION @@ -485,7 +485,7 @@ VARIABLE_COMMENT Unused, will be removed. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2241,7 +2241,7 @@ +@@ -2269,7 +2269,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4294967295 VARIABLE_SCOPE GLOBAL @@ -494,7 +494,7 @@ VARIABLE_COMMENT After this many write locks, allow some read locks to run in between NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2255,7 +2255,7 @@ +@@ -2283,7 +2283,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -503,7 +503,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -2269,7 +2269,7 @@ +@@ -2297,7 +2297,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8 VARIABLE_SCOPE GLOBAL @@ -512,7 +512,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -2283,7 +2283,7 @@ +@@ -2311,7 +2311,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -521,7 +521,7 @@ VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2297,7 +2297,7 @@ +@@ -2325,7 +2325,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 262144 VARIABLE_SCOPE SESSION @@ -530,7 +530,7 @@ VARIABLE_COMMENT Size of buffer to use when using MRR with range access NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2311,10 +2311,10 @@ +@@ -2339,10 +2339,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 256 VARIABLE_SCOPE SESSION @@ -543,7 +543,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2325,7 +2325,7 @@ +@@ -2353,7 +2353,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -552,7 +552,7 @@ VARIABLE_COMMENT Block size to be used for MyISAM index pages NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 16384 -@@ -2339,7 +2339,7 @@ +@@ -2367,7 +2367,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 6 VARIABLE_SCOPE GLOBAL @@ -561,7 +561,7 @@ VARIABLE_COMMENT Default pointer size to be used for MyISAM tables NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 7 -@@ -2349,9 +2349,9 @@ +@@ -2377,9 +2377,9 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_MAX_SORT_FILE_SIZE SESSION_VALUE NULL @@ -573,7 +573,7 @@ VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't use the fast sort index method to created index if the temporary file would get bigger than this -@@ -2363,14 +2363,14 @@ +@@ -2391,14 +2391,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_MMAP_SIZE SESSION_VALUE NULL @@ -591,7 +591,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES -@@ -2395,10 +2395,10 @@ +@@ -2423,10 +2423,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -604,7 +604,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2412,7 +2412,7 @@ +@@ -2440,7 +2440,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE NUMERIC_MIN_VALUE 4096 @@ -613,7 +613,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2465,7 +2465,7 @@ +@@ -2493,7 +2493,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION @@ -622,7 +622,7 @@ VARIABLE_COMMENT Buffer length for TCP/IP and socket communication NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1048576 -@@ -2479,7 +2479,7 @@ +@@ -2507,7 +2507,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 30 VARIABLE_SCOPE SESSION @@ -631,7 +631,7 @@ VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2493,7 +2493,7 @@ +@@ -2521,7 +2521,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE SESSION @@ -640,7 +640,7 @@ VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2507,7 +2507,7 @@ +@@ -2535,7 +2535,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 60 VARIABLE_SCOPE SESSION @@ -649,7 +649,7 @@ VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2577,7 +2577,7 @@ +@@ -2605,7 +2605,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -658,7 +658,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1 -@@ -2591,7 +2591,7 @@ +@@ -2619,7 +2619,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 62 VARIABLE_SCOPE SESSION @@ -667,7 +667,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2605,7 +2605,7 @@ +@@ -2633,7 +2633,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE SESSION @@ -676,7 +676,7 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2633,7 +2633,7 @@ +@@ -2661,7 +2661,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -685,7 +685,7 @@ VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2661,7 +2661,7 @@ +@@ -2689,7 +2689,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -694,7 +694,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2675,7 +2675,7 @@ +@@ -2703,7 +2703,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -703,7 +703,7 @@ VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 200 -@@ -2689,7 +2689,7 @@ +@@ -2717,7 +2717,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -712,7 +712,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2703,7 +2703,7 @@ +@@ -2731,7 +2731,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -721,7 +721,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2717,7 +2717,7 @@ +@@ -2745,7 +2745,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -730,7 +730,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2731,7 +2731,7 @@ +@@ -2759,7 +2759,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -739,7 +739,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2745,7 +2745,7 @@ +@@ -2773,7 +2773,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -748,7 +748,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2759,7 +2759,7 @@ +@@ -2787,7 +2787,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -757,7 +757,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2773,7 +2773,7 @@ +@@ -2801,7 +2801,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -766,7 +766,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2787,7 +2787,7 @@ +@@ -2815,7 +2815,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 80 VARIABLE_SCOPE GLOBAL @@ -775,7 +775,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2801,7 +2801,7 @@ +@@ -2829,7 +2829,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -784,7 +784,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2815,7 +2815,7 @@ +@@ -2843,7 +2843,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -793,7 +793,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2829,7 +2829,7 @@ +@@ -2857,7 +2857,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE GLOBAL @@ -802,7 +802,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2843,7 +2843,7 @@ +@@ -2871,7 +2871,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32768 VARIABLE_SCOPE GLOBAL @@ -811,7 +811,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2857,7 +2857,7 @@ +@@ -2885,7 +2885,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -820,7 +820,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2871,7 +2871,7 @@ +@@ -2899,7 +2899,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 200 VARIABLE_SCOPE GLOBAL @@ -829,7 +829,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2885,7 +2885,7 @@ +@@ -2913,7 +2913,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -838,7 +838,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2899,7 +2899,7 @@ +@@ -2927,7 +2927,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 40 VARIABLE_SCOPE GLOBAL @@ -847,7 +847,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2913,7 +2913,7 @@ +@@ -2941,7 +2941,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -856,7 +856,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2927,7 +2927,7 @@ +@@ -2955,7 +2955,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -865,7 +865,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2941,7 +2941,7 @@ +@@ -2969,7 +2969,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -874,7 +874,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2955,7 +2955,7 @@ +@@ -2983,7 +2983,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 150 VARIABLE_SCOPE GLOBAL @@ -883,16 +883,16 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2969,7 +2969,7 @@ +@@ -2997,7 +2997,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 178 + DEFAULT_VALUE 181 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2983,7 +2983,7 @@ +@@ -3011,7 +3011,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -901,7 +901,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2997,7 +2997,7 @@ +@@ -3025,7 +3025,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -910,7 +910,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3011,7 +3011,7 @@ +@@ -3039,7 +3039,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE GLOBAL @@ -919,7 +919,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3025,7 +3025,7 @@ +@@ -3053,7 +3053,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -928,7 +928,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3039,7 +3039,7 @@ +@@ -3067,7 +3067,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -937,7 +937,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3053,7 +3053,7 @@ +@@ -3081,7 +3081,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -946,7 +946,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -3067,7 +3067,7 @@ +@@ -3095,7 +3095,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -955,7 +955,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -3081,7 +3081,7 @@ +@@ -3109,7 +3109,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -964,7 +964,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3151,7 +3151,7 @@ +@@ -3179,7 +3179,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32768 VARIABLE_SCOPE SESSION @@ -973,7 +973,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3179,7 +3179,7 @@ +@@ -3207,7 +3207,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 15 VARIABLE_SCOPE SESSION @@ -982,7 +982,7 @@ VARIABLE_COMMENT Limit of query profiling memory NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -3193,7 +3193,7 @@ +@@ -3221,7 +3221,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 5 VARIABLE_SCOPE SESSION @@ -991,7 +991,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3249,10 +3249,10 @@ +@@ -3277,10 +3277,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION ONLY @@ -1004,7 +1004,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3263,7 +3263,7 @@ +@@ -3291,7 +3291,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION @@ -1013,7 +1013,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3277,7 +3277,7 @@ +@@ -3305,7 +3305,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1048576 VARIABLE_SCOPE GLOBAL @@ -1022,7 +1022,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3291,7 +3291,7 @@ +@@ -3319,7 +3319,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE GLOBAL @@ -1031,7 +1031,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3308,7 +3308,7 @@ +@@ -3336,7 +3336,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1040,7 +1040,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3361,7 +3361,7 @@ +@@ -3389,7 +3389,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 24576 VARIABLE_SCOPE SESSION @@ -1049,7 +1049,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3375,7 +3375,7 @@ +@@ -3403,7 +3403,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE SESSION @@ -1058,7 +1058,7 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -3389,7 +3389,7 @@ +@@ -3417,7 +3417,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 131072 VARIABLE_SCOPE SESSION @@ -1067,7 +1067,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -3417,7 +3417,7 @@ +@@ -3445,7 +3445,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 262144 VARIABLE_SCOPE SESSION @@ -1076,7 +1076,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -3697,10 +3697,10 @@ +@@ -3725,10 +3725,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8388608 VARIABLE_SCOPE SESSION @@ -1089,7 +1089,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3739,7 +3739,7 @@ +@@ -3767,7 +3767,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -1098,7 +1098,7 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3865,7 +3865,7 @@ +@@ -3893,7 +3893,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -1107,7 +1107,7 @@ VARIABLE_COMMENT Maximum number of parallel threads to use on slave for events in a single replication domain. When using multiple domains, this can be used to limit a single domain from grabbing all threads and thus stalling other domains. The default of 0 means to allow a domain to grab as many threads as it wants, up to the value of slave_parallel_threads. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -3907,7 +3907,7 @@ +@@ -3935,7 +3935,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1073741824 VARIABLE_SCOPE GLOBAL @@ -1116,7 +1116,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3935,7 +3935,7 @@ +@@ -3963,7 +3963,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 131072 VARIABLE_SCOPE GLOBAL @@ -1125,7 +1125,7 @@ VARIABLE_COMMENT Limit on how much memory SQL threads should use per parallel replication thread when reading ahead in the relay log looking for opportunities for parallel replication. Only used when --slave-parallel-threads > 0. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 2147483647 -@@ -3963,7 +3963,7 @@ +@@ -3991,7 +3991,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -1134,7 +1134,16 @@ VARIABLE_COMMENT If non-zero, number of threads to spawn to apply in parallel events on the slave that were group-committed on the master or were logged with GTID in different replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -4019,7 +4019,7 @@ +@@ -4005,7 +4005,7 @@ + GLOBAL_VALUE_ORIGIN COMPILE-TIME + DEFAULT_VALUE 0 + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Alias for slave_parallel_threads + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 16383 +@@ -4061,7 +4061,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -1143,7 +1152,7 @@ VARIABLE_COMMENT Number of times the slave SQL thread will retry a transaction in case it failed with a deadlock or elapsed lock wait timeout, before giving up and stopping NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -4047,7 +4047,7 @@ +@@ -4089,7 +4089,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2 VARIABLE_SCOPE GLOBAL @@ -1152,7 +1161,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -4106,7 +4106,7 @@ +@@ -4148,7 +4148,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1161,7 +1170,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4397,7 +4397,7 @@ +@@ -4439,7 +4439,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 256 VARIABLE_SCOPE GLOBAL @@ -1170,7 +1179,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -4495,7 +4495,7 @@ +@@ -4537,7 +4537,7 @@ GLOBAL_VALUE_ORIGIN AUTO DEFAULT_VALUE 400 VARIABLE_SCOPE GLOBAL @@ -1179,7 +1188,7 @@ VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 NUMERIC_MAX_VALUE 524288 -@@ -4509,7 +4509,7 @@ +@@ -4551,7 +4551,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2000 VARIABLE_SCOPE GLOBAL @@ -1188,16 +1197,16 @@ VARIABLE_COMMENT The number of cached open tables NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 524288 -@@ -4523,7 +4523,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 0 +@@ -4565,7 +4565,7 @@ + GLOBAL_VALUE_ORIGIN AUTO + DEFAULT_VALUE 256 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT How many threads we should keep in a cache for reuse + VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -4537,7 +4537,7 @@ +@@ -4579,7 +4579,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -1206,7 +1215,7 @@ VARIABLE_COMMENT Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.This variable has no effect, and is deprecated. It will be removed in a future release. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 512 -@@ -4722,7 +4722,7 @@ +@@ -4764,7 +4764,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MySQL will automatically convert it to an on-disk MyISAM or Aria table NUMERIC_MIN_VALUE 1024 @@ -1215,7 +1224,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4733,7 +4733,7 @@ +@@ -4775,7 +4775,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8192 VARIABLE_SCOPE SESSION @@ -1224,7 +1233,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4747,7 +4747,7 @@ +@@ -4789,7 +4789,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE SESSION @@ -1233,7 +1242,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4845,7 +4845,7 @@ +@@ -4887,7 +4887,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 28800 VARIABLE_SCOPE SESSION @@ -1242,7 +1251,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -4949,7 +4949,7 @@ +@@ -4991,7 +4991,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL @@ -1251,7 +1260,7 @@ VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -4962,7 +4962,7 @@ +@@ -5004,7 +5004,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1260,7 +1269,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4972,7 +4972,7 @@ +@@ -5014,7 +5014,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1269,7 +1278,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -5057,7 +5057,7 @@ +@@ -5099,7 +5099,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 28605b7900e..09c3d6e6c98 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -1829,6 +1829,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY YES COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME LOG_SLOW_ADMIN_STATEMENTS +SESSION_VALUE NULL +GLOBAL_VALUE OFF +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE OFF +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to the slow log if it is open. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME LOG_SLOW_FILTER SESSION_VALUE admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk GLOBAL_VALUE admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk @@ -1857,6 +1871,20 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME LOG_SLOW_SLAVE_STATEMENTS +SESSION_VALUE NULL +GLOBAL_VALUE OFF +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE OFF +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Log slow statements executed by slave thread to the slow log if it is open. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME LOG_SLOW_VERBOSITY SESSION_VALUE GLOBAL_VALUE @@ -2965,9 +2993,9 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME PERFORMANCE_SCHEMA_MAX_STATEMENT_CLASSES SESSION_VALUE NULL -GLOBAL_VALUE 178 +GLOBAL_VALUE 181 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 178 +DEFAULT_VALUE 181 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. @@ -3971,6 +3999,20 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SLAVE_PARALLEL_WORKERS +SESSION_VALUE NULL +GLOBAL_VALUE 0 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 0 +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Alias for slave_parallel_threads +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 16383 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SLAVE_RUN_TRIGGERS_FOR_RBR SESSION_VALUE NULL GLOBAL_VALUE NO @@ -4519,12 +4561,12 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME THREAD_CACHE_SIZE SESSION_VALUE NULL -GLOBAL_VALUE 0 -GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 0 +GLOBAL_VALUE 151 +GLOBAL_VALUE_ORIGIN AUTO +DEFAULT_VALUE 256 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT How many threads we should keep in a cache for reuse +VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 NUMERIC_BLOCK_SIZE 1 @@ -4631,9 +4673,9 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME THREAD_STACK SESSION_VALUE NULL -GLOBAL_VALUE 294912 +GLOBAL_VALUE 296960 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 294912 +DEFAULT_VALUE 296960 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The stack size for each thread diff --git a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result index 3dd9cc541c4..4d7b03690af 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result +++ b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result @@ -367,7 +367,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME WSREP_PATCH_VERSION SESSION_VALUE NULL -GLOBAL_VALUE wsrep_25.11 +GLOBAL_VALUE wsrep_25.13 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE NULL VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/thread_cache_size_basic.result b/mysql-test/suite/sys_vars/r/thread_cache_size_basic.result index af6777fcf45..a50785c42b7 100644 --- a/mysql-test/suite/sys_vars/r/thread_cache_size_basic.result +++ b/mysql-test/suite/sys_vars/r/thread_cache_size_basic.result @@ -1,24 +1,24 @@ SET @start_global_value = @@global.thread_cache_size; SELECT @start_global_value; @start_global_value -0 +256 select @@global.thread_cache_size; @@global.thread_cache_size -0 +256 select @@session.thread_cache_size; ERROR HY000: Variable 'thread_cache_size' is a GLOBAL variable show global variables like 'thread_cache_size'; Variable_name Value -thread_cache_size 0 +thread_cache_size 256 show session variables like 'thread_cache_size'; Variable_name Value -thread_cache_size 0 +thread_cache_size 256 select * from information_schema.global_variables where variable_name='thread_cache_size'; VARIABLE_NAME VARIABLE_VALUE -THREAD_CACHE_SIZE 0 +THREAD_CACHE_SIZE 256 select * from information_schema.session_variables where variable_name='thread_cache_size'; VARIABLE_NAME VARIABLE_VALUE -THREAD_CACHE_SIZE 0 +THREAD_CACHE_SIZE 256 set global thread_cache_size=1; select @@global.thread_cache_size; @@global.thread_cache_size @@ -51,4 +51,4 @@ select @@global.thread_cache_size; SET @@global.thread_cache_size = @start_global_value; SELECT @@global.thread_cache_size; @@global.thread_cache_size -0 +256 diff --git a/mysql-test/suite/sys_vars/r/thread_stack_basic.result b/mysql-test/suite/sys_vars/r/thread_stack_basic.result index 4d974f66a00..5984ffebdaf 100644 --- a/mysql-test/suite/sys_vars/r/thread_stack_basic.result +++ b/mysql-test/suite/sys_vars/r/thread_stack_basic.result @@ -1,20 +1,20 @@ select @@global.thread_stack; @@global.thread_stack -294912 +296960 select @@session.thread_stack; ERROR HY000: Variable 'thread_stack' is a GLOBAL variable show global variables like 'thread_stack'; Variable_name Value -thread_stack 294912 +thread_stack 296960 show session variables like 'thread_stack'; Variable_name Value -thread_stack 294912 +thread_stack 296960 select * from information_schema.global_variables where variable_name='thread_stack'; VARIABLE_NAME VARIABLE_VALUE -THREAD_STACK 294912 +THREAD_STACK 296960 select * from information_schema.session_variables where variable_name='thread_stack'; VARIABLE_NAME VARIABLE_VALUE -THREAD_STACK 294912 +THREAD_STACK 296960 set global thread_stack=1; ERROR HY000: Variable 'thread_stack' is a read only variable set session thread_stack=1; diff --git a/mysql-test/suite/sys_vars/r/wait_timeout_basic.result b/mysql-test/suite/sys_vars/r/wait_timeout_basic.result index 6dc99dcd5e3..d0e5188b508 100644 --- a/mysql-test/suite/sys_vars/r/wait_timeout_basic.result +++ b/mysql-test/suite/sys_vars/r/wait_timeout_basic.result @@ -124,5 +124,17 @@ SELECT session.wait_timeout; ERROR 42S02: Unknown table 'session' in field list SELECT wait_timeout = @@session.wait_timeout; ERROR 42S22: Unknown column 'wait_timeout' in 'field list' +# +# MDEV-9516 type error when setting session variable +# +SET SESSION wait_timeout= 28000; +SET SESSION wait_timeout= GREATEST(28000, @@wait_timeout); +SET SESSION wait_timeout= COALESCE(28000, @@wait_timeout); +SET SESSION wait_timeout= IFNULL(28000, @@wait_timeout); +SET SESSION wait_timeout= CASE WHEN TRUE THEN 28000 ELSE @@wait_timeout END; +SET SESSION wait_timeout= 28000.0; +ERROR 42000: Incorrect argument type to variable 'wait_timeout' +SET SESSION wait_timeout= 28000.1; +ERROR 42000: Incorrect argument type to variable 'wait_timeout' SET @@global.wait_timeout = @start_global_value; SET @@session.wait_timeout = @start_session_value; diff --git a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test index fe376a3032e..160b3ba52cc 100644 --- a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test @@ -8,12 +8,24 @@ SET @orig = @@global.innodb_buffer_pool_load_now; SELECT @orig; +let $old_status= `SELECT variable_value FROM information_schema.global_status + WHERE LOWER(variable_name) = 'innodb_buffer_pool_dump_status'`; + +# A previous test could have run buffer pool dump already; +# in this case we want to make sure that the current time is different +# from the timestamp in the status variable + +let $wait_condition = + SELECT TRIM(SUBSTR('$old_status', -8)) != DATE_FORMAT(CURTIME(), '%k:%i:%s'); +-- source include/wait_condition.inc + # Do the dump SET GLOBAL innodb_buffer_pool_dump_now = ON; # Wait for the dump to complete let $wait_condition = - SELECT SUBSTR(variable_value, 1, 33) = 'Buffer pool(s) dump completed at ' + SELECT variable_value != '$old_status' + AND SUBSTR(variable_value, 1, 33) = 'Buffer pool(s) dump completed at ' FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_buffer_pool_dump_status'; -- source include/wait_condition.inc diff --git a/mysql-test/suite/sys_vars/t/innodb_thread_sleep_delay_basic.test b/mysql-test/suite/sys_vars/t/innodb_thread_sleep_delay_basic.test index 85ae2358db5..bc4efdd1d6f 100644 --- a/mysql-test/suite/sys_vars/t/innodb_thread_sleep_delay_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_thread_sleep_delay_basic.test @@ -39,7 +39,7 @@ set global innodb_thread_sleep_delay=1.1; set global innodb_thread_sleep_delay=1e1; --error ER_WRONG_TYPE_FOR_VAR set global innodb_thread_sleep_delay="foo"; ---error ER_WRONG_TYPE_FOR_VAR + set global innodb_thread_sleep_delay=18446744073709551616; set global innodb_thread_sleep_delay=-7; diff --git a/mysql-test/suite/sys_vars/t/innodb_tmpdir_basic.test b/mysql-test/suite/sys_vars/t/innodb_tmpdir_basic.test new file mode 100644 index 00000000000..3c547152e27 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_tmpdir_basic.test @@ -0,0 +1,48 @@ +--source include/have_innodb.inc + +if (`select plugin_auth_version <= "5.6.28-MariaDB-76.1" from information_schema.plugins where plugin_name='innodb'`) +{ + --skip Not fixed in XtraDB as of 5.6.28-MariaDB-76.1 or earlier +} + +SET @start_global_value = @@global.innodb_tmpdir; +SELECT @start_global_value; + +# +# exists as global and session +# +select @@session.innodb_tmpdir; + +show global variables like 'innodb_tmpdir'; +show session variables like 'innodb_tmpdir'; + +select * from information_schema.global_variables where variable_name='innodb_tmpdir'; +select * from information_schema.session_variables where variable_name='innodb_tmpdir'; +# +# Show that it is writable +# + +set global innodb_tmpdir=@@global.tmpdir; +set session innodb_tmpdir=@@global.tmpdir; + +# +# incorrect types +# +--error ER_WRONG_TYPE_FOR_VAR +set global innodb_tmpdir=1.1; +--error ER_WRONG_TYPE_FOR_VAR +set global innodb_tmpdir=1e1; + +# +# path len more than 512 +# +--error ER_WRONG_VALUE_FOR_VAR +set global innodb_tmpdir=repeat('a',1000); +show warnings; + +# +# Cleanup +# + +SET @@global.innodb_tmpdir = @start_global_value; +SELECT @@global.innodb_tmpdir; diff --git a/mysql-test/suite/sys_vars/t/log_slow_admin_statements_func.test b/mysql-test/suite/sys_vars/t/log_slow_admin_statements_func.test new file mode 100644 index 00000000000..78e4d35f69a --- /dev/null +++ b/mysql-test/suite/sys_vars/t/log_slow_admin_statements_func.test @@ -0,0 +1,61 @@ +--source include/no_valgrind_without_big.inc +-- source include/have_innodb.inc + +SET @old_log_output= @@global.log_output; +SET @old_slow_query_log= @@global.slow_query_log; +SET @old_long_query_time= @@session.long_query_time; +SET @old_log_slow_admin_statements= @@global.log_slow_admin_statements; + +USE test; +CREATE TABLE log_slow_admin_statements ( + i INT PRIMARY KEY AUTO_INCREMENT, + j VARCHAR(255) +) ENGINE=InnoDB; + +# enable slow logging to table +SET GLOBAL log_output = 'file,table'; +SET GLOBAL slow_query_log = on; +SET SESSION long_query_time = 0; +SET GLOBAL log_slow_admin_statements = on; + +# test ALTER, OPTIMIZE and CHECK against the table shown up +ALTER TABLE log_slow_admin_statements ADD COLUMN k INT DEFAULT 17; + +# add rows so OPTIMIZE and CHECK runs +DELIMITER $; + +CREATE PROCEDURE add_rows() +BEGIN + DECLARE count INT; + SET count = 1; + INSERT INTO log_slow_admin_statements(j) values (REPEAT('A', 255)); + WHILE count <= 15 DO + INSERT INTO log_slow_admin_statements(j) SELECT j FROM log_slow_admin_statements; + SET count = count + 1; + END WHILE; +END +$ + +DELIMITER ;$ + +CALL add_rows(); + +# OPTIMIZE TABLE +OPTIMIZE TABLE log_slow_admin_statements; + +# CHECK TABLE +CHECK TABLE log_slow_admin_statements EXTENDED; + +# DROP TABLE +DROP TABLE log_slow_admin_statements; + +# ALTER, OPTIMIZE, CHECK and DROP operations should be logged in slow query log. +SELECT sql_text FROM mysql.slow_log WHERE sql_text LIKE '%TABLE log_slow_admin_statements%'; + +SET @@global.log_output= @old_log_output; +SET @@global.slow_query_log= @old_slow_query_log; +SET @@session.long_query_time= @old_long_query_time; +SET @@global.log_slow_admin_statements= @old_log_slow_admin_statements; + +DROP PROCEDURE add_rows; +TRUNCATE TABLE mysql.slow_log; diff --git a/mysql-test/suite/sys_vars/t/secure_file_priv.test b/mysql-test/suite/sys_vars/t/secure_file_priv.test index 3e2a4fa467a..5c53da58275 100644 --- a/mysql-test/suite/sys_vars/t/secure_file_priv.test +++ b/mysql-test/suite/sys_vars/t/secure_file_priv.test @@ -5,17 +5,39 @@ CREATE TABLE t1 (c1 VARCHAR(50)); INSERT INTO t1 VALUES ("one"),("two"),("three"),("four"),("five"); SHOW VARIABLES LIKE 'secure_file_priv'; --disable_query_log + # Atempt to create a file where we normally aren't allowed to create one. +# # Doing this in a portable manner is difficult but we should be able to -# count on the depth of the directory hierarchy used. Three steps up from -# the datadir is the 'mysql_test' directory. ---let $PROTECTED_FILE=`SELECT concat(@@datadir,'/../../../bug50373.txt')` ---eval SELECT * FROM t1 INTO OUTFILE '$PROTECTED_FILE'; -DELETE FROM t1; ---eval LOAD DATA INFILE '$PROTECTED_FILE' INTO TABLE t1; -SELECT * FROM t1; ---eval SELECT load_file('$PROTECTED_FILE') AS loaded_file; +# count on the directory hierarchy used. A step up from MYSQLTEST_VARDIR +# should definitely lead us to a "protected" directory, +# but at the same time should still be writable since MTR was able +# to create the vardir itself there. +# If we run tests normally, it will be mysql-test directory. +# If we run tests with --mem, it will be /dev/shm. +# If we run tests with --parallel, it will be mysql-test/var +# (because MYSQLTEST_VARDIR in this case is mysql-test/var/N). + +--perl +use File::Basename; +my $protected_file= dirname($ENV{MYSQLTEST_VARDIR}).'/bug50373.txt'; +open(FILE, ">", "$ENV{MYSQL_TMP_DIR}/bug50373.inc") or die; +print FILE "SELECT * FROM t1 INTO OUTFILE '".$protected_file."';\n"; +print FILE "DELETE FROM t1;\n"; +print FILE "LOAD DATA INFILE '".$protected_file."' INTO TABLE t1;\n"; +print FILE "SELECT * FROM t1;\n"; +print FILE "SELECT load_file('",$protected_file,"') AS loaded_file;\n"; +close(FILE); +EOF + +--source $MYSQL_TMP_DIR/bug50373.inc +--remove_file $MYSQL_TMP_DIR/bug50373.inc --enable_query_log -remove_file $PROTECTED_FILE; + DROP TABLE t1; +--perl +use File::Basename; +unlink dirname($ENV{MYSQLTEST_VARDIR}).'/bug50373.txt'; +EOF + diff --git a/mysql-test/suite/sys_vars/t/slow_launch_time_func-master.opt b/mysql-test/suite/sys_vars/t/slow_launch_time_func-master.opt new file mode 100644 index 00000000000..e92bb2476ff --- /dev/null +++ b/mysql-test/suite/sys_vars/t/slow_launch_time_func-master.opt @@ -0,0 +1 @@ +--thread_cache_size=0 diff --git a/mysql-test/suite/sys_vars/t/thread_cache_size_basic-master.opt b/mysql-test/suite/sys_vars/t/thread_cache_size_basic-master.opt new file mode 100644 index 00000000000..f28fc33b28b --- /dev/null +++ b/mysql-test/suite/sys_vars/t/thread_cache_size_basic-master.opt @@ -0,0 +1 @@ +--max-connections=1024 diff --git a/mysql-test/suite/sys_vars/t/thread_cache_size_func-master.opt b/mysql-test/suite/sys_vars/t/thread_cache_size_func-master.opt new file mode 100644 index 00000000000..b8c19e1b5ff --- /dev/null +++ b/mysql-test/suite/sys_vars/t/thread_cache_size_func-master.opt @@ -0,0 +1 @@ +--thread-cache-size=0 diff --git a/mysql-test/suite/sys_vars/t/wait_timeout_basic.test b/mysql-test/suite/sys_vars/t/wait_timeout_basic.test index e92a3294b86..598f6cb44fd 100644 --- a/mysql-test/suite/sys_vars/t/wait_timeout_basic.test +++ b/mysql-test/suite/sys_vars/t/wait_timeout_basic.test @@ -203,6 +203,20 @@ SELECT session.wait_timeout; --Error ER_BAD_FIELD_ERROR SELECT wait_timeout = @@session.wait_timeout; +--echo # +--echo # MDEV-9516 type error when setting session variable +--echo # + +SET SESSION wait_timeout= 28000; +SET SESSION wait_timeout= GREATEST(28000, @@wait_timeout); +SET SESSION wait_timeout= COALESCE(28000, @@wait_timeout); +SET SESSION wait_timeout= IFNULL(28000, @@wait_timeout); +SET SESSION wait_timeout= CASE WHEN TRUE THEN 28000 ELSE @@wait_timeout END; + +--error ER_WRONG_TYPE_FOR_VAR +SET SESSION wait_timeout= 28000.0; +--error ER_WRONG_TYPE_FOR_VAR +SET SESSION wait_timeout= 28000.1; #################################### # Restore initial value # diff --git a/mysql-test/suite/vcol/inc/vcol_ins_upd.inc b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc index 8d0a51f42c0..d9a1e062870 100644 --- a/mysql-test/suite/vcol/inc/vcol_ins_upd.inc +++ b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc @@ -287,3 +287,30 @@ select * from t1; set sql_warnings = 0; drop table t1; + +--echo # +--echo # MDEV-9093: Persistent computed column is not updated when +--echo # update query contains join +--echo # + +CREATE TABLE `t1` ( + `id` bigint(20) NOT NULL, + `name` varchar(254) DEFAULT NULL, + `name_hash` varchar(64) AS (sha1(name)) PERSISTENT, + PRIMARY KEY (`id`) +); + +insert into t1(id,name) values (2050, 'name1'),(2051, 'name2'),(2041, 'name3'); + +create table t2 (id bigint); +insert into t2 values (2050),(2051),(2041); + +select * from t1; + +update t1 join t2 using(id) set name = concat(name, +'+1') where t1.id in (2051,2041); + +select * from t1; + +drop table t1,t2; + diff --git a/mysql-test/suite/vcol/r/alter_inplace-9045.result b/mysql-test/suite/vcol/r/alter_inplace-9045.result new file mode 100644 index 00000000000..1560d830f42 --- /dev/null +++ b/mysql-test/suite/vcol/r/alter_inplace-9045.result @@ -0,0 +1,44 @@ +create table t1(id int auto_increment primary key, handle int, data bigint not null default 0) engine = innodb; +insert into t1(handle) values(12),(54),(NULL); +select *, md5(handle) from t1; +id handle data md5(handle) +1 12 0 c20ad4d76fe97759aa27a0c99bff6710 +2 54 0 a684eceee76fc522773286a895bc8436 +3 NULL 0 NULL +alter table t1 add index handle(handle), algorithm=inplace; +alter table t1 add column hash varchar(32) as (md5(handle)) persistent, algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +alter table t1 add column hash varchar(32) as (md5(handle)) persistent, add unique index hash(hash), algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +alter table t1 add column hash varchar(32) as (md5(handle)) persistent, add unique index hash(hash), algorithm=copy; +select * from t1; +id handle data hash +1 12 0 c20ad4d76fe97759aa27a0c99bff6710 +2 54 0 a684eceee76fc522773286a895bc8436 +3 NULL 0 NULL +alter table t1 modify column hash varchar(32) as (md5(handle+1)) persistent, algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +alter table t1 modify column hash varchar(32) as (md5(handle+1)) persistent, algorithm=copy; +select * from t1; +id handle data hash +1 12 0 c51ce410c124a10e0db5e4b97fc2af39 +2 54 0 b53b3a3d6ab90ce0268229151c9bde11 +3 NULL 0 NULL +alter table t1 modify column handle int not null, algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +alter table t1 modify column handle int not null, algorithm=copy; +Warnings: +Warning 1265 Data truncated for column 'handle' at row 3 +select * from t1; +id handle data hash +1 12 0 c51ce410c124a10e0db5e4b97fc2af39 +2 54 0 b53b3a3d6ab90ce0268229151c9bde11 +3 0 0 c4ca4238a0b923820dcc509a6f75849b +alter table t1 drop index handle, algorithm=inplace; +create index data on t1(data) algorithm=inplace; +alter table t1 drop column data, algorithm=inplace; +alter table t1 add column sha varchar(32) as (sha1(handle)) persistent, algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY. +alter table t1 add column sha varchar(32), algorithm=inplace; +alter table t1 drop column hash, algorithm=inplace; +drop table t1; diff --git a/mysql-test/suite/vcol/r/innodb_autoinc_vcol.result b/mysql-test/suite/vcol/r/innodb_autoinc_vcol.result new file mode 100644 index 00000000000..f2d6b4105ff --- /dev/null +++ b/mysql-test/suite/vcol/r/innodb_autoinc_vcol.result @@ -0,0 +1,16 @@ +create table t1 (c2 int as (-c1), c1 int primary key auto_increment) engine=innodb; +insert into t1(c1) values (null),(null),(null); +select * from t1; +c2 c1 +-1 1 +-2 2 +-3 3 +alter table t1 auto_increment = 3; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c2` int(11) AS (-c1) VIRTUAL, + `c1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 +drop table t1; diff --git a/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result b/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result index 44fcae7a6e5..af03cc4d482 100644 --- a/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result +++ b/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result @@ -425,3 +425,29 @@ select * from t1; a b c d set sql_warnings = 0; drop table t1; +# +# MDEV-9093: Persistent computed column is not updated when +# update query contains join +# +CREATE TABLE `t1` ( +`id` bigint(20) NOT NULL, +`name` varchar(254) DEFAULT NULL, +`name_hash` varchar(64) AS (sha1(name)) PERSISTENT, +PRIMARY KEY (`id`) +); +insert into t1(id,name) values (2050, 'name1'),(2051, 'name2'),(2041, 'name3'); +create table t2 (id bigint); +insert into t2 values (2050),(2051),(2041); +select * from t1; +id name name_hash +2041 name3 1aefcd1b0f39da45fa1fd7236f683c907c15ef82 +2050 name1 9b46b0dd3a8083c070c3b9953bb5f3f95c5ab4da +2051 name2 39ea84acf1fef629fef18a9c6f5799bba32ecc25 +update t1 join t2 using(id) set name = concat(name, +'+1') where t1.id in (2051,2041); +select * from t1; +id name name_hash +2041 name3+1 93c9096df48221428de46e146abc9f4f94bf7d2e +2050 name1 9b46b0dd3a8083c070c3b9953bb5f3f95c5ab4da +2051 name2+1 fd4f236320db3956a5ec073c5ec39707d7f05708 +drop table t1,t2; diff --git a/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result b/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result index 66745862c22..351dfd2858c 100644 --- a/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result @@ -363,3 +363,29 @@ select * from t1; a b c d set sql_warnings = 0; drop table t1; +# +# MDEV-9093: Persistent computed column is not updated when +# update query contains join +# +CREATE TABLE `t1` ( +`id` bigint(20) NOT NULL, +`name` varchar(254) DEFAULT NULL, +`name_hash` varchar(64) AS (sha1(name)) PERSISTENT, +PRIMARY KEY (`id`) +); +insert into t1(id,name) values (2050, 'name1'),(2051, 'name2'),(2041, 'name3'); +create table t2 (id bigint); +insert into t2 values (2050),(2051),(2041); +select * from t1; +id name name_hash +2050 name1 9b46b0dd3a8083c070c3b9953bb5f3f95c5ab4da +2051 name2 39ea84acf1fef629fef18a9c6f5799bba32ecc25 +2041 name3 1aefcd1b0f39da45fa1fd7236f683c907c15ef82 +update t1 join t2 using(id) set name = concat(name, +'+1') where t1.id in (2051,2041); +select * from t1; +id name name_hash +2050 name1 9b46b0dd3a8083c070c3b9953bb5f3f95c5ab4da +2051 name2+1 fd4f236320db3956a5ec073c5ec39707d7f05708 +2041 name3+1 93c9096df48221428de46e146abc9f4f94bf7d2e +drop table t1,t2; diff --git a/mysql-test/suite/vcol/t/alter_inplace-9045.test b/mysql-test/suite/vcol/t/alter_inplace-9045.test new file mode 100644 index 00000000000..8f59ba75bce --- /dev/null +++ b/mysql-test/suite/vcol/t/alter_inplace-9045.test @@ -0,0 +1,31 @@ +# +# MDEV-9045 Inconsistent handling of "ALGORITHM=INPLACE" with PERSISTENT generated columns +# +--source include/have_innodb.inc + +create table t1(id int auto_increment primary key, handle int, data bigint not null default 0) engine = innodb; +insert into t1(handle) values(12),(54),(NULL); +select *, md5(handle) from t1; +alter table t1 add index handle(handle), algorithm=inplace; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t1 add column hash varchar(32) as (md5(handle)) persistent, algorithm=inplace; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t1 add column hash varchar(32) as (md5(handle)) persistent, add unique index hash(hash), algorithm=inplace; +alter table t1 add column hash varchar(32) as (md5(handle)) persistent, add unique index hash(hash), algorithm=copy; +select * from t1; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t1 modify column hash varchar(32) as (md5(handle+1)) persistent, algorithm=inplace; +alter table t1 modify column hash varchar(32) as (md5(handle+1)) persistent, algorithm=copy; +select * from t1; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t1 modify column handle int not null, algorithm=inplace; +alter table t1 modify column handle int not null, algorithm=copy; +select * from t1; +alter table t1 drop index handle, algorithm=inplace; +create index data on t1(data) algorithm=inplace; +alter table t1 drop column data, algorithm=inplace; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t1 add column sha varchar(32) as (sha1(handle)) persistent, algorithm=inplace; +alter table t1 add column sha varchar(32), algorithm=inplace; +alter table t1 drop column hash, algorithm=inplace; +drop table t1; diff --git a/mysql-test/suite/vcol/t/innodb_autoinc_vcol.test b/mysql-test/suite/vcol/t/innodb_autoinc_vcol.test new file mode 100644 index 00000000000..2f2ac3d08e1 --- /dev/null +++ b/mysql-test/suite/vcol/t/innodb_autoinc_vcol.test @@ -0,0 +1,9 @@ +--source include/have_innodb.inc + +create table t1 (c2 int as (-c1), c1 int primary key auto_increment) engine=innodb; +insert into t1(c1) values (null),(null),(null); +select * from t1; +alter table t1 auto_increment = 3; +show create table t1; +drop table t1; + diff --git a/mysql-test/t/alter_table_online.test b/mysql-test/t/alter_table_online.test index e8cc285918c..6386a1551e1 100644 --- a/mysql-test/t/alter_table_online.test +++ b/mysql-test/t/alter_table_online.test @@ -7,22 +7,16 @@ drop table if exists t1,t2,t3; --enable_warnings # -# Test of things that can not be done online +# Test of things that can be done online # create table t1 (a int not null primary key, b int, c varchar(80), e enum('a','b')); insert into t1 (a) values (1),(2),(3); ---error ER_ALTER_OPERATION_NOT_SUPPORTED alter online table t1 modify b int default 5; ---error ER_ALTER_OPERATION_NOT_SUPPORTED alter online table t1 change b new_name int; ---error ER_ALTER_OPERATION_NOT_SUPPORTED alter online table t1 modify e enum('a','b','c'); ---error ER_ALTER_OPERATION_NOT_SUPPORTED alter online table t1 comment "new comment"; ---error ER_ALTER_OPERATION_NOT_SUPPORTED -alter online table t1 rename to t2; # No OPs @@ -68,11 +62,14 @@ alter online table t1 modify c varchar(100); alter online table t1 add f int; --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON alter online table t1 engine=memory; +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter online table t1 rename to t2; alter table t1 engine=innodb; alter table t1 add index (b); alter online table t1 add index c (c); alter online table t1 drop index b; +alter online table t1 comment "new comment"; drop table t1; create temporary table t1 (a int not null primary key, b int, c varchar(80), e enum('a','b')); diff --git a/mysql-test/t/alter_user.test b/mysql-test/t/alter_user.test new file mode 100644 index 00000000000..e32d0c29f2e --- /dev/null +++ b/mysql-test/t/alter_user.test @@ -0,0 +1,82 @@ +--source include/not_embedded.inc +--enable_connect_log + + +select * from mysql.user where user = 'root' and host = 'localhost'; +--echo # Test syntax +--echo # +--echo # These 2 selects should have no changes from the first one. +alter user CURRENT_USER; +select * from mysql.user where user = 'root' and host = 'localhost'; +alter user CURRENT_USER(); +select * from mysql.user where user = 'root' and host = 'localhost'; + +create user foo; +select * from mysql.user where user = 'foo'; +alter user foo; +select * from mysql.user where user = 'foo'; + +--echo # Test super privilege works correctly with a read only database. +SET @start_read_only = @@global.read_only; +SET GLOBAL read_only=1; +grant create user on *.* to foo; + +--echo # Currently no super privileges. +connect (a, localhost, foo); +select @@global.read_only; + +--error ER_OPTION_PREVENTS_STATEMENT +alter user foo; + +--echo # Grant super privilege to the user. +connection default; +grant super on *.* to foo; + +--echo # We now have super privilege. We should be able to run alter user. +connect (b, localhost, foo); +alter user foo; + +connection default; +SET GLOBAL read_only = @start_read_only; + +--echo # Test inexistant user. +--error ER_CANNOT_USER +alter user boo; +--echo #--warning ER_CANNOT_USER +alter if exists user boo; + +--echo # Test password related altering. +alter user foo identified by 'something'; +select * from mysql.user where user = 'foo'; + +alter user foo identified by 'something2'; +select * from mysql.user where user = 'foo'; + +alter user foo identified by password '*88C89BE093D4ECF72D039F62EBB7477EA1FD4D63'; +select * from mysql.user where user = 'foo'; + +alter user foo identified with 'somecoolplugin'; +select * from mysql.user where user = 'foo'; + +alter user foo identified with 'somecoolplugin' using 'somecoolpassphrase'; +select * from mysql.user where user = 'foo'; + +--echo # Test ssl related altering. +alter user foo identified by 'something' require SSL; +select * from mysql.user where user = 'foo'; + +alter user foo identified by 'something' require X509; +select * from mysql.user where user = 'foo'; + +alter user foo identified by 'something' +require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; +select * from mysql.user where user = 'foo'; + +--echo # Test resource limits altering. +alter user foo with MAX_QUERIES_PER_HOUR 10 + MAX_UPDATES_PER_HOUR 20 + MAX_CONNECTIONS_PER_HOUR 30 + MAX_USER_CONNECTIONS 40; +select * from mysql.user where user = 'foo'; +drop user foo; +--disable_connect_log diff --git a/mysql-test/t/auth_named_pipe-master.opt b/mysql-test/t/auth_named_pipe-master.opt new file mode 100644 index 00000000000..e534ae1eae5 --- /dev/null +++ b/mysql-test/t/auth_named_pipe-master.opt @@ -0,0 +1 @@ +--loose-enable-named-pipe diff --git a/mysql-test/t/auth_named_pipe.test b/mysql-test/t/auth_named_pipe.test new file mode 100644 index 00000000000..00577fbef05 --- /dev/null +++ b/mysql-test/t/auth_named_pipe.test @@ -0,0 +1,23 @@ +--source include/windows.inc + +INSTALL SONAME 'auth_named_pipe'; + +--replace_result $USERNAME USERNAME +eval CREATE USER '$USERNAME' IDENTIFIED WITH named_pipe; +# Connect using named pipe, correct username +connect(pipe_con,localhost,$USERNAME,,,,,PIPE); +--replace_result $USERNAME USERNAME +SELECT USER(),CURRENT_USER(); +disconnect pipe_con; +connection default; +--replace_result $USERNAME USERNAME +eval DROP USER '$USERNAME'; + +# test invalid user name +CREATE USER nosuchuser IDENTIFIED WITH named_pipe; +--disable_query_log +--error ER_ACCESS_DENIED_NO_PASSWORD_ERROR +connect(pipe_con,localhost,nosuchuser,,,,,PIPE); +--enable_query_log +DROP USER nosuchuser; +UNINSTALL SONAME 'auth_named_pipe';
\ No newline at end of file diff --git a/mysql-test/t/compound.test b/mysql-test/t/compound.test index 1c5d12a1665..cabdf96e00e 100644 --- a/mysql-test/t/compound.test +++ b/mysql-test/t/compound.test @@ -150,3 +150,10 @@ select a from t1 having a > 1| begin not atomic select a from t1 having a > 1; end| drop table t1| +--echo # +--echo # MDEV-8615: Assertion `m_cpp_buf <= begin_ptr && +--echo # begin_ptr <= m_cpp_buf + m_buf_length' failed in +--echo # Lex_input_stream::body_utf8_start +--echo # +--error ER_PARSE_ERROR +--query b' diff --git a/mysql-test/t/connect2.cnf b/mysql-test/t/connect2.cnf new file mode 100644 index 00000000000..0acd221b871 --- /dev/null +++ b/mysql-test/t/connect2.cnf @@ -0,0 +1,9 @@ +!include include/default_my.cnf + +[mysqld.1] +extra-port= @ENV.MASTER_EXTRA_PORT +extra-max-connections=2 +thread_handling=pool-of-threads + +[ENV] +MASTER_EXTRA_PORT= @OPT.port diff --git a/mysql-test/t/connect2.test b/mysql-test/t/connect2.test new file mode 100644 index 00000000000..b4614a65a91 --- /dev/null +++ b/mysql-test/t/connect2.test @@ -0,0 +1,84 @@ +# This test is to check various cases of connections, some which require +# DBUG + +# This test makes no sense with the embedded server +--source include/not_embedded.inc +--source include/have_debug.inc +call mtr.add_suppression("Allocation failed"); +SET @old_debug= @@session.debug; +set @old_thread_cache_size=@@global.thread_cache_size; + +# Test connections to the + +connect(con1,localhost,root,,test,,); +select 1; +disconnect con1; +connection default; +set global debug_dbug='+d,simulate_failed_connection_1'; +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 1041,2013 +connect(con1,localhost,root,,test,,); +connection default; +set global debug_dbug=@old_debug; +set global debug_dbug='+d,simulate_failed_connection_2'; +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT +--error 1041,2013 +connect(con1,localhost,root,,test,,); +--enable_result_log +connection default; +set global debug_dbug=@old_debug; +connect(con1,localhost,root,,test,,); +select 1; +disconnect con1; + +# Test connections to the extra port. + +connect(con1,localhost,root,,test,$MASTER_EXTRA_PORT,); +select 1; +disconnect con1; +connection default; +set global debug_dbug='+d,simulate_failed_connection_1'; +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_EXTRA_PORT MASTER_PORT +--error 1041,2013 +connect(con1,localhost,root,,test,$MASTER_EXTRA_PORT,); +connection default; +set global debug_dbug=@old_debug; +set global debug_dbug='+d,simulate_failed_connection_2'; +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_EXTRA_PORT MASTER_PORT +--error 1041,2013 +connect(con1,localhost,root,,test,$MASTER_EXTRA_PORT,); +connection default; +set global debug_dbug=@old_debug; +connect(con1,localhost,root,,test,$MASTER_EXTRA_PORT,); +select 1; +disconnect con1; +connection default; + +# +# Test thread cache +# +set @@global.thread_cache_size=2; +connect(con1,localhost,root,,test,$MASTER_EXTRA_PORT,); +select 1; +connect(con2,localhost,root,,test,$MASTER_EXTRA_PORT,); +select 1; +disconnect con1; +disconnect con2; +connection default; +set global debug_dbug='+d,simulate_failed_connection_2'; +--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_EXTRA_PORT MASTER_PORT +--error 1041,2013 +connect(con1,localhost,root,,test,$MASTER_EXTRA_PORT,); +connection default; + +# Check that threads_connected didn't count aborted connections +let $count_sessions= 1; +--source include/wait_until_count_sessions.inc +show status like "Threads_connected"; + +# +# Cleanup +# + +set global debug_dbug=@old_debug; +set global thread_cache_size=@old_thread_cache_size; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 6751c92f0be..10ee41ca2aa 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -1737,6 +1737,27 @@ create table t1(a enum('','')); drop table t1; set @@session.collation_server=default; +--echo # +--echo # MDEV-7765: Crash (Assertion `!table || (!table->write_set || +--echo # bitmap_is_set(table->write_set, field_index) || +--echo # bitmap_is_set(table->vcol_set, field_index))' fails) +--echo # on using function over not created table +--echo # + +DELIMITER |; +CREATE function f1() returns int +BEGIN + declare n int; + set n:= (select count(*) from t1); + return n; +end| +DELIMITER ;| +-- error ER_NO_SUCH_TABLE +create table t1 as select f1(); +drop function f1; + +--echo End of 5.5 tests + # # MDEV-4880 Attempt to create a table without columns produces ER_ILLEGAL_HA instead of ER_TABLE_MUST_HAVE_COLUMNS # diff --git a/mysql-test/t/create_user.test b/mysql-test/t/create_user.test new file mode 100644 index 00000000000..f04cb3e302a --- /dev/null +++ b/mysql-test/t/create_user.test @@ -0,0 +1,58 @@ +--source include/not_embedded.inc + +create user foo; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password'; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require SSL; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require X509; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require CIPHER 'cipher'; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require ISSUER 'issuer'; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require SUBJECT 'subject'; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require CIPHER 'cipher' + SUBJECT 'subject'; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo identified by 'password' require CIPHER 'cipher' + AND SUBJECT 'subject' + AND ISSUER 'issuer'; +select * from mysql.user where user = 'foo'; +drop user foo; + +create user foo, foo2 identified by 'password' require CIPHER 'cipher' + AND SUBJECT 'subject' + AND ISSUER 'issuer'; +select * from mysql.user where user like 'foo'; + +--echo #--warning ER_USER_CREATE_EXISTS +create user if not exists foo, foo2 identified by 'password2' + require CIPHER 'cipher2' AND SUBJECT 'subject2' AND ISSUER 'issuer2'; +select * from mysql.user where user like 'foo'; +drop user foo, foo2; + +create user foo with MAX_QUERIES_PER_HOUR 10 + MAX_UPDATES_PER_HOUR 20 + MAX_CONNECTIONS_PER_HOUR 30 + MAX_USER_CONNECTIONS 40; +select * from mysql.user where user like 'foo'; +drop user foo; diff --git a/mysql-test/t/cte_grant.test b/mysql-test/t/cte_grant.test new file mode 100644 index 00000000000..44fd4a0bc6e --- /dev/null +++ b/mysql-test/t/cte_grant.test @@ -0,0 +1,79 @@ +# Can't test with embedded server +-- source include/not_embedded.inc + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + +connect (root,localhost,root,,test); +connection root; + +--disable_warnings +create database mysqltest; +--enable_warnings + +create user mysqltest_1@localhost; +connect (user1,localhost,mysqltest_1,,test); +connection user1; + +connection root; + +create table mysqltest.t1 (a int, b int); +insert into mysqltest.t1 values (2,10), (1,30); +create table mysqltest.t2 (c int, d char(32)); +insert into mysqltest.t2 values (1,'xxx'), (1,'zzz'); + +grant select on mysqltest.t1 to mysqltest_1@localhost; +grant select (c) on mysqltest.t2 to mysqltest_1@localhost; + +connection user1; +with t as (select c from mysqltest.t2 where c < 2) +select t.c,t1.b from t,mysqltest.t1 where t.c=t1.a; +--error ER_COLUMNACCESS_DENIED_ERROR +select t.c,t.d,t1.b +from (select c,d from mysqltest.t2 where c < 2) as t, mysqltest.t1 +where t.c=t1.a; +--error ER_COLUMNACCESS_DENIED_ERROR +with t as (select c,d from mysqltest.t2 where c < 2) +select t.c,t.d,t1.b from t,mysqltest.t1 where t.c=t1.a; + +connection root; + +create view mysqltest.v1(f1,f2) as +with t as (select c from mysqltest.t2 where c < 2) +select t.c,t1.b from t,mysqltest.t1 where t.c=t1.a; +create view mysqltest.v2(c,d) as +with t as (select a from mysqltest.t1 where a>=3) +select t.a,b from t,mysqltest.t1 where mysqltest.t1.a = t.a; + +grant select on mysqltest.v1 to mysqltest_1@localhost; +grant select (c) on mysqltest.v2 to mysqltest_1@localhost; +grant create view on mysqltest.* to mysqltest_1@localhost; + +connection user1; + +create view mysqltest.v3(c,d) as +with t as (select c from mysqltest.t2 where c < 2) +select t.c,t1.b from t,mysqltest.t1 where t.c=t1.a; +--error ER_COLUMNACCESS_DENIED_ERROR +create view mysqltest.v4(f1,f2,f3) as +with t as (select c,d from mysqltest.t2 where c < 2) +select t.c,t.d,t1.b from t,mysqltest.t1 where t.c=t1.a; + +select * from mysqltest.v1; + +select c from mysqltest.v2; +# there are no privileges on column 'd' +--error ER_COLUMNACCESS_DENIED_ERROR +select d from mysqltest.v2; + +--error ER_TABLEACCESS_DENIED_ERROR +select * from mysqltest.v3; +connection root; +grant select on mysqltest.v3 to mysqltest_1@localhost; +connection user1; +select * from mysqltest.v3; + +connection root; +revoke all privileges on mysqltest.v1 from mysqltest_1@localhost; +drop user mysqltest_1@localhost; +drop database mysqltest;
\ No newline at end of file diff --git a/mysql-test/t/cte_nonrecursive.test b/mysql-test/t/cte_nonrecursive.test new file mode 100644 index 00000000000..5a6e07e0c0c --- /dev/null +++ b/mysql-test/t/cte_nonrecursive.test @@ -0,0 +1,436 @@ +create table t1 (a int, b varchar(32)); +insert into t1 values + (4,'aaaa' ), (7,'bb'), (1,'ccc'), (4,'dd'); +insert into t1 values + (3,'eee'), (7,'bb'), (1,'fff'), (4,'ggg'); +create table t2 (c int); +insert into t2 values + (2), (4), (5), (3); + +--echo # select certain field in the specification of t +with t as (select a from t1 where b >= 'c') + select * from t2,t where t2.c=t.a; +select * from t2, (select a from t1 where b >= 'c') as t + where t2.c=t.a; +explain +with t as (select a from t1 where b >= 'c') + select * from t2,t where t2.c=t.a; +explain +select * from t2, (select a from t1 where b >= 'c') as t + where t2.c=t.a; + +--echo # select '*' in the specification of t +with t as (select * from t1 where b >= 'c') + select * from t2,t where t2.c=t.a; +select * from t2, (select * from t1 where b >= 'c') as t + where t2.c=t.a; +explain +with t as (select * from t1 where b >= 'c') + select * from t2,t where t2.c=t.a; +explain +select * from t2, (select * from t1 where b >= 'c') as t + where t2.c=t.a; + +--echo # rename fields returned by the specication when defining t +with t(f1,f2) as (select * from t1 where b >= 'c') + select * from t2,t where t2.c=t.f1; +explain +with t(f1,f2) as (select * from t1 where b >= 'c') + select * from t2,t where t2.c=t.f1; + +--echo # materialized query specifying t +with t as (select a, count(*) from t1 where b >= 'c' group by a) + select * from t2,t where t2.c=t.a; +select * from t2, (select a, count(*) from t1 where b >= 'c' group by a) as t + where t2.c=t.a; +explain +with t as (select a, count(*) from t1 where b >= 'c' group by a) + select * from t2,t where t2.c=t.a; +explain +select * from t2, (select a, count(*) from t1 where b >= 'c' group by a) as t + where t2.c=t.a; + +--echo # specivication of t contains having +with t as (select a, count(*) from t1 where b >= 'c' + group by a having count(*)=1 ) + select * from t2,t where t2.c=t.a; +select * from t2, (select a, count(*) from t1 where b >= 'c' + group by a having count(*)=1) t + where t2.c=t.a; + +--echo # main query contains having +with t as (select * from t2 where c <= 4) + select a, count(*) from t1,t where t1.a=t.c group by a having count(*)=1; +select a, count(*) from t1, (select * from t2 where c <= 4) t + where t1.a=t.c group by a having count(*)=1; + +--echo # main query contains group by + order by +with t as (select * from t2 where c <= 4 ) + select a, count(*) from t1,t where t1.a=t.c group by a order by count(*); +select a, count(*) from t1, (select * from t2 where c <= 4 ) t + where t1.a=t.c group by a order by count(*); + +--echo # main query contains group by + order by + limit +with t as (select * from t2 where c <= 4 ) + select a, count(*) from t1,t + where t1.a=t.c group by a order by count(*) desc limit 1; +select a, count(*) from t1, (select * from t2 where c <= 4 ) t + where t1.a=t.c group by a order by count(*) desc limit 1; + + +--echo # t is used in a subquery +with t as (select a from t1 where a<5) + select * from t2 where c in (select a from t); +select * from t2 + where c in (select a from (select a from t1 where a<5) as t); +explain +with t as (select a from t1 where a<5) + select * from t2 where c in (select a from t); +explain +select * from t2 + where c in (select a from (select a from t1 where a<5) as t); + +--echo # materialized t is used in a subquery +with t as (select count(*) as c from t1 where b >= 'c' group by a) + select * from t2 where c in (select c from t); +select * from t2 + where c in (select c from (select count(*) as c from t1 + where b >= 'c' group by a) as t); +explain +with t as (select count(*) as c from t1 where b >= 'c' group by a) + select * from t2 where c in (select c from t); +explain +select * from t2 + where c in (select c from (select count(*) as c from t1 + where b >= 'c' group by a) as t); + +--echo # two references to t specified by a query +--echo # selecting a field: both in main query +with t as (select a from t1 where b >= 'c') + select * from t as r1, t as r2 where r1.a=r2.a; +select * from (select a from t1 where b >= 'c') as r1, + (select a from t1 where b >= 'c') as r2 + where r1.a=r2.a; +explain +with t as (select a from t1 where b >= 'c') + select * from t as r1, t as r2 where r1.a=r2.a; +explain +select * from (select a from t1 where b >= 'c') as r1, + (select a from t1 where b >= 'c') as r2 + where r1.a=r2.a; + +--echo # two references to materialized t: both in main query +with t as (select distinct a from t1 where b >= 'c') + select * from t as r1, t as r2 where r1.a=r2.a; +select * from (select distinct a from t1 where b >= 'c') as r1, + (select distinct a from t1 where b >= 'c') as r2 + where r1.a=r2.a; +explain +with t as (select distinct a from t1 where b >= 'c') + select * from t as r1, t as r2 where r1.a=r2.a; +explain +select * from (select distinct a from t1 where b >= 'c') as r1, + (select distinct a from t1 where b >= 'c') as r2 + where r1.a=r2.a; + +--echo # two references to t specified by a query +--echo # selecting all fields: both in main query +with t as (select * from t1 where b >= 'c') + select * from t as r1, t as r2 where r1.a=r2.a; +select * from (select * from t1 where b >= 'c') as r1, + (select * from t1 where b >= 'c') as r2 + where r1.a=r2.a; +explain +with t as (select * from t1 where b >= 'c') + select * from t as r1, t as r2 where r1.a=r2.a; +explain +select * from (select * from t1 where b >= 'c') as r1, + (select * from t1 where b >= 'c') as r2 + where r1.a=r2.a; + +--echo # two references to t specifying explicitly column names +with t(c) as (select a from t1 where b >= 'c') + select * from t r1, t r2 where r1.c=r2.c; + +--echo # specification of t contains union +with t as (select a from t1 where b >= 'f' + union + select c as a from t2 where c < 4) + select * from t2,t where t2.c=t.a; +select * from t2, + (select a from t1 where b >= 'f' + union + select c as a from t2 where c < 4) as t + where t2.c=t.a; +explain +with t as (select a from t1 where b >= 'f' + union + select c as a from t2 where c < 4) + select * from t2,t where t2.c=t.a; +explain +select * from t2, + (select a from t1 where b >= 'f' + union + select c as a from t2 where c < 4) as t + where t2.c=t.a; + +--echo # t is defined in the with clause of a subquery +select t1.a,t1.b from t1,t2 + where t1.a>t2.c and + t2.c in (with t as (select * from t1 where t1.a<5) + select t2.c from t2,t where t2.c=t.a); +select t1.a,t1.b from t1,t2 + where t1.a>t2.c and + t2.c in (select t2.c + from t2,(select * from t1 where t1.a<5) as t + where t2.c=t.a); +explain +select t1.a,t1.b from t1,t2 + where t1.a>t2.c and + t2.c in (with t as (select * from t1 where t1.a<5) + select t2.c from t2,t where t2.c=t.a); +explain +select t1.a,t1.b from t1,t2 + where t1.a>t2.c and + t2.c in (select t2.c + from t2,(select * from t1 where t1.a<5) as t + where t2.c=t.a); + +--echo # two different definitions of t: one in the with clause of the main query, +--echo # the other in the with clause of a subquery +with t as (select c from t2 where c >= 4) + select t1.a,t1.b from t1,t + where t1.a=t.c and + t.c in (with t as (select * from t1 where t1.a<5) + select t2.c from t2,t where t2.c=t.a); +select t1.a,t1.b from t1, (select c from t2 where c >= 4) as t + where t1.a=t.c and + t.c in (select t2.c from t2, (select * from t1 where t1.a<5) as t + where t2.c=t.a); +explain +with t as (select c from t2 where c >= 4) + select t1.a,t1.b from t1,t + where t1.a=t.c and + t.c in (with t as (select * from t1 where t1.a<5) + select t2.c from t2,t where t2.c=t.a); +explain +select t1.a,t1.b from t1, (select c from t2 where c >= 4) as t + where t1.a=t.c and + t.c in (select t2.c from t2, (select * from t1 where t1.a<5) as t + where t2.c=t.a); + +--echo # another with table tt is defined in the with clause of a subquery +--echo # from the specification of t +with t as (select * from t1 + where a>2 and + b in (with tt as (select * from t2 where t2.c<5) + select t1.b from t1,tt where t1.a=tt.c)) + select t.a, count(*) from t1,t where t1.a=t.a group by t.a; +select t.a, count(*) + from t1, + (select * from t1 + where a>2 and + b in (select t1.b + from t1, + (select * from t2 where t2.c<5) as tt + where t1.a=tt.c)) as t + where t1.a=t.a group by t.a; +explain +with t as (select * from t1 + where a>2 and + b in (with tt as (select * from t2 where t2.c<5) + select t1.b from t1,tt where t1.a=tt.c)) + select t.a, count(*) from t1,t where t1.a=t.a group by t.a; +explain +select t.a, count(*) + from t1, + (select * from t1 + where a>2 and + b in (select t1.b + from t1, + (select * from t2 where t2.c<5) as tt + where t1.a=tt.c)) as t + where t1.a=t.a group by t.a; + +--echo # with clause in the specification of a derived table +select * + from t1, + (with t as (select a from t1 where b >= 'c') + select * from t2,t where t2.c=t.a) as tt + where t1.b > 'f' and tt.a=t1.a; +select * + from t1, + (select * from t2, + (select a from t1 where b >= 'c') as t + where t2.c=t.a) as tt + where t1.b > 'f' and tt.a=t1.a; +explain +select * + from t1, + (with t as (select a from t1 where b >= 'c') + select * from t2,t where t2.c=t.a) as tt + where t1.b > 'f' and tt.a=t1.a; +explain +select * + from t1, + (select * from t2, + (select a from t1 where b >= 'c') as t + where t2.c=t.a) as tt + where t1.b > 'f' and tt.a=t1.a; + +--echo # with claused in the specification of a view +create view v1 as +with t as (select a from t1 where b >= 'c') + select * from t2,t where t2.c=t.a; +show create view v1; +select * from v1; +explain +select * from v1; + +--echo # with claused in the specification of a materialized view +create view v2 as +with t as (select a, count(*) from t1 where b >= 'c' group by a) + select * from t2,t where t2.c=t.a; +show create view v2; +select * from v2; +explain +select * from v2; + +--echo # with clause in the specification of a view that whose definition +--echo # table alias for a with table +create view v3 as +with t(c) as (select a from t1 where b >= 'c') +select * from t r1 where r1.c=4; +show create view v3; +select * from v3; + +--echo # with clause in the specification of a view that whose definition +--echo # two table aliases for for the same with table +create view v4(c,d) as +with t(c) as (select a from t1 where b >= 'c') +select * from t r1, t r2 where r1.c=r2.c and r2.c=4; +show create view v4; +select * from v4; +explain +select * from v4; + +drop view v1,v2,v3,v4; + + +--echo # currently any views containing with clause are not updatable +create view v1(a) as +with t as (select a from t1 where b >= 'c') + select t.a from t2,t where t2.c=t.a; +--error ER_NON_UPDATABLE_TABLE +update v1 set a=0 where a > 4; +drop view v1; + + +--echo # prepare of a query containing a definition of a with table t +prepare stmt1 from " +with t as (select a from t1 where b >= 'c') + select * from t2,t where t2.c=t.a; +"; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; + +--echo # prepare of a query containing a definition of a materialized t +prepare stmt1 from " +with t as (select a, count(*) from t1 where b >= 'c' group by a) + select * from t2,t where t2.c=t.a; +"; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; + +--echo # prepare of a query containing two references to with table t +prepare stmt1 from " +with t as (select * from t1 where b >= 'c') + select * from t as r1, t as r2 where r1.a=r2.a; +"; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; + +--ERROR ER_WITH_COL_WRONG_LIST +with t(f) as (select * from t1 where b >= 'c') + select * from t2,t where t2.c=t.f1; + +--ERROR ER_DUP_FIELDNAME +with t(f1,f1) as (select * from t1 where b >= 'c') + select * from t2,t where t2.c=t.f1; + +--ERROR ER_DUP_QUERY_NAME +with t as (select * from t2 where c>3), + t as (select a from t1 where a>2) + select * from t,t1 where t1.a=t.c; + +--ERROR ER_WRONG_ORDER_IN_WITH_CLAUSE +with t as (select a from s where a<5), + s as (select a from t1 where b>='d') + select * from t,s where t.a=s.a; + +with recursive + t as (select a from s where a<5), + s as (select a from t1 where b>='d') + select * from t,s where t.a=s.a; + +--ERROR ER_RECURSIVE_QUERY_IN_WITH_CLAUSE +with recursive t as (select * from s where a>2), + s as (select a from t1,r where t1.a>r.c), + r as (select c from t,t2 where t.a=t2.c) + select * from r where r.c<7; + +--ERROR ER_RECURSIVE_QUERY_IN_WITH_CLAUSE +with t as (select * from s where a>2), + s as (select a from t1,r where t1.a>r.c), + r as (select c from t,t2 where t.a=t2.c) + select * from r where r.c<7; + +--ERROR ER_RECURSIVE_QUERY_IN_WITH_CLAUSE +with t as (select * from t1 + where a in (select c from s where b<='ccc') and b>'b'), + s as (select * from t1,t2 + where t1.a=t2.c and t1.c in (select a from t where a<5)) + select * from s where s.b>'aaa'; + +--ERROR ER_RECURSIVE_QUERY_IN_WITH_CLAUSE +with t as (select * from t1 where b>'aaa' and b <='d') + select t.b from t,t2 + where t.a=t2.c and + t2.c in (with s as (select t1.a from s,t1 where t1.a=s.a and t1.b<'c') + select * from s); +--echo #erroneous definition of unreferenced with table t +--ERROR ER_BAD_FIELD_ERROR +with t as (select count(*) from t1 where d>='f' group by a) + select t1.b from t2,t1 where t1.a = t2.c; + +with t as (select count(*) from t1 where b>='f' group by a) + select t1.b from t2,t1 where t1.a = t2.c; + +--echo #erroneous definition of s referring to unreferenced t +--ERROR ER_BAD_FIELD_ERROR +with t(d) as (select count(*) from t1 where b<='ccc' group by b), + s as (select * from t1 where a in (select t2.d from t2,t where t2.c=t.d)) + select t1.b from t1,t2 where t1.a=t2.c; +--ERROR ER_BAD_FIELD_ERROR +with t(d) as (select count(*) from t1 where b<='ccc' group by b), + s as (select * from t1 where a in (select t2.c from t2,t where t2.c=t.c)) + select t1.b from t1,t2 where t1.a=t2.c; + +with t(d) as (select count(*) from t1 where b<='ccc' group by b), + s as (select * from t1 where a in (select t2.c from t2,t where t2.c=t.d)) + select t1.b from t1,t2 where t1.a=t2.c; + +--echo #erroneous definition of unreferenced with table t +--ERROR ER_WITH_COL_WRONG_LIST +with t(f) as (select * from t1 where b >= 'c') + select t1.b from t2,t1 where t1.a = t2.c; + +--echo #erroneous definition of unreferenced with table t +--ERROR ER_DUP_FIELDNAME +with t(f1,f1) as (select * from t1 where b >= 'c') + select t1.b from t2,t1 where t1.a = t2.c; + +drop table t1,t2; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 426985a6d42..85ffed943cf 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1577,13 +1577,13 @@ SET NAMES utf8; --echo # --echo # Bug#57687 crash when reporting duplicate group_key error and utf8 ---echo # Make sure to modify this when Bug#58081 is fixed. +--echo # Bug#58081 Duplicate entry error when doing GROUP BY +--echo # MDEV-9332 Bug after upgrade to 10.1.10 --echo # SET NAMES utf8; CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (0), (0), (1), (0), (0); ---error ER_DUP_ENTRY -SELECT COUNT(*) FROM t1, t1 t2 +SELECT COUNT(*) FROM t1, t1 t2 GROUP BY INSERT('', t2.a, t1.a, (@@global.max_binlog_size)); DROP TABLE t1; @@ -1872,5 +1872,81 @@ DROP TABLE t1; --echo # +--echo # MDEV-7231 Field ROUTINE_DEFINITION in INFORMATION_SCHEMA.`ROUTINES` contains broken procedure body when used shielding quotes inside. +--echo # +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN +SELECT CONCAT('ABC = ''',1,''''), CONCAT('ABC = ',2); +SELECT '''', """", '\'', "\""; +SELECT '<tab> <tab>\t<tab>'; +SELECT '<nl> +<nl>\n<nl>'; +SELECT 'test'; +SELECT 'tëst'; +SELECT 'test\0'; +SELECT 'tëst\0'; +SELECT _binary'test'; +SELECT _binary'test\0'; +SELECT N'''', N"""", N'\'', N"\""; +SELECT N'<tab> <tab>\t<tab>'; +SELECT N'<nl> +<nl>\n<nl>'; +SELECT N'test'; +SELECT N'tëst'; +SELECT N'test\0'; +SELECT N'tëst\0'; +END$$ +DELIMITER ;$$ +SELECT ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA='test' AND SPECIFIC_NAME ='p1'; +SELECT body_utf8 FROM mysql.proc WHERE name='p1'; +DROP PROCEDURE p1; + +SET @@SQL_MODE='NO_BACKSLASH_ESCAPES'; +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN +SELECT CONCAT('ABC = ''',1,''''), CONCAT('ABC = ',2); +SELECT '''', """"; +SELECT '<tab> <tab>\t<tab>'; +SELECT '<nl> +<nl>\n<nl>'; +SELECT 'test'; +SELECT 'tëst'; +SELECT 'test\0'; +SELECT 'tëst\0'; +SELECT _binary'test'; +SELECT _binary'test\0'; +SELECT N'''', N""""; +SELECT N'<tab> <tab>\t<tab>'; +SELECT N'<nl> +<nl>\n<nl>'; +SELECT N'test'; +SELECT N'tëst'; +SELECT N'test\0'; +SELECT N'tëst\0'; +END$$ +DELIMITER ;$$ +SELECT ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA='test' AND SPECIFIC_NAME ='p1'; +SELECT body_utf8 FROM mysql.proc WHERE name='p1'; +DROP PROCEDURE p1; +SET @@SQL_MODE=default; + + +# TODO: Uncomment the below test whe we fix: +# MDEV-9623INFORMATION_SCHEMA.ROUTINES.ROUTINE_DEFINITION does not handle binary literals well +# +#SET NAMES binary; +#CREATE FUNCTION f1() RETURNS TEXT RETURN CONCAT('i','й'); +#SELECT ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES +#WHERE ROUTINE_SCHEMA='test' AND SPECIFIC_NAME ='f1'; +#SELECT body_utf8 FROM mysql.proc WHERE name='f1'; +#DROP FUNCTION f1; +#SET NAMES utf8; + + +--echo # --echo # End of 10.1 tests --echo # diff --git a/mysql-test/t/ctype_utf8mb4.test b/mysql-test/t/ctype_utf8mb4.test index 3f2b6000597..2fe9b5e6544 100644 --- a/mysql-test/t/ctype_utf8mb4.test +++ b/mysql-test/t/ctype_utf8mb4.test @@ -1905,5 +1905,17 @@ SET NAMES utf8mb4; SELECT * FROM `testðŸ˜ðŸ˜test`; --echo # +--echo # MDEV-7231 Field ROUTINE_DEFINITION in INFORMATION_SCHEMA.`ROUTINES` contains broken procedure body when used shielding quotes inside. +--echo # +# Non-BMP characters should be replaced to '?' in ROUTINE_DEFINITION/body_utf8 +SET NAMES utf8mb4; +CREATE FUNCTION f1() RETURNS TEXT CHARACTER SET utf8mb4 +RETURN CONCAT('😎','x😎','😎y','x😎y'); +SELECT ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES +WHERE ROUTINE_SCHEMA='test' AND SPECIFIC_NAME ='f1'; +SELECT body_utf8 FROM mysql.proc WHERE name='f1'; +DROP FUNCTION f1; + +--echo # --echo # End of 10.1 tests --echo # diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test index 1898d1a4691..2886dff8f91 100644 --- a/mysql-test/t/delayed.test +++ b/mysql-test/t/delayed.test @@ -457,7 +457,7 @@ SELECT * FROM t1 WHERE a=0; --echo # Connection con1 connection con1; --echo # Sending: ---send ALTER TABLE t1 COMMENT 'test' +--send ALTER TABLE t1 MODIFY a INT UNSIGNED; --echo # Connection default connection default; @@ -465,7 +465,7 @@ connection default; let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE state = "Waiting for table metadata lock" - AND info = "ALTER TABLE t1 COMMENT 'test'"; + AND info LIKE "ALTER TABLE t1%"; --source include/wait_condition.inc --error ER_LOCK_DEADLOCK INSERT DELAYED INTO t1 VALUES (3); diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index 38636b0e971..c78613e4304 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -538,6 +538,296 @@ select x.id, message from (select id from t1) x left join where coalesce(message,0) <> 0; drop table t1,t2; +--echo # +--echo # MDEV-7827: Assertion `!table || (!table->read_set || +--echo # bitmap_is_set(table->read_set, field_index))' failed +--echo # in Field_long::val_str on EXPLAIN EXTENDED +--echo # + +CREATE TABLE t1 (f1 INT, f2 INT, KEY(f2)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (6,9); + +CREATE TABLE t2 (f3 INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (2),(0); + +EXPLAIN EXTENDED +SELECT f1 FROM ( SELECT * FROM t1 ) AS sq +WHERE f1 IN ( + SELECT f3 FROM t2 WHERE f2 IN ( + SELECT f3 FROM t2 HAVING f3 >= 8 + ) +); + +DROP TABLE t2,t1; + +--echo # +--echo # MDEV-9462: Out of memory using explain on 2 empty tables +--echo # + +CREATE TABLE `t1` ( + `REC_GROUP` char(2) DEFAULT NULL, + `CLIENT_INFO` text CHARACTER SET utf8, + `NAME` text, + `PHONE_NUMBER` text, + `ATTENTION_NAME` text, + `PAYMENT_TERM` text CHARACTER SET utf8, + `CREDIT_LIMIT` decimal(12,2) DEFAULT NULL, + `LAST_PAY_DATE` text CHARACTER SET utf8, + `TOTAL` double DEFAULT NULL, + `TOTAL_MCL` double DEFAULT NULL, + `TOTAL_MFS` double DEFAULT NULL, + `TOTAL_MIS` double DEFAULT NULL, + `BEFORE_DUE_7_MCL` double DEFAULT NULL, + `BEFORE_DUE_7_MFS` double DEFAULT NULL, + `BEFORE_DUE_7_MIS` double DEFAULT NULL, + `PER1_MCL` double DEFAULT NULL, + `PER1_MFS` double DEFAULT NULL, + `PER1_MIS` double DEFAULT NULL, + `PER2_MCL` double DEFAULT NULL, + `PER2_MFS` double DEFAULT NULL, + `PER2_MIS` double DEFAULT NULL, + `PER3_MCL` double DEFAULT NULL, + `PER3_MFS` double DEFAULT NULL, + `PER3_MIS` double DEFAULT NULL, + `PER4_MCL` double DEFAULT NULL, + `PER4_MFS` double DEFAULT NULL, + `PER4_MIS` double DEFAULT NULL, + `PER5_MCL` double DEFAULT NULL, + `PER5_MFS` double DEFAULT NULL, + `PER5_MIS` double DEFAULT NULL, + `PER6_MCL` double DEFAULT NULL, + `PER6_MFS` double DEFAULT NULL, + `PER6_MIS` double DEFAULT NULL, + `PER7_MCL` double DEFAULT NULL, + `PER7_MFS` double DEFAULT NULL, + `PER7_MIS` double DEFAULT NULL, + `BEFORE_DUE_7` double DEFAULT NULL, + `PER1` double DEFAULT NULL, + `PER2` double DEFAULT NULL, + `PER3` double DEFAULT NULL, + `PER4` double DEFAULT NULL, + `PER5` double DEFAULT NULL, + `PER6` double DEFAULT NULL, + `PER7` double DEFAULT NULL, + `REF` varchar(30) DEFAULT NULL, + `TYPE` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL +); + + +CREATE TABLE `t2` ( + `RECEIVABLE_GROUP` char(2) DEFAULT NULL, + `CLIENT_NUMBER` varchar(35) DEFAULT NULL, + `CLIENT_NAME` varchar(73) DEFAULT NULL, + `PHONE_NUMBER` char(12) DEFAULT NULL, + `ATTENTION_NAME` char(26) DEFAULT NULL, + `PAYMENT_TERM` varchar(26) CHARACTER SET utf8 DEFAULT NULL, + `CREDIT_LIMIT` decimal(12,2) DEFAULT NULL, + `LAST_PAY_DATE` varchar(42) CHARACTER SET utf8 DEFAULT NULL, + `TOTAL` decimal(12,2) DEFAULT NULL, + `BEFORE_DUE_7` decimal(12,2) DEFAULT NULL, + `PER1` decimal(12,2) DEFAULT NULL, + `PER2` decimal(12,2) DEFAULT NULL, + `PER3` decimal(12,2) DEFAULT NULL, + `PER4` decimal(12,2) DEFAULT NULL, + `PER5` decimal(12,2) DEFAULT NULL, + `PER6` decimal(12,2) DEFAULT NULL, + `PER7` decimal(12,2) DEFAULT NULL, + `DIVISION` varchar(3) CHARACTER SET utf8 NOT NULL, + `CLIENT_INFO` varchar(294) CHARACTER SET utf8 DEFAULT NULL, + `EXCHANGE_RATE` double NOT NULL, + `REF` varchar(30) DEFAULT NULL +); + +explain +SELECT A.RECEIVABLE_GROUP,A.CLIENT_INFO,A.CLIENT_NAME,A.PHONE_NUMBER,A.ATTENTION_NAME,A.PAYMENT_TERM,A.CREDIT_LIMIT,A.LAST_PAY_DATE,A.TOTAL, +COALESCE(B.TOTAL_MCL,0) AS TOTAL_MCL, +COALESCE(C.TOTAL_MFS,0) AS TOTAL_MFS, +COALESCE(D.TOTAL_MIS,0) AS TOTAL_MIS, +COALESCE(F.BEFORE_DUE_7_MCL,0) AS BEFORE_DUE_7_MCL, +COALESCE(G.BEFORE_DUE_7_MFS,0) AS BEFORE_DUE_7_MFS, +COALESCE(H.BEFORE_DUE_7_MIS,0) AS BEFORE_DUE_7_MIS, +COALESCE(I.PER1_MCL,0) AS PER1_MCL, +COALESCE(J.PER1_MFS,0) AS PER1_MFS, +COALESCE(K.PER1_MIS,0) AS PER1_MIS, +COALESCE(L.PER2_MCL,0) AS PER2_MCL, +COALESCE(M.PER2_MFS,0) AS PER2_MFS, +COALESCE(N.PER2_MIS,0) AS PER2_MIS, +COALESCE(O.PER3_MCL,0) AS PER3_MCL, +COALESCE(P.PER3_MFS,0) AS PER3_MFS, +COALESCE(R.PER3_MIS,0) AS PER3_MIS, +COALESCE(S.PER4_MCL,0) AS PER4_MCL, +COALESCE(T.PER4_MFS,0) AS PER4_MFS, +COALESCE(U.PER4_MIS,0) AS PER4_MIS, +COALESCE(V.PER5_MCL,0) AS PER5_MCL, +COALESCE(X.PER5_MFS,0) AS PER5_MFS, +COALESCE(Z.PER5_MIS,0) AS PER5_MIS, +COALESCE(Q.PER6_MCL,0) AS PER6_MCL, +COALESCE(Y.PER6_MFS,0) AS PER6_MFS, +COALESCE(W.PER6_MIS,0) AS PER6_MIS, +COALESCE(A1.PER7_MCL,0) AS PER7_MCL, +COALESCE(B1.PER7_MFS,0) AS PER7_MFS, +COALESCE(C1.PER7_MIS,0) AS PER7_MIS, +A.BEFORE_DUE_7,A.PER1,A.PER2,A.PER3,A.PER4,A.PER5,A.PER6,A.PER7, +CONCAT(A.DIVISION,'-',A.CLIENT_NUMBER) AS REF,"2" AS TYPE FROM +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER, +GROUP_CONCAT(DISTINCT CLIENT_INFO SEPARATOR '<br>') AS CLIENT_INFO, +GROUP_CONCAT(DISTINCT CLIENT_NAME SEPARATOR '<br>') AS CLIENT_NAME, +GROUP_CONCAT( DISTINCT `PHONE_NUMBER` SEPARATOR '<br>' ) AS PHONE_NUMBER , +GROUP_CONCAT( DISTINCT `ATTENTION_NAME` SEPARATOR '<br>' ) AS ATTENTION_NAME, +GROUP_CONCAT( DISTINCT `PAYMENT_TERM` SEPARATOR '<br>' ) AS PAYMENT_TERM, +CREDIT_LIMIT , +GROUP_CONCAT( `LAST_PAY_DATE` SEPARATOR '<br>' ) AS LAST_PAY_DATE, +SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL, +SUM( `BEFORE_DUE_7`*EXCHANGE_RATE ) AS BEFORE_DUE_7, +SUM( `PER1`*EXCHANGE_RATE ) AS PER1, +SUM( `PER2`*EXCHANGE_RATE ) AS PER2, +SUM( `PER3`*EXCHANGE_RATE ) AS PER3, +SUM( `PER4`*EXCHANGE_RATE ) AS PER4, +SUM( `PER5`*EXCHANGE_RATE ) AS PER5, +SUM( `PER6`*EXCHANGE_RATE ) AS PER6, +SUM( `PER7`*EXCHANGE_RATE ) AS PER7 +FROM `t2` +WHERE REF IS NULL GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS A +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS B ON A.CLIENT_NUMBER=B.CLIENT_NUMBER AND +A.DIVISION=B.DIVISION AND A.RECEIVABLE_GROUP=B.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=B.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS C ON A.CLIENT_NUMBER=C.CLIENT_NUMBER +AND +A.DIVISION=C.DIVISION AND A.RECEIVABLE_GROUP=C.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=C.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( `TOTAL`*EXCHANGE_RATE ) AS TOTAL_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS D ON A.CLIENT_NUMBER=D.CLIENT_NUMBER AND +A.DIVISION=D.DIVISION AND A.RECEIVABLE_GROUP=D.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=D.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( BEFORE_DUE_7*EXCHANGE_RATE ) AS BEFORE_DUE_7_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS F ON A.CLIENT_NUMBER=F.CLIENT_NUMBER AND +A.DIVISION=F.DIVISION AND A.RECEIVABLE_GROUP=F.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=F.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( BEFORE_DUE_7*EXCHANGE_RATE ) AS BEFORE_DUE_7_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS G ON A.CLIENT_NUMBER=G.CLIENT_NUMBER AND +A.DIVISION=G.DIVISION AND A.RECEIVABLE_GROUP=G.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=G.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( BEFORE_DUE_7*EXCHANGE_RATE ) AS BEFORE_DUE_7_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS H ON A.CLIENT_NUMBER=H.CLIENT_NUMBER AND +A.DIVISION=H.DIVISION AND A.RECEIVABLE_GROUP=H.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=H.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER1*EXCHANGE_RATE ) AS PER1_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS I ON A.CLIENT_NUMBER=I.CLIENT_NUMBER AND +A.DIVISION=I.DIVISION AND A.RECEIVABLE_GROUP=I.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=I.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER1*EXCHANGE_RATE ) AS PER1_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS J ON A.CLIENT_NUMBER=J.CLIENT_NUMBER AND +A.DIVISION=J.DIVISION AND A.RECEIVABLE_GROUP=J.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=J.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER1*EXCHANGE_RATE ) AS PER1_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS K ON A.CLIENT_NUMBER=K.CLIENT_NUMBER AND +A.DIVISION=K.DIVISION AND A.RECEIVABLE_GROUP=K.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=K.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER2*EXCHANGE_RATE ) AS PER2_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS L ON A.CLIENT_NUMBER=L.CLIENT_NUMBER AND +A.DIVISION=L.DIVISION AND A.RECEIVABLE_GROUP=L.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=L.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER2*EXCHANGE_RATE ) AS PER2_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS M ON A.CLIENT_NUMBER=M.CLIENT_NUMBER AND +A.DIVISION=M.DIVISION AND A.RECEIVABLE_GROUP=M.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=M.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER2*EXCHANGE_RATE ) AS PER2_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS N ON A.CLIENT_NUMBER=N.CLIENT_NUMBER AND +A.DIVISION=N.DIVISION AND A.RECEIVABLE_GROUP=N.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=N.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER3*EXCHANGE_RATE ) AS PER3_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS O ON A.CLIENT_NUMBER=O.CLIENT_NUMBER AND +A.DIVISION=O.DIVISION AND A.RECEIVABLE_GROUP=O.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=O.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER3*EXCHANGE_RATE ) AS PER3_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS P ON A.CLIENT_NUMBER=P.CLIENT_NUMBER AND +A.DIVISION=P.DIVISION AND A.RECEIVABLE_GROUP=P.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=P.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER3*EXCHANGE_RATE ) AS PER3_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS R ON A.CLIENT_NUMBER=R.CLIENT_NUMBER AND +A.DIVISION=R.DIVISION AND A.RECEIVABLE_GROUP=R.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=R.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER4*EXCHANGE_RATE ) AS PER4_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS S ON A.CLIENT_NUMBER=S.CLIENT_NUMBER AND +A.DIVISION=S.DIVISION AND A.RECEIVABLE_GROUP=S.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=S.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER4*EXCHANGE_RATE ) AS PER4_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS T ON A.CLIENT_NUMBER=T.CLIENT_NUMBER AND +A.DIVISION=T.DIVISION AND A.RECEIVABLE_GROUP=T.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=T.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER4*EXCHANGE_RATE ) AS PER4_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS U ON A.CLIENT_NUMBER=U.CLIENT_NUMBER AND +A.DIVISION=U.DIVISION AND A.RECEIVABLE_GROUP=U.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=U.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER5*EXCHANGE_RATE ) AS PER5_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS V ON A.CLIENT_NUMBER=V.CLIENT_NUMBER AND +A.DIVISION=V.DIVISION AND A.RECEIVABLE_GROUP=V.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=V.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER5*EXCHANGE_RATE ) AS PER5_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS X ON A.CLIENT_NUMBER=X.CLIENT_NUMBER AND +A.DIVISION=X.DIVISION AND A.RECEIVABLE_GROUP=X.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=X.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER5*EXCHANGE_RATE ) AS PER5_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS Z ON A.CLIENT_NUMBER=Z.CLIENT_NUMBER AND +A.DIVISION=Z.DIVISION AND A.RECEIVABLE_GROUP=Z.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=Z.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER6*EXCHANGE_RATE ) AS PER6_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS Q ON A.CLIENT_NUMBER=Q.CLIENT_NUMBER AND +A.DIVISION=Q.DIVISION AND A.RECEIVABLE_GROUP=Q.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=Q.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER6*EXCHANGE_RATE ) AS PER6_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS Y ON A.CLIENT_NUMBER=Y.CLIENT_NUMBER AND +A.DIVISION=Y.DIVISION AND A.RECEIVABLE_GROUP=Y.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=Y.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER6*EXCHANGE_RATE ) AS PER6_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS W ON A.CLIENT_NUMBER=W.CLIENT_NUMBER AND +A.DIVISION=W.DIVISION AND A.RECEIVABLE_GROUP=W.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=W.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER7*EXCHANGE_RATE ) AS PER7_MCL +FROM `t2` +WHERE REF IS NULL AND DIVISION="MCL" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS A1 ON A.CLIENT_NUMBER=A1.CLIENT_NUMBER AND +A.DIVISION=A1.DIVISION AND A.RECEIVABLE_GROUP=A1.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=A1.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER7*EXCHANGE_RATE ) AS PER7_MFS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MFS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS B1 ON A.CLIENT_NUMBER=B1.CLIENT_NUMBER AND +A.DIVISION=B1.DIVISION AND A.RECEIVABLE_GROUP=B1.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=B1.CREDIT_LIMIT +LEFT JOIN +(SELECT RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT,SUM( PER7*EXCHANGE_RATE ) AS PER7_MIS +FROM `t2` +WHERE REF IS NULL AND DIVISION="MIS" GROUP BY RECEIVABLE_GROUP,DIVISION,CLIENT_NUMBER,CREDIT_LIMIT) AS C1 ON A.CLIENT_NUMBER=C1.CLIENT_NUMBER AND +A.DIVISION=C1.DIVISION AND A.RECEIVABLE_GROUP=C1.RECEIVABLE_GROUP AND A.CREDIT_LIMIT=C1.CREDIT_LIMIT +ORDER BY TOTAL DESC; + +DROP TABLES t1,t2; + set optimizer_switch=@save_derived_optimizer_switch; --echo # diff --git a/mysql-test/t/events_2.test b/mysql-test/t/events_2.test index ec69a2a5591..7d9ac7c5858 100644 --- a/mysql-test/t/events_2.test +++ b/mysql-test/t/events_2.test @@ -15,7 +15,7 @@ use events_test; # mysql.event intact checking end # -create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5; +create event e_26 on schedule at '2027-01-01 00:00:00' disable do set @a = 5; select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event; drop event e_26; --error ER_WRONG_VALUE diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test index c0157a7727e..cace397e92a 100644 --- a/mysql-test/t/events_bugs.test +++ b/mysql-test/t/events_bugs.test @@ -306,7 +306,7 @@ create table events_smode_test(ev_name char(10), a date); delimiter |; create event ee_16407_2 on schedule every 60 second do begin - select get_lock('ee_16407_2', 60) /*ee_16407_2*/; + select get_lock('ee_16407_2', 60); /*ee_16407_2*/ select release_lock('ee_16407_2'); insert into events_test.events_smode_test values('ee_16407_2','1980-19-02'); end| @@ -315,7 +315,7 @@ insert into events_test.events_smode_test values ('test','1980-19-02')| --echo "This is ok" create event ee_16407_3 on schedule every 60 second do begin - select get_lock('ee_16407_2', 60) /*ee_16407_3*/; + select get_lock('ee_16407_2', 60); /*ee_16407_3*/ select release_lock('ee_16407_2'); insert into events_test.events_smode_test values ('ee_16407_3','1980-02-19'); insert into events_test.events_smode_test values ('ee_16407_3','1980-02-29'); @@ -324,7 +324,7 @@ set sql_mode=""| --echo "This will insert rows but they will be truncated" create event ee_16407_4 on schedule every 60 second do begin - select get_lock('ee_16407_2', 60) /*ee_16407_4*/; + select get_lock('ee_16407_2', 60); /*ee_16407_4*/ select release_lock('ee_16407_2'); insert into events_test.events_smode_test values ('ee_16407_4','10-11-1956'); end| @@ -412,13 +412,13 @@ create procedure ee_16407_5_pendant() begin insert into events_test.events_smode create procedure ee_16407_6_pendant() begin insert into events_test.events_smode_test values('ee_16407_6','2004-02-29'); end| create event ee_16407_5 on schedule every 60 second do begin - select get_lock('ee_16407_5', 60) /*ee_16407_5*/; + select get_lock('ee_16407_5', 60); /*ee_16407_5*/ select release_lock('ee_16407_5'); call events_test.ee_16407_5_pendant(); end| create event ee_16407_6 on schedule every 60 second do begin - select get_lock('ee_16407_5', 60) /*ee_16407_6*/; + select get_lock('ee_16407_5', 60); /*ee_16407_6*/ select release_lock('ee_16407_5'); call events_test.ee_16407_6_pendant(); end| @@ -944,7 +944,7 @@ DELIMITER ;| # reasonable time like 4 seconds. Till ~ 2 seconds could pass on a heavy # loaded testing box before something gets executed). # Detection of execution is via the records inserted by the event. ---echo Sleep till the first INSERT into events_test.event_log occured +--echo Sleep till the first INSERT into events_test.event_log occurred let $wait_timeout= 4; let $wait_condition= SELECT COUNT(*) > 0 FROM events_test.event_log; diff --git a/mysql-test/t/explain_json.test b/mysql-test/t/explain_json.test index 153d85359c9..22bfd5aedcd 100644 --- a/mysql-test/t/explain_json.test +++ b/mysql-test/t/explain_json.test @@ -394,5 +394,15 @@ set join_cache_level=@tmp_join_cache_level; drop table t1,t2,t3,t4; +--echo # +--echo # MDEV-9652: EXPLAIN FORMAT=JSON should show outer_ref_cond +--echo # +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (a int, b int); +insert into t1 select a,a from t0; +explain format=json +select a, (select max(a) from t1 where t0.a<5 and t1.b<t0.a) from t0; +drop table t0,t1; diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 5550eebf1a3..3cc244339d3 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -832,3 +832,44 @@ PREPARE stmt FROM "SELECT GROUP_CONCAT(t1a.a ORDER BY 1, t1a.a=0) FROM t1 AS t1a EXECUTE stmt; EXECUTE stmt; DROP TABLE t1; + +--echo # +--echo # WL#6098 Eliminate GROUP_CONCAT intermediate result limitation. +--echo # Bug#13387020 GROUP_CONCAT WITH ORDER BY RESULTS ARE TRUNCATED. +--echo # + + +SET group_concat_max_len= 9999999; +CREATE TABLE t1 (f1 LONGTEXT , f2 INTEGER); +INSERT INTO t1 VALUES (REPEAT('a', 500000), 0), (REPEAT('b', 500000), 1), (REPEAT('c', 500000), 2); + +SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1; +SELECT LENGTH(GROUP_CONCAT(DISTINCT f1 ORDER BY f1 DESC)) FROM t1; +SELECT SUBSTRING(GROUP_CONCAT(DISTINCT f1 ORDER BY f1 DESC), 1, 5) FROM t1; +SELECT LENGTH(GROUP_CONCAT(DISTINCT f1)) FROM t1; + +SELECT LENGTH(GROUP_CONCAT(UPPER(f1) ORDER BY f2)) FROM t1; +SELECT LENGTH(GROUP_CONCAT(DISTINCT UPPER(f1) ORDER BY f1)) FROM t1; +SELECT SUBSTRING(GROUP_CONCAT(DISTINCT UPPER(f1) ORDER BY f1), 1, 5) FROM t1; +SELECT LENGTH(GROUP_CONCAT(DISTINCT UPPER(f1))) FROM t1; + +CREATE TABLE t2 SELECT GROUP_CONCAT(f1 order by f2) FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; + +CREATE TABLE t2 SELECT GROUP_CONCAT(UPPER(f1) ORDER BY f2) FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t2; + +SET group_concat_max_len= DEFAULT; +SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1; + +SET group_concat_max_len= 499999; +SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1 WHERE f2 = 0; +SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1 GROUP BY f2; + +INSERT INTO t1 VALUES (REPEAT('a', 499999), 3), (REPEAT('b', 500000), 4); +SELECT LENGTH(GROUP_CONCAT(f1 ORDER BY f2)) FROM t1 GROUP BY f2; + +DROP TABLE t1; +SET group_concat_max_len= DEFAULT; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index b5270743465..47477c72004 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -1582,6 +1582,14 @@ SELECT id, AVG(a) AS avg, CAST(AVG(a) AS SIGNED) AS cast_avg FROM t1 GROUP BY id DROP TABLE t1; --echo # +--echo # MDEV-9656 Assertion `0' failed in Item_sum_field::get_tmp_table_field() +--echo # +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT DISTINCT VAR_POP(1) FROM t1 GROUP BY @a := 's'; +DROP TABLE t1; + +--echo # --echo # MDEV-8921 Wrong result for CAST(AVG(double_column) AS SIGNED) --echo # CREATE TABLE t1 (id INT, a DOUBLE); diff --git a/mysql-test/t/func_hybrid_type.test b/mysql-test/t/func_hybrid_type.test index 047e5f7b72e..dd8a399025b 100644 --- a/mysql-test/t/func_hybrid_type.test +++ b/mysql-test/t/func_hybrid_type.test @@ -434,5 +434,28 @@ DROP TABLE t1; --echo # +--echo # MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool) +--echo # +SELECT CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END; +SELECT CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END; +SELECT CASE WHEN TRUE THEN COALESCE(NULL) ELSE 4 END; + +--disable_ps_protocol +--enable_metadata +SELECT COALESCE(COALESCE(NULL), 1.1) AS c0, IF(0, COALESCE(NULL), 1.1) AS c1; +--disable_metadata +--enable_ps_protocol + + +--echo # +--echo # MDEV-9752 Wrong data type for COALEASCE(?,1) in prepared statements +--echo # +PREPARE stmt FROM "CREATE TABLE t1 AS SELECT CONCAT(COALESCE(?,1)) AS a, CONCAT(CASE WHEN TRUE THEN ? ELSE 1 END) AS b"; +SET @a=1; +EXECUTE stmt USING @a,@a; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--echo # --echo # End of 10.1 tests --echo # diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 511f1f31736..2645417f3e5 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -1774,5 +1774,15 @@ SELECT * FROM t1 WHERE a=18446744073709551615 AND FORMAT(a,0)='18,446,744,073,70 DROP TABLE t1; --echo # +--echo # Bug#58081 Duplicate entry error when doing GROUP BY +--echo # MDEV-9332 Bug after upgrade to 10.1.10 +--echo # +SET NAMES latin1; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0),(0),(1),(0),(0); +SELECT COUNT(*) FROM t1, t1 t2 GROUP BY INSERT('', t2.a, t1.a, @@global.max_binlog_size); +DROP TABLE t1; + +--echo # --echo # End of 10.1 tests --echo # diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 8541f62023f..18293f31dd2 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -1043,6 +1043,24 @@ select 1 from t1 where 1 < some (select cast(a as datetime) from t1); drop table t1; SET timestamp=DEFAULT; +--echo # +--echo # Bug #21564557: INCONSISTENT OUTPUT FROM 5.5 AND 5.6 +--echo # UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%M" +--echo # + +SELECT UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m")); +SELECT UNIX_TIMESTAMP('2015-06-00'); +SELECT UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s')); + +set sql_mode= 'TRADITIONAL'; +SELECT @@sql_mode; + +SELECT UNIX_TIMESTAMP(STR_TO_DATE('201506', "%Y%m")); +SELECT UNIX_TIMESTAMP('2015-06-00'); +SELECT UNIX_TIMESTAMP(STR_TO_DATE('0000-00-00 10:30:30', '%Y-%m-%d %h:%i:%s')); + +set sql_mode= default; + select time('10:10:10') > 10; select time('10:10:10') > 1010; select time('10:10:09') > 101010; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 18e244d8152..318166e6896 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -1792,3 +1792,29 @@ DROP TABLE where_subselect; --echo # End of Bug #58782 +--echo # +--echo # MDEV-8988: Apparently valid SQL query gives wrong result (nested WHERE) +--echo # +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +create table t1 (a int, b int, c int); +insert into t1 select A.a + 10*B.a, A.a, A.a + 10*B.a from t0 A, t0 B; +insert into t1 values (NULL, NULL, NULL); + +create table t2 (c int, col1 int, key(c)); +insert into t2 select t1.a, 100000 from t1; +analyze table t2; + +explain +select + max(a)+ (select col1 from t2 where t2.c=t1.c) +from t1 +group by t1.b; + +select + max(a) + (select col1 from t2 where t2.c=t1.c) +from t1 +group by t1.b; + +drop table t0,t1,t2; diff --git a/mysql-test/t/index_merge_myisam.test b/mysql-test/t/index_merge_myisam.test index 82d0474e28e..d265007431e 100644 --- a/mysql-test/t/index_merge_myisam.test +++ b/mysql-test/t/index_merge_myisam.test @@ -117,7 +117,7 @@ set optimizer_switch='default,index_merge_intersection=off'; explain select * from t1 where a=10 and b=10 or c=10; --echo This will switch to sort-union (intersection will be gone, too, ---echo thats a known limitation: +--echo that's a known limitation: set optimizer_switch='default,index_merge_union=off'; explain select * from t1 where a=10 and b=10 or c=10; diff --git a/mysql-test/t/information_schema_inno.test b/mysql-test/t/information_schema_inno.test index 657d0effd7e..9a9658e9027 100644 --- a/mysql-test/t/information_schema_inno.test +++ b/mysql-test/t/information_schema_inno.test @@ -109,3 +109,9 @@ CREATE TABLE t1 engine = InnoDB AS DROP TABLE t1; DROP VIEW v1; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval CREATE TABLE t1(i int) ENGINE=Innodb ROW_FORMAT=REDUNDANT DATA DIRECTORY='$MYSQLTEST_VARDIR/tmp'; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +SELECT CREATE_OPTIONS FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME='t1'; +DROP TABLE t1; diff --git a/mysql-test/t/mdev375.test b/mysql-test/t/mdev375.test index fe259b37808..92e403b6513 100644 --- a/mysql-test/t/mdev375.test +++ b/mysql-test/t/mdev375.test @@ -17,6 +17,7 @@ SELECT 2; --connection default SELECT 0; +show status like "Threads_connected"; SET GLOBAL log_warnings=default; SET GLOBAL max_connections=default; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 5bfe22697dd..519094d6350 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -655,7 +655,7 @@ insert into t1 values (1); flush tables; # Open t2 and (implicitly) t1. select * from t2; -# Truncate t1, wich was not recognized as open without the bugfix. +# Truncate t1, which was not recognized as open without the bugfix. # After fix for Bug#8306 and before fix for Bug#26379, # it should fail with a table-in-use error message, otherwise succeed. truncate table t1; diff --git a/mysql-test/t/merge_innodb.test b/mysql-test/t/merge_innodb.test index 7f0b1a0c36e..9f87f241d00 100644 --- a/mysql-test/t/merge_innodb.test +++ b/mysql-test/t/merge_innodb.test @@ -39,3 +39,34 @@ SELECT * FROM t2; SELECT * FROM t1; DROP TABLE t1, t2, t3, t4, t5; +# +# Bug#20691429 temporary merge over view under lock tables +# +create table t1 (c1 varchar(100)); +create table t2 (c1 varchar(100)); +create view t3 as select * from t1; +insert into t1 values ('ann'), ('alice'); +insert into t2 values ('bob'), ('brian'); +create temporary table t4 (c1 varchar(100)) engine=MERGE union=(t2, t1); +create temporary table t5 (c1 varchar(100)) engine=MERGE union=(t3, t1); +--error ER_WRONG_MRG_TABLE +select * from t5; +lock tables t1 read, t2 read, t3 read, t4 read; +--error ER_WRONG_MRG_TABLE +select * from t5; +select * from t4; +unlock tables; +drop table t2; +create view t2 as select * from t1; +--error ER_WRONG_MRG_TABLE +select * from t4; +lock tables t1 read, t2 read, t3 read; +--error ER_WRONG_MRG_TABLE +select * from t4; +--error ER_WRONG_MRG_TABLE +select * from t4; +--error ER_WRONG_MRG_TABLE +select * from t4; +unlock tables; +drop view t2, t3; +drop table t1; diff --git a/mysql-test/t/mysql_upgrade_view.test b/mysql-test/t/mysql_upgrade_view.test index 49a90264f11..7afe1ad250d 100644 --- a/mysql-test/t/mysql_upgrade_view.test +++ b/mysql-test/t/mysql_upgrade_view.test @@ -158,5 +158,30 @@ rename table mysql.ev_bk to mysql.event; drop table if exists kv; drop view v1,v2,v3,v4; -drop table t1; +# +# MDEV-9453 mysql_upgrade.exe error when mysql is migrated to mariadb +# (mysql_upgrade.exe --upgrade-system-tables fails on fixing views) +# + +# Make it look like a MySQL directory again + +rename table mysql.event to mysql.ev_bk; +--copy_file $MYSQL_TEST_DIR/std_data/mysql_upgrade/event.MYI $MYSQLD_DATADIR/mysql/event.MYI +--copy_file $MYSQL_TEST_DIR/std_data/mysql_upgrade/event.MYD $MYSQLD_DATADIR/mysql/event.MYD +--copy_file $MYSQL_TEST_DIR/std_data/mysql_upgrade/event.frm $MYSQLD_DATADIR/mysql/event.frm + +--copy_file $MYSQL_TEST_DIR/std_data/mysql_upgrade/v1.frm $MYSQLD_DATADIR/test/v1.frm +--copy_file $MYSQL_TEST_DIR/std_data/mysql_upgrade/v2.frm $MYSQLD_DATADIR/test/v2.frm +--copy_file $MYSQL_TEST_DIR/std_data/mysql_upgrade/v3.frm $MYSQLD_DATADIR/test/v3.frm + +flush tables; + +--replace_result $MYSQLTEST_VARDIR var +--exec $MYSQL_UPGRADE --force --upgrade-system-tables 2>&1 + +# back to mariadb default +drop table mysql.event; +rename table mysql.ev_bk to mysql.event; +drop view v1,v2,v3; +drop table t1; diff --git a/mysql-test/t/mysqlbinlog_raw_mode.test b/mysql-test/t/mysqlbinlog_raw_mode.test new file mode 100644 index 00000000000..26fb31516f6 --- /dev/null +++ b/mysql-test/t/mysqlbinlog_raw_mode.test @@ -0,0 +1,387 @@ +--source include/have_log_bin.inc +reset master; + +# we need this for getting fixed timestamps inside of this test +set timestamp=1000000000; + +--disable_warnings +drop table if exists t1; +--enable_warnings +CREATE TABLE t1 (c01 BIT); +INSERT INTO t1 VALUES (0); +INSERT INTO t1 VALUES (1); +DROP TABLE t1; + +CREATE TABLE t1 (c01 BIT(7)); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (4); +INSERT INTO t1 VALUES (8); +INSERT INTO t1 VALUES (16); +INSERT INTO t1 VALUES (32); +INSERT INTO t1 VALUES (64); +INSERT INTO t1 VALUES (127); +DELETE FROM t1 WHERE c01=127; +UPDATE t1 SET c01=15 WHERE c01=16; +DROP TABLE t1; + +CREATE TABLE t1 (a BIT(20), b CHAR(2)); +INSERT INTO t1 VALUES (b'00010010010010001001', 'ab'); +DROP TABLE t1; + +CREATE TABLE t1 (c02 BIT(64)); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +INSERT INTO t1 VALUES (128); +INSERT INTO t1 VALUES (b'1111111111111111111111111111111111111111111111111111111111111111'); +DROP TABLE t1; + + +CREATE TABLE t1 (c03 TINYINT); +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t1 VALUES (-128); +UPDATE t1 SET c03=2 WHERE c03=1; +DELETE FROM t1 WHERE c03=-128; +DROP TABLE t1; + +CREATE TABLE t1 (c04 TINYINT UNSIGNED); +INSERT INTO t1 VALUES (128), (255); +UPDATE t1 SET c04=2 WHERE c04=1; +DELETE FROM t1 WHERE c04=255; +DROP TABLE t1; + +CREATE TABLE t1 (c06 BOOL); +INSERT INTO t1 VALUES (TRUE); +DELETE FROM t1 WHERE c06=TRUE; +DROP TABLE t1; + +CREATE TABLE t1 (c07 SMALLINT); +INSERT INTO t1 VALUES (1234); +DELETE FROM t1 WHERE c07=1234; +DROP TABLE t1; + +CREATE TABLE t1 (c08 SMALLINT UNSIGNED); +INSERT INTO t1 VALUES (32768), (65535); +UPDATE t1 SET c08=2 WHERE c08=32768; +DELETE FROM t1 WHERE c08=65535; +DROP TABLE t1; + +CREATE TABLE t1 (c10 MEDIUMINT); +INSERT INTO t1 VALUES (12345); +DELETE FROM t1 WHERE c10=12345; +DROP TABLE t1; + +CREATE TABLE t1 (c11 MEDIUMINT UNSIGNED); +INSERT INTO t1 VALUES (8388608), (16777215); +UPDATE t1 SET c11=2 WHERE c11=8388608; +DELETE FROM t1 WHERE c11=16777215; +DROP TABLE t1; + +CREATE TABLE t1 (c13 INT); +INSERT INTO t1 VALUES (123456); +DELETE FROM t1 WHERE c13=123456; +DROP TABLE t1; + +CREATE TABLE t1 (c14 INT UNSIGNED); +INSERT INTO t1 VALUES (2147483648), (4294967295); +UPDATE t1 SET c14=2 WHERE c14=2147483648; +DELETE FROM t1 WHERE c14=4294967295; +DROP TABLE t1; + +CREATE TABLE t1 (c16 BIGINT); +INSERT INTO t1 VALUES (1234567890); +DELETE FROM t1 WHERE c16=1234567890; +DROP TABLE t1; + +CREATE TABLE t1 (c17 BIGINT UNSIGNED); +INSERT INTO t1 VALUES (9223372036854775808), (18446744073709551615); +UPDATE t1 SET c17=2 WHERE c17=9223372036854775808; +DELETE FROM t1 WHERE c17=18446744073709551615; +DROP TABLE t1; + +CREATE TABLE t1 (c19 FLOAT); +INSERT INTO t1 VALUES (123.2234); +DELETE FROM t1 WHERE c19>123; +DROP TABLE t1; + +CREATE TABLE t1 (c22 DOUBLE); +INSERT INTO t1 VALUES (123434.22344545); +DELETE FROM t1 WHERE c22>123434; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c25 DECIMAL(10,5)); +INSERT INTO t1 VALUES (124.45); +INSERT INTO t1 VALUES (-543.21); +DELETE FROM t1 WHERE c25=124.45; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c28 DATE); +INSERT INTO t1 VALUES ('2001-02-03'); +DELETE FROM t1 WHERE c28='2001-02-03'; +DROP TABLE t1; + +CREATE TABLE t1 (c29 DATETIME); +INSERT INTO t1 VALUES ('2001-02-03 10:20:30'); +DELETE FROM t1 WHERE c29='2001-02-03 10:20:30'; +DROP TABLE t1; + +CREATE TABLE t1 (c30 TIMESTAMP); +INSERT INTO t1 VALUES ('2001-02-03 10:20:30'); +DELETE FROM t1 WHERE c30='2001-02-03 10:20:30'; +DROP TABLE t1; + +CREATE TABLE t1 (c31 TIME); +INSERT INTO t1 VALUES ('11:22:33'); +DELETE FROM t1 WHERE c31='11:22:33'; +DROP TABLE t1; + +CREATE TABLE t1 (c32 YEAR); +INSERT INTO t1 VALUES ('2001'); +DELETE FROM t1 WHERE c32=2001; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c33 CHAR); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c33='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c34 CHAR(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c34=''; +DROP TABLE t1; + +CREATE TABLE t1 (c35 CHAR(1)); +INSERT INTO t1 VALUES ('b'); +DELETE FROM t1 WHERE c35='b'; +DROP TABLE t1; + +CREATE TABLE t1 (c36 CHAR(255)); +INSERT INTO t1 VALUES (repeat('c',255)); +DELETE FROM t1 WHERE c36>'c'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c37 NATIONAL CHAR); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c37='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c38 NATIONAL CHAR(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c38=''; +DROP TABLE t1; + +CREATE TABLE t1 (c39 NATIONAL CHAR(1)); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c39='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c40 NATIONAL CHAR(255)); +INSERT INTO t1 VALUES (repeat('a', 255)); +INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255)); +DELETE FROM t1 WHERE c40>'a'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c45 VARCHAR(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c45=''; +DROP TABLE t1; + +CREATE TABLE t1 (c46 VARCHAR(1)); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c46='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c47 VARCHAR(255)); +INSERT INTO t1 VALUES (repeat('a',255)); +DELETE FROM t1 WHERE c47>'a'; +DROP TABLE t1; + +CREATE TABLE t1 (c48 VARCHAR(261)); +INSERT INTO t1 VALUES (repeat('a',261)); +DELETE FROM t1 WHERE c48>'a'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c49 NATIONAL VARCHAR(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c49=''; +DROP TABLE t1; + +CREATE TABLE t1 (c50 NATIONAL VARCHAR(1)); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c50='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c51 NATIONAL VARCHAR(255)); +INSERT INTO t1 VALUES (repeat('a',255)); +INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255)); +DELETE FROM t1 WHERE c51>'a'; +DROP TABLE t1; + +CREATE TABLE t1 (c52 NATIONAL VARCHAR(261)); +INSERT INTO t1 VALUES (repeat('a',261)); +INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 261)); +DELETE FROM t1 WHERE c52>'a'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c57 BINARY); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c57='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c58 BINARY(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c58=''; +DROP TABLE t1; + +CREATE TABLE t1 (c59 BINARY(1)); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c59='a'; +DROP TABLE t1; + +CREATE TABLE t1 (c60 BINARY(255)); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES (repeat('a\0',120)); +DELETE FROM t1 WHERE c60<0x02; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c61 VARBINARY(0)); +INSERT INTO t1 VALUES (''); +DELETE FROM t1 WHERE c61=''; +DROP TABLE t1; + +CREATE TABLE t1 (c62 VARBINARY(1)); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES ('a'); +DELETE FROM t1 WHERE c62=0x02; +DROP TABLE t1; + +CREATE TABLE t1 (c63 VARBINARY(255)); +INSERT INTO t1 VALUES (0x00); +INSERT INTO t1 VALUES (0x02); +INSERT INTO t1 VALUES (repeat('a\0',120)); +DELETE FROM t1 WHERE c63=0x02; +DROP TABLE t1; + +# +flush logs; + +CREATE TABLE t1 (c65 TINYBLOB); +INSERT INTO t1 VALUES ('tinyblob1'); +DELETE FROM t1 WHERE c65='tinyblob1'; +DROP TABLE t1; + +CREATE TABLE t1 (c68 BLOB); +INSERT INTO t1 VALUES ('blob1'); +DELETE FROM t1 WHERE c68='blob1'; +DROP TABLE t1; + +CREATE TABLE t1 (c71 MEDIUMBLOB); +INSERT INTO t1 VALUES ('mediumblob1'); +DELETE FROM t1 WHERE c71='mediumblob1'; +DROP TABLE t1; + +CREATE TABLE t1 (c74 LONGBLOB); +INSERT INTO t1 VALUES ('longblob1'); +DELETE FROM t1 WHERE c74='longblob1'; +DROP TABLE t1; + +CREATE TABLE t1 (c66 TINYTEXT); +INSERT INTO t1 VALUES ('tinytext1'); +DELETE FROM t1 WHERE c66='tinytext1'; +DROP TABLE t1; + +CREATE TABLE t1 (c69 TEXT); +INSERT INTO t1 VALUES ('text1'); +DELETE FROM t1 WHERE c69='text1'; +DROP TABLE t1; + +CREATE TABLE t1 (c72 MEDIUMTEXT); +INSERT INTO t1 VALUES ('mediumtext1'); +DELETE FROM t1 WHERE c72='mediumtext1'; +DROP TABLE t1; + +CREATE TABLE t1 (c75 LONGTEXT); +INSERT INTO t1 VALUES ('longtext1'); +DELETE FROM t1 WHERE c75='longtext1'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c77 ENUM('a','b','c')); +INSERT INTO t1 VALUES ('b'); +DELETE FROM t1 WHERE c77='b'; +DROP TABLE t1; + +# + +CREATE TABLE t1 (c78 SET('a','b','c','d','e','f')); +INSERT INTO t1 VALUES ('a,b'); +INSERT INTO t1 VALUES ('a,c'); +INSERT INTO t1 VALUES ('b,c'); +INSERT INTO t1 VALUES ('a,b,c'); +INSERT INTO t1 VALUES ('a,b,c,d'); +INSERT INTO t1 VALUES ('a,b,c,d,e'); +INSERT INTO t1 VALUES ('a,b,c,d,e,f'); +DELETE FROM t1 WHERE c78='a,b'; +DROP TABLE t1; + +# +# Check multi-table update +# +CREATE TABLE t1 (a int NOT NULL DEFAULT 0, b int NOT NULL DEFAULT 0); +CREATE TABLE t2 (a int NOT NULL DEFAULT 0, b int NOT NULL DEFAULT 0); +INSERT INTO t1 SET a=1; +INSERT INTO t1 SET b=1; +INSERT INTO t2 SET a=1; +INSERT INTO t2 SET b=1; +UPDATE t1, t2 SET t1.a=10, t2.a=20; +DROP TABLE t1,t2; + +flush logs; + +let $MYSQLD_DATADIR= `select @@datadir`; + +# Test reading one file in raw mode +--exec $MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --result-file=$MYSQLTEST_VARDIR/tmp/ master-bin.000001 +--diff_files $MYSQLTEST_VARDIR/tmp/master-bin.000001 $MYSQLD_DATADIR/master-bin.000001 +--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000001 + +# Test reading all files in raw mode +# Don't test the end file since this is still open with mysqld so will be different +--exec $MYSQL_BINLOG --raw --read-from-remote-server --to-last-log --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --result-file=$MYSQLTEST_VARDIR/tmp/ master-bin.000001 +--diff_files $MYSQLTEST_VARDIR/tmp/master-bin.000001 $MYSQLD_DATADIR/master-bin.000001 +--diff_files $MYSQLTEST_VARDIR/tmp/master-bin.000002 $MYSQLD_DATADIR/master-bin.000002 + +--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000001 +--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000002 +--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000003 + + +# Test output to different filename +--exec $MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --result-file=$MYSQLTEST_VARDIR/tmp/server1- master-bin.000001 +--diff_files $MYSQLTEST_VARDIR/tmp/server1-master-bin.000001 $MYSQLD_DATADIR/master-bin.000001 +--remove_file $MYSQLTEST_VARDIR/tmp/server1-master-bin.000001 + +--echo End of tests diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test index 2ddb58e6de4..12fd968b212 100644 --- a/mysql-test/t/mysqld--help.test +++ b/mysql-test/t/mysqld--help.test @@ -31,7 +31,7 @@ perl; connect null-audit aria oqgraph sphinx thread-handling test-sql-discovery rpl-semi-sync query-cache-info query-response-time metadata-lock-info locales unix-socket - wsrep file-key-management/; + wsrep file-key-management cracklib-password-check user-variables/; # And substitute the content some environment variables with their # names: diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index e5ae109088c..9cde1f93a4a 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -702,7 +702,7 @@ drop table t1; --echo # ---echo # Bug#15328 Segmentation fault occured if my.cnf is invalid for escape sequence +--echo # Bug#15328 Segmentation fault occurred if my.cnf is invalid for escape sequence --echo # --exec $MYSQL_MY_PRINT_DEFAULTS --config-file=$MYSQL_TEST_DIR/std_data/bug15328.cnf mysqldump diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test index 5347a961c59..a5db4442183 100644 --- a/mysql-test/t/null.test +++ b/mysql-test/t/null.test @@ -909,6 +909,103 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=2020 AND NULLIF(a,2010)=CONCAT('2020',RAND()); DROP TABLE t1; +--echo # +--echo # MDEV-9181 (NULLIF(count(table.col)), 0) gives wrong result on 10.1.x +--echo # +CREATE TABLE t1 (c1 varchar(50) DEFAULT NULL); +INSERT INTO t1 (c1) VALUES ('hello'), ('hello\r\n'), ('hello'),('hello'); +SELECT NULLIF(COUNT(c1),0) FROM t1; +SELECT CASE WHEN COUNT(c1)=0 THEN NULL ELSE COUNT(c1) END FROM t1; +SELECT NULLIF(COUNT(c1)+0,0) AS c1,NULLIF(CAST(COUNT(c1) AS SIGNED),0) AS c2,NULLIF(CONCAT(COUNT(c1)),0) AS c3 FROM t1; +SELECT NULLIF(COUNT(DISTINCT c1),0) FROM t1; +SELECT CASE WHEN COUNT(DISTINCT c1)=0 THEN NULL ELSE COUNT(DISTINCT c1) END FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 ( + id INT NOT NULL, + c1 INT DEFAULT NULL +); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3),(2,4); +SELECT NULLIF(COUNT(c1),0) AS c1,NULLIF(COUNT(c1)+0,0) AS c1_wrapped,CASE WHEN COUNT(c1) IS NULL THEN 0 ELSE COUNT(c1) END AS c1_case FROM t1 GROUP BY id; +DROP TABLE t1; + +# Testing with side effects + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SET @a=0; +SELECT NULLIF(LAST_VALUE(@a:=@a+1,a),0) FROM t1; +SELECT @a; +SET @a=0; +SELECT NULLIF(AVG(a),0), NULLIF(AVG(LAST_VALUE(@a:=@a+1,a)),0) FROM t1; +SELECT @a; + +# There should not be cache in here: + +EXPLAIN EXTENDED SELECT NULLIF(a,0) FROM t1; + +# But there should be a cache in here: +EXPLAIN EXTENDED SELECT NULLIF(AVG(a),0) FROM t1; + +DROP TABLE t1; + +# +# MDEV-9576 syntax error on view with nullif and count +# +create table t1 (col1 varchar(50)); +create view v1 AS select nullif(count(distinct col1),0) from t1; +show create view v1; +drop view v1; +drop table t1; + +# +# MDEV-9637 select nullif(count(col1),0) gives wrong result if in a view +# +create table t1 (col1 varchar(50) default null); +insert into t1 (col1) values ('hello'), ('hello'), ('hello'); +create view v1 as select nullif(count(col1),0) from t1; +select * from v1; +select nullif(count(col1),0) from t1; +drop view v1; +drop table t1; + +# +# MDEV-9644 Assertion `args[0] == args[2] || thd->stmt_arena->is_stmt_execute()' failed in Item_func_nullif::fix_length_and_dec() +# +select nullif((select 1), (select 2)); +create table t1 (f int); +insert into t1 values (1),(2); +select nullif( not f, 1 ) from t1; +drop table t1; + +# +# MDEV-9641 Assertion `args[0] == args[2] || _current_thd()->lex->context_analysis_only' failed in Item_func_nullif::print(String*, enum_query_type) +# +set names utf8; +create table t1 (f1 varchar(10)); +insert into t1 values ('2015-12-31'); +--error ER_DATA_OUT_OF_RANGE +select power( timestamp( nullif( '2002-09-08', f1 ) ), 24 ) from t1; +drop table t1; + +# +# MDEV-9682 Assertion `0' failed in Item_cache_row::illegal_method_call on 2nd execution of PS with NULLIF +# +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1),(2); +PREPARE stmt FROM "SELECT * FROM t1 WHERE NULLIF( ( 1, 2 ) IN ( SELECT 3, 4 ), 1 )"; +EXECUTE stmt; +EXECUTE stmt; +DROP TABLE t1; + +# +# MDEV-9683 Server crashes in Item::basic_const_item on numerous nested NULLIFs +# +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT * FROM t1 WHERE NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(NULLIF(i = ROUND(0), 14), 13), 12), 11), 10), 9), 8), 7), 6), 5), 4), 3), 2), 1); +DROP TABLE t1; + --echo # --echo # End of 10.1 tests diff --git a/mysql-test/t/order_by_innodb.test b/mysql-test/t/order_by_innodb.test index c20eaceb053..097eddd24f1 100644 --- a/mysql-test/t/order_by_innodb.test +++ b/mysql-test/t/order_by_innodb.test @@ -21,3 +21,43 @@ SELECT * FROM t1 WHERE a = 8 AND (b = 1 OR b IS NULL) ORDER BY c; DROP TABLE t1; +--echo # +--echo # MDEV-9457: Poor query plan chosen for ORDER BY query by a recent 10.1 +--echo # +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +create table t1 ( + pk int primary key, + key1 int, + key2 int, + col1 char(255), + key(key1), + key(key2) +) engine=innodb; + +set @a=-1; +insert into t1 +select + @a:=@a+1, + @a, + @a, + repeat('abcd', 63) +from t0 A, t0 B, t0 C, t0 D; + +--echo # The following must NOT use 'index' on PK. +--echo # It should use index_merge(key1,key2) + filesort +--replace_column 9 # +explain +select * +from t1 +where key1<3 or key2<3 +order by pk; + +--replace_column 9 # +explain +select * +from t1 +where key1<3 or key2<3; + +drop table t0, t1; diff --git a/mysql-test/t/partition_pruning.test b/mysql-test/t/partition_pruning.test index 06ef99e1e70..9d72e9c0d01 100644 --- a/mysql-test/t/partition_pruning.test +++ b/mysql-test/t/partition_pruning.test @@ -1517,3 +1517,22 @@ and dept_id in (select dept_id from t2 where COMPANY_ID = 1000); drop table t1,t2; +--echo # +--echo # MDEV-9505: Valgrind failure in SEL_ARG::store_min,find_used_partitions,... +--echo # +create table t1 (a int, b char(10), c varchar(5), d int) +partition by range columns(a,b,c) +subpartition by key (c,d) +subpartitions 3 +( partition p0 values less than (1,'abc','abc'), + partition p1 values less than (2,'abc','abc'), + partition p2 values less than (3,'abc','abc'), + partition p3 values less than (4,'abc','abc') +); + +insert into t1 values (1,'a','b',1),(2,'a','b',2),(3,'a','b',3); +select * from t1 where (a = 1 AND b < 'd' AND (c = 'b' OR (c = 'c' AND d = 1)) OR + (a = 1 AND b >= 'a' AND (c = 'c' OR (c = 'd' AND d = 2)))); +drop table t1; + + diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test index 9268a3e1086..1c1d1b00910 100644 --- a/mysql-test/t/row.test +++ b/mysql-test/t/row.test @@ -19,10 +19,12 @@ select (1,2,(3,4)) IN ((3,2,(3,4)), (1,2,(3,4))); select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4)); select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL))); explain extended select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL))); +select row(1,2,row(3,null)) IN (row(3,2,row(3,4)), row(1,2,row(4,5))); +select row(1,2,row(3,null)) IN (row(3,2,row(3,4)), row(1,2,row(3,5))); + SELECT (1,2,3)=(0,NULL,3); SELECT (1,2,3)=(1,NULL,3); -# here's something for Sanja to fix :) SELECT (1,2,3)=(1,NULL,0); SELECT ROW(1,2,3)=ROW(1,2,3); @@ -300,6 +302,13 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=10 AND b=10 AND a>=10; EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a,b)=(10,10) AND a>=10; DROP TABLE t1; + +--echo # +--echo # MDEV-9369 IN operator with ( num, NULL ) gives inconsistent result +--echo # +SELECT (1,null) NOT IN ((2,2),(3,3)), (1,null) NOT IN ((2,2)), (1,null) NOT IN ((3,3)); + + --echo # --echo # End of 10.1 tests --echo # diff --git a/mysql-test/t/second_frac-9175.test b/mysql-test/t/second_frac-9175.test new file mode 100644 index 00000000000..91baf997459 --- /dev/null +++ b/mysql-test/t/second_frac-9175.test @@ -0,0 +1,9 @@ +# +# MDEV-9175 Query parser tansforms MICROSECOND into SECOND_FRAC, which does not work +# + +select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456'); +explain extended select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456'); +create view v1 as select timestampdiff(microsecond,'2000-01-01 00:00:00','2001-01-01 00:00:00.123456'); +select * from v1; +drop view v1; diff --git a/mysql-test/t/select_found.test b/mysql-test/t/select_found.test index 88940eaf2b8..33613697722 100644 --- a/mysql-test/t/select_found.test +++ b/mysql-test/t/select_found.test @@ -277,3 +277,13 @@ select sql_calc_found_rows * from t1 ignore index (i) where i = 0 order by v lim select found_rows(); drop table t1; +# +# MDEV-9390 Function found_rows() gives incorrect result where the previous SELECT contains ORDER BY clause +# +create table t1(c1 int); +insert into t1 values(1),(2),(3),(4),(5); +select * from t1 order by c1 limit 2,1; +select found_rows(); +select sql_calc_found_rows * from t1 order by c1 limit 2,1; +select found_rows(); +drop table t1; diff --git a/mysql-test/t/show.test b/mysql-test/t/show.test new file mode 100644 index 00000000000..3101f443264 --- /dev/null +++ b/mysql-test/t/show.test @@ -0,0 +1,15 @@ +# +# MDEV-9538 Server crashes in check_show_access on SHOW STATISTICS +# MDEV-9539 Server crashes in make_columns_old_format on SHOW GEOMETRY_COLUMNS +# MDEV-9540 SHOW SPATIAL_REF_SYS and SHOW SYSTEM_VARIABLES return empty results with numerous warnings +# +--error ER_PARSE_ERROR +show statistics; +--error ER_PARSE_ERROR +show spatial_ref_sys +--error ER_PARSE_ERROR +show system_variables; +--error ER_PARSE_ERROR +show geometry_columns; +--error ER_PARSE_ERROR +show nonexistent; diff --git a/mysql-test/t/show_create_user.test b/mysql-test/t/show_create_user.test new file mode 100644 index 00000000000..a10c8aeeda6 --- /dev/null +++ b/mysql-test/t/show_create_user.test @@ -0,0 +1,34 @@ +--source include/not_embedded.inc + +create user foo; +show create user foo; + +create user foo@test; +show create user foo@test; + +create user foo2@test identified by 'password'; +show create user foo2@test; + +alter user foo2@test identified with 'someplugin' as 'somepassword'; +show create user foo2@test; + +create user foo3@test require SSL; +show create user foo3@test; + +create user foo4@test require cipher 'text' issuer 'foo_issuer' subject 'foo_subject'; +show create user foo4@test; + +create user foo5@test require SSL + with MAX_QUERIES_PER_HOUR 10 + MAX_UPDATES_PER_HOUR 20 + MAX_CONNECTIONS_PER_HOUR 30 + MAX_USER_CONNECTIONS 40 + MAX_STATEMENT_TIME 0.5; +show create user foo5@test; + +drop user foo5@test; +drop user foo4@test; +drop user foo3@test; +drop user foo2@test; +drop user foo@test; +drop user foo; diff --git a/mysql-test/t/ssl_cert_verify.test b/mysql-test/t/ssl_cert_verify.test new file mode 100644 index 00000000000..83f621b7ca9 --- /dev/null +++ b/mysql-test/t/ssl_cert_verify.test @@ -0,0 +1,43 @@ +# Want to skip this test from Valgrind execution +--source include/no_valgrind_without_big.inc +# This test should work in embedded server after we fix mysqltest +-- source include/not_embedded.inc +-- source include/have_ssl_communication.inc +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + +let $ssl_verify_fail_path = --ssl --ssl-ca=$MYSQL_TEST_DIR/std_data/ca-cert-verify.pem --ssl-key=$MYSQL_TEST_DIR/std_data/server-key-verify-fail.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/server-cert-verify-fail.pem; +let $ssl_verify_pass_path = --ssl --ssl-ca=$MYSQL_TEST_DIR/std_data/ca-cert-verify.pem --ssl-key=$MYSQL_TEST_DIR/std_data/server-key-verify-pass.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/server-cert-verify-pass.pem; + +--echo #T1: Host name (/CN=localhost/) as OU name in the server certificate, server certificate verification should fail. +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +--exec echo "restart:" $ssl_verify_fail_path > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +--error 1 +--exec $MYSQL --protocol=tcp --ssl-ca=$MYSQL_TEST_DIR/std_data/ca-cert-verify.pem --ssl-verify-server-cert -e "SHOW STATUS like 'Ssl_version'" + +--echo #T2: Host name (localhost) as common name in the server certificate, server certificate verification should pass. +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +--exec echo "restart:" $ssl_verify_pass_path > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc + +--replace_result TLSv1.2 TLS_VERSION TLSv1.1 TLS_VERSION TLSv1 TLS_VERSION +--exec $MYSQL --protocol=tcp --ssl-ca=$MYSQL_TEST_DIR/std_data/ca-cert-verify.pem --ssl-verify-server-cert -e "SHOW STATUS like 'Ssl_version'" + +--echo # restart server using restart +--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--shutdown_server +--source include/wait_until_disconnected.inc + +--exec echo "restart: " > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--enable_reconnect +--source include/wait_until_connected_again.inc diff --git a/mysql-test/t/statistics.test b/mysql-test/t/statistics.test index 2c8dec307cc..805c169b2a4 100644 --- a/mysql-test/t/statistics.test +++ b/mysql-test/t/statistics.test @@ -494,6 +494,17 @@ DELETE FROM mysql.table_stats; DELETE FROM mysql.column_stats; DELETE FROM mysql.index_stats; + +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS(b) INDEXES(); +ANALYZE TABLE t1 PERSISTENT FOR columns(a,b) INDEXES(); +ANALYZE TABLE t1 PERSISTENT FOR columns(b) indexes(idx2); +ANALYZE TABLE t1 PERSISTENT FOR columns() indexes(idx2); + +DELETE FROM mysql.table_stats; +DELETE FROM mysql.column_stats; +DELETE FROM mysql.index_stats; + + DROP TABLE t1,t2; set names utf8; @@ -717,3 +728,16 @@ select db_name, table_name, column_name, FROM mysql.column_stats; drop table t1; + +--echo # +--echo # MDEV-9590: Always print "Engine-independent statistic" warnings and +--echo # might be filtering columns unintentionally from engines +--echo # + +set use_stat_tables='NEVER'; +create table t1 (test blob); +show variables like 'use_stat_tables'; +analyze table t1; +drop table t1; + +set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index a862870e9ff..7a7c01e78bd 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -5968,6 +5968,17 @@ deallocate prepare stmt; drop table t1,t2,t3,t4; --echo # +--echo # MDEV-7122 +--echo # Assertion `0' failed in subselect_hash_sj_engine::init +--echo # +SET SESSION big_tables=1; +CREATE TABLE t1(a char(255) DEFAULT '', KEY(a(10))) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +INSERT INTO t1 VALUES(0),(0),(0); +SELECT * FROM t1 WHERE a IN(SELECT MIN(a) FROM t1); +DROP TABLE t1; +SET SESSION big_tables=0; + +--echo # --echo # MDEV-7930: Assertion `table_share->tmp_table != NO_TMP_TABLE || --echo # m_lock_type != 2' failed in handler::ha_index_read_map --echo # diff --git a/mysql-test/t/subselect_mat.test b/mysql-test/t/subselect_mat.test index 09c6b3e1747..9c7c9683d0b 100644 --- a/mysql-test/t/subselect_mat.test +++ b/mysql-test/t/subselect_mat.test @@ -254,3 +254,19 @@ SELECT a, b, (a, b) NOT IN (SELECT a, b FROM t2) as sq FROM t1; drop table t1, t2; + +--echo # +--echo # MDEV-9489: Assertion `0' failed in Protocol::end_statement() on +--echo # UNION ALL +--echo # + +CREATE TABLE t1 (f1 INT); +CREATE TABLE t2 (f2 INT); +INSERT INTO t1 VALUES (1),(2); + +( SELECT 1 FROM t1 WHERE f1 NOT IN ( SELECT f2 FROM t2 ) LIMIT 0 ) +UNION ALL +( SELECT 1 FROM t1 WHERE f1 NOT IN ( SELECT f2 FROM t2 ) ) +; + +drop table t1, t2; diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test index c2b93c919dd..b6d6e0a5172 100644 --- a/mysql-test/t/subselect_sj.test +++ b/mysql-test/t/subselect_sj.test @@ -2704,5 +2704,74 @@ explain select 1 from t1 where _cp932 "1" in (select '1' from t1); drop table t1; +--echo # +--echo # MDEV-7823: Server crashes in next_depth_first_tab on nested IN clauses with SQ inside +--echo # +set @tmp_mdev7823=@@optimizer_switch; +set optimizer_switch=default; +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (1); + +CREATE TABLE t2 (f2 INT, KEY(f2)); +INSERT INTO t2 VALUES (8),(0); + +CREATE TABLE t3 (f3 INT); +INSERT INTO t3 VALUES (1),(2); + +CREATE TABLE t4 (f4 INT); +INSERT INTO t4 VALUES (0),(5); + +explain +SELECT * FROM t1, t2, t3 WHERE f2 IN ( f1 IN ( SELECT f4 FROM t4 ) ); +SELECT * FROM t1, t2, t3 WHERE f2 IN ( f1 IN ( SELECT f4 FROM t4 ) ); + +drop table t1,t2,t3,t4; +set optimizer_switch= @tmp_mdev7823; + +--echo # +--echo # MDEV-6859: scalar subqueries in a comparison produced unexpected result +--echo # +set @tmp_mdev6859=@@optimizer_switch; +set optimizer_switch=default; +CREATE TABLE t1 ( + project_number varchar(50) NOT NULL, + PRIMARY KEY (project_number) +) ENGINE=MyISAM; + +INSERT INTO t1 (project_number) VALUES ('aaa'),('bbb'); + +CREATE TABLE t2 ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + project_number varchar(50) NOT NULL, + history_date date NOT NULL, + country varchar(50) NOT NULL, + PRIMARY KEY (id) +) ENGINE=MyISAM; + +INSERT INTO t2 (id, project_number, history_date, country) VALUES +(1, 'aaa', '2014-08-09', 'france'),(2, 'aaa', '2014-09-09', 'singapore'); + +CREATE TABLE t3 ( + region varchar(50) NOT NULL, + country varchar(50) NOT NULL +) ENGINE=MyISAM; + +INSERT INTO t3 (region, country) VALUES ('apac', 'singapore'),('eame', 'france'); + +SELECT SQL_NO_CACHE a.project_number +FROM t1 a +WHERE ( SELECT z.country + FROM t2 z + WHERE z.project_number = a.project_number AND z.history_date <= '2014-09-01' + ORDER BY z.id DESC LIMIT 1 + ) IN ( + SELECT r.country + FROM t3 r + WHERE r.region = 'eame' + ); + +drop table t1, t2, t3; +set optimizer_switch= @tmp_mdev6859; + # The following command must be the last one the file set optimizer_switch=@subselect_sj_tmp; diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 20585dd9ab7..065be302237 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -292,6 +292,8 @@ eval create table t1 (a int primary key) engine=myisam index directory="$MYSQLTEST_VARDIR/run"; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR show create table t1; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +select create_options from information_schema.tables where table_name='t1'; --echo # CREATE TABLE LIKE statement on table with INDEX/DATA DIRECTORY --echo # options should not fail. Per documentation newly created table --echo # should not inherit value of these options from the original table. diff --git a/mysql-test/t/trigger_null-8605.test b/mysql-test/t/trigger_null-8605.test index 6861676145f..4b51ccd5606 100644 --- a/mysql-test/t/trigger_null-8605.test +++ b/mysql-test/t/trigger_null-8605.test @@ -325,3 +325,50 @@ insert t1 values (9, 9, 2); insert t1 (a,c) values (9, 3); select * from t1; drop table t1; + +# +# MDEV-9428 NO_AUTO_VALUE_ON_ZERO is ignored when a trigger before insert is defined +# +set session sql_mode ='no_auto_value_on_zero'; +create table t1 (id int unsigned auto_increment primary key); +insert t1 values (0); +select * from t1; +delete from t1; +create trigger t1_bi before insert on t1 for each row begin end; +insert t1 values (0); +select * from t1; +drop table t1; + +# +# MDEV-9500 Bug after upgrade to 10.1.10 (and 10.1.11) +# +create table t1 (a int not null, b int); +create trigger trgi before update on t1 for each row do 1; +insert t1 values (1,1),(2,2),(3,3),(1,4); +create table t2 select a as c, b as d from t1; +update t1 set a=(select count(c) from t2 where c+1=a+1 group by a); +select * from t1; +drop table t1, t2; + +# +# MDEV-9535 Trigger doing "SET NEW.auctionStart = NOW();" on a timestamp kills MariaDB server. +# +create table t1 (a int not null); +create table t2 (f1 int unsigned not null, f2 int); +insert into t2 values (1, null); +create trigger tr1 before update on t1 for each row do 1; +create trigger tr2 after update on t2 for each row update t1 set a=new.f2; +update t2 set f2=1 where f1=1; +drop table t1, t2; + +# +# MDEV-9629 Disappearing PRI from Key column after creating a trigger +# +create table t1 (a int not null, primary key (a)); +insert into t1 (a) values (1); +show columns from t1; +create trigger t1bu before update on t1 for each row begin end; +show columns from t1; +insert into t1 (a) values (3); +show columns from t1; +drop table t1; diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index 34437df2f2c..52ca2c85b15 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -386,6 +386,14 @@ select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1; drop table t1; --echo # +--echo # MDEV-9511 Valgrind warnings 'Invalid read' in Field_newdate::cmp and Field_newdate::val_str +--echo # +CREATE TABLE t1 (f1 DATE, f2 VARCHAR(1)); +INSERT INTO t1 VALUES ('2003-04-27','a'),('1900-01-01','a'); +SELECT GROUP_CONCAT(f2, IF(f1, f2, f1), f1 ORDER BY 2,1,3) FROM t1; +DROP TABLE t1; + +--echo # --echo # Start of 10.1 tests --echo # @@ -402,15 +410,6 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a BETWEEN '2001-01-01 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a IN ('2001-01-01','2001-01-02'); DROP TABLE t1; - ---echo # ---echo # End of 10.1 tests ---echo # - ---echo # ---echo # Start of 10.1 tests ---echo # - --echo # --echo # MDEV-8699 Wrong result for SELECT..WHERE HEX(date_column)!='323030312D30312D3031' AND date_column='2001-01-01x' --echo # diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index 3717dc028ba..ec0256beeef 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -458,3 +458,57 @@ DROP TABLE t1; --echo # --echo # End of 10.1 tests --echo # + +--echo # +--echo # Start of 10.2 tests +--echo # + +--echo # +--echo # MDEV-4102 Limitation on DOUBLE or REAL length is ignored with INSERT .. SELECT +--echo # +CREATE TABLE t1 (d1 DOUBLE(5,2), d2 DOUBLE(10,2)); +INSERT INTO t1 VALUES (10000000.55, 10000000.55); +INSERT INTO t1 SELECT d2, d2 FROM t1; +SELECT * FROM t1; +DROP TABLE t1; + +--echo # +--echo # MDEV-9709 Unexpected modification of value and warning about out of range value upon ALTER +--echo # + +CREATE TABLE t1 ( + f FLOAT, + d10_10 DOUBLE PRECISION (10,10), + d53_10 DOUBLE(53,10) +); +INSERT INTO t1 (f,d10_10,d53_10) VALUES ( + -9999999999999999999999999999999999999999999.9999999999, + -9999999999999999999999999999999999999999999.9999999999, + -9999999999999999999999999999999999999999999.9999999999 +); +--vertical_results +SELECT * FROM t1; +INSERT INTO t1 (f,d10_10,d53_10) SELECT d53_10, d53_10, d53_10 FROM t1; +SELECT * FROM t1; +ALTER TABLE t1 ADD COLUMN i INT; +SELECT * FROM t1; +DROP TABLE t1; +--horizontal_results + +CREATE TABLE t1 (d10_10 DOUBLE (10,10)); +CREATE TABLE t2 (d53_10 DOUBLE (53,10)); +INSERT INTO t2 VALUES (-9999999999999999999999999999999999999999999.9999999999); +INSERT INTO t1 (d10_10) SELECT d53_10 FROM t2; +SELECT * FROM t1; +DROP TABLE t1,t2; + +CREATE TABLE t1 (d2_2 FLOAT (2,2)); +CREATE TABLE t2 (d4_2 FLOAT (4,2)); +INSERT INTO t2 VALUES (99.99); +INSERT INTO t1 (d2_2) SELECT d4_2 FROM t2; +SELECT * FROM t1; +DROP TABLE t1,t2; + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/mysql-test/t/type_num.test b/mysql-test/t/type_num.test index 6ed04c8e1d3..64242e34160 100644 --- a/mysql-test/t/type_num.test +++ b/mysql-test/t/type_num.test @@ -681,3 +681,27 @@ SELECT --echo # --echo # End of 10.0 tests --echo # + +--echo # +--echo # Start of 10.1 tests +--echo # + +--echo # +--echo # MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool) +--echo # + +--disable_ps_protocol +--enable_metadata +SELECT NULL+1 AS c0, + COALESCE(NULL)+1 AS c2, + COALESCE(COALESCE(NULL))+1 AS c3, + ''+1 AS c4, + COALESCE('')+1 AS c5, + COALESCE(COALESCE(''))+1 AS c6; +--disable_metadata +--enable_ps_protocol + + +--echo # +--echo # Start of 10.1 tests +--echo # diff --git a/mysql-test/t/type_temporal_innodb.test b/mysql-test/t/type_temporal_innodb.test new file mode 100644 index 00000000000..ac5daca6508 --- /dev/null +++ b/mysql-test/t/type_temporal_innodb.test @@ -0,0 +1,60 @@ +--source include/have_innodb.inc + +# +# testing of temporal data types with InnoDB +# + + +--echo # +--echo # MDEV-9604 crash in Item::save_in_field with empty enum value +--echo # + +SELECT TIME'00:00:00'=''; + +CREATE TABLE t1 (a ENUM('a'), b TIME, c INT, KEY(b)) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('','00:00:00',0); +SELECT * FROM t1 WHERE b=''; +SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; +SELECT * FROM t1 WHERE a=b; +SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; + +ALTER TABLE t1 ENGINE=MyISAM; +SELECT * FROM t1 WHERE b=''; +SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; +SELECT * FROM t1 WHERE a=b; +SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; +DROP TABLE t1; + + +SELECT DATE'0000-00-00'=''; + +CREATE TABLE t1 (a ENUM('a'), b DATE, c INT, KEY(b)) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('','0000-00-00',0); +SELECT * FROM t1 WHERE b=''; +SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; +SELECT * FROM t1 WHERE a=b; +SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; + +ALTER TABLE t1 ENGINE=MyISAM; +SELECT * FROM t1 WHERE b=''; +SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; +SELECT * FROM t1 WHERE a=b; +SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; +DROP TABLE t1; + + +SELECT TIMESTAMP'0000-00-00 00:00:00'=''; + +CREATE TABLE t1 (a ENUM('a'), b DATETIME, c INT, KEY(b)) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('','0000-00-00 00:00:00',0); +SELECT * FROM t1 WHERE b=''; +SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; +SELECT * FROM t1 WHERE a=b; +SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; + +ALTER TABLE t1 ENGINE=MyISAM; +SELECT * FROM t1 WHERE b=''; +SELECT * FROM t1 IGNORE KEY (b) WHERE b=''; +SELECT * FROM t1 WHERE a=b; +SELECT 1 FROM t1 WHERE (SELECT a FROM t1 group by c) = b; +DROP TABLE t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index fb4992023f0..83b7e5839ef 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -731,6 +731,7 @@ drop table t2; create table t1 (a int); insert into t1 values (1), (2); create view v1 as select 5 from t1 order by 1; +show create view v1; select * from v1; drop view v1; drop table t1; @@ -5491,6 +5492,16 @@ deallocate prepare stmt; drop view v1,v2; drop table `t1`; + +# +# Bug#19817021 +# +create table t1 (a int, b int); +create view v1 as select a+b from t1; +alter table v1 check partition p1; +drop view v1; +drop table t1; + --echo # ----------------------------------------------------------------- --echo # -- End of 5.5 tests. --echo # ----------------------------------------------------------------- @@ -5737,6 +5748,22 @@ SELECT * FROM v1 WHERE a=_latin1'a' COLLATE latin1_bin; DROP VIEW v1; DROP TABLE t1; +--echo # +--echo # MDEV-9701: CREATE VIEW with GROUP BY or ORDER BY and constant +--echo # produces invalid definition +--echo # +CREATE TABLE t1 ( i INT ); +INSERT INTO t1 VALUES (1),(2); + +CREATE VIEW v1 AS +SELECT 3 AS three, COUNT(*) FROM t1 GROUP BY three; + +show create view v1; + +SELECT * FROM v1; + +drop view v1; +drop table t1; --echo # --echo # End of 10.1 tests diff --git a/mysql-test/t/xa_sync.test b/mysql-test/t/xa_sync.test index 8a995c4a184..bb95af7c0ba 100644 --- a/mysql-test/t/xa_sync.test +++ b/mysql-test/t/xa_sync.test @@ -25,10 +25,9 @@ while ($i) disconnect con1; disable_query_log; echo # Waiting for thread to get deleted; - while (`SELECT VARIABLE_VALUE!=2 FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='max_used_connections'`) + while (`SELECT count(*)!=2 FROM INFORMATION_SCHEMA.PROCESSLIST`) { real_sleep 0.1; - FLUSH STATUS; } enable_query_log; SET debug_sync='now SIGNAL go'; diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index a9e1a9e9d8e..b5c9b62049b 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -1,5 +1,5 @@ -# Copyright (c) 2005, 2011, Oracle and/or its affiliates. -# Copyright (c) 2008-2011, Monty Program Ab +# Copyright (c) 2005, 2015, Oracle and/or its affiliates. +# Copyright (c) 2008, 2016, MariaDB # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public @@ -1091,8 +1091,8 @@ # write_keys() and find_all_keys(). # They both return ha_rows, which is platform dependent. # -# The '...' wildcards are for 'fun:inline_mysql_file_write' which *may* -# be inlined. +# The '...' wildcards are for 'fun:inline_mysql_file_write' and +# 'fun:find_all_keys' which *may* be inlined. { Bug#12856915 VALGRIND FAILURE IN FILESORT/CREATE_SORT_INDEX / one Memcheck:Param @@ -1103,7 +1103,7 @@ fun:my_b_flush_io_cache fun:_my_b_write fun:_Z*10write_keysP13st_sort_paramPPhjP11st_io_cacheS4_ - fun:_Z*13find_all_keysP13st_sort_paramP10SQL_SELECTPPhP11st_io_cacheS6_ + ... fun:_Z8filesortP3THDP5TABLEP13st_sort_fieldjP10SQL_SELECTybPy } @@ -1278,25 +1278,12 @@ } { - GitHub codership/galera#308 - Memcheck:Leak - match-leak-kinds: definite - fun:malloc - fun:_ZNK6galera13ReplicatorSMM9stats_getEv - fun:_ZL28export_wsrep_status_to_mysqlP3THD - fun:_Z17wsrep_show_statusP3THDP17st_mysql_show_varPc - fun:_ZL17show_status_arrayP3THDPKcP17st_mysql_show_var13enum_var_typeP17system_status_varS2_P5TABLEbP4Item - fun:_Z11fill_statusP3THDP10TABLE_LISTP4Item - fun:_ZL13do_fill_tableP3THDP10TABLE_LISTP13st_join_table - fun:_Z24get_schema_tables_resultP4JOIN23enum_schema_table_state - fun:_ZN4JOIN14prepare_resultEPP4ListI4ItemE - fun:_ZN4JOIN4execEv - fun:_ZL20mysql_execute_selectP3THDP13st_select_lexb - fun:_Z12mysql_selectP3THDP10TABLE_LISTjR4ListI4ItemEPS4_P10SQL_I_ListI8st_orderESB_S7_yP13select_resultP18st_select_lex_unitP13st_select_lex - fun:_Z13handle_selectP3THDP13select_resultm - fun:_ZL21execute_sqlcom_selectP3THDP10TABLE_LIST - fun:_Z21mysql_execute_commandP3THD - fun:_Z11mysql_parseP3THDPcjP12Parser_state + vasprintf in OpenSuse 12.3 + Memcheck:Leak + fun:malloc + fun:vasprintf + fun:asprintf + fun:dlerror } { diff --git a/mysys/file_logger.c b/mysys/file_logger.c index 394b59f6378..b94cb705d3f 100644 --- a/mysys/file_logger.c +++ b/mysys/file_logger.c @@ -14,11 +14,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifndef FLOGGER_SKIP_INCLUDES #include "my_global.h" #include <my_sys.h> #include <m_string.h> #include <mysql/service_logger.h> #include <my_pthread.h> +#endif /*FLOGGER_SKIP_INCLUDES*/ #ifndef flogger_mutex_init #define flogger_mutex_init(A,B,C) mysql_mutex_init(A,B,C) diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index f8a15829fb1..b349ef88ed1 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -103,6 +103,12 @@ #include <my_sys.h> #include <lf.h> +/* + when using alloca() leave at least that many bytes of the stack - + for functions we might be calling from within this stack frame +*/ +#define ALLOCA_SAFETY_MARGIN 8192 + #define LF_PINBOX_MAX_PINS 65536 static void lf_pinbox_real_free(LF_PINS *pins); @@ -345,7 +351,8 @@ static void lf_pinbox_real_free(LF_PINS *pins) { int alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins; /* create a sorted list of pinned addresses, to speed up searches */ - if (available_stack_size(&pinbox, *pins->stack_ends_here) > alloca_size) + if (available_stack_size(&pinbox, *pins->stack_ends_here) > + alloca_size + ALLOCA_SAFETY_MARGIN) { struct st_harvester hv; addr= (void **) alloca(alloca_size); diff --git a/mysys/lf_hash.c b/mysys/lf_hash.c index 10fe5ae40c4..6be11edbfcf 100644 --- a/mysys/lf_hash.c +++ b/mysys/lf_hash.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index ffe818e12b9..92418e38c2e 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -4248,7 +4248,7 @@ mariadb_dyncol_unpack(DYNAMIC_COLUMN *str, { *names= my_malloc(sizeof(LEX_STRING) * header.column_count + DYNCOL_NUM_CHAR * header.column_count, MYF(0)); - nm= (char *)(names + sizeof(LEX_STRING) * header.column_count); + nm= (char *)((*names) + header.column_count); } else { diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c index 93caa7bc74a..2499094037d 100644 --- a/mysys/mf_iocache2.c +++ b/mysys/mf_iocache2.c @@ -44,7 +44,7 @@ RETURN VALUE 0 All OK - 1 An error occured + 1 An error occurred */ int my_b_copy_to_file(IO_CACHE *cache, FILE *file) diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index d9bc0e9094e..3077415b243 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -274,7 +274,7 @@ struct st_hash_link }; /* simple states of a block */ -#define BLOCK_ERROR 1 /* an error occured when performing file i/o */ +#define BLOCK_ERROR 1 /* an error occurred when performing file i/o */ #define BLOCK_READ 2 /* file block is in the block buffer */ #define BLOCK_IN_SWITCH 4 /* block is preparing to read new page */ #define BLOCK_REASSIGNED 8 /* blk does not accept requests for old page */ @@ -1068,7 +1068,7 @@ static void link_into_queue(KEYCACHE_WQUEUE *wqueue, static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue, struct st_my_thread_var *thread) { - KEYCACHE_DBUG_PRINT("unlink_from_queue", ("thread %ld", thread->id)); + KEYCACHE_DBUG_PRINT("unlink_from_queue", ("thread %ld", (ulong) thread->id)); DBUG_ASSERT(thread->next && thread->prev); if (thread->next == thread) @@ -1145,7 +1145,7 @@ static void wait_on_queue(KEYCACHE_WQUEUE *wqueue, */ do { - KEYCACHE_DBUG_PRINT("wait", ("suspend thread %ld", thread->id)); + KEYCACHE_DBUG_PRINT("wait", ("suspend thread %ld", (ulong) thread->id)); keycache_pthread_cond_wait(&thread->suspend, mutex); } while (thread->next); @@ -1184,7 +1184,7 @@ static void release_whole_queue(KEYCACHE_WQUEUE *wqueue) thread=next; DBUG_ASSERT(thread && thread->init == 1); KEYCACHE_DBUG_PRINT("release_whole_queue: signal", - ("thread %ld", thread->id)); + ("thread %ld", (ulong) thread->id)); /* Take thread from queue. */ next= thread->next; thread->next= NULL; @@ -1388,7 +1388,8 @@ static void link_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block, */ if ((HASH_LINK *) thread->keycache_link == hash_link) { - KEYCACHE_DBUG_PRINT("link_block: signal", ("thread %ld", thread->id)); + KEYCACHE_DBUG_PRINT("link_block: signal", + ("thread %ld", (ulong) thread->id)); keycache_pthread_cond_signal(&thread->suspend); unlink_from_queue(&keycache->waiting_for_block, thread); block->requests++; @@ -1677,7 +1678,7 @@ static void wait_for_readers(SIMPLE_KEY_CACHE_CB *keycache, { KEYCACHE_DBUG_PRINT("wait_for_readers: wait", ("suspend thread %ld block %u", - thread->id, BLOCK_NUMBER(block))); + (ulong) thread->id, BLOCK_NUMBER(block))); /* There must be no other waiter. We have no queue here. */ DBUG_ASSERT(!block->condvar); block->condvar= &thread->suspend; @@ -1737,7 +1738,8 @@ static void unlink_hash(SIMPLE_KEY_CACHE_CB *keycache, HASH_LINK *hash_link) */ if (page->file == hash_link->file && page->filepos == hash_link->diskpos) { - KEYCACHE_DBUG_PRINT("unlink_hash: signal", ("thread %ld", thread->id)); + KEYCACHE_DBUG_PRINT("unlink_hash: signal", + ("thread %ld", (ulong) thread->id)); keycache_pthread_cond_signal(&thread->suspend); unlink_from_queue(&keycache->waiting_for_hash_link, thread); } @@ -1821,7 +1823,7 @@ restart: thread->keycache_link= (void *) &page; link_into_queue(&keycache->waiting_for_hash_link, thread); KEYCACHE_DBUG_PRINT("get_hash_link: wait", - ("suspend thread %ld", thread->id)); + ("suspend thread %ld", (ulong) thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); thread->keycache_link= NULL; @@ -1987,7 +1989,7 @@ restart: do { KEYCACHE_DBUG_PRINT("find_key_block: wait", - ("suspend thread %ld", thread->id)); + ("suspend thread %ld", (ulong) thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } while (thread->next); @@ -2334,7 +2336,7 @@ restart: do { KEYCACHE_DBUG_PRINT("find_key_block: wait", - ("suspend thread %ld", thread->id)); + ("suspend thread %ld", (ulong) thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -4585,7 +4587,7 @@ static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache) KEYCACHE_PAGE *page; uint i; - fprintf(keycache_dump_file, "thread:%u\n", thread->id); + fprintf(keycache_dump_file, "thread:%lu\n", (ulong) thread->id); i=0; thread=last=waiting_for_hash_link.last_thread; @@ -4596,8 +4598,8 @@ static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache) thread=thread->next; page= (KEYCACHE_PAGE *) thread->keycache_link; fprintf(keycache_dump_file, - "thread:%u, (file,filepos)=(%u,%lu)\n", - thread->id,(uint) page->file,(ulong) page->filepos); + "thread:%lu, (file,filepos)=(%u,%lu)\n", + (ulong) thread->id,(uint) page->file,(ulong) page->filepos); if (++i == MAX_QUEUE_LEN) break; } @@ -4612,8 +4614,8 @@ static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache) thread=thread->next; hash_link= (HASH_LINK *) thread->keycache_link; fprintf(keycache_dump_file, - "thread:%u hash_link:%u (file,filepos)=(%u,%lu)\n", - thread->id, (uint) HASH_LINK_NUMBER(hash_link), + "thread:%lu hash_link:%u (file,filepos)=(%u,%lu)\n", + (ulong) thread->id, (uint) HASH_LINK_NUMBER(hash_link), (uint) hash_link->file,(ulong) hash_link->diskpos); if (++i == MAX_QUEUE_LEN) break; @@ -4640,7 +4642,7 @@ static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache) { thread=thread->next; fprintf(keycache_dump_file, - "thread:%u\n", thread->id); + "thread:%lu\n", (ulong) thread->id); if (++i == MAX_QUEUE_LEN) break; } diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c index 9c9a7d9b97c..72b04119855 100644 --- a/mysys/my_addr_resolve.c +++ b/mysys/my_addr_resolve.c @@ -145,30 +145,75 @@ static int initialized= 0; static char output[1024]; int my_addr_resolve(void *ptr, my_addr_loc *loc) { - char input[32], *s; + char input[32]; size_t len; + ssize_t total_bytes_read = 0; + ssize_t extra_bytes_read = 0; + + fd_set set; + struct timeval timeout; + + int filename_start = -1; + int line_number_start = -1; + ssize_t i; + + FD_ZERO(&set); + FD_SET(out[0], &set); + len= my_snprintf(input, sizeof(input), "%p\n", ptr - offset); if (write(in[1], input, len) <= 0) return 1; - if (read(out[0], output, sizeof(output)) <= 0) + + /* 10 ms should be plenty of time for addr2line to issue a response. */ + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + /* Read in a loop till all the output from addr2line is complete. */ + while (select(out[0] + 1, &set, NULL, NULL, &timeout) > 0) + { + extra_bytes_read= read(out[0], output + total_bytes_read, + sizeof(output) - total_bytes_read); + if (extra_bytes_read < 0) + return 1; + /* Timeout or max bytes read. */ + if (extra_bytes_read == 0) + break; + + total_bytes_read += extra_bytes_read; + } + + /* Failed starting addr2line. */ + if (total_bytes_read == 0) return 1; - loc->func= s= output; - while (*s != '\n') - s++; - *s++= 0; - loc->file= s; - while (*s != ':') - s++; - *s++= 0; + /* Go through the addr2line response and get the required data. + The response is structured in 2 lines. The first line contains the function + name, while the second one contains <filename>:<line number> */ + for (i = 0; i < total_bytes_read; i++) { + if (output[i] == '\n') { + filename_start = i + 1; + output[i] = '\0'; + } + if (filename_start != -1 && output[i] == ':') { + line_number_start = i + 1; + output[i] = '\0'; + } + if (line_number_start != -1) { + loc->line= atoi(output + line_number_start); + break; + } + } + /* Response is malformed. */ + if (filename_start == -1 || line_number_start == -1) + return 1; + + loc->func= output; + loc->file= output + filename_start; + + /* Addr2line was unable to extract any meaningful information. */ if (strcmp(loc->file, "??") == 0) return 1; - loc->line= 0; - while (isdigit(*s)) - loc->line = loc->line * 10 + (*s++ - '0'); - *s = 0; loc->file= strip_path(loc->file); return 0; diff --git a/mysys/my_default.c b/mysys/my_default.c index 0ce01960630..7f41551f779 100644 --- a/mysys/my_default.c +++ b/mysys/my_default.c @@ -363,7 +363,7 @@ err: RETURN 0 - ok - 1 - error occured + 1 - error occurred */ static int handle_default_option(void *in_ctx, const char *group_name, @@ -576,6 +576,7 @@ int my_load_defaults(const char *conf_file, const char **groups, handle_default_option, (void *) &ctx, dirs))) { + delete_dynamic(&args); free_root(&alloc,MYF(0)); DBUG_RETURN(error); } diff --git a/mysys/my_delete.c b/mysys/my_delete.c index e99c7ff5fcb..3dfe290dabe 100644 --- a/mysys/my_delete.c +++ b/mysys/my_delete.c @@ -110,7 +110,7 @@ static int my_win_unlink(const char *name) if (handle != INVALID_HANDLE_VALUE) { /* - We opened file without sharing flags (exclusive), noone else has this file + We opened file without sharing flags (exclusive), no one else has this file opened, thus it is save to close handle to remove it. No renaming is necessary. */ diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c index 208f2ff902a..0fad7f90552 100644 --- a/mysys/my_gethwaddr.c +++ b/mysys/my_gethwaddr.c @@ -72,7 +72,7 @@ err: return res; } -#elif defined(__linux__) || defined(__sun__) +#elif defined(__linux__) || defined(__sun) #include <net/if.h> #include <sys/ioctl.h> #include <net/if_arp.h> diff --git a/mysys/my_lock.c b/mysys/my_lock.c index 0abbc6c3084..082d8e9f5a0 100644 --- a/mysys/my_lock.c +++ b/mysys/my_lock.c @@ -131,7 +131,7 @@ error: RETURN VALUE 0 Success - -1 An error has occured and 'my_errno' is set + -1 An error has occurred and 'my_errno' is set to indicate the actual error code. */ @@ -203,7 +203,7 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, == MY_FILEPOS_ERROR) { /* - If an error has occured in my_seek then we will already + If an error has occurred in my_seek then we will already have an error code in my_errno; Just return error code. */ DBUG_RETURN(-1); diff --git a/mysys/my_rnd.c b/mysys/my_rnd.c index 14f212e2f32..ad7bda0b42b 100644 --- a/mysys/my_rnd.c +++ b/mysys/my_rnd.c @@ -95,7 +95,3 @@ double my_rnd_ssl(struct my_rnd_struct *rand_st) return my_rnd(rand_st); } - -#ifdef __cplusplus -} -#endif diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c index c761064dd96..07ba4f5c587 100644 --- a/mysys/my_wincond.c +++ b/mysys/my_wincond.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. + Copyright (c) 2011, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index 5d19647c989..9916650308a 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -55,6 +55,9 @@ struct st_irem struct st_irem *next; /* Linked list of structures */ struct st_irem *prev; /* Other link */ size_t datasize; /* Size requested */ +#if SIZEOF_SIZE_T == 4 + size_t pad; /* Compensate 32bit datasize */ +#endif #ifdef HAVE_BACKTRACE void *frame[SF_REMEMBER_FRAMES]; /* call stack */ #endif @@ -375,7 +378,7 @@ void sf_report_leaked_memory(my_thread_id id) { my_thread_id tid = irem->thread_id && irem->flags & MY_THREAD_SPECIFIC ? irem->thread_id : 0; - fprintf(stderr, "Warning: %4lu bytes lost at %p, allocated by T@%lu at ", + fprintf(stderr, "Warning: %4lu bytes lost at %p, allocated by T@%llu at ", (ulong) irem->datasize, (char*) (irem + 1), tid); print_stack(irem->frame); total+= irem->datasize; diff --git a/mysys/string.c b/mysys/string.c index cc73d18c601..a0fa3a02e17 100644 --- a/mysys/string.c +++ b/mysys/string.c @@ -142,16 +142,16 @@ my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n) my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...) { #ifdef __WIN__ - const char *quote_str= "\""; - const uint quote_len= 1; + LEX_CSTRING quote= { C_STRING_WITH_LEN("\"") }; + LEX_CSTRING replace= { C_STRING_WITH_LEN("\\\"") }; #else - const char *quote_str= "\'"; - const uint quote_len= 1; + LEX_CSTRING quote= { C_STRING_WITH_LEN("\'") }; + LEX_CSTRING replace= { C_STRING_WITH_LEN("'\"'\"'") }; #endif /* __WIN__ */ my_bool ret= TRUE; va_list dirty_text; - ret&= dynstr_append_mem(str, quote_str, quote_len); /* Leading quote */ + ret&= dynstr_append_mem(str, quote.str, quote.length); /* Leading quote */ va_start(dirty_text, append); while (append != NullS) { @@ -159,18 +159,17 @@ my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...) const char *next_pos= cur_pos; /* Search for quote in each string and replace with escaped quote */ - while(*(next_pos= strcend(cur_pos, quote_str[0])) != '\0') + while(*(next_pos= strcend(cur_pos, quote.str[0])) != '\0') { ret&= dynstr_append_mem(str, cur_pos, (uint) (next_pos - cur_pos)); - ret&= dynstr_append_mem(str ,"\\", 1); - ret&= dynstr_append_mem(str, quote_str, quote_len); + ret&= dynstr_append_mem(str, replace.str, replace.length); cur_pos= next_pos + 1; } ret&= dynstr_append_mem(str, cur_pos, (uint) (next_pos - cur_pos)); append= va_arg(dirty_text, char *); } va_end(dirty_text); - ret&= dynstr_append_mem(str, quote_str, quote_len); /* Trailing quote */ + ret&= dynstr_append_mem(str, quote.str, quote.length); /* Trailing quote */ return ret; } diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 8990cbd5a14..da653b12314 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -772,7 +772,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) mysql_mutex_lock(&lock->mutex); DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx type: %d", - (long) data, data->owner->thread_id, + (long) data, (ulong) data->owner->thread_id, (long) lock, (int) lock_type)); check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ? "enter read_lock" : "enter write_lock", lock_type, 0); @@ -809,7 +809,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) */ DBUG_PRINT("lock",("write locked 1 by thread: 0x%lx", - lock->write.data->owner->thread_id)); + (ulong) lock->write.data->owner->thread_id)); if (thr_lock_owner_equal(data->owner, lock->write.data->owner) || (lock->write.data->type <= TL_WRITE_DELAYED && (((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) || @@ -968,7 +968,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) goto end; } DBUG_PRINT("lock",("write locked 2 by thread: 0x%lx", - lock->write.data->owner->thread_id)); + (ulong) lock->write.data->owner->thread_id)); } else { @@ -1004,7 +1004,8 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) } } DBUG_PRINT("lock",("write locked 3 by thread: 0x%lx type: %d", - lock->read.data->owner->thread_id, data->type)); + (ulong) lock->read.data->owner->thread_id, + data->type)); } #ifdef WITH_WSREP if (wsrep_break_lock(data, &lock->write, &lock->write_wait)) @@ -1069,7 +1070,7 @@ static inline void free_all_read_locks(THR_LOCK *lock, } /* purecov: begin inspected */ DBUG_PRINT("lock",("giving read lock to thread: 0x%lx", - data->owner->thread_id)); + (ulong) data->owner->thread_id)); /* purecov: end */ data->cond=0; /* Mark thread free */ mysql_cond_signal(cond); @@ -1087,8 +1088,9 @@ void thr_unlock(THR_LOCK_DATA *data, uint unlock_flags) THR_LOCK *lock=data->lock; enum thr_lock_type lock_type=data->type; DBUG_ENTER("thr_unlock"); - DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx", - (long) data, data->owner->thread_id, (long) lock)); + DBUG_PRINT("lock",("data: %p thread: 0x%lx lock: %p", + data, (ulong) data->owner->thread_id, + lock)); mysql_mutex_lock(&lock->mutex); check_locks(lock,"start of release lock", lock_type, 0); @@ -1181,7 +1183,7 @@ static void wake_up_waiters(THR_LOCK *lock) data->type=TL_WRITE; /* Upgrade lock */ /* purecov: begin inspected */ DBUG_PRINT("lock",("giving write lock of type %d to thread: 0x%lx", - data->type, data->owner->thread_id)); + data->type, (ulong) data->owner->thread_id)); /* purecov: end */ { mysql_cond_t *cond= data->cond; @@ -1423,9 +1425,9 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count, uint unlock_flags) thr_unlock(*pos, unlock_flags); else { - DBUG_PRINT("lock",("Free lock: data: 0x%lx thread: 0x%lx lock: 0x%lx", - (long) *pos, (*pos)->owner->thread_id, - (long) (*pos)->lock)); + DBUG_PRINT("lock",("Free lock: data: %p thread: 0x%lx lock: %p", + *pos, (ulong) (*pos)->owner->thread_id, + (*pos)->lock)); } } DBUG_VOID_RETURN; @@ -1673,7 +1675,7 @@ static void thr_print_lock(const char* name,struct st_lock_list *list) prev= &list->data; for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next) { - printf("0x%lx (%lu:%d); ", (ulong) data, data->owner->thread_id, + printf("%p (%lu:%d); ", data, (ulong) data->owner->thread_id, (int) data->type); if (data->prev != prev) printf("\nWarning: prev didn't point at previous lock\n"); diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index 4d6abd4ba66..f1e83db2bb6 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -510,7 +510,7 @@ int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file, fprintf(stderr, "safe_mutex: Count was %d in thread 0x%lx when locking mutex %s " "at %s, line %d\n", - mp->count-1, my_thread_dbug_id(), mp->name, file, line); + mp->count-1, (ulong) my_thread_dbug_id(), mp->name, file, line); fflush(stderr); abort(); } @@ -564,7 +564,7 @@ int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp, fprintf(stderr, "safe_mutex: Count was %d in thread 0x%lx when locking mutex " "%s at %s, line %d (error: %d (%d))\n", - mp->count-1, my_thread_dbug_id(), mp->name, file, line, + mp->count-1, (ulong) my_thread_dbug_id(), mp->name, file, line, error, error); fflush(stderr); abort(); diff --git a/plugin/auth_dialog/CMakeLists.txt b/plugin/auth_dialog/CMakeLists.txt index a23518060be..7253b2b2f97 100644 --- a/plugin/auth_dialog/CMakeLists.txt +++ b/plugin/auth_dialog/CMakeLists.txt @@ -15,4 +15,4 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA MYSQL_ADD_PLUGIN(dialog dialog.c ${CMAKE_SOURCE_DIR}/libmysql/get_password.c - MODULE_ONLY COMPONENT ClientPlugins) + MODULE_ONLY CLIENT COMPONENT ClientPlugins) diff --git a/plugin/auth_examples/CMakeLists.txt b/plugin/auth_examples/CMakeLists.txt index c7b7e5be62d..d1152227eff 100644 --- a/plugin/auth_examples/CMakeLists.txt +++ b/plugin/auth_examples/CMakeLists.txt @@ -30,4 +30,4 @@ MYSQL_ADD_PLUGIN(qa_auth_client qa_auth_client.c MYSQL_ADD_PLUGIN(auth_0x0100 auth_0x0100.c MODULE_ONLY COMPONENT Test) MYSQL_ADD_PLUGIN(mysql_clear_password clear_password_client.c - MODULE_ONLY COMPONENT ClientPlugins) + MODULE_ONLY CLIENT COMPONENT ClientPlugins) diff --git a/plugin/auth_gssapi/CMakeLists.txt b/plugin/auth_gssapi/CMakeLists.txt new file mode 100644 index 00000000000..7d9e58e165f --- /dev/null +++ b/plugin/auth_gssapi/CMakeLists.txt @@ -0,0 +1,45 @@ +IF (WIN32) + SET(USE_SSPI 1) +ENDIF() + +IF(USE_SSPI) + SET(GSSAPI_LIBS secur32) + ADD_DEFINITIONS(-DPLUGIN_SSPI) + SET(GSSAPI_CLIENT sspi_client.cc) + SET(GSSAPI_SERVER sspi_server.cc) + SET(GSSAPI_ERRMSG sspi_errmsg.cc) +ELSE() + SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) + FIND_PACKAGE(GSSAPI) + IF(GSSAPI_FOUND) + INCLUDE_DIRECTORIES(${GSSAPI_INCS}) + ADD_DEFINITIONS(-DPLUGIN_GSSAPI) + SET(GSSAPI_CLIENT gssapi_client.cc) + SET(GSSAPI_SERVER gssapi_server.cc) + SET(GSSAPI_ERRMSG gssapi_errmsg.cc) + + SET(CMAKE_REQUIRED_INCLUDES ${GSSAPI_INCS}) + SET(CMAKE_REQUIRED_LIBRARIES ${GSSAPI_LIBS}) + INCLUDE(CheckCXXSymbolExists) + CHECK_CXX_SYMBOL_EXISTS(krb5_free_unparsed_name "krb5.h" HAVE_KRB5_FREE_UNPARSED_NAME) + IF(HAVE_KRB5_FREE_UNPARSED_NAME) + ADD_DEFINITIONS(-DHAVE_KRB5_FREE_UNPARSED_NAME=1) + ENDIF() + + ELSE() + # Can't build plugin + RETURN() + ENDIF() +ENDIF () + + +MYSQL_ADD_PLUGIN(auth_gssapi server_plugin.cc ${GSSAPI_SERVER} ${GSSAPI_ERRMSG} + LINK_LIBRARIES ${GSSAPI_LIBS} + COMPONENT gssapi-server + MODULE_ONLY) + +MYSQL_ADD_PLUGIN(auth_gssapi_client client_plugin.cc ${GSSAPI_CLIENT} ${GSSAPI_ERRMSG} + LINK_LIBRARIES ${GSSAPI_LIBS} + COMPONENT gssapi-client + CLIENT + MODULE_ONLY) diff --git a/plugin/auth_gssapi/README.md b/plugin/auth_gssapi/README.md new file mode 100644 index 00000000000..7f678400f0d --- /dev/null +++ b/plugin/auth_gssapi/README.md @@ -0,0 +1,129 @@ +# GSSAPI/SSPI authentication for MariaDB + +This article gives instructions on configuring GSSAPI authentication plugin +for MariaDB for passwordless login. + +On Unix systems, GSSAPI is usually synonymous with Kerberos authentication. +Windows has slightly different but very similar API called SSPI, that along with Kerberos, also supports NTLM authentication. + +This plugin includes support for Kerberos on Unix, but also can be used as for Windows authentication with or without domain +environment. + +## Server-side preparations on Unix +To use the plugin, some preparation need to be done on the server side on Unixes. +MariaDB server will need read access to the Kerberos keytab file, that contains service principal name for the MariaDB server. + + +If you are using **Unix Kerberos KDC (MIT,Heimdal)** + +- Create service principal using kadmin tool + +``` +kadmin -q "addprinc -randkey mariadb/host.domain.com" +``` + +(replace host.domain.com with fully qualified DNS name for the server host) + +- Export the newly created user to the keytab file + +``` +kadmin -q "ktadd -k /path/to/mariadb.keytab mariadb/host.domain.com" +``` + +More details can be found [here](http://www.microhowto.info/howto/create_a_service_principal_using_mit_kerberos.html) +and [here](http://www.microhowto.info/howto/add_a_host_or_service_principal_to_a_keytab_using_mit_kerberos.html) + +If you are using **Windows Active Directory KDC** +you can need to create keytab using ktpass.exe tool on Windows, map principal user to an existing domain user like this + +``` +ktpass.exe /princ mariadb/host.domain.com@DOMAIN.COM /mapuser someuser /pass MyPas$w0rd /out mariadb.keytab /crypto all /ptype KRB5_NT_PRINCIPAL /mapop set +``` + +and then transfer the keytab file to the Unix server. See [Microsoft documentation](https://technet.microsoft.com/en-us/library/cc753771.aspx) for details. + + +## Server side preparations on Windows. +Usually nothing need to be done. MariaDB server should to run on a domain joined machine, either as NetworkService account +(which is default if it runs as service) or run under any other domain account credentials. +Creating service principal is not required here (but you can still do it using [_setspn_](https://technet.microsoft.com/en-us/library/cc731241.aspx) tool) + + +# Installing plugin +- Start the server + +- On Unix, edit my the my.cnf/my.ini configuration file, set the parameter gssapi-keytab-path to point to previously +created keytab path. + +``` + gssapi-keytab-path=/path/to/mariadb.keytab +``` + +- Optionally on Unix, in case the service principal name differs from default mariadb/host.domain.com@REALM, +configure alternative principal name with + +``` + gssapi-principal-name=alternative/principalname@REALM +``` + +- In mysql command line client, execute + +``` + INSTALL SONAME 'auth_gssapi' +``` + +#Creating users + +Now, you can create a user for GSSAPI/SSPI authentication. CREATE USER command, for Kerberos user +would be like this (*long* form, see below for short one) + +``` +CREATE USER usr1 IDENTIFIED WITH gssapi AS 'usr1@EXAMPLE.COM'; +``` + +(replace with real username and realm) + +The part after AS is mechanism specific, and needs to be ``machine\\usr1`` for Windows users identified with NTLM. + +You may also use alternative *short* form of CREATE USER + +``` +CREATE USER usr1 IDENTIFIED WITH gssapi; +``` + +If this syntax is used, realm part is *not* used for comparison +thus 'usr1@EXAMPLE.COM', 'usr1@EXAMPLE.CO.UK' and 'mymachine\usr1' will all identify as 'usr1'. + +#Login as GSSAPI user with command line clients + +Using command line client, do + +``` +mysql --plugin-dir=/path/to/plugin-dir -u usr1 +``` + +#Plugin variables +- **gssapi-keytab-path** (Unix only) - Path to the server keytab file +- **gssapi-principal-name** - name of the service principal. +- **gssapi-mech-name** (Windows only) - Name of the SSPI package used by server. Can be either 'Kerberos' or 'Negotiate'. + Defaults to 'Negotiate' (both Kerberos and NTLM users can connect) + Set it to 'Kerberos', to prevent less secure NTLM in domain environments, but leave it as default(Negotiate) + to allow non-domain environment (e.g if server does not run in domain enviroment). + + +#Implementation + +Overview of the protocol between client and server + +1. Server : Construct gssapi-principal-name if not set in my.cnf. On Unixes defaults to hostbased name for service "mariadb". On Windows to user's or machine's domain names. +Acquire credentials for gssapi-principal-name with ```gss_acquire_cred() / AcquireSecurityCredentials()```. +Send packet with principal name and mech ```"gssapi-principal-name\0gssapi-mech-name\0"``` to client ( on Unix, empty string used for gssapi-mech) + +2. Client: execute ```gss_init_sec_context() / InitializeSecurityContext()``` passing gssapi-principal-name / gssapi-mech-name parameters. +Send resulting GSSAPI blob to server. + +3. Server : receive blob from client, execute ```gss_accept_sec_context()/ AcceptSecurityContext()```, send resulting blob back to client + +4. Perform 2. and 3. can until both client and server decide that authentication is done, or until some error occured. If authentication was successful, GSSAPI context (an opaque structure) is generated on both client and server sides. + +5. Server : Client name is extracted from the context, and compared to the name provided by client(with or without realm). If name matches, plugin returns success. diff --git a/plugin/auth_gssapi/client_plugin.cc b/plugin/auth_gssapi/client_plugin.cc new file mode 100644 index 00000000000..0ab619a08e6 --- /dev/null +++ b/plugin/auth_gssapi/client_plugin.cc @@ -0,0 +1,112 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + @file + + GSSAPI authentication plugin, client side +*/ +#include <string.h> +#include <stdarg.h> +#include <mysqld_error.h> +#include <mysql/client_plugin.h> +#include <mysql.h> +#include <stdio.h> +#include "common.h" + +extern int auth_client(char *principal_name, + char *mech, + MYSQL *mysql, + MYSQL_PLUGIN_VIO *vio); + +static void parse_server_packet(char *packet, size_t packet_len, char *spn, char *mech) +{ + size_t spn_len; + spn_len = strnlen(packet, packet_len); + strncpy(spn, packet, PRINCIPAL_NAME_MAX); + if (spn_len == packet_len - 1) + { + /* Mechanism not included into packet */ + *mech = 0; + } + else + { + strncpy(mech, packet + spn_len + 1, MECH_NAME_MAX); + } +} + +/** + Set client error message. + */ +void log_client_error(MYSQL *mysql, const char *format, ...) +{ + NET *net= &mysql->net; + va_list args; + + net->last_errno= ER_UNKNOWN_ERROR; + va_start(args, format); + vsnprintf(net->last_error, sizeof(net->last_error) - 1, + format, args); + va_end(args); + memcpy(net->sqlstate, "HY000", sizeof(net->sqlstate)); +} + +/** + The main client function of the GSSAPI plugin. + */ +static int gssapi_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) +{ + int packet_len; + unsigned char *packet; + char spn[PRINCIPAL_NAME_MAX + 1]; + char mech[MECH_NAME_MAX + 1]; + + /* read from server for service principal name */ + packet_len= vio->read_packet(vio, &packet); + if (packet_len < 0) + { + return CR_ERROR; + } + parse_server_packet((char *)packet, (size_t)packet_len, spn, mech); + return auth_client(spn, mech, mysql, vio); +} + + +/* register client plugin */ +mysql_declare_client_plugin(AUTHENTICATION) + "auth_gssapi_client", + "Shuang Qiu, Robbie Harwood, Vladislav Vaintroub", + "GSSAPI/SSPI based authentication", + {0, 1, 0}, + "BSD", + NULL, + NULL, + NULL, + NULL, + gssapi_auth_client +mysql_end_client_plugin; diff --git a/plugin/auth_gssapi/cmake/FindGSSAPI.cmake b/plugin/auth_gssapi/cmake/FindGSSAPI.cmake new file mode 100644 index 00000000000..cc8e62d1ca7 --- /dev/null +++ b/plugin/auth_gssapi/cmake/FindGSSAPI.cmake @@ -0,0 +1,98 @@ +# - Try to detect the GSSAPI support +# Once done this will define +# +# GSSAPI_FOUND - system supports GSSAPI +# GSSAPI_INCS - the GSSAPI include directory +# GSSAPI_LIBS - the libraries needed to use GSSAPI +# GSSAPI_FLAVOR - the type of API - MIT or HEIMDAL + +# Copyright (c) 2006, Pino Toscano, <toscano.pino@tiscali.it> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +if(GSSAPI_LIBS AND GSSAPI_FLAVOR) + + # in cache already + set(GSSAPI_FOUND TRUE) + +else(GSSAPI_LIBS AND GSSAPI_FLAVOR) + + find_program(KRB5_CONFIG NAMES krb5-config heimdal-krb5-config PATHS + /opt/local/bin + ONLY_CMAKE_FIND_ROOT_PATH # this is required when cross compiling with cmake 2.6 and ignored with cmake 2.4, Alex + ) + mark_as_advanced(KRB5_CONFIG) + + #reset vars + set(GSSAPI_INCS) + set(GSSAPI_LIBS) + set(GSSAPI_FLAVOR) + + if(KRB5_CONFIG) + + set(HAVE_KRB5_GSSAPI TRUE) + exec_program(${KRB5_CONFIG} ARGS --libs gssapi RETURN_VALUE _return_VALUE OUTPUT_VARIABLE GSSAPI_LIBS) + if(_return_VALUE) + message(STATUS "GSSAPI configure check failed.") + set(HAVE_KRB5_GSSAPI FALSE) + endif(_return_VALUE) + + exec_program(${KRB5_CONFIG} ARGS --cflags gssapi RETURN_VALUE _return_VALUE OUTPUT_VARIABLE GSSAPI_INCS) + string(REGEX REPLACE "(\r?\n)+$" "" GSSAPI_INCS "${GSSAPI_INCS}") + string(REGEX REPLACE " *-I" ";" GSSAPI_INCS "${GSSAPI_INCS}") + + exec_program(${KRB5_CONFIG} ARGS --vendor RETURN_VALUE _return_VALUE OUTPUT_VARIABLE gssapi_flavor_tmp) + set(GSSAPI_FLAVOR_MIT) + if(gssapi_flavor_tmp MATCHES ".*Massachusetts.*") + set(GSSAPI_FLAVOR "MIT") + else(gssapi_flavor_tmp MATCHES ".*Massachusetts.*") + set(GSSAPI_FLAVOR "HEIMDAL") + endif(gssapi_flavor_tmp MATCHES ".*Massachusetts.*") + + if(NOT HAVE_KRB5_GSSAPI) + if (gssapi_flavor_tmp MATCHES "Sun Microsystems.*") + message(STATUS "Solaris Kerberos does not have GSSAPI; this is normal.") + set(GSSAPI_LIBS) + set(GSSAPI_INCS) + else(gssapi_flavor_tmp MATCHES "Sun Microsystems.*") + message(WARNING "${KRB5_CONFIG} failed unexpectedly.") + endif(gssapi_flavor_tmp MATCHES "Sun Microsystems.*") + endif(NOT HAVE_KRB5_GSSAPI) + + if(GSSAPI_LIBS) # GSSAPI_INCS can be also empty, so don't rely on that + set(GSSAPI_FOUND TRUE CACHE STRING "") + message(STATUS "Found GSSAPI: ${GSSAPI_LIBS}") + + set(GSSAPI_INCS ${GSSAPI_INCS} CACHE STRING "") + set(GSSAPI_LIBS ${GSSAPI_LIBS} CACHE STRING "") + set(GSSAPI_FLAVOR ${GSSAPI_FLAVOR} CACHE STRING "") + + mark_as_advanced(GSSAPI_INCS GSSAPI_LIBS GSSAPI_FLAVOR) + + endif(GSSAPI_LIBS) + + endif(KRB5_CONFIG) + +endif(GSSAPI_LIBS AND GSSAPI_FLAVOR) diff --git a/plugin/auth_gssapi/common.h b/plugin/auth_gssapi/common.h new file mode 100644 index 00000000000..c04241acff9 --- /dev/null +++ b/plugin/auth_gssapi/common.h @@ -0,0 +1,4 @@ +/** Maximal length of the target name */ +#define PRINCIPAL_NAME_MAX 256 +/** Maximal length of the mech string */ +#define MECH_NAME_MAX 30 diff --git a/plugin/auth_gssapi/gssapi_client.cc b/plugin/auth_gssapi/gssapi_client.cc new file mode 100644 index 00000000000..a05ea158e4d --- /dev/null +++ b/plugin/auth_gssapi/gssapi_client.cc @@ -0,0 +1,127 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <gssapi/gssapi.h> +#include <string.h> +#include <stdio.h> +#include <mysql/plugin_auth.h> +#include <mysqld_error.h> +#include <mysql.h> +#include "gssapi_errmsg.h" + +extern void log_client_error(MYSQL *mysql,const char *fmt,...); + + +/* This sends the error to the client */ +static void log_error(MYSQL *mysql, OM_uint32 major, OM_uint32 minor, const char *msg) +{ + if (GSS_ERROR(major)) + { + char sysmsg[1024]; + gssapi_errmsg(major, minor, sysmsg, sizeof(sysmsg)); + log_client_error(mysql, + "Client GSSAPI error (major %u, minor %u) : %s - %s", + major, minor, msg, sysmsg); + } + else + { + log_client_error(mysql, "Client GSSAPI error : %s", msg); + } +} + +int auth_client(char *principal_name, char *mech, MYSQL *mysql, MYSQL_PLUGIN_VIO *vio) +{ + + int ret= CR_ERROR; + OM_uint32 major= 0, minor= 0; + gss_ctx_id_t ctxt= GSS_C_NO_CONTEXT; + gss_name_t service_name= GSS_C_NO_NAME; + + if (principal_name && principal_name[0]) + { + /* import principal from plain text */ + gss_buffer_desc principal_name_buf; + principal_name_buf.length= strlen(principal_name); + principal_name_buf.value= (void *) principal_name; + major= gss_import_name(&minor, &principal_name_buf, GSS_C_NT_USER_NAME, &service_name); + if (GSS_ERROR(major)) + { + log_error(mysql, major, minor, "gss_import_name"); + return CR_ERROR; + } + } + + gss_buffer_desc input= {0,0}; + do + { + gss_buffer_desc output= {0,0}; + major= gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ctxt, service_name, + GSS_C_NO_OID, 0, 0, GSS_C_NO_CHANNEL_BINDINGS, + &input, NULL, &output, NULL, NULL); + if (output.length) + { + /* send credential */ + if(vio->write_packet(vio, (unsigned char *)output.value, output.length)) + { + /* Server error packet contains detailed message. */ + ret= CR_OK_HANDSHAKE_COMPLETE; + gss_release_buffer (&minor, &output); + goto cleanup; + } + } + gss_release_buffer (&minor, &output); + + if (GSS_ERROR(major)) + { + log_error(mysql, major, minor,"gss_init_sec_context"); + goto cleanup; + } + + if (major & GSS_S_CONTINUE_NEEDED) + { + int len= vio->read_packet(vio, (unsigned char **) &input.value); + if (len <= 0) + { + /* Server error packet contains detailed message. */ + ret= CR_OK_HANDSHAKE_COMPLETE; + goto cleanup; + } + input.length= len; + } + } while (major & GSS_S_CONTINUE_NEEDED); + + ret= CR_OK; + +cleanup: + if (service_name != GSS_C_NO_NAME) + gss_release_name(&minor, &service_name); + if (ctxt != GSS_C_NO_CONTEXT) + gss_delete_sec_context(&minor, &ctxt, GSS_C_NO_BUFFER); + + return ret; +} diff --git a/plugin/auth_gssapi/gssapi_errmsg.cc b/plugin/auth_gssapi/gssapi_errmsg.cc new file mode 100644 index 00000000000..8ea4cab5b02 --- /dev/null +++ b/plugin/auth_gssapi/gssapi_errmsg.cc @@ -0,0 +1,75 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <gssapi.h> +#include <string.h> +void gssapi_errmsg(OM_uint32 major, OM_uint32 minor, char *buf, size_t size) +{ + OM_uint32 message_context; + OM_uint32 status_code; + OM_uint32 maj_status; + OM_uint32 min_status; + gss_buffer_desc status_string; + char *p= buf; + char *end= buf + size - 1; + int types[] = {GSS_C_GSS_CODE,GSS_C_MECH_CODE}; + + for(int i= 0; i < 2;i++) + { + message_context= 0; + status_code= types[i] == GSS_C_GSS_CODE?major:minor; + + if(!status_code) + continue; + do + { + maj_status = gss_display_status( + &min_status, + status_code, + types[i], + GSS_C_NO_OID, + &message_context, + &status_string); + + if(maj_status) + break; + + if(p + status_string.length + 2 < end) + { + memcpy(p,status_string.value, status_string.length); + p += status_string.length; + *p++ = '.'; + *p++ = ' '; + } + + gss_release_buffer(&min_status, &status_string); + } + while (message_context != 0); + } + *p= 0; +} diff --git a/plugin/auth_gssapi/gssapi_errmsg.h b/plugin/auth_gssapi/gssapi_errmsg.h new file mode 100644 index 00000000000..26db8439e04 --- /dev/null +++ b/plugin/auth_gssapi/gssapi_errmsg.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +extern void gssapi_errmsg(OM_uint32 major, OM_uint32 minor, char *buf, size_t size); diff --git a/plugin/auth_gssapi/gssapi_server.cc b/plugin/auth_gssapi/gssapi_server.cc new file mode 100644 index 00000000000..ac75a4f1593 --- /dev/null +++ b/plugin/auth_gssapi/gssapi_server.cc @@ -0,0 +1,250 @@ +#include <my_config.h> +#include <gssapi/gssapi.h> +#include <stdio.h> +#include <mysql/plugin_auth.h> +#include <my_sys.h> +#include <mysqld_error.h> +#include <log.h> +#include "server_plugin.h" +#include "gssapi_errmsg.h" + +static gss_name_t service_name = GSS_C_NO_NAME; + +/* This sends the error to the client */ +static void log_error( OM_uint32 major, OM_uint32 minor, const char *msg) +{ + if (GSS_ERROR(major)) + { + char sysmsg[1024]; + gssapi_errmsg(major, minor, sysmsg, sizeof(sysmsg)); + my_printf_error(ER_UNKNOWN_ERROR,"Server GSSAPI error (major %u, minor %u) : %s -%s", + MYF(0), major, minor, msg, sysmsg); + } + else + { + my_printf_error(ER_UNKNOWN_ERROR, "Server GSSAPI error : %s", MYF(0), msg); + } +} + + +/* + Generate default principal service name formatted as principal name "mariadb/server.fqdn@REALM" +*/ +#include <krb5.h> +#ifndef HAVE_KRB5_FREE_UNPARSED_NAME +#define krb5_free_unparsed_name(a,b) krb5_xfree(b) +#endif +static char* get_default_principal_name() +{ + static char default_name[1024]; + char *unparsed_name= NULL; + krb5_context context= NULL; + krb5_principal principal= NULL; + krb5_keyblock *key= NULL; + + if(krb5_init_context(&context)) + { + sql_print_warning("GSSAPI plugin : krb5_init_context failed"); + goto cleanup; + } + + if (krb5_sname_to_principal(context, NULL, "mariadb", KRB5_NT_SRV_HST, &principal)) + { + sql_print_warning("GSSAPI plugin : krb5_sname_to_principal failed"); + goto cleanup; + } + + if (krb5_unparse_name(context, principal, &unparsed_name)) + { + sql_print_warning("GSSAPI plugin : krb5_unparse_name failed"); + goto cleanup; + } + + /* Check for entry in keytab */ + if (krb5_kt_read_service_key(context, NULL, principal, 0, (krb5_enctype)0, &key)) + { + sql_print_warning("GSSAPI plugin : default principal '%s' not found in keytab", unparsed_name); + goto cleanup; + } + + strncpy(default_name, unparsed_name, sizeof(default_name)-1); + +cleanup: + if (key) + krb5_free_keyblock(context, key); + if (unparsed_name) + krb5_free_unparsed_name(context, unparsed_name); + if (principal) + krb5_free_principal(context, principal); + if (context) + krb5_free_context(context); + + return default_name; +} + + +int plugin_init() +{ + gss_buffer_desc principal_name_buf; + OM_uint32 major= 0, minor= 0; + gss_cred_id_t cred= GSS_C_NO_CREDENTIAL; + + if(srv_keytab_path && srv_keytab_path[0]) + { + setenv("KRB5_KTNAME", srv_keytab_path, 1); + } + + if(!srv_principal_name || !srv_principal_name[0]) + srv_principal_name= get_default_principal_name(); + + /* import service principal from plain text */ + if(srv_principal_name && srv_principal_name[0]) + { + sql_print_information("GSSAPI plugin : using principal name '%s'", srv_principal_name); + principal_name_buf.length= strlen(srv_principal_name); + principal_name_buf.value= srv_principal_name; + major= gss_import_name(&minor, &principal_name_buf, GSS_C_NT_USER_NAME, &service_name); + if(GSS_ERROR(major)) + { + log_error(major, minor, "gss_import_name"); + return -1; + } + } + else + { + service_name= GSS_C_NO_NAME; + } + + + + /* Check if SPN configuration is OK */ + major= gss_acquire_cred(&minor, service_name, GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, GSS_C_ACCEPT, &cred, NULL, + NULL); + + if (GSS_ERROR(major)) + { + log_error(major, minor, "gss_acquire_cred failed"); + return -1; + } + gss_release_cred(&minor, &cred); + + return 0; +} + +int plugin_deinit() +{ + if (service_name != GSS_C_NO_NAME) + { + OM_uint32 minor; + gss_release_name(&minor, &service_name); + } + return 0; +} + + +int auth_server(MYSQL_PLUGIN_VIO *vio,const char *user, size_t userlen, int use_full_name) +{ + + int rc= CR_ERROR; /* return code */ + + /* GSSAPI related fields */ + OM_uint32 major= 0, minor= 0, flags= 0; + gss_cred_id_t cred= GSS_C_NO_CREDENTIAL; /* credential identifier */ + gss_ctx_id_t ctxt= GSS_C_NO_CONTEXT; /* context identifier */ + gss_name_t client_name; + gss_buffer_desc client_name_buf, input, output; + char *client_name_str; + + /* server acquires credential */ + major= gss_acquire_cred(&minor, service_name, GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, GSS_C_ACCEPT, &cred, NULL, + NULL); + + if (GSS_ERROR(major)) + { + log_error(major, minor, "gss_acquire_cred failed"); + goto cleanup; + } + + input.length= 0; + input.value= NULL; + do + { + /* receive token from peer */ + int len= vio->read_packet(vio, (unsigned char **) &input.value); + if (len < 0) + { + log_error(0, 0, "fail to read token from client"); + goto cleanup; + } + + input.length= len; + major= gss_accept_sec_context(&minor, &ctxt, cred, &input, + GSS_C_NO_CHANNEL_BINDINGS, &client_name, + NULL, &output, &flags, NULL, NULL); + if (GSS_ERROR(major)) + { + + log_error(major, minor, "gss_accept_sec_context"); + rc= CR_ERROR; + goto cleanup; + } + + /* send token to peer */ + if (output.length) + { + if (vio->write_packet(vio, (const uchar *) output.value, output.length)) + { + gss_release_buffer(&minor, &output); + log_error(major, minor, "communication error(write)"); + goto cleanup; + } + gss_release_buffer(&minor, &output); + } + } while (major & GSS_S_CONTINUE_NEEDED); + + /* extract plain text client name */ + major= gss_display_name(&minor, client_name, &client_name_buf, NULL); + if (GSS_ERROR(major)) + { + log_error(major, minor, "gss_display_name"); + goto cleanup; + } + + client_name_str= (char *)client_name_buf.value; + + /* + * Compare input user name with the actual one. Return success if + * the names match exactly, or if use_full_name parameter is not set + * up to the '@' separator. + */ + if ((userlen == client_name_buf.length) || + (!use_full_name + && userlen < client_name_buf.length + && client_name_str[userlen] == '@')) + { + if (strncmp(client_name_str, user, userlen) == 0) + { + rc= CR_OK; + } + } + + if(rc != CR_OK) + { + my_printf_error(ER_ACCESS_DENIED_ERROR, + "GSSAPI name mismatch, requested '%s', actual name '%.*s'", + MYF(0), user, (int)client_name_buf.length, client_name_str); + } + + gss_release_buffer(&minor, &client_name_buf); + + +cleanup: + if (ctxt != GSS_C_NO_CONTEXT) + gss_delete_sec_context(&minor, &ctxt, GSS_C_NO_BUFFER); + if (cred != GSS_C_NO_CREDENTIAL) + gss_release_cred(&minor, &cred); + + return(rc); +} diff --git a/plugin/auth_gssapi/mysql-test/auth_gssapi/basic.result b/plugin/auth_gssapi/mysql-test/auth_gssapi/basic.result new file mode 100644 index 00000000000..dc5155fac8c --- /dev/null +++ b/plugin/auth_gssapi/mysql-test/auth_gssapi/basic.result @@ -0,0 +1,18 @@ +INSTALL SONAME 'auth_gssapi'; +CREATE USER 'GSSAPI_SHORTNAME' IDENTIFIED WITH gssapi; +SELECT USER(),CURRENT_USER(); +USER() CURRENT_USER() +GSSAPI_SHORTNAME@localhost GSSAPI_SHORTNAME@% +DROP USER 'GSSAPI_SHORTNAME'; +CREATE USER nosuchuser IDENTIFIED WITH gssapi; +ERROR 28000: GSSAPI name mismatch, requested 'nosuchuser', actual name 'GSSAPI_SHORTNAME' +DROP USER nosuchuser; +CREATE USER usr1 IDENTIFIED WITH gssapi as 'GSSAPI_FULLNAME'; +SELECT USER(),CURRENT_USER(); +USER() CURRENT_USER() +usr1@localhost usr1@% +DROP USER usr1; +CREATE USER nosuchuser IDENTIFIED WITH gssapi AS 'nosuchuser@EXAMPLE.COM'; +ERROR 28000: GSSAPI name mismatch, requested 'nosuchuser@EXAMPLE.COM', actual name 'GSSAPI_FULLNAME' +DROP USER nosuchuser; +UNINSTALL SONAME 'auth_gssapi'; diff --git a/plugin/auth_gssapi/mysql-test/auth_gssapi/basic.test b/plugin/auth_gssapi/mysql-test/auth_gssapi/basic.test new file mode 100644 index 00000000000..f47ad8c20e2 --- /dev/null +++ b/plugin/auth_gssapi/mysql-test/auth_gssapi/basic.test @@ -0,0 +1,45 @@ +INSTALL SONAME 'auth_gssapi'; + +# +# CREATE USER without 'AS' clause +# +--replace_result $GSSAPI_SHORTNAME GSSAPI_SHORTNAME +eval CREATE USER '$GSSAPI_SHORTNAME' IDENTIFIED WITH gssapi; +connect (con1,localhost,$GSSAPI_SHORTNAME,,); +--replace_result $GSSAPI_SHORTNAME GSSAPI_SHORTNAME +SELECT USER(),CURRENT_USER(); +disconnect con1; + +connection default; +--replace_result $GSSAPI_SHORTNAME GSSAPI_SHORTNAME +eval DROP USER '$GSSAPI_SHORTNAME'; + +CREATE USER nosuchuser IDENTIFIED WITH gssapi; +--disable_query_log +--replace_regex /actual name '.*'/actual name 'GSSAPI_SHORTNAME'/ +--error ER_ACCESS_DENIED_ERROR +connect (con1,localhost,nosuchuser,,); +--enable_query_log +DROP USER nosuchuser; + +# +# CREATE USER with 'AS' clause +# +--replace_result $GSSAPI_FULLNAME GSSAPI_FULLNAME +eval CREATE USER usr1 IDENTIFIED WITH gssapi as '$GSSAPI_FULLNAME'; +connect (con1,localhost,usr1,,); +--replace_result $GSSAPI_FULLNAME GSSAPI_FULLNAME +SELECT USER(),CURRENT_USER(); +disconnect con1; +connection default; +DROP USER usr1; + +CREATE USER nosuchuser IDENTIFIED WITH gssapi AS 'nosuchuser@EXAMPLE.COM'; +--disable_query_log +--replace_regex /actual name '.*'/actual name 'GSSAPI_FULLNAME'/ +--error ER_ACCESS_DENIED_ERROR +connect (con1,localhost,nosuchuser,,); +--enable_query_log +DROP USER nosuchuser; + +UNINSTALL SONAME 'auth_gssapi';
\ No newline at end of file diff --git a/plugin/auth_gssapi/mysql-test/auth_gssapi/suite.opt b/plugin/auth_gssapi/mysql-test/auth_gssapi/suite.opt new file mode 100644 index 00000000000..3077d70c9c3 --- /dev/null +++ b/plugin/auth_gssapi/mysql-test/auth_gssapi/suite.opt @@ -0,0 +1 @@ +--loose-gssapi-keytab-path=$GSSAPI_KEYTAB_PATH --loose-gssapi-principal-name=$GSSAPI_PRINCIPAL_NAME diff --git a/plugin/auth_gssapi/mysql-test/auth_gssapi/suite.pm b/plugin/auth_gssapi/mysql-test/auth_gssapi/suite.pm new file mode 100644 index 00000000000..aa225536a1e --- /dev/null +++ b/plugin/auth_gssapi/mysql-test/auth_gssapi/suite.pm @@ -0,0 +1,49 @@ +package My::Suite::AuthGSSAPI; + +@ISA = qw(My::Suite); + +return "No AUTH_GSSAPI plugin" unless $ENV{AUTH_GSSAPI_SO}; + +return "Not run for embedded server" if $::opt_embedded_server; + +# Following environment variables may need to be set +if ($^O eq "MSWin32") +{ + chomp(my $whoami =`whoami /UPN 2>NUL` || `whoami`); + my $fullname = $whoami; + $fullname =~ s/\\/\\\\/; # SQL escaping for backslash + $ENV{'GSSAPI_FULLNAME'} = $fullname; + $ENV{'GSSAPI_SHORTNAME'} = $ENV{'USERNAME'}; +} +else +{ + if (!$ENV{'GSSAPI_FULLNAME'}) + { + my $s = `klist 2>/dev/null |grep 'Default principal: '`; + if ($s) + { + chomp($s); + my $fullname = substr($s,19); + $ENV{'GSSAPI_FULLNAME'} = $fullname; + } + } + $ENV{'GSSAPI_SHORTNAME'} = (split /@/, $ENV{'GSSAPI_FULLNAME'}) [0]; +} + + +if (!$ENV{'GSSAPI_FULLNAME'} || !$ENV{'GSSAPI_SHORTNAME'}) +{ + return "Environment variable GSSAPI_SHORTNAME and GSSAPI_FULLNAME need to be set" +} + +if ($::opt_verbose) +{ + foreach $var ('GSSAPI_SHORTNAME','GSSAPI_FULLNAME','GSSAPI_KEYTAB_PATH','GSSAPI_PRINCIPAL_NAME') + { + print "$var=$ENV{$var}\n"; + } +} +sub is_default { 1 } + +bless { }; + diff --git a/plugin/auth_gssapi/server_plugin.cc b/plugin/auth_gssapi/server_plugin.cc new file mode 100644 index 00000000000..a79074abe79 --- /dev/null +++ b/plugin/auth_gssapi/server_plugin.cc @@ -0,0 +1,183 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, + Vladislav Vaintroub & MariaDB Corporation + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + @file + + GSSAPI authentication plugin, server side +*/ +#include <my_sys.h> +#include <mysqld_error.h> +#include <mysql/plugin_auth.h> +#include "server_plugin.h" +#include "common.h" + +/* First packet sent from server to client, contains srv_principal_name\0mech\0 */ +static char first_packet[PRINCIPAL_NAME_MAX + MECH_NAME_MAX +2]; +static int first_packet_len; + +/* + Target name in GSSAPI/SSPI , for Kerberos it is service principal name + (often user principal name of the server user will work) +*/ +char *srv_principal_name; +char *srv_keytab_path; +char *srv_mech_name=(char *)""; +unsigned long srv_mech; + +/** + The main server function of the GSSAPI plugin. + */ +static int gssapi_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *auth_info) +{ + int use_full_name; + const char *user; + int user_len; + + /* No user name yet ? Read the client handshake packet with the user name. */ + if (auth_info->user_name == 0) + { + unsigned char *pkt; + if (vio->read_packet(vio, &pkt) < 0) + return CR_ERROR; + } + + /* Send first packet with target name and mech name */ + if (vio->write_packet(vio, (unsigned char *)first_packet, first_packet_len)) + { + return CR_ERROR; + } + + /* Figure out whether to use full name (as given in IDENTIFIED AS clause) + * or just short username auth_string + */ + if (auth_info->auth_string_length > 0) + { + use_full_name= 1; + user= auth_info->auth_string; + user_len= auth_info->auth_string_length; + } + else + { + use_full_name= 0; + user= auth_info->user_name; + user_len= auth_info->user_name_length; + } + + return auth_server(vio, user, user_len, use_full_name); +} + +static int initialize_plugin(void *unused) +{ + int rc; + rc = plugin_init(); + if (rc) + return rc; + + strcpy(first_packet, srv_principal_name); + strcpy(first_packet + strlen(srv_principal_name) + 1,srv_mech_name); + first_packet_len = strlen(srv_principal_name) + strlen(srv_mech_name) + 2; + + return 0; +} + +static int deinitialize_plugin(void *unused) +{ + return plugin_deinit(); +} + +/* system variable */ +static MYSQL_SYSVAR_STR(keytab_path, srv_keytab_path, + PLUGIN_VAR_RQCMDARG|PLUGIN_VAR_READONLY, + "Keytab file path for Kerberos authentication", + NULL, + NULL, + ""); +static MYSQL_SYSVAR_STR(principal_name, srv_principal_name, + PLUGIN_VAR_RQCMDARG|PLUGIN_VAR_READONLY, + "GSSAPI target name - service principal name for Kerberos authentication.", + NULL, + NULL, + ""); +#ifdef PLUGIN_SSPI +static const char* mech_names[] = { + "Kerberos", + "Negotiate", + "", + NULL +}; +static TYPELIB mech_name_typelib = { + array_elements(mech_names) - 1, + "mech_name_typelib", + mech_names, + NULL +}; +static MYSQL_SYSVAR_ENUM(mech_name, srv_mech, + PLUGIN_VAR_RQCMDARG|PLUGIN_VAR_READONLY, + "GSSAPI mechanism", + NULL, + NULL, + 2,&mech_name_typelib); +#endif + +static struct st_mysql_sys_var *system_variables[]= { + MYSQL_SYSVAR(principal_name), +#ifdef PLUGIN_SSPI + MYSQL_SYSVAR(mech_name), +#endif +#ifdef PLUGIN_GSSAPI + MYSQL_SYSVAR(keytab_path), +#endif + NULL +}; + +/* Register authentication plugin */ +static struct st_mysql_auth server_handler= { + MYSQL_AUTHENTICATION_INTERFACE_VERSION, + "auth_gssapi_client", + gssapi_auth +}; + +maria_declare_plugin(gssapi_server) +{ + MYSQL_AUTHENTICATION_PLUGIN, + &server_handler, + "gssapi", + "Shuang Qiu, Robbie Harwood, Vladislav Vaintroub", + "Plugin for GSSAPI/SSPI based authentication.", + PLUGIN_LICENSE_BSD, + initialize_plugin, + deinitialize_plugin, /* destructor */ + 0x0100, /* version */ + NULL, /* status variables */ + system_variables, /* system variables */ + "1.0", + MariaDB_PLUGIN_MATURITY_BETA +} +maria_declare_plugin_end; + diff --git a/plugin/auth_gssapi/server_plugin.h b/plugin/auth_gssapi/server_plugin.h new file mode 100644 index 00000000000..1348835e653 --- /dev/null +++ b/plugin/auth_gssapi/server_plugin.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Plugin variables*/ +#include <mysql/plugin_auth.h> +typedef enum +{ + PLUGIN_MECH_KERBEROS = 0, + PLUGIN_MECH_SPNEGO = 1, + PLUGIN_MECH_DEFAULT = 2 +}PLUGIN_MECH; + +extern unsigned long srv_mech; +extern char *srv_principal_name; +extern char *srv_mech_name; +extern char *srv_keytab_path; +/* + Check, with GSSAPI/SSPI username of logged on user. + + Depending on use_full_name parameter, compare either full name + (principal name like user@real), or local name (first component) +*/ +int plugin_init(); +int plugin_deinit(); + +int auth_server(MYSQL_PLUGIN_VIO *vio, const char *username, size_t username_len, int use_full_name); diff --git a/plugin/auth_gssapi/sspi.h b/plugin/auth_gssapi/sspi.h new file mode 100644 index 00000000000..34b8a56a32e --- /dev/null +++ b/plugin/auth_gssapi/sspi.h @@ -0,0 +1,38 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#define SECURITY_WIN32 +#include <windows.h> +#include <sspi.h> +#include <SecExt.h> +#include <stdarg.h> +#include <stdio.h> + +#define SSPI_MAX_TOKEN_SIZE 50000 +#define SEC_ERROR(err) (err < 0) +extern void sspi_errmsg(int err, char *buf, size_t size);
\ No newline at end of file diff --git a/plugin/auth_gssapi/sspi_client.cc b/plugin/auth_gssapi/sspi_client.cc new file mode 100644 index 00000000000..34c1ce2e7ee --- /dev/null +++ b/plugin/auth_gssapi/sspi_client.cc @@ -0,0 +1,183 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#define SECURITY_WIN32 +#include <windows.h> +#include <sspi.h> +#include <SecExt.h> +#include <stdarg.h> +#include <stdio.h> + +#include <mysql/plugin_auth.h> +#include <mysql.h> +#include <mysqld_error.h> + +#include "sspi.h" + +extern void log_client_error(MYSQL *mysql, const char *fmt, ...); +static void log_error(MYSQL *mysql, SECURITY_STATUS err, const char *msg) +{ + if (err) + { + char buf[1024]; + sspi_errmsg(err, buf, sizeof(buf)); + log_client_error(mysql, "SSPI client error 0x%x - %s - %s", err, msg, buf); + } + else + { + log_client_error(mysql, "SSPI client error %s", msg); + } +} + + +/** Client side authentication*/ +int auth_client(char *principal_name, char *mech, MYSQL *mysql, MYSQL_PLUGIN_VIO *vio) +{ + + int ret; + CredHandle cred; + CtxtHandle ctxt; + ULONG attribs = 0; + TimeStamp lifetime; + SECURITY_STATUS sspi_err; + + SecBufferDesc inbuf_desc; + SecBuffer inbuf; + SecBufferDesc outbuf_desc; + SecBuffer outbuf; + PBYTE out = NULL; + + ret= CR_ERROR; + SecInvalidateHandle(&ctxt); + SecInvalidateHandle(&cred); + + if (!mech || strcmp(mech, "Negotiate") != 0) + { + mech= "Kerberos"; + } + + sspi_err = AcquireCredentialsHandle( + NULL, + mech, + SECPKG_CRED_OUTBOUND, + NULL, + NULL, + NULL, + NULL, + &cred, + &lifetime); + + if (SEC_ERROR(sspi_err)) + { + log_error(mysql, sspi_err, "AcquireCredentialsHandle"); + return CR_ERROR; + } + + out = (PBYTE)malloc(SSPI_MAX_TOKEN_SIZE); + if (!out) + { + log_error(mysql, SEC_E_OK, "memory allocation error"); + goto cleanup; + } + + /* Prepare buffers */ + inbuf_desc.ulVersion = SECBUFFER_VERSION; + inbuf_desc.cBuffers = 1; + inbuf_desc.pBuffers = &inbuf; + inbuf.BufferType = SECBUFFER_TOKEN; + inbuf.cbBuffer = 0; + inbuf.pvBuffer = NULL; + + outbuf_desc.ulVersion = SECBUFFER_VERSION; + outbuf_desc.cBuffers = 1; + outbuf_desc.pBuffers = &outbuf; + outbuf.BufferType = SECBUFFER_TOKEN; + outbuf.pvBuffer = out; + + do + { + outbuf.cbBuffer= SSPI_MAX_TOKEN_SIZE; + sspi_err= InitializeSecurityContext( + &cred, + SecIsValidHandle(&ctxt) ? &ctxt : NULL, + principal_name, + 0, + 0, + SECURITY_NATIVE_DREP, + inbuf.cbBuffer ? &inbuf_desc : NULL, + 0, + &ctxt, + &outbuf_desc, + &attribs, + &lifetime); + if (SEC_ERROR(sspi_err)) + { + log_error(mysql, sspi_err, "InitializeSecurityContext"); + goto cleanup; + } + if (sspi_err != SEC_E_OK && sspi_err != SEC_I_CONTINUE_NEEDED) + { + log_error(mysql, sspi_err, "Unexpected response from InitializeSecurityContext"); + goto cleanup; + } + + if (outbuf.cbBuffer) + { + /* send credential to server */ + if (vio->write_packet(vio, (unsigned char *)outbuf.pvBuffer, outbuf.cbBuffer)) + { + /* Server error packet contains detailed message. */ + ret= CR_OK_HANDSHAKE_COMPLETE; + goto cleanup; + } + } + + if (sspi_err == SEC_I_CONTINUE_NEEDED) + { + int len= vio->read_packet(vio, (unsigned char **)&inbuf.pvBuffer); + if (len <= 0) + { + /* Server side error is in the last server packet. */ + ret= CR_OK_HANDSHAKE_COMPLETE; + goto cleanup; + } + inbuf.cbBuffer= len; + } + } while (sspi_err == SEC_I_CONTINUE_NEEDED); + + ret= CR_OK; + +cleanup: + + if (SecIsValidHandle(&ctxt)) + DeleteSecurityContext(&ctxt); + if (SecIsValidHandle(&cred)) + FreeCredentialsHandle(&cred); + free(out); + return ret; +}
\ No newline at end of file diff --git a/plugin/auth_gssapi/sspi_errmsg.cc b/plugin/auth_gssapi/sspi_errmsg.cc new file mode 100644 index 00000000000..961ef51f42e --- /dev/null +++ b/plugin/auth_gssapi/sspi_errmsg.cc @@ -0,0 +1,150 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <windows.h> +#include <stdio.h> + +#define ERRSYM(x) {x, #x} +static struct { + int error; + const char *sym; +} error_symbols[] = +{ + ERRSYM(SEC_E_OK), + ERRSYM(SEC_E_INSUFFICIENT_MEMORY), + ERRSYM(SEC_E_INVALID_HANDLE), + ERRSYM(SEC_E_UNSUPPORTED_FUNCTION), + ERRSYM(SEC_E_TARGET_UNKNOWN), + ERRSYM(SEC_E_INTERNAL_ERROR), + ERRSYM(SEC_E_SECPKG_NOT_FOUND), + ERRSYM(SEC_E_NOT_OWNER), + ERRSYM(SEC_E_CANNOT_INSTALL), + ERRSYM(SEC_E_INVALID_TOKEN), + ERRSYM(SEC_E_CANNOT_PACK), + ERRSYM(SEC_E_QOP_NOT_SUPPORTED), + ERRSYM(SEC_E_NO_IMPERSONATION), + ERRSYM(SEC_E_LOGON_DENIED), + ERRSYM(SEC_E_UNKNOWN_CREDENTIALS), + ERRSYM(SEC_E_NO_CREDENTIALS), + ERRSYM(SEC_E_MESSAGE_ALTERED), + ERRSYM(SEC_E_OUT_OF_SEQUENCE), + ERRSYM(SEC_E_NO_AUTHENTICATING_AUTHORITY), + ERRSYM(SEC_E_BAD_PKGID), + ERRSYM(SEC_E_CONTEXT_EXPIRED), + ERRSYM(SEC_E_INCOMPLETE_MESSAGE), + ERRSYM(SEC_E_INCOMPLETE_CREDENTIALS), + ERRSYM(SEC_E_BUFFER_TOO_SMALL), + ERRSYM(SEC_E_WRONG_PRINCIPAL), + ERRSYM(SEC_E_TIME_SKEW), + ERRSYM(SEC_E_UNTRUSTED_ROOT), + ERRSYM(SEC_E_ILLEGAL_MESSAGE), + ERRSYM(SEC_E_CERT_UNKNOWN), + ERRSYM(SEC_E_CERT_EXPIRED), + ERRSYM(SEC_E_ENCRYPT_FAILURE), + ERRSYM(SEC_E_DECRYPT_FAILURE), + ERRSYM(SEC_E_ALGORITHM_MISMATCH), + ERRSYM(SEC_E_SECURITY_QOS_FAILED), + ERRSYM(SEC_E_UNFINISHED_CONTEXT_DELETED), + ERRSYM(SEC_E_NO_TGT_REPLY), + ERRSYM(SEC_E_NO_IP_ADDRESSES), + ERRSYM(SEC_E_WRONG_CREDENTIAL_HANDLE), + ERRSYM(SEC_E_CRYPTO_SYSTEM_INVALID), + ERRSYM(SEC_E_MAX_REFERRALS_EXCEEDED), + ERRSYM(SEC_E_MUST_BE_KDC), + ERRSYM(SEC_E_STRONG_CRYPTO_NOT_SUPPORTED), + ERRSYM(SEC_E_TOO_MANY_PRINCIPALS), + ERRSYM(SEC_E_NO_PA_DATA), + ERRSYM(SEC_E_PKINIT_NAME_MISMATCH), + ERRSYM(SEC_E_SMARTCARD_LOGON_REQUIRED), + ERRSYM(SEC_E_SHUTDOWN_IN_PROGRESS), + ERRSYM(SEC_E_KDC_INVALID_REQUEST), + ERRSYM(SEC_E_KDC_UNABLE_TO_REFER), + ERRSYM(SEC_E_KDC_UNKNOWN_ETYPE), + ERRSYM(SEC_E_UNSUPPORTED_PREAUTH), + ERRSYM(SEC_E_DELEGATION_REQUIRED), + ERRSYM(SEC_E_BAD_BINDINGS), + ERRSYM(SEC_E_MULTIPLE_ACCOUNTS), + ERRSYM(SEC_E_NO_KERB_KEY), + ERRSYM(SEC_E_CERT_WRONG_USAGE), + ERRSYM(SEC_E_DOWNGRADE_DETECTED), + ERRSYM(SEC_E_SMARTCARD_CERT_REVOKED), + ERRSYM(SEC_E_ISSUING_CA_UNTRUSTED), + ERRSYM(SEC_E_REVOCATION_OFFLINE_C), + ERRSYM(SEC_E_PKINIT_CLIENT_FAILURE), + ERRSYM(SEC_E_SMARTCARD_CERT_EXPIRED), + ERRSYM(SEC_E_NO_S4U_PROT_SUPPORT), + ERRSYM(SEC_E_CROSSREALM_DELEGATION_FAILURE), + ERRSYM(SEC_E_REVOCATION_OFFLINE_KDC), + ERRSYM(SEC_E_ISSUING_CA_UNTRUSTED_KDC), + ERRSYM(SEC_E_KDC_CERT_EXPIRED), + ERRSYM(SEC_E_KDC_CERT_REVOKED), + ERRSYM(SEC_E_INVALID_PARAMETER), + ERRSYM(SEC_E_DELEGATION_POLICY), + ERRSYM(SEC_E_POLICY_NLTM_ONLY), + ERRSYM(SEC_E_NO_CONTEXT), + ERRSYM(SEC_E_PKU2U_CERT_FAILURE), + ERRSYM(SEC_E_MUTUAL_AUTH_FAILED), + ERRSYM(SEC_E_NO_SPM), + ERRSYM(SEC_E_NOT_SUPPORTED), + {0,0} +}; + +void sspi_errmsg(int err, char *buf, size_t size) +{ + buf[size - 1] = 0; + size_t len; + + for (size_t i= 0; error_symbols[i].sym; i++) + { + if (error_symbols[i].error == err) + { + size_t len= strlen(error_symbols[i].sym); + if (len + 2 < size) + { + memcpy(buf, error_symbols[i].sym, len); + buf[len]= ' '; + buf += len + 1; + size-= len + 1; + } + break; + } + } + + len = FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, + err, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + buf, size, NULL); + + if(len > 0) + { + /* Trim trailing \n\r*/ + char *p; + for(p= buf + len;p > buf && (*p == '\n' || *p=='\r' || *p == 0);p--) + *p= 0; + } +} diff --git a/plugin/auth_gssapi/sspi_server.cc b/plugin/auth_gssapi/sspi_server.cc new file mode 100644 index 00000000000..1dfd2986aaa --- /dev/null +++ b/plugin/auth_gssapi/sspi_server.cc @@ -0,0 +1,312 @@ +/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood, +Vladislav Vaintroub & MariaDB Corporation + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "sspi.h" +#include "common.h" +#include "server_plugin.h" +#include <mysql/plugin_auth.h> +#include <my_sys.h> +#include <mysqld_error.h> +#include <log.h> + + +/* This sends the error to the client */ +static void log_error(SECURITY_STATUS err, const char *msg) +{ + if (err) + { + char buf[1024]; + sspi_errmsg(err, buf, sizeof(buf)); + my_printf_error(ER_UNKNOWN_ERROR, "SSPI server error 0x%x - %s - %s", MYF(0), msg, buf); + } + else + { + my_printf_error(ER_UNKNOWN_ERROR, "SSPI server error %s", MYF(0), msg); + } + +} + +static char INVALID_KERBEROS_PRINCIPAL[] = "localhost"; + +static char *get_default_principal_name() +{ + static char default_principal[PRINCIPAL_NAME_MAX +1]; + ULONG size= sizeof(default_principal); + + if (GetUserNameEx(NameUserPrincipal,default_principal,&size)) + return default_principal; + + size= sizeof(default_principal); + if (GetUserNameEx(NameServicePrincipal,default_principal,&size)) + return default_principal; + + char domain[PRINCIPAL_NAME_MAX+1]; + char host[PRINCIPAL_NAME_MAX+1]; + size= sizeof(domain); + if (GetComputerNameEx(ComputerNameDnsDomain,domain,&size) && size > 0) + { + size= sizeof(host); + if (GetComputerNameEx(ComputerNameDnsHostname,host,&size)) + { + _snprintf(default_principal,sizeof(default_principal),"%s$@%s",host, domain); + return default_principal; + } + } + /* Unable to retrieve useful name, return something */ + return INVALID_KERBEROS_PRINCIPAL; +} + + +/* Extract client name from SSPI context */ +static int get_client_name_from_context(CtxtHandle *ctxt, + char *name, + size_t name_len, + int use_full_name) +{ + SecPkgContext_NativeNames native_names; + SECURITY_STATUS sspi_ret; + char *p; + + sspi_ret= QueryContextAttributes(ctxt, SECPKG_ATTR_NATIVE_NAMES, &native_names); + if (sspi_ret == SEC_E_OK) + { + /* Extract user from Kerberos principal name user@realm */ + if(!use_full_name) + { + p = strrchr(native_names.sClientName,'@'); + if(p) + *p = 0; + } + strncpy(name, native_names.sClientName, name_len); + FreeContextBuffer(&native_names); + return CR_OK; + } + + sspi_ret= ImpersonateSecurityContext(ctxt); + if (sspi_ret == SEC_E_OK) + { + ULONG len= name_len; + if (!GetUserNameEx(NameSamCompatible, name, &len)) + { + log_error(GetLastError(), "GetUserNameEx"); + RevertSecurityContext(ctxt); + return CR_ERROR; + } + RevertSecurityContext(ctxt); + + /* Extract user from Windows name realm\user */ + if (!use_full_name) + { + p = strrchr(name, '\\'); + if (p) + { + p++; + memmove(name, p, name + len + 1 - p); + } + } + return CR_OK; + } + + log_error(sspi_ret, "ImpersonateSecurityContext"); + return CR_ERROR; +} + + +int auth_server(MYSQL_PLUGIN_VIO *vio, const char *user, size_t user_len, int compare_full_name) +{ + int ret; + SECURITY_STATUS sspi_ret; + ULONG attribs = 0; + TimeStamp lifetime; + CredHandle cred; + CtxtHandle ctxt; + + SecBufferDesc inbuf_desc; + SecBuffer inbuf; + SecBufferDesc outbuf_desc; + SecBuffer outbuf; + void* out= NULL; + char client_name[MYSQL_USERNAME_LENGTH + 1]; + + ret= CR_ERROR; + SecInvalidateHandle(&cred); + SecInvalidateHandle(&ctxt); + + out= malloc(SSPI_MAX_TOKEN_SIZE); + if (!out) + { + log_error(SEC_E_OK, "memory allocation failed"); + goto cleanup; + } + sspi_ret= AcquireCredentialsHandle( + srv_principal_name, + srv_mech_name, + SECPKG_CRED_INBOUND, + NULL, + NULL, + NULL, + NULL, + &cred, + &lifetime); + + if (SEC_ERROR(sspi_ret)) + { + log_error(sspi_ret, "AcquireCredentialsHandle failed"); + goto cleanup; + } + + inbuf.cbBuffer= 0; + inbuf.BufferType= SECBUFFER_TOKEN; + inbuf.pvBuffer= NULL; + inbuf_desc.ulVersion= SECBUFFER_VERSION; + inbuf_desc.cBuffers= 1; + inbuf_desc.pBuffers= &inbuf; + + outbuf.BufferType= SECBUFFER_TOKEN; + outbuf.cbBuffer= SSPI_MAX_TOKEN_SIZE; + outbuf.pvBuffer= out; + + outbuf_desc.ulVersion= SECBUFFER_VERSION; + outbuf_desc.cBuffers= 1; + outbuf_desc.pBuffers= &outbuf; + + do + { + /* Read SSPI blob from client. */ + int len= vio->read_packet(vio, (unsigned char **)&inbuf.pvBuffer); + if (len < 0) + { + log_error(SEC_E_OK, "communication error(read)"); + goto cleanup; + } + inbuf.cbBuffer= len; + outbuf.cbBuffer= SSPI_MAX_TOKEN_SIZE; + sspi_ret= AcceptSecurityContext( + &cred, + SecIsValidHandle(&ctxt) ? &ctxt : NULL, + &inbuf_desc, + attribs, + SECURITY_NATIVE_DREP, + &ctxt, + &outbuf_desc, + &attribs, + &lifetime); + + if (SEC_ERROR(sspi_ret)) + { + log_error(sspi_ret, "AcceptSecurityContext"); + goto cleanup; + } + if (sspi_ret != SEC_E_OK && sspi_ret != SEC_I_CONTINUE_NEEDED) + { + log_error(sspi_ret, "AcceptSecurityContext unexpected return value"); + goto cleanup; + } + if (outbuf.cbBuffer) + { + /* Send generated blob to client. */ + if (vio->write_packet(vio, (unsigned char *)outbuf.pvBuffer, outbuf.cbBuffer)) + { + log_error(SEC_E_OK, "communicaton error(write)"); + goto cleanup; + } + } + } while (sspi_ret == SEC_I_CONTINUE_NEEDED); + + /* Authentication done, now extract and compare user name. */ + ret= get_client_name_from_context(&ctxt, client_name, MYSQL_USERNAME_LENGTH, compare_full_name); + if (ret != CR_OK) + goto cleanup; + + /* Always compare case-insensitive on Windows. */ + ret= _stricmp(client_name, user) == 0 ? CR_OK : CR_ERROR; + if (ret != CR_OK) + { + my_printf_error(ER_ACCESS_DENIED_ERROR, + "GSSAPI name mismatch, requested '%s', actual name '%s'", + MYF(0), user, client_name); + } + +cleanup: + if (SecIsValidHandle(&ctxt)) + DeleteSecurityContext(&ctxt); + + if (SecIsValidHandle(&cred)) + FreeCredentialsHandle(&cred); + + free(out); + return ret; +} + +int plugin_init() +{ + CredHandle cred; + SECURITY_STATUS ret; + + /* + Use negotiate by default, which accepts raw kerberos + and also NTLM. + */ + if (srv_mech == PLUGIN_MECH_DEFAULT) + srv_mech= PLUGIN_MECH_SPNEGO; + + if(srv_mech == PLUGIN_MECH_KERBEROS) + srv_mech_name= "Kerberos"; + else if(srv_mech == PLUGIN_MECH_SPNEGO ) + srv_mech_name= "Negotiate"; + + if(!srv_principal_name[0]) + { + srv_principal_name= get_default_principal_name(); + } + sql_print_information("SSPI: using principal name '%s', mech '%s'", + srv_principal_name, srv_mech_name); + + ret = AcquireCredentialsHandle( + srv_principal_name, + srv_mech_name, + SECPKG_CRED_INBOUND, + NULL, + NULL, + NULL, + NULL, + &cred, + NULL); + if (SEC_ERROR(ret)) + { + log_error(ret, "AcquireCredentialsHandle"); + return -1; + } + FreeCredentialsHandle(&cred); + return 0; +} + +int plugin_deinit() +{ + return 0; +} diff --git a/plugin/auth_pam/mapper/pam_user_map.c b/plugin/auth_pam/mapper/pam_user_map.c index 1c4bccc7f27..fb149c5cc05 100644 --- a/plugin/auth_pam/mapper/pam_user_map.c +++ b/plugin/auth_pam/mapper/pam_user_map.c @@ -127,13 +127,13 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, s++; } from= s; - skip(isalnum(*s) || (*s == '_')); + skip(isalnum(*s) || (*s == '_') || (*s == '.') || (*s == '-') || (*s == '$')); end_from= s; skip(isspace(*s)); if (end_from == from || *s++ != ':') goto syntax_error; skip(isspace(*s)); to= s; - skip(isalnum(*s) || (*s == '_')); + skip(isalnum(*s) || (*s == '_') || (*s == '.') || (*s == '-') || (*s == '$')); end_to= s; if (end_to == to) goto syntax_error; diff --git a/plugin/auth_pipe/CMakeLists.txt b/plugin/auth_pipe/CMakeLists.txt new file mode 100644 index 00000000000..bbc44d0f5e2 --- /dev/null +++ b/plugin/auth_pipe/CMakeLists.txt @@ -0,0 +1,3 @@ +IF(WIN32) + MYSQL_ADD_PLUGIN(auth_named_pipe auth_pipe.c) +ENDIF() diff --git a/plugin/auth_pipe/auth_pipe.c b/plugin/auth_pipe/auth_pipe.c new file mode 100644 index 00000000000..20c33c07e84 --- /dev/null +++ b/plugin/auth_pipe/auth_pipe.c @@ -0,0 +1,94 @@ +/* Copyright (C) 2015 Vladislav Vaintroub, Georg Richter and Monty Program Ab + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; version 2 of the + License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/** + @file + + auth_pipe authentication plugin. + + Authentication is successful if the connection is done via a named pipe + pipe peer name matches mysql user name +*/ + +#include <mysql/plugin_auth.h> +#include <string.h> +#include <lmcons.h> + + +/** + This authentication callback obtains user name using named pipe impersonation +*/ +static int pipe_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) +{ + unsigned char *pkt; + MYSQL_PLUGIN_VIO_INFO vio_info; + char username[UNLEN + 1]; + size_t username_length; + int ret; + + /* no user name yet ? read the client handshake packet with the user name */ + if (info->user_name == 0) + { + if (vio->read_packet(vio, &pkt) < 0) + return CR_ERROR; + } + info->password_used= PASSWORD_USED_NO_MENTION; + vio->info(vio, &vio_info); + if (vio_info.protocol != MYSQL_VIO_PIPE) + return CR_ERROR; + + /* Impersonate the named pipe peer, and retrieve the user name */ + if (!ImpersonateNamedPipeClient(vio_info.handle)) + return CR_ERROR; + + username_length= sizeof(username) - 1; + ret= CR_ERROR; + if (GetUserName(username, &username_length)) + { + /* Always compare names case-insensitive on Windows.*/ + if (_stricmp(username, info->user_name) == 0) + ret= CR_OK; + } + RevertToSelf(); + + return ret; +} + +static struct st_mysql_auth pipe_auth_handler= +{ + MYSQL_AUTHENTICATION_INTERFACE_VERSION, + 0, + pipe_auth +}; + +maria_declare_plugin(auth_named_pipe) +{ + MYSQL_AUTHENTICATION_PLUGIN, + &pipe_auth_handler, + "named_pipe", + "Vladislav Vaintroub, Georg Richter", + "Windows named pipe based authentication", + PLUGIN_LICENSE_GPL, + NULL, + NULL, + 0x0100, + NULL, + NULL, + "1.0", + MariaDB_PLUGIN_MATURITY_STABLE +} +maria_declare_plugin_end; + diff --git a/plugin/aws_key_management/CMakeLists.txt b/plugin/aws_key_management/CMakeLists.txt new file mode 100644 index 00000000000..97bcfbb04db --- /dev/null +++ b/plugin/aws_key_management/CMakeLists.txt @@ -0,0 +1,154 @@ +# We build parts of AWS C++ SDK as CMake external project +# The restrictions of the SDK (https://github.com/awslabs/aws-sdk-cpp/blob/master/README.md) +# are + +# - OS : Windows,Linux or OSX +# - C++11 compiler : VS2013+, gcc 4.7+, clang 3.3+ +# - libcurl development package needs to be present on Unixes +# +# If we build SDK outselves, we'll need require GIT to be present on the build machine + + +# Give message why the building this plugin is skipped (only if -DVERBOSE is defined) +# or if plugin is explicitely requested to build. Then bail out. +MACRO(SKIP_AWS_PLUGIN msg) + IF(VERBOSE OR "${PLUGIN_AWS_KEY_MANAGEMENT}" MATCHES "^(STATIC|DYNAMIC)$") + MESSAGE(STATUS "Skip aws_key_management - ${msg}") + ENDIF() + RETURN() +ENDMACRO() + +MYSQL_ADD_PLUGIN(aws_key_management aws_key_management_plugin.cc DISABLED + COMPONENT aws-key-management) + +IF(NOT TARGET aws_key_management) + RETURN() +ENDIF() + +# This plugin needs recent C++ compilers (AWS C++ SDK header files are using C++11 features) +SET(CXX11_FLAGS) +SET(OLD_COMPILER_MSG "AWS SDK requires c++11 -capable compiler (minimal supported versions are g++ 4.7, clang 3.3, VS2103)") + +IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + EXECUTE_PROCESS(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) + IF (GCC_VERSION VERSION_LESS 4.8) + SKIP_AWS_PLUGIN("${OLD_COMPILER_MSG}") + ENDIF() + SET(CXX11_FLAGS "-std=c++11") +ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + IF ((CMAKE_CXX_COMPILER_VERSION AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.3) OR + (CLANG_VERSION_STRING AND CLANG_VERSION_STRING VERSION_LESS 3.3)) + SKIP_AWS_PLUGIN("${OLD_COMPILER_MSG}") + ENDIF() + SET(CXX11_FLAGS "-stdlib=libc++") +ELSEIF(MSVC) + IF (MSVC_VERSION LESS 1800) + SKIP_AWS_PLUGIN("${OLD_COMPILER_MSG}") + ENDIF() +ELSE() + SKIP_AWS_PLUGIN("Compiler not supported by AWS C++ SDK") +ENDIF() + +IF (NOT(WIN32 OR APPLE OR (CMAKE_SYSTEM_NAME MATCHES "Linux"))) + SKIP_AWS_PLUGIN("OS unsupported by AWS SDK") +ENDIF() + + +# Figure out where AWS installs SDK libraries +# The below is defined in AWS SDK's CMakeLists.txt +# (and their handling is weird, every OS has special install directory) +IF(WIN32) + SET(SDK_INSTALL_BINARY_PREFIX "windows") +ELSEIF(APPLE) + SET(SDK_INSTALL_BINARY_PREFIX "mac") +ELSEIF(UNIX) + SET(SDK_INSTALL_BINARY_PREFIX "linux") +ENDIF() +IF(NOT APPLE) + IF(CMAKE_SIZEOF_VOID_P EQUAL 8) + SET(SDK_INSTALL_BINARY_PREFIX "${SDK_INSTALL_BINARY_PREFIX}/intel64") + ELSE() + SET(SDK_INSTALL_BINARY_PREFIX "${SDK_INSTALL_BINARY_PREFIX}/ia32") + ENDIF() +ENDIF() +IF(CMAKE_CONFIGURATION_TYPES) + SET(SDK_INSTALL_BINARY_PREFIX "${SDK_INSTALL_BINARY_PREFIX}/${CMAKE_CFG_INTDIR}") +ENDIF() + +FIND_LIBRARY(AWS_CPP_SDK_CORE NAMES aws-cpp-sdk-core PATH_SUFFIXES "${SDK_INSTALL_BINARY_PREFIX}") +FIND_LIBRARY(AWS_CPP_SDK_KMS NAMES aws-cpp-sdk-core PATH_SUFFIXES "${SDK_INSTALL_BINARY_PREFIX}") +SET(CMAKE_REQUIRED_FLAGS ${CXX11_FLAGS}) +CHECK_INCLUDE_FILE_CXX(aws/kms/KMSClient.h HAVE_AWS_HEADERS) + +IF(AWS_CPP_SDK_CORE AND AWS_CPP_SDK_KMS AND HAVE_AWS_HEADERS) + # AWS C++ SDK installed + SET(AWS_SDK_LIBS ${AWS_CPP_SDK_CORE} ${AWS_CPP_SDK_KMS}) +ELSE() + # Build from source, using ExternalProject_Add + IF(CMAKE_VERSION VERSION_LESS "2.8.8") + SKIP_AWS_PLUGIN("CMake is too old") + ENDIF() + FIND_PACKAGE(Git) + IF(NOT GIT_FOUND) + SKIP_AWS_PLUGIN("no GIT") + ENDIF() + INCLUDE(ExternalProject) + IF(UNIX) + FIND_PACKAGE(CURL) + IF(NOT CURL_FOUND) + SKIP_AWS_PLUGIN("AWS C++ SDK requires libcurl development package") + ENDIF() + SET(PIC_FLAG -fPIC) + ENDIF() + IF(MSVC) + SET(EXTRA_SDK_CMAKE_FLAGS -DCMAKE_CXX_FLAGS_DEBUGOPT="" -DCMAKE_EXE_LINKER_FLAGS_DEBUGOPT="" -DCMAKE_CXX_FLAGS=/wd4592) + ENDIF() + IF(CMAKE_CXX_COMPILER) + SET(EXTRA_SDK_CMAKE_FLAGS ${EXTRA_SDK_CMAKE_FLAGS} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}) + ENDIF() + + # Relax AWS C++ SDK unreasonably high requirements for CMake version. Use replace utility (from MariaDB build) + # to patch their CMakeLists.txt + SET(AWS_SDK_PATCH_COMMAND ) + ExternalProject_Add( + aws_sdk_cpp + GIT_REPOSITORY "https://github.com/awslabs/aws-sdk-cpp.git" + GIT_TAG "0.9.6" # single tag + UPDATE_COMMAND "" + PATCH_COMMAND replace 3.1.2 2.8 -- ${CMAKE_BINARY_DIR}/aws-sdk-cpp/CMakeLists.txt + SOURCE_DIR "${CMAKE_BINARY_DIR}/aws-sdk-cpp" + CMAKE_ARGS + -DBUILD_ONLY=aws-cpp-sdk-kms -DSTATIC_LINKING=1 + "-DCMAKE_CXX_FLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG} ${PIC_FLAG}" + "-DCMAKE_CXX_FLAGS_RELWITHDEBINFO=${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${PIC_FLAG}" + "-DCMAKE_CXX_FLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE} ${PIC_FLAG}" + "-DCMAKE_CXX_FLAGS_MINSIZEREL=${CMAKE_CXX_FLAGS_MINSIZEREL} ${PIC_FLAG}" + ${EXTRA_SDK_CMAKE_FLAGS} + -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/aws_sdk_cpp + TEST_COMMAND "" + ) + + # We do not need to build the whole SDK , just 2 of its libs + set(AWS_SDK_LIBS aws-cpp-sdk-core aws-cpp-sdk-kms) + FOREACH(lib ${AWS_SDK_LIBS}) + ADD_LIBRARY(${lib} STATIC IMPORTED GLOBAL) + ADD_DEPENDENCIES(${lib} aws_sdk_cpp) + SET(loc "${CMAKE_BINARY_DIR}/aws_sdk_cpp/lib/${SDK_INSTALL_BINARY_PREFIX}/${CMAKE_STATIC_LIBRARY_PREFIX}${lib}${CMAKE_STATIC_LIBRARY_SUFFIX}") + SET_TARGET_PROPERTIES(${lib} PROPERTIES IMPORTED_LOCATION ${loc}) + IF(WIN32) + SET_TARGET_PROPERTIES(${lib} PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES "bcrypt;winhttp;wininet;userenv") + ELSE() + SET_TARGET_PROPERTIES(${lib} PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES "${SSL_LIBRARIES};${CURL_LIBRARIES}") + ENDIF() + ENDFOREACH() + + IF(CMAKE_SYSTEM_NAME MATCHES "Linux") + # Need whole-archive , otherwise static libraries are not linked + SET(AWS_SDK_LIBS -Wl,--whole-archive ${AWS_SDK_LIBS} -Wl,--no-whole-archive) + ENDIF() + SET_TARGET_PROPERTIES(aws_sdk_cpp PROPERTIES EXCLUDE_FROM_ALL TRUE) + INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/aws_sdk_cpp/include) +ENDIF() + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX11_FLAGS}") +TARGET_LINK_LIBRARIES(aws_key_management ${AWS_SDK_LIBS}) diff --git a/plugin/aws_key_management/aws_key_management_plugin.cc b/plugin/aws_key_management/aws_key_management_plugin.cc new file mode 100644 index 00000000000..3913d2c3145 --- /dev/null +++ b/plugin/aws_key_management/aws_key_management_plugin.cc @@ -0,0 +1,587 @@ +/* + Copyright (c) 2016 MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + + +#include <my_global.h> +#include <my_pthread.h> +#include <my_sys.h> +#include <my_dir.h> +#include <mysql/plugin_encryption.h> +#include <my_crypt.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <mysqld_error.h> +#include <base64.h> +#include <map> +#include <algorithm> +#include <string> +#include <vector> +#include <iterator> +#include <sstream> +#include <fstream> + +#include <aws/core/client/AWSError.h> +#include <aws/core/utils/logging/AWSLogging.h> +#include <aws/core/utils/logging/ConsoleLogSystem.h> +#include <aws/kms/KMSClient.h> +#include <aws/kms/model/DecryptRequest.h> +#include <aws/kms/model/DecryptResult.h> +#include <aws/kms/model/GenerateDataKeyWithoutPlaintextRequest.h> +#include <aws/kms/model/GenerateDataKeyWithoutPlaintextResult.h> +#include <aws/core/utils/Outcome.h> + +using namespace std; +using namespace Aws::KMS; +using namespace Aws::KMS::Model; +using namespace Aws::Utils::Logging; +extern void sql_print_error(const char *format, ...); +extern void sql_print_warning(const char *format, ...); +extern void sql_print_information(const char *format, ...); + + +/* Plaintext key info struct */ +struct KEY_INFO +{ + unsigned int key_id; + unsigned int key_version; + unsigned int length; + unsigned char data[MY_AES_MAX_KEY_LENGTH]; + bool load_failed; /* if true, do not attempt to reload?*/ +public: + KEY_INFO() : key_id(0), key_version(0), length(0), load_failed(false){}; +}; +#define KEY_ID_AND_VERSION(key_id,version) ((longlong)key_id << 32 | version) + +/* Cache for the latest version, per key id */ +static std::map<uint, uint> latest_version_cache; + +/* Cache for plaintext keys */ +static std::map<ulonglong, KEY_INFO> key_info_cache; + +static const char *key_spec_names[]={ "AES_128", "AES_256", 0 }; + +/* Plugin variables */ +static char* master_key_id; +static unsigned long key_spec; +static unsigned long log_level; +static int rotate_key; + +/* AWS functionality*/ +static int aws_decrypt_key(const char *path, KEY_INFO *info); +static int aws_generate_datakey(uint key_id, uint version); + +static int extract_id_and_version(const char *name, uint *id, uint *ver); +static unsigned int get_latest_key_version(unsigned int key_id); +static unsigned int get_latest_key_version_nolock(unsigned int key_id); +static int load_key(KEY_INFO *info); + +/* Mutex to serialize access to caches */ +static mysql_mutex_t mtx; + +#ifdef HAVE_PSI_INTERFACE +static uint mtx_key; +static PSI_mutex_info mtx_info = {&mtx_key, "mtx", 0}; +#endif + +static Aws::KMS::KMSClient *client; + +/* Redirect AWS trace to error log */ +class MySQLLogSystem : public Aws::Utils::Logging::FormattedLogSystem +{ +public: + + using Base = FormattedLogSystem; + MySQLLogSystem(LogLevel logLevel) : + Base(logLevel) + { + } + virtual LogLevel GetLogLevel(void) const override + { + return (LogLevel)log_level; + } + virtual ~MySQLLogSystem() + { + } + +protected: + virtual void ProcessFormattedStatement(Aws::String&& statement) override + { +#ifdef _WIN32 + /* + On Windows, we can't use C runtime functions to write to stdout, + because we compile with static C runtime, so plugin has a stdout + different from server. Thus we're using WriteFile(). + */ + DWORD nSize= (DWORD)statement.size(); + DWORD nWritten; + const char *s= statement.c_str(); + HANDLE h= GetStdHandle(STD_OUTPUT_HANDLE); + + WriteFile(h, s, nSize, &nWritten, NULL); +#else + printf("%s", statement.c_str()); +#endif + } +}; + + +/* + Plugin initialization. + + Create KMS client and scan datadir to find out which keys and versions + are present. +*/ +static int plugin_init(void *p) +{ + DBUG_ENTER("plugin_init"); + client = new KMSClient(); + if (!client) + { + sql_print_error("Can not initialize KMS client"); + DBUG_RETURN(-1); + } + InitializeAWSLogging(Aws::MakeShared<MySQLLogSystem>("aws_key_management_plugin", (Aws::Utils::Logging::LogLevel) log_level)); +#ifdef HAVE_PSI_INTERFACE + mysql_mutex_register("aws_key_management", &mtx_info, 1); +#endif + mysql_mutex_init(mtx_key, &mtx, NULL); + + MY_DIR *dirp = my_dir(".", MYF(0)); + if (!dirp) + { + sql_print_error("Can't scan current directory"); + DBUG_RETURN(-1); + } + for (unsigned int i=0; i < dirp->number_of_files; i++) + { + + KEY_INFO info; + if (extract_id_and_version(dirp->dir_entry[i].name, &info.key_id, &info.key_version) == 0) + { + key_info_cache[KEY_ID_AND_VERSION(info.key_id, info.key_version)]= info; + latest_version_cache[info.key_id]= max(info.key_version, latest_version_cache[info.key_id]); + } + } + my_dirend(dirp); + DBUG_RETURN(0); +} + + +static int plugin_deinit(void *p) +{ + DBUG_ENTER("plugin_deinit"); + latest_version_cache.clear(); + key_info_cache.clear(); + mysql_mutex_destroy(&mtx); + delete client; + ShutdownAWSLogging(); + DBUG_RETURN(0); +} + +/* Generate filename to store the ciphered key */ +static void format_keyfile_name(char *buf, size_t size, uint key_id, uint version) +{ + snprintf(buf, size, "aws-kms-key.%u.%u", key_id, version); +} + +/* Extract key id and version from file name */ +static int extract_id_and_version(const char *name, uint *id, uint *ver) +{ + int len; + int n= sscanf(name, "aws-kms-key.%u.%u%n", id, ver, &len); + if (n == 2 && *id > 0 && *ver > 0 && len == (int)strlen(name)) + return 0; + return 1; +} + +/* + Decrypt key stored in aws-kms-key.<id>.<version> + Cache the decrypted key. +*/ +static int load_key(KEY_INFO *info) +{ + int ret; + char path[256]; + DBUG_ENTER("load_key"); + DBUG_PRINT("enter", ("id=%u,ver=%u", info->key_id, info->key_version)); + format_keyfile_name(path, sizeof(path), info->key_id, info->key_version); + ret= aws_decrypt_key(path, info); + if (ret) + info->load_failed= true; + + latest_version_cache[info->key_id]= max(latest_version_cache[info->key_id], info->key_version); + key_info_cache[KEY_ID_AND_VERSION(info->key_id, info->key_version)]= *info; + + if (!ret) + { + sql_print_information("AWS KMS plugin: loaded key %u, version %u, key length %u bit", + info->key_id, info->key_version,(uint)info->length*8); + } + else + { + sql_print_warning("AWS KMS plugin: key %u, version %u could not be decrypted", + info->key_id, info->key_version); + } + DBUG_RETURN(ret); +} + + +/* + Get latest version for the key. + + If key is not decrypted yet, this function also decrypt the key + and error will be returned if decryption fails. + + The reason for that is that Innodb crashes + in case errors are returned by get_key(), + + A new key will be created if it does not exist, provided there is + valid master_key_id. +*/ +static unsigned int get_latest_key_version(unsigned int key_id) +{ + unsigned int ret; + DBUG_ENTER("get_latest_key_version"); + mysql_mutex_lock(&mtx); + ret= get_latest_key_version_nolock(key_id); + mysql_mutex_unlock(&mtx); + DBUG_PRINT("info", ("key=%u,ret=%u", key_id, ret)); + DBUG_RETURN(ret); +} + +static unsigned int get_latest_key_version_nolock(unsigned int key_id) +{ + KEY_INFO info; + uint ver; + DBUG_ENTER("get_latest_key_version_nolock"); + ver= latest_version_cache[key_id]; + if (ver > 0) + { + info= key_info_cache[KEY_ID_AND_VERSION(key_id, ver)]; + } + if (info.load_failed) + { + /* Decryption failed previously, don't retry */ + DBUG_RETURN(ENCRYPTION_KEY_VERSION_INVALID); + } + else if (ver > 0) + { + /* Key exists already, return it*/ + if (info.length > 0) + DBUG_RETURN(ver); + } + else // (ver == 0) + { + /* Generate a new key, version 1 */ + if (!master_key_id[0]) + { + my_printf_error(ER_UNKNOWN_ERROR, + "Can't generate encryption key %u, because 'aws_key_management_master_key_id' parameter is not set", + MYF(0), key_id); + DBUG_RETURN(ENCRYPTION_KEY_VERSION_INVALID); + } + if (aws_generate_datakey(key_id, 1) != 0) + DBUG_RETURN(ENCRYPTION_KEY_VERSION_INVALID); + info.key_id= key_id; + info.key_version= 1; + info.length= 0; + } + + if (load_key(&info)) + DBUG_RETURN(ENCRYPTION_KEY_VERSION_INVALID); + DBUG_RETURN(info.key_version); +} + + +/* + Decrypt a file with KMS +*/ +static int aws_decrypt_key(const char *path, KEY_INFO *info) +{ + DBUG_ENTER("aws_decrypt_key"); + + /* Read file content into memory */ + ifstream ifs(path, ios::binary | ios::ate); + if (!ifs.good()) + { + sql_print_error("can't open file %s", path); + DBUG_RETURN(-1); + } + size_t pos = (size_t)ifs.tellg(); + if (!pos || pos == SIZE_T_MAX) + { + sql_print_error("invalid key file %s", path); + DBUG_RETURN(-1); + } + std::vector<char> contents(pos); + ifs.seekg(0, ios::beg); + ifs.read(&contents[0], pos); + + /* Decrypt data the with AWS */ + DecryptRequest request; + Aws::Utils::ByteBuffer byteBuffer((unsigned char *)contents.data(), pos); + request.SetCiphertextBlob(byteBuffer); + DecryptOutcome outcome = client->Decrypt(request); + if (!outcome.IsSuccess()) + { + sql_print_error("AWS KMS plugin: Decrypt failed for %s : %s", path, + outcome.GetError().GetMessage().c_str()); + DBUG_RETURN(-1); + } + Aws::Utils::ByteBuffer plaintext = outcome.GetResult().GetPlaintext(); + size_t len = plaintext.GetLength(); + + if (len > (int)sizeof(info->data)) + { + sql_print_error("AWS KMS plugin: encoding key too large for %s", path); + DBUG_RETURN(ENCRYPTION_KEY_BUFFER_TOO_SMALL); + } + memcpy(info->data, plaintext.GetUnderlyingData(), len); + info->length= len; + DBUG_RETURN(0); +} + + +/* Generate a new datakey and store it a file */ +static int aws_generate_datakey(uint keyid, uint version) +{ + + DBUG_ENTER("aws_generate_datakey"); + GenerateDataKeyWithoutPlaintextRequest request; + request.SetKeyId(master_key_id); + request.SetKeySpec(DataKeySpecMapper::GetDataKeySpecForName(key_spec_names[key_spec])); + + GenerateDataKeyWithoutPlaintextOutcome outcome; + outcome= client->GenerateDataKeyWithoutPlaintext(request); + if (!outcome.IsSuccess()) + { + sql_print_error("AWS KMS plugin : GenerateDataKeyWithoutPlaintext failed : %s - %s", + outcome.GetError().GetExceptionName().c_str(), + outcome.GetError().GetMessage().c_str()); + DBUG_RETURN(-1); + } + + string out; + char filename[20]; + Aws::Utils::ByteBuffer byteBuffer = outcome.GetResult().GetCiphertextBlob(); + + format_keyfile_name(filename, sizeof(filename), keyid, version); + int fd= my_open(filename, O_RDWR | O_CREAT, 0); + if (fd < 0) + { + sql_print_error("AWS KMS plugin: Can't create file %s", filename); + DBUG_RETURN(-1); + } + size_t len= byteBuffer.GetLength(); + if (my_write(fd, byteBuffer.GetUnderlyingData(), len, 0) != len) + { + sql_print_error("AWS KMS plugin: can't write to %s", filename); + my_close(fd, 0); + my_delete(filename, 0); + DBUG_RETURN(-1); + } + my_close(fd, 0); + sql_print_information("AWS KMS plugin: generated encrypted datakey for key id=%u, version=%u", + keyid, version); + DBUG_RETURN(0); +} + +/* Key rotation for a single key */ +static int rotate_single_key(uint key_id) +{ + uint ver; + ver= latest_version_cache[key_id]; + + if (!ver) + { + my_printf_error(ER_UNKNOWN_ERROR, "key %u does not exist", MYF(ME_JUST_WARNING), key_id); + return -1; + } + else if (aws_generate_datakey(key_id, ver + 1)) + { + my_printf_error(ER_UNKNOWN_ERROR, "Could not generate datakey for key id= %u, ver= %u", + MYF(ME_JUST_WARNING), key_id, ver); + return -1; + } + else + { + KEY_INFO info; + info.key_id= key_id; + info.key_version = ver + 1; + if (load_key(&info)) + { + my_printf_error(ER_UNKNOWN_ERROR, "Could not load datakey for key id= %u, ver= %u", + MYF(ME_JUST_WARNING), key_id, ver); + return -1; + } + } + return 0; +} + +/* Key rotation for all key ids */ +static int rotate_all_keys() +{ + int ret= 0; + for (map<uint, uint>::iterator it= latest_version_cache.begin(); it != latest_version_cache.end(); it++) + { + ret= rotate_single_key(it->first); + if (ret) + break; + } + return ret; +} + +static void update_rotate(MYSQL_THD, struct st_mysql_sys_var *, void *, const void *val) +{ + if (!master_key_id[0]) + { + my_printf_error(ER_UNKNOWN_ERROR, + "aws_key_management_master_key_id must be set to generate new data keys", MYF(ME_JUST_WARNING)); + return; + } + mysql_mutex_lock(&mtx); + rotate_key= *(int *)val; + switch (rotate_key) + { + case 0: + break; + case -1: + rotate_all_keys(); + break; + default: + rotate_single_key(rotate_key); + break; + } + rotate_key= 0; + mysql_mutex_unlock(&mtx); +} + +static unsigned int get_key( + unsigned int key_id, + unsigned int version, + unsigned char* dstbuf, + unsigned int* buflen) +{ + KEY_INFO info; + + DBUG_ENTER("get_key"); + mysql_mutex_lock(&mtx); + info= key_info_cache[KEY_ID_AND_VERSION(key_id, version)]; + if (info.length == 0 && !info.load_failed) + { + info.key_id= key_id; + info.key_version= version; + load_key(&info); + } + mysql_mutex_unlock(&mtx); + if (info.load_failed) + DBUG_RETURN(ENCRYPTION_KEY_VERSION_INVALID); + if (*buflen < info.length) + { + *buflen= info.length; + DBUG_RETURN(ENCRYPTION_KEY_BUFFER_TOO_SMALL); + } + *buflen= info.length; + memcpy(dstbuf, info.data, info.length); + DBUG_RETURN(0); +} + + +/* Plugin defs */ +struct st_mariadb_encryption aws_key_management_plugin= { + MariaDB_ENCRYPTION_INTERFACE_VERSION, + get_latest_key_version, + get_key, + // use default encrypt/decrypt functions + 0, 0, 0, 0, 0 +}; + + +static TYPELIB key_spec_typelib = +{ + array_elements(key_spec_names) - 1, "", + key_spec_names, NULL +}; + +const char *log_level_names[] = +{ + "Off", + "Fatal", + "Error", + "Warn", + "Info", + "Debug", + "Trace", + 0 +}; + +static TYPELIB log_level_typelib = +{ + array_elements(log_level_names) - 1, "", + log_level_names, NULL +}; + +static MYSQL_SYSVAR_STR(master_key_id, master_key_id, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, + "Key id for master encryption key. Used to create new datakeys. If not set, no new keys will be created", + NULL, NULL, ""); + +static MYSQL_SYSVAR_ENUM(key_spec, key_spec, + PLUGIN_VAR_RQCMDARG, + "Encryption algorithm used to create new keys.", + NULL, NULL, 0, &key_spec_typelib); + + +static MYSQL_SYSVAR_ENUM(log_level, log_level, + PLUGIN_VAR_RQCMDARG, + "Logging for AWS API", + NULL, NULL, 0, &log_level_typelib); + + +static MYSQL_SYSVAR_INT(rotate_key, rotate_key, + PLUGIN_VAR_RQCMDARG, + "Set this variable to key id to perform rotation of the key. Specify -1 to rotate all keys", + NULL, update_rotate, 0, -1, INT_MAX, 1); + +static struct st_mysql_sys_var* settings[]= { + MYSQL_SYSVAR(master_key_id), + MYSQL_SYSVAR(key_spec), + MYSQL_SYSVAR(rotate_key), + MYSQL_SYSVAR(log_level), + NULL +}; + +/* + Plugin library descriptor +*/ +maria_declare_plugin(aws_key_management) +{ + MariaDB_ENCRYPTION_PLUGIN, + &aws_key_management_plugin, + "aws_key_management", + "MariaDB Corporation", + "AWS key management plugin", + PLUGIN_LICENSE_GPL, + plugin_init, + plugin_deinit, + 0x0100, + NULL, + settings, + "1.0", + MariaDB_PLUGIN_MATURITY_EXPERIMENTAL +} +maria_declare_plugin_end; diff --git a/plugin/cracklib_password_check/cracklib_password_check.c b/plugin/cracklib_password_check/cracklib_password_check.c index c16075df74b..c593173942d 100644 --- a/plugin/cracklib_password_check/cracklib_password_check.c +++ b/plugin/cracklib_password_check/cracklib_password_check.c @@ -78,6 +78,6 @@ maria_declare_plugin(cracklib_password_check) NULL, sysvars, "1.0", - MariaDB_PLUGIN_MATURITY_ALPHA, + MariaDB_PLUGIN_MATURITY_GAMMA, } maria_declare_plugin_end; diff --git a/plugin/feedback/feedback.cc b/plugin/feedback/feedback.cc index 28a907a9d93..c7861d99004 100644 --- a/plugin/feedback/feedback.cc +++ b/plugin/feedback/feedback.cc @@ -376,7 +376,6 @@ static MYSQL_SYSVAR_STR(http_proxy, http_proxy, PLUGIN_VAR_READONLY | PLUGIN_VAR_RQCMDARG, "Proxy server host:port.", NULL, NULL,0); - #ifndef DBUG_OFF static MYSQL_SYSVAR_ULONG(debug_startup_interval, debug_startup_interval, PLUGIN_VAR_RQCMDARG, "for debugging only", diff --git a/plugin/feedback/sender_thread.cc b/plugin/feedback/sender_thread.cc index 773ae887891..f7b9f440fcd 100644 --- a/plugin/feedback/sender_thread.cc +++ b/plugin/feedback/sender_thread.cc @@ -265,6 +265,7 @@ ret: thd->set_status_var_init(); thread_count--; thd->killed= KILL_CONNECTION; + thd->unlink(); mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); delete thd; @@ -280,9 +281,7 @@ pthread_handler_t background_thread(void *arg __attribute__((unused))) if (my_thread_init()) return 0; - mysql_mutex_lock(&LOCK_thread_count); - thd_thread_id= thread_id++; - mysql_mutex_unlock(&LOCK_thread_count); + thd_thread_id= next_thread_id(); if (slept_ok(startup_interval)) { diff --git a/plugin/feedback/url_base.cc b/plugin/feedback/url_base.cc index ad99249c268..6afbcd7c8f4 100644 --- a/plugin/feedback/url_base.cc +++ b/plugin/feedback/url_base.cc @@ -48,7 +48,6 @@ Url* Url::create(const char *url, size_t url_length) return self; } - int Url::parse_proxy_server(const char *proxy_server, size_t proxy_length, LEX_STRING *host, LEX_STRING *port) { diff --git a/plugin/file_key_management/file_key_management_plugin.cc b/plugin/file_key_management/file_key_management_plugin.cc index 970fae9c189..e0afbd68cc9 100644 --- a/plugin/file_key_management/file_key_management_plugin.cc +++ b/plugin/file_key_management/file_key_management_plugin.cc @@ -186,6 +186,6 @@ maria_declare_plugin(file_key_management) NULL, /* status variables */ settings, "1.0", - MariaDB_PLUGIN_MATURITY_ALPHA + MariaDB_PLUGIN_MATURITY_GAMMA } maria_declare_plugin_end; diff --git a/plugin/file_key_management/parser.cc b/plugin/file_key_management/parser.cc index 28cd981df79..628412bc171 100644 --- a/plugin/file_key_management/parser.cc +++ b/plugin/file_key_management/parser.cc @@ -220,7 +220,7 @@ bool Parser::parse_file(Dynamic_array<keyentry> *keys, const char *secret) keys->sort(sort_keys); my_free(buffer); - if (keys->at(0).id != 1) + if (keys->elements() == 0 || keys->at(0).id != 1) { report_error("System key id 1 is missing", 0); return 1; diff --git a/plugin/handler_socket/docs-en/perl-client.en.txt b/plugin/handler_socket/docs-en/perl-client.en.txt index 448d33b5f12..cc9138518ee 100644 --- a/plugin/handler_socket/docs-en/perl-client.en.txt +++ b/plugin/handler_socket/docs-en/perl-client.en.txt @@ -42,7 +42,7 @@ to be retrieved are specified by the 5th argument for the corresponding open_index call. The execute_single method always returns an arrayref. The first -element is the error code, which is 0 when no error is occured. +element is the error code, which is 0 when no error is occurred. The remaining are the field values. If more than one record is returned, it is flatten to an 1-dimensional array. For example, when 5 records that have 3 columns are returned, you can retrieve @@ -125,9 +125,9 @@ methods. die $hs->get_error() if $res->[0] != 0; ----------------------------------------------------------------- -When an error is occured, the first element of the returned +When an error is occurred, the first element of the returned arrayref becomes a non-zero value. A negative value indicates -that an I/O error is occured and the Net::HandlerSocket object +that an I/O error is occurred and the Net::HandlerSocket object should be disposed. A positive value means that the connection is still active and the Net::HandlerSocket object can be reused later. diff --git a/plugin/handler_socket/handlersocket/database.cpp b/plugin/handler_socket/handlersocket/database.cpp index 8ea7b5061a1..94eedbf6d04 100644 --- a/plugin/handler_socket/handlersocket/database.cpp +++ b/plugin/handler_socket/handlersocket/database.cpp @@ -304,15 +304,14 @@ dbcontext::init_thread(const void *stack_bottom, volatile int& shutdown_flag) thd->db = 0; thd->db = my_strdup("handlersocket", MYF(0)); } + thd->variables.option_bits |= OPTION_TABLE_LOCK; my_pthread_setspecific_ptr(THR_THD, thd); DBG_THR(fprintf(stderr, "HNDSOCK x0 %p\n", thd)); } { - pthread_mutex_lock(&LOCK_thread_count); - thd->thread_id = thread_id++; - threads.append(thd); - ++thread_count; - pthread_mutex_unlock(&LOCK_thread_count); + thd->thread_id = next_thread_id(); + thread_safe_increment32(&thread_count); + add_to_active_threads(thd); } DBG_THR(fprintf(stderr, "HNDSOCK init thread wsts\n")); @@ -343,7 +342,7 @@ void dbcontext::term_thread() { DBG_THR(fprintf(stderr, "HNDSOCK thread end %p\n", thd)); - unlock_tables_if(); + close_tables_if(); my_pthread_setspecific_ptr(THR_THD, 0); { pthread_mutex_lock(&LOCK_thread_count); diff --git a/plugin/locale_info/locale_info.cc b/plugin/locale_info/locale_info.cc index dd14dcbb769..3d775c0be7c 100644 --- a/plugin/locale_info/locale_info.cc +++ b/plugin/locale_info/locale_info.cc @@ -117,6 +117,6 @@ maria_declare_plugin(locales) NULL, /* Status variables */ NULL, /* System variables */ "1.0", /* String version representation */ - MariaDB_PLUGIN_MATURITY_GAMMA /* Maturity (see include/mysql/plugin.h)*/ + MariaDB_PLUGIN_MATURITY_STABLE /* Maturity (see include/mysql/plugin.h)*/ } maria_declare_plugin_end; diff --git a/plugin/metadata_lock_info/metadata_lock_info.cc b/plugin/metadata_lock_info/metadata_lock_info.cc index fcfdb59da30..83db2c7ca5c 100644 --- a/plugin/metadata_lock_info/metadata_lock_info.cc +++ b/plugin/metadata_lock_info/metadata_lock_info.cc @@ -164,7 +164,7 @@ maria_declare_plugin(metadata_lock_info) NULL, NULL, NULL, - MariaDB_PLUGIN_MATURITY_GAMMA, + MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; #else diff --git a/plugin/qc_info/qc_info.cc b/plugin/qc_info/qc_info.cc index 998076dadf7..4ccfdc8f8c2 100644 --- a/plugin/qc_info/qc_info.cc +++ b/plugin/qc_info/qc_info.cc @@ -282,7 +282,7 @@ maria_declare_plugin(query_cache_info) NULL, /* status variables */ NULL, /* system variables */ "1.1", /* version as a string */ - MariaDB_PLUGIN_MATURITY_GAMMA + MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; diff --git a/plugin/query_response_time/mysql-test/query_response_time/basic.result b/plugin/query_response_time/mysql-test/query_response_time/basic.result index 15746424b1d..86fba87e056 100644 --- a/plugin/query_response_time/mysql-test/query_response_time/basic.result +++ b/plugin/query_response_time/mysql-test/query_response_time/basic.result @@ -17,7 +17,7 @@ PLUGIN_TYPE INFORMATION SCHEMA PLUGIN_AUTHOR Percona and Sergey Vojtovich PLUGIN_DESCRIPTION Query Response Time Distribution INFORMATION_SCHEMA Plugin PLUGIN_LICENSE GPL -PLUGIN_MATURITY Gamma +PLUGIN_MATURITY Stable PLUGIN_NAME QUERY_RESPONSE_TIME_AUDIT PLUGIN_VERSION 1.0 PLUGIN_TYPE AUDIT diff --git a/plugin/query_response_time/plugin.cc b/plugin/query_response_time/plugin.cc index c34e4cb6e02..37d52c3ce85 100644 --- a/plugin/query_response_time/plugin.cc +++ b/plugin/query_response_time/plugin.cc @@ -144,7 +144,7 @@ maria_declare_plugin(query_response_time) NULL, query_response_time_info_vars, "1.0", - MariaDB_PLUGIN_MATURITY_GAMMA + MariaDB_PLUGIN_MATURITY_STABLE }, { MYSQL_AUDIT_PLUGIN, diff --git a/plugin/semisync/semisync_master.cc b/plugin/semisync/semisync_master.cc index bbe4e3fb7a4..7901853c3f8 100644 --- a/plugin/semisync/semisync_master.cc +++ b/plugin/semisync/semisync_master.cc @@ -1,6 +1,6 @@ /* Copyright (C) 2007 Google Inc. - Copyright (c) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. - Use is subject to license terms. + Copyright (c) 2008, 2013, Oracle and/or its affiliates. + Copyright (c) 2011, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/plugin/semisync/semisync_master.h b/plugin/semisync/semisync_master.h index d9dc4ce024b..c2862476ec8 100644 --- a/plugin/semisync/semisync_master.h +++ b/plugin/semisync/semisync_master.h @@ -102,7 +102,7 @@ public: it are in use. A new Block is allocated and is put into the rear of the Block link table if no Block is free. - @return Return a TranxNode *, or NULL if an error occured. + @return Return a TranxNode *, or NULL if an error occurred. */ TranxNode *allocate_node() { @@ -134,7 +134,7 @@ public: /** All nodes are freed. - @return Return 0, or 1 if an error occured. + @return Return 0, or 1 if an error occurred. */ int free_all_nodes() { @@ -150,7 +150,7 @@ public: @param node All nodes before 'node' will be freed - @return Return 0, or 1 if an error occured. + @return Return 0, or 1 if an error occurred. */ int free_nodes_before(TranxNode* node) { diff --git a/plugin/semisync/semisync_master_plugin.cc b/plugin/semisync/semisync_master_plugin.cc index 7bb0eea44ee..309910312c4 100644 --- a/plugin/semisync/semisync_master_plugin.cc +++ b/plugin/semisync/semisync_master_plugin.cc @@ -489,7 +489,7 @@ maria_declare_plugin(semisync_master) semi_sync_master_status_vars, /* status variables */ semi_sync_master_system_vars, /* system variables */ "1.0", - MariaDB_PLUGIN_MATURITY_GAMMA + MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; diff --git a/plugin/semisync/semisync_slave_plugin.cc b/plugin/semisync/semisync_slave_plugin.cc index 572ead214de..3a6c7625d93 100644 --- a/plugin/semisync/semisync_slave_plugin.cc +++ b/plugin/semisync/semisync_slave_plugin.cc @@ -227,7 +227,7 @@ maria_declare_plugin(semisync_slave) semi_sync_slave_status_vars, /* status variables */ semi_sync_slave_system_vars, /* system variables */ "1.0", - MariaDB_PLUGIN_MATURITY_GAMMA + MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; diff --git a/plugin/server_audit/CMakeLists.txt b/plugin/server_audit/CMakeLists.txt index 527d0d702da..3de8c43c871 100644 --- a/plugin/server_audit/CMakeLists.txt +++ b/plugin/server_audit/CMakeLists.txt @@ -13,4 +13,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -MYSQL_ADD_PLUGIN(server_audit server_audit.c MODULE_ONLY) +SET(SERVER_AUDIT_SOURCES + server_audit.c test_audit_v4.c plugin_audit_v4.h) + + MYSQL_ADD_PLUGIN(server_audit ${SERVER_AUDIT_SOURCES} MODULE_ONLY) diff --git a/plugin/server_audit/plugin_audit_v4.h b/plugin/server_audit/plugin_audit_v4.h new file mode 100644 index 00000000000..5f8e43b3811 --- /dev/null +++ b/plugin/server_audit/plugin_audit_v4.h @@ -0,0 +1,561 @@ +/* Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef _my_audit_h +#define _my_audit_h + +#ifndef PLUGIN_CONTEXT +#include "plugin.h" +#include "mysql/mysql_lex_string.h" +#ifndef MYSQL_ABI_CHECK +#include "m_string.h" +#endif +#include "my_command.h" +#include "my_sqlcommand.h" +#endif /*PLUGIN_CONTEXT*/ + +#define MYSQL_AUDIT_INTERFACE_VERSION 0x0401 + +/** + @enum mysql_event_class_t + + Audit event classes. +*/ +typedef enum +{ + MYSQL_AUDIT_GENERAL_CLASS = 0, + MYSQL_AUDIT_CONNECTION_CLASS = 1, + MYSQL_AUDIT_PARSE_CLASS = 2, + MYSQL_AUDIT_AUTHORIZATION_CLASS = 3, + MYSQL_AUDIT_TABLE_ACCESS_CLASS = 4, + MYSQL_AUDIT_GLOBAL_VARIABLE_CLASS = 5, + MYSQL_AUDIT_SERVER_STARTUP_CLASS = 6, + MYSQL_AUDIT_SERVER_SHUTDOWN_CLASS = 7, + MYSQL_AUDIT_COMMAND_CLASS = 8, + MYSQL_AUDIT_QUERY_CLASS = 9, + MYSQL_AUDIT_STORED_PROGRAM_CLASS = 10, + /* This item must be last in the list. */ + MYSQL_AUDIT_CLASS_MASK_SIZE +} mysql_event_class_t; + +/** + @struct st_mysql_audit + + The descriptor structure that is referred from st_mysql_plugin. +*/ +struct st_mysql_audit +{ + /** + Interface version. + */ + int interface_version; + + /** + Event occurs when the event class consumer is to be + disassociated from the specified THD.This would typically occur + before some operation which may require sleeping - such as when + waiting for the next query from the client. + */ + void (*release_thd)(MYSQL_THD); + + /** + Invoked whenever an event occurs which is of any + class for which the plugin has interest.The second argument + indicates the specific event class and the third argument is data + as required for that class. + */ + int (*event_notify)(MYSQL_THD, mysql_event_class_t, const void *); + + /** + An array of bits used to indicate what event classes + that this plugin wants to receive. + */ + unsigned long class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; +}; + +/** + @typedef enum_sql_command_t + + SQL command type definition. +*/ +typedef enum enum_sql_command enum_sql_command_t; + +/** + @enum mysql_event_general_subclass_t + + Events for the MYSQL_AUDIT_GENERAL_CLASS event class. +*/ +typedef enum +{ + /** occurs before emitting to the general query log. */ + MYSQL_AUDIT_GENERAL_LOG = 1 << 0, + /** occurs before transmitting errors to the user. */ + MYSQL_AUDIT_GENERAL_ERROR = 1 << 1, + /** occurs after transmitting a resultset to the user. */ + MYSQL_AUDIT_GENERAL_RESULT = 1 << 2, + /** occurs after transmitting a resultset or errors */ + MYSQL_AUDIT_GENERAL_STATUS = 1 << 3 +} mysql_event_general_subclass_t; + +#define MYSQL_AUDIT_GENERAL_ALL (MYSQL_AUDIT_GENERAL_LOG | \ + MYSQL_AUDIT_GENERAL_ERROR | \ + MYSQL_AUDIT_GENERAL_RESULT | \ + MYSQL_AUDIT_GENERAL_STATUS) +/** + @struct mysql_event_general + + Structure for the MYSQL_AUDIT_GENERAL_CLASS event class. +*/ +struct mysql_event_general +{ + mysql_event_general_subclass_t event_subclass; + int general_error_code; + unsigned long general_thread_id; + MYSQL_LEX_CSTRING general_user; + MYSQL_LEX_CSTRING general_command; + MYSQL_LEX_CSTRING general_query; + struct charset_info_st *general_charset; + unsigned long long general_time; + unsigned long long general_rows; + MYSQL_LEX_CSTRING general_host; + MYSQL_LEX_CSTRING general_sql_command; + MYSQL_LEX_CSTRING general_external_user; + MYSQL_LEX_CSTRING general_ip; +}; + +/** + @enum mysql_event_connection_subclass_t + + Events for MYSQL_AUDIT_CONNECTION_CLASS event class. +*/ +typedef enum +{ + /** occurs after authentication phase is completed. */ + MYSQL_AUDIT_CONNECTION_CONNECT = 1 << 0, + /** occurs after connection is terminated. */ + MYSQL_AUDIT_CONNECTION_DISCONNECT = 1 << 1, + /** occurs after COM_CHANGE_USER RPC is completed. */ + MYSQL_AUDIT_CONNECTION_CHANGE_USER = 1 << 2, + /** occurs before authentication. */ + MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE = 1 << 3 +} mysql_event_connection_subclass_t; + +#define MYSQL_AUDIT_CONNECTION_ALL (MYSQL_AUDIT_CONNECTION_CONNECT | \ + MYSQL_AUDIT_CONNECTION_DISCONNECT | \ + MYSQL_AUDIT_CONNECTION_CHANGE_USER | \ + MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE) +/** + @struct mysql_event_connection + + Structure for the MYSQL_AUDIT_CONNECTION_CLASS event class. +*/ +struct mysql_event_connection +{ + /** Event subclass. */ + mysql_event_connection_subclass_t event_subclass; + /** Current status of the connection. */ + int status; + /** Connection id. */ + unsigned long connection_id; + /** User name of this connection. */ + MYSQL_LEX_CSTRING user; + /** Priv user name. */ + MYSQL_LEX_CSTRING priv_user; + /** External user name. */ + MYSQL_LEX_CSTRING external_user; + /** Proxy user used for this connection. */ + MYSQL_LEX_CSTRING proxy_user; + /** Connection host. */ + MYSQL_LEX_CSTRING host; + /** IP of the connection. */ + MYSQL_LEX_CSTRING ip; + /** Database name specified at connection time. */ + MYSQL_LEX_CSTRING database; + /** Connection type: + - 0 Undefined + - 1 TCP/IP + - 2 Socket + - 3 Named pipe + - 4 SSL + - 5 Shared memory + */ + int connection_type; +}; + +/** +@enum mysql_event_parse_subclass_t + +Events for MYSQL_AUDIT_PARSE_CLASS event class. +*/ +typedef enum +{ + /** occurs before the query parsing. */ + MYSQL_AUDIT_PARSE_PREPARSE = 1 << 0, + /** occurs after the query parsing. */ + MYSQL_AUDIT_PARSE_POSTPARSE = 1 << 1 +} mysql_event_parse_subclass_t; + +#define MYSQL_AUDIT_PARSE_ALL (MYSQL_AUDIT_PARSE_PREPARSE | \ + MYSQL_AUDIT_PARSE_POSTPARSE) + +typedef enum +{ + MYSQL_AUDIT_PARSE_REWRITE_PLUGIN_NONE = 0, + /// mysql_event_parse::flags Must be set by a plugin if the query is rewritten. + MYSQL_AUDIT_PARSE_REWRITE_PLUGIN_QUERY_REWRITTEN = 1 << 0, + /// mysql_event_parse::flags Is set by the server if the query is prepared statement. + MYSQL_AUDIT_PARSE_REWRITE_PLUGIN_IS_PREPARED_STATEMENT = 1 << 1 +} mysql_event_parse_rewrite_plugin_flag; + +/** Data for the MYSQL_AUDIT_PARSE events */ +struct mysql_event_parse +{ + /** MYSQL_AUDIT_[PRE|POST]_PARSE event id */ + mysql_event_parse_subclass_t event_subclass; + + /** one of FLAG_REWRITE_PLUGIN_* */ + mysql_event_parse_rewrite_plugin_flag *flags; + + /** input: the original query text */ + MYSQL_LEX_CSTRING query; + + /** output: returns the null-terminated rewriten query allocated by my_malloc() */ + MYSQL_LEX_CSTRING *rewritten_query; +}; + +/** + @enum mysql_event_authorization_subclass_t + + Events for MYSQL_AUDIT_AUTHORIZATION_CLASS event class. +*/ +typedef enum +{ + MYSQL_AUDIT_AUTHORIZATION_USER = 1 << 0, + /** Occurs when database privilege is checked. */ + MYSQL_AUDIT_AUTHORIZATION_DB = 1 << 1, + /** Occurs when table privilege is checked. */ + MYSQL_AUDIT_AUTHORIZATION_TABLE = 1 << 2, + /** Occurs when column privilege is checked. */ + MYSQL_AUDIT_AUTHORIZATION_COLUMN = 1 << 3, + /** Occurs when procedure privilege is checked. */ + MYSQL_AUDIT_AUTHORIZATION_PROCEDURE = 1 << 4, + /** Occurs when proxy privilege is checked. */ + MYSQL_AUDIT_AUTHORIZATION_PROXY = 1 << 5 +} mysql_event_authorization_subclass_t; + +#define MYSQL_AUDIT_AUTHORIZATION_ALL (MYSQL_AUDIT_AUTHORIZATION_USER | \ + MYSQL_AUDIT_AUTHORIZATION_DB | \ + MYSQL_AUDIT_AUTHORIZATION_TABLE | \ + MYSQL_AUDIT_AUTHORIZATION_COLUMN | \ + MYSQL_AUDIT_AUTHORIZATION_PROCEDURE | \ + MYSQL_AUDIT_AUTHORIZATION_PROXY) +/** + @struct mysql_event_authorization + + Structure for MYSQL_AUDIT_AUTHORIZATION_CLASS event class. +*/ +struct mysql_event_authorization +{ + /** Event subclass. */ + mysql_event_authorization_subclass_t event_subclass; + /** Event status. */ + int status; + /** Connection id. */ + unsigned int connection_id; + /** SQL command id. */ + enum_sql_command_t sql_command_id; + /** SQL query text. */ + MYSQL_LEX_CSTRING query; + /** SQL query charset. */ + const struct charset_info_st *query_charset; + /** Database name. */ + MYSQL_LEX_CSTRING database; + /** Table name. */ + MYSQL_LEX_CSTRING table; + /** Other name associated with the event. */ + MYSQL_LEX_CSTRING object; + /** Requested authorization privileges. */ + unsigned long requested_privilege; + /** Currently granted authorization privileges. */ + unsigned long granted_privilege; +}; + +/** + @enum mysql_event_table_row_access_subclass_t + + Events for MYSQL_AUDIT_TABLE_ACCES_CLASS event class. +*/ +typedef enum +{ + /** Occurs when table data are read. */ + MYSQL_AUDIT_TABLE_ACCESS_READ = 1 << 0, + /** Occurs when table data are inserted. */ + MYSQL_AUDIT_TABLE_ACCESS_INSERT = 1 << 1, + /** Occurs when table data are updated. */ + MYSQL_AUDIT_TABLE_ACCESS_UPDATE = 1 << 2, + /** Occurs when table data are deleted. */ + MYSQL_AUDIT_TABLE_ACCESS_DELETE = 1 << 3 +} mysql_event_table_access_subclass_t; + +#define MYSQL_AUDIT_TABLE_ACCESS_ALL (MYSQL_AUDIT_TABLE_ACCESS_READ | \ + MYSQL_AUDIT_TABLE_ACCESS_INSERT | \ + MYSQL_AUDIT_TABLE_ACCESS_UPDATE | \ + MYSQL_AUDIT_TABLE_ACCESS_DELETE) + +/** + @struct mysql_event_table_row_access + + Structure for MYSQL_AUDIT_TABLE_ACCES_CLASS event class. +*/ +struct mysql_event_table_access +{ + /** Event subclass. */ + mysql_event_table_access_subclass_t event_subclass; + /** Connection id. */ + unsigned long connection_id; + /** SQL command id. */ + enum_sql_command_t sql_command_id; + /** SQL query. */ + MYSQL_LEX_CSTRING query; + /** SQL query charset. */ + const struct charset_info_st *query_charset; + /** Database name. */ + MYSQL_LEX_CSTRING table_database; + /** Table name. */ + MYSQL_LEX_CSTRING table_name; +}; + +/** + @enum mysql_event_global_variable_subclass_t + + Events for MYSQL_AUDIT_GLOBAL_VARIABLE_CLASS event class. +*/ +typedef enum +{ + /** Occurs when global variable is retrieved. */ + MYSQL_AUDIT_GLOBAL_VARIABLE_GET = 1 << 0, + /** Occurs when global variable is set. */ + MYSQL_AUDIT_GLOBAL_VARIABLE_SET = 1 << 1 +} mysql_event_global_variable_subclass_t; + +#define MYSQL_AUDIT_GLOBAL_VARIABLE_ALL (MYSQL_AUDIT_GLOBAL_VARIABLE_GET | \ + MYSQL_AUDIT_GLOBAL_VARIABLE_SET) + +/** Events for MYSQL_AUDIT_GLOBAL_VARIABLE_CLASS event class. */ +struct mysql_event_global_variable +{ + /** Event subclass. */ + mysql_event_global_variable_subclass_t event_subclass; + /** Connection id. */ + unsigned long connection_id; + /** SQL command id. */ + enum_sql_command_t sql_command_id; + /** Variable name. */ + MYSQL_LEX_CSTRING variable_name; + /** Variable value. */ + MYSQL_LEX_CSTRING variable_value; +}; + +/** + @enum mysql_event_server_startup_subclass_t + + Events for MYSQL_AUDIT_SERVER_STARTUP_CLASS event class. +*/ +typedef enum +{ + /** Occurs after all subsystem are initialized during system start. */ + MYSQL_AUDIT_SERVER_STARTUP_STARTUP = 1 << 0 +} mysql_event_server_startup_subclass_t; + +#define MYSQL_AUDIT_SERVER_STARTUP_ALL (MYSQL_AUDIT_SERVER_STARTUP_STARTUP) + +/** + @struct mysql_event_server_startup + + Structure for MYSQL_AUDIT_SERVER_STARTUP_CLASS event class. +*/ +struct mysql_event_server_startup +{ + /** Event subclass. */ + mysql_event_server_startup_subclass_t event_subclass; + /** Command line arguments. */ + const char **argv; + /** Command line arguments count. */ + unsigned int argc; +}; + +/** + @enum mysql_event_server_shutdown_subclass_t + + Events for MYSQL_AUDIT_SERVER_SHUTDOWN_CLASS event class. +*/ +typedef enum +{ + /** Occurs when global variable is set. */ + MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN = 1 << 0 +} mysql_event_server_shutdown_subclass_t; + +#define MYSQL_AUDIT_SERVER_SHUTDOWN_ALL (MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN) + +/** + @enum mysql_server_shutdown_reason_t + + Server shutdown reason. +*/ +typedef enum +{ + /** User requested shut down. */ + MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_SHUTDOWN, + /** The server aborts. */ + MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_ABORT +} mysql_server_shutdown_reason_t; + +/** + @struct mysql_event_server_shutdown + + Structure for MYSQL_AUDIT_SERVER_SHUTDOWN_CLASS event class. +*/ +struct mysql_event_server_shutdown +{ + /** Shutdown event. */ + mysql_event_server_shutdown_subclass_t event_subclass; + /** Exit code associated with the shutdown event. */ + int exit_code; + /** Shutdown reason. */ + mysql_server_shutdown_reason_t reason; +}; + +/** + @enum mysql_event_command_subclass_t + + Events for MYSQL_AUDIT_COMMAND_CLASS event class. +*/ +typedef enum +{ + /** Command start event. */ + MYSQL_AUDIT_COMMAND_START = 1 << 0, + /** Command end event. */ + MYSQL_AUDIT_COMMAND_END = 1 << 1 +} mysql_event_command_subclass_t; + +#define MYSQL_AUDIT_COMMAND_ALL (MYSQL_AUDIT_COMMAND_START | \ + MYSQL_AUDIT_COMMAND_END) +/** + @typedef enum_server_command_t + + Server command type definition. +*/ +typedef enum enum_server_command enum_server_command_t; + +/** + @struct mysql_event_command + + Event for MYSQL_AUDIT_COMMAND_CLASS event class. + Events generated as a result of RPC command requests. +*/ +struct mysql_event_command +{ + /** Command event subclass. */ + mysql_event_command_subclass_t event_subclass; + /** Command event status. */ + int status; + /** Connection id. */ + unsigned long connection_id; + /** Command id. */ + enum_server_command_t command_id; +}; + +/** + @enum mysql_event_query_subclass_t + + Events for MYSQL_AUDIT_QUERY_CLASS event class. +*/ +typedef enum +{ + /** Query start event. */ + MYSQL_AUDIT_QUERY_START = 1 << 0, + /** Nested query start event. */ + MYSQL_AUDIT_QUERY_NESTED_START = 1 << 1, + /** Query post parse event. */ + MYSQL_AUDIT_QUERY_STATUS_END = 1 << 2, + /** Nested query status end event. */ + MYSQL_AUDIT_QUERY_NESTED_STATUS_END = 1 << 3 +} mysql_event_query_subclass_t; + +#define MYSQL_AUDIT_QUERY_ALL (MYSQL_AUDIT_QUERY_START | \ + MYSQL_AUDIT_QUERY_NESTED_START | \ + MYSQL_AUDIT_QUERY_STATUS_END | \ + MYSQL_AUDIT_QUERY_NESTED_STATUS_END) +/** + @struct mysql_event_command + + Event for MYSQL_AUDIT_COMMAND_CLASS event class. +*/ +struct mysql_event_query +{ + /** Event subclass. */ + mysql_event_query_subclass_t event_subclass; + /** Event status. */ + int status; + /** Connection id. */ + unsigned long connection_id; + /** SQL command id. */ + enum_sql_command_t sql_command_id; + /** SQL query. */ + MYSQL_LEX_CSTRING query; + /** SQL query charset. */ + const struct charset_info_st *query_charset; +}; + +/** + @enum mysql_event_stored_program_subclass_t + + Events for MYSQL_AUDIT_STORED_PROGRAM_CLASS event class. +*/ +typedef enum +{ + /** Stored program execution event. */ + MYSQL_AUDIT_STORED_PROGRAM_EXECUTE = 1 << 0 +} mysql_event_stored_program_subclass_t; + +#define MYSQL_AUDIT_STORED_PROGRAM_ALL (MYSQL_AUDIT_STORED_PROGRAM_EXECUTE) + +/** + @struct mysql_event_command + +Event for MYSQL_AUDIT_COMMAND_CLASS event class. +*/ +struct mysql_event_stored_program +{ + /** Event subclass. */ + mysql_event_stored_program_subclass_t event_subclass; + /** Connection id. */ + unsigned long connection_id; + /** SQL command id. */ + enum_sql_command_t sql_command_id; + /** SQL query text. */ + MYSQL_LEX_CSTRING query; + /** SQL query charset. */ + const struct charset_info_st *query_charset; + /** The Database the procedure is defined in. */ + MYSQL_LEX_CSTRING database; + /** Name of the stored program. */ + MYSQL_LEX_CSTRING name; + /** Stored program parameters. */ + void *parameters; +}; + +#endif diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index f7e18c88202..9df0d75e3c6 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -14,13 +14,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define PLUGIN_VERSION 0x103 -#define PLUGIN_STR_VERSION "1.3.0" +#define PLUGIN_VERSION 0x104 +#define PLUGIN_STR_VERSION "1.4.0" + +#define _my_thread_var loc_thread_var #include <my_config.h> #include <stdio.h> #include <time.h> #include <string.h> +#include <fcntl.h> #ifndef _WIN32 #include <syslog.h> @@ -80,8 +83,7 @@ static void closelog() {} #endif /*MARIADB_ONLY*/ #include <my_base.h> -//#include <hash.h> -#include <my_dir.h> +//#include <my_dir.h> #include <typelib.h> #include <mysql/plugin.h> #include <mysql/plugin_audit.h> @@ -89,49 +91,6 @@ static void closelog() {} #define RTLD_DEFAULT NULL #endif -#undef my_init_dynamic_array_ci -#define init_dynamic_array2 loc_init_dynamic_array2 -#define my_init_dynamic_array_ci(A,B,C,D) loc_init_dynamic_array2(A,B,NULL,C,D) -#define my_hash_init2 loc_my_hash_init -#define my_hash_search loc_my_hash_search -#define my_hash_insert loc_my_hash_insert -#define my_hash_delete loc_my_hash_delete -#define my_hash_update loc_my_hash_update -#define my_hash_free loc_my_hash_free -#define my_hash_first loc_my_hash_first -#define my_hash_reset loc_my_hash_reset -#define my_hash_search_using_hash_value loc_my_hash_search_using_hash_value -#define my_hash_first_from_hash_value loc_my_hash_first_from_hash_value -#define my_hash_sort loc_my_hash_sort -#undef my_hash_first_from_hash_value -#define my_hash_first_from_hash_value loc_my_my_hash_first_from_hash_value -#define my_hash_next loc_my_hash_next -#define my_hash_element loc_my_hash_element -#define my_hash_replace loc_my_hash_replace -#define my_hash_iterate loc_my_hash_iterate - -#define alloc_dynamic loc_alloc_dynamic -#define pop_dynamic loc_pop_dynamic -#define delete_dynamic loc_delete_dynamic -void *loc_alloc_dynamic(DYNAMIC_ARRAY *array); -#ifdef my_strnncoll -#undef my_strnncoll -#define my_strnncoll(s, a, b, c, d) (my_strnncoll_binary((s), (a), (b), (c), (d), 0)) -#endif - -static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)), - const uchar *s, size_t slen, - const uchar *t, size_t tlen, - my_bool t_is_prefix) -{ - size_t len= slen < tlen ? slen : tlen; - int cmp= memcmp(s,t,len); - return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen); -} - -#include "../../mysys/array.c" -#include "../../mysys/hash.c" - #ifndef MARIADB_ONLY #undef MYSQL_SERVICE_LOGGER_INCLUDED #undef MYSQL_DYNAMIC_PLUGIN @@ -144,18 +103,162 @@ static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)), #define mysql_mutex_real_mutex(A) &(A)->m_mutex #endif -#define flogger_mutex_init(A,B,C) pthread_mutex_init(mysql_mutex_real_mutex(B), C) -#define flogger_mutex_destroy(A) pthread_mutex_destroy(mysql_mutex_real_mutex(A)) -#define flogger_mutex_lock(A) pthread_mutex_lock(mysql_mutex_real_mutex(A)) -#define flogger_mutex_unlock(A) pthread_mutex_unlock(mysql_mutex_real_mutex(A)) +#define flogger_mutex_init(A,B,C) do{}while(0) +#define flogger_mutex_destroy(A) do{}while(0) +#define flogger_mutex_lock(A) do{}while(0) +#define flogger_mutex_unlock(A) do{}while(0) static char **int_mysql_data_home; static char *default_home= (char *)"."; #define mysql_data_home (*int_mysql_data_home) +#define FLOGGER_SKIP_INCLUDES +#define my_open(A, B, C) loc_open(A, B) +#define my_close(A, B) loc_close(A) +#define my_rename(A, B, C) loc_rename(A, B) +#define my_tell(A, B) loc_tell(A) +#define my_write(A, B, C, D) loc_write(A, B, C) +#define my_malloc(A, B) malloc(A) +#define my_free(A) free(A) +#ifdef my_errno + #undef my_errno +#endif +static int loc_file_errno; +#define my_errno loc_file_errno +#ifdef my_vsnprintf + #undef my_vsnprintf +#endif +#define my_vsnprintf vsnprintf +#define logger_open loc_logger_open +#define logger_close loc_logger_close +#define logger_write loc_logger_write +#define logger_rotate loc_logger_rotate +#define logger_init_mutexts loc_logger_init_mutexts + + +static size_t loc_write(File Filedes, const uchar *Buffer, size_t Count) +{ + size_t writtenbytes; +#ifdef _WIN32 + writtenbytes= my_win_write(Filedes, Buffer, Count); +#else + writtenbytes= write(Filedes, Buffer, Count); +#endif + return writtenbytes; +} + + +static File loc_open(const char *FileName, int Flags) + /* Path-name of file */ + /* Read | write .. */ + /* Special flags */ +{ + File fd; +#if defined(_WIN32) + fd= my_win_open(FileName, Flags); +#elif !defined(NO_OPEN_3) + fd = open(FileName, Flags, my_umask); /* Normal unix */ +#else + fd = open((char *) FileName, Flags); +#endif + my_errno= errno; + return fd; +} + + +static int loc_close(File fd) +{ + int err; +#ifndef _WIN32 + do + { + err= close(fd); + } while (err == -1 && errno == EINTR); +#else + err= my_win_close(fd); +#endif + my_errno=errno; + return err; +} + + +static int loc_rename(const char *from, const char *to) +{ + int error = 0; + +#if defined(__WIN__) + if (!MoveFileEx(from, to, MOVEFILE_COPY_ALLOWED | + MOVEFILE_REPLACE_EXISTING)) + { + my_osmaperr(GetLastError()); +#elif defined(HAVE_RENAME) + if (rename(from,to)) + { +#else + if (link(from, to) || unlink(from)) + { +#endif + my_errno=errno; + error = -1; + } + return error; +} + + +static my_off_t loc_seek(File fd, my_off_t pos, int whence) +{ + os_off_t newpos= -1; +#ifdef _WIN32 + newpos= my_win_lseek(fd, pos, whence); +#else + newpos= lseek(fd, pos, whence); +#endif + if (newpos == (os_off_t) -1) + { + my_errno= errno; + return MY_FILEPOS_ERROR; + } + + return (my_off_t) newpos; +} + + +static my_off_t loc_tell(File fd) +{ + os_off_t pos; +#if defined (HAVE_TELL) && !defined (_WIN32) + pos= tell(fd); +#else + pos= loc_seek(fd, 0L, MY_SEEK_CUR); +#endif + if (pos == (os_off_t) -1) + { + my_errno= errno; + } + return (my_off_t) pos; +} + +#ifdef HAVE_PSI_INTERFACE +#undef HAVE_PSI_INTERFACE +#include <mysql/service_logger.h> +#include "../../mysys/file_logger.c" +#define HAVE_PSI_INTERFACE +#else +#include <mysql/service_logger.h> #include "../../mysys/file_logger.c" +#endif #endif /*!MARIADB_ONLY*/ +#undef flogger_mutex_init +#undef flogger_mutex_destroy +#undef flogger_mutex_lock +#undef flogger_mutex_unlock + +#define flogger_mutex_init(A,B,C) pthread_mutex_init(mysql_mutex_real_mutex(B), C) +#define flogger_mutex_destroy(A) pthread_mutex_destroy(mysql_mutex_real_mutex(A)) +#define flogger_mutex_lock(A) pthread_mutex_lock(mysql_mutex_real_mutex(A)) +#define flogger_mutex_unlock(A) pthread_mutex_unlock(mysql_mutex_real_mutex(A)) + #ifndef DBUG_OFF #define PLUGIN_DEBUG_VERSION "-debug" #else @@ -176,7 +279,11 @@ static char *default_home= (char *)"."; extern char server_version[]; static const char *serv_ver= NULL; static int started_mysql= 0; +static int mysql_57_started= 0; +static int debug_server_started= 0; +static int use_event_data_for_disconnect= 0; static int started_mariadb= 0; +static int maria_55_started= 0; static int maria_above_5= 0; static char *incl_users, *excl_users, *file_path, *syslog_info; @@ -201,6 +308,27 @@ static char servhost[256]; static size_t servhost_len; static char *syslog_ident; static char syslog_ident_buffer[128]= "mysql-server_auditing"; + +struct connection_info +{ + int header; + unsigned long thread_id; + unsigned long long query_id; + char db[256]; + int db_length; + char user[64]; + int user_length; + char host[64]; + int host_length; + char ip[64]; + int ip_length; + const char *query; + int query_length; + char query_buffer[1024]; + time_t query_time; + int log_always; +}; + #define DEFAULT_FILENAME_LEN 16 static char default_file_name[DEFAULT_FILENAME_LEN+1]= "server_audit.log"; @@ -254,7 +382,8 @@ static TYPELIB events_typelib= array_elements(event_names) - 1, "", event_names, NULL }; static MYSQL_SYSVAR_SET(events, events, PLUGIN_VAR_RQCMDARG, - "Specifies the set of events to monitor. Can be CONNECT, QUERY, TABLE, QUERY_DDL, QUERY_DML.", + "Specifies the set of events to monitor. Can be CONNECT, QUERY, TABLE," + " QUERY_DDL, QUERY_DML, QUERY_DCL.", NULL, NULL, 0, &events_typelib); #define OUTPUT_SYSLOG 0 #define OUTPUT_FILE 1 @@ -295,6 +424,13 @@ static MYSQL_SYSVAR_UINT(query_log_limit, query_log_limit, PLUGIN_VAR_OPCMDARG, "Limit on the length of the query string in a record.", NULL, NULL, 1024, 0, 0x7FFFFFFF, 1); +char locinfo_ini_value[sizeof(struct connection_info)+4]; + +static MYSQL_THDVAR_STR(loc_info, + PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC, + "Auxiliary info.", NULL, NULL, + locinfo_ini_value); + static const char *syslog_facility_names[]= { "LOG_USER", "LOG_MAIL", "LOG_DAEMON", "LOG_AUTH", @@ -374,6 +510,7 @@ static struct st_mysql_sys_var* vars[] = { MYSQL_SYSVAR(syslog_facility), MYSQL_SYSVAR(syslog_priority), MYSQL_SYSVAR(query_log_limit), + MYSQL_SYSVAR(loc_info), NULL }; @@ -384,6 +521,8 @@ static long log_write_failures= 0; static char current_log_buf[FN_REFLEN]= ""; static char last_error_buf[512]= ""; +extern void *mysql_v4_descriptor; + static struct st_mysql_show_var audit_status[]= { {"server_audit_active", (char *)&is_active, SHOW_BOOL}, @@ -396,10 +535,14 @@ static struct st_mysql_show_var audit_status[]= #if defined(HAVE_PSI_INTERFACE) && !defined(FLOGGER_NO_PSI) /* These belong to the service initialization */ static PSI_mutex_key key_LOCK_operations; +static PSI_mutex_key key_LOCK_bigbuffer; static PSI_mutex_info mutex_key_list[]= -{{ &key_LOCK_operations, "SERVER_AUDIT_plugin::lock_operations", -{{ &key_LOCK_bigbuffer, "SERVER_AUDIT_plugin::lock_bigbuffer", - PSI_FLAG_GLOBAL}}; +{ + { &key_LOCK_operations, "SERVER_AUDIT_plugin::lock_operations", + PSI_FLAG_GLOBAL}, + { &key_LOCK_bigbuffer, "SERVER_AUDIT_plugin::lock_bigbuffer", + PSI_FLAG_GLOBAL} +}; #endif static mysql_mutex_t lock_operations; static mysql_mutex_t lock_bigbuffer; @@ -423,7 +566,7 @@ static uchar *getkey_user(const char *entry, size_t *length, } -static void blank_user(uchar *user) +static void blank_user(char *user) { for (; *user && *user != ','; user++) *user= ' '; @@ -483,19 +626,98 @@ static void remove_blanks(char *user) } -static int user_hash_fill(HASH *h, char *users, - HASH *cmp_hash, int take_over_cmp) +struct user_name +{ + int name_len; + char *name; +}; + + +struct user_coll +{ + int n_users; + struct user_name *users; + int n_alloced; +}; + + +static void coll_init(struct user_coll *c) +{ + c->n_users= 0; + c->users= 0; + c->n_alloced= 0; +} + + +static void coll_free(struct user_coll *c) +{ + if (c->users) + { + free(c->users); + coll_init(c); + } +} + + +static int cmp_users(const void *ia, const void *ib) +{ + const struct user_name *a= (const struct user_name *) ia; + const struct user_name *b= (const struct user_name *) ib; + int dl= a->name_len - b->name_len; + if (dl != 0) + return dl; + + return strncmp(a->name, b->name, a->name_len); +} + + +static char *coll_search(struct user_coll *c, const char *n, int len) +{ + struct user_name un; + struct user_name *found; + un.name_len= len; + un.name= (char *) n; + found= (struct user_name*) bsearch(&un, c->users, c->n_users, + sizeof(c->users[0]), cmp_users); + return found ? found->name : 0; +} + + +static int coll_insert(struct user_coll *c, char *n, int len) +{ + if (c->n_users >= c->n_alloced) + { + c->n_alloced+= 128; + if (c->users == NULL) + c->users= malloc(c->n_alloced * sizeof(c->users[0])); + else + c->users= realloc(c->users, c->n_alloced * sizeof(c->users[0])); + + if (c->users == NULL) + return 1; + } + c->users[c->n_users].name= n; + c->users[c->n_users].name_len= len; + c->n_users++; + return 0; +} + + +static void coll_sort(struct user_coll *c) +{ + qsort(c->users, c->n_users, sizeof(c->users[0]), cmp_users); +} + + +static int user_coll_fill(struct user_coll *c, char *users, + struct user_coll *cmp_c, int take_over_cmp) { char *orig_users= users; - uchar *cmp_user= 0; + char *cmp_user= 0; size_t cmp_length; - int refill_cmp_hash= 0; + int refill_cmp_coll= 0; - if (my_hash_inited(h)) - my_hash_reset(h); - else - loc_my_hash_init(h, 0, &my_charset_bin, 0x100, 0, 0, - (my_hash_get_key) getkey_user, 0, 0, 0); + c->n_users= 0; while (*users) { @@ -504,11 +726,10 @@ static int user_hash_fill(HASH *h, char *users, if (!*users) return 0; - - if (cmp_hash) + (void) getkey_user(users, &cmp_length, FALSE); + if (cmp_c) { - (void) getkey_user(users, &cmp_length, FALSE); - cmp_user= my_hash_search(cmp_hash, (const uchar *) users, cmp_length); + cmp_user= coll_search(cmp_c, users, cmp_length); if (cmp_user && take_over_cmp) { @@ -518,7 +739,7 @@ static int user_hash_fill(HASH *h, char *users, MYF(ME_JUST_WARNING), (int) cmp_length, users); internal_stop_logging= 0; blank_user(cmp_user); - refill_cmp_hash= 1; + refill_cmp_coll= 1; } else if (cmp_user) { @@ -530,7 +751,7 @@ static int user_hash_fill(HASH *h, char *users, continue; } } - if (my_hash_insert(h, (const uchar *) users)) + if (coll_insert(c, users, cmp_length)) return 1; while (*users && *users != ',') users++; @@ -539,15 +760,17 @@ static int user_hash_fill(HASH *h, char *users, users++; } - if (refill_cmp_hash) + if (refill_cmp_coll) { remove_blanks(excl_users); - return user_hash_fill(cmp_hash, excl_users, 0, 0); + return user_coll_fill(cmp_c, excl_users, 0, 0); } if (users > orig_users && users[-1] == ',') users[-1]= 0; + coll_sort(c); + return 0; } @@ -676,48 +899,19 @@ static void error_header() static LOGGER_HANDLE *logfile; -static HASH incl_user_hash, excl_user_hash; +static struct user_coll incl_user_coll, excl_user_coll; static unsigned long long query_counter= 1; -struct connection_info -{ - unsigned long thread_id; - unsigned long long query_id; - char db[256]; - int db_length; - char user[64]; - int user_length; - char host[64]; - int host_length; - char ip[64]; - int ip_length; - const char *query; - int query_length; - char query_buffer[1024]; - time_t query_time; - int log_always; -}; - -static HASH connection_hash; - - -struct connection_info *alloc_connection() -{ - return malloc(ALIGN_SIZE(sizeof(struct connection_info))); -} - - -void free_connection(void* pconn) +static struct connection_info *get_loc_info(MYSQL_THD thd) { - (void) free(pconn); + return (struct connection_info *) THDVAR(thd, loc_info); } -static struct connection_info *find_connection(unsigned long id) +static int ci_needs_setup(const struct connection_info *ci) { - return (struct connection_info *) - my_hash_search(&connection_hash, (const uchar *) &id, sizeof(id)); + return ci->header != 0; } @@ -881,15 +1075,24 @@ static int stop_logging() return 0; } -static struct connection_info * - add_connection(const struct mysql_event_connection *event) + +static void setup_connection_simple(struct connection_info *ci) +{ + ci->db_length= 0; + ci->user_length= 0; + ci->host_length= 0; + ci->ip_length= 0; + ci->query_length= 0; + ci->header= 0; +} + + +static void setup_connection_connect(struct connection_info *cn, + const struct mysql_event_connection *event) { - struct connection_info *cn= alloc_connection(); - if (!cn) - return 0; - cn->thread_id= event->thread_id; cn->query_id= 0; cn->log_always= 0; + cn->thread_id= event->thread_id; get_str_n(cn->db, &cn->db_length, sizeof(cn->db), event->database, event->database_length); get_str_n(cn->user, &cn->user_length, sizeof(cn->db), @@ -898,11 +1101,7 @@ static struct connection_info * event->host, event->host_length); get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip), event->ip, event->ip_length); - - if (my_hash_insert(&connection_hash, (const uchar *) cn)) - return 0; - - return cn; + cn->header= 0; } @@ -925,46 +1124,43 @@ do { \ -static struct connection_info * - add_connection_initdb(const struct mysql_event_general *event) +static void setup_connection_initdb(struct connection_info *cn, + const struct mysql_event_general *event) { - struct connection_info *cn; size_t user_len, host_len, ip_len; char uh_buffer[512]; - if (get_user_host(event->general_user, event->general_user_length, - uh_buffer, sizeof(uh_buffer), - &user_len, &host_len, &ip_len) || - (cn= alloc_connection()) == NULL) - return 0; - cn->thread_id= event->general_thread_id; cn->query_id= 0; cn->log_always= 0; get_str_n(cn->db, &cn->db_length, sizeof(cn->db), event->general_query, event->general_query_length); - get_str_n(cn->user, &cn->user_length, sizeof(cn->db), - uh_buffer, user_len); - get_str_n(cn->host, &cn->host_length, sizeof(cn->host), - uh_buffer+user_len+1, host_len); - get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip), - uh_buffer+user_len+1+host_len+1, ip_len); - if (my_hash_insert(&connection_hash, (const uchar *) cn)) - return 0; - - return cn; + if (get_user_host(event->general_user, event->general_user_length, + uh_buffer, sizeof(uh_buffer), + &user_len, &host_len, &ip_len)) + { + /* The user@host line is incorrect. */ + cn->user_length= 0; + cn->host_length= 0; + cn->ip_length= 0; + } + else + { + get_str_n(cn->user, &cn->user_length, sizeof(cn->db), + uh_buffer, user_len); + get_str_n(cn->host, &cn->host_length, sizeof(cn->host), + uh_buffer+user_len+1, host_len); + get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip), + uh_buffer+user_len+1+host_len+1, ip_len); + } + cn->header= 0; } -static struct connection_info * - add_connection_table(const struct mysql_event_table *event) +static void setup_connection_table(struct connection_info *cn, + const struct mysql_event_table *event) { - struct connection_info *cn; - - if ((cn= alloc_connection()) == NULL) - return 0; - cn->thread_id= event->thread_id; cn->query_id= query_counter++; cn->log_always= 0; @@ -976,42 +1172,40 @@ static struct connection_info * event->host, SAFE_STRLEN(event->host)); get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip), event->ip, SAFE_STRLEN(event->ip)); - - if (my_hash_insert(&connection_hash, (const uchar *) cn)) - return 0; - - return cn; + cn->header= 0; } -static struct connection_info * - add_connection_query(const struct mysql_event_general *event) +static void setup_connection_query(struct connection_info *cn, + const struct mysql_event_general *event) { - struct connection_info *cn; size_t user_len, host_len, ip_len; char uh_buffer[512]; - if (get_user_host(event->general_user, event->general_user_length, - uh_buffer, sizeof(uh_buffer), - &user_len, &host_len, &ip_len) || - (cn= alloc_connection()) == NULL) - return 0; - cn->thread_id= event->general_thread_id; cn->query_id= query_counter++; cn->log_always= 0; get_str_n(cn->db, &cn->db_length, sizeof(cn->db), "", 0); - get_str_n(cn->user, &cn->user_length, sizeof(cn->db), - uh_buffer, user_len); - get_str_n(cn->host, &cn->host_length, sizeof(cn->host), - uh_buffer+user_len+1, host_len); - get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip), - uh_buffer+user_len+1+host_len+1, ip_len); - - if (my_hash_insert(&connection_hash, (const uchar *) cn)) - return 0; - return cn; + if (get_user_host(event->general_user, event->general_user_length, + uh_buffer, sizeof(uh_buffer), + &user_len, &host_len, &ip_len)) + { + /* The user@host line is incorrect. */ + cn->user_length= 0; + cn->host_length= 0; + cn->ip_length= 0; + } + else + { + get_str_n(cn->user, &cn->user_length, sizeof(cn->db), + uh_buffer, user_len); + get_str_n(cn->host, &cn->host_length, sizeof(cn->host), + uh_buffer+user_len+1, host_len); + get_str_n(cn->ip, &cn->ip_length, sizeof(cn->ip), + uh_buffer+user_len+1+host_len+1, ip_len); + } + cn->header= 0; } @@ -1103,6 +1297,27 @@ static int log_connection(const struct connection_info *cn, } +static int log_connection_event(const struct mysql_event_connection *event, + const char *type) +{ + time_t ctime; + size_t csize; + char message[1024]; + + (void) time(&ctime); + csize= log_header(message, sizeof(message)-1, &ctime, + servhost, servhost_len, + event->user, event->user_length, + event->host, event->host_length, + event->ip, event->ip_length, + event->thread_id, 0, type); + csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize, + ",%.*s,,%d", event->database_length, event->database, event->status); + message[csize]= '\n'; + return write_log(message, csize + 1); +} + + static size_t escape_string(const char *str, unsigned int len, char *result, size_t result_len) { @@ -1248,11 +1463,11 @@ static int do_log_user(const char *name) return 0; len= strlen(name); - if (incl_user_hash.records) - return my_hash_search(&incl_user_hash, (const uchar *) name, len) != 0; + if (incl_user_coll.n_users) + return coll_search(&incl_user_coll, name, len) != 0; - if (excl_user_hash.records) - return my_hash_search(&excl_user_hash, (const uchar *) name, len) == 0; + if (excl_user_coll.n_users) + return coll_search(&excl_user_coll, name, len) == 0; return 1; } @@ -1590,14 +1805,14 @@ static void update_general_user(struct connection_info *cn, } +static struct connection_info ci_disconnect_buffer; + #define AA_FREE_CONNECTION 1 #define AA_CHANGE_USER 2 -static struct connection_info *update_connection_hash(unsigned int event_class, - const void *ev, - int *after_action) +static void update_connection_info(struct connection_info *cn, + unsigned int event_class, const void *ev, int *after_action) { - struct connection_info *cn= NULL; *after_action= 0; switch (event_class) { @@ -1610,13 +1825,17 @@ static struct connection_info *update_connection_hash(unsigned int event_class, { int init_db_command= event->general_command_length == 7 && strncmp(event->general_command, "Init DB", 7) == 0; - if ((cn= find_connection(event->general_thread_id))) + if (!ci_needs_setup(cn)) { if (init_db_command) { /* Change DB */ - get_str_n(cn->db, &cn->db_length, sizeof(cn->db), - event->general_query, event->general_query_length); + if (mysql_57_started) + get_str_n(cn->db, &cn->db_length, sizeof(cn->db), + event->database, event->database_length); + else + get_str_n(cn->db, &cn->db_length, sizeof(cn->db), + event->general_query, event->general_query_length); } cn->query_id= mode ? query_counter++ : event->query_id; cn->query= event->general_query; @@ -1625,18 +1844,19 @@ static struct connection_info *update_connection_hash(unsigned int event_class, update_general_user(cn, event); } else if (init_db_command) - cn= add_connection_initdb(event); + setup_connection_initdb(cn, event); else if (event_query_command(event)) - cn= add_connection_query(event); + setup_connection_query(cn, event); + else + setup_connection_simple(cn); break; } case MYSQL_AUDIT_GENERAL_STATUS: if (event_query_command(event)) { - if (!(cn= find_connection(event->general_thread_id)) && - !(cn= add_connection_query(event))) - return 0; + if (ci_needs_setup(cn)) + setup_connection_query(cn, event); if (mode == 0 && cn->db_length == 0 && event->database_length > 0) get_str_n(cn->db, &cn->db_length, sizeof(cn->db), @@ -1662,13 +1882,13 @@ static struct connection_info *update_connection_hash(unsigned int event_class, } break; case MYSQL_AUDIT_GENERAL_ERROR: - /* We need this because of a bug in the MariaDB */ - /* that it returns NULL query field for the */ - /* MYSQL_AUDIT_GENERAL_STATUS in the mysqld_stmt_prepare. */ - /* As a result we get empty QUERY field for errors. */ - if (!(cn= find_connection(event->general_thread_id)) && - !(cn= add_connection_query(event))) - return 0; + /* + We need this because the MariaDB returns NULL query field for the + MYSQL_AUDIT_GENERAL_STATUS in the mysqld_stmt_prepare. + As a result we get empty QUERY field for errors. + */ + if (ci_needs_setup(cn)) + setup_connection_query(cn, event); cn->query_id= mode ? query_counter++ : event->query_id; get_str_n(cn->query_buffer, &cn->query_length, sizeof(cn->query_buffer), event->general_query, event->general_query_length); @@ -1683,9 +1903,9 @@ static struct connection_info *update_connection_hash(unsigned int event_class, { const struct mysql_event_table *event = (const struct mysql_event_table *) ev; - if (!(cn= find_connection(event->thread_id)) && - !(cn= add_connection_table(event))) - return 0; + if (ci_needs_setup(cn)) + setup_connection_table(cn, event); + if (cn->user_length == 0 && cn->host_length == 0 && cn->ip_length == 0) { get_str_n(cn->user, &cn->user_length, sizeof(cn->user), @@ -1711,17 +1931,10 @@ static struct connection_info *update_connection_hash(unsigned int event_class, switch (event->event_subclass) { case MYSQL_AUDIT_CONNECTION_CONNECT: - cn= add_connection(ev); - break; - case MYSQL_AUDIT_CONNECTION_DISCONNECT: - cn= find_connection(event->thread_id); - if (cn) - *after_action= AA_FREE_CONNECTION; + setup_connection_connect(cn, event); break; case MYSQL_AUDIT_CONNECTION_CHANGE_USER: - cn= find_connection(event->thread_id); - if (cn) - *after_action= AA_CHANGE_USER; + *after_action= AA_CHANGE_USER; break; default:; } @@ -1730,17 +1943,17 @@ static struct connection_info *update_connection_hash(unsigned int event_class, default: break; } - return cn; } +struct connection_info cn_error_buffer; + + #define FILTER(MASK) (events == 0 || (events & MASK)) -static void auditing(MYSQL_THD thd __attribute__((unused)), - unsigned int event_class, - const void *ev) +void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev) { - struct connection_info *cn; - int after_action; + struct connection_info *cn= 0; + int after_action= 0; /* That one is important as this function can be called with */ /* &lock_operations locked when the server logs an error reported */ @@ -1750,8 +1963,35 @@ static void auditing(MYSQL_THD thd __attribute__((unused)), flogger_mutex_lock(&lock_operations); - if (!(cn= update_connection_hash(event_class, ev, &after_action))) - goto exit_func; + if (maria_55_started && debug_server_started && + event_class == MYSQL_AUDIT_GENERAL_CLASS) + { + /* + There's a bug in MariaDB 5.5 that prevents using thread local + variables in some cases. + The 'select * from notexisting_table;' query produces such case. + So just use the static buffer in this case. + */ + const struct mysql_event_general *event = + (const struct mysql_event_general *) ev; + + if (event->event_subclass == MYSQL_AUDIT_GENERAL_ERROR || + (event->event_subclass == MYSQL_AUDIT_GENERAL_STATUS && + event->general_query_length == 0 && + cn_error_buffer.query_id == event->query_id)) + { + cn= &cn_error_buffer; + cn->header= 1; + } + else + cn= get_loc_info(thd); + } + else + { + cn= get_loc_info(thd); + } + + update_connection_info(cn, event_class, ev, &after_action); if (!logging) goto exit_func; @@ -1765,8 +2005,11 @@ static void auditing(MYSQL_THD thd __attribute__((unused)), /* Only one subclass is logged. */ - if (event->event_subclass == MYSQL_AUDIT_GENERAL_STATUS) + if (event->event_subclass == MYSQL_AUDIT_GENERAL_STATUS && + event_query_command(event)) + { log_statement(cn, event, "QUERY"); + } } else if (event_class == MYSQL_AUDIT_TABLE_CLASS && FILTER(EVENT_TABLE) && cn) { @@ -1807,7 +2050,10 @@ static void auditing(MYSQL_THD thd __attribute__((unused)), log_connection(cn, event, event->status ? "FAILED_CONNECT": "CONNECT"); break; case MYSQL_AUDIT_CONNECTION_DISCONNECT: - log_connection(cn, event, "DISCONNECT"); + if (use_event_data_for_disconnect) + log_connection_event(event, "DISCONNECT"); + else + log_connection(&ci_disconnect_buffer, event, "DISCONNECT"); break; case MYSQL_AUDIT_CONNECTION_CHANGE_USER: log_connection(cn, event, "CHANGEUSER"); @@ -1822,10 +2068,6 @@ exit_func: if (after_action) { switch (after_action) { - case AA_FREE_CONNECTION: - my_hash_delete(&connection_hash, (uchar *) cn); - cn= 0; - break; case AA_CHANGE_USER: { const struct mysql_event_connection *event = @@ -1843,28 +2085,6 @@ exit_func: } -#ifdef DBUG_OFF - #ifdef __x86_64__ -static const int cmd_off= 4200; -static const int db_off= 120; -static const int db_len_off= 128; - #else -static const int cmd_off= 2668; -static const int db_off= 60; -static const int db_len_off= 64; - #endif /*x86_64*/ -#else - #ifdef __x86_64__ -static const int cmd_off= 4432; -static const int db_off= 120; -static const int db_len_off= 128; - #else -static const int cmd_off= 2808; -static const int db_off= 64; -static const int db_len_off= 68; - #endif /*x86_64*/ -#endif /*DBUG_OFF*/ - struct mysql_event_general_v8 { unsigned int event_class; @@ -1882,8 +2102,31 @@ struct mysql_event_general_v8 unsigned long long general_rows; }; + static void auditing_v8(MYSQL_THD thd, struct mysql_event_general_v8 *ev_v8) { +#ifdef DBUG_OFF + #ifdef __x86_64__ + static const int cmd_off= 4200; + static const int db_off= 120; + static const int db_len_off= 128; + #else + static const int cmd_off= 2668; + static const int db_off= 60; + static const int db_len_off= 64; + #endif /*x86_64*/ +#else + #ifdef __x86_64__ + static const int cmd_off= 4432; + static const int db_off= 120; + static const int db_len_off= 128; + #else + static const int cmd_off= 2808; + static const int db_off= 64; + static const int db_len_off= 68; + #endif /*x86_64*/ +#endif /*DBUG_OFF*/ + struct mysql_event_general event; if (ev_v8->event_class != MYSQL_AUDIT_GENERAL_CLASS) @@ -1942,6 +2185,41 @@ static void auditing_v13(MYSQL_THD thd, unsigned int *ev_v0) } +int get_db_mysql57(MYSQL_THD thd, char **name, int *len) +{ + int db_off; + int db_len_off; + if (debug_server_started) + { +#ifdef __x86_64__ + db_off= 608; + db_len_off= 616; +#else + db_off= 0; + db_len_off= 0; +#endif /*x86_64*/ + } + else + { +#ifdef __x86_64__ + db_off= 536; + db_len_off= 544; +#else + db_off= 0; + db_len_off= 0; +#endif /*x86_64*/ + } + +#ifdef __linux__ + *name= *(char **) (((char *) thd) + db_off); + *len= *((int *) (((char*) thd) + db_len_off)); + if (*name && (*name)[*len] != 0) + return 1; + return 0; +#else + return 1; +#endif +} /* As it's just too difficult to #include "sql_class.h", let's just copy the necessary part of the system_variables @@ -2068,8 +2346,8 @@ static int server_audit_init(void *p __attribute__((unused))) flogger_mutex_init(key_LOCK_operations, &lock_operations, MY_MUTEX_INIT_FAST); flogger_mutex_init(key_LOCK_operations, &lock_bigbuffer, MY_MUTEX_INIT_FAST); - my_hash_clear(&incl_user_hash); - my_hash_clear(&excl_user_hash); + coll_init(&incl_user_coll); + coll_init(&excl_user_coll); if (incl_users) { @@ -2087,9 +2365,6 @@ static int server_audit_init(void *p __attribute__((unused))) update_excl_users(NULL, NULL, NULL, &excl_users); } - loc_my_hash_init(&connection_hash, 0, &my_charset_bin, 0x100, 0, - sizeof(unsigned long), 0, 0, free_connection, 0); - error_header(); fprintf(stderr, "MariaDB Audit Plugin version %s%s STARTED.\n", PLUGIN_STR_VERSION, PLUGIN_DEBUG_VERSION); @@ -2113,6 +2388,16 @@ static int server_audit_init(void *p __attribute__((unused))) } } + ci_disconnect_buffer.header= 10; + ci_disconnect_buffer.thread_id= 0; + ci_disconnect_buffer.query_id= 0; + ci_disconnect_buffer.db_length= 0; + ci_disconnect_buffer.user_length= 0; + ci_disconnect_buffer.host_length= 0; + ci_disconnect_buffer.ip_length= 0; + ci_disconnect_buffer.query= empty_str; + ci_disconnect_buffer.query_length= 0; + if (logging) start_logging(); @@ -2131,13 +2416,8 @@ static int server_audit_init_mysql(void *p) static int server_audit_deinit(void *p __attribute__((unused))) { - if (my_hash_inited(&incl_user_hash)) - my_hash_free(&incl_user_hash); - - if (my_hash_inited(&excl_user_hash)) - my_hash_free(&excl_user_hash); - - my_hash_free(&connection_hash); + coll_free(&incl_user_coll); + coll_free(&excl_user_coll); if (output_type == OUTPUT_FILE && logfile) logger_close(logfile); @@ -2172,6 +2452,7 @@ static struct st_mysql_audit mysql_descriptor = { MYSQL_AUDIT_GENERAL_CLASSMASK | MYSQL_AUDIT_CONNECTION_CLASSMASK } }; + mysql_declare_plugin(server_audit) { MYSQL_AUDIT_PLUGIN, @@ -2222,22 +2503,21 @@ maria_declare_plugin_end; static void mark_always_logged(MYSQL_THD thd) { struct connection_info *cn; - if (thd && (cn= find_connection(thd_get_thread_id(thd)))) + if (thd && (cn= get_loc_info(thd))) cn->log_always= 1; } static void log_current_query(MYSQL_THD thd) { - unsigned long thd_id; struct connection_info *cn; - if (!thd || - !(cn= find_connection((thd_id= thd_get_thread_id(thd))))) + if (!thd) return; - if (FILTER(EVENT_QUERY) && do_log_user(cn->user)) + cn= get_loc_info(thd); + if (!ci_needs_setup(cn) && FILTER(EVENT_QUERY) && do_log_user(cn->user)) { - log_statement_ex(cn, cn->query_time, thd_id, cn->query, cn->query_length, - 0, "QUERY"); + log_statement_ex(cn, cn->query_time, thd_get_thread_id(thd), + cn->query, cn->query_length, 0, "QUERY"); cn->log_always= 1; } } @@ -2249,7 +2529,8 @@ static void update_file_path(MYSQL_THD thd, { char *new_name= (*(char **) save) ? *(char **) save : empty_str; - flogger_mutex_lock(&lock_operations); + if (!maria_55_started || !debug_server_started) + flogger_mutex_lock(&lock_operations); internal_stop_logging= 1; error_header(); fprintf(stderr, "Log file name was changed to '%s'.\n", new_name); @@ -2285,7 +2566,8 @@ static void update_file_path(MYSQL_THD thd, file_path= path_buffer; exit_func: internal_stop_logging= 0; - flogger_mutex_unlock(&lock_operations); + if (!maria_55_started || !debug_server_started) + flogger_mutex_unlock(&lock_operations); } @@ -2329,14 +2611,16 @@ static void update_incl_users(MYSQL_THD thd, void *var_ptr __attribute__((unused)), const void *save) { char *new_users= (*(char **) save) ? *(char **) save : empty_str; - flogger_mutex_lock(&lock_operations); + if (!maria_55_started || !debug_server_started) + flogger_mutex_lock(&lock_operations); mark_always_logged(thd); strncpy(incl_user_buffer, new_users, sizeof(incl_user_buffer)); incl_users= incl_user_buffer; - user_hash_fill(&incl_user_hash, incl_users, &excl_user_hash, 1); + user_coll_fill(&incl_user_coll, incl_users, &excl_user_coll, 1); error_header(); fprintf(stderr, "server_audit_incl_users set to '%s'.\n", incl_users); - flogger_mutex_unlock(&lock_operations); + if (!maria_55_started || !debug_server_started) + flogger_mutex_unlock(&lock_operations); } @@ -2345,14 +2629,16 @@ static void update_excl_users(MYSQL_THD thd __attribute__((unused)), void *var_ptr __attribute__((unused)), const void *save) { char *new_users= (*(char **) save) ? *(char **) save : empty_str; - flogger_mutex_lock(&lock_operations); + if (!maria_55_started || !debug_server_started) + flogger_mutex_lock(&lock_operations); mark_always_logged(thd); strncpy(excl_user_buffer, new_users, sizeof(excl_user_buffer)); excl_users= excl_user_buffer; - user_hash_fill(&excl_user_hash, excl_users, &incl_user_hash, 0); + user_coll_fill(&excl_user_coll, excl_users, &incl_user_coll, 0); error_header(); fprintf(stderr, "server_audit_excl_users set to '%s'.\n", excl_users); - flogger_mutex_unlock(&lock_operations); + if (!maria_55_started || !debug_server_started) + flogger_mutex_unlock(&lock_operations); } @@ -2428,7 +2714,8 @@ static void update_logging(MYSQL_THD thd, if (new_logging == logging) return; - flogger_mutex_lock(&lock_operations); + if (!maria_55_started || !debug_server_started) + flogger_mutex_lock(&lock_operations); internal_stop_logging= 1; if ((logging= new_logging)) { @@ -2445,7 +2732,8 @@ static void update_logging(MYSQL_THD thd, } internal_stop_logging= 0; - flogger_mutex_unlock(&lock_operations); + if (!maria_55_started || !debug_server_started) + flogger_mutex_unlock(&lock_operations); } @@ -2457,14 +2745,16 @@ static void update_mode(MYSQL_THD thd __attribute__((unused)), if (mode_readonly || new_mode == mode) return; - flogger_mutex_lock(&lock_operations); + if (!maria_55_started || !debug_server_started) + flogger_mutex_lock(&lock_operations); internal_stop_logging= 1; mark_always_logged(thd); error_header(); fprintf(stderr, "Logging mode was changed from %d to %d.\n", mode, new_mode); mode= new_mode; internal_stop_logging= 0; - flogger_mutex_unlock(&lock_operations); + if (!maria_55_started || !debug_server_started) + flogger_mutex_unlock(&lock_operations); } @@ -2488,6 +2778,13 @@ static void update_syslog_ident(MYSQL_THD thd __attribute__((unused)), } +struct st_my_thread_var *loc_thread_var(void) +{ + return 0; +} + + + #ifdef _WIN32 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { @@ -2505,9 +2802,18 @@ void __attribute__ ((constructor)) audit_plugin_so_init(void) goto exit; started_mariadb= strstr(serv_ver, "MariaDB") != 0; + debug_server_started= strstr(serv_ver, "debug") != 0; - if (!started_mariadb) + if (started_mariadb) { + if (serv_ver[0] == '1') + use_event_data_for_disconnect= 1; + else + maria_55_started= 1; + } + else + { + /* Started MySQL. */ if (serv_ver[0] == '5' && serv_ver[2] == '5') { int sc= serv_ver[4] - '0'; @@ -2524,7 +2830,25 @@ void __attribute__ ((constructor)) audit_plugin_so_init(void) mysql_descriptor.event_notify= (void *) auditing_v13; } } + else if (serv_ver[0] == '5' && serv_ver[2] == '6') + { + int sc= serv_ver[4] - '0'; + if (serv_ver[5] >= '0' && serv_ver[5] <= '9') + sc= sc * 10 + serv_ver[5] - '0'; + if (sc >= 24) + use_event_data_for_disconnect= 1; + } + else if (serv_ver[0] == '5' && serv_ver[2] == '7') + { + mysql_57_started= 1; + _mysql_plugin_declarations_[0].info= mysql_v4_descriptor; + use_event_data_for_disconnect= 1; + } } + + memset(locinfo_ini_value, 'O', sizeof(locinfo_ini_value)-1); + locinfo_ini_value[sizeof(locinfo_ini_value)-1]= 0; + exit: #ifdef _WIN32 return 1; diff --git a/plugin/server_audit/test_audit_v4.c b/plugin/server_audit/test_audit_v4.c new file mode 100644 index 00000000000..ae7527f8449 --- /dev/null +++ b/plugin/server_audit/test_audit_v4.c @@ -0,0 +1,162 @@ +#define PLUGIN_CONTEXT + +#include <stdio.h> + +typedef void *MYSQL_THD; +struct st_mysql_const_lex_string +{ + const char *str; + size_t length; +}; +typedef struct st_mysql_const_lex_string MYSQL_LEX_CSTRING; +enum enum_sql_command{ SQLCOM_A, SQLCOM_B }; +enum enum_server_command{ SERVCOM_A, SERVCOM_B }; + +#include "plugin_audit_v4.h" + +extern void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev); +extern int get_db_mysql57(MYSQL_THD thd, char **name, int *len); + + +struct mysql_event_general_302 +{ + unsigned int event_subclass; + int general_error_code; + unsigned long general_thread_id; + const char *general_user; + unsigned int general_user_length; + const char *general_command; + unsigned int general_command_length; + const char *general_query; + unsigned int general_query_length; + struct charset_info_st *general_charset; + unsigned long long general_time; + unsigned long long general_rows; + unsigned long long query_id; + char *database; + int database_length; +}; + + +static int auditing_v4(MYSQL_THD thd, mysql_event_class_t class, const void *ev) +{ + int *subclass= (int *)ev; + struct mysql_event_general_302 ev_302; + int subclass_v3, subclass_orig; + + if (class != MYSQL_AUDIT_GENERAL_CLASS && + class != MYSQL_AUDIT_CONNECTION_CLASS) + return 0; + + subclass_orig= *subclass; + + if (class == MYSQL_AUDIT_GENERAL_CLASS) + { + struct mysql_event_general *event= (struct mysql_event_general *) ev; + ev_302.general_error_code= event->general_error_code; + ev_302.general_thread_id= event->general_thread_id; + ev_302.general_user= event->general_user.str; + ev_302.general_user_length= event->general_user.length; + ev_302.general_command= event->general_command.str; + ev_302.general_command_length= event->general_command.length; + ev_302.general_query= event->general_query.str; + ev_302.general_query_length= event->general_query.length; + ev_302.general_charset= event->general_charset; + ev_302.general_time= event->general_time; + ev_302.general_rows= event->general_rows; + if (get_db_mysql57(thd, &ev_302.database, &ev_302.database_length)) + { + ev_302.database= 0; + ev_302.database_length= 0; + } + ev= &ev_302; + switch (subclass_orig) + { + case MYSQL_AUDIT_GENERAL_LOG: + subclass_v3= 0; + ev_302.event_subclass= 0; + break; + case MYSQL_AUDIT_GENERAL_ERROR: + subclass_v3= 1; + ev_302.event_subclass= 1; + break; + case MYSQL_AUDIT_GENERAL_RESULT: + subclass_v3= 2; + ev_302.event_subclass= 2; + break; + case MYSQL_AUDIT_GENERAL_STATUS: + { + subclass_v3= 3; + ev_302.event_subclass= 3; + break; + } + default: + return 0; + } + } + else /* if (class == MYSQL_AUDIT_CONNECTION_CLASS) */ + { + switch (subclass_orig) + { + case MYSQL_AUDIT_CONNECTION_CONNECT: + subclass_v3= 0; + break; + case MYSQL_AUDIT_CONNECTION_DISCONNECT: + subclass_v3= 1; + break; + default: + return 0; + } + } + + *subclass= subclass_v3; + + auditing(thd, (int) class, ev); + + *subclass= subclass_orig; + return 0; +} + + +static struct st_mysql_audit mysql_descriptor = +{ + MYSQL_AUDIT_INTERFACE_VERSION, + NULL, + auditing_v4, + { (unsigned long) MYSQL_AUDIT_GENERAL_ALL, + (unsigned long) MYSQL_AUDIT_CONNECTION_ALL, + (unsigned long) MYSQL_AUDIT_PARSE_ALL, + 0, /* This event class is currently not supported. */ + 0, /* This event class is currently not supported. */ + (unsigned long) MYSQL_AUDIT_GLOBAL_VARIABLE_ALL, + (unsigned long) MYSQL_AUDIT_SERVER_STARTUP_ALL, + (unsigned long) MYSQL_AUDIT_SERVER_SHUTDOWN_ALL, + (unsigned long) MYSQL_AUDIT_COMMAND_ALL, + (unsigned long) MYSQL_AUDIT_QUERY_ALL, + (unsigned long) MYSQL_AUDIT_STORED_PROGRAM_ALL } +#ifdef WHEN_MYSQL_BUG_FIXED + /* + By this moment MySQL just sends no notifications at all + when we request only those we actually need. + So we have to request everything and filter them inside the + handling function. + */ + { (unsigned long) MYSQL_AUDIT_GENERAL_ALL, + (unsigned long) (MYSQL_AUDIT_CONNECTION_CONNECT | + MYSQL_AUDIT_CONNECTION_DISCONNECT), + 0, + 0, /* This event class is currently not supported. */ + 0, /* This event class is currently not supported. */ + 0, + 0, + 0, + 0, + 0, + 0 + } +#endif /*WHEN_MYSQL_BUG_FIXED*/ +}; + + +void *mysql_v4_descriptor= &mysql_descriptor; + diff --git a/plugin/simple_password_check/simple_password_check.c b/plugin/simple_password_check/simple_password_check.c index dadaa0191a2..7ad8bfc811a 100644 --- a/plugin/simple_password_check/simple_password_check.c +++ b/plugin/simple_password_check/simple_password_check.c @@ -49,15 +49,18 @@ static int validate(MYSQL_LEX_STRING *username, MYSQL_LEX_STRING *password) others < min_others; } -static void fix_min_length(MYSQL_THD thd __attribute__((unused)), - struct st_mysql_sys_var *var, - void *var_ptr, const void *save) + +static void +fix_min_length(MYSQL_THD thd __attribute__((unused)), + struct st_mysql_sys_var *var __attribute__((unused)), + void *var_ptr, const void *save) { *((unsigned int *)var_ptr)= *((unsigned int *)save); if (min_length < min_digits + 2 * min_letters + min_others) min_length= min_digits + 2 * min_letters + min_others; } + static MYSQL_SYSVAR_UINT(minimal_length, min_length, PLUGIN_VAR_RQCMDARG, "Minimal required password length", NULL, fix_min_length, 8, 0, 1000, 1); @@ -101,6 +104,6 @@ maria_declare_plugin(simple_password_check) NULL, sysvars, "1.0", - MariaDB_PLUGIN_MATURITY_ALPHA, + MariaDB_PLUGIN_MATURITY_GAMMA } maria_declare_plugin_end; diff --git a/plugin/sql_errlog/sql_errlog.c b/plugin/sql_errlog/sql_errlog.c index 1c7e141c022..6ec4659d407 100644 --- a/plugin/sql_errlog/sql_errlog.c +++ b/plugin/sql_errlog/sql_errlog.c @@ -158,6 +158,6 @@ maria_declare_plugin(sql_errlog) NULL, vars, "1.0", - MariaDB_PLUGIN_MATURITY_GAMMA + MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; diff --git a/plugin/user_variables/CMakeLists.txt b/plugin/user_variables/CMakeLists.txt new file mode 100644 index 00000000000..b9ec7d18ba1 --- /dev/null +++ b/plugin/user_variables/CMakeLists.txt @@ -0,0 +1 @@ +MYSQL_ADD_PLUGIN(user_variables user_variables.cc) diff --git a/plugin/user_variables/mysql-test/user_variables/basic.result b/plugin/user_variables/mysql-test/user_variables/basic.result new file mode 100644 index 00000000000..02de31b5e09 --- /dev/null +++ b/plugin/user_variables/mysql-test/user_variables/basic.result @@ -0,0 +1,63 @@ +SELECT PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_STATUS, PLUGIN_TYPE, PLUGIN_AUTHOR, PLUGIN_DESCRIPTION, PLUGIN_LICENSE, LOAD_OPTION, PLUGIN_MATURITY FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME='user_variables'; +PLUGIN_NAME user_variables +PLUGIN_VERSION 1.0 +PLUGIN_STATUS ACTIVE +PLUGIN_TYPE INFORMATION SCHEMA +PLUGIN_AUTHOR Sergey Vojtovich +PLUGIN_DESCRIPTION User-defined variables +PLUGIN_LICENSE GPL +LOAD_OPTION ON +PLUGIN_MATURITY Alpha +SHOW CREATE TABLE INFORMATION_SCHEMA.USER_VARIABLES; +Table Create Table +user_variables CREATE TEMPORARY TABLE `user_variables` ( + `VARIABLE_NAME` varchar(64) NOT NULL DEFAULT '', + `VARIABLE_VALUE` varchar(2048) DEFAULT NULL, + `VARIABLE_TYPE` varchar(64) NOT NULL DEFAULT '', + `CHARACTER_SET_NAME` varchar(32) DEFAULT NULL +) ENGINE=MEMORY DEFAULT CHARSET=utf8 +FLUSH USER_VARIABLES; +SELECT COUNT(*) FROM INFORMATION_SCHEMA.USER_VARIABLES; +COUNT(*) +0 +SET @int_var=1; +SET @uint_var=CAST(2 AS UNSIGNED INTEGER); +SET @str_var='Value of string variable'; +SET @utf8str_var=_utf8 'UTF8 string value'; +SET @double_var=CAST(1 AS DOUBLE); +SET @dec_var=CAST(1 AS DECIMAL(20, 10)); +SET @time_var=CAST('2016-02-25' AS DATE); +SET @' @#^%'='Value of variable with odd name'; +SET @''='Value of variable with empty name'; +SET @null_var=NULL; +SELECT COUNT(*) FROM INFORMATION_SCHEMA.USER_VARIABLES; +COUNT(*) +10 +SELECT * FROM INFORMATION_SCHEMA.USER_VARIABLES ORDER BY VARIABLE_NAME; +VARIABLE_NAME VARIABLE_VALUE VARIABLE_TYPE CHARACTER_SET_NAME + Value of variable with empty name VARCHAR latin1 + @#^% Value of variable with odd name VARCHAR latin1 +dec_var 1.0000000000 DECIMAL latin1 +double_var 1 DOUBLE latin1 +int_var 1 INT latin1 +null_var NULL VARCHAR binary +str_var Value of string variable VARCHAR latin1 +time_var 2016-02-25 VARCHAR latin1 +uint_var 2 INT UNSIGNED latin1 +utf8str_var UTF8 string value VARCHAR utf8 +SHOW USER_VARIABLES; +Variable_name Value + Value of variable with empty name + @#^% Value of variable with odd name +dec_var 1.0000000000 +double_var 1 +int_var 1 +null_var NULL +str_var Value of string variable +time_var 2016-02-25 +uint_var 2 +utf8str_var UTF8 string value +FLUSH USER_VARIABLES; +SELECT COUNT(*) FROM INFORMATION_SCHEMA.USER_VARIABLES; +COUNT(*) +0 diff --git a/plugin/user_variables/mysql-test/user_variables/basic.test b/plugin/user_variables/mysql-test/user_variables/basic.test new file mode 100644 index 00000000000..7e67e4fa5af --- /dev/null +++ b/plugin/user_variables/mysql-test/user_variables/basic.test @@ -0,0 +1,24 @@ +query_vertical SELECT PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_STATUS, PLUGIN_TYPE, PLUGIN_AUTHOR, PLUGIN_DESCRIPTION, PLUGIN_LICENSE, LOAD_OPTION, PLUGIN_MATURITY FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME='user_variables'; +SHOW CREATE TABLE INFORMATION_SCHEMA.USER_VARIABLES; + +FLUSH USER_VARIABLES; +SELECT COUNT(*) FROM INFORMATION_SCHEMA.USER_VARIABLES; + +SET @int_var=1; +SET @uint_var=CAST(2 AS UNSIGNED INTEGER); +SET @str_var='Value of string variable'; +SET @utf8str_var=_utf8 'UTF8 string value'; +SET @double_var=CAST(1 AS DOUBLE); +SET @dec_var=CAST(1 AS DECIMAL(20, 10)); +SET @time_var=CAST('2016-02-25' AS DATE); +SET @' @#^%'='Value of variable with odd name'; +SET @''='Value of variable with empty name'; +SET @null_var=NULL; + +SELECT COUNT(*) FROM INFORMATION_SCHEMA.USER_VARIABLES; +SELECT * FROM INFORMATION_SCHEMA.USER_VARIABLES ORDER BY VARIABLE_NAME; +--sorted_result +SHOW USER_VARIABLES; + +FLUSH USER_VARIABLES; +SELECT COUNT(*) FROM INFORMATION_SCHEMA.USER_VARIABLES; diff --git a/plugin/user_variables/mysql-test/user_variables/suite.opt b/plugin/user_variables/mysql-test/user_variables/suite.opt new file mode 100644 index 00000000000..6140014d569 --- /dev/null +++ b/plugin/user_variables/mysql-test/user_variables/suite.opt @@ -0,0 +1 @@ +--plugin-load-add=$USER_VARIABLES_SO --plugin-user-variables=ON diff --git a/plugin/user_variables/mysql-test/user_variables/suite.pm b/plugin/user_variables/mysql-test/user_variables/suite.pm new file mode 100644 index 00000000000..ae757eedee4 --- /dev/null +++ b/plugin/user_variables/mysql-test/user_variables/suite.pm @@ -0,0 +1,13 @@ +package My::Suite::User_variables; + +@ISA = qw(My::Suite); + +return "No USER_VARIABLES plugin" unless + $ENV{USER_VARIABLES_SO} or + $::mysqld_variables{'user-variables'} eq "ON"; + +return "Not run for embedded server" if $::opt_embedded_server; + +sub is_default { 1 } + +bless { }; diff --git a/plugin/user_variables/user_variables.cc b/plugin/user_variables/user_variables.cc new file mode 100644 index 00000000000..c6c48d09303 --- /dev/null +++ b/plugin/user_variables/user_variables.cc @@ -0,0 +1,139 @@ +/* Copyright (C) 2016 MariaDB Foundation and Sergey Vojtovich + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#define MYSQL_SERVER +#include <sql_class.h> +#include <table.h> +#include <sql_show.h> + + +static const LEX_CSTRING result_types[]= +{ + STRING_WITH_LEN("VARCHAR"), + STRING_WITH_LEN("DOUBLE"), + STRING_WITH_LEN("INT"), + STRING_WITH_LEN("<IMPOSSIBLE1>"), // ROW_RESULT + STRING_WITH_LEN("DECIMAL"), + STRING_WITH_LEN("<IMPOSSIBLE2>") // TIME_RESULT +}; + + +static const LEX_CSTRING unsigned_result_types[]= +{ + STRING_WITH_LEN("<IMPOSSIBLE3>"), // UNSIGNED STRING_RESULT + STRING_WITH_LEN("DOUBLE UNSIGNED"), + STRING_WITH_LEN("INT UNSIGNED"), + STRING_WITH_LEN("<IMPOSSIBLE4>"), // UNSIGNED ROW_RESULT + STRING_WITH_LEN("DECIMAL UNSIGNED"), + STRING_WITH_LEN("<IMPOSSIBLE5>") // UNSIGNED TIME_RESULT +}; + + +static ST_FIELD_INFO user_variables_fields_info[] = +{ + { "VARIABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Variable_name", 0 }, + { "VARIABLE_VALUE", 2048, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, "Value", 0 }, + { "VARIABLE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, 0 }, + { "CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, + MY_I_S_MAYBE_NULL, 0, 0 }, + { 0, 0, MYSQL_TYPE_NULL, 0, 0, 0, 0 } +}; + + +static int user_variables_fill(THD *thd, TABLE_LIST *tables, COND *cond) +{ + ulong i; + TABLE *table= tables->table; + Field **field= table->field; + String buff; + bool is_null; + + for (i= 0; i < thd->user_vars.records; i++) + { + user_var_entry *var= (user_var_entry*) my_hash_element(&thd->user_vars, i); + + field[0]->store(var->name.str, var->name.length, system_charset_info); + + if (var->val_str(&is_null, &buff, NOT_FIXED_DEC)) + { + field[1]->store(buff.ptr(), buff.length(), buff.charset()); + field[1]->set_notnull(); + } + else if (is_null) + field[1]->set_null(); + else + return 1; + + const LEX_CSTRING *tmp= var->unsigned_flag ? + &unsigned_result_types[var->type] : + &result_types[var->type]; + field[2]->store(tmp->str, tmp->length, system_charset_info); + + if (var->charset()) + { + field[3]->store(var->charset()->csname, strlen(var->charset()->csname), + system_charset_info); + field[3]->set_notnull(); + } + else + field[3]->set_null(); + + if (schema_table_store_record(thd, table)) + return 1; + } + return 0; +} + + +int user_variables_reset(void) +{ + THD *thd= current_thd; + if (thd) + my_hash_reset(&thd->user_vars); + return 0; +} + + +static int user_variables_init(void *p) +{ + ST_SCHEMA_TABLE *is= (ST_SCHEMA_TABLE *) p; + is->fields_info= user_variables_fields_info; + is->fill_table= user_variables_fill; + is->reset_table= user_variables_reset; + return 0; +} + + +static struct st_mysql_information_schema user_variables_descriptor= +{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; + + +maria_declare_plugin(user_variables) +{ + MYSQL_INFORMATION_SCHEMA_PLUGIN, + &user_variables_descriptor, + "user_variables", + "Sergey Vojtovich", + "User-defined variables", + PLUGIN_LICENSE_GPL, + user_variables_init, + NULL, + 0x0100, + NULL, + NULL, + "1.0", + MariaDB_PLUGIN_MATURITY_ALPHA +} +maria_declare_plugin_end; diff --git a/plugin/userstat/userstat.cc b/plugin/userstat/userstat.cc index 6ffee44f43c..69832f817c1 100644 --- a/plugin/userstat/userstat.cc +++ b/plugin/userstat/userstat.cc @@ -31,7 +31,7 @@ maria_declare_plugin(userstat) NULL, NULL, "2.0", - MariaDB_PLUGIN_MATURITY_GAMMA + MariaDB_PLUGIN_MATURITY_STABLE }, { MYSQL_INFORMATION_SCHEMA_PLUGIN, @@ -46,7 +46,7 @@ maria_declare_plugin(userstat) NULL, NULL, "2.0", - MariaDB_PLUGIN_MATURITY_GAMMA + MariaDB_PLUGIN_MATURITY_STABLE }, { MYSQL_INFORMATION_SCHEMA_PLUGIN, diff --git a/plugin/wsrep_info/plugin.cc b/plugin/wsrep_info/plugin.cc index f3de177c85f..b8aaee5a132 100644 --- a/plugin/wsrep_info/plugin.cc +++ b/plugin/wsrep_info/plugin.cc @@ -245,7 +245,7 @@ maria_declare_plugin(wsrep_info) NULL, /* Status variables */ NULL, /* System variables */ "1.0", /* Version (string) */ - MariaDB_PLUGIN_MATURITY_ALPHA /* Maturity */ + MariaDB_PLUGIN_MATURITY_GAMMA /* Maturity */ }, { MYSQL_INFORMATION_SCHEMA_PLUGIN, @@ -260,7 +260,7 @@ maria_declare_plugin(wsrep_info) NULL, /* Status variables */ NULL, /* System variables */ "1.0", /* Version (string) */ - MariaDB_PLUGIN_MATURITY_ALPHA /* Maturity */ + MariaDB_PLUGIN_MATURITY_GAMMA /* Maturity */ } maria_declare_plugin_end; diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 256797dc9d0..eeb44b75322 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -79,8 +79,6 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/mysql_performance_tables.sql ${CMAKE_CURRENT_SOURCE_DIR}/fill_help_tables.sql ${CMAKE_CURRENT_SOURCE_DIR}/mysql_test_data_timezone.sql - ${CMAKE_CURRENT_SOURCE_DIR}/maria_add_gis_sp.sql - ${CMAKE_CURRENT_SOURCE_DIR}/maria_add_gis_sp_bootstrap.sql ${FIX_PRIVILEGES_SQL} DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT Server ) @@ -287,6 +285,29 @@ ELSE() ENDFOREACH() ENDIF() +# Configure two scripts from one 'in' file. +# The maria_add_gis_sp.sql - to be sent to 'mysql' tool +# and the maria_add_gis_sp_bootstrap.sql, that can be sent to +# the server as a bootstrap command. + +SET(ADD_GIS_SP_SET_DELIMITER "delimiter |") +SET(ADD_GIS_SP_RESET_DELIMITER "delimiter ;") +SET(ADD_GIS_SP_EOL "|") +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/maria_add_gis_sp.sql.in + ${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp.sql ESCAPE_QUOTES @ONLY) + +SET(ADD_GIS_SP_SET_DELIMITER "") +SET(ADD_GIS_SP_RESET_DELIMITER "") +SET(ADD_GIS_SP_EOL ";") +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/maria_add_gis_sp.sql.in + ${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp_bootstrap.sql ESCAPE_QUOTES @ONLY) + +INSTALL_SCRIPT(${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp.sql + ${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp_bootstrap.sql + DESTINATION ${INSTALL_MYSQLSHAREDIR} + COMPONENT Server + ) + # Install libgcc as mylibgcc.a IF(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_FLAGS MATCHES "-static") EXECUTE_PROCESS ( diff --git a/scripts/maria_add_gis_sp.sql b/scripts/maria_add_gis_sp.sql deleted file mode 100644 index 8ddc7abd17f..00000000000 --- a/scripts/maria_add_gis_sp.sql +++ /dev/null @@ -1,48 +0,0 @@ --- Copyright (C) 2014 MariaDB Ab. --- --- This program is free software; you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- the Free Software Foundation; version 2 of the License. --- --- This program is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program; if not, write to the Free Software --- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - --- This part creates stored procedures required by the OpenGIS standards. --- Proc privilege is needed to run it. --- To use this file, load its contents into the mysql database like that: --- mysql -u root -p mysql < scripts/maria_add_gis_sp.sql - -SET sql_mode=''; - -DROP PROCEDURE IF EXISTS AddGeometryColumn; -DROP PROCEDURE IF EXISTS DropGeometryColumn; - -delimiter | - -CREATE PROCEDURE AddGeometryColumn(catalog varchar(64), t_schema varchar(64), - t_name varchar(64), geometry_column varchar(64), t_srid int) -begin - set @qwe= concat('ALTER TABLE ', t_schema, '.', t_name, ' ADD ', geometry_column,' GEOMETRY REF_SYSTEM_ID=', t_srid); - PREPARE ls from @qwe; - execute ls; - deallocate prepare ls; -end| - -CREATE PROCEDURE DropGeometryColumn(catalog varchar(64), t_schema varchar(64), - t_name varchar(64), geometry_column varchar(64)) -begin - set @qwe= concat('ALTER TABLE ', t_schema, '.', t_name, ' DROP ', geometry_column); - PREPARE ls from @qwe; - execute ls; - deallocate prepare ls; -end| - -delimiter ; - diff --git a/scripts/maria_add_gis_sp_bootstrap.sql b/scripts/maria_add_gis_sp.sql.in index 063b6650efd..1e2e513cd0a 100644 --- a/scripts/maria_add_gis_sp_bootstrap.sql +++ b/scripts/maria_add_gis_sp.sql.in @@ -18,17 +18,20 @@ SET sql_mode=''; +@ADD_GIS_SP_SET_DELIMITER@ + DROP PROCEDURE IF EXISTS AddGeometryColumn; DROP PROCEDURE IF EXISTS DropGeometryColumn; CREATE PROCEDURE AddGeometryColumn(catalog varchar(64), t_schema varchar(64), t_name varchar(64), geometry_column varchar(64), t_srid int) begin - set @qwe= concat('ALTER TABLE ', t_schema, '.', t_name, ' ADD ', geometry_column,' GEOMETRY REF_SYSTEM_ID=', t_srid); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end; + set @qwe= concat('ALTER TABLE ', t_schema, '.', t_name, ' ADD ', geometry_column,' GEOMETRY REF_SYSTEM_ID=', t_srid); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end @ADD_GIS_SP_EOL@ CREATE PROCEDURE DropGeometryColumn(catalog varchar(64), t_schema varchar(64), t_name varchar(64), geometry_column varchar(64)) begin - set @qwe= concat('ALTER TABLE ', t_schema, '.', t_name, ' DROP ', geometry_column); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end; + set @qwe= concat('ALTER TABLE ', t_schema, '.', t_name, ' DROP ', geometry_column); PREPARE ls from @qwe; execute ls; deallocate prepare ls; end @ADD_GIS_SP_EOL@ +@ADD_GIS_SP_RESET_DELIMITER@ diff --git a/scripts/mysqlaccess.sh b/scripts/mysqlaccess.sh index 6fc090ab972..a7cc2eccf38 100644 --- a/scripts/mysqlaccess.sh +++ b/scripts/mysqlaccess.sh @@ -441,7 +441,7 @@ use IPC::Open3; $DEBUG = 0; # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>8 -# Normaly nothing should be changed beneeth this line +# Normally nothing should be changed beneeth this line # **************************** @@ -2342,7 +2342,7 @@ BEGIN { ."of `$MySQLaccess::script'." ,'Access_denied' => "Sorry,\n" - ."An error occured when trying to connect to the database\n" + ."An error occurred when trying to connect to the database\n" ."with the grant-tables:\n" ."* Maybe YOU do not have READ-access to this database?\n" ."* If you used the -U option, you may have supplied an invalid username?\n" @@ -2352,24 +2352,24 @@ BEGIN { ."* If you used the -P option, you may have supplied an invalid password?\n" ,'Dbaccess_denied' => "Sorry,\n" - ."An error occured when trying to connect to the database\n" + ."An error occurred when trying to connect to the database\n" ."with the grant-tables. (dbaccess denied)\n" ,'Unknown_tmp_table' => "Sorry,\n" - ."An error occured when trying to work with the temporary tables in the database\n" + ."An error occurred when trying to work with the temporary tables in the database\n" ."with the grant-tables. (One of the temporary tables does not exist)\n" ,'Unknown_table' => "Sorry,\n" - ."An error occured when trying to work with some tables in the database\n" + ."An error occurred when trying to work with some tables in the database\n" ."with the grant-tables. (table does not exist)\n" ,'use_old_server' => "Sorry,\n" - ."An error occured when executing an SQL statement.\n" + ."An error occurred when executing an SQL statement.\n" ."You might consider altering the use of the parameter `--old_server' when \n" ."calling `$MySQLaccess::script'." ,'unknown_error' => "Sorry,\n" - ."An error occured when trying to connect to the database\n" + ."An error occurred when trying to connect to the database\n" ."with the grant-tables. (unknown error)\n" ,'anonymous_access' => "Accessing the db as an anonymous user.\n" @@ -2422,7 +2422,7 @@ sub Print_Header { sub Print_Footer { if ($MySQLaccess::CMD) { #command-line mode print "\n" - ."BUGs can be reported at https://mariadb.atlassian.net/browse/MDEV\n"; + ."BUGs can be reported at https://jira.mariadb.org\n"; } if ($MySQLaccess::CGI) { #CGI-BIN mode if ($MySQLaccess::Param{'brief'}) { @@ -2430,7 +2430,7 @@ sub Print_Footer { } print "<HR>\n" ."<ADDRESS>\n" - ."BUGs can be reported at <a href=\"https://mariadb.atlassian.net/browse/MDEV\">MariaDB JIRA</a><BR>\n" + ."BUGs can be reported at <a href=\"https://jira.mariadb.org\">MariaDB JIRA</a><BR>\n" # ."Don't forget to mention the version $VERSION!<BR>\n" ."</ADDRESS>\n" ."</BODY>\n" diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index a93ab940593..7e895aa4eb2 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -127,7 +127,10 @@ then then FLUSHED="$WSREP_SST_OPT_DATA/tables_flushed" + ERROR="$WSREP_SST_OPT_DATA/sst_error" + rm -rf "$FLUSHED" + rm -rf "$ERROR" # Use deltaxfer only for WAN inv=$(basename $0) @@ -137,10 +140,20 @@ then echo "flush tables" # Wait for : - # (a) tables to be flushed, and - # (b) state ID & wsrep_gtid_domain_id to be written to the file. + # (a) Tables to be flushed, AND + # (b) Cluster state ID & wsrep_gtid_domain_id to be written to the file, OR + # (c) ERROR file, in case flush tables operation failed. + while [ ! -r "$FLUSHED" ] && ! grep -q ':' "$FLUSHED" >/dev/null 2>&1 do + # Check whether ERROR file exists. + if [ -f "$ERROR" ] + then + # Flush tables operation failed. + rm -rf "$ERROR" + exit 255 + fi + sleep 0.2 done diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 2b432cb1089..4cd21d3c216 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -250,7 +250,11 @@ parse_cnf() { local group=$1 local var=$2 - reval=$($MY_PRINT_DEFAULTS $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) + # print the default settings for given group using my_print_default. + # normalize the variable names specified in cnf file (user can use _ or - for example log-bin or log_bin) + # then grep for needed variable + # finally get the variable value (if variables has been specified multiple time use the last value only) + reval=$($MY_PRINT_DEFAULTS $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2- | tail -1) if [[ -z $reval ]];then [[ -n $3 ]] && reval=$3 fi @@ -699,9 +703,8 @@ then INNOEXTRA+=" --user=$WSREP_SST_OPT_USER" fi - if [ -n "$WSREP_SST_OPT_PSWD" ]; then -# INNOEXTRA+=" --password=$WSREP_SST_OPT_PSWD" - export MYSQL_PWD="$WSREP_SST_OPT_PSWD" + if [ -n "${WSREP_SST_OPT_PSWD:-}" ]; then + INNOEXTRA+=" --password=$WSREP_SST_OPT_PSWD" else # Empty password, used for testing, debugging etc. INNOEXTRA+=" --password=" diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index 1ef3c3f3ce1..2247edec7fd 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -442,9 +442,8 @@ then INNOEXTRA+=" --user=$WSREP_SST_OPT_USER" fi - if [ -n "$WSREP_SST_OPT_PSWD" ]; then -# INNOEXTRA+=" --password=$WSREP_SST_OPT_PSWD" - export MYSQL_PWD="$WSREP_SST_OPT_PSWD" + if [ -n "${WSREP_SST_OPT_PSWD:-}" ]; then + INNOEXTRA+=" --password=$WSREP_SST_OPT_PSWD" else # Empty password, used for testing, debugging etc. INNOEXTRA+=" --password=" diff --git a/sql-bench/bench-init.pl.sh b/sql-bench/bench-init.pl.sh index a46bb2d7a49..7bc7c23be66 100644 --- a/sql-bench/bench-init.pl.sh +++ b/sql-bench/bench-init.pl.sh @@ -265,7 +265,7 @@ sub fetch_all_rows if (!($sth= $dbh->prepare($query))) { print "\n" if ($opt_debug); - die "Error occured with prepare($query)\n -> $DBI::errstr\n"; + die "Error occurred with prepare($query)\n -> $DBI::errstr\n"; return undef; } if (!$sth->execute) @@ -282,7 +282,7 @@ sub fetch_all_rows print "0\n" if ($opt_debug); return 0; } - die "Error occured with execute($query)\n -> $DBI::errstr\n"; + die "Error occurred with execute($query)\n -> $DBI::errstr\n"; $sth->finish; return undef; } diff --git a/sql-common/client.c b/sql-common/client.c index 36a644cb90f..b96231fcc13 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2003, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB +/* Copyright (c) 2003, 2016, Oracle and/or its affiliates. + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -601,7 +601,7 @@ restart: uint last_errno=uint2korr(pos); if (last_errno == 65535 && - (mysql->server_capabilities & CLIENT_PROGRESS)) + (mysql->server_capabilities & CLIENT_PROGRESS_OBSOLETE)) { if (cli_report_progress(mysql, pos+2, (uint) (len-3))) { @@ -1755,38 +1755,39 @@ mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused))) static int ssl_verify_server_cert(Vio *vio, const char* server_hostname, const char **errptr) { SSL *ssl; - X509 *server_cert; - X509_NAME *x509sn; - int cn_pos; - X509_NAME_ENTRY *cn_entry; - ASN1_STRING *cn_asn1; - const char *cn_str; + X509 *server_cert= NULL; + char *cn= NULL; + int cn_loc= -1; + ASN1_STRING *cn_asn1= NULL; + X509_NAME_ENTRY *cn_entry= NULL; + X509_NAME *subject= NULL; + int ret_validation= 1; + DBUG_ENTER("ssl_verify_server_cert"); DBUG_PRINT("enter", ("server_hostname: %s", server_hostname)); if (!(ssl= (SSL*)vio->ssl_arg)) { *errptr= "No SSL pointer found"; - DBUG_RETURN(1); + goto error; } if (!server_hostname) { *errptr= "No server hostname supplied"; - DBUG_RETURN(1); + goto error; } if (!(server_cert= SSL_get_peer_certificate(ssl))) { *errptr= "Could not get server certificate"; - DBUG_RETURN(1); + goto error; } if (X509_V_OK != SSL_get_verify_result(ssl)) { *errptr= "Failed to verify the server certificate"; - X509_free(server_cert); - DBUG_RETURN(1); + goto error; } /* We already know that the certificate exchanged was valid; the SSL library @@ -1794,33 +1795,57 @@ static int ssl_verify_server_cert(Vio *vio, const char* server_hostname, const c are what we expect. */ - x509sn= X509_get_subject_name(server_cert); - - if ((cn_pos= X509_NAME_get_index_by_NID(x509sn, NID_commonName, -1)) < 0) - goto err; + /* + Some notes for future development + We should check host name in alternative name first and then if needed check in common name. + Currently yssl doesn't support alternative name. + openssl 1.0.2 support X509_check_host method for host name validation, we may need to start using + X509_check_host in the future. + */ - if (!(cn_entry= X509_NAME_get_entry(x509sn, cn_pos))) - goto err; + subject= X509_get_subject_name(server_cert); + cn_loc= X509_NAME_get_index_by_NID(subject, NID_commonName, -1); + if (cn_loc < 0) + { + *errptr= "Failed to get CN location in the certificate subject"; + goto error; + } - if (!(cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry))) - goto err; + cn_entry= X509_NAME_get_entry(subject, cn_loc); + if (cn_entry == NULL) + { + *errptr= "Failed to get CN entry using CN location"; + goto error; + } - cn_str = (char *)ASN1_STRING_data(cn_asn1); + cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry); + if (cn_asn1 == NULL) + { + *errptr= "Failed to get CN from CN entry"; + goto error; + } - /* Make sure there is no embedded \0 in the CN */ - if ((size_t)ASN1_STRING_length(cn_asn1) != strlen(cn_str)) - goto err; + cn= (char *) ASN1_STRING_data(cn_asn1); - if (strcmp(cn_str, server_hostname)) - goto err; + if ((size_t)ASN1_STRING_length(cn_asn1) != strlen(cn)) + { + *errptr= "NULL embedded in the certificate CN"; + goto error; + } - X509_free (server_cert); - DBUG_RETURN(0); + DBUG_PRINT("info", ("Server hostname in cert: %s", cn)); + if (!strcmp(cn, server_hostname)) + { + /* Success */ + ret_validation= 0; + } -err: - X509_free(server_cert); *errptr= "SSL certificate validation failure"; - DBUG_RETURN(1); + +error: + if (server_cert != NULL) + X509_free (server_cert); + DBUG_RETURN(ret_validation); } #endif /* HAVE_OPENSSL */ @@ -4337,6 +4362,7 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) stacksize= ASYNC_CONTEXT_DEFAULT_STACK_SIZE; if (my_context_init(&ctxt->async_context, stacksize)) { + set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); my_free(ctxt); DBUG_RETURN(1); } diff --git a/sql-common/client_plugin.c b/sql-common/client_plugin.c index 063fc5c6dc6..dd87b01d932 100644 --- a/sql-common/client_plugin.c +++ b/sql-common/client_plugin.c @@ -235,7 +235,7 @@ static void load_env_plugins(MYSQL *mysql) This function must be called before any other client plugin function. @retval 0 successful - @retval != 0 error occured + @retval != 0 error occurred */ int mysql_client_plugin_init() { diff --git a/sql-common/mysql_async.c b/sql-common/mysql_async.c index ef01f292180..80b4f390641 100644 --- a/sql-common/mysql_async.c +++ b/sql-common/mysql_async.c @@ -102,7 +102,7 @@ my_connect_async(struct mysql_async_context *b, my_socket fd, my_context_yield(&b->async_context); if (b->suspend_resume_hook) (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data); - if (b->events_occured & MYSQL_WAIT_TIMEOUT) + if (b->events_occurred & MYSQL_WAIT_TIMEOUT) return -1; s_err_size= sizeof(res); @@ -149,7 +149,7 @@ my_recv_async(struct mysql_async_context *b, int fd, my_context_yield(&b->async_context); if (b->suspend_resume_hook) (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data); - if (b->events_occured & MYSQL_WAIT_TIMEOUT) + if (b->events_occurred & MYSQL_WAIT_TIMEOUT) return -1; } } @@ -177,7 +177,7 @@ my_send_async(struct mysql_async_context *b, int fd, my_context_yield(&b->async_context); if (b->suspend_resume_hook) (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data); - if (b->events_occured & MYSQL_WAIT_TIMEOUT) + if (b->events_occurred & MYSQL_WAIT_TIMEOUT) return -1; } } @@ -210,7 +210,7 @@ my_io_wait_async(struct mysql_async_context *b, enum enum_vio_io_event event, my_context_yield(&b->async_context); if (b->suspend_resume_hook) (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data); - return (b->events_occured & MYSQL_WAIT_TIMEOUT) ? 0 : 1; + return (b->events_occurred & MYSQL_WAIT_TIMEOUT) ? 0 : 1; } @@ -349,7 +349,7 @@ mysql_get_timeout_value_ms(const MYSQL *mysql) } \ \ b->active= 1; \ - b->events_occured= ready_status; \ + b->events_occurred= ready_status; \ res= my_context_continue(&b->async_context); \ b->active= 0; \ if (res > 0) \ @@ -405,7 +405,7 @@ mysql_get_timeout_value_ms(const MYSQL *mysql) } \ \ b->active= 1; \ - b->events_occured= ready_status; \ + b->events_occurred= ready_status; \ res= my_context_continue(&b->async_context); \ b->active= 0; \ if (res > 0) \ diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 19fbed85737..062e59bee5b 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -112,7 +112,8 @@ SET (SQL_SOURCE sql_statistics.cc sql_string.cc sql_table.cc sql_test.cc sql_trigger.cc sql_udf.cc sql_union.cc sql_update.cc sql_view.cc strfunc.cc table.cc thr_malloc.cc - sql_time.cc tztime.cc uniques.cc unireg.cc item_xmlfunc.cc + sql_time.cc tztime.cc unireg.cc item_xmlfunc.cc + uniques.cc uniques.h rpl_tblmap.cc sql_binlog.cc event_scheduler.cc event_data_objects.cc event_queue.cc event_db_repository.cc sql_tablespace.cc events.cc ../sql-common/my_user.c @@ -138,6 +139,7 @@ SET (SQL_SOURCE rpl_gtid.cc rpl_parallel.cc sql_type.cc sql_type.h item_windowfunc.cc sql_window.cc + sql_cte.cc sql_cte.h ${WSREP_SOURCES} table_cache.cc encryption.cc ${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc diff --git a/sql/authors.h b/sql/authors.h index cc9889bcdbc..3a8f5497248 100644 --- a/sql/authors.h +++ b/sql/authors.h @@ -56,7 +56,7 @@ struct show_table_authors_st show_table_authors[]= { "Unicode and character sets" }, { "Alexey Botchkov (Holyfoot)", "Izhevsk, Russia", "GIS extensions, embedded server, precision math"}, - { "Daniel Bartholomew", "Raleigh, USA", "MariaDB documentation"}, + { "Daniel Bartholomew", "Raleigh, USA", "MariaDB documentation, Buildbot, releases"}, { "Colin Charles", "Selangor, Malesia", "MariaDB documentation, talks at a LOT of conferences"}, { "Sergey Vojtovich", "Izhevsk, Russia", "initial implementation of plugin architecture, maintained native storage engines (MyISAM, MEMORY, ARCHIVE, etc), rewrite of table cache"}, @@ -73,6 +73,8 @@ struct show_table_authors_st show_table_authors[]= { { "Pavel Ivanov", "USA", "Some patches and bug fixes"}, { "Konstantin Osipov", "Moscow, Russia", "Prepared statements (4.1), Cursors (5.0), GET_LOCK (10.0)" }, + { "Ian Gilfillan", "South Africa", "MariaDB documentation"}, + { "Federico Razolli", "Italy", "MariaDB documentation Italian translation"}, /* People working on MySQL code base (not NDB) */ { "Guilhem Bichot", "Bordeaux, France", "Replication (since 4.0)" }, diff --git a/sql/bounded_queue.h b/sql/bounded_queue.h index 2d4e6cff96d..88c2bbc238d 100644 --- a/sql/bounded_queue.h +++ b/sql/bounded_queue.h @@ -16,11 +16,11 @@ #ifndef BOUNDED_QUEUE_INCLUDED #define BOUNDED_QUEUE_INCLUDED -#include <string.h> #include "my_global.h" #include "my_base.h" #include "my_sys.h" #include "queues.h" +#include <string.h> class Sort_param; diff --git a/sql/client_settings.h b/sql/client_settings.h index d6a157f71fd..486862b276d 100644 --- a/sql/client_settings.h +++ b/sql/client_settings.h @@ -28,7 +28,7 @@ When adding capabilities here, consider if they should be also added to the libmysql version. */ -#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | \ +#define CLIENT_CAPABILITIES (CLIENT_MYSQL | \ CLIENT_LONG_FLAG | \ CLIENT_TRANSACTIONS | \ CLIENT_PROTOCOL_41 | \ @@ -37,7 +37,7 @@ CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | \ CLIENT_CONNECT_ATTRS) -#define read_user_name(A) {} +#define read_user_name(A) A[0]= 0 #undef _CUSTOMCONFIG_ #define mysql_server_init(a,b,c) mysql_client_plugin_init() diff --git a/sql/contributors.h b/sql/contributors.h index 2479f611727..04f8b74aa65 100644 --- a/sql/contributors.h +++ b/sql/contributors.h @@ -37,21 +37,19 @@ struct show_table_contributors_st { struct show_table_contributors_st show_table_contributors[]= { /* MariaDB foundation members, in contribution, size , time order */ - {"Booking.com", "http://www.booking.com", "Founding member of the MariaDB foundation"}, - {"SkySQL Ab", "http://www.skysql.com", "Founding member of the MariaDB foundation"}, - {"Auttomatic", "http://automattic.com", "Member of the MariaDB foundation"}, - {"Parallels", "http://www.parallels.com/products/plesk", "Founding member of the MariaDB foundation"}, + {"Booking.com", "http://www.booking.com", "Founding member of the MariaDB Foundation"}, + {"MariaDB Corporation", "https://mariadb.com", "Founding member of the MariaDB Foundation"}, + {"Auttomattic", "http://automattic.com", "Member of the MariaDB Foundation"}, + {"Visma", "http://visma.com", "Member of the MariaDB Foundation"}, + {"Nexedi", "http://www.nexedi.com", "Member of the MariaDB Foundation"}, + {"Acronis", "http://www.acronis.com", "Member of the MariaDB Foundation"}, /* Smaller sponsors, newer per year */ - {"Verkkokauppa.com", "Finland", "Sponsor of the MariaDB foundation"}, - {"Webyog", "Bangalor", "Sponsor of the MariaDB foundation"}, - {"Percona", "USA", "Sponsor of the MariaDB foundation"}, - {"Jelastic.com", "Russia", "Sponsor of the MariaDB foundation"}, - {"Planetta.net", "Finland", "Sponsor of the MariaDB foundation"}, - {"Open query", "Australia", "Sponsor of the MariaDB foundation"}, + {"Verkkokauppa.com", "Finland", "Sponsor of the MariaDB Foundation"}, + {"Webyog", "Bangalore", "Sponsor of the MariaDB Foundation"}, /* Sponsors of important features */ - {"Google", "USA", "Sponsoring parallel replication and GTID" }, + {"Google", "USA", "Sponsoring encryption, parallel replication and GTID"}, {"Facebook", "USA", "Sponsoring non-blocking API, LIMIT ROWS EXAMINED etc"}, /* Individual contributors, names in historical order, newer first */ diff --git a/sql/discover.cc b/sql/discover.cc index 82648e94bc5..d8ed718fc58 100644 --- a/sql/discover.cc +++ b/sql/discover.cc @@ -199,14 +199,15 @@ int extension_based_table_discovery(MY_DIR *dirp, const char *ext_meta, end= cur + dirp->number_of_files; while (cur < end) { - char *octothorp= strrchr(cur->name + 1, '#'); + char *octothorp= strchr(cur->name + 1, '#'); char *ext= strchr(octothorp ? octothorp : cur->name, FN_EXTCHAR); if (ext) { size_t len= (octothorp ? octothorp : ext) - cur->name; if (from != cur && - (my_strnncoll(cs, (uchar*)from->name, len, (uchar*)cur->name, len) || + (strlen(from->name) <= len || + my_strnncoll(cs, (uchar*)from->name, len, (uchar*)cur->name, len) || (from->name[len] != FN_EXTCHAR && from->name[len] != '#'))) advance(from, to, cur, skip); diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index e39f727800a..5d0754cf766 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -499,7 +499,8 @@ Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table, READ_RECORD read_record_info; DBUG_ENTER("Event_db_repository::table_scan_all_for_i_s"); - if (init_read_record(&read_record_info, thd, event_table, NULL, 1, 0, FALSE)) + if (init_read_record(&read_record_info, thd, event_table, NULL, NULL, 1, 0, + FALSE)) DBUG_RETURN(TRUE); /* @@ -947,7 +948,7 @@ end: @retval FALSE an event with such db/name key exists - @retval TRUE no record found or an error occured. + @retval TRUE no record found or an error occurred. */ bool @@ -1015,7 +1016,7 @@ Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema) DBUG_VOID_RETURN; /* only enabled events are in memory, so we go now and delete the rest */ - if (init_read_record(&read_record_info, thd, table, NULL, 1, 0, FALSE)) + if (init_read_record(&read_record_info, thd, table, NULL, NULL, 1, 0, FALSE)) goto end; while (!ret && !(read_record_info.read_record(&read_record_info)) ) diff --git a/sql/event_queue.cc b/sql/event_queue.cc index 35187af23ac..ae8ba258717 100644 --- a/sql/event_queue.cc +++ b/sql/event_queue.cc @@ -191,7 +191,7 @@ Event_queue::deinit_queue() @param[out] created set to TRUE if no error and the element is added to the queue, FALSE otherwise - @retval TRUE an error occured. The value of created is undefined, + @retval TRUE an error occurred. The value of created is undefined, the element was not deleted. @retval FALSE success */ diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 95c5f6d9047..6a8bdabb948 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -135,9 +135,7 @@ post_init_event_thread(THD *thd) } thread_safe_increment32(&thread_count); - mysql_mutex_lock(&LOCK_thread_count); - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); + add_to_active_threads(thd); inc_thread_running(); return FALSE; } @@ -191,9 +189,7 @@ pre_init_event_thread(THD* thd) thd->net.read_timeout= slave_net_timeout; thd->variables.option_bits|= OPTION_AUTO_IS_NULL; thd->client_capabilities|= CLIENT_MULTI_RESULTS; - mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - mysql_mutex_unlock(&LOCK_thread_count); + thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id(); /* Guarantees that we will see the thread in SHOW PROCESSLIST though its @@ -479,7 +475,7 @@ Event_scheduler::run(THD *thd) DBUG_ENTER("Event_scheduler::run"); sql_print_information("Event Scheduler: scheduler thread started with id %lu", - thd->thread_id); + (ulong) thd->thread_id); /* Recalculate the values in the queue because there could have been stops in executions of the scheduler and some times could have passed by. @@ -669,13 +665,13 @@ Event_scheduler::stop() state= STOPPING; DBUG_PRINT("info", ("Scheduler thread has id %lu", - scheduler_thd->thread_id)); + (ulong) scheduler_thd->thread_id)); /* Lock from delete */ mysql_mutex_lock(&scheduler_thd->LOCK_thd_data); /* This will wake up the thread if it waits on Queue's conditional */ sql_print_information("Event Scheduler: Killing the scheduler thread, " "thread id %lu", - scheduler_thd->thread_id); + (ulong) scheduler_thd->thread_id); scheduler_thd->awake(KILL_CONNECTION); mysql_mutex_unlock(&scheduler_thd->LOCK_thd_data); @@ -832,7 +828,8 @@ Event_scheduler::dump_internal_status() puts(""); puts("Event scheduler status:"); printf("State : %s\n", scheduler_states_names[state].str); - printf("Thread id : %lu\n", scheduler_thd? scheduler_thd->thread_id : 0); + printf("Thread id : %lu\n", scheduler_thd ? + (ulong) scheduler_thd->thread_id : (ulong) 0); printf("LLA : %s:%u\n", mutex_last_locked_in_func, mutex_last_locked_at_line); printf("LUA : %s:%u\n", mutex_last_unlocked_in_func, diff --git a/sql/events.cc b/sql/events.cc index b80ec993ac4..f428bc17927 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -333,6 +333,10 @@ Events::create_event(THD *thd, Event_parse_data *parse_data) if (check_access(thd, EVENT_ACL, parse_data->dbname.str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); + if (lock_object_name(thd, MDL_key::EVENT, + parse_data->dbname.str, parse_data->name.str)) + DBUG_RETURN(TRUE); + if (check_db_dir_existence(parse_data->dbname.str)) { my_error(ER_BAD_DB_ERROR, MYF(0), parse_data->dbname.str); @@ -347,10 +351,6 @@ Events::create_event(THD *thd, Event_parse_data *parse_data) */ save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); - if (lock_object_name(thd, MDL_key::EVENT, - parse_data->dbname.str, parse_data->name.str)) - DBUG_RETURN(TRUE); - if (thd->lex->create_info.or_replace() && event_queue) event_queue->drop_event(thd, parse_data->dbname, parse_data->name); @@ -454,6 +454,16 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, if (check_access(thd, EVENT_ACL, parse_data->dbname.str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); + if (lock_object_name(thd, MDL_key::EVENT, + parse_data->dbname.str, parse_data->name.str)) + DBUG_RETURN(TRUE); + + if (check_db_dir_existence(parse_data->dbname.str)) + { + my_error(ER_BAD_DB_ERROR, MYF(0), parse_data->dbname.str); + DBUG_RETURN(TRUE); + } + if (new_dbname) /* It's a rename */ { @@ -476,6 +486,13 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, if (check_access(thd, EVENT_ACL, new_dbname->str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); + /* + Acquire mdl exclusive lock on target database name. + */ + if (lock_object_name(thd, MDL_key::EVENT, + new_dbname->str, new_name->str)) + DBUG_RETURN(TRUE); + /* Check that the target database exists */ if (check_db_dir_existence(new_dbname->str)) { @@ -490,10 +507,6 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, */ save_binlog_format= thd->set_current_stmt_binlog_format_stmt(); - if (lock_object_name(thd, MDL_key::EVENT, - parse_data->dbname.str, parse_data->name.str)) - DBUG_RETURN(TRUE); - /* On error conditions my_error() is called so no need to handle here */ if (!(ret= db_repository->update_event(thd, parse_data, new_dbname, new_name))) @@ -1134,7 +1147,7 @@ Events::load_events_from_db(THD *thd) DBUG_RETURN(TRUE); } - if (init_read_record(&read_record_info, thd, table, NULL, 0, 1, FALSE)) + if (init_read_record(&read_record_info, thd, table, NULL, NULL, 0, 1, FALSE)) { close_thread_tables(thd); DBUG_RETURN(TRUE); diff --git a/sql/field.cc b/sql/field.cc index 177f219c137..6be45005d48 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5647,6 +5647,18 @@ Item *Field_temporal::get_equal_const_item_datetime(THD *thd, } break; case ANY_SUBST: + if (!is_temporal_type_with_date(const_item->field_type())) + { + MYSQL_TIME ltime; + if (const_item->get_date_with_conversion(<ime, + TIME_FUZZY_DATES | + TIME_INVALID_DATES)) + return NULL; + return new (thd->mem_root) + Item_datetime_literal_for_invalid_dates(thd, <ime, + ltime.second_part ? + TIME_SECOND_PART_DIGITS : 0); + } break; } return const_item; @@ -5955,7 +5967,10 @@ Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx, { MYSQL_TIME ltime; // Get the value of const_item with conversion from DATETIME to TIME - if (const_item->get_time_with_conversion(thd, <ime, TIME_TIME_ONLY)) + if (const_item->get_time_with_conversion(thd, <ime, + TIME_TIME_ONLY | + TIME_FUZZY_DATES | + TIME_INVALID_DATES)) return NULL; /* Replace a DATE/DATETIME constant to a TIME constant: @@ -7868,7 +7883,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED; uint copy_length, new_length; String_copier copier; - const char *tmp; + char *tmp; char buff[STRING_BUFFER_USUAL_SIZE]; String tmpstr(buff,sizeof(buff), &my_charset_bin); @@ -7878,6 +7893,29 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) return 0; } + if (table->blob_storage) // GROUP_CONCAT with ORDER BY | DISTINCT + { + DBUG_ASSERT(!f_is_hex_escape(flags)); + DBUG_ASSERT(field_charset == cs); + DBUG_ASSERT(length <= max_data_length()); + + new_length= length; + copy_length= table->in_use->variables.group_concat_max_len; + if (new_length > copy_length) + { + int well_formed_error; + new_length= cs->cset->well_formed_len(cs, from, from + copy_length, + new_length, &well_formed_error); + table->blob_storage->set_truncated_value(true); + } + if (!(tmp= table->blob_storage->store(from, new_length))) + goto oom_error; + + Field_blob::store_length(new_length); + bmove(ptr + packlength, (uchar*) &tmp, sizeof(char*)); + return 0; + } + /* If the 'from' address is in the range of the temporary 'value'- object we need to copy the content to a different location or it will be @@ -7904,15 +7942,14 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) new_length= MY_MIN(max_data_length(), field_charset->mbmaxlen * length); if (value.alloc(new_length)) goto oom_error; - + tmp= const_cast<char*>(value.ptr()); if (f_is_hex_escape(flags)) { copy_length= my_copy_with_hex_escaping(field_charset, - (char*) value.ptr(), new_length, - from, length); + tmp, new_length, + from, length); Field_blob::store_length(copy_length); - tmp= value.ptr(); bmove(ptr + packlength, (uchar*) &tmp, sizeof(char*)); return 0; } @@ -7920,7 +7957,6 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) (char*) value.ptr(), new_length, cs, from, length); Field_blob::store_length(copy_length); - tmp= value.ptr(); bmove(ptr+packlength,(uchar*) &tmp,sizeof(char*)); return check_conversion_status(&copier, from + length, cs, true); diff --git a/sql/field.h b/sql/field.h index 435ea20825a..736c51c2ac3 100644 --- a/sql/field.h +++ b/sql/field.h @@ -609,6 +609,13 @@ public: { in_partitioning_expr= TRUE; } + bool is_equal(Virtual_column_info* vcol) + { + return field_type == vcol->get_real_type() + && stored_in_db == vcol->is_stored() + && expr_str.length == vcol->expr_str.length + && memcmp(expr_str.str, vcol->expr_str.str, expr_str.length) == 0; + } }; class Field: public Value_source @@ -1700,6 +1707,16 @@ public: return do_field_real; } int save_in_field(Field *to) { return to->store(val_real()); } + bool memcpy_field_possible(const Field *from) const + { + /* + Cannot do memcpy from a longer field to a shorter field, + e.g. a DOUBLE(53,10) into a DOUBLE(10,10). + But it should be OK the other way around. + */ + return Field_num::memcpy_field_possible(from) && + field_length >= from->field_length; + } int store_decimal(const my_decimal *); int store_time_dec(MYSQL_TIME *ltime, uint dec); bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); @@ -3159,7 +3176,7 @@ public: int store_field(Field *from) { // Be sure the value is stored from->val_str(&value); - if (!value.is_alloced() && from->is_updatable()) + if (table->copy_blobs || (!value.is_alloced() && from->is_updatable())) value.copy(); return store(value.ptr(), value.length(), from->charset()); } @@ -3736,7 +3753,7 @@ public: const char *field_name_arg) const { return ::make_field(share, mem_root, ptr, - length, null_pos, null_bit, + (uint32)length, null_pos, null_bit, pack_flag, sql_type, charset, geom_type, srid, unireg_check, interval, field_name_arg); diff --git a/sql/field_conv.cc b/sql/field_conv.cc index ecad05c7530..263c5bb5017 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -1,6 +1,5 @@ -/* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. + Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -643,9 +642,6 @@ void Copy_field::set(uchar *to,Field *from) Field_blob::store. Is this in order to trigger the call to well_formed_copy_nchars, by changing the pointer copy->tmp.ptr()? That call will take place anyway in all known cases. - - - The above causes a truncation to MAX_FIELD_WIDTH. Is this the intended - effect? Truncation is handled by well_formed_copy_nchars anyway. */ void Copy_field::set(Field *to,Field *from,bool save) { diff --git a/sql/filesort.cc b/sql/filesort.cc index 4a1f509a54d..78b74380f7e 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -50,34 +50,36 @@ if (my_b_write((file),(uchar*) (from),param->ref_length)) \ static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count, uchar *buf); static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, - Filesort_info *fs_info, + SORT_INFO *fs_info, IO_CACHE *buffer_file, IO_CACHE *tempfile, Bounded_queue<uchar, uchar> *pq, ha_rows *found_rows); -static bool write_keys(Sort_param *param, Filesort_info *fs_info, +static bool write_keys(Sort_param *param, SORT_INFO *fs_info, uint count, IO_CACHE *buffer_file, IO_CACHE *tempfile); static void make_sortkey(Sort_param *param, uchar *to, uchar *ref_pos); static void register_used_fields(Sort_param *param); static bool save_index(Sort_param *param, uint count, - Filesort_info *table_sort); + SORT_INFO *table_sort); static uint suffix_length(ulong string_length); static uint sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset); static SORT_ADDON_FIELD *get_addon_fields(ulong max_length_for_sort_data, Field **ptabfield, - uint sortlength, uint *plength); + uint sortlength, + LEX_STRING *addon_buf); static void unpack_addon_fields(struct st_sort_addon_field *addon_field, uchar *buff, uchar *buff_end); -static bool check_if_pq_applicable(Sort_param *param, Filesort_info *info, +static bool check_if_pq_applicable(Sort_param *param, SORT_INFO *info, TABLE *table, ha_rows records, ulong memory_available); - void Sort_param::init_for_filesort(uint sortlen, TABLE *table, ulong max_length_for_sort_data, ha_rows maxrows, bool sort_positions) { + DBUG_ASSERT(addon_field == 0 && addon_buf.length == 0); + sort_length= sortlen; ref_length= table->file->ref_length; if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && @@ -85,13 +87,13 @@ void Sort_param::init_for_filesort(uint sortlen, TABLE *table, { /* Get the descriptors of all fields whose values are appended - to sorted fields and get its total length in addon_length. + to sorted fields and get its total length in addon_buf.length */ addon_field= get_addon_fields(max_length_for_sort_data, - table->field, sort_length, &addon_length); + table->field, sort_length, &addon_buf); } if (addon_field) - res_length= addon_length; + res_length= addon_buf.length; else { res_length= ref_length; @@ -101,7 +103,7 @@ void Sort_param::init_for_filesort(uint sortlen, TABLE *table, */ sort_length+= ref_length; } - rec_length= sort_length + addon_length; + rec_length= sort_length + addon_buf.length; max_rows= maxrows; } @@ -115,35 +117,33 @@ void Sort_param::init_for_filesort(uint sortlen, TABLE *table, Before calling filesort, one must have done table->file->info(HA_STATUS_VARIABLE) - The result set is stored in table->io_cache or - table->record_pointers. + The result set is stored in + filesort_info->io_cache or + filesort_info->record_pointers. @param thd Current thread @param table Table to sort @param filesort How to sort the table - @param sort_positions Set to TRUE if we want to force sorting by position + @param sort_positions Set to TRUE if we want to force sorting by + position (Needed by UPDATE/INSERT or ALTER TABLE or when rowids are required by executor) - @param[out] examined_rows Store number of examined rows here - This is the number of found rows before applying WHERE condition. @param[out] found_rows Store the number of found rows here. This is the number of found rows after applying WHERE condition. - @note If we sort by position (like if sort_positions is 1) filesort() will call table->prepare_for_position(). @retval - HA_POS_ERROR Error - @retval - \# Number of rows + 0 Error + # SORT_INFO */ -ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, - bool sort_positions, ha_rows *examined_rows, - ha_rows *found_rows, Filesort_tracker* tracker) +SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, + bool sort_positions, + Filesort_tracker* tracker) { int error; size_t memory_available= thd->variables.sortbuff_size; @@ -161,39 +161,43 @@ ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, DBUG_ENTER("filesort"); if (!(s_length= filesort->make_sortorder(thd))) - DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ + DBUG_RETURN(NULL); /* purecov: inspected */ DBUG_EXECUTE("info",TEST_filesort(filesort->sortorder,s_length);); #ifdef SKIP_DBUG_IN_FILESORT DBUG_PUSH(""); /* No DBUG here */ #endif - Filesort_info table_sort= table->sort; + SORT_INFO *sort; TABLE_LIST *tab= table->pos_in_table_list; Item_subselect *subselect= tab ? tab->containing_subselect() : 0; - MYSQL_FILESORT_START(table->s->db.str, table->s->table_name.str); DEBUG_SYNC(thd, "filesort_start"); + if (!(sort= new SORT_INFO)) + return 0; + + if (subselect && subselect->filesort_buffer.is_allocated()) + { + /* Reuse cache from last call */ + sort->filesort_buffer= subselect->filesort_buffer; + sort->buffpek= subselect->sortbuffer; + subselect->filesort_buffer.reset(); + subselect->sortbuffer.str=0; + } + + outfile= &sort->io_cache; + /* Release InnoDB's adaptive hash index latch (if holding) before running a sort. */ ha_release_temporary_latches(thd); - /* - Don't use table->sort in filesort as it is also used by - QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end - when index_merge select has finished with it. - */ - table->sort.io_cache= NULL; - DBUG_ASSERT(table_sort.record_pointers == NULL); - - outfile= table_sort.io_cache; my_b_clear(&tempfile); my_b_clear(&buffpek_pointers); buffpek=0; error= 1; - *found_rows= HA_POS_ERROR; + sort->found_rows= HA_POS_ERROR; param.init_for_filesort(sortlength(thd, filesort->sortorder, s_length, &multi_byte_charset), @@ -201,14 +205,12 @@ ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, thd->variables.max_length_for_sort_data, max_rows, sort_positions); - table_sort.addon_buf= 0; - table_sort.addon_length= param.addon_length; - table_sort.addon_field= param.addon_field; - table_sort.unpack= unpack_addon_fields; - if (param.addon_field && - !(table_sort.addon_buf= - (uchar *) my_malloc(param.addon_length, MYF(MY_WME | - MY_THREAD_SPECIFIC)))) + sort->addon_buf= param.addon_buf; + sort->addon_field= param.addon_field; + sort->unpack= unpack_addon_fields; + if (multi_byte_charset && + !(param.tmp_buffer= (char*) my_malloc(param.sort_length, + MYF(MY_WME | MY_THREAD_SPECIFIC)))) goto err; if (select && select->quick) @@ -221,12 +223,7 @@ ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, // If number of rows is not known, use as much of sort buffer as possible. num_rows= table->file->estimate_rows_upper_bound(); - if (multi_byte_charset && - !(param.tmp_buffer= (char*) my_malloc(param.sort_length, - MYF(MY_WME | MY_THREAD_SPECIFIC)))) - goto err; - - if (check_if_pq_applicable(¶m, &table_sort, + if (check_if_pq_applicable(¶m, sort, table, num_rows, memory_available)) { DBUG_PRINT("info", ("filesort PQ is applicable")); @@ -238,45 +235,31 @@ ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, true, // max_at_top NULL, // compare_function compare_length, - &make_sortkey, ¶m, table_sort.get_sort_keys())) + &make_sortkey, ¶m, sort->get_sort_keys())) { /* If we fail to init pq, we have to give up: out of memory means my_malloc() will call my_error(). */ DBUG_PRINT("info", ("failed to allocate PQ")); - table_sort.free_sort_buffer(); DBUG_ASSERT(thd->is_error()); goto err; } // For PQ queries (with limit) we initialize all pointers. - table_sort.init_record_pointers(); + sort->init_record_pointers(); } else { DBUG_PRINT("info", ("filesort PQ is not applicable")); - size_t min_sort_memory= MY_MAX(MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2); + size_t min_sort_memory= MY_MAX(MIN_SORT_MEMORY, + param.sort_length*MERGEBUFF2); set_if_bigger(min_sort_memory, sizeof(BUFFPEK*)*MERGEBUFF2); while (memory_available >= min_sort_memory) { ulonglong keys= memory_available / (param.rec_length + sizeof(char*)); param.max_keys_per_buffer= (uint) MY_MIN(num_rows, keys); - if (table_sort.get_sort_keys()) - { - // If we have already allocated a buffer, it better have same size! - if (!table_sort.check_sort_buffer_properties(param.max_keys_per_buffer, - param.rec_length)) - { - /* - table->sort will still have a pointer to the same buffer, - but that will be overwritten by the assignment below. - */ - table_sort.free_sort_buffer(); - } - } - table_sort.alloc_sort_buffer(param.max_keys_per_buffer, param.rec_length); - if (table_sort.get_sort_keys()) + if (sort->alloc_sort_buffer(param.max_keys_per_buffer, param.rec_length)) break; size_t old_memory_available= memory_available; memory_available= memory_available/4*3; @@ -289,7 +272,7 @@ ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR + ME_FATALERROR)); goto err; } - tracker->report_sort_buffer_size(table_sort.sort_buffer_size()); + tracker->report_sort_buffer_size(sort->sort_buffer_size()); } if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX, @@ -299,21 +282,21 @@ ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, param.sort_form= table; param.end=(param.local_sortorder=filesort->sortorder)+s_length; num_rows= find_all_keys(thd, ¶m, select, - &table_sort, + sort, &buffpek_pointers, &tempfile, pq.is_initialized() ? &pq : NULL, - found_rows); + &sort->found_rows); if (num_rows == HA_POS_ERROR) goto err; maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek)); tracker->report_merge_passes_at_start(thd->query_plan_fsort_passes); - tracker->report_row_numbers(param.examined_rows, *found_rows, num_rows); + tracker->report_row_numbers(param.examined_rows, sort->found_rows, num_rows); if (maxbuffer == 0) // The whole set is in memory { - if (save_index(¶m, (uint) num_rows, &table_sort)) + if (save_index(¶m, (uint) num_rows, sort)) goto err; } else @@ -321,17 +304,17 @@ ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, /* filesort cannot handle zero-length records during merge. */ DBUG_ASSERT(param.sort_length != 0); - if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer) + if (sort->buffpek.str && sort->buffpek.length < maxbuffer) { - my_free(table_sort.buffpek); - table_sort.buffpek= 0; + my_free(sort->buffpek.str); + sort->buffpek.str= 0; } - if (!(table_sort.buffpek= - (uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, - table_sort.buffpek))) + if (!(sort->buffpek.str= + (char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, + (uchar*) sort->buffpek.str))) goto err; - buffpek= (BUFFPEK *) table_sort.buffpek; - table_sort.buffpek_len= maxbuffer; + sort->buffpek.length= maxbuffer; + buffpek= (BUFFPEK *) sort->buffpek.str; close_cached_file(&buffpek_pointers); /* Open cached file if it isn't open */ if (! my_b_inited(outfile) && @@ -350,7 +333,7 @@ ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, param.rec_length - 1); maxbuffer--; // Offset from 0 if (merge_many_buff(¶m, - (uchar*) table_sort.get_sort_keys(), + (uchar*) sort->get_sort_keys(), buffpek,&maxbuffer, &tempfile)) goto err; @@ -358,7 +341,7 @@ ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, reinit_io_cache(&tempfile,READ_CACHE,0L,0,0)) goto err; if (merge_index(¶m, - (uchar*) table_sort.get_sort_keys(), + (uchar*) sort->get_sort_keys(), buffpek, maxbuffer, &tempfile, @@ -377,11 +360,18 @@ ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, my_free(param.tmp_buffer); if (!subselect || !subselect->is_uncacheable()) { - table_sort.free_sort_buffer(); - my_free(buffpek); - table_sort.buffpek= 0; - table_sort.buffpek_len= 0; + sort->free_sort_buffer(); + my_free(sort->buffpek.str); + } + else + { + /* Remember sort buffers for next subquery call */ + subselect->filesort_buffer= sort->filesort_buffer; + subselect->sortbuffer= sort->buffpek; + sort->filesort_buffer.reset(); // Don't free this } + sort->buffpek.str= 0; + close_cached_file(&tempfile); close_cached_file(&buffpek_pointers); if (my_b_inited(outfile)) @@ -402,13 +392,6 @@ ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, int kill_errno= thd->killed_errno(); DBUG_ASSERT(thd->is_error() || kill_errno || thd->killed == ABORT_QUERY); - /* - We replace the table->sort at the end. - Hence calling free_io_cache to make sure table->sort.io_cache - used for QUICK_INDEX_MERGE_SELECT is free. - */ - free_io_cache(table); - my_printf_error(ER_FILSORT_ABORT, "%s: %s", MYF(0), @@ -429,50 +412,26 @@ ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, } else thd->inc_status_sort_rows(num_rows); - *examined_rows= param.examined_rows; + + sort->examined_rows= param.examined_rows; + sort->return_rows= num_rows; #ifdef SKIP_DBUG_IN_FILESORT DBUG_POP(); /* Ok to DBUG */ #endif - /* table->sort.io_cache should be free by this time */ - DBUG_ASSERT(NULL == table->sort.io_cache); - - // Assign the copy back! - table->sort= table_sort; - DBUG_PRINT("exit", - ("num_rows: %ld examined_rows: %ld found_rows: %ld", - (long) num_rows, (long) *examined_rows, (long) *found_rows)); + ("num_rows: %lld examined_rows: %lld found_rows: %lld", + (longlong) sort->return_rows, (longlong) sort->examined_rows, + (longlong) sort->found_rows)); MYSQL_FILESORT_DONE(error, num_rows); - DBUG_RETURN(error ? HA_POS_ERROR : num_rows); -} /* filesort */ - - -void filesort_free_buffers(TABLE *table, bool full) -{ - DBUG_ENTER("filesort_free_buffers"); - my_free(table->sort.record_pointers); - table->sort.record_pointers= NULL; - - if (unlikely(full)) - { - table->sort.free_sort_buffer(); - my_free(table->sort.buffpek); - table->sort.buffpek= NULL; - table->sort.buffpek_len= 0; - } - - /* addon_buf is only allocated if addon_field is set */ - if (unlikely(table->sort.addon_field)) + if (error) { - my_free(table->sort.addon_field); - my_free(table->sort.addon_buf); - table->sort.addon_buf= NULL; - table->sort.addon_field= NULL; + delete sort; + sort= 0; } - DBUG_VOID_RETURN; -} + DBUG_RETURN(sort); +} /* filesort */ void Filesort::cleanup() @@ -521,7 +480,7 @@ uint Filesort::make_sortorder(THD *thd) DBUG_ASSERT(pos->field != NULL || pos->item != NULL); } DBUG_RETURN(count); -} + } /** Read 'count' number of buffer pointers into memory. */ @@ -726,7 +685,7 @@ static void dbug_print_record(TABLE *table, bool print_rowid) */ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, - Filesort_info *fs_info, + SORT_INFO *fs_info, IO_CACHE *buffpek_pointers, IO_CACHE *tempfile, Bounded_queue<uchar, uchar> *pq, @@ -931,7 +890,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, const ha_rows retval= my_b_inited(tempfile) ? (ha_rows) (my_b_tell(tempfile)/param->rec_length) : idx; - DBUG_PRINT("info", ("find_all_keys return %u", (uint) retval)); + DBUG_PRINT("info", ("find_all_keys return %llu", (ulonglong) retval)); DBUG_RETURN(retval); } /* find_all_keys */ @@ -959,7 +918,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, */ static bool -write_keys(Sort_param *param, Filesort_info *fs_info, uint count, +write_keys(Sort_param *param, SORT_INFO *fs_info, uint count, IO_CACHE *buffpek_pointers, IO_CACHE *tempfile) { size_t rec_length; @@ -1328,11 +1287,13 @@ static void register_used_fields(Sort_param *param) } -static bool save_index(Sort_param *param, uint count, Filesort_info *table_sort) +static bool save_index(Sort_param *param, uint count, + SORT_INFO *table_sort) { uint offset,res_length; uchar *to; DBUG_ENTER("save_index"); + DBUG_ASSERT(table_sort->record_pointers == 0); table_sort->sort_buffer(param, count); res_length= param->res_length; @@ -1381,7 +1342,7 @@ static bool save_index(Sort_param *param, uint count, Filesort_info *table_sort) */ bool check_if_pq_applicable(Sort_param *param, - Filesort_info *filesort_info, + SORT_INFO *filesort_info, TABLE *table, ha_rows num_rows, ulong memory_available) { @@ -1415,9 +1376,8 @@ bool check_if_pq_applicable(Sort_param *param, // The whole source set fits into memory. if (param->max_rows < num_rows/PQ_slowness ) { - filesort_info->alloc_sort_buffer(param->max_keys_per_buffer, - param->rec_length); - DBUG_RETURN(filesort_info->get_sort_keys() != NULL); + DBUG_RETURN(filesort_info->alloc_sort_buffer(param->max_keys_per_buffer, + param->rec_length) != NULL); } else { @@ -1429,9 +1389,8 @@ bool check_if_pq_applicable(Sort_param *param, // Do we have space for LIMIT rows in memory? if (param->max_keys_per_buffer < num_available_keys) { - filesort_info->alloc_sort_buffer(param->max_keys_per_buffer, - param->rec_length); - DBUG_RETURN(filesort_info->get_sort_keys() != NULL); + DBUG_RETURN(filesort_info->alloc_sort_buffer(param->max_keys_per_buffer, + param->rec_length) != NULL); } // Try to strip off addon fields. @@ -1467,17 +1426,14 @@ bool check_if_pq_applicable(Sort_param *param, if (sort_merge_cost < pq_cost) DBUG_RETURN(false); - filesort_info->alloc_sort_buffer(param->max_keys_per_buffer, - param->sort_length + param->ref_length); - if (filesort_info->get_sort_keys()) + if (filesort_info->alloc_sort_buffer(param->max_keys_per_buffer, + param->sort_length + + param->ref_length)) { - // Make attached data to be references instead of fields. - my_free(filesort_info->addon_buf); + /* Make attached data to be references instead of fields. */ my_free(filesort_info->addon_field); - filesort_info->addon_buf= NULL; filesort_info->addon_field= NULL; param->addon_field= NULL; - param->addon_length= 0; param->res_length= param->ref_length; param->sort_length+= param->ref_length; @@ -2047,7 +2003,7 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, @param thd Current thread @param ptabfield Array of references to the table fields @param sortlength Total length of sorted fields - @param[out] plength Total length of appended fields + @param [out] addon_buf Buffer to us for appended fields @note The null bits for the appended values are supposed to be put together @@ -2061,7 +2017,7 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, static SORT_ADDON_FIELD * get_addon_fields(ulong max_length_for_sort_data, - Field **ptabfield, uint sortlength, uint *plength) + Field **ptabfield, uint sortlength, LEX_STRING *addon_buf) { Field **pfield; Field *field; @@ -2070,6 +2026,7 @@ get_addon_fields(ulong max_length_for_sort_data, uint fields= 0; uint null_fields= 0; MY_BITMAP *read_set= (*ptabfield)->table->read_set; + DBUG_ENTER("get_addon_fields"); /* If there is a reference to a field in the query add it @@ -2081,31 +2038,33 @@ get_addon_fields(ulong max_length_for_sort_data, the values directly from sorted fields. But beware the case when item->cmp_type() != item->result_type() */ - *plength= 0; + addon_buf->str= 0; + addon_buf->length= 0; for (pfield= ptabfield; (field= *pfield) ; pfield++) { if (!bitmap_is_set(read_set, field->field_index)) continue; if (field->flags & BLOB_FLAG) - return 0; + DBUG_RETURN(0); length+= field->max_packed_col_length(field->pack_length()); if (field->maybe_null()) null_fields++; fields++; } if (!fields) - return 0; + DBUG_RETURN(0); length+= (null_fields+7)/8; if (length+sortlength > max_length_for_sort_data || - !(addonf= (SORT_ADDON_FIELD *) my_malloc(sizeof(SORT_ADDON_FIELD)* - (fields+1), - MYF(MY_WME | - MY_THREAD_SPECIFIC)))) - return 0; + !my_multi_malloc(MYF(MY_WME | MY_THREAD_SPECIFIC), + &addonf, sizeof(SORT_ADDON_FIELD) * (fields+1), + &addon_buf->str, length, + NullS)) - *plength= length; + DBUG_RETURN(0); + + addon_buf->length= length; length= (null_fields+7)/8; null_fields= 0; for (pfield= ptabfield; (field= *pfield) ; pfield++) @@ -2132,7 +2091,7 @@ get_addon_fields(ulong max_length_for_sort_data, addonf->field= 0; // Put end marker DBUG_PRINT("info",("addon_length: %d",length)); - return (addonf-fields); + DBUG_RETURN(addonf-fields); } @@ -2218,3 +2177,13 @@ void change_double_for_sort(double nr,uchar *to) } } +/** + Free SORT_INFO +*/ + +SORT_INFO::~SORT_INFO() +{ + DBUG_ENTER("~SORT_INFO::SORT_INFO()"); + free_data(); + DBUG_VOID_RETURN; +} diff --git a/sql/filesort.h b/sql/filesort.h index 16ea89ec55a..6d665dbe0aa 100644 --- a/sql/filesort.h +++ b/sql/filesort.h @@ -16,11 +16,9 @@ #ifndef FILESORT_INCLUDED #define FILESORT_INCLUDED -class SQL_SELECT; - -#include "my_global.h" /* uint, uchar */ #include "my_base.h" /* ha_rows */ #include "sql_list.h" /* Sql_alloc */ +#include "filesort_utils.h" class SQL_SELECT; class THD; @@ -71,10 +69,88 @@ private: void cleanup(); }; -ha_rows filesort(THD *thd, TABLE *table, Filesort *filesort, - bool sort_positions, ha_rows *examined_rows, - ha_rows *found_rows, Filesort_tracker* tracker); -void filesort_free_buffers(TABLE *table, bool full); + +class SORT_INFO +{ + /// Buffer for sorting keys. + Filesort_buffer filesort_buffer; + +public: + SORT_INFO() + :addon_field(0), record_pointers(0) + { + buffpek.str= 0; + my_b_clear(&io_cache); + } + + ~SORT_INFO(); + + void free_data() + { + close_cached_file(&io_cache); + my_free(record_pointers); + my_free(buffpek.str); + my_free(addon_field); + } + + void reset() + { + free_data(); + record_pointers= 0; + buffpek.str= 0; + addon_field= 0; + } + + + IO_CACHE io_cache; /* If sorted through filesort */ + LEX_STRING buffpek; /* Buffer for buffpek structures */ + LEX_STRING addon_buf; /* Pointer to a buffer if sorted with fields */ + struct st_sort_addon_field *addon_field; /* Pointer to the fields info */ + /* To unpack back */ + void (*unpack)(struct st_sort_addon_field *, uchar *, uchar *); + uchar *record_pointers; /* If sorted in memory */ + /* + How many rows in final result. + Also how many rows in record_pointers, if used + */ + ha_rows return_rows; + ha_rows examined_rows; /* How many rows read */ + ha_rows found_rows; /* How many rows was accepted */ + + /** Sort filesort_buffer */ + void sort_buffer(Sort_param *param, uint count) + { filesort_buffer.sort_buffer(param, count); } + + /** + Accessors for Filesort_buffer (which @c). + */ + uchar *get_record_buffer(uint idx) + { return filesort_buffer.get_record_buffer(idx); } + + uchar **get_sort_keys() + { return filesort_buffer.get_sort_keys(); } + + uchar **alloc_sort_buffer(uint num_records, uint record_length) + { return filesort_buffer.alloc_sort_buffer(num_records, record_length); } + + void free_sort_buffer() + { filesort_buffer.free_sort_buffer(); } + + void init_record_pointers() + { filesort_buffer.init_record_pointers(); } + + size_t sort_buffer_size() const + { return filesort_buffer.sort_buffer_size(); } + + friend SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, + bool sort_positions, + Filesort_tracker* tracker); +}; + +SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort, + bool sort_positions, + Filesort_tracker* tracker); + void change_double_for_sort(double nr,uchar *to); #endif /* FILESORT_INCLUDED */ diff --git a/sql/filesort_utils.cc b/sql/filesort_utils.cc index 1cef30b6a56..34110dcfc1f 100644 --- a/sql/filesort_utils.cc +++ b/sql/filesort_utils.cc @@ -85,31 +85,66 @@ double get_merge_many_buffs_cost_fast(ha_rows num_rows, return total_cost; } -uchar **Filesort_buffer::alloc_sort_buffer(uint num_records, uint record_length) -{ - ulong sort_buff_sz; +/* + alloc_sort_buffer() - DBUG_ENTER("alloc_sort_buffer"); + Allocate buffer for sorting keys. + Try to reuse old buffer if possible. + @return + 0 Error + # Pointer to allocated buffer +*/ + +uchar **Filesort_buffer::alloc_sort_buffer(uint num_records, + uint record_length) +{ + size_t buff_size; + uchar **sort_keys, **start_of_data; + DBUG_ENTER("alloc_sort_buffer"); DBUG_EXECUTE_IF("alloc_sort_buffer_fail", DBUG_SET("+d,simulate_out_of_memory");); - if (m_idx_array.is_null()) + buff_size= num_records * (record_length + sizeof(uchar*)); + set_if_bigger(buff_size, record_length * MERGEBUFF2); + + if (!m_idx_array.is_null()) { - sort_buff_sz= num_records * (record_length + sizeof(uchar*)); - set_if_bigger(sort_buff_sz, record_length * MERGEBUFF2); - uchar **sort_keys= - (uchar**) my_malloc(sort_buff_sz, MYF(MY_THREAD_SPECIFIC)); - m_idx_array= Idx_array(sort_keys, num_records); - m_record_length= record_length; - uchar **start_of_data= m_idx_array.array() + m_idx_array.size(); - m_start_of_data= reinterpret_cast<uchar*>(start_of_data); + /* + Reuse old buffer if exists and is large enough + Note that we don't make the buffer smaller, as we want to be + prepared for next subquery iteration. + */ + + sort_keys= m_idx_array.array(); + if (buff_size > allocated_size) + { + /* + Better to free and alloc than realloc as we don't have to remember + the old values + */ + my_free(sort_keys); + if (!(sort_keys= (uchar**) my_malloc(buff_size, + MYF(MY_THREAD_SPECIFIC)))) + { + reset(); + DBUG_RETURN(0); + } + allocated_size= buff_size; + } } else { - DBUG_ASSERT(num_records == m_idx_array.size()); - DBUG_ASSERT(record_length == m_record_length); + if (!(sort_keys= (uchar**) my_malloc(buff_size, MYF(MY_THREAD_SPECIFIC)))) + DBUG_RETURN(0); + allocated_size= buff_size; } + + m_idx_array= Idx_array(sort_keys, num_records); + m_record_length= record_length; + start_of_data= m_idx_array.array() + m_idx_array.size(); + m_start_of_data= reinterpret_cast<uchar*>(start_of_data); + DBUG_RETURN(m_idx_array.array()); } @@ -117,8 +152,7 @@ uchar **Filesort_buffer::alloc_sort_buffer(uint num_records, uint record_length) void Filesort_buffer::free_sort_buffer() { my_free(m_idx_array.array()); - m_idx_array= Idx_array(); - m_record_length= 0; + m_idx_array.reset(); m_start_of_data= NULL; } diff --git a/sql/filesort_utils.h b/sql/filesort_utils.h index 00fa6f2566b..d537b602edf 100644 --- a/sql/filesort_utils.h +++ b/sql/filesort_utils.h @@ -60,9 +60,23 @@ double get_merge_many_buffs_cost_fast(ha_rows num_rows, class Filesort_buffer { public: - Filesort_buffer() : - m_idx_array(), m_record_length(0), m_start_of_data(NULL) + Filesort_buffer() + : m_idx_array(), m_start_of_data(NULL), allocated_size(0) {} + + ~Filesort_buffer() + { + my_free(m_idx_array.array()); + } + + bool is_allocated() + { + return m_idx_array.array() != 0; + } + void reset() + { + m_idx_array.reset(); + } /** Sort me... */ void sort_buffer(const Sort_param *param, uint count); @@ -84,20 +98,12 @@ public: /// Returns total size: pointer array + record buffers. size_t sort_buffer_size() const { - return m_idx_array.size() * (m_record_length + sizeof(uchar*)); + return allocated_size; } /// Allocates the buffer, but does *not* initialize pointers. uchar **alloc_sort_buffer(uint num_records, uint record_length); - - /// Check <num_records, record_length> for the buffer - bool check_sort_buffer_properties(uint num_records, uint record_length) - { - return (static_cast<uint>(m_idx_array.size()) == num_records && - m_record_length == record_length); - } - /// Frees the buffer. void free_sort_buffer(); @@ -115,15 +121,17 @@ public: m_idx_array= rhs.m_idx_array; m_record_length= rhs.m_record_length; m_start_of_data= rhs.m_start_of_data; + allocated_size= rhs.allocated_size; return *this; } private: typedef Bounds_checked_array<uchar*> Idx_array; - Idx_array m_idx_array; + Idx_array m_idx_array; /* Pointers to key data */ uint m_record_length; - uchar *m_start_of_data; + uchar *m_start_of_data; /* Start of key data */ + size_t allocated_size; }; #endif // FILESORT_UTILS_INCLUDED diff --git a/sql/gcalc_slicescan.cc b/sql/gcalc_slicescan.cc index ed533abdaf4..f62c413fd35 100644 --- a/sql/gcalc_slicescan.cc +++ b/sql/gcalc_slicescan.cc @@ -49,14 +49,14 @@ typedef int (*sc_compare_func)(const void*, const void*); static Gcalc_scan_iterator::point *eq_sp(const Gcalc_heap::Info *pi) { GCALC_DBUG_ASSERT(pi->type == Gcalc_heap::nt_eq_node); - return (Gcalc_scan_iterator::point *) pi->eq_data; + return (Gcalc_scan_iterator::point *) pi->node.eq.data; } static Gcalc_scan_iterator::intersection_info *i_data(const Gcalc_heap::Info *pi) { GCALC_DBUG_ASSERT(pi->type == Gcalc_heap::nt_intersection); - return (Gcalc_scan_iterator::intersection_info *) pi->intersection_data; + return (Gcalc_scan_iterator::intersection_info *) pi->node.intersection.data; } @@ -103,8 +103,8 @@ const char *gcalc_ev_name(int ev) static int gcalc_pi_str(char *str, const Gcalc_heap::Info *pi, const char *postfix) { return sprintf(str, "%s %d %d | %s %d %d%s", - GCALC_SIGN(pi->ix[0]) ? "-":"", FIRST_DIGIT(pi->ix[0]),pi->ix[1], - GCALC_SIGN(pi->iy[0]) ? "-":"", FIRST_DIGIT(pi->iy[0]),pi->iy[1], + GCALC_SIGN(pi->node.shape.ix[0]) ? "-":"", FIRST_DIGIT(pi->node.shape.ix[0]),pi->node.shape.ix[1], + GCALC_SIGN(pi->node.shape.iy[0]) ? "-":"", FIRST_DIGIT(pi->node.shape.iy[0]),pi->node.shape.iy[1], postfix); } @@ -594,8 +594,8 @@ void Gcalc_scan_iterator::intersection_info::do_calc_t() Gcalc_coord1 a2_a1x, a2_a1y; Gcalc_coord2 x1y2, x2y1; - gcalc_sub_coord1(a2_a1x, edge_b->pi->ix, edge_a->pi->ix); - gcalc_sub_coord1(a2_a1y, edge_b->pi->iy, edge_a->pi->iy); + gcalc_sub_coord1(a2_a1x, edge_b->pi->node.shape.ix, edge_a->pi->node.shape.ix); + gcalc_sub_coord1(a2_a1y, edge_b->pi->node.shape.iy, edge_a->pi->node.shape.iy); GCALC_DBUG_ASSERT(!gcalc_is_zero(edge_a->dy, GCALC_COORD_BASE) || !gcalc_is_zero(edge_b->dy, GCALC_COORD_BASE)); @@ -619,7 +619,7 @@ void Gcalc_scan_iterator::intersection_info::do_calc_y() Gcalc_coord3 a_tb, b_ta; gcalc_mul_coord(a_tb, GCALC_COORD_BASE3, - t_b, GCALC_COORD_BASE2, edge_a->pi->iy, GCALC_COORD_BASE); + t_b, GCALC_COORD_BASE2, edge_a->pi->node.shape.iy, GCALC_COORD_BASE); gcalc_mul_coord(b_ta, GCALC_COORD_BASE3, t_a, GCALC_COORD_BASE2, edge_a->dy, GCALC_COORD_BASE); @@ -635,7 +635,7 @@ void Gcalc_scan_iterator::intersection_info::do_calc_x() Gcalc_coord3 a_tb, b_ta; gcalc_mul_coord(a_tb, GCALC_COORD_BASE3, - t_b, GCALC_COORD_BASE2, edge_a->pi->ix, GCALC_COORD_BASE); + t_b, GCALC_COORD_BASE2, edge_a->pi->node.shape.ix, GCALC_COORD_BASE); gcalc_mul_coord(b_ta, GCALC_COORD_BASE3, t_a, GCALC_COORD_BASE2, edge_a->dx, GCALC_COORD_BASE); @@ -656,7 +656,7 @@ static int cmp_node_isc(const Gcalc_heap::Info *node, inf->calc_y_exp(); gcalc_mul_coord(exp, GCALC_COORD_BASE3, - inf->t_b, GCALC_COORD_BASE2, node->iy, GCALC_COORD_BASE); + inf->t_b, GCALC_COORD_BASE2, node->node.shape.iy, GCALC_COORD_BASE); result= gcalc_cmp_coord(exp, inf->y_exp, GCALC_COORD_BASE3); #ifdef GCALC_CHECK_WITH_FLOAT @@ -664,18 +664,18 @@ static int cmp_node_isc(const Gcalc_heap::Info *node, isc->calc_xy_ld(&int_x, &int_y); if (result < 0) { - if (!de_check(int_y, node->y) && node->y > int_y) - GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g < %LG", node->y, int_y)); + if (!de_check(int_y, node->node.shape.y) && node->node.shape.y > int_y) + GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g < %LG", node->node.shape.y, int_y)); } else if (result > 0) { - if (!de_check(int_y, node->y) && node->y < int_y) - GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g > %LG", node->y, int_y)); + if (!de_check(int_y, node->node.shape.y) && node->node.shape.y < int_y) + GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g > %LG", node->node.shape.y, int_y)); } else { - if (!de_check(int_y, node->y)) - GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g == %LG", node->y, int_y)); + if (!de_check(int_y, node->node.shape.y)) + GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g == %LG", node->node.shape.y, int_y)); } #endif /*GCALC_CHECK_WITH_FLOAT*/ if (result) @@ -684,27 +684,27 @@ static int cmp_node_isc(const Gcalc_heap::Info *node, inf->calc_x_exp(); gcalc_mul_coord(exp, GCALC_COORD_BASE3, - inf->t_b, GCALC_COORD_BASE2, node->ix, GCALC_COORD_BASE); + inf->t_b, GCALC_COORD_BASE2, node->node.shape.ix, GCALC_COORD_BASE); result= gcalc_cmp_coord(exp, inf->x_exp, GCALC_COORD_BASE3); #ifdef GCALC_CHECK_WITH_FLOAT if (result < 0) { - if (!de_check(int_x, node->x) && node->x > int_x) + if (!de_check(int_x, node->node.shape.x) && node->node.shape.x > int_x) GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscx failed %g < %LG", - node->x, int_x)); + node->node.shape.x, int_x)); } else if (result > 0) { - if (!de_check(int_x, node->x) && node->x < int_x) + if (!de_check(int_x, node->node.shape.x) && node->node.shape.x < int_x) GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscx failed %g > %LG", - node->x, int_x)); + node->node.shape.x, int_x)); } else { - if (!de_check(int_x, node->x)) + if (!de_check(int_x, node->node.shape.x)) GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscx failed %g == %LG", - node->x, int_x)); + node->node.shape.x, int_x)); } #endif /*GCALC_CHECK_WITH_FLOAT*/ exit: @@ -844,13 +844,13 @@ Gcalc_heap::Info *Gcalc_heap::new_point_info(double x, double y, return NULL; *m_hook= result; m_hook= &result->next; - result->x= x; - result->y= y; - result->shape= shape; - result->top_node= 1; + result->node.shape.x= x; + result->node.shape.y= y; + result->node.shape.shape= shape; + result->node.shape.top_node= 1; result->type= nt_shape_node; - gcalc_set_double(result->ix, x, coord_extent); - gcalc_set_double(result->iy, y, coord_extent); + gcalc_set_double(result->node.shape.ix, x, coord_extent); + gcalc_set_double(result->node.shape.iy, y, coord_extent); m_n_points++; return result; @@ -864,11 +864,11 @@ static Gcalc_heap::Info *new_intersection( if (!isc) return 0; isc->type= Gcalc_heap::nt_intersection; - isc->p1= ii->edge_a->pi; - isc->p2= ii->edge_a->next_pi; - isc->p3= ii->edge_b->pi; - isc->p4= ii->edge_b->next_pi; - isc->intersection_data= ii; + isc->node.intersection.p1= ii->edge_a->pi; + isc->node.intersection.p2= ii->edge_a->next_pi; + isc->node.intersection.p3= ii->edge_b->pi; + isc->node.intersection.p4= ii->edge_b->next_pi; + isc->node.intersection.data= ii; return isc; } @@ -881,46 +881,46 @@ static Gcalc_heap::Info *new_eq_point( if (!eqp) return 0; eqp->type= Gcalc_heap::nt_eq_node; - eqp->node= p; - eqp->eq_data= edge; + eqp->node.eq.node= p; + eqp->node.eq.data= edge; return eqp; } void Gcalc_heap::Info::calc_xy(double *x, double *y) const { - double b0_x= p2->x - p1->x; - double b0_y= p2->y - p1->y; - double b1_x= p4->x - p3->x; - double b1_y= p4->y - p3->y; + double b0_x= node.intersection.p2->node.shape.x - node.intersection.p1->node.shape.x; + double b0_y= node.intersection.p2->node.shape.y - node.intersection.p1->node.shape.y; + double b1_x= node.intersection.p4->node.shape.x - node.intersection.p3->node.shape.x; + double b1_y= node.intersection.p4->node.shape.y - node.intersection.p3->node.shape.y; double b0xb1= b0_x * b1_y - b0_y * b1_x; - double t= (p3->x - p1->x) * b1_y - (p3->y - p1->y) * b1_x; + double t= (node.intersection.p3->node.shape.x - node.intersection.p1->node.shape.x) * b1_y - (node.intersection.p3->node.shape.y - node.intersection.p1->node.shape.y) * b1_x; t/= b0xb1; - *x= p1->x + b0_x * t; - *y= p1->y + b0_y * t; + *x= node.intersection.p1->node.shape.x + b0_x * t; + *y= node.intersection.p1->node.shape.y + b0_y * t; } #ifdef GCALC_CHECK_WITH_FLOAT void Gcalc_heap::Info::calc_xy_ld(long double *x, long double *y) const { - long double b0_x= ((long double) p2->x) - p1->x; - long double b0_y= ((long double) p2->y) - p1->y; - long double b1_x= ((long double) p4->x) - p3->x; - long double b1_y= ((long double) p4->y) - p3->y; + long double b0_x= ((long double) p2->node.shape.x) - p1->node.shape.x; + long double b0_y= ((long double) p2->node.shape.y) - p1->node.shape.y; + long double b1_x= ((long double) p4->node.shape.x) - p3->node.shape.x; + long double b1_y= ((long double) p4->node.shape.y) - p3->node.shape.y; long double b0xb1= b0_x * b1_y - b0_y * b1_x; - long double ax= ((long double) p3->x) - p1->x; - long double ay= ((long double) p3->y) - p1->y; + long double ax= ((long double) p3->node.shape.x) - p1->node.shape.x; + long double ay= ((long double) p3->node.shape.y) - p1->node.shape.y; long double t_a= ax * b1_y - ay * b1_x; - long double hx= (b0xb1 * (long double) p1->x + b0_x * t_a); - long double hy= (b0xb1 * (long double) p1->y + b0_y * t_a); + long double hx= (b0xb1 * (long double) p1->node.shape.x + b0_x * t_a); + long double hy= (b0xb1 * (long double) p1->node.shape.y + b0_y * t_a); if (fabs(b0xb1) < 1e-15) { - *x= p1->x; - *y= p1->y; + *x= p1->node.shape.x; + *y= p1->node.shape.y; return; } @@ -933,10 +933,10 @@ void Gcalc_heap::Info::calc_xy_ld(long double *x, long double *y) const static int cmp_point_info(const Gcalc_heap::Info *i0, const Gcalc_heap::Info *i1) { - int cmp_y= gcalc_cmp_coord1(i0->iy, i1->iy); + int cmp_y= gcalc_cmp_coord1(i0->node.shape.iy, i1->node.shape.iy); if (cmp_y) return cmp_y; - return gcalc_cmp_coord1(i0->ix, i1->ix); + return gcalc_cmp_coord1(i0->node.shape.ix, i1->node.shape.ix); } @@ -944,11 +944,11 @@ static inline void trim_node(Gcalc_heap::Info *node, Gcalc_heap::Info *prev_node { if (!node) return; - node->top_node= 0; - GCALC_DBUG_ASSERT((node->left == prev_node) || (node->right == prev_node)); - if (node->left == prev_node) - node->left= node->right; - node->right= NULL; + node->node.shape.top_node= 0; + GCALC_DBUG_ASSERT((node->node.shape.left == prev_node) || (node->node.shape.right == prev_node)); + if (node->node.shape.left == prev_node) + node->node.shape.left= node->node.shape.right; + node->node.shape.right= NULL; GCALC_DBUG_ASSERT(cmp_point_info(node, prev_node)); } @@ -972,8 +972,8 @@ void Gcalc_heap::prepare_operation() /* TODO - move this to the 'normal_scan' loop */ for (cur= get_first(); cur; cur= cur->get_next()) { - trim_node(cur->left, cur); - trim_node(cur->right, cur); + trim_node(cur->node.shape.left, cur); + trim_node(cur->node.shape.right, cur); } } @@ -995,7 +995,7 @@ int Gcalc_shape_transporter::int_single_point(gcalc_shape_info Info, Gcalc_heap::Info *point= m_heap->new_point_info(x, y, Info); if (!point) return 1; - point->left= point->right= 0; + point->node.shape.left= point->node.shape.right= 0; return 0; } @@ -1018,9 +1018,9 @@ int Gcalc_shape_transporter::int_add_point(gcalc_shape_info Info, m_heap->free_point_info(point, hook); return 0; } - GCALC_DBUG_ASSERT(!m_prev || m_prev->x != x || m_prev->y != y); - m_prev->left= point; - point->right= m_prev; + GCALC_DBUG_ASSERT(!m_prev || m_prev->node.shape.x != x || m_prev->node.shape.y != y); + m_prev->node.shape.left= point; + point->node.shape.right= m_prev; } else m_first= point; @@ -1040,16 +1040,16 @@ void Gcalc_shape_transporter::int_complete() /* simple point */ if (m_first == m_prev) { - m_first->right= m_first->left= NULL; + m_first->node.shape.right= m_first->node.shape.left= NULL; return; } /* line */ if (m_shape_started == 1) { - m_first->right= NULL; - m_prev->left= m_prev->right; - m_prev->right= NULL; + m_first->node.shape.right= NULL; + m_prev->node.shape.left= m_prev->node.shape.right; + m_prev->node.shape.right= NULL; return; } @@ -1057,32 +1057,32 @@ void Gcalc_shape_transporter::int_complete() if (cmp_point_info(m_first, m_prev) == 0) { /* Coinciding points, remove the last one from the list */ - m_prev->right->left= m_first; - m_first->right= m_prev->right; + m_prev->node.shape.right->node.shape.left= m_first; + m_first->node.shape.right= m_prev->node.shape.right; m_heap->free_point_info(m_prev, m_prev_hook); } else { - GCALC_DBUG_ASSERT(m_prev->x != m_first->x || m_prev->y != m_first->y); - m_first->right= m_prev; - m_prev->left= m_first; + GCALC_DBUG_ASSERT(m_prev->node.shape.x != m_first->node.shape.x || m_prev->node.shape.y != m_first->node.shape.y); + m_first->node.shape.right= m_prev; + m_prev->node.shape.left= m_first; } } inline void calc_dx_dy(Gcalc_scan_iterator::point *p) { - gcalc_sub_coord1(p->dx, p->next_pi->ix, p->pi->ix); - gcalc_sub_coord1(p->dy, p->next_pi->iy, p->pi->iy); + gcalc_sub_coord1(p->dx, p->next_pi->node.shape.ix, p->pi->node.shape.ix); + gcalc_sub_coord1(p->dy, p->next_pi->node.shape.iy, p->pi->node.shape.iy); if (GCALC_SIGN(p->dx[0])) { - p->l_border= &p->next_pi->ix; - p->r_border= &p->pi->ix; + p->l_border= &p->next_pi->node.shape.ix; + p->r_border= &p->pi->node.shape.ix; } else { - p->r_border= &p->next_pi->ix; - p->l_border= &p->pi->ix; + p->r_border= &p->next_pi->node.shape.ix; + p->l_border= &p->pi->node.shape.ix; } } @@ -1143,10 +1143,10 @@ int Gcalc_scan_iterator::point::cmp_dx_dy(const Gcalc_heap::Info *p1, const Gcalc_heap::Info *p4) { Gcalc_coord1 dx_a, dy_a, dx_b, dy_b; - gcalc_sub_coord1(dx_a, p2->ix, p1->ix); - gcalc_sub_coord1(dy_a, p2->iy, p1->iy); - gcalc_sub_coord1(dx_b, p4->ix, p3->ix); - gcalc_sub_coord1(dy_b, p4->iy, p3->iy); + gcalc_sub_coord1(dx_a, p2->node.shape.ix, p1->node.shape.ix); + gcalc_sub_coord1(dy_a, p2->node.shape.iy, p1->node.shape.iy); + gcalc_sub_coord1(dx_b, p4->node.shape.ix, p3->node.shape.ix); + gcalc_sub_coord1(dy_b, p4->node.shape.iy, p3->node.shape.iy); return cmp_dx_dy(dx_a, dy_a, dx_b, dy_b); } @@ -1168,8 +1168,8 @@ void Gcalc_scan_iterator::point::calc_x(long double *x, long double y, *x= ix; } else - *x= (ddy * (long double) pi->x + gcalc_get_double(dx, GCALC_COORD_BASE) * - (y - pi->y)) / ddy; + *x= (ddy * (long double) pi->node.shape.x + gcalc_get_double(dx, GCALC_COORD_BASE) * + (y - pi->node.shape.y)) / ddy; } #endif /*GCALC_CHECK_WITH_FLOAT*/ @@ -1280,7 +1280,7 @@ int Gcalc_scan_iterator::arrange_event(int do_sorting, int n_intersections) int Gcalc_heap::Info::equal_pi(const Info *pi) const { if (type == nt_intersection) - return equal_intersection; + return node.intersection.equal; if (pi->type == nt_eq_node) return 1; if (type == nt_eq_node || pi->type == nt_intersection) @@ -1322,7 +1322,7 @@ int Gcalc_scan_iterator::step() #ifndef GCALC_DBUG_OFF if (m_cur_pi->type == Gcalc_heap::nt_intersection && m_cur_pi->get_next()->type == Gcalc_heap::nt_intersection && - m_cur_pi->equal_intersection) + m_cur_pi->node.intersection.equal) GCALC_DBUG_ASSERT(cmp_intersections(m_cur_pi, m_cur_pi->get_next()) == 0); #endif /*GCALC_DBUG_OFF*/ GCALC_DBUG_CHECK_COUNTER(); @@ -1377,23 +1377,23 @@ static int node_on_right(const Gcalc_heap::Info *node, Gcalc_coord2 ax_by, ay_bx; int result; - gcalc_sub_coord1(a_x, node->ix, edge_a->ix); - gcalc_sub_coord1(a_y, node->iy, edge_a->iy); - gcalc_sub_coord1(b_x, edge_b->ix, edge_a->ix); - gcalc_sub_coord1(b_y, edge_b->iy, edge_a->iy); + gcalc_sub_coord1(a_x, node->node.shape.ix, edge_a->node.shape.ix); + gcalc_sub_coord1(a_y, node->node.shape.iy, edge_a->node.shape.iy); + gcalc_sub_coord1(b_x, edge_b->node.shape.ix, edge_a->node.shape.ix); + gcalc_sub_coord1(b_y, edge_b->node.shape.iy, edge_a->node.shape.iy); gcalc_mul_coord1(ax_by, a_x, b_y); gcalc_mul_coord1(ay_bx, a_y, b_x); result= gcalc_cmp_coord(ax_by, ay_bx, GCALC_COORD_BASE2); #ifdef GCALC_CHECK_WITH_FLOAT { - long double dx= gcalc_get_double(edge_b->ix, GCALC_COORD_BASE) - - gcalc_get_double(edge_a->ix, GCALC_COORD_BASE); - long double dy= gcalc_get_double(edge_b->iy, GCALC_COORD_BASE) - - gcalc_get_double(edge_a->iy, GCALC_COORD_BASE); - long double ax= gcalc_get_double(node->ix, GCALC_COORD_BASE) - - gcalc_get_double(edge_a->ix, GCALC_COORD_BASE); - long double ay= gcalc_get_double(node->iy, GCALC_COORD_BASE) - - gcalc_get_double(edge_a->iy, GCALC_COORD_BASE); + long double dx= gcalc_get_double(edge_b->node.shape.ix, GCALC_COORD_BASE) - + gcalc_get_double(edge_a->node.shape.ix, GCALC_COORD_BASE); + long double dy= gcalc_get_double(edge_b->node.shape.iy, GCALC_COORD_BASE) - + gcalc_get_double(edge_a->node.shape.iy, GCALC_COORD_BASE); + long double ax= gcalc_get_double(node->node.shape.ix, GCALC_COORD_BASE) - + gcalc_get_double(edge_a->node.shape.ix, GCALC_COORD_BASE); + long double ay= gcalc_get_double(node->node.shape.iy, GCALC_COORD_BASE) - + gcalc_get_double(edge_a->node.shape.iy, GCALC_COORD_BASE); long double d= ax * dy - ay * dx; if (result == 0) GCALC_DBUG_ASSERT(de_check(d, 0.0)); @@ -1412,8 +1412,8 @@ static int cmp_tops(const Gcalc_heap::Info *top_node, { int cmp_res_a, cmp_res_b; - cmp_res_a= gcalc_cmp_coord1(edge_a->ix, top_node->ix); - cmp_res_b= gcalc_cmp_coord1(edge_b->ix, top_node->ix); + cmp_res_a= gcalc_cmp_coord1(edge_a->node.shape.ix, top_node->node.shape.ix); + cmp_res_b= gcalc_cmp_coord1(edge_b->node.shape.ix, top_node->node.shape.ix); if (cmp_res_a <= 0 && cmp_res_b > 0) return -1; @@ -1438,26 +1438,26 @@ int Gcalc_scan_iterator::insert_top_node() if (!sp0) GCALC_DBUG_RETURN(1); sp0->pi= m_cur_pi; - sp0->next_pi= m_cur_pi->left; + sp0->next_pi= m_cur_pi->node.shape.left; #ifndef GCALC_DBUG_OFF sp0->thread= m_cur_thread++; #endif /*GCALC_DBUG_OFF*/ - if (m_cur_pi->left) + if (m_cur_pi->node.shape.left) { calc_dx_dy(sp0); - if (m_cur_pi->right) + if (m_cur_pi->node.shape.right) { if (!(sp1= new_slice_point())) GCALC_DBUG_RETURN(1); sp1->event= sp0->event= scev_two_threads; sp1->pi= m_cur_pi; - sp1->next_pi= m_cur_pi->right; + sp1->next_pi= m_cur_pi->node.shape.right; #ifndef GCALC_DBUG_OFF sp1->thread= m_cur_thread++; #endif /*GCALC_DBUG_OFF*/ calc_dx_dy(sp1); /* We have two threads so should decide which one will be first */ - cmp_res= cmp_tops(m_cur_pi, m_cur_pi->left, m_cur_pi->right); + cmp_res= cmp_tops(m_cur_pi, m_cur_pi->node.shape.left, m_cur_pi->node.shape.right); if (cmp_res > 0) { point *tmp= sp0; @@ -1467,7 +1467,7 @@ int Gcalc_scan_iterator::insert_top_node() else if (cmp_res == 0) { /* Exactly same direction of the edges. */ - cmp_res= gcalc_cmp_coord1(m_cur_pi->left->iy, m_cur_pi->right->iy); + cmp_res= gcalc_cmp_coord1(m_cur_pi->node.shape.left->node.shape.iy, m_cur_pi->node.shape.right->node.shape.iy); if (cmp_res != 0) { if (cmp_res < 0) @@ -1483,7 +1483,7 @@ int Gcalc_scan_iterator::insert_top_node() } else { - cmp_res= gcalc_cmp_coord1(m_cur_pi->left->ix, m_cur_pi->right->ix); + cmp_res= gcalc_cmp_coord1(m_cur_pi->node.shape.left->node.shape.ix, m_cur_pi->node.shape.right->node.shape.ix); if (cmp_res != 0) { if (cmp_res < 0) @@ -1517,7 +1517,7 @@ int Gcalc_scan_iterator::insert_top_node() /* We need to find the place to insert. */ for (; sp; prev_hook= sp->next_ptr(), sp=sp->get_next()) { - if (sp->event || gcalc_cmp_coord1(*sp->r_border, m_cur_pi->ix) < 0) + if (sp->event || gcalc_cmp_coord1(*sp->r_border, m_cur_pi->node.shape.ix) < 0) continue; cmp_res= node_on_right(m_cur_pi, sp->pi, sp->next_pi); if (cmp_res == 0) @@ -1743,7 +1743,7 @@ int Gcalc_scan_iterator::node_scan() GCALC_DBUG_PRINT(("node for %d", sp->thread)); /* Handle the point itself. */ sp->pi= cur_pi; - sp->next_pi= cur_pi->left; + sp->next_pi= cur_pi->node.shape.left; sp->event= scev_point; calc_dx_dy(sp); @@ -1794,7 +1794,7 @@ void Gcalc_scan_iterator::intersection_scan() ii->edge_a->event= ii->edge_b->event= scev_intersection; ii->edge_a->ev_pi= ii->edge_b->ev_pi= m_cur_pi; free_item(ii); - m_cur_pi->intersection_data= NULL; + m_cur_pi->node.intersection.data= NULL; GCALC_DBUG_VOID_RETURN; } @@ -1813,7 +1813,7 @@ int Gcalc_scan_iterator::add_intersection(point *sp_a, point *sp_b, !(ii= new_intersection(m_heap, i_calc))) GCALC_DBUG_RETURN(1); - ii->equal_intersection= 0; + ii->node.intersection.equal= 0; for (; pi_from->get_next() != sp_a->next_pi && @@ -1824,7 +1824,7 @@ int Gcalc_scan_iterator::add_intersection(point *sp_a, point *sp_b, if (skip_next) { if (cur->type == Gcalc_heap::nt_intersection) - skip_next= cur->equal_intersection; + skip_next= cur->node.intersection.equal; else skip_next= 0; continue; @@ -1832,7 +1832,7 @@ int Gcalc_scan_iterator::add_intersection(point *sp_a, point *sp_b, if (cur->type == Gcalc_heap::nt_intersection) { cmp_res= cmp_intersections(cur, ii); - skip_next= cur->equal_intersection; + skip_next= cur->node.intersection.equal; } else if (cur->type == Gcalc_heap::nt_eq_node) continue; @@ -1840,7 +1840,7 @@ int Gcalc_scan_iterator::add_intersection(point *sp_a, point *sp_b, cmp_res= cmp_node_isc(cur, ii); if (cmp_res == 0) { - ii->equal_intersection= 1; + ii->node.intersection.equal= 1; break; } else if (cmp_res > 0) @@ -1881,13 +1881,13 @@ void calc_t(Gcalc_coord2 t_a, Gcalc_coord2 t_b, Gcalc_coord2 x1y2, x2y1; Gcalc_coord1 dya, dyb; - gcalc_sub_coord1(a2_a1x, p3->ix, p1->ix); - gcalc_sub_coord1(a2_a1y, p3->iy, p1->iy); + gcalc_sub_coord1(a2_a1x, p3->node.shape.ix, p1->node.shape.ix); + gcalc_sub_coord1(a2_a1y, p3->node.shape.iy, p1->node.shape.iy); - gcalc_sub_coord1(dxa, p2->ix, p1->ix); - gcalc_sub_coord1(dya, p2->iy, p1->iy); - gcalc_sub_coord1(dxb, p4->ix, p3->ix); - gcalc_sub_coord1(dyb, p4->iy, p3->iy); + gcalc_sub_coord1(dxa, p2->node.shape.ix, p1->node.shape.ix); + gcalc_sub_coord1(dya, p2->node.shape.iy, p1->node.shape.iy); + gcalc_sub_coord1(dxb, p4->node.shape.ix, p3->node.shape.ix); + gcalc_sub_coord1(dyb, p4->node.shape.iy, p3->node.shape.iy); gcalc_mul_coord1(x1y2, dxa, dyb); gcalc_mul_coord1(x2y1, dya, dxb); @@ -1908,11 +1908,11 @@ double Gcalc_scan_iterator::get_y() const Gcalc_coord2 t_a, t_b; Gcalc_coord3 a_tb, b_ta, y_exp; calc_t(t_a, t_b, dxa, dya, - state.pi->p1, state.pi->p2, state.pi->p3, state.pi->p4); + state.pi->node.intersection.p1, state.pi->node.intersection.p2, state.pi->node.intersection.p3, state.pi->node.intersection.p4); gcalc_mul_coord(a_tb, GCALC_COORD_BASE3, - t_b, GCALC_COORD_BASE2, state.pi->p1->iy, GCALC_COORD_BASE); + t_b, GCALC_COORD_BASE2, state.pi->node.intersection.p1->node.shape.iy, GCALC_COORD_BASE); gcalc_mul_coord(b_ta, GCALC_COORD_BASE3, t_a, GCALC_COORD_BASE2, dya, GCALC_COORD_BASE); @@ -1922,7 +1922,7 @@ double Gcalc_scan_iterator::get_y() const get_pure_double(t_b, GCALC_COORD_BASE2)) / m_heap->coord_extent; } else - return state.pi->y; + return state.pi->node.shape.y; } @@ -1934,11 +1934,11 @@ double Gcalc_scan_iterator::get_event_x() const Gcalc_coord2 t_a, t_b; Gcalc_coord3 a_tb, b_ta, x_exp; calc_t(t_a, t_b, dxa, dya, - state.pi->p1, state.pi->p2, state.pi->p3, state.pi->p4); + state.pi->node.intersection.p1, state.pi->node.intersection.p2, state.pi->node.intersection.p3, state.pi->node.intersection.p4); gcalc_mul_coord(a_tb, GCALC_COORD_BASE3, - t_b, GCALC_COORD_BASE2, state.pi->p1->ix, GCALC_COORD_BASE); + t_b, GCALC_COORD_BASE2, state.pi->node.intersection.p1->node.shape.ix, GCALC_COORD_BASE); gcalc_mul_coord(b_ta, GCALC_COORD_BASE3, t_a, GCALC_COORD_BASE2, dxa, GCALC_COORD_BASE); @@ -1948,7 +1948,7 @@ double Gcalc_scan_iterator::get_event_x() const get_pure_double(t_b, GCALC_COORD_BASE2)) / m_heap->coord_extent; } else - return state.pi->x; + return state.pi->node.shape.x; } double Gcalc_scan_iterator::get_h() const @@ -1961,7 +1961,7 @@ double Gcalc_scan_iterator::get_h() const state.pi->calc_xy(&x, &next_y); } else - next_y= state.pi->next ? state.pi->get_next()->y : 0.0; + next_y= state.pi->next ? state.pi->get_next()->node.shape.y : 0.0; return next_y - cur_y; } @@ -1970,11 +1970,11 @@ double Gcalc_scan_iterator::get_sp_x(const point *sp) const { double dy; if (sp->event & (scev_end | scev_two_ends | scev_point)) - return sp->pi->x; - dy= sp->next_pi->y - sp->pi->y; + return sp->pi->node.shape.x; + dy= sp->next_pi->node.shape.y - sp->pi->node.shape.y; if (fabs(dy) < 1e-12) - return sp->pi->x; - return sp->pi->x + (sp->next_pi->x - sp->pi->x) * dy; + return sp->pi->node.shape.x; + return sp->pi->node.shape.x + (sp->next_pi->node.shape.x - sp->pi->node.shape.x) * dy; } diff --git a/sql/gcalc_slicescan.h b/sql/gcalc_slicescan.h index 55de497f1ee..4996287ca88 100644 --- a/sql/gcalc_slicescan.h +++ b/sql/gcalc_slicescan.h @@ -26,7 +26,7 @@ #ifndef GCALC_DBUG_OFF #define GCALC_DBUG_PRINT(b) DBUG_PRINT("Gcalc", b) -#define GCALC_DBUG_ENTER(a) DBUG_ENTER("Gcalc "a) +#define GCALC_DBUG_ENTER(a) DBUG_ENTER("Gcalc " a) #define GCALC_DBUG_RETURN(r) DBUG_RETURN(r) #define GCALC_DBUG_VOID_RETURN DBUG_VOID_RETURN #define GCALC_DBUG_ASSERT(r) DBUG_ASSERT(r) @@ -188,7 +188,7 @@ public: double x,y; Gcalc_coord1 ix, iy; int top_node; - }; + } shape; struct { /* nt_intersection */ @@ -197,21 +197,21 @@ public: const Info *p2; const Info *p3; const Info *p4; - void *intersection_data; - int equal_intersection; - }; + void *data; + int equal; + } intersection; struct { /* nt_eq_node */ const Info *node; - void *eq_data; - }; - }; + void *data; + } eq; + } node; bool is_bottom() const - { GCALC_DBUG_ASSERT(type == nt_shape_node); return !left; } + { GCALC_DBUG_ASSERT(type == nt_shape_node); return !node.shape.left; } bool is_top() const - { GCALC_DBUG_ASSERT(type == nt_shape_node); return top_node; } + { GCALC_DBUG_ASSERT(type == nt_shape_node); return node.shape.top_node; } bool is_single_node() const { return is_bottom() && is_top(); } @@ -383,7 +383,7 @@ public: inline const point *c_get_next() const { return (const point *)next; } inline bool is_bottom() const { return !next_pi; } - gcalc_shape_info get_shape() const { return pi->shape; } + gcalc_shape_info get_shape() const { return pi->node.shape.shape; } inline point *get_next() { return (point *)next; } inline const point *get_next() const { return (const point *)next; } /* Compare the dx_dy parameters regarding the horiz_dir */ diff --git a/sql/gcalc_tools.cc b/sql/gcalc_tools.cc index 5aac8a71249..da0252c6b67 100644 --- a/sql/gcalc_tools.cc +++ b/sql/gcalc_tools.cc @@ -1278,7 +1278,7 @@ inline int Gcalc_operation_reducer::get_single_result(res_point *res, GCALC_DBUG_RETURN(1); } else - if (storage->single_point(res->pi->x, res->pi->y)) + if (storage->single_point(res->pi->node.shape.x, res->pi->node.shape.y)) GCALC_DBUG_RETURN(1); free_result(res); GCALC_DBUG_RETURN(0); @@ -1304,8 +1304,8 @@ int Gcalc_operation_reducer::get_result_thread(res_point *cur, } else { - x= cur->pi->x; - y= cur->pi->y; + x= cur->pi->node.shape.x; + y= cur->pi->node.shape.y; } if (storage->add_point(x, y)) GCALC_DBUG_RETURN(1); diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 5d789fa31e3..173a5f709c1 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -8306,7 +8306,7 @@ bool ha_partition::inplace_alter_table(TABLE *altered_table, /* Note that this function will try rollback failed ADD INDEX by executing DROP INDEX for the indexes that were committed (if any) - before the error occured. This means that the underlying storage + before the error occurred. This means that the underlying storage engine must be able to drop index in-place with X-lock held. (As X-lock will be held here if new indexes are to be committed) */ diff --git a/sql/handler.cc b/sql/handler.cc index bd415122388..748a51f5c59 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -30,11 +30,10 @@ #include "sql_table.h" // build_table_filename #include "sql_parse.h" // check_stack_overrun #include "sql_acl.h" // SUPER_ACL -#include "sql_base.h" // free_io_cache +#include "sql_base.h" // TDC_element #include "discover.h" // extension_based_table_discovery, etc #include "log_event.h" // *_rows_log_event #include "create_options.h" -#include "rpl_filter.h" #include <myisampack.h> #include "transaction.h" #include "myisam.h" @@ -325,7 +324,7 @@ int ha_init_errors(void) /* Set the dedicated error messages. */ SETMSG(HA_ERR_KEY_NOT_FOUND, ER_DEFAULT(ER_KEY_NOT_FOUND)); SETMSG(HA_ERR_FOUND_DUPP_KEY, ER_DEFAULT(ER_DUP_KEY)); - SETMSG(HA_ERR_RECORD_CHANGED, "Update wich is recoverable"); + SETMSG(HA_ERR_RECORD_CHANGED, "Update which is recoverable"); SETMSG(HA_ERR_WRONG_INDEX, "Wrong index given to function"); SETMSG(HA_ERR_CRASHED, ER_DEFAULT(ER_NOT_KEYFILE)); SETMSG(HA_ERR_WRONG_IN_RECORD, ER_DEFAULT(ER_CRASHED_ON_USAGE)); @@ -3931,9 +3930,7 @@ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt) if it is started. */ -inline -void -handler::mark_trx_read_write() +void handler::mark_trx_read_write_internal() { Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0]; /* @@ -4227,7 +4224,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table, IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES; if (table->file->check_if_incompatible_data(create_info, table_changes) == COMPATIBLE_DATA_YES) - DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK); + DBUG_RETURN(HA_ALTER_INPLACE_NO_LOCK); DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); } @@ -5050,7 +5047,9 @@ bool ha_table_exists(THD *thd, const char *db, const char *table_name, Table_exists_error_handler no_such_table_handler; thd->push_internal_handler(&no_such_table_handler); - TABLE_SHARE *share= tdc_acquire_share(thd, db, table_name, flags); + table.init_one_table(db, strlen(db), table_name, strlen(table_name), + table_name, TL_READ); + TABLE_SHARE *share= tdc_acquire_share(thd, &table, flags); thd->pop_internal_handler(); if (hton && share) @@ -5579,30 +5578,47 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat) correct for the table. A row in the given table should be replicated if: + - It's not called by partition engine - Row-based replication is enabled in the current thread - The binlog is enabled - It is not a temporary table - The binary log is open - The database the table resides in shall be binlogged (binlog_*_db rules) - table is not mysql.event + + RETURN VALUE + 0 No binary logging in row format + 1 Row needs to be logged */ -static bool check_table_binlog_row_based(THD *thd, TABLE *table) +inline bool handler::check_table_binlog_row_based(bool binlog_row) { - if (table->s->cached_row_logging_check == -1) + if (unlikely((table->in_use->variables.sql_log_bin_off))) + return 0; /* Called by partitioning engine */ + if (unlikely((!check_table_binlog_row_based_done))) { - int const check(table->s->tmp_table == NO_TMP_TABLE && - ! table->no_replicate && - binlog_filter->db_ok(table->s->db.str)); - table->s->cached_row_logging_check= check; + check_table_binlog_row_based_done= 1; + check_table_binlog_row_based_result= + check_table_binlog_row_based_internal(binlog_row); } + return check_table_binlog_row_based_result; +} - DBUG_ASSERT(table->s->cached_row_logging_check == 0 || - table->s->cached_row_logging_check == 1); +bool handler::check_table_binlog_row_based_internal(bool binlog_row) +{ + THD *thd= table->in_use; - return (thd->is_current_stmt_binlog_format_row() && - table->s->cached_row_logging_check && #ifdef WITH_WSREP + /* only InnoDB tables will be replicated through binlog emulation */ + if (binlog_row && + ((WSREP_EMULATE_BINLOG(thd) && + table->file->partition_ht()->db_type != DB_TYPE_INNODB) || + (thd->wsrep_ignore_table == true))) + return 0; +#endif + + return (table->s->cached_row_logging_check && + thd->is_current_stmt_binlog_format_row() && /* Wsrep partially enables binary logging if it have not been explicitly turned on. As a result we return 'true' if we are in @@ -5617,14 +5633,13 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table) Otherwise, return 'true' if binary logging is on. */ - (thd->variables.sql_log_bin_off != 1) && - ((WSREP_EMULATE_BINLOG(thd) && (thd->wsrep_exec_mode != REPL_RECV)) || - ((WSREP(thd) || (thd->variables.option_bits & OPTION_BIN_LOG)) && - mysql_bin_log.is_open()))); -#else - (thd->variables.option_bits & OPTION_BIN_LOG) && - mysql_bin_log.is_open()); -#endif + IF_WSREP(((WSREP_EMULATE_BINLOG(thd) && + (thd->wsrep_exec_mode != REPL_RECV)) || + ((WSREP(thd) || + (thd->variables.option_bits & OPTION_BIN_LOG)) && + mysql_bin_log.is_open())), + (thd->variables.option_bits & OPTION_BIN_LOG) && + mysql_bin_log.is_open())); } @@ -5658,54 +5673,51 @@ static int write_locked_table_maps(THD *thd) DBUG_PRINT("debug", ("get_binlog_table_maps(): %d", thd->get_binlog_table_maps())); - if (thd->get_binlog_table_maps() == 0) + MYSQL_LOCK *locks[2]; + locks[0]= thd->extra_lock; + locks[1]= thd->lock; + my_bool with_annotate= thd->variables.binlog_annotate_row_events && + thd->query() && thd->query_length(); + + for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i ) { - MYSQL_LOCK *locks[2]; - locks[0]= thd->extra_lock; - locks[1]= thd->lock; - my_bool with_annotate= thd->variables.binlog_annotate_row_events && - thd->query() && thd->query_length(); + MYSQL_LOCK const *const lock= locks[i]; + if (lock == NULL) + continue; - for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i ) + TABLE **const end_ptr= lock->table + lock->table_count; + for (TABLE **table_ptr= lock->table ; + table_ptr != end_ptr ; + ++table_ptr) { - MYSQL_LOCK const *const lock= locks[i]; - if (lock == NULL) - continue; - - TABLE **const end_ptr= lock->table + lock->table_count; - for (TABLE **table_ptr= lock->table ; - table_ptr != end_ptr ; - ++table_ptr) + TABLE *const table= *table_ptr; + DBUG_PRINT("info", ("Checking table %s", table->s->table_name.str)); + if (table->current_lock == F_WRLCK && + table->file->check_table_binlog_row_based(0)) { - TABLE *const table= *table_ptr; - DBUG_PRINT("info", ("Checking table %s", table->s->table_name.str)); - if (table->current_lock == F_WRLCK && - check_table_binlog_row_based(thd, table)) - { - /* - We need to have a transactional behavior for SQLCOM_CREATE_TABLE - (e.g. CREATE TABLE... SELECT * FROM TABLE) in order to keep a - compatible behavior with the STMT based replication even when - the table is not transactional. In other words, if the operation - fails while executing the insert phase nothing is written to the - binlog. - - Note that at this point, we check the type of a set of tables to - create the table map events. In the function binlog_log_row(), - which calls the current function, we check the type of the table - of the current row. - */ - bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE || - table->file->has_transactions(); - int const error= thd->binlog_write_table_map(table, has_trans, - &with_annotate); - /* - If an error occurs, it is the responsibility of the caller to - roll back the transaction. - */ - if (unlikely(error)) - DBUG_RETURN(1); - } + /* + We need to have a transactional behavior for SQLCOM_CREATE_TABLE + (e.g. CREATE TABLE... SELECT * FROM TABLE) in order to keep a + compatible behavior with the STMT based replication even when + the table is not transactional. In other words, if the operation + fails while executing the insert phase nothing is written to the + binlog. + + Note that at this point, we check the type of a set of tables to + create the table map events. In the function binlog_log_row(), + which calls the current function, we check the type of the table + of the current row. + */ + bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE || + table->file->has_transactions(); + int const error= thd->binlog_write_table_map(table, has_trans, + &with_annotate); + /* + If an error occurs, it is the responsibility of the caller to + roll back the transaction. + */ + if (unlikely(error)) + DBUG_RETURN(1); } } } @@ -5715,44 +5727,50 @@ static int write_locked_table_maps(THD *thd) typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*); -static int binlog_log_row(TABLE* table, - const uchar *before_record, - const uchar *after_record, - Log_func *log_func) + + +static int binlog_log_row_internal(TABLE* table, + const uchar *before_record, + const uchar *after_record, + Log_func *log_func) { bool error= 0; THD *const thd= table->in_use; - /* only InnoDB tables will be replicated through binlog emulation */ - if (WSREP_EMULATE_BINLOG(thd) && - table->file->partition_ht()->db_type != DB_TYPE_INNODB) - return 0; - - if (check_table_binlog_row_based(thd, table)) + /* + If there are no table maps written to the binary log, this is + the first row handled in this statement. In that case, we need + to write table maps for all locked tables to the binary log. + */ + if (likely(!(error= ((thd->get_binlog_table_maps() == 0 && + write_locked_table_maps(thd)))))) { /* - If there are no table maps written to the binary log, this is - the first row handled in this statement. In that case, we need - to write table maps for all locked tables to the binary log. + We need to have a transactional behavior for SQLCOM_CREATE_TABLE + (i.e. CREATE TABLE... SELECT * FROM TABLE) in order to keep a + compatible behavior with the STMT based replication even when + the table is not transactional. In other words, if the operation + fails while executing the insert phase nothing is written to the + binlog. */ - if (likely(!(error= write_locked_table_maps(thd)))) - { - /* - We need to have a transactional behavior for SQLCOM_CREATE_TABLE - (i.e. CREATE TABLE... SELECT * FROM TABLE) in order to keep a - compatible behavior with the STMT based replication even when - the table is not transactional. In other words, if the operation - fails while executing the insert phase nothing is written to the - binlog. - */ - bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE || - table->file->has_transactions(); - error= (*log_func)(thd, table, has_trans, before_record, after_record); - } + bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE || + table->file->has_transactions(); + error= (*log_func)(thd, table, has_trans, before_record, after_record); } return error ? HA_ERR_RBR_LOGGING_FAILED : 0; } +static inline int binlog_log_row(TABLE* table, + const uchar *before_record, + const uchar *after_record, + Log_func *log_func) +{ + if (!table->file->check_table_binlog_row_based(1)) + return 0; + return binlog_log_row_internal(table, before_record, after_record, log_func); +} + + int handler::ha_external_lock(THD *thd, int lock_type) { int error; @@ -5845,12 +5863,12 @@ int handler::ha_reset() DBUG_ASSERT(table->key_read == 0); /* ensure that ha_index_end / ha_rnd_end has been called */ DBUG_ASSERT(inited == NONE); - /* Free cache used by filesort */ - free_io_cache(table); /* reset the bitmaps to point to defaults */ table->default_column_bitmaps(); pushed_cond= NULL; tracker= NULL; + mark_trx_read_write_done= check_table_binlog_row_based_done= + check_table_binlog_row_based_result= 0; /* Reset information about pushed engine conditions */ cancel_pushed_idx_cond(); /* Reset information about pushed index conditions */ @@ -5875,14 +5893,13 @@ int handler::ha_write_row(uchar *buf) { error= write_row(buf); }) MYSQL_INSERT_ROW_DONE(error); - if (unlikely(error)) - DBUG_RETURN(error); - rows_changed++; - if (unlikely(error= binlog_log_row(table, 0, buf, log_func))) - DBUG_RETURN(error); /* purecov: inspected */ - + if (likely(!error)) + { + rows_changed++; + error= binlog_log_row(table, 0, buf, log_func); + } DEBUG_SYNC_C("ha_write_row_end"); - DBUG_RETURN(0); + DBUG_RETURN(error); } @@ -5908,12 +5925,12 @@ int handler::ha_update_row(const uchar *old_data, uchar *new_data) { error= update_row(old_data, new_data);}) MYSQL_UPDATE_ROW_DONE(error); - if (unlikely(error)) - return error; - rows_changed++; - if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func))) - return error; - return 0; + if (likely(!error)) + { + rows_changed++; + error= binlog_log_row(table, old_data, new_data, log_func); + } + return error; } int handler::ha_delete_row(const uchar *buf) @@ -5935,12 +5952,12 @@ int handler::ha_delete_row(const uchar *buf) TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_DELETE_ROW, active_index, 0, { error= delete_row(buf);}) MYSQL_DELETE_ROW_DONE(error); - if (unlikely(error)) - return error; - rows_changed++; - if (unlikely(error= binlog_log_row(table, buf, 0, log_func))) - return error; - return 0; + if (likely(!error)) + { + rows_changed++; + error= binlog_log_row(table, buf, 0, log_func); + } + return error; } diff --git a/sql/handler.h b/sql/handler.h index e0b5d922936..6054ec2db35 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1302,7 +1302,7 @@ struct handlerton }; /* - By default (if not implemented by the engine, but the discovery_table() is + By default (if not implemented by the engine, but the discover_table() is implemented) it will perform a file-based discovery: - if tablefile_extensions[0] is not null, this will discovers all tables @@ -2581,11 +2581,6 @@ public: RANGE_SEQ_IF mrr_funcs; /* Range sequence traversal functions */ HANDLER_BUFFER *multi_range_buffer; /* MRR buffer info */ uint ranges_in_seq; /* Total number of ranges in the traversed sequence */ - /* TRUE <=> source MRR ranges and the output are ordered */ - bool mrr_is_output_sorted; - - /** TRUE <=> we're currently traversing a range in mrr_cur_range. */ - bool mrr_have_range; /** Current range (the one we're now returning rows from) */ KEY_MULTI_RANGE mrr_cur_range; @@ -2593,23 +2588,32 @@ public: key_range save_end_range, *end_range; KEY_PART_INFO *range_key_part; int key_compare_result_on_equal; - bool eq_range; - bool internal_tmp_table; /* If internal tmp table */ - uint errkey; /* Last dup key */ - uint key_used_on_scan; - uint active_index; + /* TRUE <=> source MRR ranges and the output are ordered */ + bool mrr_is_output_sorted; + /** TRUE <=> we're currently traversing a range in mrr_cur_range. */ + bool mrr_have_range; + bool eq_range; + bool internal_tmp_table; /* If internal tmp table */ + bool implicit_emptied; /* Can be !=0 only if HEAP */ + bool mark_trx_read_write_done; /* mark_trx_read_write was called */ + bool check_table_binlog_row_based_done; /* check_table_binlog.. was called */ + bool check_table_binlog_row_based_result; /* cached check_table_binlog... */ /* TRUE <=> the engine guarantees that returned records are within the range being scanned. */ bool in_range_check_pushed_down; + uint errkey; /* Last dup key */ + uint key_used_on_scan; + uint active_index; + /** Length of ref (1-8 or the clustered key length) */ uint ref_length; FT_INFO *ft_handler; enum {NONE=0, INDEX, RND} inited; - bool implicit_emptied; /* Can be !=0 only if HEAP */ + const COND *pushed_cond; /** next_insert_id is the next value which should be inserted into the @@ -2693,11 +2697,16 @@ public: handler(handlerton *ht_arg, TABLE_SHARE *share_arg) :table_share(share_arg), table(0), estimation_rows_to_insert(0), ht(ht_arg), - ref(0), end_range(NULL), key_used_on_scan(MAX_KEY), active_index(MAX_KEY), + ref(0), end_range(NULL), + implicit_emptied(0), + mark_trx_read_write_done(0), + check_table_binlog_row_based_done(0), + check_table_binlog_row_based_result(0), in_range_check_pushed_down(FALSE), + key_used_on_scan(MAX_KEY), + active_index(MAX_KEY), ref_length(sizeof(my_off_t)), ft_handler(0), inited(NONE), - implicit_emptied(0), pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0), tracker(NULL), pushed_idx_cond(NULL), @@ -3617,7 +3626,7 @@ public: *) a) If the previous step succeeds, handler::ha_commit_inplace_alter_table() is called to allow the storage engine to do any final updates to its structures, to make all earlier changes durable and visible to other connections. - b) If we have failed to upgrade lock or any errors have occured during the + b) If we have failed to upgrade lock or any errors have occurred during the handler functions calls (including commit), we call handler::ha_commit_inplace_alter_table() to rollback all changes which were done during previous steps. @@ -3875,10 +3884,22 @@ protected: */ virtual int delete_table(const char *name); +public: + inline bool check_table_binlog_row_based(bool binlog_row); private: + /* Cache result to avoid extra calls */ + inline void mark_trx_read_write() + { + if (unlikely(!mark_trx_read_write_done)) + { + mark_trx_read_write_done= 1; + mark_trx_read_write_internal(); + } + } + void mark_trx_read_write_internal(); + bool check_table_binlog_row_based_internal(bool binlog_row); + /* Private helpers */ - inline void mark_trx_read_write(); -private: inline void increment_statistics(ulong SSV::*offset) const; inline void decrement_statistics(ulong SSV::*offset) const; diff --git a/sql/hostname.cc b/sql/hostname.cc index 6aef84f1b26..a84aebdf3c8 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -412,7 +412,7 @@ static inline bool is_hostname_valid(const char *hostname) int ip_to_hostname(struct sockaddr_storage *ip_storage, const char *ip_string, - char **hostname, + const char **hostname, uint *connect_errors) { const struct sockaddr *ip= (const sockaddr *) ip_storage; @@ -436,7 +436,7 @@ int ip_to_hostname(struct sockaddr_storage *ip_storage, DBUG_PRINT("info", ("Loopback address detected.")); /* Do not count connect errors from localhost. */ - *hostname= (char *) my_localhost; + *hostname= my_localhost; DBUG_RETURN(0); } diff --git a/sql/hostname.h b/sql/hostname.h index 81a1d0de88d..d6137b7c260 100644 --- a/sql/hostname.h +++ b/sql/hostname.h @@ -168,7 +168,7 @@ extern ulong host_cache_size; #define RC_BLOCKED_HOST 1 int ip_to_hostname(struct sockaddr_storage *ip_storage, const char *ip_string, - char **hostname, uint *connect_errors); + const char **hostname, uint *connect_errors); void inc_host_errors(const char *ip_string, Host_errors *errors); void reset_host_connect_errors(const char *ip_string); diff --git a/sql/item.cc b/sql/item.cc index 68376d1a746..4d3a3a6e3e7 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB + Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1260,6 +1260,22 @@ err: if allowed, otherwise - null. */ bzero((char*) ltime,sizeof(*ltime)); + if (fuzzydate & TIME_TIME_ONLY) + { + /* + In the following scenario: + - The caller expected to get a TIME value + - Item returned a not NULL string or numeric value + - But then conversion from string or number to TIME failed + we need to change the default time_type from MYSQL_TIMESTAMP_DATE + (which was set in bzero) to MYSQL_TIMESTAMP_TIME and therefore + return TIME'00:00:00' rather than DATE'0000-00-00'. + If we don't do this, methods like Item::get_time_with_conversion() + will erroneously subtract CURRENT_DATE from '0000-00-00 00:00:00' + and return TIME'-838:59:59' instead of TIME'00:00:00' as a result. + */ + ltime->time_type= MYSQL_TIMESTAMP_TIME; + } return null_value|= !(fuzzydate & TIME_FUZZY_DATES); } @@ -2340,7 +2356,7 @@ bool Item_field::update_table_bitmaps_processor(uchar *arg) static inline void set_field_to_new_field(Field **field, Field **new_field) { - if (*field) + if (*field && (*field)->table == new_field[0]->table) { Field *newf= new_field[(*field)->field_index]; if ((*field)->ptr == newf->ptr) @@ -2353,6 +2369,7 @@ bool Item_field::switch_to_nullable_fields_processor(uchar *arg) Field **new_fields= (Field **)arg; set_field_to_new_field(&field, new_fields); set_field_to_new_field(&result_field, new_fields); + maybe_null= field && field->maybe_null(); return 0; } @@ -4568,7 +4585,7 @@ bool is_outer_table(TABLE_LIST *table, SELECT_LEX *select) @retval 0 column fully fixed and fix_fields() should return FALSE @retval - -1 error occured + -1 error occurred */ int @@ -5440,8 +5457,7 @@ String_copier_for_item::copy_with_warn(CHARSET_INFO *dstcs, String *dst, if (const char *pos= cannot_convert_error_pos()) { char buf[16]; - int mblen= srccs->cset->charlen(srccs, (const uchar *) pos, - (const uchar *) src + src_length); + int mblen= my_charlen(srccs, pos, src + src_length); DBUG_ASSERT(mblen > 0 && mblen * 2 + 1 <= (int) sizeof(buf)); octet2hex(buf, pos, mblen); push_warning_printf(m_thd, Sql_condition::WARN_LEVEL_WARN, @@ -6392,6 +6408,7 @@ bool Item::cache_const_expr_analyzer(uchar **arg) !(basic_const_item() || item->basic_const_item() || item->type() == Item::FIELD_ITEM || item->type() == SUBSELECT_ITEM || + item->type() == CACHE_ITEM || /* Do not cache GET_USER_VAR() function as its const_item() may return TRUE for the current thread but it still may change @@ -6489,7 +6506,7 @@ void Item_field::update_null_value() UPDATE statement. RETURN - 0 if error occured + 0 if error occurred ref if all conditions are met this field otherwise */ diff --git a/sql/item.h b/sql/item.h index d5f0dfec033..863265a73f7 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2,7 +2,7 @@ #define SQL_ITEM_INCLUDED /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -430,7 +430,7 @@ public: RETURN FALSE if parameter value has been set, - TRUE if error has occured. + TRUE if error has occurred. */ virtual bool set_value(THD *thd, sp_rcontext *ctx, Item **it)= 0; @@ -663,9 +663,7 @@ protected: Field *tmp_table_field_from_field_type(TABLE *table, bool fixed_length, bool set_blob_packlength); - Field *create_tmp_field(bool group, TABLE *table, - uint convert_blob_length, - uint convert_int_length); + Field *create_tmp_field(bool group, TABLE *table, uint convert_int_length); public: /* @@ -1665,16 +1663,13 @@ public: // used in row subselects to get value of elements virtual void bring_value() {} - virtual Field *create_tmp_field(bool group, TABLE *table, - uint convert_blob_length) + virtual Field *create_tmp_field(bool group, TABLE *table) { /* Values with MY_INT32_NUM_DECIMAL_DIGITS digits may or may not fit into Field_long : make them Field_longlong. */ - return create_tmp_field(false, table, - convert_blob_length, - MY_INT32_NUM_DECIMAL_DIGITS - 2); + return create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS - 2); } virtual Item_field *field_for_view_update() { return 0; } @@ -2743,7 +2738,7 @@ public: /* If value for parameter was not set we treat it as non-const - so noone will use parameters value in fix_fields still + so no one will use parameters value in fix_fields still parameter is constant during execution. */ virtual table_map used_tables() const @@ -3688,6 +3683,11 @@ public: used_tables_cache|= item->used_tables(); const_item_cache&= item->const_item(); } + void used_tables_and_const_cache_update_and_join(Item *item) + { + item->update_used_tables(); + used_tables_and_const_cache_join(item); + } /* Call update_used_tables() for all "argc" items in the array "argv" and join with the current cache. @@ -3697,10 +3697,7 @@ public: void used_tables_and_const_cache_update_and_join(uint argc, Item **argv) { for (uint i=0 ; i < argc ; i++) - { - argv[i]->update_used_tables(); - used_tables_and_const_cache_join(argv[i]); - } + used_tables_and_const_cache_update_and_join(argv[i]); } /* Call update_used_tables() for all items in the list @@ -3713,10 +3710,7 @@ public: List_iterator_fast<Item> li(list); Item *item; while ((item=li++)) - { - item->update_used_tables(); - used_tables_and_const_cache_join(item); - } + used_tables_and_const_cache_update_and_join(item); } }; @@ -5161,6 +5155,12 @@ public: return (this->*processor)(arg); } virtual Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs); + void split_sum_func2_example(THD *thd, Ref_ptr_array ref_pointer_array, + List<Item> &fields, uint flags) + { + example->split_sum_func2(thd, ref_pointer_array, fields, &example, flags); + } + Item *get_example() const { return example; } }; @@ -5265,6 +5265,30 @@ public: bool cache_value(); }; + +class Item_cache_str_for_nullif: public Item_cache_str +{ +public: + Item_cache_str_for_nullif(THD *thd, const Item *item) + :Item_cache_str(thd, item) + { } + Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) + { + /** + Item_cache_str::safe_charset_converter() returns a new Item_cache + with Item_func_conv_charset installed on "example". The original + Item_cache is not referenced (neither directly nor recursively) + from the result of Item_cache_str::safe_charset_converter(). + + For NULLIF() purposes we need a different behavior: + we need a new instance of Item_func_conv_charset, + with the original Item_cache referenced in args[0]. See MDEV-9181. + */ + return Item::safe_charset_converter(thd, tocs); + } +}; + + class Item_cache_row: public Item_cache { Item_cache **values; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 0f1cccf50c9..187d2820531 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2246,50 +2246,6 @@ void Item_func_between::print(String *str, enum_query_type query_type) } -void -Item_func_case_abbreviation2::fix_length_and_dec2(Item **args) -{ - uint32 char_length; - set_handler_by_field_type(agg_field_type(args, 2, true)); - maybe_null=args[0]->maybe_null || args[1]->maybe_null; - decimals= MY_MAX(args[0]->decimals, args[1]->decimals); - unsigned_flag= args[0]->unsigned_flag && args[1]->unsigned_flag; - - if (Item_func_case_abbreviation2::result_type() == DECIMAL_RESULT || - Item_func_case_abbreviation2::result_type() == INT_RESULT) - { - int len0= args[0]->max_char_length() - args[0]->decimals - - (args[0]->unsigned_flag ? 0 : 1); - - int len1= args[1]->max_char_length() - args[1]->decimals - - (args[1]->unsigned_flag ? 0 : 1); - - char_length= MY_MAX(len0, len1) + decimals + (unsigned_flag ? 0 : 1); - } - else - char_length= MY_MAX(args[0]->max_char_length(), args[1]->max_char_length()); - - switch (Item_func_case_abbreviation2::result_type()) { - case STRING_RESULT: - if (count_string_result_length(Item_func_case_abbreviation2::field_type(), - args, 2)) - return; - break; - case DECIMAL_RESULT: - case REAL_RESULT: - break; - case INT_RESULT: - decimals= 0; - break; - case ROW_RESULT: - case TIME_RESULT: - DBUG_ASSERT(0); - } - fix_char_length(char_length); -} - - - uint Item_func_case_abbreviation2::decimal_precision2(Item **args) const { int arg0_int_part= args[0]->decimal_int_part(); @@ -2526,19 +2482,201 @@ bool Item_func_if::date_op(MYSQL_TIME *ltime, uint fuzzydate) } +void Item_func_nullif::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, + List<Item> &fields, uint flags) +{ + if (m_cache) + { + flags|= SPLIT_SUM_SKIP_REGISTERED; // See Item_func::split_sum_func + m_cache->split_sum_func2_example(thd, ref_pointer_array, fields, flags); + args[1]->split_sum_func2(thd, ref_pointer_array, fields, &args[1], flags); + } + else + { + Item_func::split_sum_func(thd, ref_pointer_array, fields, flags); + } +} + + +void Item_func_nullif::update_used_tables() +{ + if (m_cache) + { + used_tables_and_const_cache_init(); + used_tables_and_const_cache_update_and_join(m_cache->get_example()); + used_tables_and_const_cache_update_and_join(arg_count, args); + } + else + { + Item_func::update_used_tables(); + } +} + + + void Item_func_nullif::fix_length_and_dec() { - if (!args[2]) // Only false if EOM - return; + /* + If this is the first invocation of fix_length_and_dec(), create the + third argument as a copy of the first. This cannot be done before + fix_fields(), because fix_fields() might replace items, + for exampe NOT x --> x==0, or (SELECT 1) --> 1. + See also class Item_func_nullif declaration. + */ + if (arg_count == 2) + args[arg_count++]= args[0]; + + THD *thd= current_thd; + /* + At prepared statement EXECUTE time, args[0] can already + point to a different Item, created during PREPARE time fix_length_and_dec(). + For example, if character set conversion was needed, arguments can look + like this: + + args[0]= > Item_func_conv_charset \ + l_expr + args[2]= >------------------------/ + + Otherwise (during PREPARE or convensional execution), + args[0] and args[2] should still point to the same original l_expr. + */ + DBUG_ASSERT(args[0] == args[2] || thd->stmt_arena->is_stmt_execute()); + if (args[0]->type() == SUM_FUNC_ITEM && + !thd->lex->is_ps_or_view_context_analysis()) + { + /* + NULLIF(l_expr, r_expr) + + is calculated in the way to return a result equal to: + + CASE WHEN l_expr = r_expr THEN NULL ELSE r_expr END. + + There's nothing special with r_expr, because it's referenced + only by args[1] and nothing else. + + l_expr needs a special treatment, as it's referenced by both + args[0] and args[2] initially. + + args[2] is used to return the value. Afrer all transformations + (e.g. in fix_length_and_dec(), equal field propagation, etc) + args[2] points to a an Item which preserves the exact data type and + attributes (e.g. collation) of the original l_expr. + It can point: + - to the original l_expr + - to an Item_cache pointing to l_expr + - to a constant of the same data type with l_expr. + + args[0] is used for comparison. It can be replaced: + + - to Item_func_conv_charset by character set aggregation routines + - to a constant Item by equal field propagation routines + (in case of Item_field) + + The data type and/or the attributes of args[0] can differ from + the data type and the attributes of the original l_expr, to make + it comparable to args[1] (which points to r_expr or its replacement). + + For aggregate functions we have to wrap the original args[0]/args[2] + into Item_cache (see MDEV-9181). In this case the Item_cache + instance becomes the subject to character set conversion instead of + the original args[0]/args[2], while the original args[0]/args[2] get + hidden inside the cache. + + Some examples of what NULLIF can end up with after argument + substitution (we don't mention args[1] in some cases for simplicity): + 1. l_expr is not an aggragate function: + + a. No conversion happened. + args[0] and args[2] were not replaced to something else + (i.e. neither by character set conversion, nor by propagation): + + args[1] > r_expr + args[0] \ + l_expr + args[2] / + + b. Conversion of args[0] happened: + + CREATE OR REPLACE TABLE t1 ( + a CHAR(10) CHARACTER SET latin1, + b CHAR(10) CHARACTER SET utf8); + SELECT * FROM t1 WHERE NULLIF(a,b); + + args[1] > r_expr (Item_field for t1.b) + args[0] > Item_func_conv_charset\ + l_expr (Item_field for t1.a) + args[2] > ----------------------/ + + c. Conversion of args[1] happened: + + CREATE OR REPLACE TABLE t1 ( + a CHAR(10) CHARACTER SET utf8, + b CHAR(10) CHARACTER SET latin1); + SELECT * FROM t1 WHERE NULLIF(a,b); + + args[1] > Item_func_conv_charset -> r_expr (Item_field for t1.b) + args[0] \ + l_expr (Item_field for t1.a) + args[2] / + + d. Conversion of only args[0] happened (by equal field proparation): + + CREATE OR REPLACE TABLE t1 ( + a CHAR(10), + b CHAR(10)); + SELECT * FROM t1 WHERE NULLIF(a,b) AND a='a'; + + args[1] > r_expr (Item_field for t1.b) + args[0] > Item_string('a') (constant replacement for t1.a) + args[2] > l_expr (Item_field for t1.a) + + e. Conversion of both args[0] and args[2] happened + (by equal field propagation): + + CREATE OR REPLACE TABLE t1 (a INT,b INT); + SELECT * FROM t1 WHERE NULLIF(a,b) AND a=5; + + args[1] > r_expr (Item_field for "b") + args[0] \ + Item_int (5) (constant replacement for "a") + args[2] / + + 2. In case if l_expr is an aggregate function: + + a. No conversion happened: + + args[0] \ + Item_cache > l_expr + args[2] / + + b. Conversion of args[0] happened: + + args[0] > Item_func_conv_charset \ + Item_cache > l_expr + args[2] >------------------------/ + + c. Conversion of both args[0] and args[2] happened. + (e.g. by equal expression propagation) + TODO: check if it's possible (and add an example query if so). + */ + m_cache= args[0]->cmp_type() == STRING_RESULT ? + new (thd->mem_root) Item_cache_str_for_nullif(thd, args[0]) : + Item_cache::get_cache(thd, args[0]); + m_cache->setup(thd, args[0]); + m_cache->store(args[0]); + m_cache->set_used_tables(args[0]->used_tables()); + thd->change_item_tree(&args[0], m_cache); + thd->change_item_tree(&args[2], m_cache); + } set_handler_by_field_type(args[2]->field_type()); collation.set(args[2]->collation); decimals= args[2]->decimals; unsigned_flag= args[2]->unsigned_flag; fix_char_length(args[2]->max_char_length()); maybe_null=1; - setup_args_and_comparator(current_thd, &cmp); + setup_args_and_comparator(thd, &cmp); } @@ -2557,10 +2695,10 @@ void Item_func_nullif::print(String *str, enum_query_type query_type) Therefore, after equal field propagation args[0] and args[2] can point to different items. */ - if (!(query_type & QT_ITEM_FUNC_NULLIF_TO_CASE) || args[0] == args[2]) + if ((query_type & QT_ITEM_ORIGINAL_FUNC_NULLIF) || args[0] == args[2]) { /* - If no QT_ITEM_FUNC_NULLIF_TO_CASE is requested, + If QT_ITEM_ORIGINAL_FUNC_NULLIF is requested, that means we want the original NULLIF() representation, e.g. when we are in: SHOW CREATE {VIEW|FUNCTION|PROCEDURE} @@ -2568,17 +2706,14 @@ void Item_func_nullif::print(String *str, enum_query_type query_type) The original representation is possible only if args[0] and args[2] still point to the same Item. - The caller must pass call print() with QT_ITEM_FUNC_NULLIF_TO_CASE + The caller must never pass call print() with QT_ITEM_ORIGINAL_FUNC_NULLIF if an expression has undergone some optimization (e.g. equal field propagation done in optimize_cond()) already and NULLIF() potentially has two different representations of "a": - one "a" for comparison - another "a" for the returned value! - - Note, the EXPLAIN EXTENDED and EXPLAIN FORMAT=JSON routines - do pass QT_ITEM_FUNC_NULLIF_TO_CASE to print(). */ - DBUG_ASSERT(args[0] == args[2]); + DBUG_ASSERT(args[0] == args[2] || current_thd->lex->context_analysis_only); str->append(func_name()); str->append('('); args[2]->print(str, query_type); @@ -2606,6 +2741,13 @@ void Item_func_nullif::print(String *str, enum_query_type query_type) } +int Item_func_nullif::compare() +{ + if (m_cache) + m_cache->cache_value(); + return cmp.compare(); +} + /** @note Note that we have to evaluate the first argument twice as the compare @@ -2621,7 +2763,7 @@ Item_func_nullif::real_op() { DBUG_ASSERT(fixed == 1); double value; - if (!cmp.compare()) + if (!compare()) { null_value=1; return 0.0; @@ -2636,7 +2778,7 @@ Item_func_nullif::int_op() { DBUG_ASSERT(fixed == 1); longlong value; - if (!cmp.compare()) + if (!compare()) { null_value=1; return 0; @@ -2651,7 +2793,7 @@ Item_func_nullif::str_op(String *str) { DBUG_ASSERT(fixed == 1); String *res; - if (!cmp.compare()) + if (!compare()) { null_value=1; return 0; @@ -2667,7 +2809,7 @@ Item_func_nullif::decimal_op(my_decimal * decimal_value) { DBUG_ASSERT(fixed == 1); my_decimal *res; - if (!cmp.compare()) + if (!compare()) { null_value=1; return 0; @@ -2682,7 +2824,7 @@ bool Item_func_nullif::date_op(MYSQL_TIME *ltime, uint fuzzydate) { DBUG_ASSERT(fixed == 1); - if (!cmp.compare()) + if (!compare()) return (null_value= true); return (null_value= args[2]->get_date(ltime, fuzzydate)); } @@ -2691,7 +2833,7 @@ Item_func_nullif::date_op(MYSQL_TIME *ltime, uint fuzzydate) bool Item_func_nullif::is_null() { - return (null_value= (!cmp.compare() ? 1 : args[2]->null_value)); + return (null_value= (!compare() ? 1 : args[2]->null_value)); } @@ -2767,7 +2909,7 @@ Item *Item_func_case::find_item(String *str) return else_expr_num != -1 ? args[else_expr_num] : 0; value_added_map|= 1U << (uint)cmp_type; } - if (!cmp_items[(uint)cmp_type]->cmp(args[i]) && !args[i]->null_value) + if (cmp_items[(uint)cmp_type]->cmp(args[i]) == FALSE) return args[i + 1]; } } @@ -2885,24 +3027,6 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref) } -void Item_func_case::agg_str_lengths(Item* arg) -{ - fix_char_length(MY_MAX(max_char_length(), arg->max_char_length())); - set_if_bigger(decimals, arg->decimals); - unsigned_flag= unsigned_flag && arg->unsigned_flag; -} - - -void Item_func_case::agg_num_lengths(Item *arg) -{ - uint len= my_decimal_length_to_precision(arg->max_length, arg->decimals, - arg->unsigned_flag) - arg->decimals; - set_if_bigger(max_length, len); - set_if_bigger(decimals, arg->decimals); - unsigned_flag= unsigned_flag && arg->unsigned_flag; -} - - /** Check if (*place) and new_value points to different Items and call THD::change_item_tree() if needed. @@ -2964,18 +3088,7 @@ void Item_func_case::fix_length_and_dec() } else { - collation.set_numeric(); - max_length=0; - decimals=0; - unsigned_flag= TRUE; - for (uint i= 0; i < ncases; i+= 2) - agg_num_lengths(args[i + 1]); - if (else_expr_num != -1) - agg_num_lengths(args[else_expr_num]); - max_length= my_decimal_precision_to_length_no_truncation(max_length + - decimals, - decimals, - unsigned_flag); + fix_attributes(agg, nagg); } /* @@ -3277,23 +3390,25 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value) } -void Item_func_coalesce::fix_length_and_dec() +void Item_hybrid_func::fix_attributes(Item **items, uint nitems) { - set_handler_by_field_type(agg_field_type(args, arg_count, true)); - switch (Item_func_coalesce::result_type()) { + switch (Item_hybrid_func::result_type()) { case STRING_RESULT: - if (count_string_result_length(Item_func_coalesce::field_type(), - args, arg_count)) + if (count_string_result_length(Item_hybrid_func::field_type(), + items, nitems)) return; break; case DECIMAL_RESULT: - count_decimal_length(); + collation.set_numeric(); + count_decimal_length(items, nitems); break; case REAL_RESULT: - count_real_length(); + collation.set_numeric(); + count_real_length(items, nitems); break; case INT_RESULT: - count_only_length(args, arg_count); + collation.set_numeric(); + count_only_length(items, nitems); decimals= 0; break; case ROW_RESULT: @@ -3425,11 +3540,11 @@ static int cmp_decimal(void *cmp_arg, my_decimal *a, my_decimal *b) } -int in_vector::find(Item *item) +bool in_vector::find(Item *item) { uchar *result=get_value(item); if (!result || !used_count) - return 0; // Null value + return false; // Null value uint start,end; start=0; end=used_count-1; @@ -3438,13 +3553,13 @@ int in_vector::find(Item *item) uint mid=(start+end+1)/2; int res; if ((res=(*compare)(collation, base+mid*size, result)) == 0) - return 1; + return true; if (res < 0) start=mid; else end=mid-1; } - return (int) ((*compare)(collation, base+start*size, result) == 0); + return ((*compare)(collation, base+start*size, result) == 0); } in_string::in_string(THD *thd, uint elements, qsort2_cmp cmp_func, @@ -3776,14 +3891,20 @@ int cmp_item_row::cmp(Item *arg) arg->bring_value(); for (uint i=0; i < n; i++) { - if (comparators[i]->cmp(arg->element_index(i))) + const int rc= comparators[i]->cmp(arg->element_index(i)); + switch (rc) { - if (!arg->element_index(i)->null_value) - return 1; - was_null= 1; + case UNKNOWN: + was_null= true; + break; + case TRUE: + return TRUE; + case FALSE: + break; // elements #i are equal } + arg->null_value|= arg->element_index(i)->null_value; } - return (arg->null_value= was_null); + return was_null ? UNKNOWN : FALSE; } @@ -3806,15 +3927,15 @@ void cmp_item_decimal::store_value(Item *item) /* val may be zero if item is nnull */ if (val && val != &value) my_decimal2decimal(val, &value); + m_null_value= item->null_value; } int cmp_item_decimal::cmp(Item *arg) { my_decimal tmp_buf, *tmp= arg->val_decimal(&tmp_buf); - if (arg->null_value) - return 1; - return my_decimal_cmp(&value, tmp); + return (m_null_value || arg->null_value) ? + UNKNOWN : (my_decimal_cmp(&value, tmp) != 0); } @@ -3838,12 +3959,14 @@ void cmp_item_datetime::store_value(Item *item) enum_field_types f_type= tmp_item[0]->field_type_for_temporal_comparison(warn_item); value= get_datetime_value(thd, &tmp_item, &lval_cache, f_type, &is_null); + m_null_value= item->null_value; } int cmp_item_datetime::cmp(Item *arg) { - return value != arg->val_temporal_packed(warn_item); + const bool rc= value != arg->val_temporal_packed(warn_item); + return (m_null_value || arg->null_value) ? UNKNOWN : rc; } @@ -3867,10 +3990,10 @@ bool Item_func_in::count_sargable_conds(uchar *arg) } -bool Item_func_in::nulls_in_row() +bool Item_func_in::list_contains_null() { Item **arg,**arg_end; - for (arg= args+1, arg_end= args+arg_count; arg != arg_end ; arg++) + for (arg= args + 1, arg_end= args+arg_count; arg != arg_end ; arg++) { if ((*arg)->null_inside()) return 1; @@ -3985,6 +4108,32 @@ void Item_func_in::fix_length_and_dec() } } + /* + First conditions for bisection to be possible: + 1. All types are similar, and + 2. All expressions in <in value list> are const + */ + bool bisection_possible= + type_cnt == 1 && // 1 + const_itm; // 2 + if (bisection_possible) + { + /* + In the presence of NULLs, the correct result of evaluating this item + must be UNKNOWN or FALSE. To achieve that: + - If type is scalar, we can use bisection and the "have_null" boolean. + - If type is ROW, we will need to scan all of <in value list> when + searching, so bisection is impossible. Unless: + 3. UNKNOWN and FALSE are equivalent results + 4. Neither left expression nor <in value list> contain any NULL value + */ + + if (m_compare_type == ROW_RESULT && + ((!is_top_level_item() || negated) && // 3 + (list_contains_null() || args[0]->maybe_null))) // 4 + bisection_possible= false; + } + if (type_cnt == 1) { if (m_compare_type == STRING_RESULT && @@ -3997,7 +4146,7 @@ void Item_func_in::fix_length_and_dec() uint cols= args[0]->cols(); cmp_item_row *cmp= 0; - if (const_itm && !nulls_in_row()) + if (bisection_possible) { array= new (thd->mem_root) in_row(thd, arg_count-1, 0); cmp= &((in_row*)array)->tmp; @@ -4026,11 +4175,8 @@ void Item_func_in::fix_length_and_dec() } } } - /* - Row item with NULLs inside can return NULL or FALSE => - they can't be processed as static - */ - if (type_cnt == 1 && const_itm && !nulls_in_row()) + + if (bisection_possible) { /* IN must compare INT columns and constants as int values (the same @@ -4086,20 +4232,25 @@ void Item_func_in::fix_length_and_dec() array= new (thd->mem_root) in_datetime(thd, date_arg, arg_count - 1); break; } - if (array && !(thd->is_fatal_error)) // If not EOM + if (!array || thd->is_fatal_error) // OOM + return; + uint j=0; + for (uint i=1 ; i < arg_count ; i++) { - uint j=0; - for (uint i=1 ; i < arg_count ; i++) + array->set(j,args[i]); + if (!args[i]->null_value) + j++; // include this cell in the array. + else { - array->set(j,args[i]); - if (!args[i]->null_value) // Skip NULL values - j++; - else - have_null= 1; + /* + We don't put NULL values in array, to avoid erronous matches in + bisection. + */ + have_null= 1; } - if ((array->used_count= j)) - array->sort(); } + if ((array->used_count= j)) + array->sort(); } else { @@ -4167,7 +4318,14 @@ longlong Item_func_in::val_int() uint value_added_map= 0; if (array) { - int tmp=array->find(args[0]); + bool tmp=array->find(args[0]); + /* + NULL on left -> UNKNOWN. + Found no match, and NULL on right -> UNKNOWN. + NULL on right can never give a match, as it is not stored in + array. + See also the 'bisection_possible' variable in fix_length_and_dec(). + */ null_value=args[0]->null_value || (!tmp && have_null); return (longlong) (!null_value && tmp != negated); } @@ -4189,13 +4347,12 @@ longlong Item_func_in::val_int() if (!(value_added_map & (1U << (uint)cmp_type))) { in_item->store_value(args[0]); - if ((null_value= args[0]->null_value)) - return 0; value_added_map|= 1U << (uint)cmp_type; } - if (!in_item->cmp(args[i]) && !args[i]->null_value) + const int rc= in_item->cmp(args[i]); + if (rc == FALSE) return (longlong) (!negated); - have_null|= args[i]->null_value; + have_null|= (rc == UNKNOWN); } null_value= have_null; @@ -5605,7 +5762,7 @@ bool Item_func_not::fix_fields(THD *thd, Item **ref) args[0]->under_not(this); if (args[0]->type() == FIELD_ITEM) { - /* replace "NOT <field>" with "<filed> == 0" */ + /* replace "NOT <field>" with "<field> == 0" */ Query_arena backup, *arena; Item *new_item; bool rc= TRUE; @@ -6317,7 +6474,8 @@ longlong Item_equal::val_int() /* Skip fields of tables that has not been read yet */ if (!field->table->status || (field->table->status & STATUS_NULL_ROW)) { - if (eval_item->cmp(item) || (null_value= item->null_value)) + const int rc= eval_item->cmp(item); + if ((rc == TRUE) || (null_value= (rc == UNKNOWN))) return 0; } } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 38d07017b32..5789186dbe8 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1,7 +1,7 @@ #ifndef ITEM_CMPFUNC_INCLUDED #define ITEM_CMPFUNC_INCLUDED /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -795,6 +795,7 @@ public: public: inline void negate() { negated= !negated; } inline void top_level_item() { pred_level= 1; } + bool is_top_level_item() const { return pred_level; } Item *neg_transformer(THD *thd) { negated= !negated; @@ -901,7 +902,11 @@ public: String *str_op(String *); my_decimal *decimal_op(my_decimal *); bool date_op(MYSQL_TIME *ltime,uint fuzzydate); - void fix_length_and_dec(); + void fix_length_and_dec() + { + set_handler_by_field_type(agg_field_type(args, arg_count, true)); + fix_attributes(args, arg_count); + } const char *func_name() const { return "coalesce"; } table_map not_null_tables() const { return 0; } }; @@ -914,13 +919,18 @@ public: */ class Item_func_case_abbreviation2 :public Item_func_hybrid_field_type { +protected: + void fix_length_and_dec2(Item **items) + { + set_handler_by_field_type(agg_field_type(items, 2, true)); + fix_attributes(items, 2); + } + uint decimal_precision2(Item **args) const; public: Item_func_case_abbreviation2(THD *thd, Item *a, Item *b): Item_func_hybrid_field_type(thd, a, b) { } Item_func_case_abbreviation2(THD *thd, Item *a, Item *b, Item *c): Item_func_hybrid_field_type(thd, a, b, c) { } - void fix_length_and_dec2(Item **args); - uint decimal_precision2(Item **args) const; }; @@ -996,11 +1006,21 @@ class Item_func_nullif :public Item_func_hybrid_field_type - Item_field::propagate_equal_fields(ANY_SUBST) for the left "a" - Item_field::propagate_equal_fields(IDENTITY_SUBST) for the right "a" */ + Item_cache *m_cache; + int compare(); public: - // Put "a" to args[0] for comparison and to args[2] for the returned value. + /* + Here we pass three arguments to the parent constructor, as NULLIF + is a three-argument function, it needs two copies of the first argument + (see above). But fix_fields() will be confused if we try to prepare the + same Item twice (if args[0]==args[2]), so we hide the third argument + (decrementing arg_count) and copy args[2]=args[0] again after fix_fields(). + See also Item_func_nullif::fix_length_and_dec(). + */ Item_func_nullif(THD *thd, Item *a, Item *b): - Item_func_hybrid_field_type(thd, a, b, a) - {} + Item_func_hybrid_field_type(thd, a, b, a), + m_cache(NULL) + { arg_count--; } bool date_op(MYSQL_TIME *ltime, uint fuzzydate); double real_op(); longlong int_op(); @@ -1010,6 +1030,9 @@ public: uint decimal_precision() const { return args[2]->decimal_precision(); } const char *func_name() const { return "nullif"; } void print(String *str, enum_query_type query_type); + void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, + List<Item> &fields, uint flags); + void update_used_tables(); table_map not_null_tables() const { return 0; } bool is_null(); Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) @@ -1054,7 +1077,7 @@ public: { my_qsort2(base,used_count,size,compare,(void*)collation); } - int find(Item *item); + bool find(Item *item); /* Create an instance of Item_{type} (e.g. Item_decimal) constant object @@ -1222,6 +1245,10 @@ public: cmp_item() { cmp_charset= &my_charset_bin; } virtual ~cmp_item() {} virtual void store_value(Item *item)= 0; + /** + @returns result (TRUE, FALSE or UNKNOWN) of + "stored argument's value <> item's value" + */ virtual int cmp(Item *item)= 0; // for optimized IN with row virtual int compare(cmp_item *item)= 0; @@ -1234,7 +1261,14 @@ public: } }; -class cmp_item_string :public cmp_item +/// cmp_item which stores a scalar (i.e. non-ROW). +class cmp_item_scalar : public cmp_item +{ +protected: + bool m_null_value; ///< If stored value is NULL +}; + +class cmp_item_string : public cmp_item_scalar { protected: String *value_res; @@ -1260,14 +1294,20 @@ public: void store_value(Item *item) { value_res= item->val_str(&value); + m_null_value= item->null_value; } int cmp(Item *arg) { char buff[STRING_BUFFER_USUAL_SIZE]; - String tmp(buff, sizeof(buff), cmp_charset), *res; - res= arg->val_str(&tmp); - return (value_res ? (res ? sortcmp(value_res, res, cmp_charset) : 1) : - (res ? -1 : 0)); + String tmp(buff, sizeof(buff), cmp_charset), *res= arg->val_str(&tmp); + if (m_null_value || arg->null_value) + return UNKNOWN; + if (value_res && res) + return sortcmp(value_res, res, cmp_charset) != 0; + else if (!value_res && !res) + return FALSE; + else + return TRUE; } int compare(cmp_item *ci) { @@ -1282,7 +1322,7 @@ public: } }; -class cmp_item_int :public cmp_item +class cmp_item_int : public cmp_item_scalar { longlong value; public: @@ -1290,10 +1330,12 @@ public: void store_value(Item *item) { value= item->val_int(); + m_null_value= item->null_value; } int cmp(Item *arg) { - return value != arg->val_int(); + const bool rc= value != arg->val_int(); + return (m_null_value || arg->null_value) ? UNKNOWN : rc; } int compare(cmp_item *ci) { @@ -1309,7 +1351,7 @@ public: If the left item is a constant one then its value is cached in the lval_cache variable. */ -class cmp_item_datetime :public cmp_item +class cmp_item_datetime : public cmp_item_scalar { longlong value; public: @@ -1327,7 +1369,7 @@ public: cmp_item *make_same(); }; -class cmp_item_real :public cmp_item +class cmp_item_real : public cmp_item_scalar { double value; public: @@ -1335,10 +1377,12 @@ public: void store_value(Item *item) { value= item->val_real(); + m_null_value= item->null_value; } int cmp(Item *arg) { - return value != arg->val_real(); + const bool rc= value != arg->val_real(); + return (m_null_value || arg->null_value) ? UNKNOWN : rc; } int compare(cmp_item *ci) { @@ -1349,7 +1393,7 @@ public: }; -class cmp_item_decimal :public cmp_item +class cmp_item_decimal : public cmp_item_scalar { my_decimal value; public: @@ -1376,12 +1420,13 @@ public: void store_value(Item *item) { value_res= item->val_str(&value); + m_null_value= item->null_value; } int cmp(Item *item) { // Should never be called - DBUG_ASSERT(0); - return 1; + DBUG_ASSERT(false); + return TRUE; } int compare(cmp_item *ci) { @@ -1442,39 +1487,47 @@ public: Item *find_item(String *str); CHARSET_INFO *compare_collation() const { return cmp_collation.collation; } void cleanup(); - void agg_str_lengths(Item *arg); - void agg_num_lengths(Item *arg); Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond); }; /* - The Item_func_in class implements the in_expr IN(values_list) function. + The Item_func_in class implements + in_expr IN (<in value list>) + and + in_expr NOT IN (<in value list>) The current implementation distinguishes 2 cases: - 1) all items in the value_list are constants and have the same + 1) all items in <in value list> are constants and have the same result type. This case is handled by in_vector class. - 2) items in the value_list have different result types or there is some - non-constant items. - In this case Item_func_in employs several cmp_item objects to performs - comparisons of in_expr and an item from the values_list. One cmp_item + 2) otherwise Item_func_in employs several cmp_item objects to perform + comparisons of in_expr and an item from <in value list>. One cmp_item object for each result type. Different result types are collected in the fix_length_and_dec() member function by means of collect_cmp_types() function. */ class Item_func_in :public Item_func_opt_neg { + /** + Usable if <in value list> is made only of constants. Returns true if one + of these constants contains a NULL. Example: + IN ( (-5, (12,NULL)), ... ). + */ + bool list_contains_null(); protected: SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Field *field, Item *value); public: - /* - an array of values when the right hand arguments of IN - are all SQL constant and there are no nulls - */ + /// An array of values, created when the bisection lookup method is used in_vector *array; + /** + If there is some NULL among <in value list>, during a val_int() call; for + example + IN ( (1,(3,'col')), ... ), where 'col' is a column which evaluates to + NULL. + */ bool have_null; - /* - true when all arguments of the IN clause are of compatible types + /** + true when all arguments of the IN list are of compatible types and can be used safely as comparisons for key conditions */ bool arg_types_compatible; @@ -1528,7 +1581,6 @@ public: virtual void print(String *str, enum_query_type query_type); enum Functype functype() const { return IN_FUNC; } const char *func_name() const { return " IN "; } - bool nulls_in_row(); bool eval_not_null_tables(uchar *opt_arg); void fix_after_pullout(st_select_lex *new_parent, Item **ref); bool count_sargable_conds(uchar *arg); diff --git a/sql/item_func.cc b/sql/item_func.cc index 9183fd8f81a..57bd004cf88 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -234,7 +234,7 @@ Item_func::fix_fields(THD *thd, Item **ref) } } fix_length_and_dec(); - if (thd->is_error()) // An error inside fix_length_and_dec occured + if (thd->is_error()) // An error inside fix_length_and_dec occurred return TRUE; fixed= 1; return FALSE; @@ -577,18 +577,19 @@ void Item_udf_func::fix_num_length_and_dec() @retval False on success, true on error. */ -void Item_func::count_datetime_length(Item **item, uint nitems) +void Item_func::count_datetime_length(enum_field_types field_type_arg, + Item **item, uint nitems) { unsigned_flag= 0; decimals= 0; - if (field_type() != MYSQL_TYPE_DATE) + if (field_type_arg != MYSQL_TYPE_DATE) { for (uint i= 0; i < nitems; i++) set_if_bigger(decimals, item[i]->decimals); } set_if_smaller(decimals, TIME_SECOND_PART_DIGITS); uint len= decimals ? (decimals + 1) : 0; - len+= mysql_temporal_int_part_length(field_type()); + len+= mysql_temporal_int_part_length(field_type_arg); fix_char_length(len); } @@ -597,16 +598,16 @@ void Item_func::count_datetime_length(Item **item, uint nitems) result length/precision depends on argument ones. */ -void Item_func::count_decimal_length() +void Item_func::count_decimal_length(Item **item, uint nitems) { int max_int_part= 0; decimals= 0; unsigned_flag= 1; - for (uint i=0 ; i < arg_count ; i++) + for (uint i=0 ; i < nitems ; i++) { - set_if_bigger(decimals, args[i]->decimals); - set_if_bigger(max_int_part, args[i]->decimal_int_part()); - set_if_smaller(unsigned_flag, args[i]->unsigned_flag); + set_if_bigger(decimals, item[i]->decimals); + set_if_bigger(max_int_part, item[i]->decimal_int_part()); + set_if_smaller(unsigned_flag, item[i]->unsigned_flag); } int precision= MY_MIN(max_int_part + decimals, DECIMAL_MAX_PRECISION); fix_char_length(my_decimal_precision_to_length_no_truncation(precision, @@ -637,19 +638,20 @@ void Item_func::count_only_length(Item **item, uint nitems) result length/precision depends on argument ones. */ -void Item_func::count_real_length() +void Item_func::count_real_length(Item **items, uint nitems) { uint32 length= 0; decimals= 0; max_length= 0; - for (uint i=0 ; i < arg_count ; i++) + unsigned_flag= false; + for (uint i=0 ; i < nitems ; i++) { if (decimals != NOT_FIXED_DEC) { - set_if_bigger(decimals, args[i]->decimals); - set_if_bigger(length, (args[i]->max_length - args[i]->decimals)); + set_if_bigger(decimals, items[i]->decimals); + set_if_bigger(length, (items[i]->max_length - items[i]->decimals)); } - set_if_bigger(max_length, args[i]->max_length); + set_if_bigger(max_length, items[i]->max_length); } if (decimals != NOT_FIXED_DEC) { @@ -678,11 +680,11 @@ bool Item_func::count_string_result_length(enum_field_types field_type_arg, if (agg_arg_charsets_for_string_result(collation, items, nitems, 1)) return true; if (is_temporal_type(field_type_arg)) - count_datetime_length(items, nitems); + count_datetime_length(field_type_arg, items, nitems); else { - decimals= NOT_FIXED_DEC; count_only_length(items, nitems); + decimals= max_length ? NOT_FIXED_DEC : 0; } return false; } @@ -757,7 +759,7 @@ void Item_num_op::fix_length_and_dec(void) if (r0 == REAL_RESULT || r1 == REAL_RESULT || r0 == STRING_RESULT || r1 ==STRING_RESULT) { - count_real_length(); + count_real_length(args, arg_count); max_length= float_length(decimals); set_handler_by_result_type(REAL_RESULT); } @@ -5622,7 +5624,7 @@ void Item_func_get_user_var::fix_length_and_dec() /* If the variable didn't exist it has been created as a STRING-type. - 'm_var_entry' is NULL only if there occured an error during the call to + 'm_var_entry' is NULL only if there occurred an error during the call to get_var_with_binlog. */ if (!error && m_var_entry) diff --git a/sql/item_func.h b/sql/item_func.h index b11b29b6aa1..5c21535adbe 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -41,6 +41,14 @@ protected: */ uint allowed_arg_cols; String *val_str_from_val_str_ascii(String *str, String *str2); + + void count_only_length(Item **item, uint nitems); + void count_real_length(Item **item, uint nitems); + void count_decimal_length(Item **item, uint nitems); + void count_datetime_length(enum_field_types field_type, + Item **item, uint nitems); + bool count_string_result_length(enum_field_types field_type, + Item **item, uint nitems); public: table_map not_null_tables_cache; @@ -148,16 +156,10 @@ public: virtual void print(String *str, enum_query_type query_type); void print_op(String *str, enum_query_type query_type); void print_args(String *str, uint from, enum_query_type query_type); - void count_only_length(Item **item, uint nitems); - void count_real_length(); - void count_decimal_length(); inline bool get_arg0_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) { return (null_value=args[0]->get_date_with_conversion(ltime, fuzzy_date)); } - void count_datetime_length(Item **item, uint nitems); - bool count_string_result_length(enum_field_types field_type, - Item **item, uint nitems); inline bool get_arg0_time(MYSQL_TIME *ltime) { null_value= args[0]->get_time(ltime); @@ -175,7 +177,7 @@ public: { DBUG_ASSERT(thd == table->in_use); return result_type() != STRING_RESULT ? - create_tmp_field(false, table, 0, MY_INT32_NUM_DECIMAL_DIGITS) : + create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) : tmp_table_field_from_field_type(table, false, false); } Item *get_tmp_table_item(THD *thd); @@ -387,6 +389,8 @@ public: class Item_hybrid_func: public Item_func, public Type_handler_hybrid_field_type { +protected: + void fix_attributes(Item **item, uint nitems); public: Item_hybrid_func(THD *thd): Item_func(thd) { } Item_hybrid_func(THD *thd, Item *a): Item_func(thd, a) { } @@ -1766,7 +1770,7 @@ public: Field *create_field_for_create_select(THD *thd, TABLE *table) { return result_type() != STRING_RESULT ? - create_tmp_field(false, table, 0, MY_INT32_NUM_DECIMAL_DIGITS) : + create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) : tmp_table_field_from_field_type(table, false, true); } table_map used_tables() const diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 352c9fd93b9..39d06fd7a26 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -436,7 +436,7 @@ String *Item_func_convexhull::val_str(String *str_value) if (!cur_pi->get_next()) { /* Single point. */ - if (res_receiver.single_point(cur_pi->x, cur_pi->y)) + if (res_receiver.single_point(cur_pi->node.shape.x, cur_pi->node.shape.y)) goto mem_error; goto build_result; } @@ -461,8 +461,8 @@ String *Item_func_convexhull::val_str(String *str_value) { /* We only have 2 nodes in the result, so we create a polyline. */ if (res_receiver.start_shape(Gcalc_function::shape_line) || - res_receiver.add_point(left_first->pi->x, left_first->pi->y) || - res_receiver.add_point(left_cur->pi->x, left_cur->pi->y) || + res_receiver.add_point(left_first->pi->node.shape.x, left_first->pi->node.shape.y) || + res_receiver.add_point(left_cur->pi->node.shape.x, left_cur->pi->node.shape.y) || res_receiver.complete_shape()) goto mem_error; @@ -475,7 +475,7 @@ String *Item_func_convexhull::val_str(String *str_value) while (left_first) { - if (res_receiver.add_point(left_first->pi->x, left_first->pi->y)) + if (res_receiver.add_point(left_first->pi->node.shape.x, left_first->pi->node.shape.y)) goto mem_error; left_first= left_first->get_next(); } @@ -485,7 +485,7 @@ String *Item_func_convexhull::val_str(String *str_value) right_cur= right_cur->prev; while (right_cur->prev) { - if (res_receiver.add_point(right_cur->pi->x, right_cur->pi->y)) + if (res_receiver.add_point(right_cur->pi->node.shape.x, right_cur->pi->node.shape.y)) goto mem_error; right_cur= right_cur->prev; } @@ -1105,10 +1105,10 @@ static double count_edge_t(const Gcalc_heap::Info *ea, double &ex, double &ey, double &vx, double &vy, double &e_sqrlen) { - ex= eb->x - ea->x; - ey= eb->y - ea->y; - vx= v->x - ea->x; - vy= v->y - ea->y; + ex= eb->node.shape.x - ea->node.shape.x; + ey= eb->node.shape.y - ea->node.shape.y; + vx= v->node.shape.x - ea->node.shape.x; + vy= v->node.shape.y - ea->node.shape.y; e_sqrlen= ex * ex + ey * ey; return (ex * vx + ey * vy) / e_sqrlen; } @@ -1124,8 +1124,8 @@ static double distance_to_line(double ex, double ey, double vx, double vy, static double distance_points(const Gcalc_heap::Info *a, const Gcalc_heap::Info *b) { - double x= a->x - b->x; - double y= a->y - b->y; + double x= a->node.shape.x - b->node.shape.x; + double y= a->node.shape.y - b->node.shape.y; return sqrt(x * x + y * y); } @@ -2333,7 +2333,7 @@ double Item_func_distance::val_real() continue; count_distance: - if (cur_point->shape >= obj2_si) + if (cur_point->node.shape.shape >= obj2_si) continue; cur_point_edge= !cur_point->is_bottom(); @@ -2341,13 +2341,13 @@ count_distance: { /* We only check vertices of object 2 */ if (dist_point->type != Gcalc_heap::nt_shape_node || - dist_point->shape < obj2_si) + dist_point->node.shape.shape < obj2_si) continue; /* if we have an edge to check */ - if (dist_point->left) + if (dist_point->node.shape.left) { - t= count_edge_t(dist_point, dist_point->left, cur_point, + t= count_edge_t(dist_point, dist_point->node.shape.left, cur_point, ex, ey, vx, vy, e_sqrlen); if ((t>0.0) && (t<1.0)) { @@ -2358,7 +2358,7 @@ count_distance: } if (cur_point_edge) { - t= count_edge_t(cur_point, cur_point->left, dist_point, + t= count_edge_t(cur_point, cur_point->node.shape.left, dist_point, ex, ey, vx, vy, e_sqrlen); if ((t>0.0) && (t<1.0)) { diff --git a/sql/item_row.h b/sql/item_row.h index cb839b60c81..ddb6f0835f2 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -2,7 +2,7 @@ #define ITEM_ROW_INCLUDED /* - Copyright (c) 2002, 2010, Oracle and/or its affiliates. + Copyright (c) 2002, 2013, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,11 +28,20 @@ @endverbatim */ + +/** + Item which stores (x,y,...) and ROW(x,y,...). + Note that this can be recursive: ((x,y),(z,t)) is a ROW of ROWs. +*/ class Item_row: public Item, private Item_args, private Used_tables_and_const_cache { table_map not_null_tables_cache; + /** + If elements are made only of constants, of which one or more are + NULL. For example, this item is (1,2,NULL), or ( (1,NULL), (2,3) ). + */ bool with_null; public: Item_row(THD *thd, List<Item> &list): diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index bc39517a914..7c1c5f7da7d 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1564,7 +1564,7 @@ String *Item_func_insert::val_str(String *str) length= res->charpos((int) length, (uint32) start); /* Re-testing with corrected params */ - if (start > res->length()) + if (start + 1 > res->length()) // remember, start = args[1].val_int() - 1 return res; /* purecov: inspected */ // Wrong param; skip insert if (length > res->length() - start) length= res->length() - start; @@ -3404,7 +3404,7 @@ String *Item_func_conv_charset::val_str(String *str) String *arg= args[0]->val_str(str); String_copier_for_item copier(current_thd); return ((null_value= args[0]->null_value || - copier.copy_with_warn(conv_charset, &tmp_value, + copier.copy_with_warn(collation.collation, &tmp_value, arg->charset(), arg->ptr(), arg->length(), arg->length()))) ? 0 : &tmp_value; @@ -3412,7 +3412,7 @@ String *Item_func_conv_charset::val_str(String *str) void Item_func_conv_charset::fix_length_and_dec() { - collation.set(conv_charset, DERIVATION_IMPLICIT); + DBUG_ASSERT(collation.derivation == DERIVATION_IMPLICIT); fix_char_length(args[0]->max_char_length()); } @@ -3421,7 +3421,7 @@ void Item_func_conv_charset::print(String *str, enum_query_type query_type) str->append(STRING_WITH_LEN("convert(")); args[0]->print(str, query_type); str->append(STRING_WITH_LEN(" using ")); - str->append(conv_charset->csname); + str->append(collation.collation->csname); str->append(')'); } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index dfa38d7eed6..0ff38157c25 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -960,20 +960,22 @@ class Item_func_conv_charset :public Item_str_func String tmp_value; public: bool safe; - CHARSET_INFO *conv_charset; // keep it public Item_func_conv_charset(THD *thd, Item *a, CHARSET_INFO *cs): Item_str_func(thd, a) - { conv_charset= cs; use_cached_value= 0; safe= 0; } + { + collation.set(cs, DERIVATION_IMPLICIT); + use_cached_value= 0; safe= 0; + } Item_func_conv_charset(THD *thd, Item *a, CHARSET_INFO *cs, bool cache_if_const): Item_str_func(thd, a) { - conv_charset= cs; + collation.set(cs, DERIVATION_IMPLICIT); if (cache_if_const && args[0]->const_item() && !args[0]->is_expensive()) { uint errors= 0; String tmp, *str= args[0]->val_str(&tmp); if (!str || str_value.copy(str->ptr(), str->length(), - str->charset(), conv_charset, &errors)) + str->charset(), cs, &errors)) null_value= 1; use_cached_value= 1; str_value.mark_as_const(); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index b0eb22d2e0e..94e7bc98618 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -58,6 +58,8 @@ Item_subselect::Item_subselect(THD *thd_arg): { DBUG_ENTER("Item_subselect::Item_subselect"); DBUG_PRINT("enter", ("this: 0x%lx", (ulong) this)); + sortbuffer.str= 0; + #ifndef DBUG_OFF exec_counter= 0; #endif @@ -153,6 +155,9 @@ void Item_subselect::cleanup() if (engine) engine->cleanup(); reset(); + filesort_buffer.free_sort_buffer(); + my_free(sortbuffer.str); + value_assigned= 0; expr_cache= 0; forced_const= FALSE; @@ -5322,6 +5327,7 @@ int subselect_hash_sj_engine::exec() item_in->reset(); item_in->make_const(); item_in->set_first_execution(); + thd->lex->current_select= save_select; DBUG_RETURN(FALSE); } @@ -5365,6 +5371,7 @@ int subselect_hash_sj_engine::exec() item_in->null_value= 1; item_in->make_const(); item_in->set_first_execution(); + thd->lex->current_select= save_select; DBUG_RETURN(FALSE); } @@ -5907,7 +5914,7 @@ int subselect_partial_match_engine::exec() /* Search for a complete match. */ if ((lookup_res= lookup_engine->index_lookup())) { - /* An error occured during lookup(). */ + /* An error occurred during lookup(). */ item_in->value= 0; item_in->null_value= 0; return lookup_res; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 1b450044954..58b5a948048 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -95,6 +95,9 @@ public: subselect_engine *engine; /* unit of subquery */ st_select_lex_unit *unit; + /* Cached buffers used when calling filesort in sub queries */ + Filesort_buffer filesort_buffer; + LEX_STRING sortbuffer; /* A reference from inside subquery predicate to somewhere outside of it */ class Ref_to_outside : public Sql_alloc { diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 4b4ed0225d3..f774ee5a561 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -29,6 +29,7 @@ #include <my_global.h> #include "sql_priv.h" #include "sql_select.h" +#include "uniques.h" /** Calculate the affordable RAM limit for structures like TREE or Unique @@ -1187,8 +1188,7 @@ void Item_sum_hybrid::setup_hybrid(THD *thd, Item *item, Item *value_arg) } -Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table, - uint convert_blob_length) +Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table) { Field *field; MEM_ROOT *mem_root; @@ -1196,9 +1196,9 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table, if (args[0]->type() == Item::FIELD_ITEM) { field= ((Item_field*) args[0])->field; - + if ((field= create_tmp_field_from_field(table->in_use, field, name, table, - NULL, convert_blob_length))) + NULL))) field->flags&= ~NOT_NULL_FLAG; return field; } @@ -1224,7 +1224,7 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table, Field::NONE, name, decimals); break; default: - return Item_sum::create_tmp_field(group, table, convert_blob_length); + return Item_sum::create_tmp_field(group, table); } if (field) field->init(table); @@ -1636,8 +1636,7 @@ Item *Item_sum_avg::copy_or_same(THD* thd) } -Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table, - uint convert_blob_len) +Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table) { Field *field; MEM_ROOT *mem_root= table->in_use->mem_root; @@ -1873,8 +1872,7 @@ Item *Item_sum_variance::copy_or_same(THD* thd) If we're grouping, then we need some space to serialize variables into, to pass around. */ -Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table, - uint convert_blob_len) +Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table) { Field *field; if (group) @@ -3150,6 +3148,11 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), ER_THD(thd, ER_CUT_VALUE_GROUP_CONCAT), item->row_count); + /** + To avoid duplicated warnings in Item_func_group_concat::val_str() + */ + if (table && table->blob_storage) + table->blob_storage->set_truncated_value(false); return 1; } return 0; @@ -3287,6 +3290,8 @@ void Item_func_group_concat::cleanup() if (table) { THD *thd= table->in_use; + if (table->blob_storage) + delete table->blob_storage; free_tmp_table(thd, table); table= 0; if (tree) @@ -3354,6 +3359,8 @@ void Item_func_group_concat::clear() reset_tree(tree); if (unique_filter) unique_filter->reset(); + if (table && table->blob_storage) + table->blob_storage->reset(); /* No need to reset the table as we never call write_row */ } @@ -3480,6 +3487,7 @@ bool Item_func_group_concat::setup(THD *thd) { List<Item> list; SELECT_LEX *select_lex= thd->lex->current_select; + const bool order_or_distinct= MY_TEST(arg_count_order > 0 || distinct); DBUG_ENTER("Item_func_group_concat::setup"); /* @@ -3492,9 +3500,6 @@ bool Item_func_group_concat::setup(THD *thd) if (!(tmp_table_param= new TMP_TABLE_PARAM)) DBUG_RETURN(TRUE); - /* We'll convert all blobs to varchar fields in the temporary table */ - tmp_table_param->convert_blob_length= max_length * - collation.collation->mbmaxlen; /* Push all not constant fields to the list and create a temp table */ always_null= 0; for (uint i= 0; i < arg_count_field; i++) @@ -3534,18 +3539,9 @@ bool Item_func_group_concat::setup(THD *thd) count_field_types(select_lex, tmp_table_param, all_fields, 0); tmp_table_param->force_copy_fields= force_copy_fields; DBUG_ASSERT(table == 0); - if (arg_count_order > 0 || distinct) + if (order_or_distinct) { /* - Currently we have to force conversion of BLOB values to VARCHAR's - if we are to store them in TREE objects used for ORDER BY and - DISTINCT. This leads to truncation if the BLOB's size exceeds - Field_varstring::MAX_SIZE. - */ - set_if_smaller(tmp_table_param->convert_blob_length, - Field_varstring::MAX_SIZE); - - /* Force the create_tmp_table() to convert BIT columns to INT as we cannot compare two table records containg BIT fields stored in the the tree used for distinct/order by. @@ -3578,6 +3574,13 @@ bool Item_func_group_concat::setup(THD *thd) table->file->extra(HA_EXTRA_NO_ROWS); table->no_rows= 1; + /** + Initialize blob_storage if GROUP_CONCAT is used + with ORDER BY | DISTINCT and BLOB field count > 0. + */ + if (order_or_distinct && table->s->blob_fields) + table->blob_storage= new Blob_mem_storage(); + /* Need sorting or uniqueness: init tree and choose a function to sort. Don't reserve space for NULLs: if any of gconcat arguments is NULL, @@ -3630,6 +3633,16 @@ String* Item_func_group_concat::val_str(String* str) if (no_appended && tree) /* Tree is used for sorting as in ORDER BY */ tree_walk(tree, &dump_leaf_key, this, left_root_right); + + if (table && table->blob_storage && + table->blob_storage->is_truncated_value()) + { + warning_for_row= true; + push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN, + ER_CUT_VALUE_GROUP_CONCAT, ER(ER_CUT_VALUE_GROUP_CONCAT), + row_count); + } + return &result; } diff --git a/sql/item_sum.h b/sql/item_sum.h index b8f41030465..cfe2d3db878 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -484,11 +484,9 @@ public: } virtual void make_unique() { force_copy_fields= TRUE; } Item *get_tmp_table_item(THD *thd); - Field *create_tmp_field(bool group, TABLE *table, - uint convert_blob_length) + Field *create_tmp_field(bool group, TABLE *table) { - return Item::create_tmp_field(group, table, convert_blob_length, - MY_INT32_NUM_DECIMAL_DIGITS); + return Item::create_tmp_field(group, table, MY_INT32_NUM_DECIMAL_DIGITS); } virtual bool collect_outer_ref_processor(uchar *param); bool init_sum_func_check(THD *thd); @@ -872,7 +870,7 @@ public: return has_with_distinct() ? "avg(distinct " : "avg("; } Item *copy_or_same(THD* thd); - Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); + Field *create_tmp_field(bool group, TABLE *table); void cleanup() { count= 0; @@ -928,7 +926,7 @@ public: const char *func_name() const { return sample ? "var_samp(" : "variance("; } Item *copy_or_same(THD* thd); - Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); + Field *create_tmp_field(bool group, TABLE *table); enum Item_result result_type () const { return REAL_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;} void cleanup() @@ -1006,8 +1004,7 @@ protected: bool any_value() { return was_values; } void no_rows_in_result(); void restore_to_before_no_rows_in_result(); - Field *create_tmp_field(bool group, TABLE *table, - uint convert_blob_length); + Field *create_tmp_field(bool group, TABLE *table); }; @@ -1160,7 +1157,6 @@ public: fixed= true; } table_map used_tables() const { return (table_map) 1L; } - Field *get_tmp_table_field() { DBUG_ASSERT(0); return NULL; } void set_result_field(Field *) { DBUG_ASSERT(0); } void save_in_result_field(bool no_conversions) { DBUG_ASSERT(0); } }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 4cc9f6dc5bc..16edb35c392 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. - Copyright (c) 2009, 2013, Monty Program Ab + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2995,7 +2995,7 @@ void Item_func_timestamp_diff::print(String *str, enum_query_type query_type) str->append(STRING_WITH_LEN("SECOND")); break; case INTERVAL_MICROSECOND: - str->append(STRING_WITH_LEN("SECOND_FRAC")); + str->append(STRING_WITH_LEN("MICROSECOND")); break; default: break; diff --git a/sql/lex.h b/sql/lex.h index 05f0050e4f6..01e73f5f3d3 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -475,6 +475,7 @@ static SYMBOL symbols[] = { { "REAL", SYM(REAL)}, { "REBUILD", SYM(REBUILD_SYM)}, { "RECOVER", SYM(RECOVER_SYM)}, + { "RECURSIVE", SYM(RECURSIVE_SYM)}, { "REDO_BUFFER_SIZE", SYM(REDO_BUFFER_SIZE_SYM)}, { "REDOFILE", SYM(REDOFILE_SYM)}, { "REDUNDANT", SYM(REDUNDANT_SYM)}, diff --git a/sql/log.cc b/sql/log.cc index 79eb9accdff..dc8c08bfd36 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -632,7 +632,7 @@ void Log_to_csv_event_handler::cleanup() indicated in the return value. @retval FALSE OK - @retval TRUE error occured + @retval TRUE error occurred */ bool Log_to_csv_event_handler:: @@ -797,7 +797,7 @@ err: RETURN FALSE - OK - TRUE - error occured + TRUE - error occurred */ bool Log_to_csv_event_handler:: @@ -1108,7 +1108,7 @@ void Log_to_file_event_handler::flush() RETURN FALSE - OK - TRUE - error occured + TRUE - error occurred */ bool LOGGER::error_log_print(enum loglevel level, const char *format, @@ -1266,7 +1266,7 @@ bool LOGGER::flush_general_log() RETURN FALSE OK - TRUE error occured + TRUE error occurred */ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length, @@ -1674,14 +1674,14 @@ static int binlog_close_connection(handlerton *hton, THD *thd) uchar *buf; size_t len=0; wsrep_write_cache_buf(cache, &buf, &len); - WSREP_WARN("binlog trx cache not empty (%lu bytes) @ connection close %lu", - len, thd->thread_id); + WSREP_WARN("binlog trx cache not empty (%lu bytes) @ connection close %lld", + len, (longlong) thd->thread_id); if (len > 0) wsrep_dump_rbr_buf(thd, buf, len); cache = cache_mngr->get_binlog_cache_log(false); wsrep_write_cache_buf(cache, &buf, &len); - WSREP_WARN("binlog stmt cache not empty (%lu bytes) @ connection close %lu", - len, thd->thread_id); + WSREP_WARN("binlog stmt cache not empty (%lu bytes) @ connection close %lld", + len, (longlong) thd->thread_id); if (len > 0) wsrep_dump_rbr_buf(thd, buf, len); } #endif /* WITH_WSREP */ @@ -2839,7 +2839,7 @@ void MYSQL_QUERY_LOG::reopen_file() RETURN FASE - OK - TRUE - error occured + TRUE - error occurred */ bool MYSQL_QUERY_LOG::write(time_t event_time, const char *user_host, @@ -2941,7 +2941,7 @@ err: RETURN FALSE - OK - TRUE - error occured + TRUE - error occurred */ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, @@ -6403,7 +6403,7 @@ binlog_checkpoint_callback(void *cookie) /* For every supporting engine, we increment the xid_count and issue a commit_checkpoint_request(). Then we can count when all - commit_checkpoint_notify() callbacks have occured, and then log a new + commit_checkpoint_notify() callbacks have occurred, and then log a new binlog checkpoint event. */ mysql_bin_log.mark_xids_active(entry->binlog_id, 1); @@ -6582,7 +6582,6 @@ int MYSQL_BIN_LOG::rotate_and_purge(bool force_rotate) DBUG_ENTER("MYSQL_BIN_LOG::rotate_and_purge"); bool check_purge= false; - //todo: fix the macro def and restore safe_mutex_assert_not_owner(&LOCK_log); mysql_mutex_lock(&LOCK_log); prev_binlog_id= current_binlog_id; if ((error= rotate(force_rotate, &check_purge))) @@ -9508,9 +9507,7 @@ binlog_background_thread(void *arg __attribute__((unused))) thd= new THD; thd->system_thread= SYSTEM_THREAD_BINLOG_BACKGROUND; thd->thread_stack= (char*) &thd; /* Set approximate stack start */ - mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id= thread_id++; - mysql_mutex_unlock(&LOCK_thread_count); + thd->thread_id= next_thread_id(); thd->store_globals(); thd->security_ctx->skip_grants(); thd->set_command(COM_DAEMON); @@ -9597,9 +9594,8 @@ binlog_background_thread(void *arg __attribute__((unused))) THD_STAGE_INFO(thd, stage_binlog_stopping_background_thread); - mysql_mutex_lock(&LOCK_thread_count); + /* No need to use mutex as thd is not linked into other threads */ delete thd; - mysql_mutex_unlock(&LOCK_thread_count); my_thread_end(); @@ -10183,7 +10179,8 @@ IO_CACHE * get_trans_log(THD * thd) if (cache_mngr) return cache_mngr->get_binlog_cache_log(true); - WSREP_DEBUG("binlog cache not initialized, conn :%ld", thd->thread_id); + WSREP_DEBUG("binlog cache not initialized, conn: %lld", + (longlong) thd->thread_id); return NULL; } @@ -10221,7 +10218,8 @@ void thd_binlog_trx_reset(THD * thd) void thd_binlog_rollback_stmt(THD * thd) { - WSREP_DEBUG("thd_binlog_rollback_stmt :%ld", thd->thread_id); + WSREP_DEBUG("thd_binlog_rollback_stmt connection: %lld", + (longlong) thd->thread_id); binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); if (cache_mngr) diff --git a/sql/log_event.cc b/sql/log_event.cc index ff2f9594922..b56a9e2aee3 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, Monty Program Ab. + Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1392,9 +1392,9 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet, if (packet->append(file, data_len - LOG_EVENT_MINIMAL_HEADER_LEN)) { /* - Fatal error occured when appending rest of the event + Fatal error occurred when appending rest of the event to packet, possible failures: - 1. EOF occured when reading from file, it's really an error + 1. EOF occurred when reading from file, it's really an error as there's supposed to be more bytes available. file->error will have been set to number of bytes left to read 2. Read was interrupted, file->error would normally be set to -1 @@ -3525,7 +3525,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, slave_proxy_id= thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET); exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET); - db_len = (uint)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars + db_len = (uchar)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars error_code = uint2korr(buf + Q_ERR_CODE_OFFSET); /* @@ -4428,8 +4428,18 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi, if (thd->m_digest != NULL) thd->m_digest->reset(thd->m_token_array, max_digest_length); + if (thd->slave_thread) + { + /* + The opt_log_slow_slave_statements variable can be changed + dynamically, so we have to set the sql_log_slow respectively. + */ + thd->variables.sql_log_slow= opt_log_slow_slave_statements; + } + thd->enable_slow_log= thd->variables.sql_log_slow; - mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); + mysql_parse(thd, thd->query(), thd->query_length(), &parser_state, + FALSE); /* Finalize server status flags after executing a statement. */ thd->update_server_status(); log_slow_statement(thd); @@ -7463,6 +7473,7 @@ bool slave_execute_deferred_events(THD *thd) return res; res= rgi->deferred_events->execute(rgi); + rgi->deferred_events->rewind(); return res; } @@ -9895,7 +9906,18 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) } #ifdef HAVE_QUERY_CACHE +#ifdef WITH_WSREP + /* + Moved invalidation right before the call to rows_event_stmt_cleanup(), + to avoid query cache being polluted with stale entries. + */ + if (! (WSREP(thd) && (thd->wsrep_exec_mode == REPL_RECV))) + { +#endif /* WITH_WSREP */ query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ #endif } @@ -10087,6 +10109,14 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) /* remove trigger's tables */ if (slave_run_triggers_for_rbr) restore_empty_query_table_list(thd->lex); + +#if defined(WITH_WSREP) && defined(HAVE_QUERY_CACHE) + if (WSREP(thd) && thd->wsrep_exec_mode == REPL_RECV) + { + query_cache.invalidate_locked_for_write(thd, rgi->tables_to_lock); + } +#endif /* WITH_WSREP && HAVE_QUERY_CACHE */ + if (get_flags(STMT_END_F) && (error= rows_event_stmt_cleanup(rgi, thd))) slave_rows_error_report(ERROR_LEVEL, thd->is_error() ? 0 : error, @@ -11128,8 +11158,8 @@ bool Table_map_log_event::write_data_body() DBUG_ASSERT(m_dbnam != NULL); DBUG_ASSERT(m_tblnam != NULL); /* We use only one byte per length for storage in event: */ - DBUG_ASSERT(m_dblen < 128); - DBUG_ASSERT(m_tbllen < 128); + DBUG_ASSERT(m_dblen <= MY_MIN(NAME_LEN, 255)); + DBUG_ASSERT(m_tbllen <= MY_MIN(NAME_LEN, 255)); uchar const dbuf[]= { (uchar) m_dblen }; uchar const tbuf[]= { (uchar) m_tbllen }; @@ -11352,6 +11382,7 @@ bool Rows_log_event::process_triggers(trg_event_type event, { bool result; DBUG_ENTER("Rows_log_event::process_triggers"); + m_table->triggers->mark_fields_used(event); if (slave_run_triggers_for_rbr == SLAVE_RUN_TRIGGERS_FOR_RBR_YES) { tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */ @@ -11455,7 +11486,10 @@ Rows_log_event::write_row(rpl_group_info *rgi, /* unpack row into table->record[0] */ if ((error= unpack_current_row(rgi))) + { + table->file->print_error(error, MYF(0)); DBUG_RETURN(error); + } if (m_curr_row == m_rows_buf && !invoke_triggers) { @@ -12316,7 +12350,11 @@ int Delete_rows_log_event::do_exec_row(rpl_group_info *rgi) process_triggers(TRG_EVENT_DELETE, TRG_ACTION_BEFORE, FALSE)) error= HA_ERR_GENERIC; // in case if error is not set yet if (!error) + { + m_table->mark_columns_per_binlog_row_image(); error= m_table->file->ha_delete_row(m_table->record[0]); + m_table->default_column_bitmaps(); + } if (invoke_triggers && !error && process_triggers(TRG_EVENT_DELETE, TRG_ACTION_AFTER, FALSE)) error= HA_ERR_GENERIC; // in case if error is not set yet @@ -12459,8 +12497,8 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi) We need to read the second image in the event of error to be able to skip to the next pair of updates */ - m_curr_row= m_curr_row_end; - unpack_current_row(rgi, &m_cols_ai); + if ((m_curr_row= m_curr_row_end)) + unpack_current_row(rgi, &m_cols_ai); thd_proc_info(thd, tmp); return error; } diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 387534b1bed..ff2f7b156d5 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -248,7 +248,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, rpl_group_info *rgi) } if (error) - { /* error has occured during the transaction */ + { /* error has occurred during the transaction */ rli->report(ERROR_LEVEL, ev_thd->get_stmt_da()->sql_errno(), NULL, "Error in %s event: error during transaction execution " "on table %s.%s. %s", @@ -1593,7 +1593,7 @@ int Old_rows_log_event::do_apply_event(rpl_group_info *rgi) } // if (table) if (error) - { /* error has occured during the transaction */ + { /* error has occurred during the transaction */ rli->report(ERROR_LEVEL, thd->net.last_errno, NULL, "Error in %s event: error during transaction execution " "on table %s.%s. %s", diff --git a/sql/mdl.cc b/sql/mdl.cc index ab4f5288d4a..61591ec9f57 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -1064,7 +1064,16 @@ MDL_wait::timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout, wait_result != ETIMEDOUT && wait_result != ETIME) { #ifdef WITH_WSREP - if (wsrep_thd_is_BF(owner->get_thd(), true)) + // Allow tests to block the applier thread using the DBUG facilities + DBUG_EXECUTE_IF("sync.wsrep_before_mdl_wait", + { + const char act[]= + "now " + "wait_for signal.wsrep_before_mdl_wait"; + DBUG_ASSERT(!debug_sync_set_action((owner->get_thd()), + STRING_WITH_LEN(act))); + };); + if (wsrep_thd_is_BF(owner->get_thd(), false)) { wait_result= mysql_cond_wait(&m_COND_wait_status, &m_LOCK_wait_status); } diff --git a/sql/my_apc.cc b/sql/my_apc.cc index 91f5cd3f39c..dcb8503b880 100644 --- a/sql/my_apc.cc +++ b/sql/my_apc.cc @@ -119,7 +119,7 @@ void init_show_explain_psi_keys(void) @retval FALSE - Ok, the call has been made @retval TRUE - Call wasnt made (either the target is in disabled state or - timeout occured) + timeout occurred) */ bool Apc_target::make_apc_call(THD *caller_thd, Apc_call *call, diff --git a/sql/mysql_install_db.cc b/sql/mysql_install_db.cc index 9b4f45a9971..c39789f7c97 100644 --- a/sql/mysql_install_db.cc +++ b/sql/mysql_install_db.cc @@ -119,10 +119,10 @@ static void die(const char *fmt, ...) if (verbose_errors) { fprintf(stderr, - "http://kb.askmonty.org/v/installation-issues-on-windows contains some help\n" + "https://mariadb.com/kb/en/installation-issues-on-windows contains some help\n" "for solving the most common problems. If this doesn't help you, please\n" - "leave a comment in the Knowledgebase or file a bug report at\n" - "http://mariadb.org/jira"); + "leave a comment in the Knowledge Base or file a bug report at\n" + "https://jira.mariadb.org"); } fflush(stderr); va_end(args); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c79586a08da..e7d7f90d44e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2008, 2015, MariaDB + Copyright (c) 2008, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -363,6 +363,7 @@ static bool volatile select_thread_in_use, signal_thread_in_use; static volatile bool ready_to_exit; static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0; static my_bool opt_short_log_format= 0, opt_silent_startup= 0; + uint kill_cached_threads; static uint wake_thread; ulong max_used_connections; @@ -377,7 +378,7 @@ static char *default_collation_name; char *default_storage_engine, *default_tmp_storage_engine; char *enforced_storage_engine=NULL; static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME; -static I_List<THD> thread_cache; +static I_List<CONNECT> thread_cache; static bool binlog_format_used= false; LEX_STRING opt_init_connect, opt_init_slave; mysql_cond_t COND_thread_cache; @@ -389,6 +390,7 @@ static DYNAMIC_ARRAY all_options; bool opt_bin_log, opt_bin_log_used=0, opt_ignore_builtin_innodb= 0; my_bool opt_log, debug_assert_if_crashed_table= 0, opt_help= 0; +my_bool debug_assert_on_not_freed_memory= 0; my_bool disable_log_notes; static my_bool opt_abort; ulonglong log_output_options; @@ -409,8 +411,7 @@ uint volatile global_disable_checkpoint; ulong slow_start_timeout; #endif /* - True if the bootstrap thread is running. Protected by LOCK_thread_count, - just like thread_count. + True if the bootstrap thread is running. Protected by LOCK_start_thread. Used in bootstrap() function to determine if the bootstrap thread has completed. Note, that we can't use 'thread_count' instead, since in 5.1, in presence of the Event Scheduler, there may be @@ -422,7 +423,7 @@ ulong slow_start_timeout; bootstrap either, since we want to be able to process event-related SQL commands in the init file and in --bootstrap mode. */ -bool in_bootstrap= FALSE; +bool volatile in_bootstrap= FALSE; /** @brief 'grant_option' is used to indicate if privileges needs to be checked, in which case the lock, LOCK_grant, is used @@ -556,7 +557,8 @@ ulong max_prepared_stmt_count; statements. */ ulong prepared_stmt_count=0; -ulong thread_id=1L,current_pid; +my_thread_id global_thread_id= 1; +ulong current_pid; ulong slow_launch_threads = 0; uint sync_binlog_period= 0, sync_relaylog_period= 0, sync_relayloginfo_period= 0, sync_masterinfo_period= 0; @@ -712,7 +714,33 @@ SHOW_COMP_OPTION have_openssl; /* Thread specific variables */ pthread_key(THD*, THR_THD); -mysql_mutex_t LOCK_thread_count, LOCK_thread_cache; + +/* + LOCK_thread_count protects the following variables: + thread_count Number of threads with THD that servers queries. + threads Linked list of active THD's. + The effect of this is that one can't unlink and + delete a THD as long as one has locked + LOCK_thread_count. + ready_to_exit + delayed_insert_threads +*/ +mysql_mutex_t LOCK_thread_count; + +/* + LOCK_start_thread is used to syncronize thread start and stop with + other threads. + + It also protects these variables: + handler_count + in_bootstrap + select_thread_in_use + slave_init_thread_running + check_temp_dir() call +*/ +mysql_mutex_t LOCK_start_thread; + +mysql_mutex_t LOCK_thread_cache; mysql_mutex_t LOCK_status, LOCK_show_status, LOCK_error_log, LOCK_short_uuid_generator, LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, @@ -737,7 +765,7 @@ mysql_mutex_t LOCK_des_key_file; #endif mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; mysql_rwlock_t LOCK_system_variables_hash; -mysql_cond_t COND_thread_count; +mysql_cond_t COND_thread_count, COND_start_thread; pthread_t signal_thread; pthread_attr_t connection_attrib; mysql_mutex_t LOCK_server_started; @@ -887,6 +915,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, key_relay_log_info_log_space_lock, key_relay_log_info_run_lock, key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data, key_LOCK_error_messages, key_LOG_INFO_lock, + key_LOCK_start_thread, key_LOCK_thread_count, key_LOCK_thread_cache, key_PARTITION_LOCK_auto_inc; PSI_mutex_key key_RELAYLOG_LOCK_index; @@ -973,6 +1002,7 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_thread_cache, "LOCK_thread_cache", PSI_FLAG_GLOBAL}, { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0}, { &key_LOCK_slave_state, "LOCK_slave_state", 0}, + { &key_LOCK_start_thread, "LOCK_start_thread", PSI_FLAG_GLOBAL}, { &key_LOCK_binlog_state, "LOCK_binlog_state", 0}, { &key_LOCK_rpl_thread, "LOCK_rpl_thread", 0}, { &key_LOCK_rpl_thread_pool, "LOCK_rpl_thread_pool", 0}, @@ -1014,6 +1044,7 @@ PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond, key_rpl_group_info_sleep_cond, key_TABLE_SHARE_cond, key_user_level_lock_cond, key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache, + key_COND_start_thread, key_BINLOG_COND_queue_busy; PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready, key_COND_wait_commit; @@ -1073,6 +1104,7 @@ static PSI_cond_info all_server_conds[]= { &key_COND_group_commit_orderer, "COND_group_commit_orderer", 0}, { &key_COND_prepare_ordered, "COND_prepare_ordered", 0}, { &key_COND_slave_init, "COND_slave_init", 0}, + { &key_COND_start_thread, "COND_start_thread", PSI_FLAG_GLOBAL}, { &key_COND_wait_gtid, "COND_wait_gtid", 0}, { &key_COND_gtid_ignore_duplicates, "COND_gtid_ignore_duplicates", 0} }; @@ -1199,8 +1231,13 @@ void init_net_server_extension(THD *thd) /* Activate this private extension for the mysqld server. */ thd->net.extension= & thd->m_net_server_extension; } +#else +void init_net_server_extension(THD *thd) +{ +} #endif /* EMBEDDED_LIBRARY */ + /** A log message for the error log, buffered in memory. Log messages are temporarily buffered when generated before the error log @@ -1466,7 +1503,6 @@ static openssl_lock_t *openssl_dynlock_create(const char *, int); static void openssl_dynlock_destroy(openssl_lock_t *, const char *, int); static void openssl_lock_function(int, int, const char *, int); static void openssl_lock(int, openssl_lock_t *, const char *, int); -static unsigned long openssl_id_function(); #endif char *des_key_file; #ifndef EMBEDDED_LIBRARY @@ -1545,8 +1581,8 @@ static void close_connections(void) #if !defined(__WIN__) DBUG_PRINT("quit", ("waiting for select thread: 0x%lx", (ulong) select_thread)); - mysql_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_start_thread); while (select_thread_in_use) { struct timespec abstime; @@ -1560,7 +1596,7 @@ static void close_connections(void) set_timespec(abstime, 2); for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++) { - error= mysql_cond_timedwait(&COND_thread_count, &LOCK_thread_count, + error= mysql_cond_timedwait(&COND_start_thread, &LOCK_start_thread, &abstime); if (error != EINTR) break; @@ -1571,7 +1607,7 @@ static void close_connections(void) #endif close_server_sock(); } - mysql_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_start_thread); #endif /* __WIN__ */ @@ -1640,7 +1676,7 @@ static void close_connections(void) while ((tmp=it++)) { DBUG_PRINT("quit",("Informing thread %ld that it's time to die", - tmp->thread_id)); + (ulong) tmp->thread_id)); /* We skip slave threads & scheduler on this first loop through. */ if (tmp->slave_thread) continue; @@ -1696,6 +1732,8 @@ static void close_connections(void) much smaller than even 2 seconds, this is only a safety fallback against stuck threads so server shutdown is not held up forever. */ + DBUG_PRINT("info", ("thread_count: %d", thread_count)); + for (int i= 0; *(volatile int32*) &thread_count && i < 1000; i++) my_sleep(20000); @@ -1707,11 +1745,9 @@ static void close_connections(void) for (;;) { - DBUG_PRINT("quit",("Locking LOCK_thread_count")); mysql_mutex_lock(&LOCK_thread_count); // For unlink from list if (!(tmp=threads.get())) { - DBUG_PRINT("quit",("Unlocking LOCK_thread_count")); mysql_mutex_unlock(&LOCK_thread_count); break; } @@ -1720,12 +1756,13 @@ static void close_connections(void) { if (global_system_variables.log_warnings) sql_print_warning(ER_DEFAULT(ER_FORCING_CLOSE),my_progname, - tmp->thread_id, + (ulong) tmp->thread_id, (tmp->main_security_ctx.user ? tmp->main_security_ctx.user : "")); close_connection(tmp,ER_SERVER_SHUTDOWN); } #endif + #ifdef WITH_WSREP /* * WSREP_TODO: @@ -1992,7 +2029,8 @@ pthread_handler_t kill_server_thread(void *arg __attribute__((unused))) extern "C" sig_handler print_signal_warning(int sig) { if (global_system_variables.log_warnings) - sql_print_warning("Got signal %d from thread %ld", sig,my_thread_id()); + sql_print_warning("Got signal %d from thread %ld", sig, + (ulong) my_thread_id()); #ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(sig,print_signal_warning); /* int. thread system calls */ #endif @@ -2207,10 +2245,14 @@ void clean_up(bool print_message) logger.cleanup_end(); sys_var_end(); free_charsets(); + + /* + Signal mysqld_main() that it can exit + do the broadcast inside the lock to ensure that my_end() is not called + during broadcast() + */ mysql_mutex_lock(&LOCK_thread_count); - DBUG_PRINT("quit", ("got thread count lock")); ready_to_exit=1; - /* do the broadcast inside the lock to ensure that my_end() is not called */ mysql_cond_broadcast(&COND_thread_count); mysql_mutex_unlock(&LOCK_thread_count); @@ -2258,6 +2300,7 @@ static void clean_up_mutexes() mysql_rwlock_destroy(&LOCK_grant); mysql_mutex_destroy(&LOCK_thread_count); mysql_mutex_destroy(&LOCK_thread_cache); + mysql_mutex_destroy(&LOCK_start_thread); mysql_mutex_destroy(&LOCK_status); mysql_mutex_destroy(&LOCK_show_status); mysql_mutex_destroy(&LOCK_delayed_insert); @@ -2291,6 +2334,7 @@ static void clean_up_mutexes() mysql_mutex_destroy(&LOCK_error_messages); mysql_cond_destroy(&COND_thread_count); mysql_cond_destroy(&COND_thread_cache); + mysql_cond_destroy(&COND_start_thread); mysql_cond_destroy(&COND_flush_thread_cache); mysql_mutex_destroy(&LOCK_server_started); mysql_cond_destroy(&COND_server_started); @@ -2312,7 +2356,9 @@ static void clean_up_mutexes() static void set_ports() { } - +void close_connection(THD *thd, uint sql_errno) +{ +} #else static void set_ports() { @@ -2794,6 +2840,7 @@ static void network_init(void) @note For the connection that is doing shutdown, this is called twice */ + void close_connection(THD *thd, uint sql_errno) { DBUG_ENTER("close_connection"); @@ -2829,20 +2876,6 @@ extern "C" sig_handler end_mysqld_signal(int sig __attribute__((unused))) DBUG_VOID_RETURN; /* purecov: deadcode */ } - -/* - Cleanup THD object - - SYNOPSIS - thd_cleanup() - thd Thread handler -*/ - -void thd_cleanup(THD *thd) -{ - thd->cleanup(); -} - /* Decrease number of connections @@ -2850,43 +2883,49 @@ void thd_cleanup(THD *thd) dec_connection_count() */ -void dec_connection_count(THD *thd) +void dec_connection_count(scheduler_functions *scheduler) { -#ifdef WITH_WSREP - /* - Do not decrement when its wsrep system thread. wsrep_applier is set for - applier as well as rollbacker threads. - */ - if (thd->wsrep_applier) - return; -#endif /* WITH_WSREP */ - - DBUG_ASSERT(*thd->scheduler->connection_count > 0); mysql_mutex_lock(&LOCK_connection_count); - (*thd->scheduler->connection_count)--; + (*scheduler->connection_count)--; mysql_mutex_unlock(&LOCK_connection_count); } /* Delete THD and decrement thread counters, including thread_running + + This is mainly used to delete event threads which are not increasing + global counters. */ void delete_running_thd(THD *thd) { - mysql_mutex_lock(&LOCK_thread_count); - thd->unlink(); - mysql_mutex_unlock(&LOCK_thread_count); + thd->add_status_to_global(); + unlink_not_visible_thd(thd); delete thd; dec_thread_running(); + dec_thread_count(); +} + +/* + Decrease number of threads. Signal when it reaches 0 + + SYNOPSIS + dec_thread_count() +*/ + +void dec_thread_count(void) +{ + DBUG_ASSERT(thread_count > 0); thread_safe_decrement32(&thread_count); signal_thd_deleted(); } + /* - Send a signal to unblock close_conneciton() if there is no more - threads running with a THD attached + Send a signal to unblock close_conneciton() / rpl_slave_init_thread() + if there is no more threads running with a THD attached It's safe to check for thread_count and service_thread_count outside of a mutex as we are only interested to see if they where decremented @@ -2898,7 +2937,7 @@ void delete_running_thd(THD *thd) void signal_thd_deleted() { - if (!thread_count && ! service_thread_count) + if (!thread_count && !service_thread_count) { /* Signal close_connections() that all THD's are freed */ mysql_mutex_lock(&LOCK_thread_count); @@ -2914,9 +2953,6 @@ void signal_thd_deleted() SYNOPSIS unlink_thd() thd Thread handler - - NOTES - LOCK_thread_count is locked and left locked */ void unlink_thd(THD *thd) @@ -2924,23 +2960,18 @@ void unlink_thd(THD *thd) DBUG_ENTER("unlink_thd"); DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd)); - thd_cleanup(thd); - dec_connection_count(thd); - - thd->add_status_to_global(); - - mysql_mutex_lock(&LOCK_thread_count); - thd->unlink(); /* - Used by binlog_reset_master. It would be cleaner to use - DEBUG_SYNC here, but that's not possible because the THD's debug - sync feature has been shut down at this point. + Do not decrement when its wsrep system thread. wsrep_applier is set for + applier as well as rollbacker threads. */ - DBUG_EXECUTE_IF("sleep_after_lock_thread_count_before_delete_thd", sleep(5);); - mysql_mutex_unlock(&LOCK_thread_count); + if (IF_WSREP(!thd->wsrep_applier, 1)) + dec_connection_count(thd->scheduler); + thd->cleanup(); + thd->add_status_to_global(); + unlink_not_visible_thd(thd); delete thd; - thread_safe_decrement32(&thread_count); + dec_thread_count(); DBUG_VOID_RETURN; } @@ -2964,6 +2995,7 @@ void unlink_thd(THD *thd) static bool cache_thread() { + struct timespec abstime; DBUG_ENTER("cache_thread"); mysql_mutex_lock(&LOCK_thread_cache); @@ -2982,18 +3014,46 @@ static bool cache_thread() PSI_THREAD_CALL(delete_current_thread)(); #endif +#ifndef DBUG_OFF + while (_db_is_pushed_()) + _db_pop_(); +#endif + + set_timespec(abstime, THREAD_CACHE_TIMEOUT); while (!abort_loop && ! wake_thread && ! kill_cached_threads) - mysql_cond_wait(&COND_thread_cache, &LOCK_thread_cache); + { + int error= mysql_cond_timedwait(&COND_thread_cache, &LOCK_thread_cache, + &abstime); + if (error == ETIMEDOUT || error == ETIME) + { + /* + If timeout, end thread. + If a new thread is requested (wake_thread is set), we will handle + the call, even if we got a timeout (as we are already awake and free) + */ + break; + } + } cached_thread_count--; if (kill_cached_threads) mysql_cond_signal(&COND_flush_thread_cache); if (wake_thread) { + CONNECT *connect; THD *thd; + wake_thread--; - thd= thread_cache.get(); + connect= thread_cache.get(); mysql_mutex_unlock(&LOCK_thread_cache); + if (!(thd= connect->create_thd())) + { + /* Out of resources. Free thread to get more resources */ + connect->close_and_delete(); + DBUG_RETURN(0); + } + delete connect; + thd->thread_stack= (char*) &thd; // For store_globals (void) thd->store_globals(); @@ -3016,10 +3076,7 @@ static bool cache_thread() thd->thr_create_utime= microsecond_interval_timer(); thd->start_utime= thd->thr_create_utime; - /* Link thd into list of all active threads (THD's) */ - mysql_mutex_lock(&LOCK_thread_count); - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); + add_to_active_threads(thd); DBUG_RETURN(1); } } @@ -3033,7 +3090,7 @@ static bool cache_thread() SYNOPSIS one_thread_per_connection_end() - thd Thread handler + thd Thread handler. This may be null if we run out of resources. put_in_cache Store thread in cache, if there is room in it Normally this is true in all cases except when we got out of resources initializing the current thread @@ -3052,12 +3109,13 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) DBUG_ENTER("one_thread_per_connection_end"); const bool wsrep_applier= IF_WSREP(thd->wsrep_applier, false); - unlink_thd(thd); + if (thd) + unlink_thd(thd); if (!wsrep_applier && put_in_cache && cache_thread()) DBUG_RETURN(0); // Thread is reused - signal_thd_deleted(); + DBUG_PRINT("info", ("killing thread")); DBUG_LEAVE; // Must match DBUG_ENTER() #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) ERR_remove_state(0); @@ -3425,7 +3483,7 @@ static void start_signal_handler(void) (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); (void) my_setstacksize(&thr_attr,my_thread_stack_size); - mysql_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_start_thread); if ((error= mysql_thread_create(key_thread_signal_hand, &signal_thread, &thr_attr, signal_hand, 0))) { @@ -3433,8 +3491,8 @@ static void start_signal_handler(void) error,errno); exit(1); } - mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); + mysql_cond_wait(&COND_start_thread, &LOCK_start_thread); + mysql_mutex_unlock(&LOCK_start_thread); (void) pthread_attr_destroy(&thr_attr); DBUG_VOID_RETURN; @@ -3484,12 +3542,12 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) signal to start_signal_handler that we are ready This works by waiting for start_signal_handler to free mutex, after which we signal it that we are ready. - At this pointer there is no other threads running, so there + At this point there is no other threads running, so there should not be any other mysql_cond_signal() calls. */ - mysql_mutex_lock(&LOCK_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_lock(&LOCK_start_thread); + mysql_cond_broadcast(&COND_start_thread); + mysql_mutex_unlock(&LOCK_start_thread); (void) pthread_sigmask(SIG_BLOCK,&set,NULL); for (;;) @@ -3790,6 +3848,7 @@ SHOW_VAR com_status_vars[]= { {"alter_server", STMT_STATUS(SQLCOM_ALTER_SERVER)}, {"alter_table", STMT_STATUS(SQLCOM_ALTER_TABLE)}, {"alter_tablespace", STMT_STATUS(SQLCOM_ALTER_TABLESPACE)}, + {"alter_user", STMT_STATUS(SQLCOM_ALTER_USER)}, {"analyze", STMT_STATUS(SQLCOM_ANALYZE)}, {"assign_to_keycache", STMT_STATUS(SQLCOM_ASSIGN_TO_KEYCACHE)}, {"begin", STMT_STATUS(SQLCOM_BEGIN)}, @@ -3846,6 +3905,7 @@ SHOW_VAR com_status_vars[]= { {"kill", STMT_STATUS(SQLCOM_KILL)}, {"load", STMT_STATUS(SQLCOM_LOAD)}, {"lock_tables", STMT_STATUS(SQLCOM_LOCK_TABLES)}, + {"multi", COM_STATUS(com_multi)}, {"optimize", STMT_STATUS(SQLCOM_OPTIMIZE)}, {"preload_keys", STMT_STATUS(SQLCOM_PRELOAD_KEYS)}, {"prepare_sql", STMT_STATUS(SQLCOM_PREPARE)}, @@ -3879,6 +3939,7 @@ SHOW_VAR com_status_vars[]= { {"show_create_proc", STMT_STATUS(SQLCOM_SHOW_CREATE_PROC)}, {"show_create_table", STMT_STATUS(SQLCOM_SHOW_CREATE)}, {"show_create_trigger", STMT_STATUS(SQLCOM_SHOW_CREATE_TRIGGER)}, + {"show_create_user", STMT_STATUS(SQLCOM_SHOW_CREATE_USER)}, {"show_databases", STMT_STATUS(SQLCOM_SHOW_DATABASES)}, {"show_engine_logs", STMT_STATUS(SQLCOM_SHOW_ENGINE_LOGS)}, {"show_engine_mutex", STMT_STATUS(SQLCOM_SHOW_ENGINE_MUTEX)}, @@ -4045,7 +4106,8 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific) (longlong) thd->status_var.local_memory_used, size)); thd->status_var.local_memory_used+= size; - DBUG_ASSERT((longlong) thd->status_var.local_memory_used >= 0); + DBUG_ASSERT((longlong) thd->status_var.local_memory_used >= 0 || + !debug_assert_on_not_freed_memory); } } } @@ -4124,7 +4186,7 @@ static int init_common_variables() sf_malloc_dbug_id= mariadb_dbug_id; #endif - max_system_variables.pseudo_thread_id= (ulong)~0; + max_system_variables.pseudo_thread_id= ~(my_thread_id) 0; server_start_time= flush_status_time= my_time(0); global_rpl_filter= new Rpl_filter; @@ -4277,7 +4339,7 @@ static int init_common_variables() of SQLCOM_ constants. */ compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 == - SQLCOM_END + 10); + SQLCOM_END + 11); #endif if (get_options(&remaining_argc, &remaining_argv)) @@ -4637,6 +4699,7 @@ static int init_thread_environment() DBUG_ENTER("init_thread_environment"); mysql_mutex_init(key_LOCK_thread_count, &LOCK_thread_count, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_thread_cache, &LOCK_thread_cache, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_start_thread, &LOCK_start_thread, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_show_status, &LOCK_show_status, MY_MUTEX_INIT_SLOW); mysql_mutex_init(key_LOCK_delayed_insert, @@ -4691,7 +4754,6 @@ static int init_thread_environment() CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy); CRYPTO_set_dynlock_lock_callback(openssl_lock); CRYPTO_set_locking_callback(openssl_lock_function); - CRYPTO_set_id_callback(openssl_id_function); #endif #endif mysql_rwlock_init(key_rwlock_LOCK_sys_init_connect, &LOCK_sys_init_connect); @@ -4699,6 +4761,7 @@ static int init_thread_environment() mysql_rwlock_init(key_rwlock_LOCK_grant, &LOCK_grant); mysql_cond_init(key_COND_thread_count, &COND_thread_count, NULL); mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, NULL); + mysql_cond_init(key_COND_start_thread, &COND_start_thread, NULL); mysql_cond_init(key_COND_flush_thread_cache, &COND_flush_thread_cache, NULL); #ifdef HAVE_REPLICATION mysql_mutex_init(key_LOCK_rpl_status, &LOCK_rpl_status, MY_MUTEX_INIT_FAST); @@ -4727,12 +4790,6 @@ static int init_thread_environment() #if defined(HAVE_OPENSSL) && !defined(HAVE_YASSL) -static unsigned long openssl_id_function() -{ - return (unsigned long) pthread_self(); -} - - static openssl_lock_t *openssl_dynlock_create(const char *file, int line) { openssl_lock_t *lock= new openssl_lock_t; @@ -5235,49 +5292,6 @@ static int init_server_components() } plugins_are_initialized= TRUE; /* Don't separate from init function */ -#ifdef WITH_WSREP - /* Wait for wsrep threads to get created. */ - if (wsrep_creating_startup_threads == 1) { - mysql_mutex_lock(&LOCK_thread_count); - while (wsrep_running_threads < 2) - { - mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); - } - - /* Now is the time to initialize threads for queries. */ - THD *tmp; - I_List_iterator<THD> it(threads); - while ((tmp= it++)) - { - if (tmp->wsrep_applier == true) - { - /* - Save/restore server_status and variables.option_bits and they get - altered during init_for_queries(). - */ - unsigned int server_status_saved= tmp->server_status; - ulonglong option_bits_saved= tmp->variables.option_bits; - - /* - Set THR_THD to temporarily point to this THD to register all the - variables that allocates memory for this THD. - */ - THD *current_thd_saved= current_thd; - set_current_thd(tmp); - - tmp->init_for_queries(); - - /* Restore current_thd. */ - set_current_thd(current_thd_saved); - - tmp->server_status= server_status_saved; - tmp->variables.option_bits= option_bits_saved; - } - } - mysql_mutex_unlock(&LOCK_thread_count); - } -#endif - /* we do want to exit if there are any other unknown options */ if (remaining_argc > 1) { @@ -5508,7 +5522,7 @@ static void handle_connections_methods() unireg_abort(1); // Will not return } - mysql_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_start_thread); mysql_cond_init(key_COND_handler_count, &COND_handler_count, NULL); handler_count=0; if (hPipe != INVALID_HANDLE_VALUE) @@ -5551,17 +5565,17 @@ static void handle_connections_methods() #endif while (handler_count > 0) - mysql_cond_wait(&COND_handler_count, &LOCK_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); + mysql_cond_wait(&COND_handler_count, &LOCK_start_thread); + mysql_mutex_unlock(&LOCK_start_thread); DBUG_VOID_RETURN; } void decrement_handler_count() { - mysql_mutex_lock(&LOCK_thread_count); - handler_count--; - mysql_cond_signal(&COND_handler_count); - mysql_mutex_unlock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_start_thread); + if (--handler_count == 0) + mysql_cond_signal(&COND_handler_count); + mysql_mutex_unlock(&LOCK_start_thread); my_thread_end(); } #else @@ -5925,6 +5939,9 @@ int mysqld_main(int argc, char **argv) if (Events::init((THD*) 0, opt_noacl || opt_bootstrap)) unireg_abort(1); + /* It's now safe to use thread specific memory */ + mysqld_server_initialized= 1; + if (WSREP_ON) { if (opt_bootstrap) @@ -5965,9 +5982,6 @@ int mysqld_main(int argc, char **argv) } } - /* It's now safe to use thread specific memory */ - mysqld_server_initialized= 1; - create_shutdown_thread(); start_handle_manager(); @@ -6028,18 +6042,10 @@ int mysqld_main(int argc, char **argv) DBUG_PRINT("quit",("Exiting main thread")); #ifndef __WIN__ -#ifdef EXTRA_DEBUG2 - sql_print_error("Before Lock_thread_count"); -#endif - WSREP_DEBUG("Before Lock_thread_count"); - mysql_mutex_lock(&LOCK_thread_count); - DBUG_PRINT("quit", ("Got thread_count mutex")); + mysql_mutex_lock(&LOCK_start_thread); select_thread_in_use=0; // For close_connections - mysql_mutex_unlock(&LOCK_thread_count); - mysql_cond_broadcast(&COND_thread_count); -#ifdef EXTRA_DEBUG2 - sql_print_error("After lock_thread_count"); -#endif + mysql_cond_broadcast(&COND_start_thread); + mysql_mutex_unlock(&LOCK_start_thread); #endif /* __WIN__ */ #ifdef HAVE_PSI_THREAD_INTERFACE @@ -6066,6 +6072,9 @@ int mysqld_main(int argc, char **argv) CloseHandle(hEventShutdown); } #endif +#if (defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)) && !defined(EMBEDDED_LIBRARY) + ERR_remove_state(0); +#endif mysqld_exit(0); return 0; } @@ -6304,7 +6313,7 @@ static void bootstrap(MYSQL_FILE *file) my_net_init(&thd->net,(st_vio*) 0, (void*) 0, MYF(0)); thd->max_client_packet_length= thd->net.max_packet; thd->security_ctx->master_access= ~(ulong)0; - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; + thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id(); thread_count++; // Safe as only one thread running in_bootstrap= TRUE; @@ -6324,10 +6333,7 @@ static void bootstrap(MYSQL_FILE *file) /* Wait for thread to die */ mysql_mutex_lock(&LOCK_thread_count); while (in_bootstrap) - { mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); - DBUG_PRINT("quit",("One thread died (count=%u)",thread_count)); - } mysql_mutex_unlock(&LOCK_thread_count); #else thd->mysql= 0; @@ -6357,7 +6363,7 @@ static bool read_init_file(char *file_name) */ void inc_thread_created(void) { - thread_created++; + statistic_increment(thread_created, &LOCK_status); } #ifndef EMBEDDED_LIBRARY @@ -6368,18 +6374,12 @@ void inc_thread_created(void) NOTES This is only used for debugging, when starting mysqld with --thread-handling=no-threads or --one-thread - - When we enter this function, LOCK_thread_count is hold! */ -void handle_connection_in_main_thread(THD *thd) +void handle_connection_in_main_thread(CONNECT *connect) { - mysql_mutex_assert_owner(&LOCK_thread_count); - thread_cache_size=0; // Safety - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); - thd->start_utime= microsecond_interval_timer(); - do_handle_one_connection(thd); + thread_cache_size= 0; // Safety + do_handle_one_connection(connect); } @@ -6387,10 +6387,11 @@ void handle_connection_in_main_thread(THD *thd) Scheduler that uses one thread per connection */ -void create_thread_to_handle_connection(THD *thd) +void create_thread_to_handle_connection(CONNECT *connect) { + char error_message_buff[MYSQL_ERRMSG_SIZE]; + int error; DBUG_ENTER("create_thread_to_handle_connection"); - mysql_mutex_assert_owner(&LOCK_thread_count); /* Check if we can get thread from the cache */ if (cached_thread_count > wake_thread) @@ -6399,9 +6400,8 @@ void create_thread_to_handle_connection(THD *thd) /* Recheck condition when we have the lock */ if (cached_thread_count > wake_thread) { - mysql_mutex_unlock(&LOCK_thread_count); /* Get thread from cache */ - thread_cache.push_back(thd); + thread_cache.push_back(connect); wake_thread++; mysql_cond_signal(&COND_thread_cache); mysql_mutex_unlock(&LOCK_thread_cache); @@ -6411,46 +6411,33 @@ void create_thread_to_handle_connection(THD *thd) mysql_mutex_unlock(&LOCK_thread_cache); } - char error_message_buff[MYSQL_ERRMSG_SIZE]; /* Create new thread to handle connection */ - int error; - thread_created++; - threads.append(thd); - DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id)); - thd->prior_thr_create_utime= microsecond_interval_timer(); + inc_thread_created(); + DBUG_PRINT("info",(("creating thread %lu"), (ulong) connect->thread_id)); + connect->prior_thr_create_utime= microsecond_interval_timer(); + if ((error= mysql_thread_create(key_thread_one_connection, - &thd->real_id, &connection_attrib, + &connect->real_id, &connection_attrib, handle_one_connection, - (void*) thd))) + (void*) connect))) { /* purecov: begin inspected */ DBUG_PRINT("error", ("Can't create thread to handle request (error %d)", error)); - thd->killed= KILL_CONNECTION; // Safety - mysql_mutex_unlock(&LOCK_thread_count); - - mysql_mutex_lock(&LOCK_connection_count); - (*thd->scheduler->connection_count)--; - mysql_mutex_unlock(&LOCK_connection_count); - + dec_connection_count(connect->scheduler); statistic_increment(aborted_connects,&LOCK_status); statistic_increment(connection_errors_internal, &LOCK_status); - /* Can't use my_error() since store_globals has not been called. */ my_snprintf(error_message_buff, sizeof(error_message_buff), - ER_THD(thd, ER_CANT_CREATE_THREAD), error); - net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL); - close_connection(thd, ER_OUT_OF_RESOURCES); - - mysql_mutex_lock(&LOCK_thread_count); - thd->unlink(); - mysql_mutex_unlock(&LOCK_thread_count); - delete thd; - thread_safe_decrement32(&thread_count); - return; + ER_DEFAULT(ER_CANT_CREATE_THREAD), error); + connect->close_with_error(ER_CANT_CREATE_THREAD, + error_message_buff, + ER_OUT_OF_RESOURCES); + /* thread_count was incremented in create_new_thread() */ + dec_thread_count(); + DBUG_VOID_RETURN; /* purecov: end */ } - mysql_mutex_unlock(&LOCK_thread_count); DBUG_PRINT("info",("Thread created")); DBUG_VOID_RETURN; } @@ -6469,7 +6456,7 @@ void create_thread_to_handle_connection(THD *thd) @param[in,out] thd Thread handle of future thread. */ -static void create_new_thread(THD *thd) +static void create_new_thread(CONNECT *connect) { DBUG_ENTER("create_new_thread"); @@ -6480,20 +6467,19 @@ static void create_new_thread(THD *thd) mysql_mutex_lock(&LOCK_connection_count); - if (*thd->scheduler->connection_count >= - *thd->scheduler->max_connections + 1|| abort_loop) + if (*connect->scheduler->connection_count >= + *connect->scheduler->max_connections + 1|| abort_loop) { - mysql_mutex_unlock(&LOCK_connection_count); - DBUG_PRINT("error",("Too many connections")); - close_connection(thd, ER_CON_COUNT_ERROR); + + mysql_mutex_unlock(&LOCK_connection_count); statistic_increment(denied_connections, &LOCK_status); - delete thd; statistic_increment(connection_errors_max_connection, &LOCK_status); + connect->close_with_error(0, NullS, ER_CON_COUNT_ERROR); DBUG_VOID_RETURN; } - ++*thd->scheduler->connection_count; + ++*connect->scheduler->connection_count; if (connection_count + extra_connection_count > max_used_connections) max_used_connections= connection_count + extra_connection_count; @@ -6501,17 +6487,15 @@ static void create_new_thread(THD *thd) mysql_mutex_unlock(&LOCK_connection_count); thread_safe_increment32(&thread_count); + connect->thread_count_incremented= 1; - /* Start a new thread to handle connection. */ - mysql_mutex_lock(&LOCK_thread_count); /* The initialization of thread_id is done in create_embedded_thd() for the embedded library. TODO: refactor this to avoid code duplication there */ - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - - MYSQL_CALLBACK(thd->scheduler, add_connection, (thd)); + connect->thread_id= next_thread_id(); + connect->scheduler->add_connection(connect); DBUG_VOID_RETURN; } @@ -6546,13 +6530,12 @@ void handle_connections_sockets() MYSQL_SOCKET sock= mysql_socket_invalid(); MYSQL_SOCKET new_sock= mysql_socket_invalid(); uint error_count=0; - THD *thd; + CONNECT *connect; struct sockaddr_storage cAddr; int ip_flags __attribute__((unused))=0; int socket_flags __attribute__((unused))= 0; int extra_ip_flags __attribute__((unused))=0; int flags=0,retval; - st_vio *vio_tmp; bool is_unix_sock; #ifdef HAVE_POLL int socket_count= 0; @@ -6751,58 +6734,43 @@ void handle_connections_sockets() } #endif /* HAVE_LIBWRAP */ - /* - ** Don't allow too many connections - */ + DBUG_PRINT("info", ("Creating CONNECT for new connection")); - DBUG_PRINT("info", ("Creating THD for new connection")); - if (!(thd= new THD)) + if ((connect= new CONNECT())) { - (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); - (void) mysql_socket_close(new_sock); - statistic_increment(connection_errors_internal, &LOCK_status); - continue; - } - /* Set to get io buffers to be part of THD */ - set_current_thd(thd); - - is_unix_sock= (mysql_socket_getfd(sock) == - mysql_socket_getfd(unix_sock)); + is_unix_sock= (mysql_socket_getfd(sock) == + mysql_socket_getfd(unix_sock)); - if (!(vio_tmp= - mysql_socket_vio_new(new_sock, - is_unix_sock ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP, - is_unix_sock ? VIO_LOCALHOST: 0)) || - my_net_init(&thd->net, vio_tmp, thd, MYF(MY_THREAD_SPECIFIC))) - { - /* - Only delete the temporary vio if we didn't already attach it to the - NET object. The destructor in THD will delete any initialized net - structure. - */ - if (vio_tmp && thd->net.vio != vio_tmp) - vio_delete(vio_tmp); - else + if (!(connect->vio= + mysql_socket_vio_new(new_sock, + is_unix_sock ? VIO_TYPE_SOCKET : + VIO_TYPE_TCPIP, + is_unix_sock ? VIO_LOCALHOST: 0))) { - (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); - (void) mysql_socket_close(new_sock); + delete connect; + connect= 0; // Error handling below } - delete thd; + } + + if (!connect) + { + /* Connect failure */ + (void) mysql_socket_shutdown(new_sock, SHUT_RDWR); + (void) mysql_socket_close(new_sock); + statistic_increment(aborted_connects,&LOCK_status); statistic_increment(connection_errors_internal, &LOCK_status); continue; } - init_net_server_extension(thd); if (is_unix_sock) - thd->security_ctx->host=(char*) my_localhost; + connect->host= my_localhost; if (mysql_socket_getfd(sock) == mysql_socket_getfd(extra_ip_sock)) { - thd->extra_port= 1; - thd->scheduler= extra_thread_scheduler; + connect->extra_port= 1; + connect->scheduler= extra_thread_scheduler; } - create_new_thread(thd); - set_current_thd(0); + create_new_thread(connect); } sd_notify(0, "STOPPING=1\n" "STATUS=Shutdown in progress"); @@ -6823,7 +6791,6 @@ pthread_handler_t handle_connections_namedpipes(void *arg) { HANDLE hConnectedPipe; OVERLAPPED connectOverlapped= {0}; - THD *thd; my_thread_init(); DBUG_ENTER("handle_connections_namedpipes"); connectOverlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL); @@ -6891,25 +6858,19 @@ pthread_handler_t handle_connections_namedpipes(void *arg) hPipe=hConnectedPipe; continue; // We have to try again } - - if (!(thd = new THD)) + CONNECT *connect; + if (!(connect= new CONNECT) || + !(connect->vio= vio_new_win32pipe(hConnectedPipe))) { DisconnectNamedPipe(hConnectedPipe); CloseHandle(hConnectedPipe); + delete connect; + statistic_increment(aborted_connects,&LOCK_status); + statistic_increment(connection_errors_internal, &LOCK_status); continue; } - set_current_thd(thd); - if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) || - my_net_init(&thd->net, thd->net.vio, thd, MYF(MY_THREAD_SPECIFIC))) - { - close_connection(thd, ER_OUT_OF_RESOURCES); - delete thd; - continue; - } - /* Host is unknown */ - thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); - create_new_thread(thd); - set_current_thd(0); + connect->host= my_localhost; + create_new_thread(connect); } CloseHandle(connectOverlapped.hEvent); DBUG_LEAVE; @@ -6946,7 +6907,8 @@ pthread_handler_t handle_connections_shared_memory(void *arg) /* get enough space base-name + '_' + longest suffix we might ever send */ - if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, MYF(MY_FAE)))) + if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, + MYF(MY_FAE)))) goto error; if (my_security_attr_create(&sa_event, &errmsg, @@ -7012,7 +6974,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg) HANDLE event_server_wrote= 0; HANDLE event_server_read= 0; HANDLE event_conn_closed= 0; - THD *thd= 0; + CONNECT *connect= 0; p= int10_to_str(connect_number, connect_number_char, 10); /* @@ -7074,8 +7036,13 @@ pthread_handler_t handle_connections_shared_memory(void *arg) } if (abort_loop) goto errorconn; - if (!(thd= new THD)) + + if (!(connect= new CONNECT)) + { + errmsg= "Could not create CONNECT object"; goto errorconn; + } + /* Send number of connection to client */ int4store(handle_connect_map, connect_number); if (!SetEvent(event_connect_answer)) @@ -7089,24 +7056,20 @@ pthread_handler_t handle_connections_shared_memory(void *arg) errmsg= "Could not set client to read mode"; goto errorconn; } - set_current_thd(thd); - if (!(thd->net.vio= vio_new_win32shared_memory(handle_client_file_map, + if (!(connect->vio= vio_new_win32shared_memory(handle_client_file_map, handle_client_map, event_client_wrote, event_client_read, event_server_wrote, event_server_read, - event_conn_closed)) || - my_net_init(&thd->net, thd->net.vio, thd, MYF(MY_THREAD_SPECIFIC))) + event_conn_closed))) { - close_connection(thd, ER_OUT_OF_RESOURCES); - errmsg= 0; + errmsg= "Could not create VIO object"; goto errorconn; } - thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */ - create_new_thread(thd); + connect->host= my_localhost; /* Host is unknown */ + create_new_thread(connect); connect_number++; - set_current_thd(thd); continue; errorconn: @@ -7132,9 +7095,11 @@ errorconn: CloseHandle(event_client_read); if (event_conn_closed) CloseHandle(event_conn_closed); - delete thd; + + delete connect; + statistic_increment(aborted_connects,&LOCK_status); + statistic_increment(connection_errors_internal, &LOCK_status); } - set_current_thd(0); /* End shared memory handling */ error: @@ -7355,6 +7320,13 @@ struct my_option my_long_options[]= &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ +#ifndef DBUG_OFF + {"debug-assert-on-not-freed-memory", 0, + "Assert if we found problems with memory allocation", + &debug_assert_on_not_freed_memory, + &debug_assert_on_not_freed_memory, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, + 0}, +#endif /* DBUG_OFF */ /* default-storage-engine should have "MyISAM" as def_value. Instead of initializing it here it is done in init_common_variables() due to a compiler bug in Sun Studio compiler. */ @@ -7451,14 +7423,6 @@ struct my_option my_long_options[]= "Don't log extra information to update and slow-query logs.", &opt_short_log_format, &opt_short_log_format, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"log-slow-admin-statements", 0, - "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to " - "the slow log if it is open.", &opt_log_slow_admin_statements, - &opt_log_slow_admin_statements, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"log-slow-slave-statements", 0, - "Log slow statements executed by slave thread to the slow log if it is open.", - &opt_log_slow_slave_statements, &opt_log_slow_slave_statements, - 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-tc", 0, "Path to transaction coordinator log (used for transactions that affect " "more than one storage engine, when binary log is disabled).", @@ -7694,7 +7658,6 @@ struct my_option my_long_options[]= MYSQL_TO_BE_IMPLEMENTED_OPTION("slave-allow-batching"), // HAVE_REPLICATION MYSQL_COMPATIBILITY_OPTION("slave-checkpoint-period"), // HAVE_REPLICATION MYSQL_COMPATIBILITY_OPTION("slave-checkpoint-group"), // HAVE_REPLICATION - MYSQL_SUGGEST_ANALOG_OPTION("slave-parallel-workers", "--slave-parallel-threads"), // HAVE_REPLICATION MYSQL_SUGGEST_ANALOG_OPTION("slave-pending-jobs-size-max", "--slave-parallel-max-queued"), // HAVE_REPLICATION MYSQL_TO_BE_IMPLEMENTED_OPTION("disconnect-on-expired-password"), MYSQL_TO_BE_IMPLEMENTED_OPTION("sha256-password-private-key-path"), // HAVE_OPENSSL && !HAVE_YASSL @@ -7774,8 +7737,8 @@ static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff, get_master_info(&thd->variables.default_master_connection, Sql_condition::WARN_LEVEL_NOTE); if (mi) - tmp= (my_bool) (mi->slave_running == MYSQL_SLAVE_RUN_CONNECT && - mi->rli.slave_running); + tmp= (my_bool) (mi->slave_running == MYSQL_SLAVE_RUN_READING && + mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN); } mysql_mutex_unlock(&LOCK_active_mi); if (mi) @@ -7786,6 +7749,38 @@ static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff, } +/* How many slaves are connected to this master */ + +static int show_slaves_connected(THD *thd, SHOW_VAR *var, char *buff) +{ + + var->type= SHOW_LONGLONG; + var->value= buff; + mysql_mutex_lock(&LOCK_slave_list); + + *((longlong *)buff)= slave_list.records; + + mysql_mutex_unlock(&LOCK_slave_list); + return 0; +} + + +/* How many masters this slave is connected to */ + + +static int show_slaves_running(THD *thd, SHOW_VAR *var, char *buff) +{ + var->type= SHOW_LONGLONG; + var->value= buff; + mysql_mutex_lock(&LOCK_active_mi); + + *((longlong *)buff)= master_info_index->any_slave_sql_running(); + + mysql_mutex_unlock(&LOCK_active_mi); + return 0; +} + + static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff, enum enum_var_type scope) { @@ -8395,7 +8390,7 @@ SHOW_VAR status_vars[]= { {"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS}, {"Com", (char*) com_status_vars, SHOW_ARRAY}, {"Compression", (char*) &show_net_compression, SHOW_SIMPLE_FUNC}, - {"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH}, + {"Connections", (char*) &global_thread_id, SHOW_LONG_NOFLUSH}, {"Connection_errors_accept", (char*) &connection_errors_accept, SHOW_LONG}, {"Connection_errors_internal", (char*) &connection_errors_internal, SHOW_LONG}, {"Connection_errors_max_connections", (char*) &connection_errors_max_connection, SHOW_LONG}, @@ -8494,6 +8489,9 @@ SHOW_VAR status_vars[]= { {"Select_scan", (char*) offsetof(STATUS_VAR, select_scan_count_), SHOW_LONG_STATUS}, {"Slave_open_temp_tables", (char*) &slave_open_temp_tables, SHOW_INT}, #ifdef HAVE_REPLICATION + {"Slaves_connected", (char*) &show_slaves_connected, SHOW_SIMPLE_FUNC }, + {"Slaves_running", (char*) &show_slaves_running, SHOW_SIMPLE_FUNC }, + {"Slave_connections", (char*) offsetof(STATUS_VAR, com_register_slave), SHOW_LONG_STATUS}, {"Slave_heartbeat_period", (char*) &show_heartbeat_period, SHOW_SIMPLE_FUNC}, {"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats, SHOW_SIMPLE_FUNC}, {"Slave_retried_transactions",(char*)&slave_retried_transactions, SHOW_LONG}, @@ -8772,8 +8770,9 @@ static int mysql_init_variables(void) what_to_log= ~ (1L << (uint) COM_TIME); denied_connections= 0; executed_events= 0; - global_query_id= thread_id= 1L; - strmov(server_version, MYSQL_SERVER_VERSION); + global_query_id= 1; + global_thread_id= 1; + strnmov(server_version, MYSQL_SERVER_VERSION, sizeof(server_version)-1); threads.empty(); thread_cache.empty(); key_caches.empty(); @@ -9693,17 +9692,20 @@ void set_server_version(void) { if (!IS_SYSVAR_AUTOSIZE(&server_version_ptr)) return; - char *end= strxmov(server_version, MYSQL_SERVER_VERSION, - MYSQL_SERVER_SUFFIX_STR, NullS); + char *version_end= server_version+sizeof(server_version)-1; + char *end= strxnmov(server_version, sizeof(server_version)-1, + MYSQL_SERVER_VERSION, + MYSQL_SERVER_SUFFIX_STR, NullS); #ifdef EMBEDDED_LIBRARY - end= strmov(end, "-embedded"); + end= strnmov(end, "-embedded", (version_end-end)); #endif #ifndef DBUG_OFF if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug")) - end= strmov(end, "-debug"); + end= strnmov(end, "-debug", (version_end-end)); #endif if (opt_log || global_system_variables.sql_log_slow || opt_bin_log) - strmov(end, "-log"); // This may slow down system + strnmov(end, "-log", (version_end-end)); // This may slow down system + *end= 0; } @@ -10009,7 +10011,7 @@ void refresh_status(THD *thd) Set max_used_connections to the number of currently open connections. This is not perfect, but status data is not exact anyway. */ - max_used_connections= thread_count-delayed_insert_threads; + max_used_connections= connection_count + extra_connection_count; } #ifdef HAVE_PSI_INTERFACE diff --git a/sql/mysqld.h b/sql/mysqld.h index 4e6f2fcd29d..ef4a0d6a47a 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -30,6 +30,7 @@ #include "my_rdtsc.h" class THD; +class CONNECT; struct handlerton; class Time_zone; @@ -81,8 +82,8 @@ enum enum_slave_parallel_mode { /* Function prototypes */ void kill_mysql(THD *thd= 0); void close_connection(THD *thd, uint sql_errno= 0); -void handle_connection_in_main_thread(THD *thd); -void create_thread_to_handle_connection(THD *thd); +void handle_connection_in_main_thread(CONNECT *thd); +void create_thread_to_handle_connection(CONNECT *connect); void delete_running_thd(THD *thd); void signal_thd_deleted(); void unlink_thd(THD *thd); @@ -90,6 +91,8 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache); void flush_thread_cache(); void refresh_status(THD *thd); bool is_secure_file_path(char *path); +void dec_connection_count(scheduler_functions *scheduler); +extern void init_net_server_extension(THD *thd); extern "C" MYSQL_PLUGIN_IMPORT CHARSET_INFO *system_charset_info; extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *files_charset_info ; @@ -116,8 +119,9 @@ extern bool opt_disable_networking, opt_skip_show_db; extern bool opt_skip_name_resolve; extern bool opt_ignore_builtin_innodb; extern my_bool opt_character_set_client_handshake; +extern my_bool debug_assert_on_not_freed_memory; extern bool volatile abort_loop; -extern bool in_bootstrap; +extern bool volatile in_bootstrap; extern uint connection_count; extern my_bool opt_safe_user_create; extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap; @@ -177,7 +181,7 @@ extern char log_error_file[FN_REFLEN], *opt_tc_log_file; extern const double log_10[309]; extern ulonglong keybuff_size; extern ulonglong thd_startup_options; -extern ulong thread_id; +extern my_thread_id global_thread_id; extern ulong binlog_cache_use, binlog_cache_disk_use; extern ulong binlog_stmt_cache_use, binlog_stmt_cache_disk_use; extern ulong aborted_threads,aborted_connects; @@ -292,6 +296,7 @@ extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, key_relay_log_info_log_space_lock, key_relay_log_info_run_lock, key_rpl_group_info_sleep_lock, key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data, + key_LOCK_start_thread, key_LOCK_error_messages, key_LOCK_thread_count, key_PARTITION_LOCK_auto_inc; extern PSI_mutex_key key_RELAYLOG_LOCK_index; extern PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state, @@ -323,6 +328,7 @@ extern PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond, key_relay_log_info_start_cond, key_relay_log_info_stop_cond, key_rpl_group_info_sleep_cond, key_TABLE_SHARE_cond, key_user_level_lock_cond, + key_COND_start_thread, key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache; extern PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready, key_COND_wait_commit; @@ -558,6 +564,7 @@ extern mysql_mutex_t LOCK_prepared_stmt_count, LOCK_error_messages, LOCK_connection_count, LOCK_slave_init; extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_thread_count; +extern mysql_mutex_t LOCK_start_thread; #ifdef HAVE_OPENSSL extern char* des_key_file; extern mysql_mutex_t LOCK_des_key_file; @@ -566,7 +573,7 @@ extern mysql_mutex_t LOCK_server_started; extern mysql_cond_t COND_server_started; extern mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; extern mysql_rwlock_t LOCK_system_variables_hash; -extern mysql_cond_t COND_thread_count; +extern mysql_cond_t COND_thread_count, COND_start_thread; extern mysql_cond_t COND_manager; extern mysql_cond_t COND_slave_init; extern int32 thread_running; @@ -660,15 +667,16 @@ enum enum_query_type /// If NULLIF(a,b) should print itself as /// CASE WHEN a_for_comparison=b THEN NULL ELSE a_for_return_value END /// when "a" was replaced to two different items - /// (e.g. by equal fields propagation in optimize_cond()). - /// The default behaviour is to print as NULLIF(a_for_return, b) - /// which should be Ok for SHOW CREATE {VIEW|PROCEDURE|FUNCTION} - /// as they are not affected by WHERE optimization. - QT_ITEM_FUNC_NULLIF_TO_CASE= (1 <<6), + /// (e.g. by equal fields propagation in optimize_cond()) + /// or always as NULLIF(a, b). + /// The default behaviour is to use CASE syntax when + /// a_for_return_value is not the same as a_for_comparison. + /// SHOW CREATE {VIEW|PROCEDURE|FUNCTION} and other cases where the + /// original representation is required, should set this flag. + QT_ITEM_ORIGINAL_FUNC_NULLIF= (1 <<6), /// This value means focus on readability, not on ability to parse back, etc. QT_EXPLAIN= QT_TO_SYSTEM_CHARSET | - QT_ITEM_FUNC_NULLIF_TO_CASE | QT_ITEM_IDENT_SKIP_CURRENT_DATABASE | QT_ITEM_CACHE_WRAPPER_SKIP_DETAILS | QT_ITEM_SUBSELECT_ID_ONLY, @@ -677,7 +685,7 @@ enum enum_query_type /// Be more detailed than QT_EXPLAIN. /// Perhaps we should eventually include QT_ITEM_IDENT_SKIP_CURRENT_DATABASE /// here, as it would give better readable results - QT_EXPLAIN_EXTENDED= QT_TO_SYSTEM_CHARSET | QT_ITEM_FUNC_NULLIF_TO_CASE + QT_EXPLAIN_EXTENDED= QT_TO_SYSTEM_CHARSET }; @@ -698,6 +706,16 @@ inline query_id_t get_query_id() return my_atomic_load64_explicit(&global_query_id, MY_MEMORY_ORDER_RELAXED); } +/* increment global_thread_id and return it. */ +inline __attribute__((warn_unused_result)) my_thread_id next_thread_id() +{ + return my_atomic_add64_explicit(&global_thread_id, 1, MY_MEMORY_ORDER_RELAXED); +} + +#if defined(MYSQL_DYNAMIC_PLUGIN) && defined(_WIN32) +extern "C" my_thread_id next_thread_id_noinline(); +#define next_thread_id() next_thread_id_noinline() +#endif /* TODO: Replace this with an inline function. @@ -746,7 +764,8 @@ inline void dec_thread_running() thread_safe_decrement32(&thread_running); } -void set_server_version(void); +extern void set_server_version(void); +extern void dec_thread_count(void); #if defined(MYSQL_DYNAMIC_PLUGIN) && defined(_WIN32) extern "C" THD *_current_thd_noinline(); @@ -768,6 +787,7 @@ inline int set_current_thd(THD *thd) return my_pthread_setspecific_ptr(THR_THD, thd); } + /* @todo remove, make it static in ha_maria.cc currently it's needed for sql_select.cc diff --git a/sql/net_serv.cc b/sql/net_serv.cc index b6da7933bb1..f0284462206 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -34,6 +34,7 @@ HFTODO this must be hidden if we don't want client capabilities in embedded library */ + #include <my_global.h> #include <mysql.h> #include <mysql_com.h> @@ -107,13 +108,12 @@ extern void query_cache_insert(void *thd, const char *packet, ulong length, unsigned pkt_nr); #endif // HAVE_QUERY_CACHE #define update_statistics(A) A -#else -#define update_statistics(A) -#endif - -#ifdef MYSQL_SERVER +extern my_bool thd_net_is_killed(); /* Additional instrumentation hooks for the server */ #include "mysql_com_server.h" +#else +#define update_statistics(A) +#define thd_net_is_killed() 0 #endif #define TEST_BLOCKING 8 @@ -121,6 +121,8 @@ extern void query_cache_insert(void *thd, const char *packet, ulong length, static my_bool net_write_buff(NET *, const uchar *, ulong); +my_bool net_allocate_new_packet(NET *net, void *thd, uint my_flags); + /** Init with packet info. */ my_bool my_net_init(NET *net, Vio *vio, void *thd, uint my_flags) @@ -129,14 +131,12 @@ my_bool my_net_init(NET *net, Vio *vio, void *thd, uint my_flags) DBUG_PRINT("enter", ("my_flags: %u", my_flags)); net->vio = vio; my_net_local_init(net); /* Set some limits */ - if (!(net->buff=(uchar*) my_malloc((size_t) net->max_packet+ - NET_HEADER_SIZE + COMP_HEADER_SIZE +1, - MYF(MY_WME | my_flags)))) + + if (net_allocate_new_packet(net, thd, my_flags)) DBUG_RETURN(1); - net->buff_end=net->buff+net->max_packet; + net->error=0; net->return_status=0; net->pkt_nr=net->compress_pkt_nr=0; - net->write_pos=net->read_pos = net->buff; net->last_error[0]=0; net->compress=0; net->reading_or_writing=0; net->where_b = net->remain_in_buf=0; @@ -165,6 +165,18 @@ my_bool my_net_init(NET *net, Vio *vio, void *thd, uint my_flags) DBUG_RETURN(0); } +my_bool net_allocate_new_packet(NET *net, void *thd, uint my_flags) +{ + DBUG_ENTER("net_allocate_new_packet"); + if (!(net->buff=(uchar*) my_malloc((size_t) net->max_packet+ + NET_HEADER_SIZE + COMP_HEADER_SIZE +1, + MYF(MY_WME | my_flags)))) + DBUG_RETURN(1); + net->buff_end=net->buff+net->max_packet; + net->write_pos=net->read_pos = net->buff; + DBUG_RETURN(0); +} + void net_end(NET *net) { @@ -876,6 +888,16 @@ my_real_read(NET *net, size_t *complen, DBUG_PRINT("info",("vio_read returned %ld errno: %d", (long) length, vio_errno(net->vio))); + + if (i== 0 && thd_net_is_killed()) + { + len= packet_error; + net->error= 0; + net->last_errno= ER_CONNECTION_KILLED; + MYSQL_SERVER_my_error(net->last_errno, MYF(0)); + goto end; + } + #if !defined(__WIN__) && defined(MYSQL_SERVER) /* We got an error that there was no data on the socket. We now set up diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 79ac2fe38a7..af027ad6fdc 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -114,12 +114,11 @@ #include "sql_parse.h" // check_stack_overrun #include "sql_partition.h" // get_part_id_func, PARTITION_ITERATOR, // struct partition_info, NOT_A_PARTITION_ID -#include "sql_base.h" // free_io_cache #include "records.h" // init_read_record, end_read_record #include <m_ctype.h> #include "sql_select.h" #include "sql_statistics.h" -#include "filesort.h" // filesort_free_buffers +#include "uniques.h" #ifndef EXTRA_DEBUG #define test_rb_tree(A,B) {} @@ -1154,6 +1153,7 @@ int imerge_list_and_tree(RANGE_OPT_PARAM *param, SQL_SELECT *make_select(TABLE *head, table_map const_tables, table_map read_tables, COND *conds, + SORT_INFO *filesort, bool allow_null_cond, int *error) { @@ -1174,13 +1174,16 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables, select->head=head; select->cond= conds; - if (head->sort.io_cache) + if (filesort && my_b_inited(&filesort->io_cache)) { - select->file= *head->sort.io_cache; + /* + Hijack the filesort io_cache for make_select + SQL_SELECT will be responsible for ensuring that it's properly freed. + */ + select->file= filesort->io_cache; select->records=(ha_rows) (select->file.end_of_file/ head->file->ref_length); - my_free(head->sort.io_cache); - head->sort.io_cache=0; + my_b_clear(&filesort->io_cache); } DBUG_RETURN(select); } @@ -1393,7 +1396,6 @@ QUICK_INDEX_SORT_SELECT::~QUICK_INDEX_SORT_SELECT() delete pk_quick_select; /* It's ok to call the next two even if they are already deinitialized */ end_read_record(&read_record); - free_io_cache(head); free_root(&alloc,MYF(0)); DBUG_VOID_RETURN; } @@ -4336,15 +4338,14 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar) Field **field= (ppar->part_fields)? part_info->part_field_array : part_info->subpart_field_array; bool in_subpart_fields= FALSE; - uint max_key_len= 0; - uint cur_key_len= 0; + uint total_key_len= 0; for (uint part= 0; part < total_parts; part++, key_part++) { key_part->key= 0; key_part->part= part; key_part->length= (uint16)(*field)->key_length(); key_part->store_length= (uint16)get_partition_field_store_length(*field); - cur_key_len += key_part->store_length; + total_key_len += key_part->store_length; DBUG_PRINT("info", ("part %u length %u store_length %u", part, key_part->length, key_part->store_length)); @@ -4370,18 +4371,13 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar) { field= part_info->subpart_field_array; in_subpart_fields= TRUE; - max_key_len= cur_key_len; - cur_key_len= 0; } } range_par->key_parts_end= key_part; - if (cur_key_len > max_key_len) - max_key_len= cur_key_len; - - max_key_len++; /* Take into account the "+1" in QUICK_RANGE::QUICK_RANGE */ - if (!(range_par->min_key= (uchar*)alloc_root(alloc,max_key_len)) || - !(range_par->max_key= (uchar*)alloc_root(alloc,max_key_len))) + total_key_len++; /* Take into account the "+1" in QUICK_RANGE::QUICK_RANGE */ + if (!(range_par->min_key= (uchar*)alloc_root(alloc,total_key_len)) || + !(range_par->max_key= (uchar*)alloc_root(alloc,total_key_len))) { return true; } @@ -10680,7 +10676,6 @@ int read_keys_and_merge_scans(THD *thd, else { unique->reset(); - filesort_free_buffers(head, false); } DBUG_ASSERT(file->ref_length == unique->get_size()); @@ -10733,7 +10728,7 @@ int read_keys_and_merge_scans(THD *thd, /* Ok all rowids are in the Unique now. The next call will initialize - head->sort structure so it can be used to iterate through the rowids + the unique structure so it can be used to iterate through the rowids sequence. */ result= unique->get(head); @@ -10742,7 +10737,8 @@ int read_keys_and_merge_scans(THD *thd, */ if (enabled_keyread) head->set_keyread(false); - if (init_read_record(read_record, thd, head, (SQL_SELECT*) 0, 1 , 1, TRUE)) + if (init_read_record(read_record, thd, head, (SQL_SELECT*) 0, + &unique->sort, 1 , 1, TRUE)) result= 1; DBUG_RETURN(result); @@ -10785,7 +10781,8 @@ int QUICK_INDEX_MERGE_SELECT::get_next() { result= HA_ERR_END_OF_FILE; end_read_record(&read_record); - free_io_cache(head); + // Free things used by sort early. Shouldn't be strictly necessary + unique->sort.reset(); /* All rows from Unique have been retrieved, do a clustered PK scan */ if (pk_quick_select) { @@ -10820,7 +10817,7 @@ int QUICK_INDEX_INTERSECT_SELECT::get_next() { result= HA_ERR_END_OF_FILE; end_read_record(&read_record); - free_io_cache(head); + unique->sort.reset(); // Free things early } DBUG_RETURN(result); @@ -14621,6 +14618,4 @@ void QUICK_GROUP_MIN_MAX_SELECT::dbug_dump(int indent, bool verbose) } } - #endif /* !DBUG_OFF */ - diff --git a/sql/opt_range.h b/sql/opt_range.h index 80f4064a529..6970b87f6d8 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -26,6 +26,8 @@ #include "records.h" /* READ_RECORD */ #include "queues.h" /* QUEUE */ +#include "filesort.h" /* SORT_INFO */ + /* It is necessary to include set_var.h instead of item.h because there are dependencies on include order for set_var.h and item.h. This @@ -1658,6 +1660,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, ha_rows records); SQL_SELECT *make_select(TABLE *head, table_map const_tables, table_map read_tables, COND *conds, + SORT_INFO* filesort, bool allow_null_cond, int *error); bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond); diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index a1c4187f5ca..9140ed11828 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -833,12 +833,14 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs) in_subs->sjm_scan_allowed= FALSE; bool all_are_fields= TRUE; + uint32 total_key_length = 0; for (uint i= 0; i < elements; i++) { Item *outer= in_subs->left_expr->element_index(i); Item *inner= it++; all_are_fields &= (outer->real_item()->type() == Item::FIELD_ITEM && inner->real_item()->type() == Item::FIELD_ITEM); + total_key_length += inner->max_length; if (outer->cmp_type() != inner->cmp_type()) DBUG_RETURN(FALSE); switch (outer->cmp_type()) { @@ -869,6 +871,15 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs) } } + /* + Make sure that create_tmp_table will not fail due to too long keys. + See MDEV-7122. This check is performed inside create_tmp_table also and + we must do it so that we know the table has keys created. + */ + if (total_key_length > tmp_table_max_key_length() || + elements > tmp_table_max_key_parts()) + DBUG_RETURN(FALSE); + in_subs->types_allow_materialization= TRUE; in_subs->sjm_scan_allowed= all_are_fields; DBUG_PRINT("info",("subquery_types_allow_materialization: ok, allowed")); @@ -3936,7 +3947,7 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd) { /* if we run out of slots or we are not using tempool */ sprintf(path,"%s%lx_%lx_%x", tmp_file_prefix,current_pid, - thd->thread_id, thd->tmp_table++); + (ulong) thd->thread_id, thd->tmp_table++); } fn_format(path, path, mysql_tmpdir, "", MY_REPLACE_EXT|MY_UNPACK_FILENAME); @@ -4720,8 +4731,6 @@ int clear_sj_tmp_tables(JOIN *join) { if ((res= table->file->ha_delete_all_rows())) return res; /* purecov: inspected */ - free_io_cache(table); - filesort_free_buffers(table,0); } SJ_MATERIALIZATION_INFO *sjm; @@ -5525,7 +5534,8 @@ bool JOIN::choose_subquery_plan(table_map join_tables) outer join has not been optimized yet). */ if (outer_join && outer_join->table_count > 0 && // (1) - outer_join->join_tab) // (2) + outer_join->join_tab && // (2) + !in_subs->const_item()) { /* TODO: diff --git a/sql/records.cc b/sql/records.cc index f208c507fbe..e7a4ab836c0 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -29,10 +29,10 @@ #include "records.h" #include "sql_priv.h" #include "records.h" -#include "filesort.h" // filesort_free_buffers #include "opt_range.h" // SQL_SELECT #include "sql_class.h" // THD #include "sql_base.h" +#include "sql_sort.h" // SORT_ADDON_FIELD static int rr_quick(READ_RECORD *info); int rr_sequential(READ_RECORD *info); @@ -182,26 +182,30 @@ bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table, SQL_SELECT *select, + SORT_INFO *filesort, int use_record_cache, bool print_error, bool disable_rr_cache) { IO_CACHE *tempfile; + SORT_ADDON_FIELD *addon_field= filesort ? filesort->addon_field : 0; DBUG_ENTER("init_read_record"); bzero((char*) info,sizeof(*info)); info->thd=thd; info->table=table; info->forms= &info->table; /* Only one table */ + info->addon_field= addon_field; if ((table->s->tmp_table == INTERNAL_TMP_TABLE || table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE) && - !table->sort.addon_field) + !addon_field) (void) table->file->extra(HA_EXTRA_MMAP); - if (table->sort.addon_field) + if (addon_field) { - info->rec_buf= table->sort.addon_buf; - info->ref_length= table->sort.addon_length; + info->rec_buf= (uchar*) filesort->addon_buf.str; + info->ref_length= filesort->addon_buf.length; + info->unpack= filesort->unpack; } else { @@ -213,19 +217,20 @@ bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table, info->print_error=print_error; info->unlock_row= rr_unlock_row; info->ignore_not_found_rows= 0; - table->status=0; /* And it's always found */ + table->status= 0; /* Rows are always found */ + tempfile= 0; if (select && my_b_inited(&select->file)) tempfile= &select->file; - else - tempfile= table->sort.io_cache; - if (tempfile && my_b_inited(tempfile) && - !(select && select->quick)) + else if (filesort && my_b_inited(&filesort->io_cache)) + tempfile= &filesort->io_cache; + + if (tempfile && !(select && select->quick)) { DBUG_PRINT("info",("using rr_from_tempfile")); - info->read_record= (table->sort.addon_field ? + info->read_record= (addon_field ? rr_unpack_from_tempfile : rr_from_tempfile); - info->io_cache=tempfile; + info->io_cache= tempfile; reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0); info->ref_pos=table->file->ref; if (!table->file->inited) @@ -233,12 +238,12 @@ bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table, DBUG_RETURN(1); /* - table->sort.addon_field is checked because if we use addon fields, + addon_field is checked because if we use addon fields, it doesn't make sense to use cache - we don't read from the table - and table->sort.io_cache is read sequentially + and filesort->io_cache is read sequentially */ if (!disable_rr_cache && - !table->sort.addon_field && + !addon_field && thd->variables.read_rnd_buff_size && !(table->file->ha_table_flags() & HA_FAST_KEY_READ) && (table->db_stat & HA_READ_ONLY || @@ -263,15 +268,15 @@ bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table, DBUG_PRINT("info",("using rr_quick")); info->read_record=rr_quick; } - else if (table->sort.record_pointers) + else if (filesort && filesort->record_pointers) { DBUG_PRINT("info",("using record_pointers")); if (table->file->ha_rnd_init_with_error(0)) DBUG_RETURN(1); - info->cache_pos=table->sort.record_pointers; - info->cache_end=info->cache_pos+ - table->sort.found_records*info->ref_length; - info->read_record= (table->sort.addon_field ? + info->cache_pos= filesort->record_pointers; + info->cache_end= (info->cache_pos+ + filesort->return_rows * info->ref_length); + info->read_record= (addon_field ? rr_unpack_from_buffer : rr_from_pointers); } else @@ -288,7 +293,7 @@ bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table, (use_record_cache < 0 && !(table->file->ha_table_flags() & HA_NOT_DELETE_WITH_CACHE)))) (void) table->file->extra_opt(HA_EXTRA_CACHE, - thd->variables.read_buff_size); + thd->variables.read_buff_size); } /* Condition pushdown to storage engine */ if ((table->file->ha_table_flags() & HA_CAN_TABLE_CONDITION_PUSHDOWN) && @@ -311,7 +316,6 @@ void end_read_record(READ_RECORD *info) } if (info->table) { - filesort_free_buffers(info->table,0); if (info->table->is_created()) (void) info->table->file->extra(HA_EXTRA_NO_CACHE); if (info->read_record != rr_quick) // otherwise quick_range does it @@ -525,9 +529,8 @@ static int rr_unpack_from_tempfile(READ_RECORD *info) { if (my_b_read(info->io_cache, info->rec_buf, info->ref_length)) return -1; - TABLE *table= info->table; - (*table->sort.unpack)(table->sort.addon_field, info->rec_buf, - info->rec_buf + info->ref_length); + (*info->unpack)(info->addon_field, info->rec_buf, + info->rec_buf + info->ref_length); return 0; } @@ -577,11 +580,9 @@ static int rr_unpack_from_buffer(READ_RECORD *info) { if (info->cache_pos == info->cache_end) return -1; /* End of buffer */ - TABLE *table= info->table; - (*table->sort.unpack)(table->sort.addon_field, info->cache_pos, - info->cache_end); + (*info->unpack)(info->addon_field, info->cache_pos, + info->cache_end); info->cache_pos+= info->ref_length; - return 0; } /* cacheing of records from a database */ diff --git a/sql/records.h b/sql/records.h index a3f0b5eb084..1928acfd4f4 100644 --- a/sql/records.h +++ b/sql/records.h @@ -25,6 +25,7 @@ struct TABLE; class THD; class SQL_SELECT; class Copy_field; +class SORT_INFO; /** A context for reading through a single table using a chosen access method: @@ -60,8 +61,10 @@ struct READ_RECORD uchar *record; uchar *rec_buf; /* to read field values after filesort */ uchar *cache,*cache_pos,*cache_end,*read_positions; + struct st_sort_addon_field *addon_field; /* Pointer to the fields info */ struct st_io_cache *io_cache; bool print_error, ignore_not_found_rows; + void (*unpack)(struct st_sort_addon_field *, uchar *, uchar *); /* SJ-Materialization runtime may need to read fields from the materialized @@ -74,7 +77,8 @@ public: }; bool init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form, - SQL_SELECT *select, int use_record_cache, + SQL_SELECT *select, SORT_INFO *sort, + int use_record_cache, bool print_errors, bool disable_rr_cache); bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, bool print_error, uint idx, bool reverse); diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 47c0f4e3fb7..f54ef2b0081 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -567,7 +567,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, Updates in slave state table should not be appended to galera transaction writeset. */ - thd->wsrep_skip_append_keys= true; + thd->wsrep_ignore_table= true; #endif if (!in_transaction) @@ -685,7 +685,7 @@ IF_DBUG(dbug_break:, ) end: #ifdef WITH_WSREP - thd->wsrep_skip_append_keys= false; + thd->wsrep_ignore_table= false; #endif if (table_opened) diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 216fbde0177..df721342d1d 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -35,7 +35,8 @@ Master_info::Master_info(LEX_STRING *connection_name_arg, rli(is_slave_recovery), port(MYSQL_PORT), checksum_alg_before_fd(BINLOG_CHECKSUM_ALG_UNDEF), connect_retry(DEFAULT_CONNECT_RETRY), inited(0), abort_slave(0), - slave_running(0), slave_run_id(0), clock_diff_with_master(0), + slave_running(MYSQL_SLAVE_NOT_RUN), slave_run_id(0), + clock_diff_with_master(0), sync_counter(0), heartbeat_period(0), received_heartbeats(0), master_id(0), prev_master_id(0), using_gtid(USE_GTID_NO), events_queued_since_last_gtid(0), @@ -1396,23 +1397,24 @@ bool Master_info_index::give_error_if_slave_running() The LOCK_active_mi must be held while calling this function. @return - TRUE If some slave SQL thread is running. - FALSE No slave SQL thread is running + 0 No Slave SQL thread is running + # Number of slave SQL thread running */ -bool Master_info_index::any_slave_sql_running() +uint Master_info_index::any_slave_sql_running() { + uint count= 0; DBUG_ENTER("any_slave_sql_running"); if (!this) // master_info_index is set to NULL on server shutdown - DBUG_RETURN(TRUE); + DBUG_RETURN(count); for (uint i= 0; i< master_info_hash.records; ++i) { Master_info *mi= (Master_info *)my_hash_element(&master_info_hash, i); if (mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN) - DBUG_RETURN(TRUE); + count++; } - DBUG_RETURN(FALSE); + DBUG_RETURN(count); } @@ -1442,7 +1444,7 @@ bool Master_info_index::start_all_slaves(THD *thd) Try to start all slaves that are configured (host is defined) and are not already running */ - if ((mi->slave_running != MYSQL_SLAVE_RUN_CONNECT || + if ((mi->slave_running == MYSQL_SLAVE_NOT_RUN || !mi->rli.slave_running) && *mi->host) { if ((error= start_slave(thd, mi, 1))) diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index 69d602c1dcb..9365c065ea9 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -345,7 +345,7 @@ public: Master_info *get_master_info(const LEX_STRING *connection_name, Sql_condition::enum_warning_level warning); bool give_error_if_slave_running(); - bool any_slave_sql_running(); + uint any_slave_sql_running(); bool start_all_slaves(THD *thd); bool stop_all_slaves(THD *thd); }; diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index b4e7b1a89dd..acdedd6e0a0 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -705,7 +705,7 @@ do_retry: thd->clear_error(); /* - If we retry due to a deadlock kill that occured during the commit step, we + If we retry due to a deadlock kill that occurred during the commit step, we might have already updated (but not committed) an update of table mysql.gtid_slave_pos, and cleared the gtid_pending flag. Now we have rolled back any such update, so we must set the gtid_pending flag back to @@ -969,10 +969,8 @@ handle_rpl_parallel_thread(void *arg) my_thread_init(); thd = new THD; thd->thread_stack = (char*)&thd; - mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); + thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id(); + add_to_active_threads(thd); set_current_thd(thd); pthread_detach_this_thread(); thd->init_for_queries(); @@ -1128,7 +1126,7 @@ handle_rpl_parallel_thread(void *arg) /* Register ourself to wait for the previous commit, if we need to do such registration _and_ that previous commit has not already - occured. + occurred. */ register_wait_for_prior_event_group_commit(rgi, entry); @@ -1189,7 +1187,7 @@ handle_rpl_parallel_thread(void *arg) { /* Do an extra check for (deadlock) kill here. This helps prevent a - lingering deadlock kill that occured during normal DML processing to + lingering deadlock kill that occurred during normal DML processing to propagate past the mark_start_commit(). If we detect a deadlock only after mark_start_commit(), we have to unmark, which has at least a theoretical possibility of leaving a window where it looks like all @@ -1372,10 +1370,10 @@ handle_rpl_parallel_thread(void *arg) thd->reset_db(NULL, 0); thd_proc_info(thd, "Slave worker thread exiting"); thd->temporary_tables= 0; - mysql_mutex_lock(&LOCK_thread_count); + THD_CHECK_SENTRY(thd); + unlink_not_visible_thd(thd); delete thd; - mysql_mutex_unlock(&LOCK_thread_count); mysql_mutex_lock(&rpt->LOCK_rpl_thread); rpt->running= false; diff --git a/sql/rpl_parallel.h b/sql/rpl_parallel.h index 9bb37f77dbd..c6f77b0144c 100644 --- a/sql/rpl_parallel.h +++ b/sql/rpl_parallel.h @@ -319,7 +319,7 @@ struct rpl_parallel_entry { group here. Then later event groups (with higher sub_id) can know not to try to start (event groups that already started will be rolled back when wait_for_prior_commit() returns error). - The value is ULONGLONG_MAX when no error occured. + The value is ULONGLONG_MAX when no error occurred. */ uint64 stop_on_error_sub_id; /* diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 208b2b61704..f82c5a3982a 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -185,7 +185,7 @@ pack_row(TABLE *table, MY_BITMAP const* cols, @retval HA_ERR_GENERIC A generic, internal, error caused the unpacking to fail. - @retval ER_SLAVE_CORRUPT_EVENT + @retval HA_ERR_CORRUPT_EVENT Found error when trying to unpack fields. */ #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) @@ -349,7 +349,7 @@ unpack_row(rpl_group_info *rgi, "Could not read field '%s' of table '%s.%s'", f->field_name, table->s->db.str, table->s->table_name.str); - DBUG_RETURN(ER_SLAVE_CORRUPT_EVENT); + DBUG_RETURN(HA_ERR_CORRUPT_EVENT); } } diff --git a/sql/rpl_reporting.cc b/sql/rpl_reporting.cc index 49708df40f7..ad949402511 100644 --- a/sql/rpl_reporting.cc +++ b/sql/rpl_reporting.cc @@ -59,6 +59,7 @@ Slave_reporting_capability::report(loglevel level, int err_code, report_function= sql_print_information; break; default: + va_end(args); DBUG_ASSERT(0); // should not come here return; // don't crash production builds, just do nothing } diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 987e011d5eb..2dd6f7d7afc 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -63,7 +63,7 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery) last_master_timestamp(0), sql_thread_caught_up(true), slave_skip_counter(0), abort_pos_wait(0), slave_run_id(0), sql_driver_thd(), gtid_skip_flag(GTID_SKIP_NOT), inited(0), abort_slave(0), stop_for_until(0), - slave_running(0), until_condition(UNTIL_NONE), + slave_running(MYSQL_SLAVE_NOT_RUN), until_condition(UNTIL_NONE), until_log_pos(0), retried_trans(0), executed_entries(0), m_flags(0) { @@ -389,6 +389,7 @@ Failed to open the existing relay log info file '%s' (errno %d)", if (rli->is_relay_log_recovery && init_recovery(rli->mi, &msg)) goto err; + rli->relay_log_state.load(rpl_global_gtid_slave_state); if (init_relay_log_pos(rli, rli->group_relay_log_name, rli->group_relay_log_pos, @@ -1148,6 +1149,7 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, error=1; goto err; } + rli->relay_log_state.load(rpl_global_gtid_slave_state); if (!just_reset) { /* Save name of used relay log file */ diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index 244363e43ac..bdf5b7dea80 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -15,6 +15,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <my_global.h> +#include <my_bit.h> #include "rpl_utility.h" #include "log_event.h" @@ -23,30 +24,6 @@ #include "sql_select.h" /** - Function to compare two size_t integers for their relative - order. Used below. - */ -int compare(size_t a, size_t b) -{ - if (a < b) - return -1; - if (b < a) - return 1; - return 0; -} - - -/** - Max value for an unsigned integer of 'bits' bits. - - The somewhat contorted expression is to avoid overflow. - */ -uint32 uint_max(int bits) { - return (((1UL << (bits - 1)) - 1) << 1) | 1; -} - - -/** Calculate display length for MySQL56 temporal data types from their metadata. It contains fractional precision in the low 16-bit word. */ @@ -121,20 +98,22 @@ max_display_length_for_field(enum_field_types sql_type, unsigned int metadata) return 3; case MYSQL_TYPE_DATE: - case MYSQL_TYPE_TIME: return 3; + case MYSQL_TYPE_TIME: + return MIN_TIME_WIDTH; + case MYSQL_TYPE_TIME2: return max_display_length_for_temporal2_field(MIN_TIME_WIDTH, metadata); case MYSQL_TYPE_TIMESTAMP: - return 4; + return MAX_DATETIME_WIDTH; case MYSQL_TYPE_TIMESTAMP2: return max_display_length_for_temporal2_field(MAX_DATETIME_WIDTH, metadata); case MYSQL_TYPE_DATETIME: - return 8; + return MAX_DATETIME_WIDTH; case MYSQL_TYPE_DATETIME2: return max_display_length_for_temporal2_field(MAX_DATETIME_WIDTH, metadata); @@ -160,10 +139,10 @@ max_display_length_for_field(enum_field_types sql_type, unsigned int metadata) */ case MYSQL_TYPE_TINY_BLOB: - return uint_max(1 * 8); + return my_set_bits(1 * 8); case MYSQL_TYPE_MEDIUM_BLOB: - return uint_max(3 * 8); + return my_set_bits(3 * 8); case MYSQL_TYPE_BLOB: /* @@ -171,11 +150,11 @@ max_display_length_for_field(enum_field_types sql_type, unsigned int metadata) blobs are of type MYSQL_TYPE_BLOB. In that case, we have to look at the length instead to decide what the max display size is. */ - return uint_max(metadata * 8); + return my_set_bits(metadata * 8); case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_GEOMETRY: - return uint_max(4 * 8); + return my_set_bits(4 * 8); default: return ~(uint32) 0; @@ -205,7 +184,7 @@ int compare_lengths(Field *field, enum_field_types source_type, uint16 metadata) " target_length: %lu, target_type: %u", (unsigned long) source_length, source_type, (unsigned long) target_length, field->real_type())); - int result= compare(source_length, target_length); + int result= source_length < target_length ? -1 : source_length > target_length; DBUG_PRINT("result", ("%d", result)); DBUG_RETURN(result); } diff --git a/sql/scheduler.cc b/sql/scheduler.cc index bc3166210b5..2a0138d06a8 100644 --- a/sql/scheduler.cc +++ b/sql/scheduler.cc @@ -22,9 +22,9 @@ #pragma implementation #endif +#include "mysqld.h" #include "sql_connect.h" // init_new_connection_handler_thread #include "scheduler.h" -#include "mysqld.h" #include "sql_class.h" #include "sql_callback.h" #include <violite.h> @@ -35,7 +35,8 @@ static bool no_threads_end(THD *thd, bool put_in_cache) { - unlink_thd(thd); + if (thd) + unlink_thd(thd); return 1; // Abort handle_one_connection } @@ -81,7 +82,9 @@ static void scheduler_wait_net_end(void) { one_thread_scheduler() or one_thread_per_connection_scheduler() in mysqld.cc, so this init function will always be called. */ -void scheduler_init() { + +void scheduler_init() +{ thr_set_lock_wait_callback(scheduler_wait_lock_begin, scheduler_wait_lock_end); thr_set_sync_wait_callback(scheduler_wait_sync_begin, @@ -118,7 +121,6 @@ void post_kill_notification(THD *thd) #ifndef EMBEDDED_LIBRARY - void one_thread_per_connection_scheduler(scheduler_functions *func, ulong *arg_max_connections, uint *arg_connection_count) @@ -132,6 +134,14 @@ void one_thread_per_connection_scheduler(scheduler_functions *func, func->end_thread= one_thread_per_connection_end; func->post_kill_notification= post_kill_notification; } +#else +bool init_new_connection_handler_thread() +{ + return 0; +} +void handle_connection_in_main_thread(CONNECT *connect) +{ +} #endif /* @@ -144,10 +154,7 @@ void one_thread_scheduler(scheduler_functions *func) func->max_threads= 1; func->max_connections= &max_connections; func->connection_count= &connection_count; -#ifndef EMBEDDED_LIBRARY func->init_new_connection_thread= init_new_connection_handler_thread; func->add_connection= handle_connection_in_main_thread; -#endif func->end_thread= no_threads_end; } - diff --git a/sql/scheduler.h b/sql/scheduler.h index f7aff377eac..71553372999 100644 --- a/sql/scheduler.h +++ b/sql/scheduler.h @@ -37,7 +37,7 @@ struct scheduler_functions ulong *max_connections; bool (*init)(void); bool (*init_new_connection_thread)(void); - void (*add_connection)(THD *thd); + void (*add_connection)(CONNECT *connect); void (*thd_wait_begin)(THD *thd, int wait_type); void (*thd_wait_end)(THD *thd); void (*post_kill_notification)(THD *thd); diff --git a/sql/set_var.cc b/sql/set_var.cc index 18f6cbc41fd..b5430c56865 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -739,7 +739,7 @@ int set_var::check(THD *thd) if ((!value->fixed && value->fix_fields(thd, &value)) || value->check_cols(1)) return -1; - if (var->check_update_type(value->result_type())) + if (var->check_update_type(value)) { my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name.str); return -1; diff --git a/sql/set_var.h b/sql/set_var.h index b8192e67ca9..cf86ecf18fa 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -137,8 +137,9 @@ public: bool is_set_stmt_ok() const { return !(flags & NO_SET_STATEMENT); } bool is_written_to_binlog(enum_var_type type) { return type != OPT_GLOBAL && binlog_status == SESSION_VARIABLE_IN_BINLOG; } - bool check_update_type(Item_result type) + bool check_update_type(const Item *item) { + Item_result type= item->result_type(); switch (option.var_type & GET_TYPE_MASK) { case GET_INT: case GET_UINT: @@ -146,7 +147,8 @@ public: case GET_ULONG: case GET_LL: case GET_ULL: - return type != INT_RESULT; + return type != INT_RESULT && + (type != DECIMAL_RESULT || item->decimals != 0); case GET_STR: case GET_STR_ALLOC: return type != STRING_RESULT; diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 062854d8cea..dfd12ec20ac 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -3947,21 +3947,21 @@ ER_ERROR_DURING_CHECKPOINT swe "Fick fel %M vid CHECKPOINT" ukr "Отримано помилку %M під Ñ‡Ð°Ñ CHECKPOINT" ER_NEW_ABORTING_CONNECTION 08S01 - cze "Spojenà %ld do databáze: '%-.192s' uživatel: '%-.48s' stroj: '%-.64s' (%-.64s) bylo pÅ™eruÅ¡eno" - dan "Afbrød forbindelsen %ld til databasen '%-.192s' bruger: '%-.48s' vært: '%-.64s' (%-.64s)" - nla "Afgebroken verbinding %ld naar db: '%-.192s' gebruiker: '%-.48s' host: '%-.64s' (%-.64s)" - eng "Aborted connection %ld to db: '%-.192s' user: '%-.48s' host: '%-.64s' (%-.64s)" - est "Ühendus katkestatud %ld andmebaas: '%-.192s' kasutaja: '%-.48s' masin: '%-.64s' (%-.64s)" - fre "Connection %ld avortée vers la bd: '%-.192s' utilisateur: '%-.48s' hôte: '%-.64s' (%-.64s)" - ger "Abbruch der Verbindung %ld zur Datenbank '%-.192s'. Benutzer: '%-.48s', Host: '%-.64s' (%-.64s)" - ita "Interrotta la connessione %ld al db: ''%-.192s' utente: '%-.48s' host: '%-.64s' (%-.64s)" - jpn "接続 %ld ãŒä¸æ–ã•れã¾ã—ãŸã€‚データベース: '%-.192s' ユーザー: '%-.48s' ホスト: '%-.64s' (%-.64s)" - por "Conexão %ld abortada para banco de dados '%-.192s' - usuário '%-.48s' - 'host' '%-.64s' ('%-.64s')" - rus "Прервано Ñоединение %ld к базе данных '%-.192s' Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ '%-.48s' Ñ Ñ…Ð¾Ñта '%-.64s' (%-.64s)" - serbian "Prekinuta konekcija broj %ld ka bazi: '%-.192s' korisnik je bio: '%-.48s' a host: '%-.64s' (%-.64s)" - spa "Abortada conexión %ld para db: '%-.192s' usuario: '%-.48s' servidor: '%-.64s' (%-.64s)" - swe "Avbröt länken för trÃ¥d %ld till db '%-.192s', användare '%-.48s', host '%-.64s' (%-.64s)" - ukr "Перервано з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ %ld до бази данних: '%-.192s' кориÑтувач: '%-.48s' хоÑÑ‚: '%-.64s' (%-.64s)" + cze "Spojenà %lld do databáze: '%-.192s' uživatel: '%-.48s' stroj: '%-.64s' (%-.64s) bylo pÅ™eruÅ¡eno" + dan "Afbrød forbindelsen %lld til databasen '%-.192s' bruger: '%-.48s' vært: '%-.64s' (%-.64s)" + nla "Afgebroken verbinding %lld naar db: '%-.192s' gebruiker: '%-.48s' host: '%-.64s' (%-.64s)" + eng "Aborted connection %lld to db: '%-.192s' user: '%-.48s' host: '%-.64s' (%-.64s)" + est "Ühendus katkestatud %lld andmebaas: '%-.192s' kasutaja: '%-.48s' masin: '%-.64s' (%-.64s)" + fre "Connection %lld avortée vers la bd: '%-.192s' utilisateur: '%-.48s' hôte: '%-.64s' (%-.64s)" + ger "Abbruch der Verbindung %lld zur Datenbank '%-.192s'. Benutzer: '%-.48s', Host: '%-.64s' (%-.64s)" + ita "Interrotta la connessione %lld al db: ''%-.192s' utente: '%-.48s' host: '%-.64s' (%-.64s)" + jpn "接続 %lld ãŒä¸æ–ã•れã¾ã—ãŸã€‚データベース: '%-.192s' ユーザー: '%-.48s' ホスト: '%-.64s' (%-.64s)" + por "Conexão %lld abortada para banco de dados '%-.192s' - usuário '%-.48s' - 'host' '%-.64s' ('%-.64s')" + rus "Прервано Ñоединение %lld к базе данных '%-.192s' Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ '%-.48s' Ñ Ñ…Ð¾Ñта '%-.64s' (%-.64s)" + serbian "Prekinuta konekcija broj %lld ka bazi: '%-.192s' korisnik je bio: '%-.48s' a host: '%-.64s' (%-.64s)" + spa "Abortada conexión %lld para db: '%-.192s' usuario: '%-.48s' servidor: '%-.64s' (%-.64s)" + swe "Avbröt länken för trÃ¥d %lld till db '%-.192s', användare '%-.48s', host '%-.64s' (%-.64s)" + ukr "Перервано з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ %lld до бази данних: '%-.192s' кориÑтувач: '%-.48s' хоÑÑ‚: '%-.64s' (%-.64s)" ER_UNUSED_10 eng "You should never see it" ER_FLUSH_MASTER_BINLOG_CLOSED @@ -6034,7 +6034,7 @@ ER_EVENT_CANNOT_ALTER_IN_THE_PAST eng "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was not changed. Specify a time in the future." ger "Execution Zeitpunkt des Ereignisses in der Vergangenheit liegt, und es war NACH ABSCHLUSS Set nicht erhalten. Die Veranstaltung wurde nicht verändert. Geben Sie einen Zeitpunkt in der Zukunft." ER_SLAVE_INCIDENT - eng "The incident %s occured on the master. Message: %-.64s" + eng "The incident %s occurred on the master. Message: %-.64s" ger "Der Vorfall %s passierte auf dem Master. Meldung: %-.64s" ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT eng "Table has no partition for some existing values" @@ -7106,7 +7106,7 @@ ER_PRIOR_COMMIT_FAILED ER_IT_IS_A_VIEW 42S02 eng "'%-.192s' is a view" ER_SLAVE_SKIP_NOT_IN_GTID - eng "When using GTID, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position." + eng "When using parallel replication and GTID with multiple replication domains, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position." ER_TABLE_DEFINITION_TOO_BIG eng "The definition for table %`s is too big" ER_PLUGIN_INSTALLED @@ -7136,6 +7136,24 @@ ER_KILL_QUERY_DENIED_ERROR eng "You are not owner of query %lu" ger "Sie sind nicht Eigentümer von Abfrage %lu" rus "Ð’Ñ‹ не ÑвлÑетеÑÑŒ владельцем запроÑа %lu" +ER_NO_EIS_FOR_FIELD + eng "Engine-independent statistics are not collected for column '%s'" + ukr "Ðезалежна від типу таблиці ÑтатиÑтика не збираєтьÑÑ Ð´Ð»Ñ ÑÑ‚Ð¾Ð²Ð±Ñ†Ñ '%s'" +ER_COMMULTI_BADCONTEXT 0A000 + eng "COM_MULTI can't return a result set in the given context" + ger "COM_MULTI kann im gegebenen Kontext keine Ergebnismenge zurückgeben" + ukr "COM_MULTI не може повернути результати у цьому контекÑті" +ER_BAD_COMMAND_IN_MULTI + eng "Command '%s' is not allowed for COM_MULTI" + ukr "Команда '%s' не дозволена Ð´Ð»Ñ COM_MULTI" +ER_WITH_COL_WRONG_LIST + eng "WITH column list and SELECT field list have different column counts" +ER_DUP_QUERY_NAME + eng "Duplicate query name in WITH clause" +ER_WRONG_ORDER_IN_WITH_CLAUSE + eng "The definition of the table '%s' refers to the table '%s' defined later in a non-recursive WITH clause" +ER_RECURSIVE_QUERY_IN_WITH_CLAUSE + eng "Recursive queries in WITH clause are not supported yet" ER_WRONG_WINDOW_SPEC_NAME eng "Window specification with name '%s' is not defined" ER_DUP_WINDOW_NAME diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index 4490aae6b62..bbe714fc5b4 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -100,14 +100,13 @@ extern "C" sig_handler handle_fatal_signal(int sig) "or misconfigured. This error can also be caused by malfunctioning hardware.\n\n"); my_safe_printf_stderr("%s", - "To report this bug, see http://kb.askmonty.org/en/reporting-bugs\n\n"); + "To report this bug, see https://mariadb.com/kb/en/reporting-bugs\n\n"); my_safe_printf_stderr("%s", "We will try our best to scrape up some info that will hopefully help\n" "diagnose the problem, but since we have already crashed, \n" "something is definitely wrong and this may fail.\n\n"); - set_server_version(); my_safe_printf_stderr("Server version: %s\n", server_version); if (dflt_key_cache) @@ -227,7 +226,7 @@ extern "C" sig_handler handle_fatal_signal(int sig) if (calling_initgroups) { my_safe_printf_stderr("%s", "\n" - "This crash occured while the server was calling initgroups(). This is\n" + "This crash occurred while the server was calling initgroups(). This is\n" "often due to the use of a mysqld that is statically linked against \n" "glibc and configured to use LDAP in /etc/nsswitch.conf.\n" "You will need to either upgrade to a version of glibc that does not\n" diff --git a/sql/slave.cc b/sql/slave.cc index 8512fc229c1..93506bc2ccd 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -117,7 +117,7 @@ static const char *reconnect_messages[SLAVE_RECON_ACT_MAX][SLAVE_RECON_MSG_MAX]= { { "Waiting to reconnect after a failed registration on master", - "Slave I/O thread killed while waitnig to reconnect after a failed \ + "Slave I/O thread killed while waiting to reconnect after a failed \ registration on master", "Reconnecting after a failed registration on master", "failed registering on master, reconnecting to try again, \ @@ -163,7 +163,6 @@ static int queue_event(Master_info* mi,const char* buf,ulong event_len); static int terminate_slave_thread(THD *, mysql_mutex_t *, mysql_cond_t *, volatile uint *, bool); static bool check_io_slave_killed(Master_info *mi, const char *info); -static bool send_show_master_info_header(THD *, bool, size_t); static bool send_show_master_info_data(THD *, Master_info *, bool, String *); /* Function to set the slave's max_allowed_packet based on the value @@ -295,9 +294,7 @@ handle_slave_init(void *arg __attribute__((unused))) my_thread_init(); thd= new THD; thd->thread_stack= (char*) &thd; /* Set approximate stack start */ - mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id= thread_id++; - mysql_mutex_unlock(&LOCK_thread_count); + thd->thread_id= next_thread_id(); thd->system_thread = SYSTEM_THREAD_SLAVE_INIT; thread_safe_increment32(&service_thread_count); thd->store_globals(); @@ -311,19 +308,17 @@ handle_slave_init(void *arg __attribute__((unused))) rpl_gtid_slave_state_table_name.str, thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message()); - - mysql_mutex_lock(&LOCK_thread_count); delete thd; - mysql_mutex_unlock(&LOCK_thread_count); thread_safe_decrement32(&service_thread_count); - signal_thd_deleted(); - my_thread_end(); - mysql_mutex_lock(&LOCK_slave_init); + /* Signal run_slave_init_thread() that we are done */ + + mysql_mutex_lock(&LOCK_start_thread); slave_init_thread_running= false; - mysql_cond_broadcast(&COND_slave_init); - mysql_mutex_unlock(&LOCK_slave_init); + mysql_cond_broadcast(&COND_start_thread); + mysql_mutex_unlock(&LOCK_start_thread); + my_thread_end(); return 0; } @@ -348,11 +343,10 @@ run_slave_init_thread() return 1; } - mysql_mutex_lock(&LOCK_slave_init); + mysql_mutex_lock(&LOCK_start_thread); while (slave_init_thread_running) - mysql_cond_wait(&COND_slave_init, &LOCK_slave_init); - mysql_mutex_unlock(&LOCK_slave_init); - + mysql_cond_wait(&COND_start_thread, &LOCK_start_thread); + mysql_mutex_unlock(&LOCK_start_thread); return 0; } @@ -2497,10 +2491,13 @@ bool show_master_info(THD *thd, Master_info *mi, bool full) { DBUG_ENTER("show_master_info"); String gtid_pos; + List<Item> field_list; if (full && rpl_global_gtid_slave_state->tostring(>id_pos, NULL, 0)) DBUG_RETURN(TRUE); - if (send_show_master_info_header(thd, full, gtid_pos.length())) + show_master_info_get_fields(thd, &field_list, full, gtid_pos.length()); + if (thd->protocol->send_result_set_metadata(&field_list, + Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); if (send_show_master_info_data(thd, mi, full, >id_pos)) DBUG_RETURN(TRUE); @@ -2508,226 +2505,222 @@ bool show_master_info(THD *thd, Master_info *mi, bool full) DBUG_RETURN(FALSE); } -static bool send_show_master_info_header(THD *thd, bool full, - size_t gtid_pos_length) +void show_master_info_get_fields(THD *thd, List<Item> *field_list, + bool full, size_t gtid_pos_length) { - List<Item> field_list; - Protocol *protocol= thd->protocol; Master_info *mi; MEM_ROOT *mem_root= thd->mem_root; - DBUG_ENTER("show_master_info_header"); + DBUG_ENTER("show_master_info_get_fields"); if (full) { - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Connection_name", - MAX_CONNECTION_NAME), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Slave_SQL_State", 30), - thd->mem_root); - } - - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Slave_IO_State", 30), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Master_Host", sizeof(mi->host)), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Master_User", sizeof(mi->user)), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Master_Port", 7, MYSQL_TYPE_LONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Connect_Retry", 10, - MYSQL_TYPE_LONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Master_Log_File", FN_REFLEN), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Read_Master_Log_Pos", 10, - MYSQL_TYPE_LONGLONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Relay_Log_File", FN_REFLEN), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Relay_Log_Pos", 10, - MYSQL_TYPE_LONGLONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Relay_Master_Log_File", - FN_REFLEN), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Slave_IO_Running", 3), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Slave_SQL_Running", 3), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Replicate_Do_DB", 20), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Replicate_Ignore_DB", 20), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Replicate_Do_Table", 20), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Replicate_Ignore_Table", 23), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Replicate_Wild_Do_Table", 24), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Replicate_Wild_Ignore_Table", - 28), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Last_Errno", 4, MYSQL_TYPE_LONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Last_Error", 20), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Skip_Counter", 10, - MYSQL_TYPE_LONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Exec_Master_Log_Pos", 10, - MYSQL_TYPE_LONGLONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Relay_Log_Space", 10, - MYSQL_TYPE_LONGLONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Until_Condition", 6), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Until_Log_File", FN_REFLEN), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Until_Log_Pos", 10, - MYSQL_TYPE_LONGLONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Master_SSL_Allowed", 7), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Master_SSL_CA_File", - sizeof(mi->ssl_ca)), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Master_SSL_CA_Path", - sizeof(mi->ssl_capath)), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Master_SSL_Cert", - sizeof(mi->ssl_cert)), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Master_SSL_Cipher", - sizeof(mi->ssl_cipher)), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Master_SSL_Key", - sizeof(mi->ssl_key)), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Seconds_Behind_Master", 10, - MYSQL_TYPE_LONGLONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Master_SSL_Verify_Server_Cert", - 3), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Last_IO_Errno", 4, - MYSQL_TYPE_LONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Last_IO_Error", 20), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Last_SQL_Errno", 4, - MYSQL_TYPE_LONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Last_SQL_Error", 20), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Replicate_Ignore_Server_Ids", - FN_REFLEN), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Master_Server_Id", sizeof(ulong), - MYSQL_TYPE_LONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Master_SSL_Crl", - sizeof(mi->ssl_crl)), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Master_SSL_Crlpath", - sizeof(mi->ssl_crlpath)), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Using_Gtid", - sizeof("Current_Pos")-1), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Gtid_IO_Pos", 30), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Replicate_Do_Domain_Ids", - FN_REFLEN), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Replicate_Ignore_Domain_Ids", - FN_REFLEN), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Parallel_Mode", - sizeof("conservative")-1), - thd->mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Connection_name", + MAX_CONNECTION_NAME), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Slave_SQL_State", 30), + mem_root); + } + + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Slave_IO_State", 30), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Master_Host", sizeof(mi->host)), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Master_User", sizeof(mi->user)), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Master_Port", 7, MYSQL_TYPE_LONG), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Connect_Retry", 10, + MYSQL_TYPE_LONG), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Master_Log_File", FN_REFLEN), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Read_Master_Log_Pos", 10, + MYSQL_TYPE_LONGLONG), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Relay_Log_File", FN_REFLEN), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Relay_Log_Pos", 10, + MYSQL_TYPE_LONGLONG), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Relay_Master_Log_File", + FN_REFLEN), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Slave_IO_Running", 3), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Slave_SQL_Running", 3), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Replicate_Do_DB", 20), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Replicate_Ignore_DB", 20), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Replicate_Do_Table", 20), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Replicate_Ignore_Table", 23), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Replicate_Wild_Do_Table", 24), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Replicate_Wild_Ignore_Table", + 28), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Last_Errno", 4, MYSQL_TYPE_LONG), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Last_Error", 20), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Skip_Counter", 10, + MYSQL_TYPE_LONG), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Exec_Master_Log_Pos", 10, + MYSQL_TYPE_LONGLONG), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Relay_Log_Space", 10, + MYSQL_TYPE_LONGLONG), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Until_Condition", 6), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Until_Log_File", FN_REFLEN), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Until_Log_Pos", 10, + MYSQL_TYPE_LONGLONG), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Master_SSL_Allowed", 7), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Master_SSL_CA_File", + sizeof(mi->ssl_ca)), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Master_SSL_CA_Path", + sizeof(mi->ssl_capath)), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Master_SSL_Cert", + sizeof(mi->ssl_cert)), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Master_SSL_Cipher", + sizeof(mi->ssl_cipher)), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Master_SSL_Key", + sizeof(mi->ssl_key)), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Seconds_Behind_Master", 10, + MYSQL_TYPE_LONGLONG), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Master_SSL_Verify_Server_Cert", + 3), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Last_IO_Errno", 4, + MYSQL_TYPE_LONG), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Last_IO_Error", 20), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Last_SQL_Errno", 4, + MYSQL_TYPE_LONG), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Last_SQL_Error", 20), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Replicate_Ignore_Server_Ids", + FN_REFLEN), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Master_Server_Id", sizeof(ulong), + MYSQL_TYPE_LONG), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Master_SSL_Crl", + sizeof(mi->ssl_crl)), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Master_SSL_Crlpath", + sizeof(mi->ssl_crlpath)), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Using_Gtid", + sizeof("Current_Pos")-1), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Gtid_IO_Pos", 30), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Replicate_Do_Domain_Ids", + FN_REFLEN), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Replicate_Ignore_Domain_Ids", + FN_REFLEN), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Parallel_Mode", + sizeof("conservative")-1), + mem_root); if (full) { - field_list.push_back(new (mem_root) - Item_return_int(thd, "Retried_transactions", 10, - MYSQL_TYPE_LONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Max_relay_log_size", 10, - MYSQL_TYPE_LONGLONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Executed_log_entries", 10, - MYSQL_TYPE_LONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Slave_received_heartbeats", 10, - MYSQL_TYPE_LONG), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_float(thd, "Slave_heartbeat_period", 0.0, 3, 10), - thd->mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Gtid_Slave_Pos", - gtid_pos_length), - thd->mem_root); - } - - if (protocol->send_result_set_metadata(&field_list, - Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) - DBUG_RETURN(TRUE); - DBUG_RETURN(FALSE); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Retried_transactions", 10, + MYSQL_TYPE_LONG), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Max_relay_log_size", 10, + MYSQL_TYPE_LONGLONG), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Executed_log_entries", 10, + MYSQL_TYPE_LONG), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Slave_received_heartbeats", 10, + MYSQL_TYPE_LONG), + mem_root); + field_list->push_back(new (mem_root) + Item_float(thd, "Slave_heartbeat_period", 0.0, 3, 10), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Gtid_Slave_Pos", + gtid_pos_length), + mem_root); + } + DBUG_VOID_RETURN; } +/* Text for Slave_IO_Running */ +static const char *slave_running[]= { "No", "Connecting", "Preparing", "Yes" }; static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full, String *gtid_pos) @@ -2780,9 +2773,7 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full, &my_charset_bin); protocol->store((ulonglong) mi->rli.group_relay_log_pos); protocol->store(mi->rli.group_master_log_name, &my_charset_bin); - protocol->store(mi->slave_running == MYSQL_SLAVE_RUN_CONNECT ? - "Yes" : (mi->slave_running == MYSQL_SLAVE_RUN_NOT_CONNECT ? - "Connecting" : "No"), &my_charset_bin); + protocol->store(slave_running[mi->slave_running], &my_charset_bin); protocol->store(mi->rli.slave_running ? "Yes":"No", &my_charset_bin); protocol->store(rpl_filter->get_do_db()); protocol->store(rpl_filter->get_ignore_db()); @@ -2825,7 +2816,7 @@ static bool send_show_master_info_data(THD *thd, Master_info *mi, bool full, Seconds_Behind_Master: if SQL thread is running and I/O thread is connected, we can compute it otherwise show NULL (i.e. unknown). */ - if ((mi->slave_running == MYSQL_SLAVE_RUN_CONNECT) && + if ((mi->slave_running == MYSQL_SLAVE_RUN_READING) && mi->rli.slave_running) { long time_diff; @@ -2962,6 +2953,7 @@ bool show_all_master_info(THD* thd) uint i, elements; String gtid_pos; Master_info **tmp; + List<Item> field_list; DBUG_ENTER("show_master_info"); mysql_mutex_assert_owner(&LOCK_active_mi); @@ -2972,7 +2964,9 @@ bool show_all_master_info(THD* thd) DBUG_RETURN(TRUE); } - if (send_show_master_info_header(thd, 1, gtid_pos.length())) + show_master_info_get_fields(thd, &field_list, 1, gtid_pos.length()); + if (thd->protocol->send_result_set_metadata(&field_list, + Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); if (!master_info_index || @@ -3077,9 +3071,7 @@ static int init_slave_thread(THD* thd, Master_info *mi, thd->variables.log_slow_filter= global_system_variables.log_slow_filter; set_slave_thread_options(thd); thd->client_capabilities = CLIENT_LOCAL_FILES; - mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - mysql_mutex_unlock(&LOCK_thread_count); + thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id(); if (thd_type == SLAVE_THD_SQL) THD_STAGE_INFO(thd, stage_waiting_for_the_next_event_in_relay_log); @@ -3971,9 +3963,7 @@ pthread_handler_t handle_slave_io(void *arg) goto err_during_init; } thd->system_thread_info.rpl_io_info= &io_info; - mysql_mutex_lock(&LOCK_thread_count); - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); + add_to_active_threads(thd); mi->slave_running = MYSQL_SLAVE_RUN_NOT_CONNECT; mi->abort_slave = 0; mysql_mutex_unlock(&mi->run_lock); @@ -4128,16 +4118,16 @@ connected: if (request_dump(thd, mysql, mi, &suppress_warnings)) { sql_print_error("Failed on request_dump()"); - if (check_io_slave_killed(mi, "Slave I/O thread killed while \ -requesting master dump") || - try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings, - reconnect_messages[SLAVE_RECON_ACT_DUMP])) + if (check_io_slave_killed(mi, NullS) || + try_to_reconnect(thd, mysql, mi, &retry_count, suppress_warnings, + reconnect_messages[SLAVE_RECON_ACT_DUMP])) goto err; goto connected; } const char *event_buf; + mi->slave_running= MYSQL_SLAVE_RUN_READING; DBUG_ASSERT(mi->last_error().number == 0); while (!io_slave_killed(mi)) { @@ -4150,8 +4140,7 @@ requesting master dump") || */ THD_STAGE_INFO(thd, stage_waiting_for_master_to_send_event); event_len= read_event(mysql, mi, &suppress_warnings); - if (check_io_slave_killed(mi, "Slave I/O thread killed while \ -reading event")) + if (check_io_slave_killed(mi, NullS)) goto err; if (event_len == packet_error) @@ -4297,6 +4286,7 @@ err: flush_master_info(mi, TRUE, TRUE); THD_STAGE_INFO(thd, stage_waiting_for_slave_mutex_on_exit); thd->add_status_to_global(); + unlink_not_visible_thd(thd); mysql_mutex_lock(&mi->run_lock); err_during_init: @@ -4356,7 +4346,8 @@ int check_temp_dir(char* tmp_file) size_t tmp_dir_size; DBUG_ENTER("check_temp_dir"); - mysql_mutex_lock(&LOCK_thread_count); + /* This look is safe to use as this function is only called once */ + mysql_mutex_lock(&LOCK_start_thread); if (check_temp_dir_run) { result= check_temp_dir_result; @@ -4395,7 +4386,7 @@ int check_temp_dir(char* tmp_file) end: check_temp_dir_result= result; - mysql_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_start_thread); DBUG_RETURN(result); } @@ -4573,9 +4564,7 @@ pthread_handler_t handle_slave_sql(void *arg) applied. In all other cases it must be FALSE. */ thd->variables.binlog_annotate_row_events= 0; - mysql_mutex_lock(&LOCK_thread_count); - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); + add_to_active_threads(thd); /* We are going to set slave_running to 1. Assuming slave I/O thread is alive and connected, this is going to make Seconds_Behind_Master be 0 @@ -4607,15 +4596,6 @@ pthread_handler_t handle_slave_sql(void *arg) serial_rgi->gtid_sub_id= 0; serial_rgi->gtid_pending= false; - if (mi->using_gtid != Master_info::USE_GTID_NO) - { - /* - We initialize the relay log state from the know starting position. - It will then be updated as required by GTID and GTID_LIST events found - while applying events read from relay logs. - */ - rli->relay_log_state.load(rpl_global_gtid_slave_state); - } rli->gtid_skip_flag = GTID_SKIP_NOT; if (init_relay_log_pos(rli, rli->group_relay_log_name, @@ -4886,13 +4866,16 @@ pthread_handler_t handle_slave_sql(void *arg) } strmake_buf(rli->group_relay_log_name, ir->name); rli->group_relay_log_pos= BIN_LOG_HEADER_SIZE; + rli->relay_log_state.load(ir->relay_log_state, ir->relay_log_state_count); } } } } THD_STAGE_INFO(thd, stage_waiting_for_slave_mutex_on_exit); thd->add_status_to_global(); + unlink_not_visible_thd(thd); mysql_mutex_lock(&rli->run_lock); + err_during_init: /* We need data_lock, at least to wake up any waiting master_pos_wait() */ mysql_mutex_lock(&rli->data_lock); @@ -4916,12 +4899,8 @@ err_during_init: to avoid unneeded position re-init */ thd->temporary_tables = 0; // remove tempation from destructor to close them - THD_CHECK_SENTRY(thd); rli->sql_driver_thd= 0; - mysql_mutex_lock(&LOCK_thread_count); thd->rgi_fake= thd->rgi_slave= NULL; - delete serial_rgi; - mysql_mutex_unlock(&LOCK_thread_count); #ifdef WITH_WSREP /* @@ -4950,10 +4929,11 @@ err_during_init: #endif /* WITH_WSREP */ /* - Note: the order of the broadcast and unlock calls below (first broadcast, then unlock) - is important. Otherwise a killer_thread can execute between the calls and - delete the mi structure leading to a crash! (see BUG#25306 for details) - */ + Note: the order of the broadcast and unlock calls below (first + broadcast, then unlock) is important. Otherwise a killer_thread can + execute between the calls and delete the mi structure leading to a + crash! (see BUG#25306 for details) + */ mysql_cond_broadcast(&rli->stop_cond); DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5);); mysql_mutex_unlock(&rli->run_lock); // tell the world we are done @@ -4965,13 +4945,18 @@ err_during_init: */ mysql_mutex_lock(&LOCK_active_mi); if (opt_slave_parallel_threads > 0 && + master_info_index &&// master_info_index is set to NULL on server shutdown !master_info_index->any_slave_sql_running()) rpl_parallel_inactivate_pool(&global_rpl_thread_pool); mysql_mutex_unlock(&LOCK_active_mi); + /* TODO: Check if this lock is needed */ mysql_mutex_lock(&LOCK_thread_count); - delete thd; + delete serial_rgi; mysql_mutex_unlock(&LOCK_thread_count); + + THD_CHECK_SENTRY(thd); + delete thd; thread_safe_decrement32(&service_thread_count); signal_thd_deleted(); diff --git a/sql/slave.h b/sql/slave.h index a519229fac1..ca89064d773 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -135,11 +135,11 @@ extern const char *relay_log_index; extern const char *relay_log_basename; /* - 3 possible values for Master_info::slave_running and + 4 possible values for Master_info::slave_running and Relay_log_info::slave_running. - The values 0,1,2 are very important: to keep the diff small, I didn't - substitute places where we use 0/1 with the newly defined symbols. So don't change - these values. + The values 0,1,2,3 are very important: to keep the diff small, I didn't + substitute places where we use 0/1 with the newly defined symbols. + So don't change these values. The same way, code is assuming that in Relay_log_info we use only values 0/1. I started with using an enum, but @@ -148,6 +148,7 @@ extern const char *relay_log_basename; #define MYSQL_SLAVE_NOT_RUN 0 #define MYSQL_SLAVE_RUN_NOT_CONNECT 1 #define MYSQL_SLAVE_RUN_CONNECT 2 +#define MYSQL_SLAVE_RUN_READING 3 #define RPL_LOG_NAME (rli->group_master_log_name[0] ? rli->group_master_log_name :\ "FIRST") @@ -206,8 +207,11 @@ int mysql_table_dump(THD* thd, const char* db, int fetch_master_table(THD* thd, const char* db_name, const char* table_name, Master_info* mi, MYSQL* mysql, bool overwrite); +void show_master_info_get_fields(THD *thd, List<Item> *field_list, + bool full, size_t gtid_pos_length); bool show_master_info(THD* thd, Master_info* mi, bool full); bool show_all_master_info(THD* thd); +void show_binlog_info_get_fields(THD *thd, List<Item> *field_list); bool show_binlog_info(THD* thd); bool rpl_master_has_bug(const Relay_log_info *rli, uint bug_id, bool report, bool (*pred)(const void *), const void *param); diff --git a/sql/sp.cc b/sql/sp.cc index 6ec59143720..a518b520786 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -34,6 +34,10 @@ #include <my_user.h> +/* Used in error handling only */ +#define SP_TYPE_STRING(type) \ + (type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE") + static int db_load_routine(THD *thd, stored_procedure_type type, sp_name *name, sp_head **sphp, @@ -1007,15 +1011,16 @@ sp_drop_routine_internal(THD *thd, stored_procedure_type type, followed by an implicit grant (sp_grant_privileges()) and this subsequent call opens and closes mysql.procs_priv. - @return Error code. SP_OK is returned on success. Other - SP_ constants are used to indicate about errors. + @return Error status. + @retval FALSE on success + @retval TRUE on error */ -int +bool sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp) { LEX *lex= thd->lex; - int ret; + bool ret= TRUE; TABLE *table; char definer_buf[USER_HOST_BUFF_SIZE]; LEX_STRING definer; @@ -1040,7 +1045,22 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp) /* Grab an exclusive MDL lock. */ if (lock_object_name(thd, mdl_type, sp->m_db.str, sp->m_name.str)) - DBUG_RETURN(SP_OPEN_TABLE_FAILED); + { + my_error(ER_BAD_DB_ERROR, MYF(0), sp->m_db.str); + DBUG_RETURN(TRUE); + } + + /* + Check that a database directory with this name + exists. Design note: This won't work on virtual databases + like information_schema. + */ + if (check_db_dir_existence(sp->m_db.str)) + { + my_error(ER_BAD_DB_ERROR, MYF(0), sp->m_db.str); + DBUG_RETURN(TRUE); + } + /* Reset sql_mode during data dictionary operations. */ thd->variables.sql_mode= 0; @@ -1049,7 +1069,10 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp) thd->count_cuted_fields= CHECK_FIELD_WARN; if (!(table= open_proc_table_for_update(thd))) - ret= SP_OPEN_TABLE_FAILED; + { + my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(type),sp->m_name.str); + goto done; + } else { /* Checking if the routine already exists */ @@ -1065,11 +1088,10 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp) push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_SP_ALREADY_EXISTS, ER_THD(thd, ER_SP_ALREADY_EXISTS), - type == TYPE_ENUM_FUNCTION ? - "FUNCTION" : "PROCEDURE", + SP_TYPE_STRING(type), lex->spname->m_name.str); - ret= SP_OK; + ret= FALSE; // Setting retstr as it is used for logging. if (sp->m_type == TYPE_ENUM_FUNCTION) @@ -1078,7 +1100,8 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp) } else { - ret= SP_WRITE_ROW_FAILED; + my_error(ER_SP_ALREADY_EXISTS, MYF(0), + SP_TYPE_STRING(type), sp->m_name.str); goto done; } } @@ -1090,7 +1113,8 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp) if (table->s->fields < MYSQL_PROC_FIELD_COUNT) { - ret= SP_GET_FIELD_FAILED; + my_error(ER_SP_STORE_FAILED, MYF(0), + SP_TYPE_STRING(type), sp->m_name.str); goto done; } @@ -1099,12 +1123,12 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp) sp->m_name.str+sp->m_name.length) > table->field[MYSQL_PROC_FIELD_NAME]->char_length()) { - ret= SP_BAD_IDENTIFIER; + my_error(ER_TOO_LONG_IDENT, MYF(0), sp->m_name.str); goto done; } if (sp->m_body.length > table->field[MYSQL_PROC_FIELD_BODY]->field_length) { - ret= SP_BODY_TOO_LONG; + my_error(ER_TOO_LONG_BODY, MYF(0), sp->m_name.str); goto done; } @@ -1193,17 +1217,13 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp) if (access == SP_CONTAINS_SQL || access == SP_MODIFIES_SQL_DATA) { - my_message(ER_BINLOG_UNSAFE_ROUTINE, - ER_THD(thd, ER_BINLOG_UNSAFE_ROUTINE), MYF(0)); - ret= SP_INTERNAL_ERROR; + my_error(ER_BINLOG_UNSAFE_ROUTINE, MYF(0)); goto done; } } if (!(thd->security_ctx->master_access & SUPER_ACL)) { - my_message(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER, - ER_THD(thd, ER_BINLOG_CREATE_ROUTINE_NEED_SUPER), MYF(0)); - ret= SP_INTERNAL_ERROR; + my_error(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER,MYF(0)); goto done; } } @@ -1234,22 +1254,24 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp) if (store_failed) { - ret= SP_FLD_STORE_FAILED; + my_error(ER_CANT_CREATE_SROUTINE, MYF(0), sp->m_name.str); goto done; } - ret= SP_OK; if (table->file->ha_write_row(table->record[0])) - ret= SP_WRITE_ROW_FAILED; + { + my_error(ER_SP_ALREADY_EXISTS, MYF(0), + SP_TYPE_STRING(type), sp->m_name.str); + goto done; + } /* Make change permanent and avoid 'table is marked as crashed' errors */ table->file->extra(HA_EXTRA_FLUSH); - if (ret == SP_OK) - sp_cache_invalidate(); + sp_cache_invalidate(); } log: - if (ret == SP_OK && mysql_bin_log.is_open()) + if (mysql_bin_log.is_open()) { thd->clear_error(); @@ -1268,7 +1290,7 @@ log: &(thd->lex->definer->host), saved_mode)) { - ret= SP_INTERNAL_ERROR; + my_error(ER_OUT_OF_RESOURCES, MYF(0)); goto done; } /* restore sql_mode when binloging */ @@ -1277,9 +1299,13 @@ log: if (thd->binlog_query(THD::STMT_QUERY_TYPE, log_query.ptr(), log_query.length(), FALSE, FALSE, FALSE, 0)) - ret= SP_INTERNAL_ERROR; + { + my_error(ER_ERROR_ON_WRITE, MYF(MY_WME), "binary log", -1); + goto done; + } thd->variables.sql_mode= 0; } + ret= FALSE; done: thd->count_cuted_fields= saved_count_cuted_fields; @@ -126,7 +126,7 @@ sp_exist_routines(THD *thd, TABLE_LIST *procs, bool is_proc); bool sp_show_create_routine(THD *thd, stored_procedure_type type, sp_name *name); -int +bool sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp); int diff --git a/sql/sp_head.cc b/sql/sp_head.cc index ce4ec09bede..d58b51afc5e 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -216,6 +216,7 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_SHOW_CREATE_PROC: case SQLCOM_SHOW_CREATE_EVENT: case SQLCOM_SHOW_CREATE_TRIGGER: + case SQLCOM_SHOW_CREATE_USER: case SQLCOM_SHOW_DATABASES: case SQLCOM_SHOW_ERRORS: case SQLCOM_SHOW_EXPLAIN: @@ -283,6 +284,7 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_CREATE_USER: case SQLCOM_CREATE_ROLE: case SQLCOM_ALTER_TABLE: + case SQLCOM_ALTER_USER: case SQLCOM_GRANT: case SQLCOM_GRANT_ROLE: case SQLCOM_REVOKE: @@ -2534,6 +2536,69 @@ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access) /** + Collect metadata for SHOW CREATE statement for stored routines. + + @param thd Thread context. + @param type Stored routine type + @param type Stored routine type + (TYPE_ENUM_PROCEDURE or TYPE_ENUM_FUNCTION) + + @return Error status. + @retval FALSE on success + @retval TRUE on error +*/ + +void +sp_head::show_create_routine_get_fields(THD *thd, int type, List<Item> *fields) +{ + const char *col1_caption= type == TYPE_ENUM_PROCEDURE ? + "Procedure" : "Function"; + + const char *col3_caption= type == TYPE_ENUM_PROCEDURE ? + "Create Procedure" : "Create Function"; + + MEM_ROOT *mem_root= thd->mem_root; + + /* Send header. */ + + fields->push_back(new (mem_root) + Item_empty_string(thd, col1_caption, NAME_CHAR_LEN), + mem_root); + fields->push_back(new (mem_root) + Item_empty_string(thd, "sql_mode", 256), + mem_root); + + { + /* + NOTE: SQL statement field must be not less than 1024 in order not to + confuse old clients. + */ + + Item_empty_string *stmt_fld= + new (mem_root) Item_empty_string(thd, col3_caption, 1024); + stmt_fld->maybe_null= TRUE; + + fields->push_back(stmt_fld, mem_root); + } + + fields->push_back(new (mem_root) + Item_empty_string(thd, "character_set_client", + MY_CS_NAME_SIZE), + mem_root); + + fields->push_back(new (mem_root) + Item_empty_string(thd, "collation_connection", + MY_CS_NAME_SIZE), + mem_root); + + fields->push_back(new (mem_root) + Item_empty_string(thd, "Database Collation", + MY_CS_NAME_SIZE), + mem_root); +} + + +/** Implement SHOW CREATE statement for stored routines. @param thd Thread context. @@ -3211,7 +3276,8 @@ sp_instr_set::print(String *str) } str->qs_append(m_offset); str->qs_append(' '); - m_value->print(str, QT_ORDINARY); + m_value->print(str, enum_query_type(QT_ORDINARY | + QT_ITEM_ORIGINAL_FUNC_NULLIF)); } @@ -3243,9 +3309,11 @@ void sp_instr_set_trigger_field::print(String *str) { str->append(STRING_WITH_LEN("set_trigger_field ")); - trigger_field->print(str, QT_ORDINARY); + trigger_field->print(str, enum_query_type(QT_ORDINARY | + QT_ITEM_ORIGINAL_FUNC_NULLIF)); str->append(STRING_WITH_LEN(":=")); - value->print(str, QT_ORDINARY); + value->print(str, enum_query_type(QT_ORDINARY | + QT_ITEM_ORIGINAL_FUNC_NULLIF)); } /* @@ -3371,7 +3439,8 @@ sp_instr_jump_if_not::print(String *str) str->qs_append('('); str->qs_append(m_cont_dest); str->qs_append(STRING_WITH_LEN(") ")); - m_expr->print(str, QT_ORDINARY); + m_expr->print(str, enum_query_type(QT_ORDINARY | + QT_ITEM_ORIGINAL_FUNC_NULLIF)); } @@ -3467,7 +3536,8 @@ sp_instr_freturn::print(String *str) str->qs_append(STRING_WITH_LEN("freturn ")); str->qs_append((uint)m_type); str->qs_append(' '); - m_value->print(str, QT_ORDINARY); + m_value->print(str, enum_query_type(QT_ORDINARY | + QT_ITEM_ORIGINAL_FUNC_NULLIF)); } /* @@ -3939,7 +4009,8 @@ sp_instr_set_case_expr::print(String *str) str->qs_append(STRING_WITH_LEN(") ")); str->qs_append(m_case_expr_id); str->qs_append(' '); - m_case_expr->print(str, QT_ORDINARY); + m_case_expr->print(str, enum_query_type(QT_ORDINARY | + QT_ITEM_ORIGINAL_FUNC_NULLIF)); } uint diff --git a/sql/sp_head.h b/sql/sp_head.h index 4e761c31d5b..65aad1dd5a1 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -337,6 +337,9 @@ public: bool execute_procedure(THD *thd, List<Item> *args); + static void + show_create_routine_get_fields(THD *thd, int type, List<Item> *fields); + bool show_create_routine(THD *thd, int type); @@ -604,7 +607,7 @@ public: instruction for CONTINUE error handlers. @retval 0 on success, - @retval other if some error occured + @retval other if some error occurred */ virtual int execute(THD *thd, uint *nextp) = 0; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 2bcd351ae32..241f19c75a3 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -634,9 +634,6 @@ bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, char *username, char *hostname, char *rolename, bool with_admin_option) { - if (!this) - return true; - size_t uname_l = safe_strlen(username); size_t hname_l = safe_strlen(hostname); size_t rname_l = safe_strlen(rolename); @@ -874,6 +871,17 @@ static void free_acl_role(ACL_ROLE *role) delete_dynamic(&(role->parent_grantee)); } +static my_bool check_if_exists(THD *, plugin_ref, void *) +{ + return TRUE; +} + +static bool has_validation_plugins() +{ + return plugin_foreach(NULL, check_if_exists, + MariaDB_PASSWORD_VALIDATION_PLUGIN, NULL); +} + struct validation_data { LEX_STRING *user, *password; }; static my_bool do_validate(THD *, plugin_ref plugin, void *arg) @@ -885,22 +893,27 @@ static my_bool do_validate(THD *, plugin_ref plugin, void *arg) } -static bool validate_password(LEX_STRING *user, LEX_STRING *password) +static bool validate_password(LEX_USER *user) { - struct validation_data data= { user, password }; - return plugin_foreach(NULL, do_validate, - MariaDB_PASSWORD_VALIDATION_PLUGIN, &data); -} - -static my_bool check_if_exists(THD *, plugin_ref, void *) -{ - return TRUE; -} - -static bool has_validation_plugins() -{ - return plugin_foreach(NULL, check_if_exists, - MariaDB_PASSWORD_VALIDATION_PLUGIN, NULL); + if (user->pwtext.length || !user->pwhash.length) + { + struct validation_data data= { &user->user, &user->pwtext }; + if (plugin_foreach(NULL, do_validate, + MariaDB_PASSWORD_VALIDATION_PLUGIN, &data)) + { + my_error(ER_NOT_VALID_PASSWORD, MYF(0)); + return true; + } + } + else + { + if (strict_password_validation && has_validation_plugins()) + { + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--strict-password-validation"); + return true; + } + } + return false; } /** @@ -984,16 +997,17 @@ static bool fix_user_plugin_ptr(ACL_USER *user) - if user->plugin is specified, user->auth is the plugin auth data. - if user->plugin is mysql_native_password or mysql_old_password, - user->auth if the password hash, and LEX_USER is transformed + user->auth is the password hash, and LEX_USER is transformed to match the next case (that is, user->plugin is cleared). - if user->plugin is NOT specified, built-in auth is assumed, that is mysql_native_password or mysql_old_password. In that case, - user->auth is the password hash. And user->password is the original - plain-text password. Either one can be set or even both. + user->pwhash is the password hash. And user->pwtext is the original + plain-text password. Either one can be set or both. Upon exiting this function: - - user->password is the password hash, as the mysql.user.password column + - user->pwtext is left untouched + - user->pwhash is the password hash, as the mysql.user.password column - user->plugin is the plugin name, as the mysql.user.plugin column - user->auth is the plugin auth data, as the mysql.user.authentication_string column */ @@ -1001,6 +1015,9 @@ static bool fix_lex_user(THD *thd, LEX_USER *user) { size_t check_length; + DBUG_ASSERT(user->plugin.length || !user->auth.length); + DBUG_ASSERT(!(user->plugin.length && (user->pwtext.length || user->pwhash.length))); + if (my_strcasecmp(system_charset_info, user->plugin.str, native_password_plugin_name.str) == 0) check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; @@ -1011,36 +1028,26 @@ static bool fix_lex_user(THD *thd, LEX_USER *user) else if (user->plugin.length) return false; // nothing else to do - else - if (user->auth.length == SCRAMBLED_PASSWORD_CHAR_LENGTH_323) - check_length= 0; // length is valid, no need to re-check + else if (thd->variables.old_passwords == 1 || + user->pwhash.length == SCRAMBLED_PASSWORD_CHAR_LENGTH_323) + check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; else check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; - if (check_length && user->auth.length && user->auth.length != check_length) + if (user->plugin.length) { - my_error(ER_PASSWD_LENGTH, MYF(0), check_length); - return true; + user->pwhash= user->auth; + user->plugin= empty_lex_str; + user->auth= empty_lex_str; } - if (user->password.length || !user->auth.length) - { - if (validate_password(&user->user, &user->password)) - { - my_error(ER_NOT_VALID_PASSWORD, MYF(0)); - return true; - } - } - else + if (user->pwhash.length && user->pwhash.length != check_length) { - if (strict_password_validation && has_validation_plugins()) - { - my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--strict-password-validation"); - return true; - } + my_error(ER_PASSWD_LENGTH, MYF(0), check_length); + return true; } - if (user->password.length && !user->auth.length) + if (user->pwtext.length && !user->pwhash.length) { size_t scramble_length; void (*make_scramble)(char *, const char *, size_t); @@ -1059,14 +1066,11 @@ static bool fix_lex_user(THD *thd, LEX_USER *user) char *buff= (char *) thd->alloc(scramble_length + 1); if (buff == NULL) return true; - make_scramble(buff, user->password.str, user->password.length); - user->auth.str= buff; - user->auth.length= scramble_length; + make_scramble(buff, user->pwtext.str, user->pwtext.length); + user->pwhash.str= buff; + user->pwhash.length= scramble_length; } - user->password= user->auth.length ? user->auth : null_lex_str; - user->plugin= empty_lex_str; - user->auth= empty_lex_str; return false; } @@ -1202,7 +1206,8 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) (void) my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST), 20, 50, MYF(0)); if ((table= tables[HOST_TABLE].table)) // "host" table may not exist (e.g. in MySQL 5.6.7+) { - if (init_read_record(&read_record_info, thd, table, NULL, 1, 1, FALSE)) + if (init_read_record(&read_record_info, thd, table, NULL, NULL, + 1, 1, FALSE)) goto end; table->use_all_columns(); while (!(read_record_info.read_record(&read_record_info))) @@ -1257,7 +1262,7 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) freeze_size(&acl_hosts); if (init_read_record(&read_record_info, thd, table=tables[USER_TABLE].table, - NULL, 1, 1, FALSE)) + NULL, NULL, 1, 1, FALSE)) goto end; table->use_all_columns(); (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER), 50, 100, MYF(0)); @@ -1519,7 +1524,7 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) freeze_size(&acl_users); if (init_read_record(&read_record_info, thd, table=tables[DB_TABLE].table, - NULL, 1, 1, FALSE)) + NULL, NULL, 1, 1, FALSE)) goto end; table->use_all_columns(); (void) my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB), 50, 100, MYF(0)); @@ -1589,7 +1594,7 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) if ((table= tables[PROXIES_PRIV_TABLE].table)) { if (init_read_record(&read_record_info, thd, table, - NULL, 1, 1, FALSE)) + NULL, NULL, 1, 1, FALSE)) goto end; table->use_all_columns(); while (!(read_record_info.read_record(&read_record_info))) @@ -1618,7 +1623,8 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) if ((table= tables[ROLES_MAPPING_TABLE].table)) { - if (init_read_record(&read_record_info, thd, table, NULL, 1, 1, FALSE)) + if (init_read_record(&read_record_info, thd, table, NULL, NULL, 1, 1, + FALSE)) goto end; table->use_all_columns(); /* account for every role mapping */ @@ -2737,7 +2743,8 @@ bool check_change_password(THD *thd, LEX_USER *user) { LEX_USER *real_user= get_current_user(thd, user); - if (fix_and_copy_user(real_user, user, thd)) + if (fix_and_copy_user(real_user, user, thd) || + validate_password(real_user)) return true; *user= *real_user; @@ -2767,7 +2774,7 @@ bool change_password(THD *thd, LEX_USER *user) const CSET_STRING query_save __attribute__((unused)) = thd->query_string; DBUG_ENTER("change_password"); DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'", - user->host.str, user->user.str, user->password.str)); + user->host.str, user->user.str, user->pwhash.str)); DBUG_ASSERT(user->host.str != 0); // Ensured by parent /* @@ -2784,7 +2791,7 @@ bool change_password(THD *thd, LEX_USER *user) { query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'", safe_str(user->user.str), safe_str(user->host.str), - safe_str(user->password.str)); + safe_str(user->pwhash.str)); } if (WSREP(thd) && !IF_WSREP(thd->wsrep_applier, 0)) @@ -2812,10 +2819,10 @@ bool change_password(THD *thd, LEX_USER *user) if (acl_user->plugin.str == native_password_plugin_name.str || acl_user->plugin.str == old_password_plugin_name.str) { - acl_user->auth_string.str= strmake_root(&acl_memroot, user->password.str, user->password.length); - acl_user->auth_string.length= user->password.length; - set_user_salt(acl_user, user->password.str, user->password.length); - set_user_plugin(acl_user, user->password.length); + acl_user->auth_string.str= strmake_root(&acl_memroot, user->pwhash.str, user->pwhash.length); + acl_user->auth_string.length= user->pwhash.length; + set_user_salt(acl_user, user->pwhash.str, user->pwhash.length); + set_user_plugin(acl_user, user->pwhash.length); } else push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, @@ -2825,7 +2832,7 @@ bool change_password(THD *thd, LEX_USER *user) if (update_user_table(thd, tables[USER_TABLE].table, safe_str(acl_user->host.hostname), safe_str(acl_user->user.str), - user->password.str, user->password.length)) + user->pwhash.str, user->pwhash.length)) { mysql_mutex_unlock(&acl_cache->lock); /* purecov: deadcode */ goto end; @@ -3366,17 +3373,18 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo, mysql_mutex_assert_owner(&acl_cache->lock); - if (combo.password.str && combo.password.str[0]) + if (combo.pwhash.str && combo.pwhash.str[0]) { - if (combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH && - combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH_323) + if (combo.pwhash.length != SCRAMBLED_PASSWORD_CHAR_LENGTH && + combo.pwhash.length != SCRAMBLED_PASSWORD_CHAR_LENGTH_323) { + DBUG_ASSERT(0); my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH); DBUG_RETURN(-1); } } else - combo.password= empty_lex_str; + combo.pwhash= empty_lex_str; /* if the user table is not up to date, we can't handle role updates */ if (table->s->fields <= ROLE_ASSIGN_COLUMN_IDX && handle_as_role) @@ -3418,7 +3426,7 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo, see also test_if_create_new_users() */ - else if (!combo.password.length && !combo.plugin.length && no_auto_create) + else if (!combo.pwhash.length && !combo.plugin.length && no_auto_create) { my_error(ER_PASSWORD_NO_MATCH, MYF(0)); goto end; @@ -3450,6 +3458,10 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo, store_record(table,record[1]); // Save copy for update } + if (!old_row_exists || combo.pwtext.length || combo.pwhash.length) + if (validate_password(&combo)) + goto end; + /* Update table columns with new privileges */ Field **tmp_field; @@ -3465,8 +3477,8 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo, } rights= get_access(table, 3, &next_field); DBUG_PRINT("info",("table fields: %d",table->s->fields)); - if (combo.password.str[0]) - table->field[2]->store(combo.password.str, combo.password.length, system_charset_info); + if (combo.pwhash.str[0]) + table->field[2]->store(combo.pwhash.str, combo.pwhash.length, system_charset_info); if (table->s->fields >= 31) /* From 4.0.0 we have more fields */ { /* We write down SSL related ACL stuff */ @@ -3529,14 +3541,14 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo, table->field[next_field + 1]->set_notnull(); if (combo.plugin.str[0]) { - DBUG_ASSERT(combo.password.str[0] == 0); + DBUG_ASSERT(combo.pwhash.str[0] == 0); table->field[2]->reset(); table->field[next_field]->store(combo.plugin.str, combo.plugin.length, system_charset_info); table->field[next_field + 1]->store(combo.auth.str, combo.auth.length, system_charset_info); } - if (combo.password.str[0]) + if (combo.pwhash.str[0]) { DBUG_ASSERT(combo.plugin.str[0] == 0); table->field[next_field]->reset(); @@ -3605,7 +3617,7 @@ end: acl_update_role(combo.user.str, rights); else acl_update_user(combo.user.str, combo.host.str, - combo.password.str, combo.password.length, + combo.pwhash.str, combo.pwhash.length, lex->ssl_type, lex->ssl_cipher, lex->x509_issuer, @@ -3621,7 +3633,7 @@ end: acl_insert_role(combo.user.str, rights); else acl_insert_user(combo.user.str, combo.host.str, - combo.password.str, combo.password.length, + combo.pwhash.str, combo.pwhash.length, lex->ssl_type, lex->ssl_cipher, lex->x509_issuer, @@ -5679,7 +5691,7 @@ static bool merge_one_role_privileges(ACL_ROLE *grantee) static bool has_auth(LEX_USER *user, LEX *lex) { - return user->password.str || user->plugin.length || user->auth.length || + return user->pwtext.length || user->pwhash.length || user->plugin.length || user->auth.length || lex->ssl_type != SSL_TYPE_NOT_SPECIFIED || lex->ssl_cipher || lex->x509_issuer || lex->x509_subject || lex->mqh.specified_limits; @@ -5690,7 +5702,8 @@ static bool fix_and_copy_user(LEX_USER *to, LEX_USER *from, THD *thd) if (to != from) { /* preserve authentication information, if LEX_USER was reallocated */ - to->password= from->password; + to->pwtext= from->pwtext; + to->pwhash= from->pwhash; to->plugin= from->plugin; to->auth= from->auth; } @@ -7667,6 +7680,94 @@ static void add_user_option(String *grant, double value, const char *name) } } +static void add_user_parameters(String *result, ACL_USER* acl_user, + bool with_grant) +{ + result->append(STRING_WITH_LEN("@'")); + result->append(acl_user->host.hostname, acl_user->hostname_length, + system_charset_info); + result->append('\''); + + if (acl_user->plugin.str == native_password_plugin_name.str || + acl_user->plugin.str == old_password_plugin_name.str) + { + if (acl_user->auth_string.length) + { + DBUG_ASSERT(acl_user->salt_len); + result->append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '")); + result->append(acl_user->auth_string.str, acl_user->auth_string.length); + result->append('\''); + } + } + else + { + result->append(STRING_WITH_LEN(" IDENTIFIED VIA ")); + result->append(acl_user->plugin.str, acl_user->plugin.length); + if (acl_user->auth_string.length) + { + result->append(STRING_WITH_LEN(" USING '")); + result->append(acl_user->auth_string.str, acl_user->auth_string.length); + result->append('\''); + } + } + /* "show grants" SSL related stuff */ + if (acl_user->ssl_type == SSL_TYPE_ANY) + result->append(STRING_WITH_LEN(" REQUIRE SSL")); + else if (acl_user->ssl_type == SSL_TYPE_X509) + result->append(STRING_WITH_LEN(" REQUIRE X509")); + else if (acl_user->ssl_type == SSL_TYPE_SPECIFIED) + { + int ssl_options = 0; + result->append(STRING_WITH_LEN(" REQUIRE ")); + if (acl_user->x509_issuer) + { + ssl_options++; + result->append(STRING_WITH_LEN("ISSUER \'")); + result->append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); + result->append('\''); + } + if (acl_user->x509_subject) + { + if (ssl_options++) + result->append(' '); + result->append(STRING_WITH_LEN("SUBJECT \'")); + result->append(acl_user->x509_subject,strlen(acl_user->x509_subject), + system_charset_info); + result->append('\''); + } + if (acl_user->ssl_cipher) + { + if (ssl_options++) + result->append(' '); + result->append(STRING_WITH_LEN("CIPHER '")); + result->append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher), + system_charset_info); + result->append('\''); + } + } + if (with_grant || + (acl_user->user_resource.questions || + acl_user->user_resource.updates || + acl_user->user_resource.conn_per_hour || + acl_user->user_resource.user_conn || + acl_user->user_resource.max_statement_time != 0.0)) + { + result->append(STRING_WITH_LEN(" WITH")); + if (with_grant) + result->append(STRING_WITH_LEN(" GRANT OPTION")); + add_user_option(result, acl_user->user_resource.questions, + "MAX_QUERIES_PER_HOUR", false); + add_user_option(result, acl_user->user_resource.updates, + "MAX_UPDATES_PER_HOUR", false); + add_user_option(result, acl_user->user_resource.conn_per_hour, + "MAX_CONNECTIONS_PER_HOUR", false); + add_user_option(result, acl_user->user_resource.user_conn, + "MAX_USER_CONNECTIONS", true); + add_user_option(result, acl_user->user_resource.max_statement_time, + "MAX_STATEMENT_TIME"); + } +} + static const char *command_array[]= { "SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "RELOAD", @@ -7713,6 +7814,77 @@ static bool print_grants_for_role(THD *thd, ACL_ROLE * role) } +bool mysql_show_create_user(THD *thd, LEX_USER *lex_user) +{ + const char *username = safe_str(lex_user->user.str); + const char *hostname = safe_str(lex_user->host.str); + char buff[1024]; //Show create user should not take more than 1024 bytes. + Protocol *protocol= thd->protocol; + bool error= false; + ACL_USER *acl_user; + DBUG_ENTER("mysql_show_create_user"); + + // Check if the command specifies a username or not. + if (lex_user->user.str == current_user.str) + { + username= thd->security_ctx->priv_user; + hostname= thd->security_ctx->priv_host; + } + + List<Item> field_list; + strxmov(buff, "CREATE USER for ", username, "@", hostname, NullS); + Item_string *field = new (thd->mem_root) Item_string_ascii(thd, "", 0); + if (!field) + { + my_error(ER_OUTOFMEMORY, MYF(0)); + DBUG_RETURN(true); + } + + field->name= buff; + field->max_length= sizeof(buff); + field_list.push_back(field, thd->mem_root); + if (protocol->send_result_set_metadata(&field_list, + Protocol::SEND_NUM_ROWS | + Protocol::SEND_EOF)) + DBUG_RETURN(true); + + String result(buff, sizeof(buff), system_charset_info); + result.length(0); + mysql_rwlock_rdlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); + + acl_user= find_user_exact(hostname, username); + + // User not found in the internal data structures. + if (!acl_user) + { + my_error(ER_PASSWORD_NO_MATCH, MYF(0)); + error= true; + goto end; + } + + result.append("CREATE USER '"); + result.append(username); + result.append('\''); + + add_user_parameters(&result, acl_user, false); + + protocol->prepare_for_resend(); + protocol->store(result.ptr(), result.length(), result.charset()); + if (protocol->write()) + { + error= true; + } + my_eof(thd); + +end: + mysql_rwlock_unlock(&LOCK_grant); + mysql_mutex_unlock(&acl_cache->lock); + + DBUG_RETURN(error); +} + + static int show_grants_callback(ACL_USER_BASE *role, void *data) { THD *thd= (THD *)data; @@ -7722,6 +7894,15 @@ static int show_grants_callback(ACL_USER_BASE *role, void *data) return 0; } +void mysql_show_grants_get_fields(THD *thd, List<Item> *fields, + const char *name) +{ + Item_string *field=new (thd->mem_root) Item_string_ascii(thd, "", 0); + field->name= (char *) name; + field->max_length=1024; + fields->push_back(field, thd->mem_root); +} + /* SHOW GRANTS; Send grants for a user to the client @@ -7788,15 +7969,14 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user) } DBUG_ASSERT(rolename || username); - Item_string *field=new (thd->mem_root) Item_string_ascii(thd, "", 0); List<Item> field_list; - field->name=buff; - field->max_length=1024; if (!username) strxmov(buff,"Grants for ",rolename, NullS); else strxmov(buff,"Grants for ",username,"@",hostname, NullS); - field_list.push_back(field, thd->mem_root); + + mysql_show_grants_get_fields(thd, &field_list, buff); + if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) @@ -7981,93 +8161,7 @@ static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry, global.append('\''); if (!handle_as_role) - { - ACL_USER *acl_user= (ACL_USER *)acl_entry; - - global.append (STRING_WITH_LEN("@'")); - global.append(acl_user->host.hostname, acl_user->hostname_length, - system_charset_info); - global.append ('\''); - - if (acl_user->plugin.str == native_password_plugin_name.str || - acl_user->plugin.str == old_password_plugin_name.str) - { - if (acl_user->auth_string.length) - { - DBUG_ASSERT(acl_user->salt_len); - global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '")); - global.append(acl_user->auth_string.str, acl_user->auth_string.length); - global.append('\''); - } - } - else - { - global.append(STRING_WITH_LEN(" IDENTIFIED VIA ")); - global.append(acl_user->plugin.str, acl_user->plugin.length); - if (acl_user->auth_string.length) - { - global.append(STRING_WITH_LEN(" USING '")); - global.append(acl_user->auth_string.str, acl_user->auth_string.length); - global.append('\''); - } - } - /* "show grants" SSL related stuff */ - if (acl_user->ssl_type == SSL_TYPE_ANY) - global.append(STRING_WITH_LEN(" REQUIRE SSL")); - else if (acl_user->ssl_type == SSL_TYPE_X509) - global.append(STRING_WITH_LEN(" REQUIRE X509")); - else if (acl_user->ssl_type == SSL_TYPE_SPECIFIED) - { - int ssl_options = 0; - global.append(STRING_WITH_LEN(" REQUIRE ")); - if (acl_user->x509_issuer) - { - ssl_options++; - global.append(STRING_WITH_LEN("ISSUER \'")); - global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); - global.append('\''); - } - if (acl_user->x509_subject) - { - if (ssl_options++) - global.append(' '); - global.append(STRING_WITH_LEN("SUBJECT \'")); - global.append(acl_user->x509_subject,strlen(acl_user->x509_subject), - system_charset_info); - global.append('\''); - } - if (acl_user->ssl_cipher) - { - if (ssl_options++) - global.append(' '); - global.append(STRING_WITH_LEN("CIPHER '")); - global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher), - system_charset_info); - global.append('\''); - } - } - if ((want_access & GRANT_ACL) || - (acl_user->user_resource.questions || - acl_user->user_resource.updates || - acl_user->user_resource.conn_per_hour || - acl_user->user_resource.user_conn || - acl_user->user_resource.max_statement_time != 0.0)) - { - global.append(STRING_WITH_LEN(" WITH")); - if (want_access & GRANT_ACL) - global.append(STRING_WITH_LEN(" GRANT OPTION")); - add_user_option(&global, acl_user->user_resource.questions, - "MAX_QUERIES_PER_HOUR", false); - add_user_option(&global, acl_user->user_resource.updates, - "MAX_UPDATES_PER_HOUR", false); - add_user_option(&global, acl_user->user_resource.conn_per_hour, - "MAX_CONNECTIONS_PER_HOUR", false); - add_user_option(&global, acl_user->user_resource.user_conn, - "MAX_USER_CONNECTIONS", true); - add_user_option(&global, acl_user->user_resource.max_statement_time, - "MAX_STATEMENT_TIME"); - } - } + add_user_parameters(&global, (ACL_USER *)acl_entry, (want_access & GRANT_ACL)); protocol->prepare_for_resend(); protocol->store(global.ptr(),global.length(),global.charset()); @@ -9724,6 +9818,73 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) DBUG_RETURN(result); } +/* + Alter a user's connection and resource settings. + + SYNOPSIS + mysql_alter_user() + thd The current thread. + list The users to alter. + + RETURN + > 0 Error. Error message already sent. + 0 OK. +*/ +int mysql_alter_user(THD* thd, List<LEX_USER> &users_list) +{ + DBUG_ENTER("mysql_alter_user"); + int result= 0; + TABLE_LIST tables[TABLES_MAX]; + String wrong_users; + // The only table we're altering is the user table. + if ((result= open_grant_tables(thd, tables, TL_WRITE, Table_user))) + DBUG_RETURN(result); + + // Lock ACL data structures until we finish altering all users. + mysql_rwlock_wrlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); + + LEX_USER *tmp_lex_user; + List_iterator<LEX_USER> users_list_iterator(users_list); + while ((tmp_lex_user= users_list_iterator++)) + { + LEX_USER* lex_user= get_current_user(thd, tmp_lex_user, false); + if (!lex_user || + fix_lex_user(thd, lex_user) || + replace_user_table(thd, tables[USER_TABLE].table, *lex_user,0, + false, false, true)) + { + thd->clear_error(); + append_user(thd, &wrong_users, tmp_lex_user); + result= TRUE; + continue; + } + } + + // Unlock ACL data structures. + mysql_mutex_unlock(&acl_cache->lock); + mysql_rwlock_unlock(&LOCK_grant); + + if (result) + { + // 'if exists' flag leads to warnings instead of errors. + if (thd->lex->create_info.if_exists()) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_CANNOT_USER, + ER_THD(thd, ER_CANNOT_USER), + "ALTER USER", wrong_users.c_ptr_safe()); + result= FALSE; + } + else + { + my_error(ER_CANNOT_USER, MYF(0), + "ALTER USER", + wrong_users.c_ptr_safe()); + } + } + DBUG_RETURN(result); +} /* Revoke all privileges from a list of users. @@ -10107,7 +10268,7 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, @return @retval FALSE Success - @retval TRUE An error occured. Error message not yet sent. + @retval TRUE An error occurred. Error message not yet sent. */ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, @@ -10153,15 +10314,11 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, thd->make_lex_string(&combo->user, combo->user.str, strlen(combo->user.str)); thd->make_lex_string(&combo->host, combo->host.str, strlen(combo->host.str)); - combo->password= null_lex_str; - combo->plugin= empty_lex_str; - combo->auth= empty_lex_str; + combo->reset_auth(); if(au) { - if (au->plugin.str != native_password_plugin_name.str && - au->plugin.str != old_password_plugin_name.str) - combo->plugin= au->plugin; + combo->plugin= au->plugin; combo->auth= au->auth_string; } @@ -10915,7 +11072,7 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, /* global privileges */ grant->privilege= sctx->master_access; - if (!sctx->priv_user) + if (!sctx->priv_user[0]) { DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); DBUG_VOID_RETURN; // it is slave @@ -11314,7 +11471,8 @@ static bool send_server_handshake_packet(MPVIO_EXT *mpvio, int2store(end+5, thd->client_capabilities >> 16); end[7]= data_len; DBUG_EXECUTE_IF("poison_srv_handshake_scramble_len", end[7]= -100;); - bzero(end + 8, 10); + bzero(end + 8, 6); + int4store(end + 14, thd->client_capabilities >> 32); end+= 18; /* write scramble tail */ end= (char*) memcpy(end, data + SCRAMBLE_LENGTH_323, @@ -11730,18 +11888,27 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, */ DBUG_ASSERT(net->read_pos[pkt_len] == 0); - ulong client_capabilities= uint2korr(net->read_pos); + ulonglong client_capabilities= uint2korr(net->read_pos); + compile_time_assert(sizeof(client_capabilities) >= 8); if (client_capabilities & CLIENT_PROTOCOL_41) { - if (pkt_len < 4) + if (pkt_len < 32) return packet_error; client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16; + if (!(client_capabilities & CLIENT_MYSQL)) + { + // it is client with mariadb extensions + ulonglong ext_client_capabilities= + (((ulonglong)uint4korr(net->read_pos + 28)) << 32); + client_capabilities|= ext_client_capabilities; + } } /* Disable those bits which are not supported by the client. */ + compile_time_assert(sizeof(thd->client_capabilities) >= 8); thd->client_capabilities&= client_capabilities; - DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities)); + DBUG_PRINT("info", ("client capabilities: %llu", thd->client_capabilities)); if (thd->client_capabilities & CLIENT_SSL) { unsigned long errptr __attribute__((unused)); @@ -11769,8 +11936,6 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, if (client_capabilities & CLIENT_PROTOCOL_41) { - if (pkt_len < 32) - return packet_error; thd->max_client_packet_length= uint4korr(net->read_pos+4); DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8])); if (thd_init_client_charset(thd, (uint) net->read_pos[8])) @@ -12547,7 +12712,7 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) } DBUG_PRINT("info", - ("Capabilities: %lu packet_length: %ld Host: '%s' " + ("Capabilities: %llu packet_length: %ld Host: '%s' " "Login user: '%s' Priv_user: '%s' Using password: %s " "Access: %lu db: '%s'", thd->client_capabilities, thd->max_client_packet_length, diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 335a558cddb..be206b1f86f 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -241,7 +241,10 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table); ulong get_column_grant(THD *thd, GRANT_INFO *grant, const char *db_name, const char *table_name, const char *field_name); +void mysql_show_grants_get_fields(THD *thd, List<Item> *fields, + const char *name); bool mysql_show_grants(THD *thd, LEX_USER *user); +bool mysql_show_create_user(THD *thd, LEX_USER *user); int fill_schema_enabled_roles(THD *thd, TABLE_LIST *tables, COND *cond); int fill_schema_applicable_roles(THD *thd, TABLE_LIST *tables, COND *cond); void get_privilege_desc(char *to, uint max_length, ulong access); @@ -249,6 +252,7 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc); bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role); bool mysql_drop_user(THD *thd, List <LEX_USER> &list, bool handle_as_role); bool mysql_rename_user(THD *thd, List <LEX_USER> &list); +int mysql_alter_user(THD *thd, List <LEX_USER> &list); bool mysql_revoke_all(THD *thd, List <LEX_USER> &list); void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, const char *db, const char *table); diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 0787aa9e92f..205621c6f9f 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2010, 2014, Oracle and/or its affiliates. - Copyright (c) 2012, 2015, MariaDB +/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. + Copyright (c) 2011, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -131,7 +131,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(0); has_mdl_lock= TRUE; - share= tdc_acquire_share_shortlived(thd, table_list, GTS_TABLE); + share= tdc_acquire_share(thd, table_list, GTS_TABLE); if (share == NULL) DBUG_RETURN(0); // Can't open frm file @@ -288,7 +288,8 @@ static inline bool table_not_corrupt_error(uint sql_errno) sql_errno == ER_LOCK_WAIT_TIMEOUT || sql_errno == ER_LOCK_DEADLOCK || sql_errno == ER_CANT_LOCK_LOG_TABLE || - sql_errno == ER_OPEN_AS_READONLY); + sql_errno == ER_OPEN_AS_READONLY || + sql_errno == ER_WRONG_OBJECT); } @@ -368,6 +369,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, char* db = table->db; bool fatal_error=0; bool open_error; + bool collect_eis= FALSE; DBUG_PRINT("admin", ("table: '%s'.'%s'", table->db, table->table_name)); strxmov(table_name, db, ".", table->table_name, NullS); @@ -399,7 +401,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, lex->query_tables_last= &table->next_global; lex->query_tables_own_last= 0; - if (view_operator_func == NULL) + /* + CHECK TABLE command is allowed for views as well. Check on alter flags + to differentiate from ALTER TABLE...CHECK PARTITION on which view is not + allowed. + */ + if (lex->alter_info.flags & Alter_info::ALTER_ADMIN_PARTITION || + view_operator_func == NULL) { table->required_type=FRMTYPE_TABLE; DBUG_ASSERT(!lex->only_view); @@ -690,34 +698,64 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, { compl_result_code= result_code= HA_ADMIN_INVALID; } + collect_eis= + (table->table->s->table_category == TABLE_CATEGORY_USER && + (get_use_stat_tables_mode(thd) > NEVER || + lex->with_persistent_for_clause)); - if (!lex->column_list) - { - uint fields= 0; - for ( ; *field_ptr; field_ptr++, fields++) ; - bitmap_set_prefix(tab->read_set, fields); - } - else + if (collect_eis) { - int pos; - LEX_STRING *column_name; - List_iterator_fast<LEX_STRING> it(*lex->column_list); + if (!lex->column_list) + { + bitmap_clear_all(tab->read_set); + for (uint fields= 0; *field_ptr; field_ptr++, fields++) + { + enum enum_field_types type= (*field_ptr)->type(); + if (type < MYSQL_TYPE_MEDIUM_BLOB || + type > MYSQL_TYPE_BLOB) + bitmap_set_bit(tab->read_set, fields); + else if (collect_eis) + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NO_EIS_FOR_FIELD, + ER_THD(thd, ER_NO_EIS_FOR_FIELD), + (*field_ptr)->field_name); + } + } + else + { + int pos; + LEX_STRING *column_name; + List_iterator_fast<LEX_STRING> it(*lex->column_list); - bitmap_clear_all(tab->read_set); - while ((column_name= it++)) - { - if (tab->s->fieldnames.type_names == 0 || - (pos= find_type(&tab->s->fieldnames, column_name->str, - column_name->length, 1)) <= 0) + bitmap_clear_all(tab->read_set); + while ((column_name= it++)) { - compl_result_code= result_code= HA_ADMIN_INVALID; - break; + if (tab->s->fieldnames.type_names == 0 || + (pos= find_type(&tab->s->fieldnames, column_name->str, + column_name->length, 1)) <= 0) + { + compl_result_code= result_code= HA_ADMIN_INVALID; + break; + } + pos--; + enum enum_field_types type= tab->field[pos]->type(); + if (type < MYSQL_TYPE_MEDIUM_BLOB || + type > MYSQL_TYPE_BLOB) + bitmap_set_bit(tab->read_set, pos); + else if (collect_eis) + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_NO_EIS_FOR_FIELD, + ER_THD(thd, ER_NO_EIS_FOR_FIELD), + column_name->str); } - bitmap_set_bit(tab->read_set, pos-1); - } - tab->file->column_bitmaps_signal(); + tab->file->column_bitmaps_signal(); + } } - + else + { + DBUG_ASSERT(!lex->column_list); + } + if (!lex->index_list) { tab->keys_in_use_for_query.init(tab->s->keys); @@ -752,11 +790,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, DBUG_PRINT("admin", ("operator_func returned: %d", result_code)); } - if (compl_result_code == HA_ADMIN_OK && - operator_func == &handler::ha_analyze && - table->table->s->table_category == TABLE_CATEGORY_USER && - (get_use_stat_tables_mode(thd) > NEVER || - lex->with_persistent_for_clause)) + if (compl_result_code == HA_ADMIN_OK && collect_eis) { if (!(compl_result_code= alloc_statistics_for_table(thd, table->table)) && @@ -1180,9 +1214,8 @@ bool Sql_cmd_analyze_table::execute(THD *thd) if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table, FALSE, UINT_MAX, FALSE)) goto error; + WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table); thd->enable_slow_log= opt_log_slow_admin_statements; - WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL); - res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "analyze", lock_type, 1, 0, 0, 0, &handler::ha_analyze, 0); @@ -1237,7 +1270,7 @@ bool Sql_cmd_optimize_table::execute(THD *thd) if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table, FALSE, UINT_MAX, FALSE)) goto error; /* purecov: inspected */ - WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL) + WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table); thd->enable_slow_log= opt_log_slow_admin_statements; res= (specialflag & SPECIAL_NO_NEW_FUNC) ? mysql_recreate_table(thd, first_table, true) : @@ -1271,7 +1304,7 @@ bool Sql_cmd_repair_table::execute(THD *thd) FALSE, UINT_MAX, FALSE)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; - WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL) + WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table); res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "repair", TL_WRITE, 1, MY_TEST(m_lex->check_opt.sql_flags & TT_USEFRM), diff --git a/sql/sql_audit.cc b/sql/sql_audit.cc index b659054a50b..e2132efc528 100644 --- a/sql/sql_audit.cc +++ b/sql/sql_audit.cc @@ -24,6 +24,7 @@ extern int finalize_audit_plugin(st_plugin_int *plugin); struct st_mysql_event_generic { + unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; unsigned int event_class; const void *event; }; @@ -32,8 +33,6 @@ unsigned long mysql_global_audit_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; static mysql_mutex_t LOCK_audit_mask; -static void event_class_dispatch(THD *, unsigned int, const void *); - static inline void set_audit_mask(unsigned long *mask, uint event_class) @@ -56,101 +55,6 @@ bool check_audit_mask(const unsigned long *lhs, } -typedef void (*audit_handler_t)(THD *thd, uint event_subtype, va_list ap); - -/** - MYSQL_AUDIT_GENERAL_CLASS handler - - @param[in] thd - @param[in] event_subtype - @param[in] error_code - @param[in] ap - -*/ - -static void general_class_handler(THD *thd, uint event_subtype, va_list ap) -{ - mysql_event_general event; - event.event_subclass= event_subtype; - event.general_error_code= va_arg(ap, int); - event.general_thread_id= thd ? thd->thread_id : 0; - event.general_time= va_arg(ap, time_t); - event.general_user= va_arg(ap, const char *); - event.general_user_length= va_arg(ap, unsigned int); - event.general_command= va_arg(ap, const char *); - event.general_command_length= va_arg(ap, unsigned int); - event.general_query= va_arg(ap, const char *); - event.general_query_length= va_arg(ap, unsigned int); - event.general_charset= va_arg(ap, struct charset_info_st *); - event.general_rows= (unsigned long long) va_arg(ap, ha_rows); - event.database= va_arg(ap, const char *); - event.database_length= va_arg(ap, unsigned int); - event.query_id= (unsigned long long) (thd ? thd->query_id : 0); - event_class_dispatch(thd, MYSQL_AUDIT_GENERAL_CLASS, &event); -} - - -static void connection_class_handler(THD *thd, uint event_subclass, va_list ap) -{ - mysql_event_connection event; - event.event_subclass= event_subclass; - event.status= va_arg(ap, int); - event.thread_id= va_arg(ap, unsigned long); - event.user= va_arg(ap, const char *); - event.user_length= va_arg(ap, unsigned int); - event.priv_user= va_arg(ap, const char *); - event.priv_user_length= va_arg(ap, unsigned int); - event.external_user= va_arg(ap, const char *); - event.external_user_length= va_arg(ap, unsigned int); - event.proxy_user= va_arg(ap, const char *); - event.proxy_user_length= va_arg(ap, unsigned int); - event.host= va_arg(ap, const char *); - event.host_length= va_arg(ap, unsigned int); - event.ip= va_arg(ap, const char *); - event.ip_length= va_arg(ap, unsigned int); - event.database= va_arg(ap, const char *); - event.database_length= va_arg(ap, unsigned int); - event_class_dispatch(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event); -} - - -static void table_class_handler(THD *thd, uint event_subclass, va_list ap) -{ - mysql_event_table event; - event.event_subclass= event_subclass; - event.read_only= va_arg(ap, int); - event.thread_id= va_arg(ap, unsigned long); - event.user= va_arg(ap, const char *); - event.priv_user= va_arg(ap, const char *); - event.priv_host= va_arg(ap, const char *); - event.external_user= va_arg(ap, const char *); - event.proxy_user= va_arg(ap, const char *); - event.host= va_arg(ap, const char *); - event.ip= va_arg(ap, const char *); - event.database= va_arg(ap, const char *); - event.database_length= va_arg(ap, unsigned int); - event.table= va_arg(ap, const char *); - event.table_length= va_arg(ap, unsigned int); - event.new_database= va_arg(ap, const char *); - event.new_database_length= va_arg(ap, unsigned int); - event.new_table= va_arg(ap, const char *); - event.new_table_length= va_arg(ap, unsigned int); - event.query_id= (unsigned long long) (thd ? thd->query_id : 0); - event_class_dispatch(thd, MYSQL_AUDIT_TABLE_CLASS, &event); -} - - -static audit_handler_t audit_handlers[] = -{ - general_class_handler, connection_class_handler, - 0,0,0,0,0,0,0,0,0,0,0,0,0, /* placeholders */ - table_class_handler -}; - -static const uint audit_handlers_count= - (sizeof(audit_handlers) / sizeof(audit_handler_t)); - - /** Acquire and lock any additional audit plugins as required @@ -207,38 +111,16 @@ static my_bool acquire_plugins(THD *thd, plugin_ref plugin, void *arg) void mysql_audit_acquire_plugins(THD *thd, ulong *event_class_mask) { DBUG_ENTER("mysql_audit_acquire_plugins"); - if (thd && !check_audit_mask(mysql_global_audit_mask, event_class_mask) && - check_audit_mask(thd->audit_class_mask, event_class_mask)) + DBUG_ASSERT(thd); + DBUG_ASSERT(!check_audit_mask(mysql_global_audit_mask, event_class_mask)); + + if (check_audit_mask(thd->audit_class_mask, event_class_mask)) { plugin_foreach(thd, acquire_plugins, MYSQL_AUDIT_PLUGIN, event_class_mask); add_audit_mask(thd->audit_class_mask, event_class_mask); } DBUG_VOID_RETURN; } - - -/** - Notify the audit system of an event - - @param[in] thd - @param[in] event_class - @param[in] event_subtype - @param[in] error_code - -*/ - -void mysql_audit_notify(THD *thd, uint event_class, uint event_subtype, ...) -{ - va_list ap; - audit_handler_t *handlers= audit_handlers + event_class; - DBUG_ASSERT(event_class < audit_handlers_count); - unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; - set_audit_mask(event_class_mask, event_class); - mysql_audit_acquire_plugins(thd, event_class_mask); - va_start(ap, event_subtype); - (*handlers)(thd, event_subtype, ap); - va_end(ap); -} /** @@ -496,17 +378,11 @@ static my_bool plugins_dispatch(THD *thd, plugin_ref plugin, void *arg) { const struct st_mysql_event_generic *event_generic= (const struct st_mysql_event_generic *) arg; - unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; st_mysql_audit *data= plugin_data(plugin, struct st_mysql_audit *); - set_audit_mask(event_class_mask, event_generic->event_class); - /* Check to see if the plugin is interested in this event */ - if (check_audit_mask(data->class_mask, event_class_mask)) - return 0; - - /* Actually notify the plugin */ - data->event_notify(thd, event_generic->event_class, event_generic->event); + if (!check_audit_mask(data->class_mask, event_generic->event_class_mask)) + data->event_notify(thd, event_generic->event_class, event_generic->event); return 0; } @@ -514,17 +390,18 @@ static my_bool plugins_dispatch(THD *thd, plugin_ref plugin, void *arg) /** Distributes an audit event to plug-ins - + @param[in] thd + @param[in] event_class @param[in] event */ -static void event_class_dispatch(THD *thd, unsigned int event_class, - const void *event) +void mysql_audit_notify(THD *thd, uint event_class, const void *event) { struct st_mysql_event_generic event_generic; event_generic.event_class= event_class; event_generic.event= event; + set_audit_mask(event_generic.event_class_mask, event_class); /* Check if we are doing a slow global dispatch. This event occurs when thd == NULL as it is not associated with any particular thread. @@ -537,6 +414,8 @@ static void event_class_dispatch(THD *thd, unsigned int event_class, { plugin_ref *plugins, *plugins_last; + mysql_audit_acquire_plugins(thd, event_generic.event_class_mask); + /* Use the cached set of audit plugins */ plugins= (plugin_ref*) thd->audit_class_plugins.buffer; plugins_last= plugins + thd->audit_class_plugins.elements; diff --git a/sql/sql_audit.h b/sql/sql_audit.h index 68106f099cc..d6f670538cd 100644 --- a/sql/sql_audit.h +++ b/sql/sql_audit.h @@ -35,8 +35,7 @@ extern void mysql_audit_acquire_plugins(THD *thd, ulong *event_class_mask); #ifndef EMBEDDED_LIBRARY -extern void mysql_audit_notify(THD *thd, uint event_class, - uint event_subtype, ...); +extern void mysql_audit_notify(THD *thd, uint event_class, const void *event); static inline bool mysql_audit_general_enabled() { @@ -55,7 +54,7 @@ static inline bool mysql_audit_table_enabled() #else static inline void mysql_audit_notify(THD *thd, uint event_class, - uint event_subtype, ...) { } + const void *event) {} #define mysql_audit_general_enabled() 0 #define mysql_audit_connection_enabled() 0 #define mysql_audit_table_enabled() 0 @@ -94,15 +93,37 @@ void mysql_audit_general_log(THD *thd, time_t time, { if (mysql_audit_general_enabled()) { - CHARSET_INFO *clientcs= thd ? thd->variables.character_set_client - : global_system_variables.character_set_client; - const char *db= thd ? thd->db : ""; - size_t db_length= thd ? thd->db_length : 0; - - mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, MYSQL_AUDIT_GENERAL_LOG, - 0, time, user, userlen, cmd, cmdlen, - query, querylen, clientcs, (ha_rows) 0, - db, db_length); + mysql_event_general event; + + event.event_subclass= MYSQL_AUDIT_GENERAL_LOG; + event.general_error_code= 0; + event.general_time= time; + event.general_user= user; + event.general_user_length= userlen; + event.general_command= cmd; + event.general_command_length= cmdlen; + event.general_query= query; + event.general_query_length= querylen; + event.general_rows= 0; + + if (thd) + { + event.general_thread_id= (unsigned long)thd->thread_id; + event.general_charset= thd->variables.character_set_client; + event.database= thd->db; + event.database_length= thd->db_length; + event.query_id= thd->query_id; + } + else + { + event.general_thread_id= 0; + event.general_charset= global_system_variables.character_set_client; + event.database= ""; + event.database_length= 0; + event.query_id= 0; + } + + mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, &event); } } @@ -124,38 +145,41 @@ void mysql_audit_general(THD *thd, uint event_subtype, { if (mysql_audit_general_enabled()) { - time_t time= my_time(0); - uint msglen= msg ? strlen(msg) : 0; - const char *user; - uint userlen; char user_buff[MAX_USER_HOST_SIZE]; - CSET_STRING query; - ha_rows rows; - const char *db; - size_t db_length; + mysql_event_general event; + + event.event_subclass= event_subtype; + event.general_error_code= error_code; + event.general_time= my_time(0); + event.general_command= msg; + event.general_command_length= safe_strlen(msg); if (thd) { - query= thd->query_string; - user= user_buff; - userlen= make_user_name(thd, user_buff); - rows= thd->get_stmt_da()->current_row_for_warning(); - db= thd->db; - db_length= thd->db_length; + event.general_user= user_buff; + event.general_user_length= make_user_name(thd, user_buff); + event.general_thread_id= (unsigned long)thd->thread_id; + event.general_query= thd->query_string.str(); + event.general_query_length= thd->query_string.length(); + event.general_charset= thd->query_string.charset(); + event.general_rows= thd->get_stmt_da()->current_row_for_warning(); + event.database= thd->db; + event.database_length= thd->db_length; + event.query_id= thd->query_id; } else { - user= 0; - userlen= 0; - rows= 0; - db= ""; - db_length= 0; + event.general_thread_id= 0; + event.general_query= NULL; + event.general_query_length= 0; + event.general_charset= &my_charset_bin; + event.general_rows= 0; + event.database= ""; + event.database_length= 0; + event.query_id= 0; } - mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, event_subtype, - error_code, time, user, userlen, msg, msglen, - query.str(), query.length(), query.charset(), rows, - db, db_length); + mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, &event); } } @@ -165,19 +189,28 @@ void mysql_audit_notify_connection_connect(THD *thd) if (mysql_audit_connection_enabled()) { const Security_context *sctx= thd->security_ctx; - Diagnostics_area *da= thd->get_stmt_da(); - mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS, - MYSQL_AUDIT_CONNECTION_CONNECT, - da->is_error() ? da->sql_errno() : 0, - thd->thread_id, - sctx->user, sctx->user ? strlen(sctx->user) : 0, - sctx->priv_user, strlen(sctx->priv_user), - sctx->external_user, - sctx->external_user ? strlen(sctx->external_user) : 0, - sctx->proxy_user, strlen(sctx->proxy_user), - sctx->host, sctx->host ? strlen(sctx->host) : 0, - sctx->ip, sctx->ip ? strlen(sctx->ip) : 0, - thd->db, thd->db ? strlen(thd->db) : 0); + mysql_event_connection event; + + event.event_subclass= MYSQL_AUDIT_CONNECTION_CONNECT; + event.status= thd->get_stmt_da()->is_error() ? + thd->get_stmt_da()->sql_errno() : 0; + event.thread_id= (unsigned long)thd->thread_id; + event.user= sctx->user; + event.user_length= safe_strlen(sctx->user); + event.priv_user= sctx->priv_user; + event.priv_user_length= strlen(sctx->priv_user); + event.external_user= sctx->external_user; + event.external_user_length= safe_strlen(sctx->external_user); + event.proxy_user= sctx->proxy_user; + event.proxy_user_length= strlen(sctx->proxy_user); + event.host= sctx->host; + event.host_length= safe_strlen(sctx->host); + event.ip= sctx->ip; + event.ip_length= safe_strlen(sctx->ip); + event.database= thd->db; + event.database_length= safe_strlen(thd->db); + + mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event); } } @@ -187,17 +220,27 @@ void mysql_audit_notify_connection_disconnect(THD *thd, int errcode) if (mysql_audit_connection_enabled()) { const Security_context *sctx= thd->security_ctx; - mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS, - MYSQL_AUDIT_CONNECTION_DISCONNECT, - errcode, thd->thread_id, - sctx->user, sctx->user ? strlen(sctx->user) : 0, - sctx->priv_user, strlen(sctx->priv_user), - sctx->external_user, - sctx->external_user ? strlen(sctx->external_user) : 0, - sctx->proxy_user, strlen(sctx->proxy_user), - sctx->host, sctx->host ? strlen(sctx->host) : 0, - sctx->ip, sctx->ip ? strlen(sctx->ip) : 0, - thd->db, thd->db ? strlen(thd->db) : 0); + mysql_event_connection event; + + event.event_subclass= MYSQL_AUDIT_CONNECTION_DISCONNECT; + event.status= errcode; + event.thread_id= (unsigned long)thd->thread_id; + event.user= sctx->user; + event.user_length= safe_strlen(sctx->user); + event.priv_user= sctx->priv_user; + event.priv_user_length= strlen(sctx->priv_user); + event.external_user= sctx->external_user; + event.external_user_length= safe_strlen(sctx->external_user); + event.proxy_user= sctx->proxy_user; + event.proxy_user_length= strlen(sctx->proxy_user); + event.host= sctx->host; + event.host_length= safe_strlen(sctx->host); + event.ip= sctx->ip; + event.ip_length= safe_strlen(sctx->ip) ; + event.database= thd->db; + event.database_length= safe_strlen(thd->db); + + mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event); } } @@ -207,19 +250,28 @@ void mysql_audit_notify_connection_change_user(THD *thd) if (mysql_audit_connection_enabled()) { const Security_context *sctx= thd->security_ctx; - Diagnostics_area *da= thd->get_stmt_da(); - mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS, - MYSQL_AUDIT_CONNECTION_CHANGE_USER, - da->is_error() ? da->sql_errno() : 0, - thd->thread_id, - sctx->user, sctx->user ? strlen(sctx->user) : 0, - sctx->priv_user, strlen(sctx->priv_user), - sctx->external_user, - sctx->external_user ? strlen(sctx->external_user) : 0, - sctx->proxy_user, strlen(sctx->proxy_user), - sctx->host, sctx->host ? strlen(sctx->host) : 0, - sctx->ip, sctx->ip ? strlen(sctx->ip) : 0, - thd->db, thd->db ? strlen(thd->db) : 0); + mysql_event_connection event; + + event.event_subclass= MYSQL_AUDIT_CONNECTION_CHANGE_USER; + event.status= thd->get_stmt_da()->is_error() ? + thd->get_stmt_da()->sql_errno() : 0; + event.thread_id= (unsigned long)thd->thread_id; + event.user= sctx->user; + event.user_length= safe_strlen(sctx->user); + event.priv_user= sctx->priv_user; + event.priv_user_length= strlen(sctx->priv_user); + event.external_user= sctx->external_user; + event.external_user_length= safe_strlen(sctx->external_user); + event.proxy_user= sctx->proxy_user; + event.proxy_user_length= strlen(sctx->proxy_user); + event.host= sctx->host; + event.host_length= safe_strlen(sctx->host); + event.ip= sctx->ip; + event.ip_length= safe_strlen(sctx->ip); + event.database= thd->db; + event.database_length= safe_strlen(thd->db); + + mysql_audit_notify(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event); } } @@ -229,13 +281,29 @@ void mysql_audit_external_lock(THD *thd, TABLE_SHARE *share, int lock) if (lock != F_UNLCK && mysql_audit_table_enabled()) { const Security_context *sctx= thd->security_ctx; - mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, MYSQL_AUDIT_TABLE_LOCK, - (int)(lock == F_RDLCK), (ulong)thd->thread_id, - sctx->user, sctx->priv_user, sctx->priv_host, - sctx->external_user, sctx->proxy_user, sctx->host, - sctx->ip, share->db.str, (uint)share->db.length, - share->table_name.str, (uint)share->table_name.length, - 0,0,0,0); + mysql_event_table event; + + event.event_subclass= MYSQL_AUDIT_TABLE_LOCK; + event.read_only= lock == F_RDLCK; + event.thread_id= (unsigned long)thd->thread_id; + event.user= sctx->user; + event.priv_user= sctx->priv_user; + event.priv_host= sctx->priv_host; + event.external_user= sctx->external_user; + event.proxy_user= sctx->proxy_user; + event.host= sctx->host; + event.ip= sctx->ip; + event.database= share->db.str; + event.database_length= share->db.length; + event.table= share->table_name.str; + event.table_length= share->table_name.length; + event.new_database= 0; + event.new_database_length= 0; + event.new_table= 0; + event.new_table_length= 0; + event.query_id= thd->query_id; + + mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, &event); } } @@ -247,13 +315,29 @@ void mysql_audit_create_table(TABLE *table) THD *thd= table->in_use; const TABLE_SHARE *share= table->s; const Security_context *sctx= thd->security_ctx; - mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, MYSQL_AUDIT_TABLE_CREATE, - 0, (ulong)thd->thread_id, - sctx->user, sctx->priv_user, sctx->priv_host, - sctx->external_user, sctx->proxy_user, sctx->host, - sctx->ip, share->db.str, (uint)share->db.length, - share->table_name.str, (uint)share->table_name.length, - 0,0,0,0); + mysql_event_table event; + + event.event_subclass= MYSQL_AUDIT_TABLE_CREATE; + event.read_only= 0; + event.thread_id= (unsigned long)thd->thread_id; + event.user= sctx->user; + event.priv_user= sctx->priv_user; + event.priv_host= sctx->priv_host; + event.external_user= sctx->external_user; + event.proxy_user= sctx->proxy_user; + event.host= sctx->host; + event.ip= sctx->ip; + event.database= share->db.str; + event.database_length= share->db.length; + event.table= share->table_name.str; + event.table_length= share->table_name.length; + event.new_database= 0; + event.new_database_length= 0; + event.new_table= 0; + event.new_table_length= 0; + event.query_id= thd->query_id; + + mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, &event); } } @@ -263,13 +347,29 @@ void mysql_audit_drop_table(THD *thd, TABLE_LIST *table) if (mysql_audit_table_enabled()) { const Security_context *sctx= thd->security_ctx; - mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, MYSQL_AUDIT_TABLE_DROP, - 0, (ulong)thd->thread_id, - sctx->user, sctx->priv_user, sctx->priv_host, - sctx->external_user, sctx->proxy_user, sctx->host, - sctx->ip, table->db, (uint)table->db_length, - table->table_name, (uint)table->table_name_length, - 0,0,0,0); + mysql_event_table event; + + event.event_subclass= MYSQL_AUDIT_TABLE_DROP; + event.read_only= 0; + event.thread_id= (unsigned long)thd->thread_id; + event.user= sctx->user; + event.priv_user= sctx->priv_user; + event.priv_host= sctx->priv_host; + event.external_user= sctx->external_user; + event.proxy_user= sctx->proxy_user; + event.host= sctx->host; + event.ip= sctx->ip; + event.database= table->db; + event.database_length= table->db_length; + event.table= table->table_name; + event.table_length= table->table_name_length; + event.new_database= 0; + event.new_database_length= 0; + event.new_table= 0; + event.new_table_length= 0; + event.query_id= thd->query_id; + + mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, &event); } } @@ -280,13 +380,29 @@ void mysql_audit_rename_table(THD *thd, const char *old_db, const char *old_tb, if (mysql_audit_table_enabled()) { const Security_context *sctx= thd->security_ctx; - mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, MYSQL_AUDIT_TABLE_RENAME, - 0, (ulong)thd->thread_id, - sctx->user, sctx->priv_user, sctx->priv_host, - sctx->external_user, sctx->proxy_user, sctx->host, - sctx->ip, - old_db, (uint)strlen(old_db), old_tb, (uint)strlen(old_tb), - new_db, (uint)strlen(new_db), new_tb, (uint)strlen(new_tb)); + mysql_event_table event; + + event.event_subclass= MYSQL_AUDIT_TABLE_RENAME; + event.read_only= 0; + event.thread_id= (unsigned long)thd->thread_id; + event.user= sctx->user; + event.priv_user= sctx->priv_user; + event.priv_host= sctx->priv_host; + event.external_user= sctx->external_user; + event.proxy_user= sctx->proxy_user; + event.host= sctx->host; + event.ip= sctx->ip; + event.database= old_db; + event.database_length= strlen(old_db); + event.table= old_tb; + event.table_length= strlen(old_tb); + event.new_database= new_db; + event.new_database_length= strlen(new_db); + event.new_table= new_tb; + event.new_table_length= strlen(new_tb); + event.query_id= thd->query_id; + + mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, &event); } } @@ -296,13 +412,29 @@ void mysql_audit_alter_table(THD *thd, TABLE_LIST *table) if (mysql_audit_table_enabled()) { const Security_context *sctx= thd->security_ctx; - mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, MYSQL_AUDIT_TABLE_ALTER, - 0, (ulong)thd->thread_id, - sctx->user, sctx->priv_user, sctx->priv_host, - sctx->external_user, sctx->proxy_user, sctx->host, - sctx->ip, table->db, (uint)table->db_length, - table->table_name, (uint)table->table_name_length, - 0,0,0,0); + mysql_event_table event; + + event.event_subclass= MYSQL_AUDIT_TABLE_ALTER; + event.read_only= 0; + event.thread_id= (unsigned long)thd->thread_id; + event.user= sctx->user; + event.priv_user= sctx->priv_user; + event.priv_host= sctx->priv_host; + event.external_user= sctx->external_user; + event.proxy_user= sctx->proxy_user; + event.host= sctx->host; + event.ip= sctx->ip; + event.database= table->db; + event.database_length= table->db_length; + event.table= table->table_name; + event.table_length= table->table_name_length; + event.new_database= 0; + event.new_database_length= 0; + event.new_table= 0; + event.new_table_length= 0; + event.query_id= thd->query_id; + + mysql_audit_notify(thd, MYSQL_AUDIT_TABLE_CLASS, &event); } } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 20f602ce038..819f89d5ac4 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB + Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -49,6 +49,7 @@ #include "transaction.h" #include "sql_prepare.h" #include "sql_statistics.h" +#include "sql_cte.h" #include <m_ctype.h> #include <my_dir.h> #include <hash.h> @@ -168,11 +169,6 @@ static bool check_and_update_table_version(THD *thd, TABLE_LIST *tables, TABLE_SHARE *table_share); static bool open_table_entry_fini(THD *thd, TABLE_SHARE *share, TABLE *entry); static bool auto_repair_table(THD *thd, TABLE_LIST *table_list); -static bool -has_write_table_with_auto_increment(TABLE_LIST *tables); -static bool -has_write_table_with_auto_increment_and_select(TABLE_LIST *tables); -static bool has_write_table_auto_increment_not_first_in_pk(TABLE_LIST *tables); /** @@ -353,7 +349,6 @@ void intern_close_table(TABLE *table) table->s ? table->s->table_name.str : "?", (long) table)); - free_io_cache(table); delete table->triggers; if (table->file) // Not true if placeholder (void) closefrm(table, 1); // close file @@ -363,21 +358,6 @@ void intern_close_table(TABLE *table) } -/* Free resources allocated by filesort() and read_record() */ - -void free_io_cache(TABLE *table) -{ - DBUG_ENTER("free_io_cache"); - if (table->sort.io_cache) - { - close_cached_file(table->sort.io_cache); - my_free(table->sort.io_cache); - table->sort.io_cache=0; - } - DBUG_VOID_RETURN; -} - - /** Auxiliary function which allows to kill delayed threads for particular table identified by its share. @@ -1233,7 +1213,8 @@ bool close_temporary_tables(THD *thd) */ for (; table && is_user_table(table) && - tmpkeyval(thd, table) == thd->variables.pseudo_thread_id && + (ulong) tmpkeyval(thd, table) == + (ulong) thd->variables.pseudo_thread_id && table->s->db.length == db.length() && memcmp(table->s->db.str, db.ptr(), db.length()) == 0; table= next) @@ -1815,7 +1796,6 @@ void close_temporary(TABLE *table, bool free_share, bool delete_table) DBUG_PRINT("tmptable", ("closing table: '%s'.'%s'", table->s->db.str, table->s->table_name.str)); - free_io_cache(table); closefrm(table, 0); if (delete_table) rm_temporary_table(table_type, table->s->path.str); @@ -2294,8 +2274,17 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) */ if (dd_frm_is_view(thd, path)) { - if (!tdc_open_view(thd, table_list, alias, key, key_length, - CHECK_METADATA_VERSION)) + /* + If parent_l of the table_list is non null then a merge table + has this view as child table, which is not supported. + */ + if (table_list->parent_l) + { + my_error(ER_WRONG_MRG_TABLE, MYF(0)); + DBUG_RETURN(true); + } + + if (!tdc_open_view(thd, table_list, CHECK_METADATA_VERSION)) { DBUG_ASSERT(table_list->view != 0); DBUG_RETURN(FALSE); // VIEW @@ -2413,10 +2402,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) retry_share: - share= tdc_acquire_share(thd, table_list->db, table_list->table_name, - key, key_length, - table_list->mdl_request.key.tc_hash_value(), - gts_flags, &table); + share= tdc_acquire_share(thd, table_list, gts_flags, &table); if (!share) { @@ -3266,9 +3252,6 @@ check_and_update_routine_version(THD *thd, Sroutine_hash_entry *rt, @param thd Thread handle @param table_list TABLE_LIST with db, table_name & belong_to_view - @param alias Alias name - @param cache_key Key for table definition cache - @param cache_key_length Length of cache_key @param flags Flags which modify how we open the view @todo This function is needed for special handling of views under @@ -3277,16 +3260,13 @@ check_and_update_routine_version(THD *thd, Sroutine_hash_entry *rt, @return FALSE if success, TRUE - otherwise. */ -bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias, - const char *cache_key, uint cache_key_length, - uint flags) +bool tdc_open_view(THD *thd, TABLE_LIST *table_list, uint flags) { TABLE not_used; TABLE_SHARE *share; bool err= TRUE; - if (!(share= tdc_acquire_share(thd, table_list->db, table_list->table_name, - cache_key, cache_key_length, GTS_VIEW))) + if (!(share= tdc_acquire_share(thd, table_list, GTS_VIEW))) return TRUE; DBUG_ASSERT(share->is_view); @@ -3373,7 +3353,7 @@ static bool auto_repair_table(THD *thd, TABLE_LIST *table_list) if (!(entry= (TABLE*)my_malloc(sizeof(TABLE), MYF(MY_WME)))) return result; - if (!(share= tdc_acquire_share_shortlived(thd, table_list, GTS_TABLE))) + if (!(share= tdc_acquire_share(thd, table_list, GTS_TABLE))) goto end_free; DBUG_ASSERT(! share->is_view); @@ -3592,8 +3572,7 @@ Open_table_context::recover_from_failed_open() if (open_if_exists) m_thd->push_internal_handler(&no_such_table_handler); - result= !tdc_acquire_share(m_thd, m_failed_table->db, - m_failed_table->table_name, + result= !tdc_acquire_share(m_thd, m_failed_table, GTS_TABLE | GTS_FORCE_DISCOVERY | GTS_NOLOCK); if (open_if_exists) { @@ -3925,6 +3904,26 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables, tables->table_name= tables->view_name.str; tables->table_name_length= tables->view_name.length; } + else if (tables->select_lex) + { + /* + Check whether 'tables' refers to a table defined in a with clause. + If so set the reference to the definition in tables->with. + */ + if (!tables->with) + tables->with= tables->select_lex->find_table_def_in_with_clauses(tables); + /* + If 'tables' is defined in a with clause set the pointer to the + specification from its definition in tables->derived. + */ + if (tables->with) + { + if (tables->set_as_with_table(thd, tables->with)) + DBUG_RETURN(1); + else + goto end; + } + } /* If this TABLE_LIST object is a placeholder for an information_schema table, create a temporary table to represent the information_schema @@ -5416,65 +5415,6 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, *(ptr++)= table->table; } - /* - DML statements that modify a table with an auto_increment column based on - rows selected from a table are unsafe as the order in which the rows are - fetched fron the select tables cannot be determined and may differ on - master and slave. - */ - if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables && - has_write_table_with_auto_increment_and_select(tables)) - thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT); - /* Todo: merge all has_write_table_auto_inc with decide_logging_format */ - if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables) - { - if (has_write_table_auto_increment_not_first_in_pk(tables)) - thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST); - } - -#ifdef NOT_USED_IN_MARIADB - /* - INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys - can be unsafe. - */ - uint unique_keys= 0; - for (TABLE_LIST *query_table= tables; query_table && unique_keys <= 1; - query_table= query_table->next_global) - if(query_table->table) - { - uint keys= query_table->table->s->keys, i= 0; - unique_keys= 0; - for (KEY* keyinfo= query_table->table->s->key_info; - i < keys && unique_keys <= 1; i++, keyinfo++) - { - if (keyinfo->flags & HA_NOSAME) - unique_keys++; - } - if (!query_table->placeholder() && - query_table->lock_type >= TL_WRITE_ALLOW_WRITE && - unique_keys > 1 && thd->lex->sql_command == SQLCOM_INSERT && - /* Duplicate key update is not supported by INSERT DELAYED */ - thd->get_command() != COM_DELAYED_INSERT && - thd->lex->duplicates == DUP_UPDATE) - thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS); - } -#endif - - /* We have to emulate LOCK TABLES if we are statement needs prelocking. */ - if (thd->lex->requires_prelocking()) - { - - /* - A query that modifies autoinc column in sub-statement can make the - master and slave inconsistent. - We can solve these problems in mixed mode by switching to binlogging - if at least one updated table is used by sub-statement - */ - if (thd->wsrep_binlog_format() != BINLOG_FORMAT_ROW && tables && - has_write_table_with_auto_increment(thd->lex->first_not_own_table())) - thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS); - } - DEBUG_SYNC(thd, "before_lock_tables_takes_lock"); if (! (thd->lock= mysql_lock_tables(thd, start, (uint) (ptr - start), @@ -8434,7 +8374,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, temporary table. Thus in this case we can be sure that 'item' is an Item_field. */ - if (any_privileges) + if (any_privileges && !tables->is_with_table() && !tables->is_derived()) { DBUG_ASSERT((tables->field_translation == NULL && table) || tables->is_natural_join); @@ -8635,7 +8575,7 @@ bool setup_on_expr(THD *thd, TABLE_LIST *table, bool is_update) TODO RETURN - TRUE if some error occured (e.g. out of memory) + TRUE if some error occurred (e.g. out of memory) FALSE if all is OK */ @@ -8745,7 +8685,7 @@ err_no_arena: function. @return Status - @retval true An error occured. + @retval true An error occurred. @retval false OK. */ @@ -8907,7 +8847,7 @@ static bool not_null_fields_have_null_values(TABLE *table) record[1] buffers correspond to new and old versions of row respectively. @return Status - @retval true An error occured. + @retval true An error occurred. @retval false OK. */ @@ -8967,7 +8907,7 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, List<Item> &fields, function. @return Status - @retval true An error occured. + @retval true An error occurred. @retval false OK. */ @@ -8980,6 +8920,9 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values, Item *value; Field *field; bool abort_on_warning_saved= thd->abort_on_warning; + uint autoinc_index= table->next_number_field + ? table->next_number_field->field_index + : ~0U; DBUG_ENTER("fill_record"); if (!*ptr) @@ -9005,7 +8948,7 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values, DBUG_ASSERT(field->table == table); value=v++; - if (field == table->next_number_field) + if (field->field_index == autoinc_index) table->auto_increment_field_not_null= TRUE; if (field->vcol_info && value->type() != Item::DEFAULT_VALUE_ITEM && @@ -9059,7 +9002,7 @@ err: record[1] buffers correspond to new and old versions of row respectively. @return Status - @retval true An error occured. + @retval true An error occurred. @retval false OK. */ @@ -9284,98 +9227,6 @@ bool is_equal(const LEX_STRING *a, const LEX_STRING *b) return a->length == b->length && !strncmp(a->str, b->str, a->length); } - -/* - Tells if two (or more) tables have auto_increment columns and we want to - lock those tables with a write lock. - - SYNOPSIS - has_two_write_locked_tables_with_auto_increment - tables Table list - - NOTES: - Call this function only when you have established the list of all tables - which you'll want to update (including stored functions, triggers, views - inside your statement). -*/ - -static bool -has_write_table_with_auto_increment(TABLE_LIST *tables) -{ - for (TABLE_LIST *table= tables; table; table= table->next_global) - { - /* we must do preliminary checks as table->table may be NULL */ - if (!table->placeholder() && - table->table->found_next_number_field && - (table->lock_type >= TL_WRITE_ALLOW_WRITE)) - return 1; - } - - return 0; -} - -/* - checks if we have select tables in the table list and write tables - with auto-increment column. - - SYNOPSIS - has_two_write_locked_tables_with_auto_increment_and_select - tables Table list - - RETURN VALUES - - -true if the table list has atleast one table with auto-increment column - - - and atleast one table to select from. - -false otherwise -*/ - -static bool -has_write_table_with_auto_increment_and_select(TABLE_LIST *tables) -{ - bool has_select= false; - bool has_auto_increment_tables = has_write_table_with_auto_increment(tables); - for(TABLE_LIST *table= tables; table; table= table->next_global) - { - if (!table->placeholder() && - (table->lock_type <= TL_READ_NO_INSERT)) - { - has_select= true; - break; - } - } - return(has_select && has_auto_increment_tables); -} - -/* - Tells if there is a table whose auto_increment column is a part - of a compound primary key while is not the first column in - the table definition. - - @param tables Table list - - @return true if the table exists, fais if does not. -*/ - -static bool -has_write_table_auto_increment_not_first_in_pk(TABLE_LIST *tables) -{ - for (TABLE_LIST *table= tables; table; table= table->next_global) - { - /* we must do preliminary checks as table->table may be NULL */ - if (!table->placeholder() && - table->table->found_next_number_field && - (table->lock_type >= TL_WRITE_ALLOW_WRITE) - && table->table->s->next_number_keypart != 0) - return 1; - } - - return 0; -} - - - /* Open and lock system tables for read. diff --git a/sql/sql_base.h b/sql/sql_base.h index 58cd18321b7..24a7c7a5a2e 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -267,7 +267,6 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags, uint dt_phases); bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags); int decide_logging_format(THD *thd, TABLE_LIST *tables); -void free_io_cache(TABLE *entry); void intern_close_table(TABLE *entry); void kill_delayed_threads_for_table(TDC_element *element); void close_thread_table(THD *thd, TABLE **table_ptr); @@ -305,16 +304,7 @@ 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); -bool tdc_open_view(THD *thd, TABLE_LIST *table_list, const char *alias, - const char *cache_key, uint cache_key_length, uint flags); - -static inline bool tdc_open_view(THD *thd, TABLE_LIST *table_list, - const char *alias, uint flags) -{ - const char *key; - uint key_length= get_table_def_key(table_list, &key); - return tdc_open_view(thd, table_list, alias, key, key_length, flags); -} +bool tdc_open_view(THD *thd, TABLE_LIST *table_list, uint flags); TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db, const char *table_name, diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 03505dec0cf..91dd8ad7325 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1933,6 +1933,13 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", (int)flags.autocommit)); memcpy((uchar *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)), (uchar*) &flags, QUERY_CACHE_FLAGS_SIZE); + +#ifdef WITH_WSREP + bool once_more; + once_more= true; +lookup: +#endif /* WITH_WSREP */ + query_block = (Query_cache_block *) my_hash_search(&queries, (uchar*) sql, tot_length); /* Quick abort on unlocked data */ @@ -1945,6 +1952,19 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", } DBUG_PRINT("qcache", ("Query in query hash 0x%lx", (ulong)query_block)); +#ifdef WITH_WSREP + if (once_more && WSREP_CLIENT(thd) && wsrep_must_sync_wait(thd)) + { + unlock(); + if (wsrep_sync_wait(thd)) + goto err; + if (try_lock(thd, Query_cache::TIMEOUT)) + goto err; + once_more= false; + goto lookup; + } +#endif /* WITH_WSREP */ + /* Now lock and test that nothing changed while blocks was unlocked */ BLOCK_LOCK_RD(query_block); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c5ad66200c8..e3b70566597 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2008, 2015, MariaDB + Copyright (c) 2008, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -702,12 +702,6 @@ extern "C" @param length length of buffer @param max_query_len how many chars of query to copy (0 for all) - @req LOCK_thread_count - - @note LOCK_thread_count mutex is not necessary when the function is invoked on - the currently running thread (current_thd) or if the caller in some other - way guarantees that access to thd->query is serialized. - @return Pointer to string */ @@ -902,7 +896,7 @@ THD::THD(bool is_wsrep_applier) wsrep_po_handle(WSREP_PO_INITIALIZER), wsrep_po_cnt(0), wsrep_apply_format(0), - wsrep_skip_append_keys(false) + wsrep_ignore_table(false) #endif { ulong tmp; @@ -953,7 +947,7 @@ THD::THD(bool is_wsrep_applier) // Must be reset to handle error with THD's created for init of mysqld lex->current_select= 0; user_time.val= start_time= start_time_sec_part= 0; - start_utime= utime_after_query= prior_thr_create_utime= 0L; + start_utime= utime_after_query= 0; utime_after_lock= 0L; progress.arena= 0; progress.report_to_client= 0; @@ -1027,6 +1021,7 @@ THD::THD(bool is_wsrep_applier) wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; wsrep_info[sizeof(wsrep_info) - 1] = '\0'; /* make sure it is 0-terminated */ + wsrep_sync_wait_gtid = WSREP_GTID_UNDEFINED; #endif /* Call to init() below requires fully initialized Open_tables_state. */ reset_open_tables_state(this); @@ -1378,6 +1373,12 @@ extern "C" THD *_current_thd_noinline(void) { return my_pthread_getspecific_ptr(THD*,THR_THD); } + +extern "C" my_thread_id next_thread_id_noinline() +{ +#undef next_thread_id + return next_thread_id(); +} #endif /* @@ -1425,6 +1426,7 @@ void THD::init(void) bzero((char *) &org_status_var, sizeof(org_status_var)); start_bytes_received= 0; last_commit_gtid.seq_no= 0; + last_stmt= NULL; status_in_global= 0; #ifdef WITH_WSREP wsrep_exec_mode= wsrep_applier ? REPL_RECV : LOCAL_STATE; @@ -1441,7 +1443,8 @@ void THD::init(void) wsrep_mysql_replicated = 0; wsrep_TOI_pre_query = NULL; wsrep_TOI_pre_query_len = 0; -#endif + wsrep_sync_wait_gtid = WSREP_GTID_UNDEFINED; +#endif /* WITH_WSREP */ if (variables.sql_log_bin) variables.option_bits|= OPTION_BIN_LOG; @@ -1628,6 +1631,10 @@ THD::~THD() THD *orig_thd= current_thd; THD_CHECK_SENTRY(this); DBUG_ENTER("~THD()"); + /* Check that we have already called thd->unlink() */ + DBUG_ASSERT(prev == 0 && next == 0); + /* This takes a long time so we should not do this under LOCK_thread_count */ + mysql_mutex_assert_not_owner(&LOCK_thread_count); /* In error cases, thd may not be current thd. We have to fix this so @@ -1699,8 +1706,9 @@ THD::~THD() if (status_var.local_memory_used != 0) { DBUG_PRINT("error", ("memory_used: %lld", status_var.local_memory_used)); - SAFEMALLOC_REPORT_MEMORY(my_thread_dbug_id()); - DBUG_ASSERT(status_var.local_memory_used == 0); + SAFEMALLOC_REPORT_MEMORY(thread_id); + DBUG_ASSERT(status_var.local_memory_used == 0 || + !debug_assert_on_not_freed_memory); } set_current_thd(orig_thd == this ? 0 : orig_thd); @@ -1817,7 +1825,8 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, void THD::awake(killed_state state_to_set) { DBUG_ENTER("THD::awake"); - DBUG_PRINT("enter", ("this: %p current_thd: %p", this, current_thd)); + DBUG_PRINT("enter", ("this: %p current_thd: %p state: %d", + this, current_thd, (int) state_to_set)); THD_CHECK_SENTRY(this); mysql_mutex_assert_owner(&LOCK_thd_data); @@ -2199,6 +2208,10 @@ void THD::cleanup_after_query() rgi_slave->cleanup_after_query(); #endif +#ifdef WITH_WSREP + wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED; +#endif /* WITH_WSREP */ + DBUG_VOID_RETURN; } @@ -4024,6 +4037,12 @@ void thd_increment_bytes_sent(void *thd, ulong length) } } +my_bool thd_net_is_killed() +{ + THD *thd= current_thd; + return thd && thd->killed ? 1 : 0; +} + void thd_increment_bytes_received(void *thd, ulong length) { @@ -4066,7 +4085,7 @@ void Security_context::destroy() // If not pointer to constant if (host != my_localhost) { - my_free(host); + my_free((char*) host); host= NULL; } if (user != delayed_user) @@ -4329,7 +4348,7 @@ extern "C" void thd_progress_init(MYSQL_THD thd, uint max_stage) is a high level command (like ALTER TABLE) and we are not in a stored procedure */ - thd->progress.report= ((thd->client_capabilities & CLIENT_PROGRESS) && + thd->progress.report= ((thd->client_capabilities & MARIADB_CLIENT_PROGRESS) && thd->progress.report_to_client && !thd->in_sub_stmt); thd->progress.next_report_time= 0; @@ -5158,9 +5177,7 @@ void THD::get_definer(LEX_USER *definer, bool role) { definer->user = invoker_user; definer->host= invoker_host; - definer->password= null_lex_str; - definer->plugin= empty_lex_str; - definer->auth= empty_lex_str; + definer->reset_auth(); } else #endif @@ -5441,6 +5458,94 @@ int xid_cache_iterate(THD *thd, my_hash_walk_action action, void *arg) &argument); } +/* + Tells if two (or more) tables have auto_increment columns and we want to + lock those tables with a write lock. + + SYNOPSIS + has_two_write_locked_tables_with_auto_increment + tables Table list + + NOTES: + Call this function only when you have established the list of all tables + which you'll want to update (including stored functions, triggers, views + inside your statement). +*/ + +static bool +has_write_table_with_auto_increment(TABLE_LIST *tables) +{ + for (TABLE_LIST *table= tables; table; table= table->next_global) + { + /* we must do preliminary checks as table->table may be NULL */ + if (!table->placeholder() && + table->table->found_next_number_field && + (table->lock_type >= TL_WRITE_ALLOW_WRITE)) + return 1; + } + + return 0; +} + +/* + checks if we have select tables in the table list and write tables + with auto-increment column. + + SYNOPSIS + has_two_write_locked_tables_with_auto_increment_and_select + tables Table list + + RETURN VALUES + + -true if the table list has atleast one table with auto-increment column + + + and atleast one table to select from. + -false otherwise +*/ + +static bool +has_write_table_with_auto_increment_and_select(TABLE_LIST *tables) +{ + bool has_select= false; + bool has_auto_increment_tables = has_write_table_with_auto_increment(tables); + for(TABLE_LIST *table= tables; table; table= table->next_global) + { + if (!table->placeholder() && + (table->lock_type <= TL_READ_NO_INSERT)) + { + has_select= true; + break; + } + } + return(has_select && has_auto_increment_tables); +} + +/* + Tells if there is a table whose auto_increment column is a part + of a compound primary key while is not the first column in + the table definition. + + @param tables Table list + + @return true if the table exists, fais if does not. +*/ + +static bool +has_write_table_auto_increment_not_first_in_pk(TABLE_LIST *tables) +{ + for (TABLE_LIST *table= tables; table; table= table->next_global) + { + /* we must do preliminary checks as table->table may be NULL */ + if (!table->placeholder() && + table->table->found_next_number_field && + (table->lock_type >= TL_WRITE_ALLOW_WRITE) + && table->table->s->next_number_keypart != 0) + return 1; + } + + return 0; +} /** Decide on logging format to use for the statement and issue errors @@ -5625,6 +5730,31 @@ int THD::decide_logging_format(TABLE_LIST *tables) } #endif + if (wsrep_binlog_format() != BINLOG_FORMAT_ROW && tables) + { + /* + DML statements that modify a table with an auto_increment column based on + rows selected from a table are unsafe as the order in which the rows are + fetched fron the select tables cannot be determined and may differ on + master and slave. + */ + if (has_write_table_with_auto_increment_and_select(tables)) + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT); + + if (has_write_table_auto_increment_not_first_in_pk(tables)) + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST); + + /* + A query that modifies autoinc column in sub-statement can make the + master and slave inconsistent. + We can solve these problems in mixed mode by switching to binlogging + if at least one updated table is used by sub-statement + */ + if (lex->requires_prelocking() && + has_write_table_with_auto_increment(lex->first_not_own_table())) + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS); + } + /* Get the capabilities vector for all involved storage engines and mask out the flags for the binary log. diff --git a/sql/sql_class.h b/sql/sql_class.h index 1365642b4fb..f2b8481ff7f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -695,6 +695,7 @@ typedef struct system_status_var ulong com_create_tmp_table; ulong com_drop_tmp_table; ulong com_other; + ulong com_multi; ulong com_stmt_prepare; ulong com_stmt_reprepare; @@ -704,6 +705,7 @@ typedef struct system_status_var ulong com_stmt_reset; ulong com_stmt_close; + ulong com_register_slave; ulong created_tmp_disk_tables_; ulong created_tmp_tables_; ulong ha_commit_count; @@ -1184,7 +1186,8 @@ public: priv_user - The user privilege we are using. May be "" for anonymous user. ip - client IP */ - char *host, *user, *ip; + const char *host; + char *user, *ip; char priv_user[USERNAME_LENGTH]; char proxy_user[USERNAME_LENGTH + MAX_HOSTNAME + 5]; /* The host privilege we are using */ @@ -1411,7 +1414,7 @@ public: Discrete_intervals_list auto_inc_intervals_forced; ulonglong limit_found_rows; ha_rows cuted_fields, sent_row_count, examined_row_count; - ulong client_capabilities; + ulonglong client_capabilities; ulong query_plan_flags; uint in_sub_stmt; bool enable_slow_log; @@ -1962,6 +1965,13 @@ public: /* all prepared statements and cursors of this connection */ Statement_map stmt_map; + + /* Last created prepared statement */ + Statement *last_stmt; + inline void set_last_stmt(Statement *stmt) + { last_stmt= (is_error() ? NULL : stmt); } + inline void clear_last_stmt() { last_stmt= NULL; } + /* A pointer to the stack frame of handle_one_connection(), which is called first in the thread for handling a client @@ -2044,7 +2054,7 @@ public: /* Needed by MariaDB semi sync replication */ Trans_binlog_info *semisync_info; - ulong client_capabilities; /* What the client supports */ + ulonglong client_capabilities; /* What the client supports */ ulong max_client_packet_length; HASH handler_tables_hash; @@ -2086,7 +2096,7 @@ public: bool report_to_client; /* true, if we will send progress report packets to a client - (client has requested them, see CLIENT_PROGRESS; report_to_client + (client has requested them, see MARIADB_CLIENT_PROGRESS; report_to_client is true; not in sub-statement) */ bool report; @@ -2177,7 +2187,7 @@ public: int is_current_stmt_binlog_format_row() const { DBUG_ASSERT(current_stmt_binlog_format == BINLOG_FORMAT_STMT || current_stmt_binlog_format == BINLOG_FORMAT_ROW); - return WSREP_FORMAT(current_stmt_binlog_format) == BINLOG_FORMAT_ROW; + return current_stmt_binlog_format == BINLOG_FORMAT_ROW; } enum binlog_filter_state @@ -3990,7 +4000,13 @@ public: #endif /* GTID_SUPPORT */ void *wsrep_apply_format; char wsrep_info[128]; /* string for dynamic proc info */ - bool wsrep_skip_append_keys; + /* + When enabled, do not replicate/binlog updates from the current table that's + being processed. At the moment, it is used to keep mysql.gtid_slave_pos + table updates from being replicated to other nodes via galera replication. + */ + bool wsrep_ignore_table; + wsrep_gtid_t wsrep_sync_wait_gtid; #endif /* WITH_WSREP */ /* Handling of timeouts for commands */ @@ -4026,8 +4042,41 @@ public: { main_lex.restore_set_statement_var(); } + + /* + Reset current_linfo + Setting current_linfo to 0 needs to be done with LOCK_thread_count to + ensure that adjust_linfo_offsets doesn't use a structure that may + be deleted. + */ + inline void reset_current_linfo() + { + mysql_mutex_lock(&LOCK_thread_count); + current_linfo= 0; + mysql_mutex_unlock(&LOCK_thread_count); + } }; +inline void add_to_active_threads(THD *thd) +{ + mysql_mutex_lock(&LOCK_thread_count); + threads.append(thd); + mysql_mutex_unlock(&LOCK_thread_count); +} + +/* + This should be called when you want to delete a thd that was not + running any queries. + This function will assert if the THD was not linked. +*/ + +inline void unlink_not_visible_thd(THD *thd) +{ + thd->assert_if_linked(); + mysql_mutex_lock(&LOCK_thread_count); + thd->unlink(); + mysql_mutex_unlock(&LOCK_thread_count); +} /** A short cut for thd->get_stmt_da()->set_ok_status(). */ @@ -4460,10 +4509,14 @@ public: #define TMP_ENGINE_COLUMNDEF MARIA_COLUMNDEF #define TMP_ENGINE_HTON maria_hton #define TMP_ENGINE_NAME "Aria" +inline uint tmp_table_max_key_length() { return maria_max_key_length(); } +inline uint tmp_table_max_key_parts() { return maria_max_key_segments(); } #else #define TMP_ENGINE_COLUMNDEF MI_COLUMNDEF #define TMP_ENGINE_HTON myisam_hton #define TMP_ENGINE_NAME "MyISAM" +inline uint tmp_table_max_key_length() { return MI_MAX_KEY_LENGTH; } +inline uint tmp_table_max_key_parts() { return MI_MAX_KEY_SEG; } #endif /* @@ -4511,8 +4564,6 @@ public: uint hidden_field_count; uint group_parts,group_length,group_null_parts; uint quick_group; - /* If >0 convert all blob fields to varchar(convert_blob_length) */ - uint convert_blob_length; /** Enabled when we have atleast one outer_sum_func. Needed when used along with distinct. @@ -4548,7 +4599,7 @@ public: TMP_TABLE_PARAM() :copy_field(0), group_parts(0), - group_length(0), group_null_parts(0), convert_blob_length(0), + group_length(0), group_null_parts(0), using_outer_summary_function(0), schema_table(0), materialized_subquery(0), force_not_null_cols(0), precomputed_group_by(0), @@ -4973,85 +5024,7 @@ class user_var_entry user_var_entry *get_variable(HASH *hash, LEX_STRING &name, bool create_if_not_exists); -/* - Unique -- class for unique (removing of duplicates). - Puts all values to the TREE. If the tree becomes too big, - it's dumped to the file. User can request sorted values, or - just iterate through them. In the last case tree merging is performed in - memory simultaneously with iteration, so it should be ~2-3x faster. - */ - -class Unique :public Sql_alloc -{ - DYNAMIC_ARRAY file_ptrs; - ulong max_elements; - ulonglong max_in_memory_size; - IO_CACHE file; - TREE tree; - uchar *record_pointers; - ulong filtered_out_elems; - bool flush(); - uint size; - uint full_size; - uint min_dupl_count; /* always 0 for unions, > 0 for intersections */ - bool with_counters; - - bool merge(TABLE *table, uchar *buff, bool without_last_merge); - -public: - ulong elements; - Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg, - uint size_arg, ulonglong max_in_memory_size_arg, - uint min_dupl_count_arg= 0); - ~Unique(); - ulong elements_in_tree() { return tree.elements_in_tree; } - inline bool unique_add(void *ptr) - { - DBUG_ENTER("unique_add"); - DBUG_PRINT("info", ("tree %u - %lu", tree.elements_in_tree, max_elements)); - if (!(tree.flag & TREE_ONLY_DUPS) && - tree.elements_in_tree >= max_elements && flush()) - DBUG_RETURN(1); - DBUG_RETURN(!tree_insert(&tree, ptr, 0, tree.custom_arg)); - } - - bool is_in_memory() { return (my_b_tell(&file) == 0); } - void close_for_expansion() { tree.flag= TREE_ONLY_DUPS; } - - bool get(TABLE *table); - - /* Cost of searching for an element in the tree */ - inline static double get_search_cost(ulonglong tree_elems, uint compare_factor) - { - return log((double) tree_elems) / (compare_factor * M_LN2); - } - - static double get_use_cost(uint *buffer, size_t nkeys, uint key_size, - ulonglong max_in_memory_size, uint compare_factor, - bool intersect_fl, bool *in_memory); - inline static int get_cost_calc_buff_size(size_t nkeys, uint key_size, - ulonglong max_in_memory_size) - { - register ulonglong max_elems_in_tree= - max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size); - return (int) (sizeof(uint)*(1 + nkeys/max_elems_in_tree)); - } - - void reset(); - bool walk(TABLE *table, tree_walk_action action, void *walk_action_arg); - - uint get_size() const { return size; } - ulonglong get_max_in_memory_size() const { return max_in_memory_size; } - - friend int unique_write_to_file(uchar* key, element_count count, Unique *unique); - friend int unique_write_to_ptrs(uchar* key, element_count count, Unique *unique); - - friend int unique_write_to_file_with_count(uchar* key, element_count count, - Unique *unique); - friend int unique_intersect_write_to_ptrs(uchar* key, element_count count, - Unique *unique); -}; - +class SORT_INFO; class multi_delete :public select_result_interceptor { @@ -5079,7 +5052,7 @@ public: int send_data(List<Item> &items); bool initialize_tables (JOIN *join); int do_deletes(); - int do_table_deletes(TABLE *table, bool ignore); + int do_table_deletes(TABLE *table, SORT_INFO *sort_info, bool ignore); bool send_eof(); inline ha_rows num_deleted() { @@ -5319,6 +5292,10 @@ public: Do not check that wsrep snapshot is ready before allowing this command */ #define CF_SKIP_WSREP_CHECK (1U << 2) +/** + Do not allow it for COM_MULTI batch +*/ +#define CF_NO_COM_MULTI (1U << 3) /* Inline functions */ diff --git a/sql/sql_cmd.h b/sql/sql_cmd.h index 904578134b4..92b74bb88ab 100644 --- a/sql/sql_cmd.h +++ b/sql/sql_cmd.h @@ -93,6 +93,8 @@ enum enum_sql_command { SQLCOM_CREATE_ROLE, SQLCOM_DROP_ROLE, SQLCOM_GRANT_ROLE, SQLCOM_REVOKE_ROLE, SQLCOM_COMPOUND, SQLCOM_SHOW_GENERIC, + SQLCOM_ALTER_USER, + SQLCOM_SHOW_CREATE_USER, /* When a command is added here, be sure it's also added in mysqld.cc diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 7821b96b9bb..ea114bf40a5 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -827,14 +827,17 @@ bool thd_init_client_charset(THD *thd, uint cs_number) Initialize connection threads */ +#ifndef EMBEDDED_LIBRARY bool init_new_connection_handler_thread() { pthread_detach_this_thread(); if (my_thread_init()) { + statistic_increment(aborted_connects,&LOCK_status); statistic_increment(connection_errors_internal, &LOCK_status); return 1; } + DBUG_EXECUTE_IF("simulate_failed_connection_1", return(1); ); return 0; } @@ -850,7 +853,6 @@ bool init_new_connection_handler_thread() 1 error */ -#ifndef EMBEDDED_LIBRARY static int check_connection(THD *thd) { uint connect_errors= 0; @@ -951,6 +953,7 @@ static int check_connection(THD *thd) this is treated as a global server OOM error. TODO: remove the need for my_strdup. */ + statistic_increment(aborted_connects,&LOCK_status); statistic_increment(connection_errors_internal, &LOCK_status); return 1; /* The error is set by my_strdup(). */ } @@ -968,7 +971,7 @@ static int check_connection(THD *thd) if (thd->main_security_ctx.host) { if (thd->main_security_ctx.host != my_localhost) - thd->main_security_ctx.host[MY_MIN(strlen(thd->main_security_ctx.host), + ((char*) thd->main_security_ctx.host)[MY_MIN(strlen(thd->main_security_ctx.host), HOSTNAME_LENGTH)]= 0; thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host; } @@ -1016,6 +1019,7 @@ static int check_connection(THD *thd) Hence, there is no reason to account on OOM conditions per client IP, we count failures in the global server status instead. */ + statistic_increment(aborted_connects,&LOCK_status); statistic_increment(connection_errors_internal, &LOCK_status); return 1; /* The error is set by alloc(). */ } @@ -1054,7 +1058,8 @@ bool setup_connection_thread_globals(THD *thd) { close_connection(thd, ER_OUT_OF_RESOURCES); statistic_increment(aborted_connects,&LOCK_status); - MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0)); + statistic_increment(connection_errors_internal, &LOCK_status); + thd->scheduler->end_thread(thd, 0); return 1; // Error } return 0; @@ -1082,7 +1087,7 @@ bool login_connection(THD *thd) int error= 0; DBUG_ENTER("login_connection"); DBUG_PRINT("info", ("login_connection called by thread %lu", - thd->thread_id)); + (ulong) thd->thread_id)); /* Use "connect_timeout" value during connection phase */ my_net_set_read_timeout(net, connect_timeout); @@ -1134,8 +1139,8 @@ void end_connection(THD *thd) { wsrep_status_t rcode= wsrep->free_connection(wsrep, thd->thread_id); if (rcode) { - WSREP_WARN("wsrep failed to free connection context: %lu, code: %d", - thd->thread_id, rcode); + WSREP_WARN("wsrep failed to free connection context: %lld code: %d", + (longlong) thd->thread_id, rcode); } } thd->wsrep_client_thread= 0; @@ -1254,11 +1259,11 @@ void prepare_new_connection_state(THD* thd) pthread_handler_t handle_one_connection(void *arg) { - THD *thd= (THD*) arg; + CONNECT *connect= (CONNECT*) arg; - mysql_thread_set_psi_id(thd->thread_id); + mysql_thread_set_psi_id(connect->thread_id); - do_handle_one_connection(thd); + do_handle_one_connection(connect); return 0; } @@ -1290,19 +1295,17 @@ bool thd_is_connection_alive(THD *thd) return FALSE; } -void do_handle_one_connection(THD *thd_arg) -{ - THD *thd= thd_arg; - - thd->thr_create_utime= microsecond_interval_timer(); - /* We need to set this because of time_out_user_resource_limits */ - thd->start_utime= thd->thr_create_utime; - if (MYSQL_CALLBACK_ELSE(thd->scheduler, init_new_connection_thread, (), 0)) +void do_handle_one_connection(CONNECT *connect) +{ + ulonglong thr_create_utime= microsecond_interval_timer(); + THD *thd; + if (connect->scheduler->init_new_connection_thread() || + !(thd= connect->create_thd())) { - close_connection(thd, ER_OUT_OF_RESOURCES); - statistic_increment(aborted_connects,&LOCK_status); - MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0)); + scheduler_functions *scheduler= connect->scheduler; + connect->close_with_error(0, 0, ER_OUT_OF_RESOURCES); + scheduler->end_thread(0, 0); return; } @@ -1311,14 +1314,22 @@ void do_handle_one_connection(THD *thd_arg) increment slow_launch_threads counter if it took more than slow_launch_time seconds to create the thread. */ - if (thd->prior_thr_create_utime) + + if (connect->prior_thr_create_utime) { - ulong launch_time= (ulong) (thd->thr_create_utime - - thd->prior_thr_create_utime); + ulong launch_time= (ulong) (thr_create_utime - + connect->prior_thr_create_utime); if (launch_time >= slow_launch_time*1000000L) statistic_increment(slow_launch_threads, &LOCK_status); - thd->prior_thr_create_utime= 0; } + delete connect; + + /* Make THD visible in show processlist */ + add_to_active_threads(thd); + + thd->thr_create_utime= thr_create_utime; + /* We need to set this because of time_out_user_resource_limits */ + thd->start_utime= thr_create_utime; /* handle_one_connection() is normally the only way a thread would @@ -1365,7 +1376,7 @@ end_thread: if (thd->userstat_running) update_global_user_stats(thd, create_user, time(NULL)); - if (MYSQL_CALLBACK_ELSE(thd->scheduler, end_thread, (thd, 1), 0)) + if (thd->scheduler->end_thread(thd, 1)) return; // Probably no-threads /* @@ -1377,3 +1388,110 @@ end_thread: } } #endif /* EMBEDDED_LIBRARY */ + + +/* Handling of CONNECT objects */ + +/* + Close connection without error and delete the connect object + This and close_with_error are only called if we didn't manage to + create a new thd object. +*/ + +void CONNECT::close_and_delete() +{ + DBUG_ENTER("close_and_delete"); + + if (vio) + vio_close(vio); + if (thread_count_incremented) + { + /* + Normally this is handled by THD::unlink. As we haven't yet created + a THD and put it in the thread list, we have to manage counting here. + */ + dec_thread_count(); + dec_connection_count(scheduler); + } + statistic_increment(connection_errors_internal, &LOCK_status); + statistic_increment(aborted_connects,&LOCK_status); + + delete this; + DBUG_VOID_RETURN; +} + +/* + Close a connection with a possible error to the end user + Alse deletes the connection object, like close_and_delete() +*/ + +void CONNECT::close_with_error(uint sql_errno, + const char *message, uint close_error) +{ + THD *thd= create_thd(); + if (thd) + { + if (sql_errno) + net_send_error(thd, sql_errno, message, NULL); + close_connection(thd, close_error); + delete thd; + set_current_thd(0); + if (thread_count_incremented) + { + dec_thread_count(); + dec_connection_count(scheduler); + } + delete this; + statistic_increment(connection_errors_internal, &LOCK_status); + statistic_increment(aborted_connects,&LOCK_status); + } + else + { + /* + Out of memory; We can't generate an error, just close the connection + close_and_delete() will increment statistics. + */ + close_and_delete(); + } +} + + +CONNECT::~CONNECT() +{ + if (vio) + vio_delete(vio); +} + +/* Create a THD based on a CONNECT object */ + +THD *CONNECT::create_thd() +{ + my_bool res; + THD *thd; + DBUG_ENTER("create_thd"); + + DBUG_EXECUTE_IF("simulate_failed_connection_2", DBUG_RETURN(0); ); + + if (!(thd= new THD)) + DBUG_RETURN(0); + + set_current_thd(thd); + res= my_net_init(&thd->net, vio, thd, MYF(MY_THREAD_SPECIFIC)); + vio= 0; // Vio now handled by thd + + if (res) + { + delete thd; + set_current_thd(0); + DBUG_RETURN(0); + } + + init_net_server_extension(thd); + + thd->security_ctx->host= host; + thd->extra_port= extra_port; + thd->scheduler= scheduler; + thd->thread_id= thd->variables.pseudo_thread_id= thread_id; + thd->real_id= real_id; + DBUG_RETURN(thd); +} diff --git a/sql/sql_connect.h b/sql/sql_connect.h index bab171606ba..22a12e845c7 100644 --- a/sql/sql_connect.h +++ b/sql/sql_connect.h @@ -19,8 +19,43 @@ #include "my_sys.h" /* pthread_handler_t */ #include "mysql_com.h" /* enum_server_command */ #include "structs.h" +#include <mysql/psi/mysql_socket.h> #include <hash.h> +/* + Object to hold connect information to be given to the newly created thread +*/ + +struct scheduler_functions; + +class CONNECT : public ilink { +public: + /* To be copied to THD */ + Vio *vio; /* Copied to THD with my_net_init() */ + const char *host; + scheduler_functions *scheduler; + my_thread_id thread_id; + pthread_t real_id; + bool extra_port; + + /* Own variables */ + bool thread_count_incremented; + ulonglong prior_thr_create_utime; + + CONNECT() + :vio(0), host(0), scheduler(thread_scheduler), thread_id(0), real_id(0), + extra_port(0), + thread_count_incremented(0), prior_thr_create_utime(0) + { + }; + ~CONNECT(); + void close_and_delete(); + void close_with_error(uint sql_errno, + const char *message, uint close_error); + THD *create_thd(); +}; + + class THD; typedef struct st_lex_user LEX_USER; typedef struct user_conn USER_CONN; @@ -37,7 +72,7 @@ void free_global_index_stats(void); void free_global_client_stats(void); pthread_handler_t handle_one_connection(void *arg); -void do_handle_one_connection(THD *thd_arg); +void do_handle_one_connection(CONNECT *connect); bool init_new_connection_handler_thread(); void reset_mqh(LEX_USER *lu, bool get_them); bool check_mqh(THD *thd, uint check_command); diff --git a/sql/sql_const.h b/sql/sql_const.h index 76e47bd278b..31ee4603dc9 100644 --- a/sql/sql_const.h +++ b/sql/sql_const.h @@ -235,6 +235,8 @@ that does not respond to "initial server greeting" timely */ #define CONNECT_TIMEOUT 10 + /* Wait 5 minutes before removing thread from thread cache */ +#define THREAD_CACHE_TIMEOUT 5*60 /* The following can also be changed from the command line */ #define DEFAULT_CONCURRENCY 10 diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc new file mode 100644 index 00000000000..1203a4ce0c8 --- /dev/null +++ b/sql/sql_cte.cc @@ -0,0 +1,601 @@ +#include "sql_class.h" +#include "sql_lex.h" +#include "sql_cte.h" +#include "sql_view.h" // for make_valid_column_names +#include "sql_parse.h" + + +/** + @brief + Check dependencies between tables defined in a list of with clauses + + @param + with_clauses_list Pointer to the first clause in the list + + @details + The procedure just calls the method With_clause::check_dependencies + for each member of the given list. + + @retval + false on success + true on failure +*/ + +bool check_dependencies_in_with_clauses(With_clause *with_clauses_list) +{ + for (With_clause *with_clause= with_clauses_list; + with_clause; + with_clause= with_clause->next_with_clause) + { + if (with_clause->check_dependencies()) + return true; + } + return false; +} + + +/** + @brief + Check dependencies between tables defined in this with clause + + @details + The method performs the following actions for this with clause: + + 1. Test for definitions of the tables with the same name. + 2. For each table T defined in this with clause look for tables + from the same with clause that are used in the query that + specifies T and set the dependencies of T on these tables + in dependency_map. + 3. Build the transitive closure of the above direct dependencies + to find out all recursive definitions. + 4. If this with clause is not specified as recursive then + for each with table T defined in this with clause check whether + it is used in any definition that follows the definition of T. + + @retval + true if an error is reported + false otherwise +*/ + +bool With_clause::check_dependencies() +{ + if (dependencies_are_checked) + return false; + /* + Look for for definitions with the same query name. + When found report an error and return true immediately. + For each table T defined in this with clause look for all other tables from + the same with with clause that are used in the specification of T. + For each such table set the dependency bit in the dependency map of + with element for T. + */ + for (With_element *with_elem= first_elem; + with_elem != NULL; + with_elem= with_elem->next_elem) + { + for (With_element *elem= first_elem; + elem != with_elem; + elem= elem->next_elem) + { + if (my_strcasecmp(system_charset_info, with_elem->query_name->str, + elem->query_name->str) == 0) + { + my_error(ER_DUP_QUERY_NAME, MYF(0), with_elem->query_name->str); + return true; + } + } + with_elem->check_dependencies_in_unit(with_elem->spec); + } + /* Build the transitive closure of the direct dependencies found above */ + for (With_element *with_elem= first_elem; + with_elem != NULL; + with_elem= with_elem->next_elem) + { + table_map with_elem_map= with_elem->get_elem_map(); + for (With_element *elem= first_elem; elem != NULL; elem= elem->next_elem) + { + if (elem->dependency_map & with_elem_map) + elem->dependency_map |= with_elem->dependency_map; + } + } + + /* + Mark those elements where tables are defined with direct or indirect recursion. + Report an error when recursion (direct or indirect) is used to define a table. + */ + for (With_element *with_elem= first_elem; + with_elem != NULL; + with_elem= with_elem->next_elem) + { + if (with_elem->dependency_map & with_elem->get_elem_map()) + with_elem->is_recursive= true; + } + for (With_element *with_elem= first_elem; + with_elem != NULL; + with_elem= with_elem->next_elem) + { + if (with_elem->is_recursive) + { + my_error(ER_RECURSIVE_QUERY_IN_WITH_CLAUSE, MYF(0), + with_elem->query_name->str); + return true; + } + } + + if (!with_recursive) + { + /* + For each with table T defined in this with clause check whether + it is used in any definition that follows the definition of T. + */ + for (With_element *with_elem= first_elem; + with_elem != NULL; + with_elem= with_elem->next_elem) + { + With_element *checked_elem= with_elem->next_elem; + for (uint i = with_elem->number+1; + i < elements; + i++, checked_elem= checked_elem->next_elem) + { + if (with_elem->check_dependency_on(checked_elem)) + { + my_error(ER_WRONG_ORDER_IN_WITH_CLAUSE, MYF(0), + with_elem->query_name->str, checked_elem->query_name->str); + return true; + } + } + } + } + + dependencies_are_checked= true; + return false; +} + + +/** + @brief + Check dependencies on the sibling with tables used in the given unit + + @param unit The unit where the siblings are to be searched for + + @details + The method recursively looks through all from lists encountered + the given unit. If it finds a reference to a table that is + defined in the same with clause to which this element belongs + the method set the bit of dependency on this table in the + dependency_map of this element. +*/ + +void With_element::check_dependencies_in_unit(st_select_lex_unit *unit) +{ + st_select_lex *sl= unit->first_select(); + for (; sl; sl= sl->next_select()) + { + for (TABLE_LIST *tbl= sl->table_list.first; tbl; tbl= tbl->next_local) + { + if (!tbl->with) + tbl->with= owner->find_table_def(tbl); + if (!tbl->with && tbl->select_lex) + tbl->with= tbl->select_lex->find_table_def_in_with_clauses(tbl); + if (tbl->with && tbl->with->owner== this->owner) + set_dependency_on(tbl->with); + } + st_select_lex_unit *inner_unit= sl->first_inner_unit(); + for (; inner_unit; inner_unit= inner_unit->next_unit()) + check_dependencies_in_unit(inner_unit); + } +} + + +/** + @brief + Search for the definition of a table among the elements of this with clause + + @param table The reference to the table that is looked for + + @details + The function looks through the elements of this with clause trying to find + the definition of the given table. When it encounters the element with + the same query name as the table's name it returns this element. If no + such definitions are found the function returns NULL. + + @retval + found with element if the search succeeded + NULL - otherwise +*/ + +With_element *With_clause::find_table_def(TABLE_LIST *table) +{ + for (With_element *with_elem= first_elem; + with_elem != NULL; + with_elem= with_elem->next_elem) + { + if (my_strcasecmp(system_charset_info, with_elem->query_name->str, table->table_name) == 0) + { + return with_elem; + } + } + return NULL; +} + + +/** + @brief + Perform context analysis for all unreferenced tables defined in with clause + + @param thd The context of the statement containing this with clause + + @details + For each unreferenced table T defined in this with clause the method + calls the method With_element::prepare_unreferenced that performs + context analysis of the element with the definition of T. + + @retval + false If context analysis does not report any error + true Otherwise +*/ + +bool With_clause::prepare_unreferenced_elements(THD *thd) +{ + for (With_element *with_elem= first_elem; + with_elem != NULL; + with_elem= with_elem->next_elem) + { + if (!with_elem->is_referenced() && with_elem->prepare_unreferenced(thd)) + return true; + } + + return false; +} + + +/** + @brief + Save the specification of the given with table as a string + + @param thd The context of the statement containing this with element + @param spec_start The beginning of the specification in the input string + @param spec_end The end of the specification in the input string + + @details + The method creates for a string copy of the specification used in this element. + The method is called when the element is parsed. The copy may be used to + create clones of the specification whenever they are needed. + + @retval + false on success + true on failure +*/ + +bool With_element::set_unparsed_spec(THD *thd, char *spec_start, char *spec_end) +{ + unparsed_spec.length= spec_end - spec_start; + unparsed_spec.str= (char*) thd->memdup(spec_start, unparsed_spec.length+1); + unparsed_spec.str[unparsed_spec.length]= '\0'; + + if (!unparsed_spec.str) + { + my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), + static_cast<int>(unparsed_spec.length)); + return true; + } + return false; +} + + +/** + @brief + Create a clone of the specification for the given with table + + @param thd The context of the statement containing this with element + @param with_table The reference to the table defined in this element for which + the clone is created. + + @details + The method creates a clone of the specification used in this element. + The clone is created for the given reference to the table defined by + this element. + The clone is created when the string with the specification saved in + unparsed_spec is fed into the parser as an input string. The parsing + this string a unit object representing the specification is build. + A chain of all table references occurred in the specification is also + formed. + The method includes the new unit and its sub-unit into hierarchy of + the units of the main query. I also insert the constructed chain of the + table references into the chain of all table references of the main query. + + @note + Clones is created only for not first references to tables defined in + the with clause. They are necessary for merged specifications because + the optimizer handles any such specification as independent on the others. + When a table defined in the with clause is materialized in a temporary table + one could do without specification clones. However in this case they + are created as well, because currently different table references to a + the same temporary table cannot share the same definition structure. + + @retval + pointer to the built clone if succeeds + NULL - otherwise +*/ + +st_select_lex_unit *With_element::clone_parsed_spec(THD *thd, + TABLE_LIST *with_table) +{ + LEX *lex; + st_select_lex_unit *res= NULL; + Query_arena backup; + Query_arena *arena= thd->activate_stmt_arena_if_needed(&backup); + + if (!(lex= (LEX*) new(thd->mem_root) st_lex_local)) + { + if (arena) + thd->restore_active_arena(arena, &backup); + return res; + } + LEX *old_lex= thd->lex; + thd->lex= lex; + + bool parse_status= false; + Parser_state parser_state; + TABLE_LIST *spec_tables; + TABLE_LIST *spec_tables_tail; + st_select_lex *with_select; + + if (parser_state.init(thd, unparsed_spec.str, unparsed_spec.length)) + goto err; + lex_start(thd); + with_select= &lex->select_lex; + with_select->select_number= ++thd->select_number; + parse_status= parse_sql(thd, &parser_state, 0); + if (parse_status) + goto err; + spec_tables= lex->query_tables; + spec_tables_tail= 0; + for (TABLE_LIST *tbl= spec_tables; + tbl; + tbl= tbl->next_global) + { + tbl->grant.privilege= with_table->grant.privilege; + spec_tables_tail= tbl; + } + if (spec_tables) + { + if (with_table->next_global) + { + spec_tables_tail->next_global= with_table->next_global; + with_table->next_global->prev_global= &spec_tables_tail->next_global; + } + else + { + old_lex->query_tables_last= &spec_tables_tail->next_global; + } + spec_tables->prev_global= &with_table->next_global; + with_table->next_global= spec_tables; + } + res= &lex->unit; + + lex->unit.include_down(with_table->select_lex); + lex->unit.set_slave(with_select); + old_lex->all_selects_list= + (st_select_lex*) (lex->all_selects_list-> + insert_chain_before( + (st_select_lex_node **) &(old_lex->all_selects_list), + with_select)); + lex_end(lex); +err: + if (arena) + thd->restore_active_arena(arena, &backup); + thd->lex= old_lex; + return res; +} + + +/** + @brief + Rename columns of the unit derived from the spec of this with element + @param thd The context of the statement containing the with element + @param unit The specification of the with element or its clone + + @details + The method assumes that the parameter unit is either specification itself + of this with element or a clone of this specification. The looks through + the column list in this with element. It reports an error if the cardinality + of this list differs from the cardinality of select lists in 'unit'. + Otherwise it renames the columns of the first select list and sets the flag + unit->column_list_is_processed to true preventing renaming columns for the + second time. + + @retval + true if an error was reported + false otherwise +*/ + +bool +With_element::rename_columns_of_derived_unit(THD *thd, + st_select_lex_unit *unit) +{ + if (unit->columns_are_renamed) + return false; + + st_select_lex *select= unit->first_select(); + + if (column_list.elements) // The column list is optional + { + List_iterator_fast<Item> it(select->item_list); + List_iterator_fast<LEX_STRING> nm(column_list); + Item *item; + LEX_STRING *name; + + if (column_list.elements != select->item_list.elements) + { + my_error(ER_WITH_COL_WRONG_LIST, MYF(0)); + return true; + } + /* Rename the columns of the first select in the unit */ + while ((item= it++, name= nm++)) + { + item->set_name(thd, name->str, (uint) name->length, system_charset_info); + item->is_autogenerated_name= false; + } + } + + make_valid_column_names(thd, select->item_list); + + unit->columns_are_renamed= true; + + return false; +} + + +/** + @brief + Perform context analysis the definition of an unreferenced table + + @param thd The context of the statement containing this with element + + @details + The method assumes that this with element contains the definition + of a table that is not used anywhere. In this case one has to check + that context conditions are met. + + @retval + true if an error was reported + false otherwise +*/ + +bool With_element::prepare_unreferenced(THD *thd) +{ + bool rc= false; + st_select_lex *first_sl= spec->first_select(); + + /* Prevent name resolution for field references out of with elements */ + for (st_select_lex *sl= first_sl; + sl; + sl= sl->next_select()) + sl->context.outer_context= 0; + + thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED; + if (!spec->prepared && + (spec->prepare(thd, 0, 0) || + rename_columns_of_derived_unit(thd, spec) || + check_duplicate_names(thd, first_sl->item_list, 1))) + rc= true; + + thd->lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED; + return rc; +} + + +/** + @brief + Search for the definition of the given table referred in this select node + + @param table reference to the table whose definition is searched for + + @details + The method looks for the definition the table whose reference is occurred + in the FROM list of this select node. First it searches for it in the + with clause attached to the unit this select node belongs to. If such a + definition is not found there the embedding units are looked through. + + @retval + pointer to the found definition if the search has been successful + NULL - otherwise +*/ + +With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) +{ + With_element *found= NULL; + for (st_select_lex *sl= this; + sl; + sl= sl->master_unit()->outer_select()) + { + With_clause *with_clause=sl->get_with_clause(); + if (with_clause && (found= with_clause->find_table_def(table))) + return found; + } + return found; +} + + +/** + @brief + Set the specifying unit in this reference to a with table + + @details + The method assumes that the given element with_elem defines the table T + this table reference refers to. + If this is the first reference to T the method just sets its specification + in the field 'derived' as the unit that yields T. Otherwise the method + first creates a clone specification and sets rather this clone in this field. + + @retval + false on success + true on failure +*/ + +bool TABLE_LIST::set_as_with_table(THD *thd, With_element *with_elem) +{ + with= with_elem; + if (!with_elem->is_referenced()) + derived= with_elem->spec; + else + { + if(!(derived= with_elem->clone_parsed_spec(thd, this))) + return true; + derived->with_element= with_elem; + } + with_elem->inc_references(); + return false; +} + + +/** + @brief + Print this with clause + + @param str Where to print to + @param query_type The mode of printing + + @details + The method prints a string representation of this clause in the + string str. The parameter query_type specifies the mode of printing. +*/ + +void With_clause::print(String *str, enum_query_type query_type) +{ + str->append(STRING_WITH_LEN("WITH ")); + if (with_recursive) + str->append(STRING_WITH_LEN("RECURSIVE ")); + for (With_element *with_elem= first_elem; + with_elem != NULL; + with_elem= with_elem->next_elem) + { + with_elem->print(str, query_type); + if (with_elem != first_elem) + str->append(", "); + } +} + + +/** + @brief + Print this with element + + @param str Where to print to + @param query_type The mode of printing + + @details + The method prints a string representation of this with element in the + string str. The parameter query_type specifies the mode of printing. +*/ + +void With_element::print(String *str, enum_query_type query_type) +{ + str->append(query_name); + str->append(STRING_WITH_LEN(" AS ")); + str->append('('); + spec->print(str, query_type); + str->append(')'); +} + diff --git a/sql/sql_cte.h b/sql/sql_cte.h new file mode 100644 index 00000000000..0cbc9247af9 --- /dev/null +++ b/sql/sql_cte.h @@ -0,0 +1,178 @@ +#ifndef SQL_CTE_INCLUDED +#define SQL_CTE_INCLUDED +#include "sql_list.h" +#include "sql_lex.h" + +class With_clause; + +/** + @class With_clause + @brief Set of with_elements + + It has a reference to the first with element from this with clause. + This reference allows to navigate through all the elements of the with clause. + It contains a reference to the unit to which this with clause is attached. + It also contains a flag saying whether this with clause was specified as recursive. +*/ + +class With_element : public Sql_alloc +{ +private: + With_clause *owner; // with clause this object belongs to + With_element *next_elem; // next element in the with clause + uint number; // number of the element in the with clause (starting from 0) + /* + The map dependency_map has 1 in the i-th position if the query that + specifies this element contains a reference to the element number i + in the query FROM list. + */ + table_map elem_map; // The map where with only one 1 set in this->number + table_map dependency_map; + /* + Total number of references to this element in the FROM lists of + the queries that are in the scope of the element (including + subqueries and specifications of other with elements). + */ + uint references; + /* + Unparsed specification of the query that specifies this element. + It used to build clones of the specification if they are needed. + */ + LEX_STRING unparsed_spec; + + /* Return the map where 1 is set only in the position for this element */ + table_map get_elem_map() { return 1 << number; } + +public: + /* + The name of the table introduced by this with elememt. The name + can be used in FROM lists of the queries in the scope of the element. + */ + LEX_STRING *query_name; + /* + Optional list of column names to name the columns of the table introduced + by this with element. It is used in the case when the names are not + inherited from the query that specified the table. Otherwise the list is + always empty. + */ + List <LEX_STRING> column_list; + /* The query that specifies the table introduced by this with element */ + st_select_lex_unit *spec; + /* + Set to true is recursion is used (directly or indirectly) + for the definition of this element + */ + bool is_recursive; + + With_element(LEX_STRING *name, + List <LEX_STRING> list, + st_select_lex_unit *unit) + : next_elem(NULL), dependency_map(0), references(0), + query_name(name), column_list(list), spec(unit), + is_recursive(false) {} + + void check_dependencies_in_unit(st_select_lex_unit *unit); + + void set_dependency_on(With_element *with_elem) + { dependency_map|= with_elem->get_elem_map(); } + + bool check_dependency_on(With_element *with_elem) + { return dependency_map & with_elem->get_elem_map(); } + + bool set_unparsed_spec(THD *thd, char *spec_start, char *spec_end); + + st_select_lex_unit *clone_parsed_spec(THD *thd, TABLE_LIST *with_table); + + bool is_referenced() { return references != 0; } + + void inc_references() { references++; } + + bool rename_columns_of_derived_unit(THD *thd, st_select_lex_unit *unit); + + bool prepare_unreferenced(THD *thd); + + void print(String *str, enum_query_type query_type); + + friend class With_clause; +}; + + +/** + @class With_element + @brief Definition of a CTE table + + It contains a reference to the name of the table introduced by this with element, + and a reference to the unit that specificies this table. Also it contains + a reference to the with clause to which this element belongs to. +*/ + +class With_clause : public Sql_alloc +{ +private: + st_select_lex_unit *owner; // the unit this with clause attached to + With_element *first_elem; // the first definition in this with clause + With_element **last_next; // here is set the link for the next added element + uint elements; // number of the elements/defintions in this with clauses + /* + The with clause immediately containing this with clause if there is any, + otherwise NULL. Now used only at parsing. + */ + With_clause *embedding_with_clause; + /* + The next with the clause of the chain of with clauses encountered + in the current statement + */ + With_clause *next_with_clause; + /* Set to true if dependencies between with elements have been checked */ + bool dependencies_are_checked; + +public: + /* If true the specifier RECURSIVE is present in the with clause */ + bool with_recursive; + + With_clause(bool recursive_fl, With_clause *emb_with_clause) + : owner(NULL), first_elem(NULL), elements(0), + embedding_with_clause(emb_with_clause), next_with_clause(NULL), + dependencies_are_checked(false), + with_recursive(recursive_fl) + { last_next= &first_elem; } + + /* Add a new element to the current with clause */ + bool add_with_element(With_element *elem) + { + elem->owner= this; + elem->number= elements; + owner= elem->spec; + owner->with_element= elem; + *last_next= elem; + last_next= &elem->next_elem; + elements++; + return false; + } + + /* Add this with clause to the list of with clauses used in the statement */ + void add_to_list(With_clause ** &last_next) + { + *last_next= this; + last_next= &this->next_with_clause; + } + + With_clause *pop() { return embedding_with_clause; } + + bool check_dependencies(); + + With_element *find_table_def(TABLE_LIST *table); + + With_element *find_table_def_in_with_clauses(TABLE_LIST *table); + + bool prepare_unreferenced_elements(THD *thd); + + void print(String *str, enum_query_type query_type); + + friend + bool check_dependencies_in_with_clauses(With_clause *with_clauses_list); + +}; + + +#endif /* SQL_CTE_INCLUDED */ diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 3377a6736a0..0a76ee0a699 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -40,6 +40,8 @@ #include "sql_statistics.h" #include "transaction.h" #include "records.h" // init_read_record, +#include "filesort.h" +#include "uniques.h" #include "sql_derived.h" // mysql_handle_list_of_derived // end_read_record #include "sql_partition.h" // make_used_partitions_str @@ -227,10 +229,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, int error, loc_error; TABLE *table; SQL_SELECT *select=0; + SORT_INFO *file_sort= 0; READ_RECORD info; bool using_limit=limit != HA_POS_ERROR; bool transactional_table, safe_update, const_cond; bool const_cond_result; + bool return_error= 0; ha_rows deleted= 0; bool reverse= FALSE; ORDER *order= (ORDER *) ((order_list && order_list->elements) ? @@ -405,7 +409,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, table->covering_keys.clear_all(); table->quick_keys.clear_all(); // Can't use 'only index' - select=make_select(table, 0, 0, conds, 0, &error); + select=make_select(table, 0, 0, conds, (SORT_INFO*) 0, 0, &error); if (error) DBUG_RETURN(TRUE); if ((select && select->check_quick(thd, safe_update, limit)) || !limit) @@ -486,28 +490,17 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (query_plan.using_filesort) { - ha_rows examined_rows; - ha_rows found_rows; { Filesort fsort(order, HA_POS_ERROR, select); DBUG_ASSERT(query_plan.index == MAX_KEY); - table->sort.io_cache= (IO_CACHE *) my_malloc(sizeof(IO_CACHE), - MYF(MY_FAE | MY_ZEROFILL | - MY_THREAD_SPECIFIC)); Filesort_tracker *fs_tracker= thd->lex->explain->get_upd_del_plan()->filesort_tracker; - if ((table->sort.found_records= filesort(thd, table, &fsort, true, - &examined_rows, &found_rows, - fs_tracker)) - == HA_POS_ERROR) - { - delete select; - free_underlaid_joins(thd, &thd->lex->select_lex); - DBUG_RETURN(TRUE); - } - thd->inc_examined_row_count(examined_rows); + if (!(file_sort= filesort(thd, table, &fsort, true, fs_tracker))) + goto got_error; + + thd->inc_examined_row_count(file_sort->examined_rows); /* Filesort has already found and selected the rows we want to delete, so we don't need the where clause @@ -527,24 +520,16 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, /* If quick select is used, initialize it before retrieving rows. */ if (select && select->quick && select->quick->reset()) - { - delete select; - free_underlaid_joins(thd, select_lex); - DBUG_RETURN(TRUE); - } + goto got_error; if (query_plan.index == MAX_KEY || (select && select->quick)) - error= init_read_record(&info, thd, table, select, 1, 1, FALSE); + error= init_read_record(&info, thd, table, select, file_sort, 1, 1, FALSE); else error= init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse); if (error) - { - delete select; - free_underlaid_joins(thd, select_lex); - DBUG_RETURN(TRUE); - } - + goto got_error; + init_ftfuncs(thd, select_lex, 1); THD_STAGE_INFO(thd, stage_updating); @@ -700,8 +685,6 @@ cleanup: } DBUG_ASSERT(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table); - - free_underlaid_joins(thd, select_lex); if (error < 0 || (thd->lex->ignore && !thd->is_error() && !thd->is_fatal_error)) { @@ -714,6 +697,8 @@ cleanup: my_ok(thd, deleted); DBUG_PRINT("info",("%ld records deleted",(long) deleted)); } + delete file_sort; + free_underlaid_joins(thd, select_lex); DBUG_RETURN(error >= 0 || thd->is_error()); /* Special exits */ @@ -732,9 +717,16 @@ send_nothing_and_leave: */ delete select; + delete file_sort; free_underlaid_joins(thd, select_lex); //table->set_keyread(false); - DBUG_RETURN((thd->is_error() || thd->killed) ? 1 : 0); + + DBUG_ASSERT(!return_error || thd->is_error() || thd->killed); + DBUG_RETURN((return_error || thd->is_error() || thd->killed) ? 1 : 0); + +got_error: + return_error= 1; + goto send_nothing_and_leave; } @@ -1187,7 +1179,8 @@ int multi_delete::do_deletes() if (tempfiles[counter]->get(table)) DBUG_RETURN(1); - local_error= do_table_deletes(table, thd->lex->ignore); + local_error= do_table_deletes(table, &tempfiles[counter]->sort, + thd->lex->ignore); if (thd->killed && !local_error) DBUG_RETURN(1); @@ -1217,14 +1210,15 @@ int multi_delete::do_deletes() @retval 1 Triggers or handler reported error. @retval -1 End of file from handler. */ -int multi_delete::do_table_deletes(TABLE *table, bool ignore) +int multi_delete::do_table_deletes(TABLE *table, SORT_INFO *sort_info, + bool ignore) { int local_error= 0; READ_RECORD info; ha_rows last_deleted= deleted; DBUG_ENTER("do_deletes_for_table"); - if (init_read_record(&info, thd, table, NULL, 0, 1, FALSE)) + if (init_read_record(&info, thd, table, NULL, sort_info, 0, 1, FALSE)) DBUG_RETURN(1); /* diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 53628335508..79e57cded81 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -30,6 +30,7 @@ #include "sql_base.h" #include "sql_view.h" // check_duplicate_names #include "sql_acl.h" // SELECT_ACL +#include "sql_cte.h" typedef bool (*dt_processor)(THD *thd, LEX *lex, TABLE_LIST *derived); @@ -670,6 +671,9 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) // st_select_lex_unit::prepare correctly work for single select if ((res= unit->prepare(thd, derived->derived_result, 0))) goto exit; + if (derived->with && + (res= derived->with->rename_columns_of_derived_unit(thd, unit))) + goto exit; lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED; if ((res= check_duplicate_names(thd, unit->types, 0))) goto exit; diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index f3001d5942a..ae54f8bd455 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -843,6 +843,12 @@ void Explain_select::print_explain_json(Explain_query *query, writer->add_member("const_condition"); write_item(writer, exec_const_cond); } + if (outer_ref_cond) + { + writer->add_member("outer_ref_condition"); + write_item(writer, outer_ref_cond); + } + /* we do not print HAVING which always evaluates to TRUE */ if (having || (having_value == Item::COND_FALSE)) { diff --git a/sql/sql_explain.h b/sql/sql_explain.h index 3f57f7ac937..9f8a0361cd5 100644 --- a/sql/sql_explain.h +++ b/sql/sql_explain.h @@ -225,9 +225,10 @@ public: /* Expensive constant condition */ Item *exec_const_cond; + Item *outer_ref_cond; /* HAVING condition */ - COND *having; + Item *having; Item::cond_result having_value; /* Global join attributes. In tabular form, they are printed on the first row */ diff --git a/sql/sql_help.cc b/sql/sql_help.cc index a0e836da203..a50b90fc111 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -194,7 +194,8 @@ int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_fields, DBUG_ENTER("search_topics"); /* Should never happen. As this is part of help, we can ignore this */ - if (init_read_record(&read_record_info, thd, topics, select, 1, 0, FALSE)) + if (init_read_record(&read_record_info, thd, topics, select, NULL, 1, 0, + FALSE)) DBUG_RETURN(0); while (!read_record_info.read_record(&read_record_info)) @@ -229,14 +230,16 @@ int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_fields, 2 found more then one topic matching the mask */ -int search_keyword(THD *thd, TABLE *keywords, struct st_find_field *find_fields, +int search_keyword(THD *thd, TABLE *keywords, + struct st_find_field *find_fields, SQL_SELECT *select, int *key_id) { int count= 0; READ_RECORD read_record_info; DBUG_ENTER("search_keyword"); /* Should never happen. As this is part of help, we can ignore this */ - if (init_read_record(&read_record_info, thd, keywords, select, 1, 0, FALSE)) + if (init_read_record(&read_record_info, thd, keywords, select, NULL, 1, 0, + FALSE)) DBUG_RETURN(0); while (!read_record_info.read_record(&read_record_info) && count<2) @@ -370,7 +373,8 @@ int search_categories(THD *thd, TABLE *categories, DBUG_ENTER("search_categories"); /* Should never happen. As this is part of help, we can ignore this */ - if (init_read_record(&read_record_info, thd, categories, select,1,0,FALSE)) + if (init_read_record(&read_record_info, thd, categories, select, NULL, + 1, 0, FALSE)) DBUG_RETURN(0); while (!read_record_info.read_record(&read_record_info)) { @@ -406,7 +410,8 @@ void get_all_items_for_category(THD *thd, TABLE *items, Field *pfname, DBUG_ENTER("get_all_items_for_category"); /* Should never happen. As this is part of help, we can ignore this */ - if (init_read_record(&read_record_info, thd, items, select,1,0,FALSE)) + if (init_read_record(&read_record_info, thd, items, select, NULL, 1, 0, + FALSE)) DBUG_VOID_RETURN; while (!read_record_info.read_record(&read_record_info)) @@ -608,7 +613,7 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, /* Assume that no indexes cover all required fields */ table->covering_keys.clear_all(); - SQL_SELECT *res= make_select(table, 0, 0, cond, 0, error); + SQL_SELECT *res= make_select(table, 0, 0, cond, 0, 0, error); if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)) || (res && res->quick && res->quick->reset())) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 15a04cbb170..6e40ac02274 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2071,6 +2071,7 @@ public: delayed_lock= global_system_variables.low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE; mysql_mutex_unlock(&LOCK_thread_count); + thread_safe_increment32(&thread_count); DBUG_VOID_RETURN; } ~Delayed_insert() @@ -2084,17 +2085,24 @@ public: close_thread_tables(&thd); thd.mdl_context.release_transactional_locks(); } - mysql_mutex_lock(&LOCK_thread_count); mysql_mutex_destroy(&mutex); mysql_cond_destroy(&cond); mysql_cond_destroy(&cond_client); + + /* + We could use unlink_not_visible_threads() here, but as + delayed_insert_threads also needs to be protected by + the LOCK_thread_count mutex, we open code this. + */ + mysql_mutex_lock(&LOCK_thread_count); thd.unlink(); // Must be unlinked under lock - my_free(thd.query()); - thd.security_ctx->user= thd.security_ctx->host=0; delayed_insert_threads--; mysql_mutex_unlock(&LOCK_thread_count); - thread_safe_decrement32(&thread_count); - mysql_cond_broadcast(&COND_thread_count); /* Tell main we are ready */ + + my_free(thd.query()); + thd.security_ctx->user= 0; + thd.security_ctx->host= 0; + dec_thread_count(); } /* The following is for checking when we can delete ourselves */ @@ -2229,8 +2237,6 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, if (!(di= new Delayed_insert(thd->lex->current_select))) goto end_create; - thread_safe_increment32(&thread_count); - /* Annotating delayed inserts is not supported. */ @@ -2806,15 +2812,13 @@ pthread_handler_t handle_delayed_insert(void *arg) pthread_detach_this_thread(); /* Add thread to THD list so that's it's visible in 'show processlist' */ - mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; + thd->thread_id= thd->variables.pseudo_thread_id= next_thread_id(); thd->set_current_time(); - threads.append(thd); + add_to_active_threads(thd); if (abort_loop) thd->killed= KILL_CONNECTION; else thd->reset_killed(); - mysql_mutex_unlock(&LOCK_thread_count); mysql_thread_set_psi_id(thd->thread_id); @@ -3896,7 +3900,7 @@ Field *Item::create_field_for_create_select(THD *thd, TABLE *table) { Field *def_field, *tmp_field; return ::create_tmp_field(thd, table, this, type(), - (Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0, 0); + (Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0); } @@ -4256,6 +4260,8 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) DBUG_RETURN(1); table->mark_columns_needed_for_insert(); table->file->extra(HA_EXTRA_WRITE_CACHE); + // Mark table as used + table->query_id= thd->query_id; DBUG_RETURN(0); } @@ -4342,8 +4348,9 @@ bool select_create::send_eof() mysql_mutex_lock(&thd->LOCK_wsrep_thd); if (thd->wsrep_conflict_state != NO_CONFLICT) { - WSREP_DEBUG("select_create commit failed, thd: %lu err: %d %s", - thd->thread_id, thd->wsrep_conflict_state, thd->query()); + WSREP_DEBUG("select_create commit failed, thd: %lld err: %d %s", + (longlong) thd->thread_id, thd->wsrep_conflict_state, + thd->query()); mysql_mutex_unlock(&thd->LOCK_wsrep_thd); abort_result_set(); DBUG_RETURN(true); diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index f84440afa90..818598110ca 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -2206,7 +2206,7 @@ finish: for a match for any record from join_tab. To iterate over the candidates for a match the virtual function get_next_candidate_for_match is used, while the virtual function prepare_look_for_matches is called to prepare - for such iteration proccess. + for such iteration process. NOTES The function produces all matching extensions for the records in the diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 5bfa062a628..6056b03f4eb 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #include "sp_head.h" #include "sp.h" #include "sql_select.h" +#include "sql_cte.h" static int lex_one_token(YYSTYPE *yylval, THD *thd); @@ -324,9 +325,7 @@ void Lex_input_stream::body_utf8_start(THD *thd, const char *begin_ptr) DBUG_ASSERT(begin_ptr); DBUG_ASSERT(m_cpp_buf <= begin_ptr && begin_ptr <= m_cpp_buf + m_buf_length); - uint body_utf8_length= - (m_buf_length / thd->variables.character_set_client->mbminlen) * - my_charset_utf8_bin.mbmaxlen; + uint body_utf8_length= get_body_utf8_maximum_length(thd); m_body_utf8= (char *) thd->alloc(body_utf8_length + 1); m_body_utf8_ptr= m_body_utf8; @@ -335,6 +334,22 @@ void Lex_input_stream::body_utf8_start(THD *thd, const char *begin_ptr) m_cpp_utf8_processed_ptr= begin_ptr; } + +uint Lex_input_stream::get_body_utf8_maximum_length(THD *thd) +{ + /* + String literals can grow during escaping: + 1a. Character string '<TAB>' can grow to '\t', 3 bytes to 4 bytes growth. + 1b. Character string '1000 times <TAB>' grows from + 1002 to 2002 bytes (including quotes), which gives a little bit + less than 2 times growth. + "2" should be a reasonable multiplier that safely covers escaping needs. + */ + return (m_buf_length / thd->variables.character_set_client->mbminlen) * + my_charset_utf8_bin.mbmaxlen * 2/*for escaping*/; +} + + /** @brief The operation appends unprocessed part of pre-processed buffer till the given pointer (ptr) and sets m_cpp_utf8_processed_ptr to end_ptr. @@ -402,15 +417,15 @@ void Lex_input_stream::body_utf8_append(const char *ptr) operation. */ -void Lex_input_stream::body_utf8_append_literal(THD *thd, - const LEX_STRING *txt, - CHARSET_INFO *txt_cs, - const char *end_ptr) +void Lex_input_stream::body_utf8_append_ident(THD *thd, + const LEX_STRING *txt, + const char *end_ptr) { if (!m_cpp_utf8_processed_ptr) return; LEX_STRING utf_txt; + CHARSET_INFO *txt_cs= thd->charset(); if (!my_charset_same(txt_cs, &my_charset_utf8_general_ci)) { @@ -434,6 +449,189 @@ void Lex_input_stream::body_utf8_append_literal(THD *thd, m_cpp_utf8_processed_ptr= end_ptr; } + + + +extern "C" { + +/** + Escape a character. Consequently puts "escape" and "wc" characters into + the destination utf8 string. + @param cs - the character set (utf8) + @param escape - the escape character (backslash, single quote, double quote) + @param wc - the character to be escaped + @param str - the destination string + @param end - the end of the destination string + @returns - a code according to the wc_mb() convension. +*/ +int my_wc_mb_utf8_with_escape(CHARSET_INFO *cs, my_wc_t escape, my_wc_t wc, + uchar *str, uchar *end) +{ + DBUG_ASSERT(escape > 0); + if (str + 1 >= end) + return MY_CS_TOOSMALL2; // Not enough space, need at least two bytes. + *str= escape; + int cnvres= my_charset_utf8_handler.wc_mb(cs, wc, str + 1, end); + if (cnvres > 0) + return cnvres + 1; // The character was normally put + if (cnvres == MY_CS_ILUNI) + return MY_CS_ILUNI; // Could not encode "wc" (e.g. non-BMP character) + DBUG_ASSERT(cnvres <= MY_CS_TOOSMALL); + return cnvres - 1; // Not enough space +} + + +/** + Optionally escape a character. + If "escape" is non-zero, then both "escape" and "wc" are put to + the destination string. Otherwise, only "wc" is put. + @param cs - the character set (utf8) + @param wc - the character to be optionally escaped + @param escape - the escape character, or 0 + @param ewc - the escaped replacement of "wc" (e.g. 't' for '\t') + @param str - the destination string + @param end - the end of the destination string + @returns - a code according to the wc_mb() conversion. +*/ +int my_wc_mb_utf8_opt_escape(CHARSET_INFO *cs, + my_wc_t wc, my_wc_t escape, my_wc_t ewc, + uchar *str, uchar *end) +{ + return escape ? my_wc_mb_utf8_with_escape(cs, escape, ewc, str, end) : + my_charset_utf8_handler.wc_mb(cs, wc, str, end); +} + +/** + Encode a character with optional backlash escaping and quote escaping. + Quote marks are escaped using another quote mark. + Additionally, if "escape" is non-zero, then special characters are + also escaped using "escape". + Otherwise (if "escape" is zero, e.g. in case of MODE_NO_BACKSLASH_ESCAPES), + then special characters are not escaped and handled as normal characters. + + @param cs - the character set (utf8) + @param wc - the character to be encoded + @param str - the destination string + @param end - the end of the destination string + @param sep - the string delimiter (e.g. ' or ") + @param escape - the escape character (backslash, or 0) + @returns - a code according to the wc_mb() convension. +*/ +int my_wc_mb_utf8_escape(CHARSET_INFO *cs, my_wc_t wc, uchar *str, uchar *end, + my_wc_t sep, my_wc_t escape) +{ + DBUG_ASSERT(escape == 0 || escape == '\\'); + DBUG_ASSERT(sep == '"' || sep == '\''); + switch (wc) { + case 0: return my_wc_mb_utf8_opt_escape(cs, wc, escape, '0', str, end); + case '\t': return my_wc_mb_utf8_opt_escape(cs, wc, escape, 't', str, end); + case '\r': return my_wc_mb_utf8_opt_escape(cs, wc, escape, 'r', str, end); + case '\n': return my_wc_mb_utf8_opt_escape(cs, wc, escape, 'n', str, end); + case '\032': return my_wc_mb_utf8_opt_escape(cs, wc, escape, 'Z', str, end); + case '\'': + case '\"': + if (wc == sep) + return my_wc_mb_utf8_with_escape(cs, wc, wc, str, end); + } + return my_charset_utf8_handler.wc_mb(cs, wc, str, end); // No escaping needed +} + + +/** wc_mb() compatible routines for all sql_mode and delimiter combinations */ +int my_wc_mb_utf8_escape_single_quote_and_backslash(CHARSET_INFO *cs, + my_wc_t wc, + uchar *str, uchar *end) +{ + return my_wc_mb_utf8_escape(cs, wc, str, end, '\'', '\\'); +} + + +int my_wc_mb_utf8_escape_double_quote_and_backslash(CHARSET_INFO *cs, + my_wc_t wc, + uchar *str, uchar *end) +{ + return my_wc_mb_utf8_escape(cs, wc, str, end, '"', '\\'); +} + + +int my_wc_mb_utf8_escape_single_quote(CHARSET_INFO *cs, my_wc_t wc, + uchar *str, uchar *end) +{ + return my_wc_mb_utf8_escape(cs, wc, str, end, '\'', 0); +} + + +int my_wc_mb_utf8_escape_double_quote(CHARSET_INFO *cs, my_wc_t wc, + uchar *str, uchar *end) +{ + return my_wc_mb_utf8_escape(cs, wc, str, end, '"', 0); +} + +}; // End of extern "C" + + +/** + Get an escaping function, depending on the current sql_mode and the + string separator. +*/ +my_charset_conv_wc_mb +Lex_input_stream::get_escape_func(THD *thd, my_wc_t sep) const +{ + return thd->backslash_escapes() ? + (sep == '"' ? my_wc_mb_utf8_escape_double_quote_and_backslash: + my_wc_mb_utf8_escape_single_quote_and_backslash) : + (sep == '"' ? my_wc_mb_utf8_escape_double_quote: + my_wc_mb_utf8_escape_single_quote); +} + + +/** + Append a text literal to the end of m_body_utf8. + The string is escaped according to the current sql_mode and the + string delimiter (e.g. ' or "). + + @param thd - current THD + @param txt - the string to be appended to m_body_utf8. + Note, the string must be already unescaped. + @param cs - the character set of the string + @param end_ptr - m_cpp_utf8_processed_ptr will be set to this value + (see body_utf8_append_ident for details) + @param sep - the string delimiter (single or double quote) +*/ +void Lex_input_stream::body_utf8_append_escape(THD *thd, + const LEX_STRING *txt, + CHARSET_INFO *cs, + const char *end_ptr, + my_wc_t sep) +{ + DBUG_ASSERT(sep == '\'' || sep == '"'); + if (!m_cpp_utf8_processed_ptr) + return; + uint errors; + /** + We previously alloced m_body_utf8 to be able to store the query with all + strings properly escaped. See get_body_utf8_maximum_length(). + So here we have guaranteedly enough space to append any string literal + with escaping. Passing txt->length*2 as "available space" is always safe. + For better safety purposes we could calculate get_body_utf8_maximum_length() + every time we append a string, but this would affect performance negatively, + so let's check that we don't get beyond the allocated buffer in + debug build only. + */ + DBUG_ASSERT(m_body_utf8 + get_body_utf8_maximum_length(thd) >= + m_body_utf8_ptr + txt->length * 2); + uint32 cnv_length= my_convert_using_func(m_body_utf8_ptr, txt->length * 2, + &my_charset_utf8_general_ci, + get_escape_func(thd, sep), + txt->str, txt->length, + cs, cs->cset->mb_wc, + &errors); + m_body_utf8_ptr+= cnv_length; + *m_body_utf8_ptr= 0; + m_cpp_utf8_processed_ptr= end_ptr; +} + + void Lex_input_stream::add_digest_token(uint token, LEX_YYSTYPE yylval) { if (m_digest != NULL) @@ -471,11 +669,15 @@ void lex_start(THD *thd) /* 'parent_lex' is used in init_query() so it must be before it. */ lex->select_lex.parent_lex= lex; lex->select_lex.init_query(); + lex->curr_with_clause= 0; + lex->with_clauses_list= 0; + lex->with_clauses_list_last_next= &lex->with_clauses_list; lex->value_list.empty(); lex->update_list.empty(); lex->set_var_list.empty(); lex->param_list.empty(); lex->view_list.empty(); + lex->with_column_list.empty(); lex->with_persistent_for_clause= FALSE; lex->column_list= NULL; lex->index_list= NULL; @@ -804,14 +1006,14 @@ Lex_input_stream::unescape(CHARSET_INFO *cs, char *to, Fix sometimes to do only one scan of the string */ -bool Lex_input_stream::get_text(LEX_STRING *dst, int pre_skip, int post_skip) +bool Lex_input_stream::get_text(LEX_STRING *dst, uint sep, + int pre_skip, int post_skip) { - reg1 uchar c,sep; + reg1 uchar c; uint found_escape=0; CHARSET_INFO *cs= m_thd->charset(); tok_bitmap= 0; - sep= yyGetLast(); // String should end with this while (! eof()) { c= yyGet(); @@ -1176,6 +1378,8 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) return((int) c); case MY_LEX_IDENT_OR_NCHAR: + { + uint sep; if (lip->yyPeek() != '\'') { state= MY_LEX_IDENT; @@ -1183,14 +1387,20 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) } /* Found N'string' */ lip->yySkip(); // Skip ' - if (lip->get_text(&yylval->lex_str, 2, 1)) + if (lip->get_text(&yylval->lex_str, (sep= lip->yyGetLast()), 2, 1)) { state= MY_LEX_CHAR; // Read char by char break; } + + lip->body_utf8_append(lip->m_cpp_text_start); + lip->body_utf8_append_escape(thd, &yylval->lex_str, + national_charset_info, + lip->m_cpp_text_end, sep); + lex->text_string_is_7bit= (lip->tok_bitmap & 0x80) ? 0 : 1; return(NCHAR_STRING); - + } case MY_LEX_IDENT_OR_HEX: if (lip->yyPeek() == '\'') { // Found x'hex-number' @@ -1209,28 +1419,22 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) if (use_mb(cs)) { result_state= IDENT_QUOTED; - if (my_mbcharlen(cs, lip->yyGetLast()) > 1) + int char_length= my_charlen(cs, lip->get_ptr() - 1, + lip->get_end_of_query()); + if (char_length <= 0) { - int l = my_ismbchar(cs, - lip->get_ptr() -1, - lip->get_end_of_query()); - if (l == 0) { - state = MY_LEX_CHAR; - continue; - } - lip->skip_binary(l - 1); + state= MY_LEX_CHAR; + continue; } + lip->skip_binary(char_length - 1); + while (ident_map[c=lip->yyGet()]) { - if (my_mbcharlen(cs, c) > 1) - { - int l; - if ((l = my_ismbchar(cs, - lip->get_ptr() -1, - lip->get_end_of_query())) == 0) - break; - lip->skip_binary(l-1); - } + char_length= my_charlen(cs, lip->get_ptr() - 1, + lip->get_end_of_query()); + if (char_length <= 0) + break; + lip->skip_binary(char_length - 1); } } else @@ -1293,8 +1497,7 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) lip->body_utf8_append(lip->m_cpp_text_start); - lip->body_utf8_append_literal(thd, &yylval->lex_str, cs, - lip->m_cpp_text_end); + lip->body_utf8_append_ident(thd, &yylval->lex_str, lip->m_cpp_text_end); return(result_state); // IDENT or IDENT_QUOTED @@ -1372,15 +1575,11 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) result_state= IDENT_QUOTED; while (ident_map[c=lip->yyGet()]) { - if (my_mbcharlen(cs, c) > 1) - { - int l; - if ((l = my_ismbchar(cs, - lip->get_ptr() -1, - lip->get_end_of_query())) == 0) - break; - lip->skip_binary(l-1); - } + int char_length= my_charlen(cs, lip->get_ptr() - 1, + lip->get_end_of_query()); + if (char_length <= 0) + break; + lip->skip_binary(char_length - 1); } } else @@ -1398,8 +1597,7 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) lip->body_utf8_append(lip->m_cpp_text_start); - lip->body_utf8_append_literal(thd, &yylval->lex_str, cs, - lip->m_cpp_text_end); + lip->body_utf8_append_ident(thd, &yylval->lex_str, lip->m_cpp_text_end); return(result_state); @@ -1409,8 +1607,9 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) char quote_char= c; // Used char while ((c=lip->yyGet())) { - int var_length; - if ((var_length= my_mbcharlen(cs, c)) == 1) + int var_length= my_charlen(cs, lip->get_ptr() - 1, + lip->get_end_of_query()); + if (var_length == 1) { if (c == quote_char) { @@ -1422,11 +1621,9 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) } } #ifdef USE_MB - else if (use_mb(cs)) + else if (var_length > 1) { - if ((var_length= my_ismbchar(cs, lip->get_ptr() - 1, - lip->get_end_of_query()))) - lip->skip_binary(var_length-1); + lip->skip_binary(var_length - 1); } #endif } @@ -1442,8 +1639,7 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) lip->body_utf8_append(lip->m_cpp_text_start); - lip->body_utf8_append_literal(thd, &yylval->lex_str, cs, - lip->m_cpp_text_end); + lip->body_utf8_append_ident(thd, &yylval->lex_str, lip->m_cpp_text_end); return(IDENT_QUOTED); } @@ -1548,23 +1744,23 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) } /* " used for strings */ case MY_LEX_STRING: // Incomplete text string - if (lip->get_text(&yylval->lex_str, 1, 1)) + { + uint sep; + if (lip->get_text(&yylval->lex_str, (sep= lip->yyGetLast()), 1, 1)) { state= MY_LEX_CHAR; // Read char by char break; } - + CHARSET_INFO *strcs= lip->m_underscore_cs ? lip->m_underscore_cs : cs; lip->body_utf8_append(lip->m_cpp_text_start); - lip->body_utf8_append_literal(thd, &yylval->lex_str, - lip->m_underscore_cs ? lip->m_underscore_cs : cs, - lip->m_cpp_text_end); - + lip->body_utf8_append_escape(thd, &yylval->lex_str, strcs, + lip->m_cpp_text_end, sep); lip->m_underscore_cs= NULL; lex->text_string_is_7bit= (lip->tok_bitmap & 0x80) ? 0 : 1; return(TEXT_STRING); - + } case MY_LEX_COMMENT: // Comment lex->select_lex.options|= OPTION_FOUND_COMMENT; while ((c = lip->yyGet()) != '\n' && c) ; @@ -1813,8 +2009,7 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd) lip->body_utf8_append(lip->m_cpp_text_start); - lip->body_utf8_append_literal(thd, &yylval->lex_str, cs, - lip->m_cpp_text_end); + lip->body_utf8_append_ident(thd, &yylval->lex_str, lip->m_cpp_text_end); return(result_state); } @@ -1883,6 +2078,9 @@ void st_select_lex_unit::init_query() found_rows_for_union= 0; insert_table_with_stored_vcol= 0; derived= 0; + with_clause= 0; + with_element= 0; + columns_are_renamed= false; } void st_select_lex::init_query() @@ -2068,6 +2266,37 @@ void st_select_lex_node::fast_exclude() } +/** + @brief + Insert a new chain of nodes into another chain before a particular link + + @param in/out + ptr_pos_to_insert the address of the chain pointer pointing to the link + before which the subchain has to be inserted + @param + end_chain_node the last link of the subchain to be inserted + + @details + The method inserts the chain of nodes starting from this node and ending + with the node nd_chain_node into another chain of nodes before the node + pointed to by *ptr_pos_to_insert. + It is assumed that ptr_pos_to_insert belongs to the chain where we insert. + So it must be updated. + + @retval + The method returns the pointer to the first link of the inserted chain +*/ + +st_select_lex_node *st_select_lex_node:: insert_chain_before( + st_select_lex_node **ptr_pos_to_insert, + st_select_lex_node *end_chain_node) +{ + end_chain_node->link_next= *ptr_pos_to_insert; + (*ptr_pos_to_insert)->link_prev= &end_chain_node->link_next; + this->link_prev= ptr_pos_to_insert; + return this; +} + /* Exclude a node from the tree lex structure, but leave it in the global list of nodes. @@ -2464,6 +2693,8 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) void st_select_lex_unit::print(String *str, enum_query_type query_type) { bool union_all= !union_distinct; + if (with_clause) + with_clause->print(str, query_type); for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) { if (sl != first_select()) @@ -2504,30 +2735,22 @@ void st_select_lex::print_order(String *str, { if (order->counter_used) { - if (query_type != QT_VIEW_INTERNAL) + char buffer[20]; + size_t length= my_snprintf(buffer, 20, "%d", order->counter); + str->append(buffer, (uint) length); + } + else + { + /* replace numeric reference with equivalent for ORDER constant */ + if (order->item[0]->type() == Item::INT_ITEM && + order->item[0]->basic_const_item()) { - char buffer[20]; - size_t length= my_snprintf(buffer, 20, "%d", order->counter); - str->append(buffer, (uint) length); + /* make it expression instead of integer constant */ + str->append(STRING_WITH_LEN("''")); } else - { - /* replace numeric reference with expression */ - if (order->item[0]->type() == Item::INT_ITEM && - order->item[0]->basic_const_item()) - { - char buffer[20]; - size_t length= my_snprintf(buffer, 20, "%d", order->counter); - str->append(buffer, (uint) length); - /* make it expression instead of integer constant */ - str->append(STRING_WITH_LEN("+0")); - } - else - (*order->item)->print(str, query_type); - } + (*order->item)->print(str, query_type); } - else - (*order->item)->print(str, query_type); if (order->direction == ORDER::ORDER_DESC) str->append(STRING_WITH_LEN(" desc")); if (order->next) @@ -3932,6 +4155,19 @@ void SELECT_LEX::update_used_tables() tl->on_expr->update_used_tables(); tl->on_expr->walk(&Item::eval_not_null_tables, 0, NULL); } + /* + - There is no need to check sj_on_expr, because merged semi-joins inject + sj_on_expr into the parent's WHERE clase. + - For non-merged semi-joins (aka JTBMs), we need to check their + left_expr. There is no need to check the rest of the subselect, we know + it is uncorrelated and so cannot refer to any tables in this select. + */ + if (tl->jtbm_subselect) + { + Item *left_expr= tl->jtbm_subselect->left_expr; + left_expr->walk(&Item::update_table_bitmaps_processor, FALSE, NULL); + } + embedding= tl->embedding; while (embedding) { diff --git a/sql/sql_lex.h b/sql/sql_lex.h index d4acf98c5d4..fcfa96023a4 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB +/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -50,6 +50,8 @@ class File_parser; class Key_part_spec; class Item_window_func; struct sql_digest_state; +class With_clause; + #define ALLOC_ROOT_SET 1024 @@ -180,6 +182,7 @@ const LEX_STRING sp_data_access_name[]= #define DERIVED_SUBQUERY 1 #define DERIVED_VIEW 2 +#define DERIVED_WITH 4 enum enum_view_create_mode { @@ -542,7 +545,9 @@ public: List<String> *partition_names= 0, LEX_STRING *option= 0); virtual void set_lock_for_tables(thr_lock_type lock_type) {} - + void set_slave(st_select_lex_node *slave_arg) { slave= slave_arg; } + st_select_lex_node *insert_chain_before(st_select_lex_node **ptr_pos_to_insert, + st_select_lex_node *end_chain_node); friend class st_select_lex_unit; friend bool mysql_new_select(LEX *lex, bool move_down); friend bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, @@ -629,7 +634,7 @@ public: return saved_fake_select_lex; return first_select(); }; - //node on wich we should return current_select pointer after parsing subquery + //node on which we should return current_select pointer after parsing subquery st_select_lex *return_to; /* LIMIT clause runtime counters */ ha_rows select_limit_cnt, offset_limit_cnt; @@ -640,6 +645,10 @@ public: derived tables/views handling. */ TABLE_LIST *derived; + /* With clause attached to this unit (if any) */ + With_clause *with_clause; + /* With element where this unit is used as the specification (if any) */ + With_element *with_element; /* thread handler */ THD *thd; /* @@ -648,7 +657,7 @@ public: */ st_select_lex *fake_select_lex; /** - SELECT_LEX that stores LIMIT and OFFSET for UNION ALL when no + SELECT_LEX that stores LIMIT and OFFSET for UNION ALL when noq fake_select_lex is used. */ st_select_lex *saved_fake_select_lex; @@ -664,12 +673,15 @@ public: */ TABLE *insert_table_with_stored_vcol; + bool columns_are_renamed; + void init_query(); st_select_lex* outer_select(); st_select_lex* first_select() { return reinterpret_cast<st_select_lex*>(slave); } + void set_with_clause(With_clause *with_cl) { with_clause= with_cl; } st_select_lex_unit* next_unit() { return reinterpret_cast<st_select_lex_unit*>(next); @@ -1071,6 +1083,19 @@ public: void set_non_agg_field_used(bool val) { m_non_agg_field_used= val; } void set_agg_func_used(bool val) { m_agg_func_used= val; } + void set_with_clause(With_clause *with_clause) + { + master_unit()->with_clause= with_clause; + } + With_clause *get_with_clause() + { + return master_unit()->with_clause; + } + With_element *get_with_element() + { + return master_unit()->with_element; + } + With_element *find_table_def_in_with_clauses(TABLE_LIST *table); List<Window_spec> window_specs; void prepare_add_window_spec(THD *thd); @@ -1097,6 +1122,13 @@ private: index_clause_map current_index_hint_clause; /* a list of USE/FORCE/IGNORE INDEX */ List<Index_hint> *index_hints; + +public: + inline void add_where_field(st_select_lex *sel) + { + DBUG_ASSERT(this != sel); + select_n_where_fields+= sel->select_n_where_fields; + } }; typedef class st_select_lex SELECT_LEX; @@ -1432,6 +1464,11 @@ public: return get_stmt_unsafe_flags() != 0; } + inline bool is_stmt_unsafe(enum_binlog_stmt_unsafe unsafe) + { + return binlog_stmt_flags & (1 << unsafe); + } + /** Flag the current (top-level) statement as unsafe. The flag will be reset after the statement has finished. @@ -1828,6 +1865,7 @@ class Lex_input_stream { size_t unescape(CHARSET_INFO *cs, char *to, const char *str, const char *end, int sep); + my_charset_conv_wc_mb get_escape_func(THD *thd, my_wc_t sep) const; public: Lex_input_stream() { @@ -2098,14 +2136,23 @@ public: return (uint) (m_body_utf8_ptr - m_body_utf8); } + /** + Get the maximum length of the utf8-body buffer. + The utf8 body can grow because of the character set conversion and escaping. + */ + uint get_body_utf8_maximum_length(THD *thd); + void body_utf8_start(THD *thd, const char *begin_ptr); void body_utf8_append(const char *ptr); void body_utf8_append(const char *ptr, const char *end_ptr); - void body_utf8_append_literal(THD *thd, - const LEX_STRING *txt, - CHARSET_INFO *txt_cs, - const char *end_ptr); - + void body_utf8_append_ident(THD *thd, + const LEX_STRING *txt, + const char *end_ptr); + void body_utf8_append_escape(THD *thd, + const LEX_STRING *txt, + CHARSET_INFO *txt_cs, + const char *end_ptr, + my_wc_t sep); /** Current thread. */ THD *m_thd; @@ -2126,7 +2173,7 @@ public: /** LALR(2) resolution, value of the look ahead token.*/ LEX_YYSTYPE lookahead_yylval; - bool get_text(LEX_STRING *to, int pre_skip, int post_skip); + bool get_text(LEX_STRING *to, uint sep, int pre_skip, int post_skip); void add_digest_token(uint token, LEX_YYSTYPE yylval); @@ -2412,7 +2459,16 @@ struct LEX: public Query_tables_list SELECT_LEX *current_select; /* list of all SELECT_LEX */ SELECT_LEX *all_selects_list; - + /* current with clause in parsing if any, otherwise 0*/ + With_clause *curr_with_clause; + /* pointer to the first with clause in the current statemant */ + With_clause *with_clauses_list; + /* + (*with_clauses_list_last_next) contains a pointer to the last + with clause in the current statement + */ + With_clause **with_clauses_list_last_next; + /* Query Plan Footprint of a currently running select */ Explain_query *explain; @@ -2478,6 +2534,7 @@ public: List<Item_func_set_user_var> set_var_list; // in-query assignment list List<Item_param> param_list; List<LEX_STRING> view_list; // view list (list of field names in view) + List<LEX_STRING> with_column_list; // list of column names in with_list_element List<LEX_STRING> *column_list; // list of column names (in ANALYZE) List<LEX_STRING> *index_list; // list of index names (in ANALYZE) /* diff --git a/sql/sql_list.h b/sql/sql_list.h index 718306c2193..113af35bad7 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -650,6 +650,10 @@ struct ilink if (next) next->prev=prev; prev=0 ; next=0; } + inline void assert_if_linked() + { + DBUG_ASSERT(prev != 0 && next != 0); + } virtual ~ilink() { unlink(); } /*lint -e1740 */ }; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8f73087979f..79d284a5952 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -92,6 +92,7 @@ #include "transaction.h" #include "sql_audit.h" #include "sql_prepare.h" +#include "sql_cte.h" #include "debug_sync.h" #include "probes_mysql.h" #include "set_var.h" @@ -110,7 +111,7 @@ #include "wsrep_thd.h" static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, - Parser_state *parser_state); + Parser_state *parser_state, bool is_next_command); /** @defgroup Runtime_Environment Runtime Environment @@ -118,8 +119,6 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, */ /* Used in error handling only */ -#define SP_TYPE_STRING(LP) \ - ((LP)->sphead->m_type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE") #define SP_COM_STRING(LP) \ ((LP)->sql_command == SQLCOM_CREATE_SPFUNCTION || \ (LP)->sql_command == SQLCOM_ALTER_FUNCTION || \ @@ -136,38 +135,263 @@ static bool check_rename_table(THD *, TABLE_LIST *, TABLE_LIST *); const char *any_db="*any*"; // Special symbol for check_access -const LEX_STRING command_name[]={ - { C_STRING_WITH_LEN("Sleep") }, - { C_STRING_WITH_LEN("Quit") }, - { C_STRING_WITH_LEN("Init DB") }, - { C_STRING_WITH_LEN("Query") }, - { C_STRING_WITH_LEN("Field List") }, - { C_STRING_WITH_LEN("Create DB") }, - { C_STRING_WITH_LEN("Drop DB") }, - { C_STRING_WITH_LEN("Refresh") }, - { C_STRING_WITH_LEN("Shutdown") }, - { C_STRING_WITH_LEN("Statistics") }, - { C_STRING_WITH_LEN("Processlist") }, - { C_STRING_WITH_LEN("Connect") }, - { C_STRING_WITH_LEN("Kill") }, - { C_STRING_WITH_LEN("Debug") }, - { C_STRING_WITH_LEN("Ping") }, - { C_STRING_WITH_LEN("Time") }, - { C_STRING_WITH_LEN("Delayed insert") }, - { C_STRING_WITH_LEN("Change user") }, - { C_STRING_WITH_LEN("Binlog Dump") }, - { C_STRING_WITH_LEN("Table Dump") }, - { C_STRING_WITH_LEN("Connect Out") }, - { C_STRING_WITH_LEN("Register Slave") }, - { C_STRING_WITH_LEN("Prepare") }, - { C_STRING_WITH_LEN("Execute") }, - { C_STRING_WITH_LEN("Long Data") }, - { C_STRING_WITH_LEN("Close stmt") }, - { C_STRING_WITH_LEN("Reset stmt") }, - { C_STRING_WITH_LEN("Set option") }, - { C_STRING_WITH_LEN("Fetch") }, - { C_STRING_WITH_LEN("Daemon") }, - { C_STRING_WITH_LEN("Error") } // Last command number +const LEX_STRING command_name[257]={ + { C_STRING_WITH_LEN("Sleep") }, //0 + { C_STRING_WITH_LEN("Quit") }, //1 + { C_STRING_WITH_LEN("Init DB") }, //2 + { C_STRING_WITH_LEN("Query") }, //3 + { C_STRING_WITH_LEN("Field List") }, //4 + { C_STRING_WITH_LEN("Create DB") }, //5 + { C_STRING_WITH_LEN("Drop DB") }, //6 + { C_STRING_WITH_LEN("Refresh") }, //7 + { C_STRING_WITH_LEN("Shutdown") }, //8 + { C_STRING_WITH_LEN("Statistics") }, //9 + { C_STRING_WITH_LEN("Processlist") }, //10 + { C_STRING_WITH_LEN("Connect") }, //11 + { C_STRING_WITH_LEN("Kill") }, //12 + { C_STRING_WITH_LEN("Debug") }, //13 + { C_STRING_WITH_LEN("Ping") }, //14 + { C_STRING_WITH_LEN("Time") }, //15 + { C_STRING_WITH_LEN("Delayed insert") }, //16 + { C_STRING_WITH_LEN("Change user") }, //17 + { C_STRING_WITH_LEN("Binlog Dump") }, //18 + { C_STRING_WITH_LEN("Table Dump") }, //19 + { C_STRING_WITH_LEN("Connect Out") }, //20 + { C_STRING_WITH_LEN("Register Slave") }, //21 + { C_STRING_WITH_LEN("Prepare") }, //22 + { C_STRING_WITH_LEN("Execute") }, //23 + { C_STRING_WITH_LEN("Long Data") }, //24 + { C_STRING_WITH_LEN("Close stmt") }, //25 + { C_STRING_WITH_LEN("Reset stmt") }, //26 + { C_STRING_WITH_LEN("Set option") }, //27 + { C_STRING_WITH_LEN("Fetch") }, //28 + { C_STRING_WITH_LEN("Daemon") }, //29 + { 0, 0 }, //30 + { 0, 0 }, //31 + { 0, 0 }, //32 + { 0, 0 }, //33 + { 0, 0 }, //34 + { 0, 0 }, //35 + { 0, 0 }, //36 + { 0, 0 }, //37 + { 0, 0 }, //38 + { 0, 0 }, //39 + { 0, 0 }, //40 + { 0, 0 }, //41 + { 0, 0 }, //42 + { 0, 0 }, //43 + { 0, 0 }, //44 + { 0, 0 }, //45 + { 0, 0 }, //46 + { 0, 0 }, //47 + { 0, 0 }, //48 + { 0, 0 }, //49 + { 0, 0 }, //50 + { 0, 0 }, //51 + { 0, 0 }, //52 + { 0, 0 }, //53 + { 0, 0 }, //54 + { 0, 0 }, //55 + { 0, 0 }, //56 + { 0, 0 }, //57 + { 0, 0 }, //58 + { 0, 0 }, //59 + { 0, 0 }, //60 + { 0, 0 }, //61 + { 0, 0 }, //62 + { 0, 0 }, //63 + { 0, 0 }, //64 + { 0, 0 }, //65 + { 0, 0 }, //66 + { 0, 0 }, //67 + { 0, 0 }, //68 + { 0, 0 }, //69 + { 0, 0 }, //70 + { 0, 0 }, //71 + { 0, 0 }, //72 + { 0, 0 }, //73 + { 0, 0 }, //74 + { 0, 0 }, //75 + { 0, 0 }, //76 + { 0, 0 }, //77 + { 0, 0 }, //78 + { 0, 0 }, //79 + { 0, 0 }, //80 + { 0, 0 }, //81 + { 0, 0 }, //82 + { 0, 0 }, //83 + { 0, 0 }, //84 + { 0, 0 }, //85 + { 0, 0 }, //86 + { 0, 0 }, //87 + { 0, 0 }, //88 + { 0, 0 }, //89 + { 0, 0 }, //90 + { 0, 0 }, //91 + { 0, 0 }, //92 + { 0, 0 }, //93 + { 0, 0 }, //94 + { 0, 0 }, //95 + { 0, 0 }, //96 + { 0, 0 }, //97 + { 0, 0 }, //98 + { 0, 0 }, //99 + { 0, 0 }, //100 + { 0, 0 }, //101 + { 0, 0 }, //102 + { 0, 0 }, //103 + { 0, 0 }, //104 + { 0, 0 }, //105 + { 0, 0 }, //106 + { 0, 0 }, //107 + { 0, 0 }, //108 + { 0, 0 }, //109 + { 0, 0 }, //110 + { 0, 0 }, //111 + { 0, 0 }, //112 + { 0, 0 }, //113 + { 0, 0 }, //114 + { 0, 0 }, //115 + { 0, 0 }, //116 + { 0, 0 }, //117 + { 0, 0 }, //118 + { 0, 0 }, //119 + { 0, 0 }, //120 + { 0, 0 }, //121 + { 0, 0 }, //122 + { 0, 0 }, //123 + { 0, 0 }, //124 + { 0, 0 }, //125 + { 0, 0 }, //126 + { 0, 0 }, //127 + { 0, 0 }, //128 + { 0, 0 }, //129 + { 0, 0 }, //130 + { 0, 0 }, //131 + { 0, 0 }, //132 + { 0, 0 }, //133 + { 0, 0 }, //134 + { 0, 0 }, //135 + { 0, 0 }, //136 + { 0, 0 }, //137 + { 0, 0 }, //138 + { 0, 0 }, //139 + { 0, 0 }, //140 + { 0, 0 }, //141 + { 0, 0 }, //142 + { 0, 0 }, //143 + { 0, 0 }, //144 + { 0, 0 }, //145 + { 0, 0 }, //146 + { 0, 0 }, //147 + { 0, 0 }, //148 + { 0, 0 }, //149 + { 0, 0 }, //150 + { 0, 0 }, //151 + { 0, 0 }, //152 + { 0, 0 }, //153 + { 0, 0 }, //154 + { 0, 0 }, //155 + { 0, 0 }, //156 + { 0, 0 }, //157 + { 0, 0 }, //158 + { 0, 0 }, //159 + { 0, 0 }, //160 + { 0, 0 }, //161 + { 0, 0 }, //162 + { 0, 0 }, //163 + { 0, 0 }, //164 + { 0, 0 }, //165 + { 0, 0 }, //166 + { 0, 0 }, //167 + { 0, 0 }, //168 + { 0, 0 }, //169 + { 0, 0 }, //170 + { 0, 0 }, //171 + { 0, 0 }, //172 + { 0, 0 }, //173 + { 0, 0 }, //174 + { 0, 0 }, //175 + { 0, 0 }, //176 + { 0, 0 }, //177 + { 0, 0 }, //178 + { 0, 0 }, //179 + { 0, 0 }, //180 + { 0, 0 }, //181 + { 0, 0 }, //182 + { 0, 0 }, //183 + { 0, 0 }, //184 + { 0, 0 }, //185 + { 0, 0 }, //186 + { 0, 0 }, //187 + { 0, 0 }, //188 + { 0, 0 }, //189 + { 0, 0 }, //190 + { 0, 0 }, //191 + { 0, 0 }, //192 + { 0, 0 }, //193 + { 0, 0 }, //194 + { 0, 0 }, //195 + { 0, 0 }, //196 + { 0, 0 }, //197 + { 0, 0 }, //198 + { 0, 0 }, //199 + { 0, 0 }, //200 + { 0, 0 }, //201 + { 0, 0 }, //202 + { 0, 0 }, //203 + { 0, 0 }, //204 + { 0, 0 }, //205 + { 0, 0 }, //206 + { 0, 0 }, //207 + { 0, 0 }, //208 + { 0, 0 }, //209 + { 0, 0 }, //210 + { 0, 0 }, //211 + { 0, 0 }, //212 + { 0, 0 }, //213 + { 0, 0 }, //214 + { 0, 0 }, //215 + { 0, 0 }, //216 + { 0, 0 }, //217 + { 0, 0 }, //218 + { 0, 0 }, //219 + { 0, 0 }, //220 + { 0, 0 }, //221 + { 0, 0 }, //222 + { 0, 0 }, //223 + { 0, 0 }, //224 + { 0, 0 }, //225 + { 0, 0 }, //226 + { 0, 0 }, //227 + { 0, 0 }, //228 + { 0, 0 }, //229 + { 0, 0 }, //230 + { 0, 0 }, //231 + { 0, 0 }, //232 + { 0, 0 }, //233 + { 0, 0 }, //234 + { 0, 0 }, //235 + { 0, 0 }, //236 + { 0, 0 }, //237 + { 0, 0 }, //238 + { 0, 0 }, //239 + { 0, 0 }, //240 + { 0, 0 }, //241 + { 0, 0 }, //242 + { 0, 0 }, //243 + { 0, 0 }, //244 + { 0, 0 }, //245 + { 0, 0 }, //246 + { 0, 0 }, //247 + { 0, 0 }, //248 + { 0, 0 }, //249 + { 0, 0 }, //250 + { 0, 0 }, //251 + { 0, 0 }, //252 + { 0, 0 }, //253 + { C_STRING_WITH_LEN("Com_multi") }, //254 + { C_STRING_WITH_LEN("Error") } // Last command number 255 }; const char *xa_state_names[]={ @@ -269,7 +493,7 @@ void init_update_queries(void) memset(server_command_flags, 0, sizeof(server_command_flags)); server_command_flags[COM_STATISTICS]= CF_SKIP_QUERY_ID | CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK; - server_command_flags[COM_PING]= CF_SKIP_QUERY_ID | CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK; + server_command_flags[COM_PING]= CF_SKIP_QUERY_ID | CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK | CF_NO_COM_MULTI; server_command_flags[COM_QUIT]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_PROCESS_INFO]= CF_SKIP_WSREP_CHECK; @@ -278,6 +502,10 @@ void init_update_queries(void) server_command_flags[COM_SLEEP]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_TIME]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_END]= CF_SKIP_WSREP_CHECK; + for (uint i= COM_MDB_GAP_BEG; i <= COM_MDB_GAP_END; i++) + { + server_command_flags[i]= CF_SKIP_WSREP_CHECK; + } /* COM_QUERY, COM_SET_OPTION and COM_STMT_XXX are allowed to pass the early @@ -290,6 +518,7 @@ void init_update_queries(void) server_command_flags[COM_STMT_RESET]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_EXECUTE]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_SEND_LONG_DATA]= CF_SKIP_WSREP_CHECK; + server_command_flags[COM_MULTI]= CF_SKIP_WSREP_CHECK | CF_NO_COM_MULTI; /* Initialize the sql command flags array. */ memset(sql_command_flags, 0, sizeof(sql_command_flags)); @@ -417,6 +646,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_SHOW_EXPLAIN]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_GRANTS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_CREATE_USER]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND; @@ -438,6 +668,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_CREATE_USER]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_RENAME_USER]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_DROP_USER]= CF_CHANGES_DATA; + sql_command_flags[SQLCOM_ALTER_USER]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_CREATE_ROLE]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_GRANT]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_GRANT_ROLE]= CF_CHANGES_DATA; @@ -494,6 +725,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_CHECKSUM]= CF_REPORT_PROGRESS; sql_command_flags[SQLCOM_CREATE_USER]|= CF_AUTO_COMMIT_TRANS; + sql_command_flags[SQLCOM_ALTER_USER]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_DROP_USER]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_RENAME_USER]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_CREATE_ROLE]|= CF_AUTO_COMMIT_TRANS; @@ -587,6 +819,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_ALTER_EVENT]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_DROP_EVENT]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_CREATE_USER]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_ALTER_USER]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_RENAME_USER]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_DROP_USER]|= CF_DISALLOW_IN_RO_TRANS; sql_command_flags[SQLCOM_CREATE_SERVER]|= CF_DISALLOW_IN_RO_TRANS; @@ -637,7 +870,7 @@ void execute_init_command(THD *thd, LEX_STRING *init_command, mysql_rwlock_t *var_lock) { Vio* save_vio; - ulong save_client_capabilities; + ulonglong save_client_capabilities; mysql_rwlock_rdlock(var_lock); if (!init_command->length) @@ -669,7 +902,7 @@ void execute_init_command(THD *thd, LEX_STRING *init_command, */ save_vio= thd->net.vio; thd->net.vio= 0; - dispatch_command(COM_QUERY, thd, buf, len); + dispatch_command(COM_QUERY, thd, buf, len, FALSE, FALSE); thd->client_capabilities= save_client_capabilities; thd->net.vio= save_vio; @@ -787,7 +1020,7 @@ static void handle_bootstrap_impl(THD *thd) break; } - mysql_parse(thd, thd->query(), length, &parser_state); + mysql_parse(thd, thd->query(), length, &parser_state, FALSE); bootstrap_error= thd->is_error(); thd->protocol->end_statement(); @@ -844,12 +1077,13 @@ end: delete thd; #ifndef EMBEDDED_LIBRARY - thread_safe_decrement32(&thread_count); + DBUG_ASSERT(thread_count == 1); in_bootstrap= FALSE; - - mysql_mutex_lock(&LOCK_thread_count); - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); + /* + dec_thread_count will signal bootstrap() function that we have ended as + thread_count will become 0. + */ + dec_thread_count(); my_thread_end(); pthread_exit(0); #endif @@ -884,6 +1118,23 @@ void cleanup_items(Item *item) DBUG_VOID_RETURN; } +static enum enum_server_command fetch_command(THD *thd, char *packet) +{ + enum enum_server_command + command= (enum enum_server_command) (uchar) packet[0]; + NET *net= &thd->net; + DBUG_ENTER("fetch_command"); + + if (command >= COM_END || + (command >= COM_MDB_GAP_BEG && command <= COM_MDB_GAP_END)) + command= COM_END; // Wrong command + + DBUG_PRINT("info",("Command on %s = %d (%s)", + vio_description(net->vio), command, + command_name[command].str)); + DBUG_RETURN(command); +} + #ifndef EMBEDDED_LIBRARY @@ -954,7 +1205,6 @@ bool do_command(THD *thd) if(!thd->skip_wait_timeout) my_net_set_read_timeout(net, thd->variables.net_wait_timeout); - /* XXX: this code is here only to clear possible errors of init_connect. Consider moving to init_connect() instead. @@ -1073,14 +1323,8 @@ bool do_command(THD *thd) /* Do not rely on my_net_read, extra safety against programming errors. */ packet[packet_length]= '\0'; /* safety */ - command= (enum enum_server_command) (uchar) packet[0]; - if (command >= COM_END) - command= COM_END; // Wrong command - - DBUG_PRINT("info",("Command on %s = %d (%s)", - vio_description(net->vio), command, - command_name[command].str)); + command= fetch_command(thd, packet); #ifdef WITH_WSREP /* @@ -1106,7 +1350,8 @@ bool do_command(THD *thd) DBUG_ASSERT(packet_length); DBUG_ASSERT(!thd->apc_target.is_enabled()); - return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length-1)); + return_value= dispatch_command(command, thd, packet+1, + (uint) (packet_length-1), FALSE, FALSE); #ifdef WITH_WSREP if (WSREP(thd)) { @@ -1124,7 +1369,7 @@ bool do_command(THD *thd) my_charset_latin1.csname); } return_value= dispatch_command(command, thd, thd->wsrep_retry_query, - thd->wsrep_retry_query_len); + thd->wsrep_retry_query_len, FALSE, FALSE); thd->variables.character_set_client = current_charset; } @@ -1216,6 +1461,44 @@ static my_bool deny_updates_if_read_only_option(THD *thd, /** + check COM_MULTI packet + + @param thd thread handle + @param packet pointer on the packet of commands + @param packet_length length of this packet + + @retval 0 - Error + @retval # - Number of commands in the batch +*/ + +uint maria_multi_check(THD *thd, char *packet, uint packet_length) +{ + uint counter= 0; + DBUG_ENTER("maria_multi_check"); + while (packet_length) + { + // length of command + 3 bytes where that length was stored + uint subpacket_length= (uint3korr(packet) + 3); + DBUG_PRINT("info", ("sub-packet length: %d command: %x", + subpacket_length, packet[3])); + + if (subpacket_length == 3 || + subpacket_length > packet_length) + { + my_message(ER_UNKNOWN_COM_ERROR, ER_THD(thd, ER_UNKNOWN_COM_ERROR), + MYF(0)); + DBUG_RETURN(0); + } + + counter++; + packet+= subpacket_length; + packet_length-= subpacket_length; + } + DBUG_RETURN(counter); +} + + +/** Perform one connection-level (COM_XXXX) command. @param command type of command to perform @@ -1224,6 +1507,8 @@ static my_bool deny_updates_if_read_only_option(THD *thd, @param packet_length length of packet + 1 (to show that data is null-terminated) except for COM_SLEEP, where it can be zero. + @param is_com_multi recursive call from COM_MULTI + @param is_next_command there will be more command in the COM_MULTI batch @todo set thd->lex->sql_command to SQLCOM_END here. @@ -1237,15 +1522,24 @@ static my_bool deny_updates_if_read_only_option(THD *thd, COM_QUIT/COM_SHUTDOWN */ bool dispatch_command(enum enum_server_command command, THD *thd, - char* packet, uint packet_length) + char* packet, uint packet_length, bool is_com_multi, + bool is_next_command) { NET *net= &thd->net; bool error= 0; bool do_end_of_statement= true; DBUG_ENTER("dispatch_command"); - DBUG_PRINT("info", ("command: %d", command)); + DBUG_PRINT("info", ("command: %d %s", command, + (command_name[command].str != 0 ? + command_name[command].str : + "<?>"))); + bool drop_more_results= 0; + + if (!is_com_multi) + inc_thread_running(); - inc_thread_running(); + /* keep it withing 1 byte */ + compile_time_assert(COM_END == 255); #ifdef WITH_WSREP if (WSREP(thd)) @@ -1335,6 +1629,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, beginning of each command. */ thd->server_status&= ~SERVER_STATUS_CLEAR_SET; + if (is_next_command) + { + drop_more_results= !MY_TEST(thd->server_status & + SERVER_MORE_RESULTS_EXISTS); + thd->server_status|= SERVER_MORE_RESULTS_EXISTS; + } + switch (command) { case COM_INIT_DB: { @@ -1353,6 +1654,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #ifdef HAVE_REPLICATION case COM_REGISTER_SLAVE: { + status_var_increment(thd->status_var.com_register_slave); if (!register_slave(thd, (uchar*)packet, packet_length)) my_ok(thd); break; @@ -1482,9 +1784,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; if (WSREP_ON) - wsrep_mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); + wsrep_mysql_parse(thd, thd->query(), thd->query_length(), &parser_state, + is_next_command); else - mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); + mysql_parse(thd, thd->query(), thd->query_length(), &parser_state, + is_next_command); while (!thd->killed && (parser_state.m_lip.found_semicolon != NULL) && ! thd->is_error()) @@ -1569,9 +1873,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* TODO: set thd->lex->sql_command to SQLCOM_END here */ if (WSREP_ON) - wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); + wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state, + is_next_command); else - mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); + mysql_parse(thd, beginning_of_next_stmt, length, &parser_state, + is_next_command); } @@ -1623,6 +1929,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } packet= arg_end + 1; thd->reset_for_next_command(); + // thd->reset_for_next_command reset state => restore it + if (is_next_command) + thd->server_status|= SERVER_MORE_RESULTS_EXISTS; lex_start(thd); /* Must be before we init the table list. */ if (lower_case_table_names) @@ -1901,6 +2210,66 @@ bool dispatch_command(enum enum_server_command command, THD *thd, general_log_print(thd, command, NullS); my_eof(thd); break; + case COM_MULTI: + { + uint counter; + uint current_com= 0; + DBUG_ASSERT(!is_com_multi); + if (!(thd->client_capabilities & CLIENT_MULTI_RESULTS)) + { + /* The client does not support multiple result sets being sent back */ + my_error(ER_COMMULTI_BADCONTEXT, MYF(0)); + break; + } + + if (!(counter= maria_multi_check(thd, packet, packet_length))) + break; + + { + /* We have to store next length because it will be destroyed by '\0' */ + uint next_subpacket_length= uint3korr(packet); + unsigned char *readbuff= net->buff; + + if (net_allocate_new_packet(net, thd, MYF(0))) + break; + + while (packet_length) + { + current_com++; + uint subpacket_length= next_subpacket_length + 3; + if (subpacket_length < packet_length) + next_subpacket_length= uint3korr(packet + subpacket_length); + /* safety like in do_command() */ + packet[subpacket_length]= '\0'; + + enum enum_server_command subcommand= fetch_command(thd, (packet + 3)); + + if (server_command_flags[subcommand] & CF_NO_COM_MULTI) + { + my_error(ER_BAD_COMMAND_IN_MULTI, MYF(0), command_name[subcommand]); + goto com_multi_end; + } + + if (dispatch_command(subcommand, thd, packet + (1 + 3), + subpacket_length - (1 + 3), TRUE, + (current_com != counter))) + { + DBUG_ASSERT(thd->is_error()); + goto com_multi_end; + } + + DBUG_ASSERT(subpacket_length <= packet_length); + packet+= subpacket_length; + packet_length-= subpacket_length; + } + +com_multi_end: + /* release old buffer */ + DBUG_ASSERT(net->buff == net->write_pos); // nothing to send + my_free(readbuff); + } + break; + } case COM_SLEEP: case COM_CONNECT: // Impossible here case COM_TIME: // Impossible from client @@ -1937,9 +2306,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd_proc_info(thd, "updating status"); /* Finalize server status flags after executing a command. */ thd->update_server_status(); - thd->protocol->end_statement(); - query_cache_end_of_result(thd); + if (command != COM_MULTI) + { + thd->protocol->end_statement(); + query_cache_end_of_result(thd); + } } + if (drop_more_results) + thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS; if (!thd->is_error() && !thd->killed_errno()) mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0); @@ -1963,8 +2337,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->m_statement_psi= NULL; thd->m_digest= NULL; - dec_thread_running(); - thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory + if (!is_com_multi) + { + dec_thread_running(); + thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory + } free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); #if defined(ENABLED_PROFILING) @@ -2829,7 +3206,8 @@ mysql_execute_command(THD *thd) thd->mdl_context.release_transactional_locks(); if (commit_failed) { - WSREP_DEBUG("implicit commit failed, MDL released: %lu", thd->thread_id); + WSREP_DEBUG("implicit commit failed, MDL released: %lld", + (longlong) thd->thread_id); goto error; } } @@ -4516,6 +4894,11 @@ end_with_restore_list: db_name.str= db_name_buff; db_name.length= lex->name.length; strmov(db_name.str, lex->name.str); + +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error; +#endif /* WITH_WSREP */ + if (check_db_name(&db_name)) { my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str); @@ -4569,6 +4952,9 @@ end_with_restore_list: /* lex->unit.cleanup() is called outside, no need to call it here */ break; case SQLCOM_SHOW_CREATE_EVENT: +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error; +#endif /* WITH_WSREP */ res= Events::show_create_event(thd, lex->spname->m_db, lex->spname->m_name); break; @@ -4628,6 +5014,7 @@ end_with_restore_list: my_ok(thd); break; } + case SQLCOM_ALTER_USER: case SQLCOM_RENAME_USER: { if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1) && @@ -4635,7 +5022,11 @@ end_with_restore_list: break; /* Conditionally writes to binlog */ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) - if (!(res= mysql_rename_user(thd, lex->users_list))) + if (lex->sql_command == SQLCOM_ALTER_USER) + res= mysql_alter_user(thd, lex->users_list); + else + res= mysql_rename_user(thd, lex->users_list); + if (!res) my_ok(thd); break; } @@ -4797,16 +5188,29 @@ end_with_restore_list: #ifdef WITH_WSREP if (lex->type & ( - REFRESH_GRANT | - REFRESH_HOSTS | - REFRESH_DES_KEY_FILE | + REFRESH_GRANT | + REFRESH_HOSTS | +#ifdef HAVE_OPENSSL + REFRESH_DES_KEY_FILE | +#endif + /* + Write all flush log statements except + FLUSH LOGS + FLUSH BINARY LOGS + Check reload_acl_and_cache for why. + */ + REFRESH_RELAY_LOG | + REFRESH_SLOW_LOG | + REFRESH_GENERAL_LOG | + REFRESH_ENGINE_LOG | + REFRESH_ERROR_LOG | #ifdef HAVE_QUERY_CACHE - REFRESH_QUERY_CACHE_FREE | + REFRESH_QUERY_CACHE_FREE | #endif /* HAVE_QUERY_CACHE */ - REFRESH_STATUS | - REFRESH_USER_RESOURCES)) + REFRESH_STATUS | + REFRESH_USER_RESOURCES)) { - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + WSREP_TO_ISOLATION_BEGIN_WRTCHK(WSREP_MYSQL_DB, NULL, NULL) } #endif /* WITH_WSREP*/ @@ -4840,11 +5244,11 @@ end_with_restore_list: */ if (first_table) { - WSREP_TO_ISOLATION_BEGIN(NULL, NULL, first_table); + WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table); } else { - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); + WSREP_TO_ISOLATION_BEGIN_WRTCHK(WSREP_MYSQL_DB, NULL, NULL); } } #endif /* WITH_WSREP */ @@ -4915,6 +5319,7 @@ end_with_restore_list: break; #ifndef NO_EMBEDDED_ACCESS_CHECKS + case SQLCOM_SHOW_CREATE_USER: case SQLCOM_SHOW_GRANTS: { LEX_USER *grant_user= lex->grant_user; @@ -4931,7 +5336,10 @@ end_with_restore_list: grant_user->user.str == current_user_and_current_role.str || !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0)) { - res = mysql_show_grants(thd, grant_user); + if (lex->sql_command == SQLCOM_SHOW_GRANTS) + res = mysql_show_grants(thd, grant_user); + else + res = mysql_show_create_user(thd, grant_user); } break; } @@ -4968,7 +5376,8 @@ end_with_restore_list: if (trans_begin(thd, lex->start_transaction_opt)) { thd->mdl_context.release_transactional_locks(); - WSREP_DEBUG("BEGIN failed, MDL released: %lu", thd->thread_id); + WSREP_DEBUG("BEGIN failed, MDL released: %lld", + (longlong) thd->thread_id); goto error; } my_ok(thd); @@ -4987,7 +5396,8 @@ end_with_restore_list: thd->mdl_context.release_transactional_locks(); if (commit_failed) { - WSREP_DEBUG("COMMIT failed, MDL released: %lu", thd->thread_id); + WSREP_DEBUG("COMMIT failed, MDL released: %lld", + (longlong) thd->thread_id); goto error; } /* Begin transaction with the same isolation level. */ @@ -5034,7 +5444,8 @@ end_with_restore_list: if (rollback_failed) { - WSREP_DEBUG("rollback failed, MDL released: %lu", thd->thread_id); + WSREP_DEBUG("rollback failed, MDL released: %lld", + (longlong) thd->thread_id); goto error; } /* Begin transaction with the same isolation level. */ @@ -5082,7 +5493,6 @@ end_with_restore_list: { uint namelen; char *name; - int sp_result= SP_INTERNAL_ERROR; DBUG_ASSERT(lex->sphead != 0); DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */ @@ -5093,23 +5503,12 @@ end_with_restore_list: if (check_db_name(&lex->sphead->m_db)) { my_error(ER_WRONG_DB_NAME, MYF(0), lex->sphead->m_db.str); - goto create_sp_error; + goto error; } if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, NULL, NULL, 0, 0)) - goto create_sp_error; - - /* - Check that a database directory with this name - exists. Design note: This won't work on virtual databases - like information_schema. - */ - if (check_db_dir_existence(lex->sphead->m_db.str)) - { - my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str); - goto create_sp_error; - } + goto error; /* Checking the drop permissions if CREATE OR REPLACE is used */ if (lex->create_info.or_replace()) @@ -5117,7 +5516,7 @@ end_with_restore_list: if (check_routine_access(thd, ALTER_PROC_ACL, lex->spname->m_db.str, lex->spname->m_name.str, lex->sql_command == SQLCOM_DROP_PROCEDURE, 0)) - goto create_sp_error; + goto error; } name= lex->sphead->name(&namelen); @@ -5129,18 +5528,17 @@ end_with_restore_list: if (udf) { my_error(ER_UDF_EXISTS, MYF(0), name); - goto create_sp_error; + goto error; } } #endif if (sp_process_definer(thd)) - goto create_sp_error; + goto error; WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) - res= (sp_result= sp_create_routine(thd, lex->sphead->m_type, lex->sphead)); - switch (sp_result) { - case SP_OK: { + if (!sp_create_routine(thd, lex->sphead->m_type, lex->sphead)) + { #ifndef NO_EMBEDDED_ACCESS_CHECKS /* only add privileges if really neccessary */ @@ -5205,31 +5603,8 @@ end_with_restore_list: } #endif - break; } - case SP_WRITE_ROW_FAILED: - my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name); - break; - case SP_BAD_IDENTIFIER: - my_error(ER_TOO_LONG_IDENT, MYF(0), name); - break; - case SP_BODY_TOO_LONG: - my_error(ER_TOO_LONG_BODY, MYF(0), name); - break; - case SP_FLD_STORE_FAILED: - my_error(ER_CANT_CREATE_SROUTINE, MYF(0), name); - break; - default: - my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name); - break; - } /* end switch */ - - /* - Capture all errors within this CASE and - clean up the environment. - */ -create_sp_error: - if (sp_result != SP_OK ) + else goto error; my_ok(thd); break; /* break super switch */ @@ -5446,12 +5821,18 @@ create_sp_error: } case SQLCOM_SHOW_CREATE_PROC: { +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error; +#endif /* WITH_WSREP */ if (sp_show_create_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname)) goto error; break; } case SQLCOM_SHOW_CREATE_FUNC: { +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error; +#endif /* WITH_WSREP */ if (sp_show_create_routine(thd, TYPE_ENUM_FUNCTION, lex->spname)) goto error; break; @@ -5464,6 +5845,9 @@ create_sp_error: stored_procedure_type type= (lex->sql_command == SQLCOM_SHOW_PROC_CODE ? TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION); +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error; +#endif /* WITH_WSREP */ if (sp_cache_routine(thd, type, lex->spname, FALSE, &sp)) goto error; if (!sp || sp->show_routine_code(thd)) @@ -5488,6 +5872,9 @@ create_sp_error: goto error; } +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && wsrep_sync_wait(thd)) goto error; +#endif /* WITH_WSREP */ if (show_create_trigger(thd, lex->spname)) goto error; /* Error has been already logged. */ @@ -5548,7 +5935,8 @@ create_sp_error: thd->mdl_context.release_transactional_locks(); if (commit_failed) { - WSREP_DEBUG("XA commit failed, MDL released: %lu", thd->thread_id); + WSREP_DEBUG("XA commit failed, MDL released: %lld", + (longlong) thd->thread_id); goto error; } /* @@ -5566,7 +5954,8 @@ create_sp_error: thd->mdl_context.release_transactional_locks(); if (rollback_failed) { - WSREP_DEBUG("XA rollback failed, MDL released: %lu", thd->thread_id); + WSREP_DEBUG("XA rollback failed, MDL released: %lld", + (longlong) thd->thread_id); goto error; } /* @@ -5615,6 +6004,8 @@ create_sp_error: if (check_global_access(thd, SUPER_ACL)) break; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + res= create_server(thd, &lex->server_options); break; } @@ -5626,6 +6017,8 @@ create_sp_error: if (check_global_access(thd, SUPER_ACL)) break; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + if ((error= alter_server(thd, &lex->server_options))) { DBUG_PRINT("info", ("problem altering server <%s>", @@ -5644,6 +6037,8 @@ create_sp_error: if (check_global_access(thd, SUPER_ACL)) break; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + if ((err_code= drop_server(thd, &lex->server_options))) { if (! lex->if_exists() && err_code == ER_FOREIGN_SERVER_DOESNT_EXIST) @@ -5797,8 +6192,8 @@ finish: ! thd->in_active_multi_stmt_transaction() && thd->mdl_context.has_transactional_locks()) { - WSREP_DEBUG("Forcing release of transactional locks for thd %lu", - thd->thread_id); + WSREP_DEBUG("Forcing release of transactional locks for thd: %lld", + (longlong) thd->thread_id); thd->mdl_context.release_transactional_locks(); } #endif /* WITH_WSREP */ @@ -5820,6 +6215,9 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) new (thd->mem_root) Item_int(thd, (ulonglong) thd->variables.select_limit); } + if (check_dependencies_in_with_clauses(lex->with_clauses_list)) + return 1; + if (!(res= open_and_lock_tables(thd, all_tables, TRUE, 0))) { if (lex->describe) @@ -7102,7 +7500,7 @@ void mysql_init_multi_delete(LEX *lex) } static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, - Parser_state *parser_state) + Parser_state *parser_state, bool is_next_command) { #ifdef WITH_WSREP bool is_autocommit= @@ -7121,7 +7519,7 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, thd->query(), thd->query_length()); } - mysql_parse(thd, rawbuf, length, parser_state); + mysql_parse(thd, rawbuf, length, parser_state, is_next_command); if (WSREP(thd)) { /* wsrep BF abort in query exec phase */ @@ -7164,10 +7562,11 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, } else { - WSREP_DEBUG("%s, thd: %lu is_AC: %d, retry: %lu - %lu SQL: %s", + WSREP_DEBUG("%s, thd: %lld is_AC: %d, retry: %lu - %lu SQL: %s", (thd->wsrep_conflict_state == ABORTED) ? "BF Aborted" : "cert failure", - thd->thread_id, is_autocommit, thd->wsrep_retry_counter, + (longlong) thd->thread_id, is_autocommit, + thd->wsrep_retry_counter, thd->variables.wsrep_retry_autocommit, thd->query()); my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); thd->killed= NOT_KILLED; @@ -7218,10 +7617,11 @@ static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, @param length Length of the query text @param[out] found_semicolon For multi queries, position of the character of the next query in the query text. + @param is_next_command there will be more command in the COM_MULTI batch */ void mysql_parse(THD *thd, char *rawbuf, uint length, - Parser_state *parser_state) + Parser_state *parser_state, bool is_next_command) { int error __attribute__((unused)); DBUG_ENTER("mysql_parse"); @@ -7245,6 +7645,8 @@ void mysql_parse(THD *thd, char *rawbuf, uint length, */ lex_start(thd); thd->reset_for_next_command(); + if (is_next_command) + thd->server_status|= SERVER_MORE_RESULTS_EXISTS; if (query_cache_send_result_to_client(thd, rawbuf, length) <= 0) { @@ -7278,7 +7680,6 @@ void mysql_parse(THD *thd, char *rawbuf, uint length, and Query_log_event::print() would give ';;' output). This also helps display only the current query in SHOW PROCESSLIST. - Note that we don't need LOCK_thread_count to modify query_length. */ if (found_semicolon && (ulong) (found_semicolon - thd->query())) thd->set_query_inner(thd->query(), @@ -7332,6 +7733,12 @@ void mysql_parse(THD *thd, char *rawbuf, uint length, sql_statement_info[SQLCOM_SELECT].m_key); status_var_increment(thd->status_var.com_stat[SQLCOM_SELECT]); thd->update_stats(); +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd)) + { + thd->wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED; + } +#endif /* WITH_WSREP */ } DBUG_VOID_RETURN; } @@ -7987,7 +8394,7 @@ bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg) @retval FALSE if all is OK @retval - TRUE if a memory allocation error occured + TRUE if a memory allocation error occurred */ bool @@ -8999,9 +9406,7 @@ void get_default_definer(THD *thd, LEX_USER *definer, bool role) } definer->user.length= strlen(definer->user.str); - definer->password= null_lex_str; - definer->plugin= empty_lex_str; - definer->auth= empty_lex_str; + definer->reset_auth(); } @@ -9059,7 +9464,7 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) definer->user= *user_name; definer->host= *host_name; - definer->password= null_lex_str; + definer->reset_auth(); return definer; } diff --git a/sql/sql_parse.h b/sql/sql_parse.h index 6cb49f267d2..53a9ed3b24c 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -35,6 +35,7 @@ enum enum_mysql_completiontype { extern "C" int test_if_data_home_dir(const char *dir); int error_if_data_home_dir(const char *path, const char *what); +my_bool net_allocate_new_packet(NET *net, void *thd, uint my_flags); bool multi_update_precheck(THD *thd, TABLE_LIST *tables); bool multi_delete_precheck(THD *thd, TABLE_LIST *tables); @@ -87,7 +88,7 @@ bool is_log_table_write_query(enum enum_sql_command command); bool alloc_query(THD *thd, const char *packet, uint packet_length); void mysql_init_select(LEX *lex); void mysql_parse(THD *thd, char *rawbuf, uint length, - Parser_state *parser_state); + Parser_state *parser_state, bool is_com_multi); bool mysql_new_select(LEX *lex, bool move_down); void create_select_for_variable(const char *var_name); void create_table_set_open_action_and_adjust_tables(LEX *lex); @@ -99,7 +100,8 @@ int mysql_execute_command(THD *thd); bool do_command(THD *thd); void do_handle_bootstrap(THD *thd); bool dispatch_command(enum enum_server_command command, THD *thd, - char* packet, uint packet_length); + char* packet, uint packet_length, + bool is_com_multi, bool is_next_command); void log_slow_statement(THD *thd); bool append_file_to_dir(THD *thd, const char **filename_ptr, const char *table_name); diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 0158ab7d206..dbe19674cf2 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1796,7 +1796,8 @@ static void plugin_load(MEM_ROOT *tmp_root) goto end; } - if (init_read_record(&read_record_info, new_thd, table, NULL, 1, 0, FALSE)) + if (init_read_record(&read_record_info, new_thd, table, NULL, NULL, 1, 0, + FALSE)) { sql_print_error("Could not initialize init_read_record; Plugins not " "loaded"); @@ -2152,7 +2153,8 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, */ unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE] = { MYSQL_AUDIT_GENERAL_CLASSMASK }; - mysql_audit_acquire_plugins(thd, event_class_mask); + if (mysql_audit_general_enabled()) + mysql_audit_acquire_plugins(thd, event_class_mask); mysql_mutex_lock(&LOCK_plugin); error= plugin_add(thd->mem_root, name, &dl, REPORT_TO_USER); @@ -2282,7 +2284,8 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name, */ unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE] = { MYSQL_AUDIT_GENERAL_CLASSMASK }; - mysql_audit_acquire_plugins(thd, event_class_mask); + if (mysql_audit_general_enabled()) + mysql_audit_acquire_plugins(thd, event_class_mask); mysql_mutex_lock(&LOCK_plugin); diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic index da0cc17250b..c3dfde18ab6 100644 --- a/sql/sql_plugin_services.ic +++ b/sql/sql_plugin_services.ic @@ -133,7 +133,7 @@ static struct wsrep_service_st wsrep_handler = { wsrep_thd_query_state_str, wsrep_thd_retry_counter, wsrep_thd_set_conflict_state, - wsrep_thd_skip_append_keys, + wsrep_thd_ignore_table, wsrep_thd_trx_seqno, wsrep_thd_ws_handle, wsrep_trx_is_aborting, diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index f309084c1bf..2d6a7302afc 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -102,7 +102,11 @@ When one supplies long data for a placeholder: #include "sql_acl.h" // *_ACL #include "sql_derived.h" // mysql_derived_prepare, // mysql_handle_derived +#include "sql_cte.h" #include "sql_cursor.h" +#include "sql_show.h" +#include "sql_repl.h" +#include "slave.h" #include "sp_head.h" #include "sp.h" #include "sp_cache.h" @@ -323,8 +327,14 @@ find_prepared_statement(THD *thd, ulong id) To strictly separate namespaces of SQL prepared statements and C API prepared statements find() will return 0 if there is a named prepared statement with such id. + + LAST_STMT_ID is special value which mean last prepared statement ID + (it was made for COM_MULTI to allow prepare and execute a statement + in the same command but usage is not limited by COM_MULTI only). */ - Statement *stmt= thd->stmt_map.find(id); + Statement *stmt= ((id == LAST_STMT_ID) ? + thd->last_stmt : + thd->stmt_map.find(id)); if (stmt == 0 || stmt->type() != Query_arena::PREPARED_STATEMENT) return NULL; @@ -1499,6 +1509,8 @@ static int mysql_test_select(Prepared_statement *stmt, lex->select_lex.context.resolve_in_select_list= TRUE; ulong privilege= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL; + if (check_dependencies_in_with_clauses(lex->with_clauses_list)) + goto error; if (tables) { if (check_table_access(thd, privilege, tables, FALSE, UINT_MAX, FALSE)) @@ -1802,6 +1814,191 @@ static bool mysql_test_create_table(Prepared_statement *stmt) } +static int send_stmt_metadata(THD *thd, Prepared_statement *stmt, List<Item> *fields) +{ + if (stmt->is_sql_prepare()) + return 0; + + if (send_prep_stmt(stmt, fields->elements) || + thd->protocol->send_result_set_metadata(fields, Protocol::SEND_EOF) || + thd->protocol->flush()) + return 1; + + return 2; +} + + +/** + Validate and prepare for execution SHOW CREATE TABLE statement. + + @param stmt prepared statement + @param tables list of tables used in this query + + @retval + FALSE success + @retval + TRUE error, error message is set in THD +*/ + +static int mysql_test_show_create_table(Prepared_statement *stmt, + TABLE_LIST *tables) +{ + DBUG_ENTER("mysql_test_show_create_table"); + THD *thd= stmt->thd; + List<Item> fields; + char buff[2048]; + String buffer(buff, sizeof(buff), system_charset_info); + + if (mysqld_show_create_get_fields(thd, tables, &fields, &buffer)) + DBUG_RETURN(1); + + DBUG_RETURN(send_stmt_metadata(thd, stmt, &fields)); +} + + +/** + Validate and prepare for execution SHOW CREATE DATABASE statement. + + @param stmt prepared statement + + @retval + FALSE success + @retval + TRUE error, error message is set in THD +*/ + +static int mysql_test_show_create_db(Prepared_statement *stmt) +{ + DBUG_ENTER("mysql_test_show_create_db"); + THD *thd= stmt->thd; + List<Item> fields; + + mysqld_show_create_db_get_fields(thd, &fields); + + DBUG_RETURN(send_stmt_metadata(thd, stmt, &fields)); +} + + +#ifndef NO_EMBEDDED_ACCESS_CHECKS +/** + Validate and prepare for execution SHOW GRANTS statement. + + @param stmt prepared statement + + @retval + FALSE success + @retval + TRUE error, error message is set in THD +*/ + +static int mysql_test_show_grants(Prepared_statement *stmt) +{ + DBUG_ENTER("mysql_test_show_grants"); + THD *thd= stmt->thd; + List<Item> fields; + + mysql_show_grants_get_fields(thd, &fields, "Grants for"); + + DBUG_RETURN(send_stmt_metadata(thd, stmt, &fields)); +} +#endif /*NO_EMBEDDED_ACCESS_CHECKS*/ + + +#ifndef EMBEDDED_LIBRARY +/** + Validate and prepare for execution SHOW SLAVE STATUS statement. + + @param stmt prepared statement + + @retval + FALSE success + @retval + TRUE error, error message is set in THD +*/ + +static int mysql_test_show_slave_status(Prepared_statement *stmt) +{ + DBUG_ENTER("mysql_test_show_slave_status"); + THD *thd= stmt->thd; + List<Item> fields; + + show_master_info_get_fields(thd, &fields, 0, 0); + + DBUG_RETURN(send_stmt_metadata(thd, stmt, &fields)); +} + + +/** + Validate and prepare for execution SHOW MASTER STATUS statement. + + @param stmt prepared statement + + @retval + FALSE success + @retval + TRUE error, error message is set in THD +*/ + +static int mysql_test_show_master_status(Prepared_statement *stmt) +{ + DBUG_ENTER("mysql_test_show_master_status"); + THD *thd= stmt->thd; + List<Item> fields; + + show_binlog_info_get_fields(thd, &fields); + + DBUG_RETURN(send_stmt_metadata(thd, stmt, &fields)); +} + + +/** + Validate and prepare for execution SHOW BINLOGS statement. + + @param stmt prepared statement + + @retval + FALSE success + @retval + TRUE error, error message is set in THD +*/ + +static int mysql_test_show_binlogs(Prepared_statement *stmt) +{ + DBUG_ENTER("mysql_test_show_binlogs"); + THD *thd= stmt->thd; + List<Item> fields; + + show_binlogs_get_fields(thd, &fields); + + DBUG_RETURN(send_stmt_metadata(thd, stmt, &fields)); +} + +#endif /* EMBEDDED_LIBRARY */ + + +/** + Validate and prepare for execution SHOW CREATE PROC/FUNC statement. + + @param stmt prepared statement + + @retval + FALSE success + @retval + TRUE error, error message is set in THD +*/ + +static int mysql_test_show_create_routine(Prepared_statement *stmt, int type) +{ + DBUG_ENTER("mysql_test_show_binlogs"); + THD *thd= stmt->thd; + List<Item> fields; + + sp_head::show_create_routine_get_fields(thd, type, &fields); + + DBUG_RETURN(send_stmt_metadata(thd, stmt, &fields)); +} + + /** @brief Validate and prepare for execution CREATE VIEW statement @@ -1810,7 +2007,7 @@ static bool mysql_test_create_table(Prepared_statement *stmt) @note This function handles create view commands. @retval FALSE Operation was a success. - @retval TRUE An error occured. + @retval TRUE An error occurred. */ static bool mysql_test_create_view(Prepared_statement *stmt) @@ -2135,7 +2332,66 @@ static bool check_prepared_statement(Prepared_statement *stmt) case SQLCOM_CREATE_TABLE: res= mysql_test_create_table(stmt); break; - + case SQLCOM_SHOW_CREATE: + if ((res= mysql_test_show_create_table(stmt, tables)) == 2) + { + /* Statement and field info has already been sent */ + DBUG_RETURN(FALSE); + } + break; + case SQLCOM_SHOW_CREATE_DB: + if ((res= mysql_test_show_create_db(stmt)) == 2) + { + /* Statement and field info has already been sent */ + DBUG_RETURN(FALSE); + } + break; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + case SQLCOM_SHOW_GRANTS: + if ((res= mysql_test_show_grants(stmt)) == 2) + { + /* Statement and field info has already been sent */ + DBUG_RETURN(FALSE); + } + break; +#endif /* NO_EMBEDDED_ACCESS_CHECKS */ +#ifndef EMBEDDED_LIBRARY + case SQLCOM_SHOW_SLAVE_STAT: + if ((res= mysql_test_show_slave_status(stmt)) == 2) + { + /* Statement and field info has already been sent */ + DBUG_RETURN(FALSE); + } + break; + case SQLCOM_SHOW_MASTER_STAT: + if ((res= mysql_test_show_master_status(stmt)) == 2) + { + /* Statement and field info has already been sent */ + DBUG_RETURN(FALSE); + } + break; + case SQLCOM_SHOW_BINLOGS: + if ((res= mysql_test_show_binlogs(stmt)) == 2) + { + /* Statement and field info has already been sent */ + DBUG_RETURN(FALSE); + } + break; +#endif /* EMBEDDED_LIBRARY */ + case SQLCOM_SHOW_CREATE_PROC: + if ((res= mysql_test_show_create_routine(stmt, TYPE_ENUM_PROCEDURE)) == 2) + { + /* Statement and field info has already been sent */ + DBUG_RETURN(FALSE); + } + break; + case SQLCOM_SHOW_CREATE_FUNC: + if ((res= mysql_test_show_create_routine(stmt, TYPE_ENUM_FUNCTION)) == 2) + { + /* Statement and field info has already been sent */ + DBUG_RETURN(FALSE); + } + break; case SQLCOM_CREATE_VIEW: if (lex->create_view_mode == VIEW_ALTER) { @@ -2202,10 +2458,14 @@ static bool check_prepared_statement(Prepared_statement *stmt) case SQLCOM_CREATE_USER: case SQLCOM_RENAME_USER: case SQLCOM_DROP_USER: + case SQLCOM_CREATE_ROLE: + case SQLCOM_DROP_ROLE: case SQLCOM_ASSIGN_TO_KEYCACHE: case SQLCOM_PRELOAD_KEYS: case SQLCOM_GRANT: + case SQLCOM_GRANT_ROLE: case SQLCOM_REVOKE: + case SQLCOM_REVOKE_ROLE: case SQLCOM_KILL: case SQLCOM_COMPOUND: case SQLCOM_SHUTDOWN: @@ -2325,7 +2585,10 @@ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length) { /* Statement map deletes statement on erase */ thd->stmt_map.erase(stmt); + thd->clear_last_stmt(); } + else + thd->set_last_stmt(stmt); thd->protocol= save_protocol; @@ -2911,6 +3174,9 @@ void mysqld_stmt_close(THD *thd, char *packet) stmt->deallocate(); general_log_print(thd, thd->get_command(), NullS); + if (thd->last_stmt == stmt) + thd->clear_last_stmt(); + DBUG_VOID_RETURN; } @@ -3173,7 +3439,8 @@ end: Prepared_statement::Prepared_statement(THD *thd_arg) :Statement(NULL, &main_mem_root, - STMT_INITIALIZED, ++thd_arg->statement_id_counter), + STMT_INITIALIZED, + ((++thd_arg->statement_id_counter) & STMT_ID_MASK)), thd(thd_arg), result(thd_arg), param_array(0), @@ -3649,8 +3916,9 @@ reexecute: switch (thd->wsrep_conflict_state) { case CERT_FAILURE: - WSREP_DEBUG("PS execute fail for CERT_FAILURE: thd: %ld err: %d", - thd->thread_id, thd->get_stmt_da()->sql_errno() ); + WSREP_DEBUG("PS execute fail for CERT_FAILURE: thd: %lld err: %d", + (longlong) thd->thread_id, + thd->get_stmt_da()->sql_errno() ); thd->wsrep_conflict_state = NO_CONFLICT; break; diff --git a/sql/sql_prepare.h b/sql/sql_prepare.h index b468ac1bf9b..aec4ac40036 100644 --- a/sql/sql_prepare.h +++ b/sql/sql_prepare.h @@ -18,6 +18,10 @@ #include "sql_error.h" + +#define LAST_STMT_ID 0xFFFFFFFF +#define STMT_ID_MASK 0x7FFFFFFF + class THD; struct LEX; diff --git a/sql/sql_priv.h b/sql/sql_priv.h index 95102c82044..b15a80a889a 100644 --- a/sql/sql_priv.h +++ b/sql/sql_priv.h @@ -320,11 +320,11 @@ /* Used to check GROUP BY list in the MODE_ONLY_FULL_GROUP_BY mode */ #define UNDEF_POS (-1) +#endif /* !MYSQL_CLIENT */ + /* BINLOG_DUMP options */ #define BINLOG_DUMP_NON_BLOCK 1 -#endif /* !MYSQL_CLIENT */ - #define BINLOG_SEND_ANNOTATE_ROWS_EVENT 2 #ifndef MYSQL_CLIENT diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index e524153ad15..c9e2b3a586d 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -2181,9 +2181,7 @@ static int init_binlog_sender(binlog_send_info *info, linfo->pos= *pos; // note: publish that we use file, before we open it - mysql_mutex_lock(&LOCK_thread_count); thd->current_linfo= linfo; - mysql_mutex_unlock(&LOCK_thread_count); if (check_start_offset(info, linfo->log_file_name, *pos)) return 1; @@ -2922,9 +2920,7 @@ err: mysql_file_close(file, MYF(MY_WME)); } - mysql_mutex_lock(&LOCK_thread_count); - thd->current_linfo = 0; - mysql_mutex_unlock(&LOCK_thread_count); + thd->reset_current_linfo(); thd->variables.max_allowed_packet= old_max_allowed_packet; delete info->fdev; @@ -3285,7 +3281,7 @@ int reset_slave(THD *thd, Master_info* mi) char fname[FN_REFLEN]; int thread_mask= 0, error= 0; uint sql_errno=ER_UNKNOWN_ERROR; - const char* errmsg= "Unknown error occured while reseting slave"; + const char* errmsg= "Unknown error occurred while reseting slave"; char master_info_file_tmp[FN_REFLEN]; char relay_log_info_file_tmp[FN_REFLEN]; DBUG_ENTER("reset_slave"); @@ -3379,10 +3375,8 @@ err: SYNOPSIS kill_zombie_dump_threads() slave_server_id the slave's server id - */ - void kill_zombie_dump_threads(uint32 slave_server_id) { mysql_mutex_lock(&LOCK_thread_count); @@ -3890,7 +3884,7 @@ bool mysql_show_binlog_events(THD* thd) DBUG_ASSERT(thd->lex->sql_command == SQLCOM_SHOW_BINLOG_EVENTS || thd->lex->sql_command == SQLCOM_SHOW_RELAYLOG_EVENTS); - /* select wich binary log to use: binlog or relay */ + /* select which binary log to use: binlog or relay */ if ( thd->lex->sql_command == SQLCOM_SHOW_BINLOG_EVENTS ) { binary_log= &mysql_bin_log; @@ -3946,9 +3940,7 @@ bool mysql_show_binlog_events(THD* thd) goto err; } - mysql_mutex_lock(&LOCK_thread_count); - thd->current_linfo = &linfo; - mysql_mutex_unlock(&LOCK_thread_count); + thd->current_linfo= &linfo; if ((file=open_binlog(&log, linfo.log_file_name, &errmsg)) < 0) goto err; @@ -4080,14 +4072,31 @@ err: else my_eof(thd); - mysql_mutex_lock(&LOCK_thread_count); - thd->current_linfo = 0; - mysql_mutex_unlock(&LOCK_thread_count); + thd->reset_current_linfo(); thd->variables.max_allowed_packet= old_max_allowed_packet; DBUG_RETURN(ret); } +void show_binlog_info_get_fields(THD *thd, List<Item> *field_list) +{ + MEM_ROOT *mem_root= thd->mem_root; + field_list->push_back(new (mem_root) + Item_empty_string(thd, "File", FN_REFLEN), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "Position", 20, + MYSQL_TYPE_LONGLONG), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Binlog_Do_DB", 255), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Binlog_Ignore_DB", 255), + mem_root); +} + + /** Execute a SHOW MASTER STATUS statement. @@ -4100,23 +4109,10 @@ err: bool show_binlog_info(THD* thd) { Protocol *protocol= thd->protocol; - MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("show_binlog_info"); List<Item> field_list; - field_list.push_back(new (mem_root) - Item_empty_string(thd, "File", FN_REFLEN), - mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "Position", 20, - MYSQL_TYPE_LONGLONG), - mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Binlog_Do_DB", 255), - mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Binlog_Ignore_DB", 255), - mem_root); + show_binlog_info_get_fields(thd, &field_list); if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) @@ -4140,6 +4136,19 @@ bool show_binlog_info(THD* thd) } +void show_binlogs_get_fields(THD *thd, List<Item> *field_list) +{ + MEM_ROOT *mem_root= thd->mem_root; + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Log_name", 255), + mem_root); + field_list->push_back(new (mem_root) + Item_return_int(thd, "File_size", 20, + MYSQL_TYPE_LONGLONG), + mem_root); +} + + /** Execute a SHOW BINARY LOGS statement. @@ -4159,7 +4168,6 @@ bool show_binlogs(THD* thd) uint length; int cur_dir_len; Protocol *protocol= thd->protocol; - MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("show_binlogs"); if (!mysql_bin_log.is_open()) @@ -4168,13 +4176,8 @@ bool show_binlogs(THD* thd) DBUG_RETURN(TRUE); } - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Log_name", 255), - mem_root); - field_list.push_back(new (mem_root) - Item_return_int(thd, "File_size", 20, - MYSQL_TYPE_LONGLONG), - mem_root); + show_binlogs_get_fields(thd, &field_list); + if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); diff --git a/sql/sql_repl.h b/sql/sql_repl.h index 774e43c0a87..e2000bbca73 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -52,6 +52,7 @@ bool purge_master_logs(THD* thd, const char* to_log); bool purge_master_logs_before_date(THD* thd, time_t purge_time); bool log_in_use(const char* log_name); void adjust_linfo_offsets(my_off_t purge_offset); +void show_binlogs_get_fields(THD *thd, List<Item> *field_list); bool show_binlogs(THD* thd); extern int init_master_info(Master_info* mi); void kill_zombie_dump_threads(uint32 slave_server_id); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 30be455b3d3..cc1310f1632 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015 Oracle and/or its affiliates. - Copyright (c) 2009, 2015 MariaDB + Copyright (c) 2009, 2016 MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -53,6 +53,7 @@ #include "log_slow.h" #include "sql_derived.h" #include "sql_statistics.h" +#include "sql_cte.h" #include "sql_window.h" #include "debug_sync.h" // DEBUG_SYNC @@ -446,7 +447,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, this field from inner subqueries. @return Status - @retval true An error occured. + @retval true An error occurred. @retval false OK. */ @@ -854,6 +855,10 @@ JOIN::prepare(TABLE_LIST *tables_init, DBUG_RETURN(-1); } } + + With_clause *with_clause=select_lex->get_with_clause(); + if (with_clause && with_clause->prepare_unreferenced_elements(thd)) + DBUG_RETURN(1); int res= check_and_do_in_subquery_rewrites(this); @@ -1477,7 +1482,7 @@ JOIN::optimize_inner() } select= make_select(*table, const_table_map, - const_table_map, conds, 1, &error); + const_table_map, conds, (SORT_INFO*) 0, 1, &error); if (error) { /* purecov: inspected */ error= -1; /* purecov: inspected */ @@ -2642,7 +2647,7 @@ bool JOIN::make_aggr_tables_info() select_limit : unit->select_limit_cnt; } if (!only_const_tables() && - !join_tab[const_tables].table->sort.io_cache && + !join_tab[const_tables].filesort && !(select_options & SELECT_DESCRIBE)) { /* @@ -2990,8 +2995,6 @@ JOIN::reinit() continue; tmp_table->file->extra(HA_EXTRA_RESET_STATE); tmp_table->file->ha_delete_all_rows(); - free_io_cache(tmp_table); - filesort_free_buffers(tmp_table,0); } } clear_sj_tmp_tables(this); @@ -3353,7 +3356,6 @@ JOIN::destroy() for (JOIN_TAB *tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITH_CONST_TABLES); tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS)) { - DBUG_ASSERT(!tab->table || !tab->table->sort.record_pointers); if (tab->aggr) { free_tmp_table(thd, tab->table); @@ -4167,6 +4169,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, select= make_select(s->table, found_const_table_map, found_const_table_map, *s->on_expr_ref ? *s->on_expr_ref : join->conds, + (SORT_INFO*) 0, 1, &error); if (!select) goto error; @@ -9114,6 +9117,7 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables, keyuse->val, FALSE); } + inline void add_cond_and_fix(THD *thd, Item **e1, Item *e2) { if (*e1) @@ -9223,7 +9227,7 @@ static void add_not_null_conds(JOIN *join) if (!referred_tab) continue; if (!(notnull= new (join->thd->mem_root) - Item_func_isnotnull(join->thd, not_null_item))) + Item_func_isnotnull(join->thd, item))) DBUG_VOID_RETURN; /* We need to do full fix_fields() call here in order to have correct @@ -11400,13 +11404,16 @@ bool error_if_full_join(JOIN *join) void JOIN_TAB::cleanup() { DBUG_ENTER("JOIN_TAB::cleanup"); - DBUG_PRINT("enter", ("table %s.%s", + DBUG_PRINT("enter", ("tab: %p table %s.%s", + this, (table ? table->s->db.str : "?"), (table ? table->s->table_name.str : "?"))); delete select; select= 0; delete quick; quick= 0; + delete filesort; + filesort= 0; if (cache) { cache->free(); @@ -11424,9 +11431,6 @@ void JOIN_TAB::cleanup() { table->set_keyread(FALSE); table->file->ha_index_or_rnd_end(); - - free_io_cache(table); - filesort_free_buffers(table, true); } if (table) { @@ -11829,7 +11833,11 @@ void JOIN::cleanup(bool full) for (tab= first_breadth_first_tab(); tab; tab= next_breadth_first_tab(first_breadth_first_tab(), top_join_tab_count, tab)) + { tab->cleanup(); + delete tab->filesort_result; + tab->filesort_result= NULL; + } } cleaned= true; //psergey2: added (Q: why not in the above loop?) @@ -11843,6 +11851,9 @@ void JOIN::cleanup(bool full) delete curr_tab->tmp_table_param; curr_tab->tmp_table_param= NULL; curr_tab->aggr= NULL; + + delete curr_tab->filesort_result; + curr_tab->filesort_result= NULL; } } aggr_tables= 0; // psergey3 @@ -11869,8 +11880,8 @@ void JOIN::cleanup(bool full) tab->table->file->print_error(tmp, MYF(0)); } } - free_io_cache(tab->table); - filesort_free_buffers(tab->table, full); + delete tab->filesort_result; + tab->filesort_result= NULL; } } } @@ -12840,7 +12851,7 @@ bool Item_func_eq::check_equality(THD *thd, COND_EQUAL *cond_equal, equality predicates that is equivalent to the conjunction. Thus, =(a1,a2,a3) can substitute for ((a1=a3) AND (a2=a3) AND (a2=a1)) as it is equivalent to ((a1=a2) AND (a2=a3)). - The function always makes a substitution of all equality predicates occured + The function always makes a substitution of all equality predicates occurred in a conjuction for a minimal set of multiple equality predicates. This set can be considered as a canonical representation of the sub-conjunction of the equality predicates. @@ -15615,8 +15626,6 @@ const_expression_in_where(COND *cond, Item *comp_item, Field *comp_field, the record in the original table. If item == NULL then fill_record() will update the temporary table - @param convert_blob_length If >0 create a varstring(convert_blob_length) - field instead of blob. @retval NULL on error @@ -15626,23 +15635,12 @@ const_expression_in_where(COND *cond, Item *comp_item, Field *comp_field, Field *create_tmp_field_from_field(THD *thd, Field *org_field, const char *name, TABLE *table, - Item_field *item, uint convert_blob_length) + Item_field *item) { Field *new_field; - /* - Make sure that the blob fits into a Field_varstring which has - 2-byte lenght. - */ - if (convert_blob_length && convert_blob_length <= Field_varstring::MAX_SIZE && - (org_field->flags & BLOB_FLAG)) - new_field= new Field_varstring(convert_blob_length, - org_field->maybe_null(), - org_field->field_name, table->s, - org_field->charset()); - else - new_field= org_field->make_new_field(thd->mem_root, table, - table == org_field->table); + new_field= org_field->make_new_field(thd->mem_root, table, + table == org_field->table); if (new_field) { new_field->init(table); @@ -15669,9 +15667,7 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field, } -Field *Item::create_tmp_field(bool group, TABLE *table, - uint convert_blob_length, - uint convert_int_length) +Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length) { Field *UNINIT_VAR(new_field); MEM_ROOT *mem_root= table->in_use->mem_root; @@ -15705,16 +15701,6 @@ Field *Item::create_tmp_field(bool group, TABLE *table, */ if (field_type() == MYSQL_TYPE_GEOMETRY) new_field= tmp_table_field_from_field_type(table, true, false); - /* - Make sure that the blob fits into a Field_varstring which has - 2-byte lenght. - */ - else if (max_length / collation.collation->mbmaxlen > 255 && - convert_blob_length <= Field_varstring::MAX_SIZE && - convert_blob_length) - new_field= new (mem_root) - Field_varstring(convert_blob_length, maybe_null, - name, table->s, collation.collation); else new_field= make_string_field(table); new_field->set_derivation(collation.derivation); @@ -15760,12 +15746,11 @@ Field *Item::create_tmp_field(bool group, TABLE *table, */ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, - Item ***copy_func, bool modify_item, - uint convert_blob_length) + Item ***copy_func, bool modify_item) { Field *UNINIT_VAR(new_field); DBUG_ASSERT(thd == table->in_use); - new_field= item->Item::create_tmp_field(false, table, convert_blob_length); + new_field= item->Item::create_tmp_field(false, table); if (copy_func && item->real_item()->is_result_field()) *((*copy_func)++) = item; // Save for copy_funcs @@ -15828,8 +15813,6 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table) the record in the original table. If modify_item is 0 then fill_record() will update the temporary table - @param convert_blob_length If >0 create a varstring(convert_blob_length) - field instead of blob. @retval 0 on error @@ -15842,8 +15825,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Field **default_field, bool group, bool modify_item, bool table_cant_handle_bit_fields, - bool make_copy_field, - uint convert_blob_length) + bool make_copy_field) { Field *result; Item::Type orig_type= type; @@ -15860,7 +15842,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, switch (type) { case Item::SUM_FUNC_ITEM: { - result= item->create_tmp_field(group, table, convert_blob_length); + result= item->create_tmp_field(group, table); if (!result) my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); return result; @@ -15896,7 +15878,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, item->maybe_null= orig_item->maybe_null; } result= create_tmp_field_from_item(thd, item, table, NULL, - modify_item, convert_blob_length); + modify_item); *from_field= field->field; if (result && modify_item) field->result_field= result; @@ -15908,7 +15890,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, { *from_field= field->field; result= create_tmp_field_from_item(thd, item, table, copy_func, - modify_item, convert_blob_length); + modify_item); if (result && modify_item) field->result_field= result; } @@ -15918,8 +15900,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, item->name, table, modify_item ? field : - NULL, - convert_blob_length); + NULL); if (orig_type == Item::REF_ITEM && orig_modify) ((Item_ref*)orig_item)->set_result_field(result); /* @@ -15953,8 +15934,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, sp_result_field, item_func_sp->name, table, - NULL, - convert_blob_length); + NULL); if (modify_item) item->set_result_field(result_field); @@ -15987,7 +15967,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, } return create_tmp_field_from_item(thd, item, table, (make_copy_field ? 0 : copy_func), - modify_item, convert_blob_length); + modify_item); case Item::TYPE_HOLDER: result= ((Item_type_holder *)item)->make_field_by_type(table); result->set_derivation(item->collation.derivation); @@ -16125,7 +16105,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, { /* if we run out of slots or we are not using tempool */ sprintf(path, "%s%lx_%lx_%x", tmp_file_prefix,current_pid, - thd->thread_id, thd->tmp_table++); + (ulong) thd->thread_id, thd->tmp_table++); } /* @@ -16297,8 +16277,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, create_tmp_field(thd, table, arg, arg->type(), ©_func, tmp_from_field, &default_field[fieldnr], group != 0,not_all_columns, - distinct, 0, - param->convert_blob_length); + distinct, false); if (!new_field) goto err; // Should be OOM tmp_from_field++; @@ -16368,8 +16347,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, to be usable in this case too. */ item->marker == 4 || param->bit_fields_as_long, - force_copy_fields, - param->convert_blob_length); + force_copy_fields); if (!new_field) { @@ -17100,6 +17078,12 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, goto err; bzero(seg, sizeof(*seg) * keyinfo->user_defined_key_parts); + /* + Note that a similar check is performed during + subquery_types_allow_materialization. See MDEV-7122 for more details as + to why. Whenever this changes, it must be updated there as well, for + all tmp_table engines. + */ if (keyinfo->key_length > table->file->max_key_length() || keyinfo->user_defined_key_parts > table->file->max_key_parts() || share->uniques) @@ -17299,6 +17283,12 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, goto err; bzero(seg, sizeof(*seg) * keyinfo->user_defined_key_parts); + /* + Note that a similar check is performed during + subquery_types_allow_materialization. See MDEV-7122 for more details as + to why. Whenever this changes, it must be updated there as well, for + all tmp_table engines. + */ if (keyinfo->key_length > table->file->max_key_length() || keyinfo->user_defined_key_parts > table->file->max_key_parts() || share->uniques) @@ -17564,7 +17554,6 @@ free_tmp_table(THD *thd, TABLE *entry) /* free blobs */ for (Field **ptr=entry->field ; *ptr ; ptr++) (*ptr)->free(); - free_io_cache(entry); if (entry->temp_pool_slot != MY_BIT_NONE) bitmap_lock_clear_bit(&temp_pool, entry->temp_pool_slot); @@ -18891,7 +18880,18 @@ int join_read_key2(THD *thd, JOIN_TAB *tab, TABLE *table, TABLE_REF *table_ref) } } + /* + The following is needed when one makes ref (or eq_ref) access from row + comparisons: one must call row->bring_value() to get the new values. + */ + if (tab && tab->bush_children) + { + TABLE_LIST *emb_sj_nest= tab->bush_children->start->emb_sj_nest; + emb_sj_nest->sj_subq_pred->left_expr->bring_value(); + } + /* TODO: Why don't we do "Late NULLs Filtering" here? */ + if (cmp_buffer_with_ref(thd, table, table_ref) || (table->status & (STATUS_GARBAGE | STATUS_NO_PARENT | STATUS_NULL_ROW))) { @@ -19152,7 +19152,7 @@ int join_init_read_record(JOIN_TAB *tab) if (!tab->preread_init_done && tab->preread_init()) return 1; if (init_read_record(&tab->read_record, tab->join->thd, tab->table, - tab->select,1,1, FALSE)) + tab->select, tab->filesort_result, 1,1, FALSE)) return 1; return (*tab->read_record.read_record)(&tab->read_record); } @@ -19170,7 +19170,7 @@ join_read_record_no_init(JOIN_TAB *tab) save_copy_end= tab->read_record.copy_field_end; init_read_record(&tab->read_record, tab->join->thd, tab->table, - tab->select,1,1, FALSE); + tab->select, tab->filesort_result, 1, 1, FALSE); tab->read_record.copy_field= save_copy; tab->read_record.copy_field_end= save_copy_end; @@ -19440,11 +19440,9 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), /* Join over all rows in table; Return number of found rows */ TABLE *table=jt->table; - if (table->sort.record_pointers || - (table->sort.io_cache && my_b_inited(table->sort.io_cache))) + if (jt->filesort_result) // If filesort was used { - /* Using filesort */ - join->send_records= table->sort.found_records; + join->send_records= jt->filesort_result->found_rows; } else { @@ -20787,7 +20785,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_INTERSECT || quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION || quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) - ref_key= -1; + { + /* + we set ref_key=MAX_KEY instead of -1, because test_if_cheaper ordering + assumes that "ref_key==-1" means doing full index scan. + (This is not very straightforward and we got into this situation for + historical reasons. Should be fixed at some point). + */ + ref_key= MAX_KEY; + } else { ref_key= select->quick->index; @@ -21171,8 +21177,7 @@ use_filesort: 'join' is modified to use this index. - If no index, create with filesort() an index file that can be used to retrieve rows in order (should be done with 'read_record'). - The sorted data is stored in tab->table and will be freed when calling - free_io_cache(tab->table). + The sorted data is stored in tab->filesort RETURN VALUES 0 ok @@ -21183,12 +21188,11 @@ use_filesort: int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort) { - ha_rows examined_rows; - ha_rows found_rows; - ha_rows filesort_retval= HA_POS_ERROR; + uint length; TABLE *table; SQL_SELECT *select; bool quick_created= FALSE; + SORT_INFO *file_sort= 0; DBUG_ENTER("create_sort_index"); if (fsort == NULL) @@ -21202,10 +21206,14 @@ create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort) /* Currently ORDER BY ... LIMIT is not supported in subqueries. */ DBUG_ASSERT(join->group_list || !join->is_in_subquery()); + /* + Calculate length of join->order as this may be longer than 'order', + which may come from 'group by'. This is needed as join->sortorder is + used both for grouping and ordering. + */ + length= 0; + - table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), - MYF(MY_WME | MY_ZEROFILL| - MY_THREAD_SPECIFIC)); table->status=0; // May be wrong if quick_select if (!tab->preread_init_done && tab->preread_init()) @@ -21261,11 +21269,16 @@ create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort) if (table->s->tmp_table) table->file->info(HA_STATUS_VARIABLE); // Get record count - filesort_retval= filesort(thd, table, fsort, tab->keep_current_rowid, - &examined_rows, &found_rows, - fsort->tracker); - table->sort.found_records= filesort_retval; - tab->records= found_rows; // For SQL_CALC_ROWS + file_sort= filesort(thd, table, fsort, tab->keep_current_rowid, fsort->tracker); + DBUG_ASSERT(tab->filesort_result == 0); + tab->filesort_result= file_sort; + tab->records= 0; + if (file_sort) + { + tab->records= join->select_options & OPTION_FOUND_ROWS ? + file_sort->found_rows : file_sort->return_rows; + tab->join->join_examined_rows+= file_sort->examined_rows; + } if (quick_created) { @@ -21273,13 +21286,13 @@ create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort) select->cleanup(); } - tab->join->join_examined_rows+= examined_rows; table->set_keyread(FALSE); // Restore if we used indexes if (tab->type == JT_FT) table->file->ft_end(); else table->file->ha_index_or_rnd_end(); - DBUG_RETURN(filesort_retval == HA_POS_ERROR); + + DBUG_RETURN(file_sort == 0); err: DBUG_RETURN(-1); } @@ -21394,7 +21407,6 @@ JOIN_TAB::remove_duplicates() if (thd->killed == ABORT_QUERY) thd->reset_killed(); - free_io_cache(table); // Safety table->file->info(HA_STATUS_VARIABLE); if (table->s->db_type() == heap_hton || (!table->s->blob_fields && @@ -21732,7 +21744,11 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables */ if (order_item->type() == Item::INT_ITEM && order_item->basic_const_item()) { /* Order by position */ - uint count= (uint) order_item->val_int(); + uint count; + if (order->counter_used) + count= order->counter; // counter was once resolved + else + count= (uint) order_item->val_int(); if (!count || count > fields.elements) { my_error(ER_BAD_FIELD_ERROR, MYF(0), @@ -21749,7 +21765,7 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables select_item= find_item_in_list(order_item, fields, &counter, REPORT_EXCEPT_NOT_FOUND, &resolution); if (!select_item) - return TRUE; /* The item is not unique, or some other error occured. */ + return TRUE; /* The item is not unique, or some other error occurred. */ /* Check whether the resolved field is not ambiguos. */ @@ -23106,8 +23122,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) } join_tab->set_select_cond(cond, __LINE__); } - else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0, - &error))) + else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, + (SORT_INFO*) 0, 0, &error))) join_tab->set_select_cond(cond, __LINE__); DBUG_RETURN(error ? TRUE : FALSE); @@ -24204,9 +24220,8 @@ int JOIN::save_explain_data_intern(Explain_query *output, /* There should be no attempts to save query plans for merged selects */ DBUG_ASSERT(!join->select_lex->master_unit()->derived || - join->select_lex->master_unit()->derived->is_materialized_derived()); - - explain= NULL; + join->select_lex->master_unit()->derived->is_materialized_derived() || + join->select_lex->master_unit()->derived->is_with_table()); /* Don't log this into the slow query log */ @@ -24260,6 +24275,7 @@ int JOIN::save_explain_data_intern(Explain_query *output, save_agg_explain_data(this, xpl_sel); xpl_sel->exec_const_cond= exec_const_cond; + xpl_sel->outer_ref_cond= outer_ref_cond; if (tmp_having) xpl_sel->having= tmp_having; else @@ -24699,11 +24715,19 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str, } else if (derived) { - // A derived table - str->append('('); - derived->print(str, query_type); - str->append(')'); - cmp_name= ""; // Force printing of alias + if (!derived->derived->is_with_table()) + { + // A derived table + str->append('('); + derived->print(str, query_type); + str->append(')'); + cmp_name= ""; // Force printing of alias + } + else + { + append_identifier(thd, str, table_name, table_name_length); + cmp_name= table_name; + } } else { @@ -25099,7 +25123,7 @@ void JOIN::restore_query_plan(Join_plan_state *restore_from) @retval REOPT_NEW_PLAN there is a new plan. @retval REOPT_OLD_PLAN no new improved plan was produced, use the old one. - @retval REOPT_ERROR an irrecovarable error occured during reoptimization. + @retval REOPT_ERROR an irrecovarable error occurred during reoptimization. */ JOIN::enum_reopt_result @@ -25325,8 +25349,12 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab, @param table Table if tab == NULL or tab->table @param usable_keys Key map to find a cheaper key in @param ref_key - * 0 <= key < MAX_KEY - key number (hint) to start the search - * -1 - no key number provided + 0 <= key < MAX_KEY - Key that is currently used for finding + row + MAX_KEY - means index_merge is used + -1 - means we're currently not using an + index to find rows. + @param select_limit LIMIT value @param [out] new_key Key number if success, otherwise undefined @param [out] new_key_direction Return -1 (reverse) or +1 if success, @@ -25355,7 +25383,6 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, uint *saved_best_key_parts) { DBUG_ENTER("test_if_cheaper_ordering"); - DBUG_ASSERT(ref_key < int(MAX_KEY)); /* Check whether there is an index compatible with the given order usage of which is cheaper than usage of the ref_key index (ref_key>=0) @@ -25420,7 +25447,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, Calculate the selectivity of the ref_key for REF_ACCESS. For RANGE_ACCESS we use table->quick_condition_rows. */ - if (ref_key >= 0 && !is_hash_join_key_no(ref_key) && tab->type == JT_REF) + if (ref_key >= 0 && ref_key != MAX_KEY && tab->type == JT_REF) { if (table->quick_keys.is_set(ref_key)) refkey_rows_estimate= table->quick_rows[ref_key]; diff --git a/sql/sql_select.h b/sql/sql_select.h index e85931dcc7c..f5b9cb4684d 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -35,7 +35,6 @@ #include "filesort.h" typedef struct st_join_table JOIN_TAB; - /* Values in optimize */ #define KEY_OPTIMIZE_EXISTS 1 #define KEY_OPTIMIZE_REF_OR_NULL 2 @@ -423,6 +422,7 @@ typedef struct st_join_table { /* Sorting related info */ Filesort *filesort; + SORT_INFO *filesort_result; /* Non-NULL value means this join_tab must do window function computation @@ -1042,7 +1042,7 @@ protected: enum enum_reopt_result { REOPT_NEW_PLAN, /* there is a new reoptimized plan */ REOPT_OLD_PLAN, /* no new improved plan can be found, use the old one */ - REOPT_ERROR, /* an irrecovarable error occured during reoptimization */ + REOPT_ERROR, /* an irrecovarable error occurred during reoptimization */ REOPT_NONE /* not yet reoptimized */ }; @@ -1708,8 +1708,8 @@ bool copy_funcs(Item **func_ptr, const THD *thd); uint find_shortest_key(TABLE *table, const key_map *usable_keys); Field* create_tmp_field_from_field(THD *thd, Field* org_field, const char *name, TABLE *table, - Item_field *item, uint convert_blob_length); - + Item_field *item); + bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args); /* functions from opt_sum.cc */ @@ -1967,8 +1967,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Field **def_field, bool group, bool modify_item, bool table_cant_handle_bit_fields, - bool make_copy_field, - uint convert_blob_length); + bool make_copy_field); /* General routine to change field->ptr of a NULL-terminated array of Field diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index 0138c3e5a3b..196c138c04d 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -205,8 +205,8 @@ static bool servers_load(THD *thd, TABLE_LIST *tables) free_root(&mem, MYF(0)); init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); - if (init_read_record(&read_record_info,thd,table=tables[0].table,NULL,1,0, - FALSE)) + if (init_read_record(&read_record_info,thd,table=tables[0].table, NULL, NULL, + 1,0, FALSE)) DBUG_RETURN(1); while (!(read_record_info.read_record(&read_record_info))) { diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 0d2d07a4503..00881adff1d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -39,7 +39,6 @@ #include "tztime.h" // struct Time_zone #include "sql_acl.h" // TABLE_ACLS, check_grant, DB_ACLS, acl_get, // check_grant_db -#include "filesort.h" // filesort_free_buffers #include "sp.h" #include "sp_head.h" #include "sp_pcontext.h" @@ -1092,39 +1091,29 @@ public: /* - Return CREATE command for table or view + Return metadata for CREATE command for table or view @param thd Thread handler @param table_list Table / view + @param field_list resulting list of fields + @param buffer resulting CREATE statement @return @retval 0 OK @retval 1 Error - @notes - table_list->db and table_list->table_name are kept unchanged to - not cause problems with SP. */ bool -mysqld_show_create(THD *thd, TABLE_LIST *table_list) +mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list, + List<Item> *field_list, String *buffer) { - Protocol *protocol= thd->protocol; - char buff[2048]; - String buffer(buff, sizeof(buff), system_charset_info); - List<Item> field_list; bool error= TRUE; MEM_ROOT *mem_root= thd->mem_root; - DBUG_ENTER("mysqld_show_create"); + DBUG_ENTER("mysqld_show_create_get_fields"); DBUG_PRINT("enter",("db: %s table: %s",table_list->db, table_list->table_name)); - /* - Metadata locks taken during SHOW CREATE should be released when - the statmement completes as it is an information statement. - */ - MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint(); - /* We want to preserve the tree for views. */ thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW; @@ -1155,45 +1144,88 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) goto exit; } - buffer.length(0); + buffer->length(0); if (table_list->view) - buffer.set_charset(table_list->view_creation_ctx->get_client_cs()); + buffer->set_charset(table_list->view_creation_ctx->get_client_cs()); if ((table_list->view ? - show_create_view(thd, table_list, &buffer) : - show_create_table(thd, table_list, &buffer, NULL, WITHOUT_DB_NAME))) + show_create_view(thd, table_list, buffer) : + show_create_table(thd, table_list, buffer, NULL, WITHOUT_DB_NAME))) goto exit; if (table_list->view) { - field_list.push_back(new (mem_root) + field_list->push_back(new (mem_root) Item_empty_string(thd, "View", NAME_CHAR_LEN), mem_root); - field_list.push_back(new (mem_root) + field_list->push_back(new (mem_root) Item_empty_string(thd, "Create View", - MY_MAX(buffer.length(),1024)), + MY_MAX(buffer->length(),1024)), mem_root); - field_list.push_back(new (mem_root) + field_list->push_back(new (mem_root) Item_empty_string(thd, "character_set_client", MY_CS_NAME_SIZE), mem_root); - field_list.push_back(new (mem_root) + field_list->push_back(new (mem_root) Item_empty_string(thd, "collation_connection", MY_CS_NAME_SIZE), mem_root); } else { - field_list.push_back(new (mem_root) + field_list->push_back(new (mem_root) Item_empty_string(thd, "Table", NAME_CHAR_LEN), mem_root); // 1024 is for not to confuse old clients - field_list.push_back(new (mem_root) + field_list->push_back(new (mem_root) Item_empty_string(thd, "Create Table", - MY_MAX(buffer.length(),1024)), + MY_MAX(buffer->length(),1024)), mem_root); } + error= FALSE; + +exit: + DBUG_RETURN(error); +} + + +/* + Return CREATE command for table or view + + @param thd Thread handler + @param table_list Table / view + + @return + @retval 0 OK + @retval 1 Error + + @notes + table_list->db and table_list->table_name are kept unchanged to + not cause problems with SP. +*/ + +bool +mysqld_show_create(THD *thd, TABLE_LIST *table_list) +{ + Protocol *protocol= thd->protocol; + char buff[2048]; + String buffer(buff, sizeof(buff), system_charset_info); + List<Item> field_list; + bool error= TRUE; + DBUG_ENTER("mysqld_show_create"); + DBUG_PRINT("enter",("db: %s table: %s",table_list->db, + table_list->table_name)); + + /* + Metadata locks taken during SHOW CREATE should be released when + the statmement completes as it is an information statement. + */ + MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint(); + + + if (mysqld_show_create_get_fields(thd, table_list, &field_list, &buffer)) + goto exit; if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | @@ -1239,6 +1271,19 @@ exit: DBUG_RETURN(error); } + +void mysqld_show_create_db_get_fields(THD *thd, List<Item> *field_list) +{ + MEM_ROOT *mem_root= thd->mem_root; + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Database", NAME_CHAR_LEN), + mem_root); + field_list->push_back(new (mem_root) + Item_empty_string(thd, "Create Database", 1024), + mem_root); +} + + bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname, LEX_STRING *orig_dbname, const DDL_options_st &options) @@ -1251,7 +1296,7 @@ bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname, #endif Schema_specification_st create; Protocol *protocol=thd->protocol; - MEM_ROOT *mem_root= thd->mem_root; + List<Item> field_list; DBUG_ENTER("mysql_show_create_db"); #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -1285,13 +1330,8 @@ bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname, load_db_opt_by_name(thd, dbname->str, &create); } - List<Item> field_list; - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Database", NAME_CHAR_LEN), - mem_root); - field_list.push_back(new (mem_root) - Item_empty_string(thd, "Create Database", 1024), - mem_root); + + mysqld_show_create_db_get_fields(thd, &field_list); if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | @@ -1390,14 +1430,13 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) static const char *require_quotes(const char *name, uint name_length) { - uint length; bool pure_digit= TRUE; const char *end= name + name_length; for (; name < end ; name++) { uchar chr= (uchar) *name; - length= my_mbcharlen(system_charset_info, chr); + int length= my_charlen(system_charset_info, name, end); if (length == 1 && !system_charset_info->ident_map[chr]) return name; if (length == 1 && (chr < '0' || chr > '9')) @@ -1409,20 +1448,17 @@ static const char *require_quotes(const char *name, uint name_length) } -/* - Quote the given identifier if needed and append it to the target string. - If the given identifier is empty, it will be quoted. - - SYNOPSIS - append_identifier() - thd thread handler - packet target string - name the identifier to be appended - name_length length of the appending identifier +/** + Convert and quote the given identifier if needed and append it to the + target string. If the given identifier is empty, it will be quoted. + @thd thread handler + @packet target string + @name the identifier to be appended + @length length of the appending identifier - RETURN VALUES - true Error - false Ok + @return + 0 success + 1 error */ bool @@ -1458,24 +1494,25 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) if (packet->append("e_char, 1, quote_charset)) return true; - for (name_end= name+length ; name < name_end ; name+= length) + for (name_end= name+length ; name < name_end ; ) { uchar chr= (uchar) *name; - length= my_mbcharlen(system_charset_info, chr); + int char_length= my_charlen(system_charset_info, name, name_end); /* - my_mbcharlen can return 0 on a wrong multibyte + charlen can return 0 and negative numbers on a wrong multibyte sequence. It is possible when upgrading from 4.0, and identifier contains some accented characters. The manual says it does not work. So we'll just - change length to 1 not to hang in the endless loop. + change char_length to 1 not to hang in the endless loop. */ - if (!length) - length= 1; - if (length == 1 && chr == (uchar) quote_char && + if (char_length <= 0) + char_length= 1; + if (char_length == 1 && chr == (uchar) quote_char && packet->append("e_char, 1, quote_charset)) return true; - if (packet->append(name, length, system_charset_info)) + if (packet->append(name, char_length, system_charset_info)) return true; + name+= char_length; } return packet->append("e_char, 1, quote_charset); } @@ -2314,7 +2351,8 @@ static int show_create_view(THD *thd, TABLE_LIST *table, String *buff) We can't just use table->query, because our SQL_MODE may trigger a different syntax, like when ANSI_QUOTES is defined. */ - table->view->unit.print(buff, QT_ORDINARY); + table->view->unit.print(buff, enum_query_type(QT_ORDINARY | + QT_ITEM_ORIGINAL_FUNC_NULLIF)); if (table->with_check != VIEW_CHECK_NONE) { @@ -4305,7 +4343,7 @@ uint get_table_open_method(TABLE_LIST *tables, @retval FALSE No error, if lock was obtained TABLE_LIST::mdl_request::ticket is set to non-NULL value. - @retval TRUE Some error occured (probably thread was killed). + @retval TRUE Some error occurred (probably thread was killed). */ static bool @@ -4413,7 +4451,7 @@ static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables, if (try_acquire_high_prio_shared_mdl_lock(thd, &table_list, can_deadlock)) { /* - Some error occured (most probably we have been killed while + Some error occurred (most probably we have been killed while waiting for conflicting locks to go away), let the caller to handle the situation. */ @@ -4451,7 +4489,7 @@ static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables, goto end; } - share= tdc_acquire_share_shortlived(thd, &table_list, GTS_TABLE | GTS_VIEW); + share= tdc_acquire_share(thd, &table_list, GTS_TABLE | GTS_VIEW); if (!share) { res= 0; @@ -4995,6 +5033,15 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, } append_create_options(thd, &str, share->option_list, false, 0); + if (file) + { + HA_CREATE_INFO create_info; + memset(&create_info, 0, sizeof(create_info)); + file->update_create_info(&create_info); + append_directory(thd, &str, "DATA", create_info.data_file_name); + append_directory(thd, &str, "INDEX", create_info.index_file_name); + } + if (str.length()) table->field[19]->store(str.ptr()+1, str.length()-1, cs); @@ -5015,7 +5062,10 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, HA_STATUS_TIME | HA_STATUS_VARIABLE_EXTRA | HA_STATUS_AUTO)) != 0) + { + file->print_error(info_error, MYF(0)); goto err; + } enum row_type row_type = file->get_row_type(); switch (row_type) { @@ -7304,12 +7354,14 @@ static my_bool find_schema_table_in_plugin(THD *thd, plugin_ref plugin, # pointer to 'schema_tables' element */ -ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name) +ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name, + bool *in_plugin) { schema_table_ref schema_table_a; ST_SCHEMA_TABLE *schema_table= schema_tables; DBUG_ENTER("find_schema_table"); + *in_plugin= false; for (; schema_table->table_name; schema_table++) { if (!my_strcasecmp(system_charset_info, @@ -7318,6 +7370,7 @@ ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name) DBUG_RETURN(schema_table); } + *in_plugin= true; schema_table_a.table_name= table_name; if (plugin_foreach(thd, find_schema_table_in_plugin, MYSQL_INFORMATION_SCHEMA_PLUGIN, &schema_table_a)) @@ -8016,8 +8069,6 @@ bool get_schema_tables_result(JOIN *join, table_list->table->file->extra(HA_EXTRA_NO_CACHE); table_list->table->file->extra(HA_EXTRA_RESET_STATE); table_list->table->file->ha_delete_all_rows(); - free_io_cache(table_list->table); - filesort_free_buffers(table_list->table,1); table_list->table->null_row= 0; } else @@ -8239,8 +8290,8 @@ ST_FIELD_INFO tables_fields_info[]= OPEN_FRM_ONLY}, {"CHECKSUM", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Checksum", OPEN_FULL_TABLE}, - {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options", - OPEN_FRM_ONLY}, + {"CREATE_OPTIONS", 2048, MYSQL_TYPE_STRING, 0, 1, "Create_options", + OPEN_FULL_TABLE}, {"TABLE_COMMENT", TABLE_COMMENT_MAXLEN, MYSQL_TYPE_STRING, 0, 0, "Comment", OPEN_FRM_ONLY}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} diff --git a/sql/sql_show.h b/sql/sql_show.h index 029249f4129..9dae78e7f0e 100644 --- a/sql/sql_show.h +++ b/sql/sql_show.h @@ -1,4 +1,5 @@ -/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. + Copyright (c) 2012, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -85,7 +86,10 @@ bool append_identifier(THD *thd, String *packet, const char *name, uint length); void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild); int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd); +bool mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list, + List<Item> *field_list, String *buffer); bool mysqld_show_create(THD *thd, TABLE_LIST *table_list); +void mysqld_show_create_db_get_fields(THD *thd, List<Item> *field_list); bool mysqld_show_create_db(THD *thd, LEX_STRING *db_name, LEX_STRING *orig_db_name, const DDL_options_st &options); @@ -114,7 +118,10 @@ bool schema_table_store_record(THD *thd, TABLE *table); void initialize_information_schema_acl(); COND *make_cond_for_info_schema(THD *thd, COND *cond, TABLE_LIST *table); -ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name); +ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name, bool *in_plugin); +static inline ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name) +{ bool unused; return find_schema_table(thd, table_name, &unused); } + ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx); int make_schema_select(THD *thd, SELECT_LEX *sel, ST_SCHEMA_TABLE *schema_table); diff --git a/sql/sql_sort.h b/sql/sql_sort.h index 1622d9df360..6c97ad7e9ab 100644 --- a/sql/sql_sort.h +++ b/sql/sql_sort.h @@ -16,8 +16,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "m_string.h" /* memset */ -#include "my_global.h" /* uchar */ #include "my_base.h" /* ha_rows */ #include "my_sys.h" /* qsort2_cmp */ #include "queues.h" @@ -71,7 +69,6 @@ public: uint rec_length; // Length of sorted records. uint sort_length; // Length of sorted columns. uint ref_length; // Length of record ref. - uint addon_length; // Length of added packed fields. uint res_length; // Length of records in final sorted file/buffer. uint max_keys_per_buffer; // Max keys / buffer. uint min_dupl_count; @@ -81,6 +78,8 @@ public: SORT_FIELD *local_sortorder; SORT_FIELD *end; SORT_ADDON_FIELD *addon_field; // Descriptors for companion fields. + LEX_STRING addon_buf; // Buffer & length of added packed fields. + uchar *unique_buff; bool not_killable; char* tmp_buffer; diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 324741fb55e..f6811b020eb 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -28,6 +28,7 @@ #include "key.h" #include "sql_statistics.h" #include "opt_range.h" +#include "uniques.h" #include "my_atomic.h" /* diff --git a/sql/sql_string.cc b/sql/sql_string.cc index b14c3afca4b..20772adcb22 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -76,9 +76,9 @@ bool String::real_alloc(uint32 length) @retval false Either the copy operation is complete or, if the size of the new buffer is smaller than the currently allocated buffer (if one exists), - no allocation occured. + no allocation occurred. - @retval true An error occured when attempting to allocate memory. + @retval true An error occurred when attempting to allocate memory. */ bool String::realloc_raw(uint32 alloc_length) { @@ -789,12 +789,114 @@ int stringcmp(const String *s,const String *t) } +/** + Return a string which has the same value with "from" and + which is safe to modify, trying to avoid unnecessary allocation + and copying when possible. + + @param to Buffer. Must not be a constant string. + @param from Some existing value. We'll try to reuse it. + Can be a constant or a variable string. + @param from_length The total size that will be possibly needed. + Note, can be 0. + + Note, in some cases "from" and "to" can point to the same object. + + If "from" is a variable string and its allocated memory is enough + to store "from_length" bytes, then "from" is returned as is. + + If "from" is a variable string and its allocated memory is not enough + to store "from_length" bytes, then "from" is reallocated and returned. + + Otherwise (if "from" is a constant string, or looks like a constant string), + then "to" is reallocated to fit "from_length" bytes, the value is copied + from "from" to "to", then "to" is returned. +*/ String *copy_if_not_alloced(String *to,String *from,uint32 from_length) { - if (from->Alloced_length >= from_length) - return from; - if ((from->alloced && (from->Alloced_length != 0)) || !to || from == to) + DBUG_ASSERT(to); + /* + If "from" is a constant string, e.g.: + SELECT INSERT('', <pos>, <length>, <replacement>); + we should not return it. See MDEV-9332. + + The code below detects different string types: + + a. All constant strings have Alloced_length==0 and alloced==false. + They point to a static memory array, or a mem_root memory, + and should stay untouched until the end of their life cycle. + Not safe to reuse. + + b. Some variable string have Alloced_length==0 and alloced==false initially, + they are not bound to any char array and allocate space on the first use + (and become #d). A typical example of such String is Item::str_value. + This type of string could be reused, but there is no a way to distinguish + them from the true constant strings (#a). + Not safe to reuse. + + c. Some variable strings have Alloced_length>0 and alloced==false. + They point to a fixed size writtable char array (typically on stack) + initially but can later allocate more space on the heap when the + fixed size array is too small (these strings become #d after allocation). + Safe to reuse. + + d. Some variable strings have Alloced_length>0 and alloced==true. + They already store data on the heap. + Safe to reuse. + + e. Some strings can have Alloced_length==0 and alloced==true. + This type of strings allocate space on the heap, but then are marked + as constant strings using String::mark_as_const(). + A typical example - the result of a character set conversion + of a constant string. + Not safe to reuse. + */ + if (from->Alloced_length > 0) // "from" is #c or #d (not a constant) { + if (from->Alloced_length >= from_length) + return from; // #c or #d (large enough to store from_length bytes) + + if (from->alloced) + { + (void) from->realloc(from_length); + return from; // #d (reallocated to fit from_length bytes) + } + /* + "from" is of type #c. It currently points to a writtable char array + (typically on stack), but is too small for "from_length" bytes. + We need to reallocate either "from" or "to". + + "from" typically points to a temporary buffer inside Item_xxx::val_str(), + or to Item::str_value, and thus is "less permanent" than "to". + + Reallocating "to" may give more benifits: + - "to" can point to a "more permanent" storage and can be reused + for multiple rows, e.g. str_buffer in Protocol::send_result_set_row(), + which is passed to val_str() for all string type rows. + - "from" can stay pointing to its original fixed size stack char array, + and thus reduce the total amount of my_alloc/my_free. + */ + } + + if (from == to) + { + /* + Possible string types: + #a not possible (constants should not be passed as "to") + #b possible (a fresh variable with no associated char buffer) + #c possible (a variable with a char buffer, + in case it's smaller than fixed_length) + #d not possible (handled earlier) + #e not possible (constants should not be passed as "to") + + If a string of types #a or #e appears here, that means the caller made + something wrong. Otherwise, it's safe to reallocate and return "to". + + Note, as we can't distinguish between #a and #b for sure, + so we can't assert "not #a", but we can at least assert "not #e". + */ + DBUG_ASSERT(!from->alloced || from->Alloced_length > 0); // Not #e + (void) from->realloc(from_length); return from; } @@ -803,7 +905,7 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length) if ((to->str_length=MY_MIN(from->str_length,from_length))) memcpy(to->Ptr,from->Ptr,to->str_length); to->str_charset=from->str_charset; - return to; + return to; // "from" was of types #a, #b, #e, or small #c. } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 08e47022b48..583058f80a5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB + Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -90,7 +90,7 @@ static char* add_identifier(THD* thd, char *to_p, const char * end_p, { uint res; uint errors; - const char *conv_name; + const char *conv_name, *conv_name_end; char tmp_name[FN_REFLEN]; char conv_string[FN_REFLEN]; int quote; @@ -111,11 +111,13 @@ static char* add_identifier(THD* thd, char *to_p, const char * end_p, { DBUG_PRINT("error", ("strconvert of '%s' failed with %u (errors: %u)", conv_name, res, errors)); conv_name= name; + conv_name_end= name + name_len; } else { DBUG_PRINT("info", ("conv '%s' -> '%s'", conv_name, conv_string)); conv_name= conv_string; + conv_name_end= conv_string + res; } quote = thd ? get_quote_char_for_identifier(thd, conv_name, res - 1) : '"'; @@ -125,8 +127,8 @@ static char* add_identifier(THD* thd, char *to_p, const char * end_p, *(to_p++)= (char) quote; while (*conv_name && (end_p - to_p - 1) > 0) { - uint length= my_mbcharlen(system_charset_info, *conv_name); - if (!length) + int length= my_charlen(system_charset_info, conv_name, conv_name_end); + if (length <= 0) length= 1; if (length == 1 && *conv_name == (char) quote) { @@ -573,7 +575,7 @@ uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen) DBUG_ENTER("build_tmptable_filename"); char *p= strnmov(buff, mysql_tmpdir, bufflen); - my_snprintf(p, bufflen - (p - buff), "/%s%lx_%lx_%x", + my_snprintf(p, bufflen - (p - buff), "/%s%lx_%llx_%x", tmp_file_prefix, current_pid, thd->thread_id, thd->tmp_table++); @@ -2232,7 +2234,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, const char *comment_start; uint32 comment_len; - built_query.set_charset(system_charset_info); + built_query.set_charset(thd->charset()); if (if_exists) built_query.append("DROP TABLE IF EXISTS "); else @@ -3448,8 +3450,31 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, else { /* Field redefined */ + + /* + If we are replacing a BIT field, revert the increment + of total_uneven_bit_length that was done above. + */ + if (sql_field->sql_type == MYSQL_TYPE_BIT && + file->ha_table_flags() & HA_CAN_BIT_FIELD) + total_uneven_bit_length-= sql_field->length & 7; + sql_field->def= dup_field->def; sql_field->sql_type= dup_field->sql_type; + + /* + If we are replacing a field with a BIT field, we need + to initialize pack_flag. Note that we do not need to + increment total_uneven_bit_length here as this dup_field + has already been processed. + */ + if (sql_field->sql_type == MYSQL_TYPE_BIT) + { + sql_field->pack_flag= FIELDFLAG_NUMBER; + if (!(file->ha_table_flags() & HA_CAN_BIT_FIELD)) + sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR; + } + sql_field->charset= (dup_field->charset ? dup_field->charset : create_info->default_table_charset); @@ -6167,6 +6192,7 @@ static bool fill_alter_inplace_info(THD *thd, c) flags passed to storage engine contain more detailed information about nature of changes than those provided from parser. */ + bool maybe_alter_vcol= false; for (f_ptr= table->field; (field= *f_ptr); f_ptr++) { /* Clear marker for renamed or dropped field @@ -6190,7 +6216,8 @@ static bool fill_alter_inplace_info(THD *thd, /* Check if type of column has changed to some incompatible type. */ - switch (field->is_equal(new_field)) + uint is_equal= field->is_equal(new_field); + switch (is_equal) { case IS_EQUAL_NO: /* New column type is incompatible with old one. */ @@ -6242,6 +6269,20 @@ static bool fill_alter_inplace_info(THD *thd, ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_TYPE; } + /* + Check if the column is computed and either + is stored or is used in the partitioning expression. + */ + if (field->vcol_info && + (field->stored_in_db() || field->vcol_info->is_in_partitioning_expr())) + { + if (is_equal == IS_EQUAL_NO || + !field->vcol_info->is_equal(new_field->vcol_info)) + ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_VCOL; + else + maybe_alter_vcol= true; + } + /* Check if field was renamed */ if (my_strcasecmp(system_charset_info, field->field_name, new_field->field_name)) @@ -6305,32 +6346,37 @@ static bool fill_alter_inplace_info(THD *thd, } } + if (maybe_alter_vcol) + { + /* + No virtual column was altered, but perhaps one of the other columns was, + and that column was part of the vcol expression? + We don't detect this correctly (FIXME), so let's just say that a vcol + *might* be affected if any other column was altered. + */ + if (ha_alter_info->handler_flags & + ( Alter_inplace_info::ALTER_COLUMN_TYPE + | Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE + | Alter_inplace_info::ALTER_COLUMN_OPTION )) + ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_VCOL; + } + new_field_it.init(alter_info->create_list); while ((new_field= new_field_it++)) { - Virtual_column_info *vcol_info; - if (new_field->field) - vcol_info= new_field->field->vcol_info; - else + if (! new_field->field) { - vcol_info= new_field->vcol_info; /* Field is not present in old version of table and therefore was added. Again corresponding storage engine flag should be already set. */ DBUG_ASSERT(ha_alter_info->handler_flags & Alter_inplace_info::ADD_COLUMN); - } - /* - Check if the altered column is computed and either - is stored or is used in the partitioning expression. - TODO: Mark such a column with an alter flag only if - the defining expression has changed. - */ - if (vcol_info && - (vcol_info->stored_in_db || vcol_info->is_in_partitioning_expr())) - { - ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_VCOL; + if (new_field->vcol_info && + (new_field->stored_in_db() || new_field->vcol_info->is_in_partitioning_expr())) + { + ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_VCOL; + } } } @@ -6917,7 +6963,7 @@ static bool mysql_inplace_alter_table(THD *thd, MDL_request *target_mdl_request, Alter_table_ctx *alter_ctx) { - Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN); + Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN | MYSQL_OPEN_IGNORE_KILLED); handlerton *db_type= table->s->db_type(); MDL_ticket *mdl_ticket= table->mdl_ticket; HA_CREATE_INFO *create_info= ha_alter_info->create_info; @@ -9143,13 +9189,13 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, error, but still worth reporting as it might indicate serious problem with server. */ - goto err_with_mdl; + goto err_with_mdl_after_alter; } end_inplace: if (thd->locked_tables_list.reopen_tables(thd)) - goto err_with_mdl; + goto err_with_mdl_after_alter; THD_STAGE_INFO(thd, stage_end); @@ -9230,6 +9276,10 @@ err_new_table_cleanup: DBUG_RETURN(true); +err_with_mdl_after_alter: + /* the table was altered. binlog the operation */ + write_bin_log(thd, true, thd->query(), thd->query_length()); + err_with_mdl: /* An error happened while we were holding exclusive name metadata lock @@ -9301,13 +9351,13 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, int error= 1; Copy_field *copy= NULL, *copy_end; ha_rows found_count= 0, delete_count= 0; + SORT_INFO *file_sort= 0; READ_RECORD info; TABLE_LIST tables; List<Item> fields; List<Item> all_fields; - ha_rows examined_rows; - ha_rows found_rows; bool auto_increment_field_copied= 0; + bool init_read_record_done= 0; ulonglong save_sql_mode= thd->variables.sql_mode; ulonglong prev_insert_id, time_to_report_progress; Field **dfield_ptr= to->default_field; @@ -9390,9 +9440,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, } else { - from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), - MYF(MY_FAE | MY_ZEROFILL | - MY_THREAD_SPECIFIC)); bzero((char *) &tables, sizeof(tables)); tables.table= from; tables.alias= tables.table_name= from->s->table_name.str; @@ -9400,16 +9447,13 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, THD_STAGE_INFO(thd, stage_sorting); Filesort_tracker dummy_tracker(false); + Filesort fsort(order, HA_POS_ERROR, NULL); if (thd->lex->select_lex.setup_ref_array(thd, order_num) || setup_order(thd, thd->lex->select_lex.ref_pointer_array, &tables, fields, all_fields, order)) goto err; - Filesort fsort(order, HA_POS_ERROR, NULL); - if ((from->sort.found_records= filesort(thd, from, &fsort, - true, - &examined_rows, &found_rows, - &dummy_tracker)) == - HA_POS_ERROR) + + if (!(file_sort= filesort(thd, from, &fsort, true, &dummy_tracker))) goto err; } thd_progress_next_stage(thd); @@ -9419,8 +9463,10 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, /* Tell handler that we have values for all columns in the to table */ to->use_all_columns(); to->mark_virtual_columns_for_write(TRUE); - if (init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE)) + if (init_read_record(&info, thd, from, (SQL_SELECT *) 0, file_sort, 1, 1, + FALSE)) goto err; + init_read_record_done= 1; if (ignore && !alter_ctx->fk_error_if_delete_row) to->file->extra(HA_EXTRA_IGNORE_DUP_KEY); @@ -9535,9 +9581,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, found_count++; thd->get_stmt_da()->inc_current_row_for_warning(); } - end_read_record(&info); - free_io_cache(from); - delete [] copy; THD_STAGE_INFO(thd, stage_enabling_keys); thd_progress_next_stage(thd); @@ -9558,6 +9601,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, error= 1; err: + /* Free resources */ + if (init_read_record_done) + end_read_record(&info); + delete [] copy; + delete file_sort; + thd->variables.sql_mode= save_sql_mode; thd->abort_on_warning= 0; *copied= found_count; diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 8e7525893eb..642cf208908 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -88,7 +88,7 @@ static my_bool print_cached_tables_callback(TDC_element *element, THD *in_use= entry->in_use; printf("%-14.14s %-32s%6ld%8ld%6d %s\n", entry->s->db.str, entry->s->table_name.str, element->version, - in_use ? in_use->thread_id : 0, + in_use ? (long) in_use->thread_id : (long) 0, entry->db_stat ? 1 : 0, in_use ? lock_descriptions[(int)entry->reginfo.lock_type] : "Not in use"); diff --git a/sql/sql_time.h b/sql/sql_time.h index 5a985710ee1..e0cab5cfa66 100644 --- a/sql/sql_time.h +++ b/sql/sql_time.h @@ -1,4 +1,5 @@ -/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. + Copyright (c) 2011, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 272e1445273..7a61279fc9c 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1101,6 +1101,7 @@ bool Table_triggers_list::prepare_record_accessors(TABLE *table) table == (*fld)->table))) return 1; + f->flags= (*fld)->flags; f->null_ptr= null_ptr; f->null_bit= null_bit; if (null_bit == 128) @@ -2305,7 +2306,7 @@ void Table_triggers_list::mark_fields_used(trg_event_type event) /** - Signals to the Table_triggers_list that a parse error has occured when + Signals to the Table_triggers_list that a parse error has occurred when reading a trigger from file. This makes the Table_triggers_list enter an error state flagged by m_has_unparseable_trigger == true. The error message will be used whenever a statement invoking or manipulating triggers is diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 4e492e7099d..d85664568a1 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -433,10 +433,8 @@ Field *Type_handler_timestamp::make_conversion_table_field(TABLE *table, const Field *target) const { - // We assume TIMESTAMP(0) - return new(table->in_use->mem_root) - Field_timestamp(NULL, MAX_DATETIME_WIDTH, (uchar *) "", 1, - Field::NONE, TMPNAME, table->s); + return new_Field_timestamp(table->in_use->mem_root, NULL, (uchar *) "", 1, + Field::NONE, TMPNAME, table->s, target->decimals()); } @@ -476,9 +474,8 @@ Field *Type_handler_time::make_conversion_table_field(TABLE *table, const Field *target) const { - return new(table->in_use->mem_root) - Field_time(NULL, MAX_TIME_WIDTH, (uchar *) "", 1, - Field::NONE, TMPNAME); + return new_Field_time(table->in_use->mem_root, NULL, (uchar *) "", 1, + Field::NONE, TMPNAME, target->decimals()); } @@ -497,9 +494,8 @@ Field *Type_handler_datetime::make_conversion_table_field(TABLE *table, const Field *target) const { - return new(table->in_use->mem_root) - Field_datetime(NULL, MAX_DATETIME_WIDTH, (uchar *) "", 1, - Field::NONE, TMPNAME); + return new_Field_datetime(table->in_use->mem_root, NULL, (uchar *) "", 1, + Field::NONE, TMPNAME, target->decimals()); } diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 0b294b5af8c..502bc88c489 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -180,7 +180,8 @@ void udf_init() } table= tables.table; - if (init_read_record(&read_record_info, new_thd, table, NULL,1,0,FALSE)) + if (init_read_record(&read_record_info, new_thd, table, NULL, NULL, 1, 0, + FALSE)) { sql_print_error("Could not initialize init_read_record; udf's not " "loaded"); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 4dac37eb563..87b836f40d9 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -173,7 +173,8 @@ select_union::create_result_table(THD *thd_arg, List<Item> *column_types, /** - Reset and empty the temporary table that stores the materialized query result. + Reset and empty the temporary table that stores the materialized query + result. @note The cleanup performed here is exactly the same as for the two temp tables of JOIN - exec_tmp_table_[1 | 2]. @@ -183,8 +184,6 @@ void select_union::cleanup() { table->file->extra(HA_EXTRA_RESET_STATE); table->file->ha_delete_all_rows(); - free_io_cache(table); - filesort_free_buffers(table,0); } @@ -1152,11 +1151,22 @@ List<Item> *st_select_lex_unit::get_unit_column_types() return &sl->item_list; } + +static void cleanup_order(ORDER *order) +{ + for (; order; order= order->next) + order->counter_used= 0; +} + + bool st_select_lex::cleanup() { bool error= FALSE; DBUG_ENTER("st_select_lex::cleanup()"); + cleanup_order(order_list.first); + cleanup_order(group_list.first); + if (join) { DBUG_ASSERT((st_select_lex*)join->select_lex == this); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index b9f7b53b2bf..739bef82ab2 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -270,6 +270,7 @@ int mysql_update(THD *thd, key_map old_covering_keys; TABLE *table; SQL_SELECT *select= NULL; + SORT_INFO *file_sort= 0; READ_RECORD info; SELECT_LEX *select_lex= &thd->lex->select_lex; ulonglong id; @@ -369,6 +370,9 @@ int mysql_update(THD *thd, if (check_unique_table(thd, table_list)) DBUG_RETURN(TRUE); + switch_to_nullable_trigger_fields(fields, table); + switch_to_nullable_trigger_fields(values, table); + /* Apply the IN=>EXISTS transformation to all subqueries and optimize them. */ if (select_lex->optimize_unflattened_subqueries(false)) DBUG_RETURN(TRUE); @@ -418,7 +422,7 @@ int mysql_update(THD *thd, table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); set_statistics_for_table(thd, table); - select= make_select(table, 0, 0, conds, 0, &error); + select= make_select(table, 0, 0, conds, (SORT_INFO*) 0, 0, &error); if (error || !limit || thd->is_error() || (select && select->check_quick(thd, safe_update, limit))) { @@ -456,8 +460,6 @@ int mysql_update(THD *thd, } init_ftfuncs(thd, select_lex, 1); - switch_to_nullable_trigger_fields(fields, table); - switch_to_nullable_trigger_fields(values, table); table->mark_columns_needed_for_update(); table->update_const_key_parts(conds); @@ -556,24 +558,15 @@ int mysql_update(THD *thd, to update NOTE: filesort will call table->prepare_for_position() */ - ha_rows examined_rows; - ha_rows found_rows; Filesort fsort(order, limit, select); - table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), - MYF(MY_FAE | MY_ZEROFILL | - MY_THREAD_SPECIFIC)); Filesort_tracker *fs_tracker= thd->lex->explain->get_upd_del_plan()->filesort_tracker; - if ((table->sort.found_records= filesort(thd, table, &fsort, true, - &examined_rows, &found_rows, - fs_tracker)) - == HA_POS_ERROR) - { + if (!(file_sort= filesort(thd, table, &fsort, true, fs_tracker))) goto err; - } - thd->inc_examined_row_count(examined_rows); + thd->inc_examined_row_count(file_sort->examined_rows); + /* Filesort has already found and selected the rows we want to update, so we don't need the where clause @@ -614,7 +607,7 @@ int mysql_update(THD *thd, */ if (query_plan.index == MAX_KEY || (select && select->quick)) - error= init_read_record(&info, thd, table, select, 0, 1, FALSE); + error= init_read_record(&info, thd, table, select, NULL, 0, 1, FALSE); else error= init_read_record_idx(&info, thd, table, 1, query_plan.index, reverse); @@ -658,8 +651,9 @@ int mysql_update(THD *thd, else { /* - Don't try unlocking the row if skip_record reported an error since in - this case the transaction might have been rolled back already. + Don't try unlocking the row if skip_record reported an + error since in this case the transaction might have been + rolled back already. */ if (error < 0) { @@ -708,7 +702,7 @@ int mysql_update(THD *thd, if (select && select->quick && select->quick->reset()) goto err; table->file->try_semi_consistent_read(1); - if (init_read_record(&info, thd, table, select, 0, 1, FALSE)) + if (init_read_record(&info, thd, table, select, file_sort, 0, 1, FALSE)) goto err; updated= found= 0; @@ -1016,6 +1010,7 @@ int mysql_update(THD *thd, } DBUG_ASSERT(transactional_table || !updated || thd->transaction.stmt.modified_non_trans_table); free_underlaid_joins(thd, select_lex); + delete file_sort; /* If LAST_INSERT_ID(X) was used, report X */ id= thd->arg_of_last_insert_id_function ? @@ -1049,6 +1044,7 @@ int mysql_update(THD *thd, err: delete select; + delete file_sort; free_underlaid_joins(thd, select_lex); table->set_keyread(false); thd->abort_on_warning= 0; @@ -2430,6 +2426,10 @@ int multi_update::do_updates() int error; if (table->default_field && (error= table->update_default_fields())) goto err2; + if (table->vfield && + update_virtual_fields(thd, table, + (table->triggers ? VCOL_UPDATE_ALL : VCOL_UPDATE_FOR_WRITE))) + goto err2; if ((error= cur_table->view_check_option(thd, ignore)) != VIEW_CHECK_OK) { @@ -2586,7 +2586,7 @@ bool multi_update::send_eof() if (local_error > 0) // if the above log write did not fail ... { /* Safety: If we haven't got an error before (can happen in do_updates) */ - my_message(ER_UNKNOWN_ERROR, "An error occured in multi-table update", + my_message(ER_UNKNOWN_ERROR, "An error occurred in multi-table update", MYF(0)); DBUG_RETURN(TRUE); } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 62e6790a142..41fd5b78f04 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -167,7 +167,7 @@ err: @param item_list List of Items which should be checked */ -static void make_valid_column_names(THD *thd, List<Item> &item_list) +void make_valid_column_names(THD *thd, List<Item> &item_list) { Item *item; uint name_len; @@ -215,7 +215,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) TABLE_LIST decoy; memcpy (&decoy, view, sizeof (TABLE_LIST)); - if (tdc_open_view(thd, &decoy, decoy.alias, OPEN_VIEW_NO_PARSE)) + if (tdc_open_view(thd, &decoy, OPEN_VIEW_NO_PARSE)) return TRUE; if (!lex->definer) @@ -244,7 +244,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view) @param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE @retval FALSE Operation was a success. - @retval TRUE An error occured. + @retval TRUE An error occurred. */ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, @@ -387,7 +387,7 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, @note This function handles both create and alter view commands. @retval FALSE Operation was a success. - @retval TRUE An error occured. + @retval TRUE An error occurred. */ bool mysql_create_view(THD *thd, TABLE_LIST *views, @@ -901,9 +901,11 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, ulong sql_mode= thd->variables.sql_mode & MODE_ANSI_QUOTES; thd->variables.sql_mode&= ~MODE_ANSI_QUOTES; - lex->unit.print(&view_query, QT_VIEW_INTERNAL); - lex->unit.print(&is_query, - enum_query_type(QT_TO_SYSTEM_CHARSET | QT_WITHOUT_INTRODUCERS)); + lex->unit.print(&view_query, enum_query_type(QT_VIEW_INTERNAL | + QT_ITEM_ORIGINAL_FUNC_NULLIF)); + lex->unit.print(&is_query, enum_query_type(QT_TO_SYSTEM_CHARSET | + QT_WITHOUT_INTRODUCERS | + QT_ITEM_ORIGINAL_FUNC_NULLIF)); thd->variables.sql_mode|= sql_mode; } @@ -1535,8 +1537,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, /* Fields in this view can be used in upper select in case of merge. */ if (table->select_lex) - table->select_lex->select_n_where_fields+= - lex->select_lex.select_n_where_fields; + table->select_lex->add_where_field(&lex->select_lex); } /* This method has a dependency on the proper lock type being set, diff --git a/sql/sql_view.h b/sql/sql_view.h index 9c75643fd48..b9eb92198f8 100644 --- a/sql/sql_view.h +++ b/sql/sql_view.h @@ -56,8 +56,12 @@ bool check_duplicate_names(THD *thd, List<Item>& item_list, bool mysql_rename_view(THD *thd, const char *new_db, const char *new_name, TABLE_LIST *view); +void make_valid_column_names(THD *thd, List<Item> &item_list); + #define VIEW_ANY_ACL (SELECT_ACL | UPDATE_ACL | INSERT_ACL | DELETE_ACL) extern const LEX_STRING view_type; +void make_valid_column_names(List<Item> &item_list); + #endif /* SQL_VIEW_INCLUDED */ diff --git a/sql/sql_window.cc b/sql/sql_window.cc index 0352a0dfb5f..ef7f512f7fc 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -265,7 +265,7 @@ int rr_from_pointers(READ_RECORD *info); */ bool clone_read_record(const READ_RECORD *src, READ_RECORD *dst) { - DBUG_ASSERT(src->table->sort.record_pointers); + //DBUG_ASSERT(src->table->sort.record_pointers); DBUG_ASSERT(src->read_record == rr_from_pointers); memcpy(dst, src, sizeof(READ_RECORD)); return false; @@ -1534,8 +1534,9 @@ bool Window_func_runner::setup(THD *thd) bool Window_func_runner::exec(JOIN *join) { THD *thd= join->thd; + JOIN_TAB *join_tab= &join->join_tab[join->top_join_tab_count]; - if (create_sort_index(thd, join, &join->join_tab[join->top_join_tab_count], + if (create_sort_index(thd, join, join_tab, filesort)) return true; @@ -1545,19 +1546,18 @@ bool Window_func_runner::exec(JOIN *join) Go through the sorted array and compute the window function */ READ_RECORD info; - TABLE *tbl= join->join_tab[join->top_join_tab_count].table; + TABLE *tbl= join_tab->table; - if (init_read_record(&info, thd, tbl, NULL/*select*/, 0, 1, FALSE)) + if (init_read_record(&info, thd, tbl, NULL/*select*/, join_tab->filesort_result, + 0, 1, FALSE)) return true; bool is_error= compute_func(win_func, tbl, &info); /* This calls filesort_free_buffers(): */ end_read_record(&info); - - //TODO: should this be moved to cleanup: ? - free_io_cache(tbl); - + delete join_tab->filesort_result; + join_tab->filesort_result= NULL; win_func->set_phase_to_retrieval(); return is_error; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index bb939bb6994..b8d0238b753 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -54,6 +54,7 @@ #include "sql_handler.h" // Sql_cmd_handler_* #include "sql_signal.h" #include "sql_get_diagnostics.h" // Sql_cmd_get_diagnostics +#include "sql_cte.h" #include "sql_window.h" #include "item_windowfunc.h" #include "event_parse_data.h" @@ -250,6 +251,35 @@ static bool maybe_start_compound_statement(THD *thd) return 0; } +static bool push_sp_label(THD *thd, LEX_STRING label) +{ + sp_pcontext *ctx= thd->lex->spcont; + sp_label *lab= ctx->find_label(label); + + if (lab) + { + my_error(ER_SP_LABEL_REDEFINE, MYF(0), label.str); + return 1; + } + else + { + lab= thd->lex->spcont->push_label(thd, label, + thd->lex->sphead->instructions()); + lab->type= sp_label::ITERATION; + } + return 0; +} + +static bool push_sp_empty_label(THD *thd) +{ + if (maybe_start_compound_statement(thd)) + return 1; + /* Unlabeled controls get an empty label. */ + thd->lex->spcont->push_label(thd, empty_lex_str, + thd->lex->sphead->instructions()); + return 0; +} + /** Helper action for a case expression statement (the expr in 'CASE expr'). This helper is used for 'searched' cases only. @@ -961,6 +991,8 @@ bool LEX::set_bincmp(CHARSET_INFO *cs, bool bin) class sp_label *splabel; class sp_name *spname; class sp_variable *spvar; + class With_clause *with_clause; + handlerton *db_type; st_select_lex *select_lex; struct p_elem_val *p_elem_value; @@ -1472,6 +1504,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token REAL /* SQL-2003-R */ %token REBUILD_SYM %token RECOVER_SYM +%token RECURSIVE_SYM %token REDOFILE_SYM %token REDO_BUFFER_SIZE_SYM %token REDUNDANT_SYM @@ -1760,6 +1793,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); case_stmt_body opt_bin_mod opt_if_exists_table_element opt_if_not_exists_table_element opt_into opt_procedure_clause + opt_recursive %type <object_ddl_options> create_or_replace @@ -1973,6 +2007,7 @@ END_OF_INPUT %type <NONE> sp_proc_stmt_iterate %type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close %type <NONE> case_stmt_specification +%type <NONE> loop_body while_body repeat_body %type <num> sp_decl_idents sp_handler_type sp_hcond_list %type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value @@ -2013,6 +2048,10 @@ END_OF_INPUT THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM DELETE_SYM ROLE_SYM +%type <with_clause> opt_with_clause with_clause + +%type <lex_str_ptr> query_name + %% @@ -2577,6 +2616,7 @@ create: } view_or_trigger_or_sp_or_event { } | create_or_replace USER opt_if_not_exists clear_privileges grant_list + opt_require_clause opt_resource_options { if (Lex->set_command_with_check(SQLCOM_CREATE_USER, $1 | $3)) MYSQL_YYABORT; @@ -3783,7 +3823,7 @@ sp_proc_stmt_statement: if (yychar == YYEMPTY) i->m_query.length= lip->get_ptr() - sp->m_tmp_query; else - i->m_query.length= lip->get_tok_end() - sp->m_tmp_query; + i->m_query.length= lip->get_tok_start() - sp->m_tmp_query;; if (!(i->m_query.str= strmake_root(thd->mem_root, sp->m_tmp_query, i->m_query.length)) || @@ -3825,20 +3865,6 @@ sp_proc_stmt_return: } ; -sp_unlabeled_control: - { - if (maybe_start_compound_statement(thd)) - MYSQL_YYABORT; - /* Unlabeled controls get an empty label. */ - Lex->spcont->push_label(thd, empty_lex_str, - Lex->sphead->instructions()); - } - sp_control_content - { - Lex->sphead->backpatch(Lex->spcont->pop_label()); - } - ; - sp_proc_stmt_leave: LEAVE_SYM label_ident { @@ -4257,41 +4283,6 @@ else_clause_opt: | ELSE sp_proc_stmts1 ; -sp_labeled_control: - label_ident ':' - { - LEX *lex= Lex; - sp_pcontext *ctx= lex->spcont; - sp_label *lab= ctx->find_label($1); - - if (lab) - { - my_error(ER_SP_LABEL_REDEFINE, MYF(0), $1.str); - MYSQL_YYABORT; - } - else - { - lab= lex->spcont->push_label(thd, $1, lex->sphead->instructions()); - lab->type= sp_label::ITERATION; - } - } - sp_control_content sp_opt_label - { - LEX *lex= Lex; - sp_label *lab= lex->spcont->pop_label(); - - if ($5.str) - { - if (my_strcasecmp(system_charset_info, $5.str, lab->name.str) != 0) - { - my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str); - MYSQL_YYABORT; - } - } - lex->sphead->backpatch(lab); - } - ; - sp_opt_label: /* Empty */ { $$= null_lex_str; } | label_ident { $$= $1; } @@ -4384,8 +4375,7 @@ sp_block_content: } ; -sp_control_content: - LOOP_SYM +loop_body: sp_proc_stmts1 END LOOP_SYM { LEX *lex= Lex; @@ -4397,15 +4387,16 @@ sp_control_content: lex->sphead->add_instr(i)) MYSQL_YYABORT; } - | WHILE_SYM - { Lex->sphead->reset_lex(thd); } + ; + +while_body: expr DO_SYM { LEX *lex= Lex; sp_head *sp= lex->sphead; uint ip= sp->instructions(); sp_instr_jump_if_not *i= new (lex->thd->mem_root) - sp_instr_jump_if_not(ip, lex->spcont, $3, lex); + sp_instr_jump_if_not(ip, lex->spcont, $1, lex); if (i == NULL || /* Jumping forward */ sp->push_backpatch(thd, i, lex->spcont->last_label()) || @@ -4427,7 +4418,10 @@ sp_control_content: MYSQL_YYABORT; lex->sphead->do_cont_backpatch(); } - | REPEAT_SYM sp_proc_stmts1 UNTIL_SYM + ; + +repeat_body: + sp_proc_stmts1 UNTIL_SYM { Lex->sphead->reset_lex(thd); } expr END REPEAT_SYM { @@ -4435,7 +4429,7 @@ sp_control_content: uint ip= lex->sphead->instructions(); sp_label *lab= lex->spcont->last_label(); /* Jumping back */ sp_instr_jump_if_not *i= new (lex->thd->mem_root) - sp_instr_jump_if_not(ip, lex->spcont, $5, lab->ip, lex); + sp_instr_jump_if_not(ip, lex->spcont, $4, lab->ip, lex); if (i == NULL || lex->sphead->add_instr(i)) MYSQL_YYABORT; @@ -4446,6 +4440,84 @@ sp_control_content: } ; +pop_sp_label: + sp_opt_label + { + sp_label *lab; + Lex->sphead->backpatch(lab= Lex->spcont->pop_label()); + if ($1.str) + { + if (my_strcasecmp(system_charset_info, $1.str, + lab->name.str) != 0) + { + my_error(ER_SP_LABEL_MISMATCH, MYF(0), $1.str); + MYSQL_YYABORT; + } + } + } + ; + +pop_sp_empty_label: + { + sp_label *lab; + Lex->sphead->backpatch(lab= Lex->spcont->pop_label()); + DBUG_ASSERT(lab->name.length == 0); + } + ; + +sp_labeled_control: + label_ident ':' LOOP_SYM + { + if (push_sp_label(thd, $1)) + MYSQL_YYABORT; + } + loop_body pop_sp_label + { } + | label_ident ':' WHILE_SYM + { + if (push_sp_label(thd, $1)) + MYSQL_YYABORT; + Lex->sphead->reset_lex(thd); + } + while_body pop_sp_label + { } + | label_ident ':' REPEAT_SYM + { + if (push_sp_label(thd, $1)) + MYSQL_YYABORT; + } + repeat_body pop_sp_label + { } + ; + +sp_unlabeled_control: + LOOP_SYM + { + if (push_sp_empty_label(thd)) + MYSQL_YYABORT; + } + loop_body + pop_sp_empty_label + { } + | WHILE_SYM + { + if (push_sp_empty_label(thd)) + MYSQL_YYABORT; + Lex->sphead->reset_lex(thd); + } + while_body + pop_sp_empty_label + { } + | REPEAT_SYM + { + if (push_sp_empty_label(thd)) + MYSQL_YYABORT; + } + repeat_body + pop_sp_empty_label + { } + ; + trg_action_time: BEFORE_SYM { Lex->trg_chistics.action_time= TRG_ACTION_BEFORE; } @@ -4912,7 +4984,7 @@ opt_create_partitioning: /* This part of the parser is about handling of the partition information. - It's first version was written by Mikael Ronström with lots of answers to + It's first version was written by Mikael Ronstrm with lots of answers to questions provided by Antony Curtis. The partition grammar can be called from three places. @@ -7311,6 +7383,13 @@ alter: lex->sql_command= SQLCOM_ALTER_SERVER; lex->server_options.reset($3); } OPTIONS_SYM '(' server_options_list ')' { } + /* ALTER USER foo is allowed for MySQL compatibility. */ + | ALTER opt_if_exists USER clear_privileges grant_list + opt_require_clause opt_resource_options + { + Lex->create_info.set($2); + Lex->sql_command= SQLCOM_ALTER_USER; + } ; ev_alter_on_schedule_completion: @@ -7368,7 +7447,7 @@ alter_commands: | remove_partitioning | partitioning /* - This part was added for release 5.1 by Mikael Ronström. + This part was added for release 5.1 by Mikael Ronstrm. From here we insert a number of commands to manage the partitions of a partitioned table such as adding partitions, dropping partitions, reorganising partitions in various manners. In future releases the list @@ -8419,10 +8498,11 @@ opt_ignore_leaves: select: - select_init + opt_with_clause select_init { LEX *lex= Lex; lex->sql_command= SQLCOM_SELECT; + lex->current_select->set_with_clause($1); } ; @@ -10930,20 +11010,20 @@ table_factor: and our parser. Possibly this rule could be replaced by our query_expression_body. */ - | '(' get_select_lex select_derived_union ')' opt_table_alias + | '('opt_with_clause get_select_lex select_derived_union ')' opt_table_alias { - /* Use $2 instead of Lex->current_select as derived table will + /* Use $3 instead of Lex->current_select as derived table will alter value of Lex->current_select. */ - if (!($3 || $5) && $2->embedding && - !$2->embedding->nested_join->join_list.elements) + if (!($4 || $6) && $3->embedding && + !$3->embedding->nested_join->join_list.elements) { - /* we have a derived table ($3 == NULL) but no alias, + /* we have a derived table ($4 == NULL) but no alias, Since we are nested in further parentheses so we can pass NULL to the outer level parentheses Permits parsing of "((((select ...))) as xyz)" */ $$= 0; } - else if (!$3) + else if (!$4) { /* Handle case of derived table, alias may be NULL if there are no outer parentheses, add_table_to_list() will throw @@ -10951,33 +11031,25 @@ table_factor: LEX *lex=Lex; SELECT_LEX *sel= lex->current_select; SELECT_LEX_UNIT *unit= sel->master_unit(); + unit->set_with_clause($2); lex->current_select= sel= unit->outer_select(); Table_ident *ti= new (thd->mem_root) Table_ident(unit); if (ti == NULL) MYSQL_YYABORT; if (!($$= sel->add_table_to_list(lex->thd, - ti, $5, 0, + ti, $6, 0, TL_READ, MDL_SHARED_READ))) MYSQL_YYABORT; sel->add_joined_table($$); lex->pop_context(); lex->nest_level--; - /* - Fields in derived table can be used in upper select in - case of merge. We do not add HAVING fields because we do - not merge such derived. We do not add union because - also do not merge them - */ - if (!sel->next_select()) - $2->select_n_where_fields+= - sel->select_n_where_fields; } - /*else if (($3->select_lex && - $3->select_lex->master_unit()->is_union() && - ($3->select_lex->master_unit()->first_select() == - $3->select_lex || !$3->lifted)) || $5)*/ - else if ($5 != NULL) + /*else if (($4->select_lex && + $4->select_lex->master_unit()->is_union() && + ($4->select_lex->master_unit()->first_select() == + $4->select_lex || !$4->lifted)) || $6)*/ + else if ($6 != NULL) { /* Tables with or without joins within parentheses cannot @@ -10990,8 +11062,17 @@ table_factor: { /* nested join: FROM (t1 JOIN t2 ...), nest_level is the same as in the outer query */ - $$= $3; + $$= $4; } + /* + Fields in derived table can be used in upper select in + case of merge. We do not add HAVING fields because we do + not merge such derived. We do not add union because + also do not merge them + */ + if ($$ && $$->derived && + !$$->derived->first_select()->next_select()) + $$->select_lex->add_where_field($$->derived->first_select()); } ; @@ -12968,6 +13049,18 @@ show_param: lex->sql_command= SQLCOM_SHOW_CREATE_TRIGGER; lex->spname= $3; } + | CREATE USER + { + Lex->sql_command= SQLCOM_SHOW_CREATE_USER; + if (!(Lex->grant_user= (LEX_USER*)thd->alloc(sizeof(LEX_USER)))) + MYSQL_YYABORT; + Lex->grant_user->user= current_user; + } + | CREATE USER user + { + Lex->sql_command= SQLCOM_SHOW_CREATE_USER; + Lex->grant_user= $3; + } | PROCEDURE_SYM STATUS_SYM wild_and_where { LEX *lex= Lex; @@ -13007,9 +13100,10 @@ show_param: | IDENT_sys remember_tok_start wild_and_where { LEX *lex= Lex; + bool in_plugin; lex->sql_command= SQLCOM_SHOW_GENERIC; - ST_SCHEMA_TABLE *table= find_schema_table(thd, $1.str); - if (!table || !table->old_format) + ST_SCHEMA_TABLE *table= find_schema_table(thd, $1.str, &in_plugin); + if (!table || !table->old_format || !in_plugin) { my_parse_error(thd, ER_SYNTAX_ERROR, $2); MYSQL_YYABORT; @@ -13916,8 +14010,93 @@ temporal_literal: ; +opt_with_clause: + /*empty */ { $$= 0; } + | with_clause + { + $$= $1; + Lex->derived_tables|= DERIVED_WITH; + } + ; + + +with_clause: + WITH opt_recursive + { + With_clause *with_clause= + new With_clause($2, Lex->curr_with_clause); + if (with_clause == NULL) + MYSQL_YYABORT; + Lex->curr_with_clause= with_clause; + with_clause->add_to_list(Lex->with_clauses_list_last_next); + } + with_list + { + $$= Lex->curr_with_clause; + Lex->curr_with_clause= Lex->curr_with_clause->pop(); + } + ; + + +opt_recursive: + /*empty*/ { $$= 0; } + | RECURSIVE_SYM { $$= 1; } + ; + + +with_list: + with_list_element + | with_list ',' with_list_element + ; + + +with_list_element: + query_name + opt_with_column_list + AS '(' remember_name subselect remember_end ')' + { + With_element *elem= new With_element($1, Lex->with_column_list, $6->master_unit()); + if (elem == NULL || Lex->curr_with_clause->add_with_element(elem)) + MYSQL_YYABORT; + Lex->with_column_list.empty(); + if (elem->set_unparsed_spec(thd, $5+1, $7)) + MYSQL_YYABORT; + } + ; + + +opt_with_column_list: + /* empty */ + {} + | '(' with_column_list ')' + ; + + +with_column_list: + ident + { + Lex->with_column_list.push_back((LEX_STRING*) + thd->memdup(&$1, sizeof(LEX_STRING))); + } + | with_column_list ',' ident + { + Lex->with_column_list.push_back((LEX_STRING*) + thd->memdup(&$3, sizeof(LEX_STRING))); + } + ; + + +query_name: + ident + { + $$= (LEX_STRING *) thd->memdup(&$1, sizeof(LEX_STRING)); + if ($$ == NULL) + MYSQL_YYABORT; + } + ; + /********************************************************************** ** Creating different items. **********************************************************************/ @@ -14343,9 +14522,7 @@ user_maybe_role: MYSQL_YYABORT; $$->user = $1; $$->host= null_lex_str; // User or Role, see get_current_user() - $$->password= null_lex_str; - $$->plugin= empty_lex_str; - $$->auth= empty_lex_str; + $$->reset_auth(); if (check_string_char_length(&$$->user, ER_USERNAME, username_char_length, @@ -14357,9 +14534,7 @@ user_maybe_role: if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) MYSQL_YYABORT; $$->user = $1; $$->host=$3; - $$->password= null_lex_str; - $$->plugin= empty_lex_str; - $$->auth= empty_lex_str; + $$->reset_auth(); if (check_string_char_length(&$$->user, ER_USERNAME, username_char_length, @@ -15275,14 +15450,14 @@ opt_for_user: ; text_or_password: - TEXT_STRING { Lex->definer->auth= $1;} - | PASSWORD_SYM '(' TEXT_STRING ')' { Lex->definer->password= $3; } + TEXT_STRING { Lex->definer->pwhash= $1;} + | PASSWORD_SYM '(' TEXT_STRING ')' { Lex->definer->pwtext= $3; } | OLD_PASSWORD_SYM '(' TEXT_STRING ')' { - Lex->definer->password= $3; - Lex->definer->auth.str= Item_func_password::alloc(thd, + Lex->definer->pwtext= $3; + Lex->definer->pwhash.str= Item_func_password::alloc(thd, $3.str, $3.length, Item_func_password::OLD); - Lex->definer->auth.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; + Lex->definer->pwhash.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; } ; @@ -15546,14 +15721,14 @@ grant: grant_command: grant_privileges ON opt_table grant_ident TO_SYM grant_list - require_clause grant_options + opt_require_clause opt_grant_options { LEX *lex= Lex; lex->sql_command= SQLCOM_GRANT; lex->type= 0; } | grant_privileges ON FUNCTION_SYM grant_ident TO_SYM grant_list - require_clause grant_options + opt_require_clause opt_grant_options { LEX *lex= Lex; if (lex->columns.elements) @@ -15565,7 +15740,7 @@ grant_command: lex->type= TYPE_ENUM_FUNCTION; } | grant_privileges ON PROCEDURE_SYM grant_ident TO_SYM grant_list - require_clause grant_options + opt_require_clause opt_grant_options { LEX *lex= Lex; if (lex->columns.elements) @@ -15621,9 +15796,7 @@ current_role: if (!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER)))) MYSQL_YYABORT; $$->user= current_role; - $$->password= null_lex_str; - $$->plugin= empty_lex_str; - $$->auth= empty_lex_str; + $$->reset_auth(); } ; @@ -15642,9 +15815,7 @@ grant_role: MYSQL_YYABORT; $$->user = $1; $$->host= empty_lex_str; - $$->password= null_lex_str; - $$->plugin= empty_lex_str; - $$->auth= empty_lex_str; + $$->reset_auth(); if (check_string_char_length(&$$->user, ER_USERNAME, username_char_length, @@ -15860,14 +16031,15 @@ using_or_as: USING | AS ; grant_user: user IDENTIFIED_SYM BY TEXT_STRING { - $$=$1; $1->password=$4; + $$= $1; + $1->pwtext= $4; if (Lex->sql_command == SQLCOM_REVOKE) MYSQL_YYABORT; } | user IDENTIFIED_SYM BY PASSWORD_SYM TEXT_STRING { $$= $1; - $1->auth= $5; + $1->pwhash= $5; } | user IDENTIFIED_SYM via_or_with ident_or_text { @@ -15928,7 +16100,7 @@ column_list_id: } ; -require_clause: +opt_require_clause: /* empty */ | REQUIRE_SYM require_list { @@ -15948,24 +16120,8 @@ require_clause: } ; -grant_options: - /* empty */ {} - | WITH grant_option_list - ; - -opt_grant_option: - /* empty */ {} - | WITH GRANT OPTION { Lex->grant |= GRANT_ACL;} - ; - -grant_option_list: - grant_option_list grant_option {} - | grant_option {} - ; - -grant_option: - GRANT OPTION { Lex->grant |= GRANT_ACL;} - | MAX_QUERIES_PER_HOUR ulong_num +resource_option: + MAX_QUERIES_PER_HOUR ulong_num { LEX *lex=Lex; lex->mqh.questions=$2; @@ -15997,6 +16153,37 @@ grant_option: } ; +resource_option_list: + resource_option_list resource_option {} + | resource_option {} + ; + +opt_resource_options: + /* empty */ {} + | WITH resource_option_list + ; + + +opt_grant_options: + /* empty */ {} + | WITH grant_option_list {} + ; + +opt_grant_option: + /* empty */ {} + | WITH GRANT OPTION { Lex->grant |= GRANT_ACL;} + ; + +grant_option_list: + grant_option_list grant_option {} + | grant_option {} + ; + +grant_option: + GRANT OPTION { Lex->grant |= GRANT_ACL;} + | resource_option {} + ; + begin: BEGIN_SYM { @@ -16192,9 +16379,10 @@ query_expression_body: /* Corresponds to <query expression> in the SQL:2003 standard. */ subselect: - subselect_start query_expression_body subselect_end + subselect_start opt_with_clause query_expression_body subselect_end { - $$= $2; + $3->set_with_clause($2); + $$= $3; } ; @@ -16421,7 +16609,7 @@ view_select: lex->parsing_options.allows_derived= FALSE; lex->create_view_select.str= (char *) YYLIP->get_cpp_ptr(); } - view_select_aux view_check_option + opt_with_clause view_select_aux view_check_option { LEX *lex= Lex; uint len= YYLIP->get_cpp_ptr() - lex->create_view_select.str; @@ -16433,6 +16621,7 @@ view_select: lex->parsing_options.allows_select_into= TRUE; lex->parsing_options.allows_select_procedure= TRUE; lex->parsing_options.allows_derived= TRUE; + lex->current_select->set_with_clause($2); } ; diff --git a/sql/structs.h b/sql/structs.h index 8dc6323bde0..e51f3e0fe3a 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -202,7 +202,8 @@ extern const char *show_comp_option_name[]; typedef int *(*update_var)(THD *, struct st_mysql_show_var *); typedef struct st_lex_user { - LEX_STRING user, host, password, plugin, auth; + LEX_STRING user, host, plugin, auth; + LEX_STRING pwtext, pwhash; bool is_role() { return user.str[0] && !host.str[0]; } void set_lex_string(LEX_STRING *l, char *buf) { @@ -211,6 +212,12 @@ typedef struct st_lex_user { else l->length= strxmov(l->str= buf, user.str, "@", host.str, NullS) - buf; } + void reset_auth() + { + pwtext.length= pwhash.length= plugin.length= auth.length= 0; + pwtext.str= pwhash.str= 0; + plugin.str= auth.str= const_cast<char*>(""); + } } LEX_USER; /* diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index cdd2366ca29..9d871703bfe 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -283,7 +283,7 @@ static Sys_var_long Sys_pfs_events_stages_history_size( /** Variable performance_schema_max_statement_classes. The default number of statement classes is the sum of: - - COM_END for all regular "statement/com/...", + - (COM_END - mariadb gap) for all regular "statement/com/...", - 1 for "statement/com/new_packet", for unknown enum_server_command - 1 for "statement/com/Error", for invalid enum_server_command - SQLCOM_END for all regular "statement/sql/...", @@ -295,7 +295,8 @@ static Sys_var_ulong Sys_pfs_max_statement_classes( "Maximum number of statement instruments.", PARSED_EARLY READ_ONLY GLOBAL_VAR(pfs_param.m_statement_class_sizing), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256), - DEFAULT((ulong) SQLCOM_END + (ulong) COM_END + 4), + DEFAULT((ulong) SQLCOM_END + + (ulong) (COM_END -(COM_MDB_GAP_END - COM_MDB_GAP_BEG + 1)) + 4), BLOCK_SIZE(1)); static Sys_var_long Sys_pfs_events_statements_history_long_size( @@ -1183,6 +1184,19 @@ static Sys_var_mybool Sys_log_queries_not_using_indexes( GLOBAL_VAR(opt_log_queries_not_using_indexes), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); +static Sys_var_mybool Sys_log_slow_admin_statements( + "log_slow_admin_statements", + "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to " + "the slow log if it is open.", + GLOBAL_VAR(opt_log_slow_admin_statements), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_mybool Sys_log_slow_slave_statements( + "log_slow_slave_statements", + "Log slow statements executed by slave thread to the slow log if it is open.", + GLOBAL_VAR(opt_log_slow_slave_statements), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + static Sys_var_ulong Sys_log_warnings( "log_warnings", "Log some not critical warnings to the general log file." @@ -1437,16 +1451,11 @@ static Sys_var_ulong Sys_metadata_locks_hash_instances( VALID_RANGE(1, 1024), DEFAULT(8), BLOCK_SIZE(1)); -/* - "pseudo_thread_id" variable used in the test suite to detect 32/64bit - systems. If you change it to something else then ulong then fix the tests - in mysql-test/include/have_32bit.inc and have_64bit.inc. -*/ -static Sys_var_ulong Sys_pseudo_thread_id( +static Sys_var_ulonglong Sys_pseudo_thread_id( "pseudo_thread_id", "This variable is for internal server use", SESSION_ONLY(pseudo_thread_id), - NO_CMD_LINE, VALID_RANGE(0, ULONG_MAX), DEFAULT(0), + NO_CMD_LINE, VALID_RANGE(0, ULONGLONG_MAX), DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_has_super)); @@ -1848,6 +1857,15 @@ static Sys_var_ulong Sys_slave_parallel_threads( NOT_IN_BINLOG, ON_CHECK(check_slave_parallel_threads), ON_UPDATE(fix_slave_parallel_threads)); +/* Alias for @@slave_parallel_threads to match what MySQL 5.7 uses. */ +static Sys_var_ulong Sys_slave_parallel_workers( + "slave_parallel_workers", + "Alias for slave_parallel_threads", + GLOBAL_VAR(opt_slave_parallel_threads), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0,16383), DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD, + NOT_IN_BINLOG, ON_CHECK(check_slave_parallel_threads), + ON_UPDATE(fix_slave_parallel_threads)); + static bool check_slave_domain_parallel_threads(sys_var *self, THD *thd, set_var *var) @@ -3189,9 +3207,9 @@ static Sys_var_ulong Sys_table_cache_size( static Sys_var_ulong Sys_thread_cache_size( "thread_cache_size", - "How many threads we should keep in a cache for reuse", + "How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time", GLOBAL_VAR(thread_cache_size), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(0, 16384), DEFAULT(0), BLOCK_SIZE(1)); + VALID_RANGE(0, 16384), DEFAULT(256), BLOCK_SIZE(1)); #ifdef HAVE_POOL_OF_THREADS static bool fix_tp_max_threads(sys_var *, THD *, enum_var_type) @@ -3516,7 +3534,8 @@ static bool fix_autocommit(sys_var *self, THD *thd, enum_var_type type) { thd->variables.option_bits&= ~OPTION_AUTOCOMMIT; thd->mdl_context.release_transactional_locks(); - WSREP_DEBUG("autocommit, MDL TRX lock released: %lu", thd->thread_id); + WSREP_DEBUG("autocommit, MDL TRX lock released: %lld", + (longlong) thd->thread_id); return true; } /* @@ -4474,6 +4493,28 @@ static bool update_slave_skip_counter(sys_var *self, THD *thd, Master_info *mi) mi->connection_name.str); return true; } + if (mi->using_gtid != Master_info::USE_GTID_NO && mi->using_parallel()) + { + ulong domain_count; + mysql_mutex_lock(&rpl_global_gtid_slave_state->LOCK_slave_state); + domain_count= rpl_global_gtid_slave_state->count(); + mysql_mutex_unlock(&rpl_global_gtid_slave_state->LOCK_slave_state); + if (domain_count > 1) + { + /* + With domain-based parallel replication, the slave position is + multi-dimensional, so the relay log position is not very meaningful. + It might not even correspond to the next GTID to execute in _any_ + domain (the case after error stop). So slave_skip_counter will most + likely not do what the user intends. Instead give an error, with a + suggestion to instead set @@gtid_slave_pos past the point of error; + this works reliably also in the case of multiple domains. + */ + my_error(ER_SLAVE_SKIP_NOT_IN_GTID, MYF(0)); + return true; + } + } + /* The value was stored temporarily in thd */ mi->rli.slave_skip_counter= thd->variables.slave_skip_counter; return false; @@ -5032,7 +5073,7 @@ static Sys_var_set Sys_log_slow_filter( "Log only certain types of queries", SESSION_VAR(log_slow_filter), CMD_LINE(REQUIRED_ARG), log_slow_filter_names, - DEFAULT(MAX_SET(array_elements(log_slow_filter_names)-1))); + DEFAULT(my_set_bits(array_elements(log_slow_filter_names)-1))); static const char *default_regex_flags_names[]= { diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic index 2badd5d997a..373f5834838 100644 --- a/sql/sys_vars.ic +++ b/sql/sys_vars.ic @@ -1094,9 +1094,6 @@ public: } }; -// overflow-safe (1 << X)-1 -#define MAX_SET(X) ((((1UL << ((X)-1))-1) << 1) | 1) - /** The class for flagset variables - a variant of SET that allows in-place editing (turning on/off individual bits). String representations looks like @@ -1131,7 +1128,7 @@ public: global_var(ulonglong)= def_val; SYSVAR_ASSERT(typelib.count > 1); SYSVAR_ASSERT(typelib.count <= 65); - SYSVAR_ASSERT(def_val < MAX_SET(typelib.count)); + SYSVAR_ASSERT(def_val < my_set_bits(typelib.count)); SYSVAR_ASSERT(strcmp(values[typelib.count-1], "default") == 0); SYSVAR_ASSERT(size == sizeof(ulonglong)); } @@ -1179,7 +1176,7 @@ public: { longlong tmp=var->value->val_int(); if ((tmp < 0 && ! var->value->unsigned_flag) - || (ulonglong)tmp > MAX_SET(typelib.count)) + || (ulonglong)tmp > my_set_bits(typelib.count)) return true; else var->save_result.ulonglong_value= tmp; @@ -1240,7 +1237,7 @@ public: global_var(ulonglong)= def_val; SYSVAR_ASSERT(typelib.count > 0); SYSVAR_ASSERT(typelib.count <= 64); - SYSVAR_ASSERT(def_val <= MAX_SET(typelib.count)); + SYSVAR_ASSERT(def_val <= my_set_bits(typelib.count)); SYSVAR_ASSERT(size == sizeof(ulonglong)); } bool do_check(THD *thd, set_var *var) @@ -1278,7 +1275,7 @@ public: { longlong tmp=var->value->val_int(); if ((tmp < 0 && ! var->value->unsigned_flag) - || (ulonglong)tmp > MAX_SET(typelib.count)) + || (ulonglong)tmp > my_set_bits(typelib.count)) return true; else var->save_result.ulonglong_value= tmp; diff --git a/sql/table.cc b/sql/table.cc index 2bcc10dec39..dc1730b5b6f 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -40,6 +40,7 @@ #include "discover.h" #include "mdl.h" // MDL_wait_for_graph_visitor #include "sql_view.h" +#include "rpl_filter.h" /* INFORMATION_SCHEMA name */ LEX_STRING INFORMATION_SCHEMA_NAME= {C_STRING_WITH_LEN("information_schema")}; @@ -62,6 +63,8 @@ LEX_STRING SLOW_LOG_NAME= {C_STRING_WITH_LEN("slow_log")}; */ LEX_STRING parse_vcol_keyword= { C_STRING_WITH_LEN("PARSE_VCOL_EXPR ") }; +static int64 last_table_id; + /* Functions defined in this file */ static void fix_type_pointers(const char ***array, TYPELIB *point_to_type, @@ -316,7 +319,8 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name, share->normalized_path.length= path_length; share->table_category= get_table_category(& share->db, & share->table_name); share->open_errno= ENOENT; - share->cached_row_logging_check= -1; + /* The following will be fixed in open_table_from_share */ + share->cached_row_logging_check= 1; init_sql_alloc(&share->stats_cb.mem_root, TABLE_ALLOC_BLOCK_SIZE, 0, MYF(0)); @@ -325,7 +329,16 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name, &share->LOCK_share, MY_MUTEX_INIT_SLOW); mysql_mutex_init(key_TABLE_SHARE_LOCK_ha_data, &share->LOCK_ha_data, MY_MUTEX_INIT_FAST); - tdc_assign_new_table_id(share); + + /* + There is one reserved number that cannot be used. Remember to + change this when 6-byte global table id's are introduced. + */ + do + { + share->table_map_id= my_atomic_add64_explicit(&last_table_id, 1, + MY_MEMORY_ORDER_RELAXED); + } while (unlikely(share->table_map_id == ~0UL)); } DBUG_RETURN(share); } @@ -381,7 +394,7 @@ void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key, share->path.length= share->normalized_path.length= strlen(path); share->frm_version= FRM_VER_TRUE_VARCHAR; - share->cached_row_logging_check= -1; + share->cached_row_logging_check= 0; // No row logging /* table_map_id is also used for MERGE tables to suppress repeated @@ -2974,6 +2987,9 @@ partititon_err: outparam->no_replicate= FALSE; } + if (outparam->no_replicate || !binlog_filter->db_ok(outparam->s->db.str)) + outparam->s->cached_row_logging_check= 0; // No row based replication + /* Increment the opened_tables counter, only when open flags set. */ if (db_stat) thd->status_var.opened_tables++; @@ -7265,7 +7281,9 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view) */ if (is_merged_derived()) { - if (is_view() || unit->prepared) + if (is_view() || + (unit->prepared && + !(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW))) create_field_translation(thd); } @@ -7407,6 +7425,11 @@ void TABLE_LIST::set_lock_type(THD *thd, enum thr_lock_type lock) } } +bool TABLE_LIST::is_with_table() +{ + return derived && derived->with_element; +} + uint TABLE_SHARE::actual_n_key_parts(THD *thd) { return use_ext_keys && diff --git a/sql/table.h b/sql/table.h index f646fc5ad50..aa7c11ba3d8 100644 --- a/sql/table.h +++ b/sql/table.h @@ -48,6 +48,7 @@ class ACL_internal_schema_access; class ACL_internal_table_access; class Field; class Table_statistics; +class With_element; class TDC_element; /* @@ -326,56 +327,6 @@ enum enum_vcol_update_mode VCOL_UPDATE_ALL }; -class Filesort_info -{ - /// Buffer for sorting keys. - Filesort_buffer filesort_buffer; - -public: - IO_CACHE *io_cache; /* If sorted through filesort */ - uchar *buffpek; /* Buffer for buffpek structures */ - uint buffpek_len; /* Max number of buffpeks in the buffer */ - uchar *addon_buf; /* Pointer to a buffer if sorted with fields */ - size_t addon_length; /* Length of the buffer */ - struct st_sort_addon_field *addon_field; /* Pointer to the fields info */ - void (*unpack)(struct st_sort_addon_field *, uchar *, uchar *); /* To unpack back */ - uchar *record_pointers; /* If sorted in memory */ - ha_rows found_records; /* How many records in sort */ - - Filesort_info(): record_pointers(0) {}; - /** Sort filesort_buffer */ - void sort_buffer(Sort_param *param, uint count) - { filesort_buffer.sort_buffer(param, count); } - - /** - Accessors for Filesort_buffer (which @c). - */ - uchar *get_record_buffer(uint idx) - { return filesort_buffer.get_record_buffer(idx); } - - uchar **get_sort_keys() - { return filesort_buffer.get_sort_keys(); } - - uchar **alloc_sort_buffer(uint num_records, uint record_length) - { return filesort_buffer.alloc_sort_buffer(num_records, record_length); } - - bool check_sort_buffer_properties(uint num_records, uint record_length) - { - return filesort_buffer.check_sort_buffer_properties(num_records, - record_length); - } - - void free_sort_buffer() - { filesort_buffer.free_sort_buffer(); } - - void init_record_pointers() - { filesort_buffer.init_record_pointers(); } - - size_t sort_buffer_size() const - { return filesort_buffer.sort_buffer_size(); } -}; - - class Field_blob; class Table_triggers_list; @@ -496,9 +447,6 @@ TABLE_CATEGORY get_table_category(const LEX_STRING *db, const LEX_STRING *name); -struct TABLE_share; -struct All_share_tables; - typedef struct st_table_field_type { LEX_STRING name; @@ -983,6 +931,57 @@ struct TABLE_SHARE }; +/** + Class is used as a BLOB field value storage for + intermediate GROUP_CONCAT results. Used only for + GROUP_CONCAT with DISTINCT or ORDER BY options. + */ + +class Blob_mem_storage: public Sql_alloc +{ +private: + MEM_ROOT storage; + /** + Sign that some values were cut + during saving into the storage. + */ + bool truncated_value; +public: + Blob_mem_storage() :truncated_value(false) + { + init_alloc_root(&storage, MAX_FIELD_VARCHARLENGTH, 0, MYF(0)); + } + ~ Blob_mem_storage() + { + free_root(&storage, MYF(0)); + } + void reset() + { + free_root(&storage, MYF(MY_MARK_BLOCKS_FREE)); + truncated_value= false; + } + /** + Fuction creates duplicate of 'from' + string in 'storage' MEM_ROOT. + + @param from string to copy + @param length string length + + @retval Pointer to the copied string. + @retval 0 if an error occured. + */ + char *store(const char *from, uint length) + { + return (char*) memdup_root(&storage, from, length); + } + void set_truncated_value(bool is_truncated_value) + { + truncated_value= is_truncated_value; + } + bool is_truncated_value() { return truncated_value; } +}; + + /* Information for one open table */ enum index_hint_type { @@ -1014,7 +1013,7 @@ private: One should use methods of I_P_List template instead. */ TABLE *share_all_next, **share_all_prev; - friend struct All_share_tables; + friend class TDC_element; public: @@ -1255,8 +1254,13 @@ public: REGINFO reginfo; /* field connections */ MEM_ROOT mem_root; + /** + Initialized in Item_func_group_concat::setup for appropriate + temporary table if GROUP_CONCAT is used with ORDER BY | DISTINCT + and BLOB field count > 0. + */ + Blob_mem_storage *blob_storage; GRANT_INFO grant; - Filesort_info sort; /* The arena which the items for expressions from the table definition are associated with. @@ -1433,19 +1437,6 @@ struct TABLE_share }; -struct All_share_tables -{ - static inline TABLE **next_ptr(TABLE *l) - { - return &l->share_all_next; - } - static inline TABLE ***prev_ptr(TABLE *l) - { - return &l->share_all_prev; - } -}; - - enum enum_schema_table_state { NOT_PROCESSED= 0, @@ -1864,6 +1855,7 @@ struct TABLE_LIST derived tables. Use TABLE_LIST::is_anonymous_derived_table(). */ st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */ + With_element *with; /* With element of with_table */ ST_SCHEMA_TABLE *schema_table; /* Information_schema table */ st_select_lex *schema_select_lex; /* @@ -2233,6 +2225,7 @@ struct TABLE_LIST { return (derived_type & DTYPE_TABLE); } + bool is_with_table(); inline void set_view() { derived_type= DTYPE_VIEW; @@ -2273,6 +2266,7 @@ struct TABLE_LIST { derived_type|= DTYPE_MULTITABLE; } + bool set_as_with_table(THD *thd, With_element *with_elem); void reset_const_table(); bool handle_derived(LEX *lex, uint phases); diff --git a/sql/table_cache.cc b/sql/table_cache.cc index 2dd368a1945..b6c1e32b350 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -67,7 +67,6 @@ I_P_List <TDC_element, I_P_List_fast_push_back<TDC_element> > unused_shares; static int64 tdc_version; /* Increments on each reload */ -static int64 last_table_id; static bool tdc_inited; static int32 tc_count; /**< Number of TABLE objects in table cache. */ @@ -599,13 +598,14 @@ void tdc_unlock_share(TDC_element *element) # Share for table */ -TABLE_SHARE *tdc_acquire_share(THD *thd, const char *db, const char *table_name, - const char *key, uint key_length, - my_hash_value_type hash_value, uint flags, +TABLE_SHARE *tdc_acquire_share(THD *thd, TABLE_LIST *tl, uint flags, TABLE **out_table) { TABLE_SHARE *share; TDC_element *element; + const char *key; + uint key_length= get_table_def_key(tl, &key); + my_hash_value_type hash_value= tl->mdl_request.key.tc_hash_value(); bool was_unused; DBUG_ENTER("tdc_acquire_share"); @@ -629,7 +629,7 @@ retry: lf_hash_search_unpin(thd->tdc_hash_pins); DBUG_ASSERT(element); - if (!(share= alloc_table_share(db, table_name, key, key_length))) + if (!(share= alloc_table_share(tl->db, tl->table_name, key, key_length))) { lf_hash_delete(&tdc_hash, thd->tdc_hash_pins, key, key_length); DBUG_RETURN(0); @@ -841,7 +841,7 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, const char *db, const char *table_name, bool kill_delayed_threads) { - I_P_List <TABLE, TABLE_share> purge_tables; + TDC_element::TABLE_list purge_tables; TABLE *table; TDC_element *element; uint my_refs= 1; @@ -1091,56 +1091,3 @@ int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument, } return res; } - - -/* - Function to assign a new table map id to a table share. - - PARAMETERS - - share - Pointer to table share structure - - DESCRIPTION - - We are intentionally not checking that share->mutex is locked - since this function should only be called when opening a table - share and before it is entered into the table definition cache - (meaning that it cannot be fetched by another thread, even - accidentally). - - PRE-CONDITION(S) - - share is non-NULL - last_table_id_lock initialized (tdc_inited) - - POST-CONDITION(S) - - share->table_map_id is given a value that with a high certainty is - not used by any other table (the only case where a table id can be - reused is on wrap-around, which means more than 4 billion table - share opens have been executed while one table was open all the - time). - - share->table_map_id is not ~0UL. -*/ - -void tdc_assign_new_table_id(TABLE_SHARE *share) -{ - ulong tid; - DBUG_ENTER("assign_new_table_id"); - DBUG_ASSERT(share); - DBUG_ASSERT(tdc_inited); - - /* - There is one reserved number that cannot be used. Remember to - change this when 6-byte global table id's are introduced. - */ - do - { - tid= my_atomic_add64_explicit(&last_table_id, 1, MY_MEMORY_ORDER_RELAXED); - } while (unlikely(tid == ~0UL)); - - share->table_map_id= tid; - DBUG_PRINT("info", ("table_id= %lu", share->table_map_id)); - DBUG_VOID_RETURN; -} diff --git a/sql/table_cache.h b/sql/table_cache.h index 2c5b0fc45a2..2efc535c425 100644 --- a/sql/table_cache.h +++ b/sql/table_cache.h @@ -31,7 +31,9 @@ public: TABLE_SHARE *share; typedef I_P_List <TABLE, TABLE_share> TABLE_list; - typedef I_P_List <TABLE, All_share_tables> All_share_tables_list; + typedef I_P_List <TABLE, I_P_List_adapter<TABLE, &TABLE::share_all_next, + &TABLE::share_all_prev> > + All_share_tables_list; /** Protects ref_count, m_flush_tickets, all_tables, free_tables, flushed, all_tables_refs. @@ -205,11 +207,8 @@ extern void tdc_purge(bool all); extern TDC_element *tdc_lock_share(THD *thd, const char *db, const char *table_name); extern void tdc_unlock_share(TDC_element *element); -extern TABLE_SHARE *tdc_acquire_share(THD *thd, const char *db, - const char *table_name, - const char *key, uint key_length, - my_hash_value_type hash_value, - uint flags, TABLE **out_table); +extern TABLE_SHARE *tdc_acquire_share(THD *thd, TABLE_LIST *tl, uint flags, + TABLE **out_table= 0); extern void tdc_release_share(TABLE_SHARE *share); extern bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type, const char *db, const char *table_name, @@ -220,7 +219,6 @@ extern int tdc_wait_for_old_version(THD *thd, const char *db, ulong refresh_version= ULONG_MAX); extern ulong tdc_refresh_version(void); extern ulong tdc_increment_refresh_version(void); -extern void tdc_assign_new_table_id(TABLE_SHARE *share); extern int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument, bool no_dups= false); @@ -249,50 +247,3 @@ inline uint tdc_create_key(char *key, const char *db, const char *table_name) return (uint) (strmake(strmake(key, db, NAME_LEN) + 1, table_name, NAME_LEN) - key + 1); } - -/** - Convenience helper: call tdc_acquire_share() without out_table. -*/ - -static inline TABLE_SHARE *tdc_acquire_share(THD *thd, const char *db, - const char *table_name, - const char *key, - uint key_length, uint flags) -{ - return tdc_acquire_share(thd, db, table_name, key, key_length, - my_hash_sort(&my_charset_bin, (uchar*) key, - key_length), flags, 0); -} - - -/** - Convenience helper: call tdc_acquire_share() without precomputed cache key. -*/ - -static inline TABLE_SHARE *tdc_acquire_share(THD *thd, const char *db, - const char *table_name, uint flags) -{ - char key[MAX_DBKEY_LENGTH]; - uint key_length; - key_length= tdc_create_key(key, db, table_name); - return tdc_acquire_share(thd, db, table_name, key, key_length, flags); -} - - -/** - Convenience helper: call tdc_acquire_share() reusing the MDL cache key. - - @note lifetime of the returned TABLE_SHARE is limited by the - lifetime of the TABLE_LIST object!!! -*/ - -uint get_table_def_key(const TABLE_LIST *table_list, const char **key); - -static inline TABLE_SHARE *tdc_acquire_share_shortlived(THD *thd, TABLE_LIST *tl, - uint flags) -{ - const char *key; - uint key_length= get_table_def_key(tl, &key); - return tdc_acquire_share(thd, tl->db, tl->table_name, key, key_length, - tl->mdl_request.key.tc_hash_value(), flags, 0); -} diff --git a/sql/threadpool.h b/sql/threadpool.h index 7b62d2cb70a..7ddc661565f 100644 --- a/sql/threadpool.h +++ b/sql/threadpool.h @@ -27,10 +27,9 @@ extern uint threadpool_oversubscribe; /* Maximum active threads in group */ /* Common thread pool routines, suitable for different implementations */ -extern void threadpool_cleanup_connection(THD *thd); extern void threadpool_remove_connection(THD *thd); extern int threadpool_process_request(THD *thd); -extern int threadpool_add_connection(THD *thd); +extern THD* threadpool_add_connection(CONNECT *connect, void *scheduled_data); /* Functions used by scheduler. @@ -38,7 +37,7 @@ extern int threadpool_add_connection(THD *thd); threadpool_unix.cc or threadpool_win.cc */ extern bool tp_init(); -extern void tp_add_connection(THD*); +extern void tp_add_connection(CONNECT *); extern void tp_wait_begin(THD *, int); extern void tp_wait_end(THD*); extern void tp_post_kill_notification(THD *thd); diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc index 9fb38319096..2cfa3473222 100644 --- a/sql/threadpool_common.cc +++ b/sql/threadpool_common.cc @@ -94,7 +94,7 @@ struct Worker_thread_context /* Attach/associate the connection with the OS thread, */ -static bool thread_attach(THD* thd) +static void thread_attach(THD* thd) { pthread_setspecific(THR_KEY_mysys,thd->mysys_var); thd->thread_stack=(char*)&thd; @@ -103,13 +103,14 @@ static bool thread_attach(THD* thd) if (PSI_server) PSI_server->set_thread(thd->event_scheduler.m_psi); #endif - return 0; } -int threadpool_add_connection(THD *thd) +THD* threadpool_add_connection(CONNECT *connect, void *scheduler_data) { - int retval=1; + THD *thd= NULL; + int error=1; + Worker_thread_context worker_context; worker_context.save(); @@ -120,13 +121,29 @@ int threadpool_add_connection(THD *thd) pthread_setspecific(THR_KEY_mysys, 0); my_thread_init(); - thd->mysys_var= (st_my_thread_var *)pthread_getspecific(THR_KEY_mysys); - if (!thd->mysys_var) + st_my_thread_var* mysys_var= (st_my_thread_var *)pthread_getspecific(THR_KEY_mysys); + if (!mysys_var ||!(thd= connect->create_thd())) { /* Out of memory? */ + connect->close_and_delete(); + if (mysys_var) + { +#ifdef HAVE_PSI_INTERFACE + /* + current PSI is still from worker thread. + Set to 0, to avoid premature cleanup by my_thread_end + */ + if (PSI_server) PSI_server->set_thread(0); +#endif + my_thread_end(); + } worker_context.restore(); - return 1; + return NULL; } + delete connect; + add_to_active_threads(thd); + thd->mysys_var= mysys_var; + thd->event_scheduler.data= scheduler_data; /* Create new PSI thread for use with the THD. */ #ifdef HAVE_PSI_INTERFACE @@ -157,28 +174,19 @@ int threadpool_add_connection(THD *thd) */ if (thd_is_connection_alive(thd)) { - retval= 0; + error= 0; thd->net.reading_or_writing= 1; thd->skip_wait_timeout= true; } } } + if (error) + { + threadpool_remove_connection(thd); + thd= NULL; + } worker_context.restore(); - return retval; -} - -/* - threadpool_cleanup_connection() does the bulk of connection shutdown work. - Usually called from threadpool_remove_connection(), but rarely it might - be called also in the main polling thread if connection initialization fails. -*/ -void threadpool_cleanup_connection(THD *thd) -{ - thd->net.reading_or_writing = 0; - end_connection(thd); - close_connection(thd, 0); - unlink_thd(thd); - mysql_cond_broadcast(&COND_thread_count); + return thd; } @@ -188,7 +196,12 @@ void threadpool_remove_connection(THD *thd) worker_context.save(); thread_attach(thd); - threadpool_cleanup_connection(thd); + thd->net.reading_or_writing = 0; + end_connection(thd); + close_connection(thd, 0); + unlink_thd(thd); + mysql_cond_broadcast(&COND_thread_count); + /* Free resources associated with this connection: mysys thread_var and PSI thread. @@ -221,7 +234,8 @@ int threadpool_process_request(THD *thd) /* - In the loop below, the flow is essentially the copy of thead-per-connections + In the loop below, the flow is essentially the copy of + thead-per-connections logic, see do_handle_one_connection() in sql_connect.c The goal is to execute a single query, thus the loop is normally executed @@ -260,18 +274,31 @@ end: } + +/* Dummy functions, do nothing */ + +static bool tp_init_new_connection_thread() +{ + return 0; +} + +static bool tp_end_thread(THD *, bool) +{ + return 0; +} + static scheduler_functions tp_scheduler_functions= { 0, // max_threads NULL, NULL, tp_init, // init - NULL, // init_new_connection_thread + tp_init_new_connection_thread, // init_new_connection_thread tp_add_connection, // add_connection tp_wait_begin, // thd_wait_begin tp_wait_end, // thd_wait_end post_kill_notification, // post_kill_notification - NULL, // end_thread + tp_end_thread, // Dummy function tp_end // end }; diff --git a/sql/threadpool_unix.cc b/sql/threadpool_unix.cc index 89a2036cb10..91b392eb766 100644 --- a/sql/threadpool_unix.cc +++ b/sql/threadpool_unix.cc @@ -116,6 +116,7 @@ struct connection_t connection_t *next_in_queue; connection_t **prev_in_queue; ulonglong abs_wait_timeout; + CONNECT* connect; bool logged_in; bool bound_to_poll_descriptor; bool waiting; @@ -809,7 +810,7 @@ static int create_worker(thread_group_t *thread_group) if (!err) { thread_group->last_thread_creation_time=microsecond_interval_timer(); - thread_created++; + statistic_increment(thread_created,&LOCK_status); add_thread_count(thread_group, 1); } else @@ -1203,18 +1204,19 @@ void wait_end(thread_group_t *thread_group) Allocate/initialize a new connection structure. */ -connection_t *alloc_connection(THD *thd) +connection_t *alloc_connection() { + connection_t* connection; DBUG_ENTER("alloc_connection"); + DBUG_EXECUTE_IF("simulate_failed_connection_1", DBUG_RETURN(0); ); - connection_t* connection = (connection_t *)my_malloc(sizeof(connection_t),0); - if (connection) + if ((connection = (connection_t *)my_malloc(sizeof(connection_t),0))) { - connection->thd = thd; connection->waiting= false; connection->logged_in= false; connection->bound_to_poll_descriptor= false; connection->abs_wait_timeout= ULONGLONG_MAX; + connection->thd= 0; } DBUG_RETURN(connection); } @@ -1225,38 +1227,34 @@ connection_t *alloc_connection(THD *thd) Add a new connection to thread pool.. */ -void tp_add_connection(THD *thd) +void tp_add_connection(CONNECT *connect) { + connection_t *connection; DBUG_ENTER("tp_add_connection"); - - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); - connection_t *connection= alloc_connection(thd); - if (connection) + + connection= alloc_connection(); + if (!connection) { - thd->event_scheduler.data= connection; - - /* Assign connection to a group. */ - thread_group_t *group= - &all_groups[thd->thread_id%group_count]; - - connection->thread_group=group; + connect->close_and_delete(); + DBUG_VOID_RETURN; + } + connection->connect= connect; + + /* Assign connection to a group. */ + thread_group_t *group= + &all_groups[connect->thread_id%group_count]; + + connection->thread_group=group; - mysql_mutex_lock(&group->mutex); - group->connection_count++; - mysql_mutex_unlock(&group->mutex); + mysql_mutex_lock(&group->mutex); + group->connection_count++; + mysql_mutex_unlock(&group->mutex); - /* - Add connection to the work queue.Actual logon - will be done by a worker thread. - */ - queue_put(group, connection); - } - else - { - /* Allocation failed */ - threadpool_cleanup_connection(thd); - } + /* + Add connection to the work queue.Actual logon + will be done by a worker thread. + */ + queue_put(group, connection); DBUG_VOID_RETURN; } @@ -1269,9 +1267,12 @@ static void connection_abort(connection_t *connection) { DBUG_ENTER("connection_abort"); thread_group_t *group= connection->thread_group; - - threadpool_remove_connection(connection->thd); - + + if (connection->thd) + { + threadpool_remove_connection(connection->thd); + } + mysql_mutex_lock(&group->mutex); group->connection_count--; mysql_mutex_unlock(&group->mutex); @@ -1440,7 +1441,8 @@ static void handle_event(connection_t *connection) if (!connection->logged_in) { - err= threadpool_add_connection(connection->thd); + connection->thd = threadpool_add_connection(connection->connect, connection); + err= (connection->thd == NULL); connection->logged_in= true; } else @@ -1548,7 +1550,6 @@ bool tp_init() DBUG_RETURN(0); } - void tp_end() { DBUG_ENTER("tp_end"); diff --git a/sql/threadpool_win.cc b/sql/threadpool_win.cc index 4be51f3d6e9..2ca815a6062 100644 --- a/sql/threadpool_win.cc +++ b/sql/threadpool_win.cc @@ -226,11 +226,12 @@ struct connection_t PTP_WAIT shm_read; /* Callback instance, used to inform treadpool about long callbacks */ PTP_CALLBACK_INSTANCE callback_instance; + CONNECT* connect; bool logged_in; }; -void init_connection(connection_t *connection) +void init_connection(connection_t *connection, CONNECT *connect) { connection->logged_in = false; connection->handle= 0; @@ -240,10 +241,11 @@ void init_connection(connection_t *connection) connection->logged_in = false; connection->timeout= ULONGLONG_MAX; connection->callback_instance= 0; + connection->thd= 0; memset(&connection->overlapped, 0, sizeof(OVERLAPPED)); InitializeThreadpoolEnvironment(&connection->callback_environ); SetThreadpoolCallbackPool(&connection->callback_environ, pool); - connection->thd = 0; + connection->connect= connect; } @@ -388,7 +390,7 @@ int start_io(connection_t *connection, PTP_CALLBACK_INSTANCE instance) return 0; } - /* Some error occured */ + /* Some error occurred */ CancelThreadpoolIo(io); return -1; } @@ -396,8 +398,8 @@ int start_io(connection_t *connection, PTP_CALLBACK_INSTANCE instance) int login(connection_t *connection, PTP_CALLBACK_INSTANCE instance) { - if (threadpool_add_connection(connection->thd) == 0 - && init_io(connection, connection->thd) == 0 + if ((connection->thd= threadpool_add_connection(connection->connect, connection)) + && init_io(connection, connection->thd) == 0 && start_io(connection, instance) == 0) { return 0; @@ -465,7 +467,7 @@ static void check_thread_init() if (FlsGetValue(fls) == NULL) { FlsSetValue(fls, (void *)1); - thread_created++; + statistic_increment(thread_created, &LOCK_status); InterlockedIncrement((volatile long *)&tp_stats.num_worker_threads); } } @@ -544,7 +546,6 @@ void tp_end(void) } } - /* Handle read completion/notification. */ @@ -575,7 +576,7 @@ static VOID CALLBACK io_completion_callback(PTP_CALLBACK_INSTANCE instance, return; error: - /* Some error has occured. */ + /* Some error has occurred. */ destroy_connection(connection, instance); free(connection); @@ -656,24 +657,21 @@ static void CALLBACK shm_read_callback(PTP_CALLBACK_INSTANCE instance, /* Notify the thread pool about a new connection. - NOTE: LOCK_thread_count is locked on entry. This function must unlock it. */ -void tp_add_connection(THD *thd) -{ - threads.append(thd); - mysql_mutex_unlock(&LOCK_thread_count); - connection_t *con = (connection_t *)malloc(sizeof(connection_t)); - if(!con) +void tp_add_connection(CONNECT *connect) +{ + connection_t *con; + con= (connection_t *)malloc(sizeof(connection_t)); + DBUG_EXECUTE_IF("simulate_failed_connection_1", free(con);con= 0; ); + if (!con) { tp_log_warning("Allocation failed", "tp_add_connection"); - threadpool_cleanup_connection(thd); + connect->close_and_delete(); return; } - init_connection(con); - con->thd= thd; - thd->event_scheduler.data= con; + init_connection(con, connect); /* Try to login asynchronously, using threads in the pool */ PTP_WORK wrk = CreateThreadpoolWork(login_callback,con, &con->callback_environ); @@ -685,7 +683,7 @@ void tp_add_connection(THD *thd) else { /* Likely memory pressure */ - threadpool_cleanup_connection(thd); + connect->close_and_delete(); } } diff --git a/sql/tztime.cc b/sql/tztime.cc index f94e10c4877..ce0272d996d 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -309,7 +309,7 @@ tz_load(const char *name, TIME_ZONE_INFO *sp, MEM_ROOT *storage) Note: See description of TIME_to_gmt_sec() function first. In order to perform MYSQL_TIME -> my_time_t conversion we need to build table which defines "shifted by tz offset and leap seconds my_time_t" -> - my_time_t function wich is almost the same (except ranges of ambiguity) + my_time_t function which is almost the same (except ranges of ambiguity) as reverse function to piecewise linear function used for my_time_t -> "shifted my_time_t" conversion and which is also specified as table in zoneinfo file or in our db (It is specified as start of time type ranges @@ -612,7 +612,7 @@ sec_to_TIME(MYSQL_TIME * tmp, my_time_t t, long offset) /* - Find time range wich contains given my_time_t value + Find time range which contains given my_time_t value SYNOPSIS find_time_range() @@ -708,7 +708,7 @@ find_transition_type(my_time_t t, const TIME_ZONE_INFO *sp) TODO We can improve this function by creating joined array of transitions and leap corrections. This will require adding extra field to TRAN_TYPE_INFO - for storing number of "extra" seconds to minute occured due to correction + for storing number of "extra" seconds to minute occurred due to correction (60th and 61st second, look how we calculate them as "hit" in this function). Under realistic assumptions about frequency of transitions the same array @@ -2769,7 +2769,7 @@ main(int argc, char **argv) #ifdef TESTTIME /* - Some simple brute-force test wich allowed to catch a pair of bugs. + Some simple brute-force test which allowed to catch a pair of bugs. Also can provide interesting facts about system's time zone support implementation. */ diff --git a/sql/uniques.cc b/sql/uniques.cc index 63eb6e0eb90..f2fa0bf7b1a 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -37,7 +37,9 @@ #include "sql_sort.h" #include "queues.h" // QUEUE #include "my_tree.h" // element_count -#include "sql_class.h" // Unique +#include "uniques.h" // Unique +#include "sql_sort.h" +#include "myisamchk.h" // BUFFPEK int unique_write_to_file(uchar* key, element_count count, Unique *unique) { @@ -58,8 +60,8 @@ int unique_write_to_file_with_count(uchar* key, element_count count, Unique *uni int unique_write_to_ptrs(uchar* key, element_count count, Unique *unique) { - memcpy(unique->record_pointers, key, unique->size); - unique->record_pointers+=unique->size; + memcpy(unique->sort.record_pointers, key, unique->size); + unique->sort.record_pointers+=unique->size; return 0; } @@ -67,8 +69,8 @@ int unique_intersect_write_to_ptrs(uchar* key, element_count count, Unique *uniq { if (count >= unique->min_dupl_count) { - memcpy(unique->record_pointers, key, unique->size); - unique->record_pointers+=unique->size; + memcpy(unique->sort.record_pointers, key, unique->size); + unique->sort.record_pointers+=unique->size; } else unique->filtered_out_elems++; @@ -80,16 +82,15 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg, uint size_arg, ulonglong max_in_memory_size_arg, uint min_dupl_count_arg) :max_in_memory_size(max_in_memory_size_arg), - record_pointers(NULL), size(size_arg), elements(0) { + my_b_clear(&file); min_dupl_count= min_dupl_count_arg; full_size= size; if (min_dupl_count_arg) full_size+= sizeof(element_count); with_counters= MY_TEST(min_dupl_count_arg); - my_b_clear(&file); init_tree(&tree, (ulong) (max_in_memory_size / 16), 0, size, comp_func, NULL, comp_func_fixed_arg, MYF(MY_THREAD_SPECIFIC)); /* If the following fail's the next add will also fail */ @@ -408,8 +409,10 @@ Unique::reset() reset_dynamic(&file_ptrs); reinit_io_cache(&file, WRITE_CACHE, 0L, 0, 1); } + my_free(sort.record_pointers); elements= 0; tree.flag= 0; + sort.record_pointers= 0; } /* @@ -636,7 +639,7 @@ bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg) if (elements == 0) /* the whole tree is in memory */ return tree_walk(&tree, action, walk_action_arg, left_root_right); - table->sort.found_records=elements+tree.elements_in_tree; + sort.return_rows= elements+tree.elements_in_tree; /* flush current tree to the file to have some memory for merge buffer */ if (flush()) return 1; @@ -663,9 +666,11 @@ bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg) /* DESCRIPTION - Perform multi-pass sort merge of the elements accessed through table->sort, - using the buffer buff as the merge buffer. The last pass is not performed - if without_last_merge is TRUE. + + Perform multi-pass sort merge of the elements using the buffer buff as + the merge buffer. The last pass is not performed if without_last_merge is + TRUE. + SYNOPSIS Unique:merge() All params are 'IN': @@ -679,23 +684,19 @@ bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg) bool Unique::merge(TABLE *table, uchar *buff, bool without_last_merge) { - IO_CACHE *outfile= table->sort.io_cache; + IO_CACHE *outfile= &sort.io_cache; BUFFPEK *file_ptr= (BUFFPEK*) file_ptrs.buffer; uint maxbuffer= file_ptrs.elements - 1; my_off_t save_pos; bool error= 1; + Sort_param sort_param; - /* Open cached file if it isn't open */ - if (!outfile) - outfile= table->sort.io_cache= (IO_CACHE*) my_malloc(sizeof(IO_CACHE), - MYF(MY_THREAD_SPECIFIC|MY_ZEROFILL)); - if (!outfile || - (! my_b_inited(outfile) && - open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER, - MYF(MY_WME)))) + /* Open cached file for table records if it isn't open */ + if (! my_b_inited(outfile) && + open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER, + MYF(MY_WME))) return 1; - Sort_param sort_param; bzero((char*) &sort_param,sizeof(sort_param)); sort_param.max_rows= elements; sort_param.sort_form= table; @@ -744,44 +745,49 @@ err: /* - Modify the TABLE element so that when one calls init_records() - the rows will be read in priority order. + Allocate memory that can be used with init_records() so that + rows will be read in priority order. */ bool Unique::get(TABLE *table) { bool rc= 1; uchar *sort_buffer= NULL; - table->sort.found_records= elements+tree.elements_in_tree; + sort.return_rows= elements+tree.elements_in_tree; + DBUG_ENTER("Unique::get"); if (my_b_tell(&file) == 0) { /* Whole tree is in memory; Don't use disk if you don't need to */ - if ((record_pointers=table->sort.record_pointers= (uchar*) + if ((sort.record_pointers= (uchar*) my_malloc(size * tree.elements_in_tree, MYF(MY_THREAD_SPECIFIC)))) { + uchar *save_record_pointers= sort.record_pointers; tree_walk_action action= min_dupl_count ? (tree_walk_action) unique_intersect_write_to_ptrs : (tree_walk_action) unique_write_to_ptrs; filtered_out_elems= 0; (void) tree_walk(&tree, action, this, left_root_right); - table->sort.found_records-= filtered_out_elems; - return 0; + /* Restore record_pointers that was changed in by 'action' above */ + sort.record_pointers= save_record_pointers; + sort.return_rows-= filtered_out_elems; + DBUG_RETURN(0); } } /* Not enough memory; Save the result to file && free memory used by tree */ if (flush()) - return 1; + DBUG_RETURN(1); size_t buff_sz= (max_in_memory_size / full_size + 1) * full_size; - if (!(sort_buffer= (uchar*) my_malloc(buff_sz, MYF(MY_THREAD_SPECIFIC|MY_WME)))) - return 1; + if (!(sort_buffer= (uchar*) my_malloc(buff_sz, + MYF(MY_THREAD_SPECIFIC|MY_WME)))) + DBUG_RETURN(1); if (merge(table, sort_buffer, FALSE)) - goto err; + goto err; rc= 0; err: my_free(sort_buffer); - return rc; + DBUG_RETURN(rc); } diff --git a/sql/uniques.h b/sql/uniques.h new file mode 100644 index 00000000000..0210e879788 --- /dev/null +++ b/sql/uniques.h @@ -0,0 +1,100 @@ +/* Copyright (c) 2016 MariaDB corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef UNIQUE_INCLUDED +#define UNIQUE_INCLUDED + +#include "filesort.h" + +/* + Unique -- class for unique (removing of duplicates). + Puts all values to the TREE. If the tree becomes too big, + it's dumped to the file. User can request sorted values, or + just iterate through them. In the last case tree merging is performed in + memory simultaneously with iteration, so it should be ~2-3x faster. + */ + +class Unique :public Sql_alloc +{ + DYNAMIC_ARRAY file_ptrs; + ulong max_elements; + ulonglong max_in_memory_size; + IO_CACHE file; + TREE tree; + ulong filtered_out_elems; + uint size; + uint full_size; + uint min_dupl_count; /* always 0 for unions, > 0 for intersections */ + bool with_counters; + + bool merge(TABLE *table, uchar *buff, bool without_last_merge); + bool flush(); + +public: + ulong elements; + SORT_INFO sort; + Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg, + uint size_arg, ulonglong max_in_memory_size_arg, + uint min_dupl_count_arg= 0); + ~Unique(); + ulong elements_in_tree() { return tree.elements_in_tree; } + inline bool unique_add(void *ptr) + { + DBUG_ENTER("unique_add"); + DBUG_PRINT("info", ("tree %u - %lu", tree.elements_in_tree, max_elements)); + if (!(tree.flag & TREE_ONLY_DUPS) && + tree.elements_in_tree >= max_elements && flush()) + DBUG_RETURN(1); + DBUG_RETURN(!tree_insert(&tree, ptr, 0, tree.custom_arg)); + } + + bool is_in_memory() { return (my_b_tell(&file) == 0); } + void close_for_expansion() { tree.flag= TREE_ONLY_DUPS; } + + bool get(TABLE *table); + + /* Cost of searching for an element in the tree */ + inline static double get_search_cost(ulonglong tree_elems, uint compare_factor) + { + return log((double) tree_elems) / (compare_factor * M_LN2); + } + + static double get_use_cost(uint *buffer, size_t nkeys, uint key_size, + ulonglong max_in_memory_size, uint compare_factor, + bool intersect_fl, bool *in_memory); + inline static int get_cost_calc_buff_size(size_t nkeys, uint key_size, + ulonglong max_in_memory_size) + { + register ulonglong max_elems_in_tree= + max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size); + return (int) (sizeof(uint)*(1 + nkeys/max_elems_in_tree)); + } + + void reset(); + bool walk(TABLE *table, tree_walk_action action, void *walk_action_arg); + + uint get_size() const { return size; } + ulonglong get_max_in_memory_size() const { return max_in_memory_size; } + + friend int unique_write_to_file(uchar* key, element_count count, Unique *unique); + friend int unique_write_to_ptrs(uchar* key, element_count count, Unique *unique); + + friend int unique_write_to_file_with_count(uchar* key, element_count count, + Unique *unique); + friend int unique_intersect_write_to_ptrs(uchar* key, element_count count, + Unique *unique); +}; + +#endif /* UNIQUE_INCLUDED */ diff --git a/sql/wsrep_applier.cc b/sql/wsrep_applier.cc index c1c6a90e614..cf1feb49f41 100644 --- a/sql/wsrep_applier.cc +++ b/sql/wsrep_applier.cc @@ -19,6 +19,7 @@ #include "log_event.h" // class THD, EVENT_LEN_OFFSET, etc. #include "wsrep_applier.h" +#include "debug_sync.h" /* read the first event from (*buf). The size of the (*buf) is (*buf_len). @@ -220,6 +221,16 @@ wsrep_cb_status_t wsrep_apply_cb(void* const ctx, { THD* const thd((THD*)ctx); + // Allow tests to block the applier thread using the DBUG facilities. + DBUG_EXECUTE_IF("sync.wsrep_apply_cb", + { + const char act[]= + "now " + "wait_for signal.wsrep_apply_cb"; + DBUG_ASSERT(!debug_sync_set_action(thd, + STRING_WITH_LEN(act))); + };); + thd->wsrep_trx_meta = *meta; #ifdef WSREP_PROC_INFO @@ -269,8 +280,8 @@ wsrep_cb_status_t wsrep_apply_cb(void* const ctx, TABLE *tmp; while ((tmp = thd->temporary_tables)) { - WSREP_DEBUG("Applier %lu, has temporary tables: %s.%s", - thd->thread_id, + WSREP_DEBUG("Applier %lld, has temporary tables: %s.%s", + (longlong) thd->thread_id, (tmp->s) ? tmp->s->db.str : "void", (tmp->s) ? tmp->s->table_name.str : "void"); close_temporary_table(thd, tmp, 1, 1); @@ -279,8 +290,7 @@ wsrep_cb_status_t wsrep_apply_cb(void* const ctx, return rcode; } -static wsrep_cb_status_t wsrep_commit(THD* const thd, - wsrep_seqno_t const global_seqno) +static wsrep_cb_status_t wsrep_commit(THD* const thd) { #ifdef WSREP_PROC_INFO snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, @@ -299,7 +309,11 @@ static wsrep_cb_status_t wsrep_commit(THD* const thd, #ifdef GTID_SUPPORT thd->variables.gtid_next.set_automatic(); #endif /* GTID_SUPPORT */ - // TODO: mark snapshot with global_seqno. + if (thd->wsrep_apply_toi) + { + wsrep_set_SE_checkpoint(thd->wsrep_trx_meta.gtid.uuid, + thd->wsrep_trx_meta.gtid.seqno); + } } #ifdef WSREP_PROC_INFO @@ -313,8 +327,7 @@ static wsrep_cb_status_t wsrep_commit(THD* const thd, return rcode; } -static wsrep_cb_status_t wsrep_rollback(THD* const thd, - wsrep_seqno_t const global_seqno) +static wsrep_cb_status_t wsrep_rollback(THD* const thd) { #ifdef WSREP_PROC_INFO snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, @@ -351,9 +364,9 @@ wsrep_cb_status_t wsrep_commit_cb(void* const ctx, wsrep_cb_status_t rcode; if (commit) - rcode = wsrep_commit(thd, meta->gtid.seqno); + rcode = wsrep_commit(thd); else - rcode = wsrep_rollback(thd, meta->gtid.seqno); + rcode = wsrep_rollback(thd); wsrep_set_apply_format(thd, NULL); thd->mdl_context.release_transactional_locks(); diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc index 36917674128..7884df586a1 100644 --- a/sql/wsrep_binlog.cc +++ b/sql/wsrep_binlog.cc @@ -319,9 +319,9 @@ int wsrep_write_cache(wsrep_t* const wsrep, void wsrep_dump_rbr_buf(THD *thd, const void* rbr_buf, size_t buf_len) { char filename[PATH_MAX]= {0}; - int len= snprintf(filename, PATH_MAX, "%s/GRA_%ld_%lld.log", - wsrep_data_home_dir, thd->thread_id, - (long long)wsrep_thd_trx_seqno(thd)); + int len= snprintf(filename, PATH_MAX, "%s/GRA_%lld_%lld.log", + wsrep_data_home_dir, (longlong) thd->thread_id, + (longlong) wsrep_thd_trx_seqno(thd)); if (len >= PATH_MAX) { WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len); @@ -374,9 +374,9 @@ int wsrep_binlog_savepoint_rollback(THD *thd, void *sv) void wsrep_dump_rbr_direct(THD* thd, IO_CACHE* cache) { char filename[PATH_MAX]= {0}; - int len= snprintf(filename, PATH_MAX, "%s/GRA_%ld_%lld.log", - wsrep_data_home_dir, thd->thread_id, - (long long)wsrep_thd_trx_seqno(thd)); + int len= snprintf(filename, PATH_MAX, "%s/GRA_%lld_%lld.log", + wsrep_data_home_dir, (longlong) thd->thread_id, + (longlong) wsrep_thd_trx_seqno(thd)); size_t bytes_in_cache = 0; // check path if (len >= PATH_MAX) @@ -448,8 +448,8 @@ void wsrep_dump_rbr_buf_with_header(THD *thd, const void *rbr_buf, Log_event_writer writer(&cache); Format_description_log_event *ev= wsrep_get_apply_format(thd); - int len= my_snprintf(filename, PATH_MAX, "%s/GRA_%ld_%lld_v2.log", - wsrep_data_home_dir, thd->thread_id, + int len= my_snprintf(filename, PATH_MAX, "%s/GRA_%lld_%lld_v2.log", + wsrep_data_home_dir, (longlong) thd->thread_id, (long long) wsrep_thd_trx_seqno(thd)); if (len >= PATH_MAX) diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc index 603cd8ec5ea..0aa7f9b0aad 100644 --- a/sql/wsrep_dummy.cc +++ b/sql/wsrep_dummy.cc @@ -116,7 +116,7 @@ int wsrep_thd_retry_counter(THD *) void wsrep_thd_set_conflict_state(THD *, enum wsrep_conflict_state) { } -bool wsrep_thd_skip_append_keys(THD *) +bool wsrep_thd_ignore_table(THD *) { return 0; } longlong wsrep_thd_trx_seqno(THD *) diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 5bec467708c..fa34a5bbc55 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -22,6 +22,7 @@ #include "wsrep_xid.h" #include <cstdio> #include <cstdlib> +#include "debug_sync.h" extern ulonglong thd_to_trx_id(THD *thd); @@ -67,6 +68,17 @@ void wsrep_register_hton(THD* thd, bool all) if (WSREP(thd) && thd->wsrep_exec_mode != TOTAL_ORDER && !thd->wsrep_apply_toi) { + if (thd->wsrep_exec_mode == LOCAL_STATE && + (thd_sql_command(thd) == SQLCOM_OPTIMIZE || + thd_sql_command(thd) == SQLCOM_ANALYZE || + thd_sql_command(thd) == SQLCOM_REPAIR) && + thd->lex->no_write_to_binlog == 1) + { + WSREP_DEBUG("Skipping wsrep_register_hton for LOCAL sql admin command : %s", + thd->query()); + return; + } + THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; for (Ha_trx_info *i= trans->ha_list; i; i = i->next()) { @@ -317,6 +329,8 @@ wsrep_run_wsrep_commit(THD *thd, bool all) thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message()); } + DEBUG_SYNC(thd, "wsrep_before_replication"); + if (thd->slave_thread && !opt_log_slave_updates) DBUG_RETURN(WSREP_TRX_OK); if (thd->wsrep_exec_mode == REPL_RECV) { @@ -383,9 +397,9 @@ wsrep_run_wsrep_commit(THD *thd, bool all) &wtime); if (replay_round++ % 100000 == 0) - WSREP_DEBUG("commit waiting for replaying: replayers %d, thd: (%lu) " + WSREP_DEBUG("commit waiting for replaying: replayers %d, thd: %lld " "conflict: %d (round: %d)", - wsrep_replaying, thd->thread_id, + wsrep_replaying, (longlong) thd->thread_id, thd->wsrep_conflict_state, replay_round); mysql_mutex_unlock(&LOCK_wsrep_replaying); @@ -449,11 +463,11 @@ wsrep_run_wsrep_commit(THD *thd, bool all) if (WSREP_UNDEFINED_TRX_ID == thd->wsrep_ws_handle.trx_id) { - WSREP_WARN("SQL statement was ineffective, THD: %lu, buf: %zu\n" + WSREP_WARN("SQL statement was ineffective thd: %lld buf: %zu\n" "schema: %s \n" "QUERY: %s\n" " => Skipping replication", - thd->thread_id, data_len, + (longlong) thd->thread_id, data_len, (thd->db ? thd->db : "(null)"), thd->query()); rcode = WSREP_TRX_FAIL; } @@ -469,20 +483,22 @@ wsrep_run_wsrep_commit(THD *thd, bool all) &thd->wsrep_trx_meta); if (rcode == WSREP_TRX_MISSING) { - WSREP_WARN("Transaction missing in provider, thd: %ld, schema: %s, SQL: %s", - thd->thread_id, (thd->db ? thd->db : "(null)"), thd->query()); + WSREP_WARN("Transaction missing in provider, thd: %lld schema: %s SQL: %s", + (longlong) thd->thread_id, + (thd->db ? thd->db : "(null)"), thd->query()); rcode = WSREP_TRX_FAIL; } else if (rcode == WSREP_BF_ABORT) { - WSREP_DEBUG("thd %lu seqno %lld BF aborted by provider, will replay", - thd->thread_id, (long long)thd->wsrep_trx_meta.gtid.seqno); + WSREP_DEBUG("thd: %lld seqno: %lld BF aborted by provider, will replay", + (longlong) thd->thread_id, + (longlong) thd->wsrep_trx_meta.gtid.seqno); mysql_mutex_lock(&thd->LOCK_wsrep_thd); thd->wsrep_conflict_state = MUST_REPLAY; DBUG_ASSERT(wsrep_thd_trx_seqno(thd) > 0); mysql_mutex_unlock(&thd->LOCK_wsrep_thd); mysql_mutex_lock(&LOCK_wsrep_replaying); wsrep_replaying++; - WSREP_DEBUG("replaying increased: %d, thd: %lu", - wsrep_replaying, thd->thread_id); + WSREP_DEBUG("replaying increased: %d, thd: %lld", + wsrep_replaying, (longlong) thd->thread_id); mysql_mutex_unlock(&LOCK_wsrep_replaying); } } else { @@ -506,9 +522,9 @@ wsrep_run_wsrep_commit(THD *thd, bool all) if (thd->wsrep_conflict_state != NO_CONFLICT) { - WSREP_WARN("thd %lu seqno %lld: conflict state %d after post commit", - thd->thread_id, - (long long)thd->wsrep_trx_meta.gtid.seqno, + WSREP_WARN("thd: %llu seqno: %lld conflict state %d after post commit", + (longlong) thd->thread_id, + (longlong) thd->wsrep_trx_meta.gtid.seqno, thd->wsrep_conflict_state); } thd->wsrep_exec_mode= LOCAL_COMMIT; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index b922d2b2857..f84ebe4dbb9 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -91,12 +91,6 @@ my_bool wsrep_slave_UK_checks = 0; // slave thread does UK checks my_bool wsrep_slave_FK_checks = 0; // slave thread does FK checks bool wsrep_new_cluster = false; // Bootstrap the cluster ? -/* - Set during the creation of first wsrep applier and rollback threads. - Since these threads are critical, abort if the thread creation fails. -*/ -my_bool wsrep_creating_startup_threads = 0; - // Use wsrep_gtid_domain_id for galera transactions? bool wsrep_gtid_mode = 0; // gtid_domain_id for galera transactions. @@ -798,7 +792,6 @@ void wsrep_init_startup (bool first) if (!wsrep_start_replication()) unireg_abort(1); - wsrep_creating_startup_threads= 1; wsrep_create_rollbacker(); wsrep_create_appliers(1); @@ -947,19 +940,24 @@ bool wsrep_start_replication() return true; } +bool wsrep_must_sync_wait (THD* thd, uint mask) +{ + return (thd->variables.wsrep_sync_wait & mask) && + thd->variables.wsrep_on && + !thd->in_active_multi_stmt_transaction() && + thd->wsrep_conflict_state != REPLAYING && + thd->wsrep_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED; +} + bool wsrep_sync_wait (THD* thd, uint mask) { - if ((thd->variables.wsrep_sync_wait & mask) && - thd->variables.wsrep_on && - !thd->in_active_multi_stmt_transaction() && - thd->wsrep_conflict_state != REPLAYING) + if (wsrep_must_sync_wait(thd, mask)) { WSREP_DEBUG("wsrep_sync_wait: thd->variables.wsrep_sync_wait = %u, mask = %u", thd->variables.wsrep_sync_wait, mask); // This allows autocommit SELECTs and a first SELECT after SET AUTOCOMMIT=0 // TODO: modify to check if thd has locked any rows. - wsrep_gtid_t gtid; - wsrep_status_t ret= wsrep->causal_read (wsrep, >id); + wsrep_status_t ret= wsrep->causal_read (wsrep, &thd->wsrep_sync_wait_gtid); if (unlikely(WSREP_OK != ret)) { @@ -1467,16 +1465,19 @@ static int wsrep_RSU_begin(THD *thd, char *db_, char *table_) WSREP_DEBUG("RSU BEGIN: %lld, %d : %s", (long long)wsrep_thd_trx_seqno(thd), thd->wsrep_exec_mode, thd->query() ); - ret = wsrep->desync(wsrep); - if (ret != WSREP_OK) + if (!wsrep_desync) { - WSREP_WARN("RSU desync failed %d for schema: %s, query: %s", - ret, - (thd->db ? thd->db : "(null)"), - thd->query()); - my_error(ER_LOCK_DEADLOCK, MYF(0)); - return(ret); + ret = wsrep->desync(wsrep); + if (ret != WSREP_OK) + { + WSREP_WARN("RSU desync failed %d for schema: %s, query: %s", + ret, (thd->db ? thd->db : "(null)"), thd->query()); + my_error(ER_LOCK_DEADLOCK, MYF(0)); + return(ret); + } } + else + WSREP_DEBUG("RSU desync skipped: %d", wsrep_desync); mysql_mutex_lock(&LOCK_wsrep_replaying); wsrep_replaying++; mysql_mutex_unlock(&LOCK_wsrep_replaying); @@ -1491,13 +1492,14 @@ static int wsrep_RSU_begin(THD *thd, char *db_, char *table_) wsrep_replaying--; mysql_mutex_unlock(&LOCK_wsrep_replaying); - ret = wsrep->resync(wsrep); - if (ret != WSREP_OK) + if (!wsrep_desync) { - WSREP_WARN("resync failed %d for schema: %s, query: %s", - ret, - (thd->db ? thd->db : "(null)"), - thd->query()); + ret = wsrep->resync(wsrep); + if (ret != WSREP_OK) + { + WSREP_WARN("resync failed %d for schema: %s, query: %s", + ret, (thd->db ? thd->db : "(null)"), thd->query()); + } } my_error(ER_LOCK_DEADLOCK, MYF(0)); return(1); @@ -1534,14 +1536,18 @@ static void wsrep_RSU_end(THD *thd) (thd->db ? thd->db : "(null)"), thd->query()); } - ret = wsrep->resync(wsrep); - if (ret != WSREP_OK) + if (!wsrep_desync) { - WSREP_WARN("resync failed %d for schema: %s, query: %s", ret, - (thd->db ? thd->db : "(null)"), - thd->query()); - return; + ret = wsrep->resync(wsrep); + if (ret != WSREP_OK) + { + WSREP_WARN("resync failed %d for schema: %s, query: %s", ret, + (thd->db ? thd->db : "(null)"), thd->query()); + return; + } } + else + WSREP_DEBUG("RSU resync skipped: %d", wsrep_desync); thd->variables.wsrep_on = 1; } @@ -1560,8 +1566,8 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, if (thd->wsrep_conflict_state == MUST_ABORT) { - WSREP_INFO("thread: %lu, schema: %s, query: %s has been aborted due to multi-master conflict", - thd->thread_id, + WSREP_INFO("thread: %lld schema: %s query: %s has been aborted due to multi-master conflict", + (longlong) thd->thread_id, (thd->db ? thd->db : "(null)"), thd->query()); mysql_mutex_unlock(&thd->LOCK_wsrep_thd); @@ -1574,15 +1580,15 @@ int wsrep_to_isolation_begin(THD *thd, char *db_, char *table_, if (thd->global_read_lock.can_acquire_protection()) { - WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %lu", - thd->query(), thd->thread_id); + WSREP_DEBUG("Aborting TOI: Global Read-Lock (FTWRL) in place: %s %lld", + thd->query(), (longlong) thd->thread_id); return -1; } if (wsrep_debug && thd->mdl_context.has_locks()) { - WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lu", - thd->query(), thd->thread_id); + WSREP_DEBUG("thread holds MDL locks at TI begin: %s %lld", + thd->query(), (longlong) thd->thread_id); } /* @@ -1645,13 +1651,13 @@ void wsrep_to_isolation_end(THD *thd) WSREP_##severity( \ "%s\n" \ "schema: %.*s\n" \ - "request: (%lu \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)\n" \ - "granted: (%lu \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)", \ + "request: (%lld \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)\n" \ + "granted: (%lld \tseqno %lld \twsrep (%d, %d, %d) cmd %d %d \t%s)", \ msg, schema_len, schema, \ - req->thread_id, (long long)wsrep_thd_trx_seqno(req), \ + (longlong) req->thread_id, (long long)wsrep_thd_trx_seqno(req), \ req->wsrep_exec_mode, req->wsrep_query_state, req->wsrep_conflict_state, \ req->get_command(), req->lex->sql_command, req->query(), \ - gra->thread_id, (long long)wsrep_thd_trx_seqno(gra), \ + (longlong) gra->thread_id, (long long)wsrep_thd_trx_seqno(gra), \ gra->wsrep_exec_mode, gra->wsrep_query_state, gra->wsrep_conflict_state, \ gra->get_command(), gra->lex->sql_command, gra->query()); @@ -1751,8 +1757,9 @@ pthread_handler_t start_wsrep_THD(void *arg) goto error; } + thd->thread_id= next_thread_id(); + mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id=thread_id++; if (wsrep_gtid_mode) { @@ -1820,21 +1827,11 @@ pthread_handler_t start_wsrep_THD(void *arg) //thd->version= refresh_version; thd->proc_info= 0; thd->set_command(COM_SLEEP); - - if (wsrep_creating_startup_threads == 0) - { - thd->init_for_queries(); - } + thd->init_for_queries(); mysql_mutex_lock(&LOCK_thread_count); wsrep_running_threads++; mysql_cond_broadcast(&COND_thread_count); - - if (wsrep_running_threads > 2) - { - wsrep_creating_startup_threads= 0; - } - mysql_mutex_unlock(&LOCK_thread_count); processor(thd); @@ -1863,21 +1860,22 @@ pthread_handler_t start_wsrep_THD(void *arg) // at server shutdown } - my_thread_end(); if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) { mysql_mutex_lock(&LOCK_thread_count); - delete thd; - thread_count--; + thd->unlink(); mysql_mutex_unlock(&LOCK_thread_count); + delete thd; + dec_thread_count(); } + my_thread_end(); return(NULL); error: WSREP_ERROR("Failed to create/initialize system thread"); /* Abort if its the first applier/rollbacker thread. */ - if (wsrep_creating_startup_threads == 1) + if (!mysqld_server_initialized) unireg_abort(1); else return NULL; @@ -1937,8 +1935,8 @@ static bool have_client_connections() I_List_iterator<THD> it(threads); while ((tmp=it++)) { - DBUG_PRINT("quit",("Informing thread %ld that it's time to die", - tmp->thread_id)); + DBUG_PRINT("quit",("Informing thread %lld that it's time to die", + (longlong) tmp->thread_id)); if (is_client_connection(tmp) && tmp->killed == KILL_CONNECTION) { (void)abort_replicated(tmp); @@ -2022,8 +2020,8 @@ void wsrep_close_client_connections(my_bool wait_to_end) I_List_iterator<THD> it(threads); while ((tmp=it++)) { - DBUG_PRINT("quit",("Informing thread %ld that it's time to die", - tmp->thread_id)); + DBUG_PRINT("quit",("Informing thread %lld that it's time to die", + (longlong) tmp->thread_id)); /* We skip slave threads & scheduler on this first loop through. */ if (!is_client_connection(tmp)) continue; @@ -2038,7 +2036,7 @@ void wsrep_close_client_connections(my_bool wait_to_end) if (abort_replicated(tmp)) continue; - WSREP_DEBUG("closing connection %ld", tmp->thread_id); + WSREP_DEBUG("closing connection %lld", (longlong) tmp->thread_id); wsrep_close_thread(tmp); } mysql_mutex_unlock(&LOCK_thread_count); @@ -2059,7 +2057,7 @@ void wsrep_close_client_connections(my_bool wait_to_end) !abort_replicated(tmp) && !is_replaying_connection(tmp)) { - WSREP_INFO("killing local connection: %ld",tmp->thread_id); + WSREP_INFO("killing local connection: %lld", (longlong) tmp->thread_id); close_connection(tmp,0); } #endif @@ -2084,7 +2082,7 @@ void wsrep_close_client_connections(my_bool wait_to_end) void wsrep_close_applier(THD *thd) { - WSREP_DEBUG("closing applier %ld", thd->thread_id); + WSREP_DEBUG("closing applier %lld", (longlong) thd->thread_id); wsrep_close_thread(thd); } @@ -2097,12 +2095,12 @@ void wsrep_close_threads(THD *thd) I_List_iterator<THD> it(threads); while ((tmp=it++)) { - DBUG_PRINT("quit",("Informing thread %ld that it's time to die", - tmp->thread_id)); + DBUG_PRINT("quit",("Informing thread %lld that it's time to die", + (longlong) tmp->thread_id)); /* We skip slave threads & scheduler on this first loop through. */ if (tmp->wsrep_applier && tmp != thd) { - WSREP_DEBUG("closing wsrep thread %ld", tmp->thread_id); + WSREP_DEBUG("closing wsrep thread %lld", (longlong) tmp->thread_id); wsrep_close_thread (tmp); } } @@ -2198,9 +2196,9 @@ int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len) &(thd->lex->definer->host), saved_mode)) { - WSREP_WARN("SP create string failed: schema: %s, query: %s", - (thd->db ? thd->db : "(null)"), thd->query()); - return 1; + WSREP_WARN("SP create string failed: schema: %s, query: %s", + (thd->db ? thd->db : "(null)"), thd->query()); + return 1; } return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len); @@ -2381,9 +2379,9 @@ int wsrep_thd_retry_counter(THD *thd) } -extern "C" bool wsrep_thd_skip_append_keys(THD *thd) +extern "C" bool wsrep_thd_ignore_table(THD *thd) { - return thd->wsrep_skip_append_keys; + return thd->wsrep_ignore_table; } diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 26d3484b3b4..e91ed2302a2 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -86,7 +86,6 @@ extern my_bool wsrep_slave_FK_checks; extern my_bool wsrep_slave_UK_checks; extern ulong wsrep_running_threads; extern bool wsrep_new_cluster; -extern my_bool wsrep_creating_startup_threads; extern bool wsrep_gtid_mode; extern uint32 wsrep_gtid_domain_id; @@ -161,6 +160,7 @@ extern void wsrep_kill_mysql(THD *thd); /* new defines */ extern void wsrep_stop_replication(THD *thd); extern bool wsrep_start_replication(); +extern bool wsrep_must_sync_wait(THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ); extern bool wsrep_sync_wait(THD* thd, uint mask = WSREP_SYNC_WAIT_BEFORE_READ); extern int wsrep_check_opts(); extern void wsrep_prepend_PATH (const char* path); @@ -328,6 +328,7 @@ int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len); #define wsrep_prepend_PATH(X) #define wsrep_before_SE() (0) #define wsrep_init_startup(X) +#define wsrep_must_sync_wait(...) (0) #define wsrep_sync_wait(...) (0) #define wsrep_to_isolation_begin(...) (0) #define wsrep_register_hton(...) do { } while(0) @@ -341,7 +342,6 @@ int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len); #define wsrep_thr_init() do {} while(0) #define wsrep_thr_deinit() do {} while(0) #define wsrep_running_threads (0) -#define wsrep_creating_startup_threads (0) #endif /* WITH_WSREP */ #endif /* WSREP_MYSQLD_H */ diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index c75f2c116ec..6d04527cbcb 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -875,7 +875,7 @@ static int sst_donate_mysqldump (const char* addr, host, port, mysqld_port, mysqld_unix_port, wsrep_defaults_file, uuid_str, (long long)seqno, wsrep_gtid_domain_id, - bypass ? " "WSREP_SST_OPT_BYPASS : ""); + bypass ? " " WSREP_SST_OPT_BYPASS : ""); if (ret < 0 || ret >= cmd_len) { @@ -896,6 +896,56 @@ static int sst_donate_mysqldump (const char* addr, wsrep_seqno_t wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; + +/* + Create a file under data directory. +*/ +static int sst_create_file(const char *name, const char *content) +{ + int err= 0; + char *real_name; + char *tmp_name; + ssize_t len; + FILE *file; + + len= strlen(mysql_real_data_home) + strlen(name) + 2; + real_name= (char *) alloca(len); + + snprintf(real_name, (size_t) len, "%s/%s", mysql_real_data_home, name); + + tmp_name= (char *) alloca(len + 4); + snprintf(tmp_name, (size_t) len + 4, "%s.tmp", real_name); + + file= fopen(tmp_name, "w+"); + + if (0 == file) + { + err= errno; + WSREP_ERROR("Failed to open '%s': %d (%s)", tmp_name, err, strerror(err)); + } + else + { + // Write the specified content into the file. + if (content != NULL) + { + fprintf(file, "%s\n", content); + fsync(fileno(file)); + } + + fclose(file); + + if (rename(tmp_name, real_name) == -1) + { + err= errno; + WSREP_ERROR("Failed to rename '%s' to '%s': %d (%s)", tmp_name, + real_name, err, strerror(err)); + } + } + + return err; +} + + static int run_sql_command(THD *thd, const char *query) { thd->set_query((char *)query, strlen(query)); @@ -907,11 +957,11 @@ static int run_sql_command(THD *thd, const char *query) return -1; } - mysql_parse(thd, thd->query(), thd->query_length(), &ps); + mysql_parse(thd, thd->query(), thd->query_length(), &ps, FALSE); if (thd->is_error()) { int const err= thd->get_stmt_da()->sql_errno(); - WSREP_WARN ("error executing '%s': %d (%s)%s", + WSREP_WARN ("Error executing '%s': %d (%s)%s", query, err, thd->get_stmt_da()->message(), err == ER_UNKNOWN_SYSTEM_VARIABLE ? ". Was mysqld built with --with-innodb-disallow-writes ?" : ""); @@ -921,15 +971,21 @@ static int run_sql_command(THD *thd, const char *query) return 0; } + static int sst_flush_tables(THD* thd) { WSREP_INFO("Flushing tables for SST..."); - int err; + int err= 0; int not_used; - CHARSET_INFO *current_charset; + /* + Files created to notify the SST script about the outcome of table flush + operation. + */ + const char *flush_success= "tables_flushed"; + const char *flush_error= "sst_error"; - current_charset = thd->variables.character_set_client; + CHARSET_INFO *current_charset= thd->variables.character_set_client; if (!is_supported_parser_charset(current_charset)) { @@ -942,61 +998,55 @@ static int sst_flush_tables(THD* thd) if (run_sql_command(thd, "FLUSH TABLES WITH READ LOCK")) { - WSREP_ERROR("Failed to flush and lock tables"); - err = -1; + err= -1; } else { - /* make sure logs are flushed after global read lock acquired */ - err= reload_acl_and_cache(thd, REFRESH_ENGINE_LOG | REFRESH_BINARY_LOG, - (TABLE_LIST*) 0, ¬_used); + /* + Make sure logs are flushed after global read lock acquired. In case + reload fails, we must also release the acquired FTWRL. + */ + if (reload_acl_and_cache(thd, REFRESH_ENGINE_LOG | REFRESH_BINARY_LOG, + (TABLE_LIST*) 0, ¬_used)) + { + thd->global_read_lock.unlock_global_read_lock(thd); + err= -1; + } } thd->variables.character_set_client = current_charset; - if (err) { - WSREP_ERROR("Failed to flush tables: %d (%s)", err, strerror(err)); + WSREP_ERROR("Failed to flush and lock tables"); + + /* + The SST must be aborted as the flush tables failed. Notify this to SST + script by creating the error file. + */ + int tmp; + if ((tmp= sst_create_file(flush_error, NULL))) { + err= tmp; + } } else { WSREP_INFO("Tables flushed."); - const char base_name[]= "tables_flushed"; - - ssize_t const full_len= strlen(mysql_real_data_home) + strlen(base_name)+2; - char *real_name= (char *) alloca(full_len); - snprintf(real_name, (size_t) full_len, "%s/%s", mysql_real_data_home, - base_name); - char *tmp_name= (char *) alloca(full_len + 4); - snprintf(tmp_name, (size_t) full_len + 4, "%s.tmp", real_name); - FILE* file= fopen(tmp_name, "w+"); - if (0 == file) - { - err= errno; - WSREP_ERROR("Failed to open '%s': %d (%s)", tmp_name, err,strerror(err)); - } - else - { - // Write cluster state ID and wsrep_gtid_domain_id. - fprintf(file, "%s:%lld %d\n", - wsrep_cluster_state_uuid, (long long)wsrep_locked_seqno, - wsrep_gtid_domain_id); - fsync(fileno(file)); - fclose(file); - if (rename(tmp_name, real_name) == -1) - { - err= errno; - WSREP_ERROR("Failed to rename '%s' to '%s': %d (%s)", - tmp_name, real_name, err,strerror(err)); - } - } + /* + Tables have been flushed. Create a file with cluster state ID and + wsrep_gtid_domain_id. + */ + char content[100]; + snprintf(content, sizeof(content), "%s:%lld %d\n", wsrep_cluster_state_uuid, + (long long)wsrep_locked_seqno, wsrep_gtid_domain_id); + err= sst_create_file(flush_success, content); } return err; } + static void sst_disallow_writes (THD* thd, bool yes) { char query_str[64] = { 0, }; @@ -1170,7 +1220,7 @@ static int sst_donate_other (const char* method, wsrep_defaults_file, binlog_opt, binlog_opt_val, uuid, (long long) seqno, wsrep_gtid_domain_id, - bypass ? " "WSREP_SST_OPT_BYPASS : ""); + bypass ? " " WSREP_SST_OPT_BYPASS : ""); my_free(binlog_opt_val); if (ret < 0 || ret >= cmd_len) diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index ab09a9e3a99..3835c925745 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -50,8 +50,8 @@ int wsrep_show_bf_aborts (THD *thd, SHOW_VAR *var, char *buff, /* must have (&thd->LOCK_wsrep_thd) */ void wsrep_client_rollback(THD *thd) { - WSREP_DEBUG("client rollback due to BF abort for (%ld), query: %s", - thd->thread_id, thd->query()); + WSREP_DEBUG("client rollback due to BF abort for (%lld), query: %s", + (longlong) thd->thread_id, thd->query()); WSREP_ATOMIC_ADD_LONG(&wsrep_bf_aborts_counter, 1); @@ -61,14 +61,16 @@ void wsrep_client_rollback(THD *thd) if (thd->locked_tables_mode && thd->lock) { - WSREP_DEBUG("unlocking tables for BF abort (%ld)", thd->thread_id); + WSREP_DEBUG("unlocking tables for BF abort (%lld)", + (longlong) thd->thread_id); thd->locked_tables_list.unlock_locked_tables(thd); thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); } if (thd->global_read_lock.is_acquired()) { - WSREP_DEBUG("unlocking GRL for BF abort (%ld)", thd->thread_id); + WSREP_DEBUG("unlocking GRL for BF abort (%lld)", + (longlong) thd->thread_id); thd->global_read_lock.unlock_global_read_lock(thd); } @@ -80,7 +82,8 @@ void wsrep_client_rollback(THD *thd) if (thd->get_binlog_table_maps()) { - WSREP_DEBUG("clearing binlog table map for BF abort (%ld)", thd->thread_id); + WSREP_DEBUG("clearing binlog table map for BF abort (%lld)", + (longlong) thd->thread_id); thd->clear_binlog_table_maps(); } mysql_mutex_lock(&thd->LOCK_wsrep_thd); @@ -202,8 +205,8 @@ void wsrep_replay_transaction(THD *thd) close_thread_tables(thd); if (thd->locked_tables_mode && thd->lock) { - WSREP_DEBUG("releasing table lock for replaying (%ld)", - thd->thread_id); + WSREP_DEBUG("releasing table lock for replaying (%lld)", + (longlong) thd->thread_id); thd->locked_tables_list.unlock_locked_tables(thd); thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); } @@ -242,8 +245,8 @@ void wsrep_replay_transaction(THD *thd) case WSREP_OK: thd->wsrep_conflict_state= NO_CONFLICT; wsrep->post_commit(wsrep, &thd->wsrep_ws_handle); - WSREP_DEBUG("trx_replay successful for: %ld %llu", - thd->thread_id, (long long)thd->real_id); + WSREP_DEBUG("trx_replay successful for: %lld %lld", + (longlong) thd->thread_id, (longlong) thd->real_id); if (thd->get_stmt_da()->is_sent()) { WSREP_WARN("replay ok, thd has reported status"); @@ -292,8 +295,8 @@ void wsrep_replay_transaction(THD *thd) mysql_mutex_lock(&LOCK_wsrep_replaying); wsrep_replaying--; - WSREP_DEBUG("replaying decreased: %d, thd: %lu", - wsrep_replaying, thd->thread_id); + WSREP_DEBUG("replaying decreased: %d, thd: %lld", + wsrep_replaying, (longlong) thd->thread_id); mysql_cond_broadcast(&COND_wsrep_replaying); mysql_mutex_unlock(&LOCK_wsrep_replaying); } @@ -360,15 +363,34 @@ static void wsrep_replication_process(THD *thd) TABLE *tmp; while ((tmp = thd->temporary_tables)) { - WSREP_WARN("Applier %lu, has temporary tables at exit: %s.%s", - thd->thread_id, - (tmp->s) ? tmp->s->db.str : "void", - (tmp->s) ? tmp->s->table_name.str : "void"); + WSREP_WARN("Applier %lld, has temporary tables at exit: %s.%s", + (longlong) thd->thread_id, + (tmp->s) ? tmp->s->db.str : "void", + (tmp->s) ? tmp->s->table_name.str : "void"); } wsrep_return_from_bf_mode(thd, &shadow); DBUG_VOID_RETURN; } +static bool create_wsrep_THD(wsrep_thd_processor_fun processor) +{ + ulong old_wsrep_running_threads= wsrep_running_threads; + pthread_t unused; + mysql_mutex_lock(&LOCK_thread_count); + bool res= pthread_create(&unused, &connection_attrib, start_wsrep_THD, + (void*)processor); + /* + if starting a thread on server startup, wait until the this thread's THD + is fully initialized (otherwise a THD initialization code might + try to access a partially initialized server data structure - MDEV-8208). + */ + if (!mysqld_server_initialized) + while (old_wsrep_running_threads == wsrep_running_threads) + mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + return res; +} + void wsrep_create_appliers(long threads) { if (!wsrep_connected) @@ -385,11 +407,8 @@ void wsrep_create_appliers(long threads) } long wsrep_threads=0; - pthread_t hThread; while (wsrep_threads++ < threads) { - if (pthread_create( - &hThread, &connection_attrib, - start_wsrep_THD, (void*)wsrep_replication_process)) + if (create_wsrep_THD(wsrep_replication_process)) WSREP_WARN("Can't create thread to manage wsrep replication"); } } @@ -454,8 +473,9 @@ static void wsrep_rollback_process(THD *thd) mysql_mutex_lock(&aborting->LOCK_wsrep_thd); wsrep_client_rollback(aborting); - WSREP_DEBUG("WSREP rollbacker aborted thd: (%lu %llu)", - aborting->thread_id, (long long)aborting->real_id); + WSREP_DEBUG("WSREP rollbacker aborted thd: (%lld %lld)", + (longlong) aborting->thread_id, + (longlong) aborting->real_id); mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); set_current_thd(thd); @@ -476,10 +496,8 @@ void wsrep_create_rollbacker() { if (wsrep_provider && strcasecmp(wsrep_provider, "none")) { - pthread_t hThread; /* create rollbacker */ - if (pthread_create( &hThread, &connection_attrib, - start_wsrep_THD, (void*)wsrep_rollback_process)) + if (create_wsrep_THD(wsrep_rollback_process)) WSREP_WARN("Can't create thread to manage wsrep rollback"); } } diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index bbce62e0641..c322c8eee54 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -56,7 +56,7 @@ meta file is first opened it is marked as dirty. It is opened when the table itself is opened for writing. When the table is closed the new count for rows is written to the meta file and the file is marked as clean. If the meta file - is opened and it is marked as dirty, it is assumed that a crash occured. At + is opened and it is marked as dirty, it is assumed that a crash occurred. At this point an error occurs and the user is told to rebuild the file. A rebuild scans the rows and rewrites the meta file. If corruption is found in the data file then the meta file is not repaired. diff --git a/storage/connect/catalog.h b/storage/connect/catalog.h index 6488b513ba9..70304c410cc 100644 --- a/storage/connect/catalog.h +++ b/storage/connect/catalog.h @@ -77,8 +77,8 @@ class DllExport CATALOG { virtual bool ClearName(PGLOBAL, PSZ) {return true;} virtual PRELDEF MakeOneTableDesc(PGLOBAL, LPCSTR, LPCSTR) {return NULL;} virtual PRELDEF GetTableDescEx(PGLOBAL, PTABLE) {return NULL;} - virtual PRELDEF GetTableDesc(PGLOBAL, LPCSTR, LPCSTR, - PRELDEF* = NULL) {return NULL;} + //virtual PRELDEF GetTableDesc(PGLOBAL, LPCSTR, LPCSTR, + // PRELDEF* = NULL) {return NULL;} virtual PRELDEF GetFirstTable(PGLOBAL) {return NULL;} virtual PRELDEF GetNextTable(PGLOBAL) {return NULL;} virtual bool TestCond(PGLOBAL, const char*, const char*) {return true;} @@ -95,7 +95,7 @@ class DllExport CATALOG { protected: virtual bool ClearSection(PGLOBAL, const char*, const char*) {return true;} - virtual PRELDEF MakeTableDesc(PGLOBAL, LPCSTR, LPCSTR) {return NULL;} + //virtual PRELDEF MakeTableDesc(PGLOBAL, LPCSTR, LPCSTR) {return NULL;} // Members char *Cbuf; /* Buffer used for col section */ diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 04926228aa4..d96d7455d8b 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -1,4 +1,4 @@ -/* Copyright (C) Olivier Bertrand 2004 - 2015 +/* Copyright (C) Olivier Bertrand 2004 - 2016 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -169,9 +169,9 @@ #define JSONMAX 10 // JSON Default max grp size extern "C" { - char version[]= "Version 1.04.0005 December 11, 2015"; + char version[]= "Version 1.04.0006 March 12, 2016"; #if defined(__WIN__) - char compver[]= "Version 1.04.0005 " __DATE__ " " __TIME__; + char compver[]= "Version 1.04.0006 " __DATE__ " " __TIME__; char slash= '\\'; #else // !__WIN__ char slash= '/'; @@ -340,14 +340,21 @@ static MYSQL_THDVAR_ENUM( #endif // XMSG || NEWMSG /***********************************************************************/ +/* The CONNECT handlerton object. */ +/***********************************************************************/ +handlerton *connect_hton= NULL; + +/***********************************************************************/ /* Function to export session variable values to other source files. */ /***********************************************************************/ -extern "C" int GetTraceValue(void) {return THDVAR(current_thd, xtrace);} +extern "C" int GetTraceValue(void) + {return connect_hton ? THDVAR(current_thd, xtrace) : 0;} bool ExactInfo(void) {return THDVAR(current_thd, exact_info);} USETEMP UseTemp(void) {return (USETEMP)THDVAR(current_thd, use_tempfile);} int GetConvSize(void) {return THDVAR(current_thd, conv_size);} TYPCONV GetTypeConv(void) {return (TYPCONV)THDVAR(current_thd, type_conv);} -uint GetJsonGrpSize(void) {return THDVAR(current_thd, json_grp_size);} +uint GetJsonGrpSize(void) + {return connect_hton ? THDVAR(current_thd, json_grp_size) : 10;} uint GetWorkSize(void) {return THDVAR(current_thd, work_size);} void SetWorkSize(uint) { @@ -442,11 +449,6 @@ static int check_msg_path (MYSQL_THD thd, struct st_mysql_sys_var *var, } // end of check_msg_path #endif // 0 -/***********************************************************************/ -/* The CONNECT handlerton object. */ -/***********************************************************************/ -handlerton *connect_hton; - /** CREATE TABLE option list (table options) @@ -687,6 +689,7 @@ static int connect_done_func(void *) delete pc; } // endfor pc + connect_hton= NULL; DBUG_RETURN(error); } // end of connect_done_func @@ -4922,11 +4925,11 @@ static bool add_field(String *sql, const char *field_name, int typ, int len, error|= sql->append("` "); error|= sql->append(type); - if (len && typ != TYPE_DATE) { + if (len && typ != TYPE_DATE && (typ != TYPE_DOUBLE || dec >= 0)) { error|= sql->append('('); error|= sql->append_ulonglong(len); - if (!strcmp(type, "DOUBLE")) { + if (typ == TYPE_DOUBLE) { error|= sql->append(','); // dec must be < len and < 31 error|= sql->append_ulonglong(MY_MIN(dec, (MY_MIN(len, 31) - 1))); @@ -5156,7 +5159,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, fncn= topt->catfunc; fnc= GetFuncID(fncn); sep= topt->separator; - spc= (!sep) ? ',' : (!strcmp(sep, "\\t")) ? '\t' : *sep; + spc= (!sep) ? ',' : *sep; qch= topt->qchar ? *topt->qchar : (signed)topt->quoted >= 0 ? '"' : 0; hdr= (int)topt->header; tbl= topt->tablist; @@ -5223,7 +5226,6 @@ static int connect_assisted_discovery(handlerton *, THD* thd, goto err; } // endif rc - if (!tab) { if (ttp == TAB_TBL) { // Make tab the first table of the list @@ -5292,8 +5294,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd, case TAB_CSV: if (!fn && fnc != FNC_NO) sprintf(g->Message, "Missing %s file name", topt->type); - else - ok= true; + else if (sep && strlen(sep) > 1) + sprintf(g->Message, "Invalid separator %s", sep); + else + ok= true; break; case TAB_MYSQL: @@ -5512,6 +5516,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, dec= crp->Prec; flg= crp->Flag; v= crp->Var; + tm= (crp->Kdata->IsNullable()) ? 0 : NOT_NULL_FLAG; if (!len && typ == TYPE_STRING) len= 256; // STRBLK's have 0 length @@ -5519,9 +5524,9 @@ static int connect_assisted_discovery(handlerton *, THD* thd, // Now add the field #if defined(NEW_WAY) rc= add_fields(g, thd, &alter_info, cnm, typ, len, dec, - NOT_NULL_FLAG, "", flg, dbf, v); + tm, "", flg, dbf, v); #else // !NEW_WAY - if (add_field(&sql, cnm, typ, len, dec, NULL, NOT_NULL_FLAG, + if (add_field(&sql, cnm, typ, len, dec, NULL, tm, NULL, NULL, NULL, NULL, flg, dbf, v)) rc= HA_ERR_OUT_OF_MEM; #endif // !NEW_WAY @@ -5578,7 +5583,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd, len= crp->Kdata->GetIntValue(i); break; case FLD_SCALE: - dec= crp->Kdata->GetIntValue(i); + dec = (!crp->Kdata->IsNull(i)) ? crp->Kdata->GetIntValue(i) : -1; break; case FLD_NULL: if (crp->Kdata->GetIntValue(i)) @@ -5671,14 +5676,14 @@ static int connect_assisted_discovery(handlerton *, THD* thd, dec= 0; } // endswitch typ - } // endif ttp + } else #endif // ODBC_SUPPORT - // Make the arguments as required by add_fields - if (typ == TYPE_DATE) + if (typ == TYPE_DOUBLE) + prec= len; + + if (typ == TYPE_DATE) prec= 0; - else if (typ == TYPE_DOUBLE) - prec= len; // Now add the field #if defined(NEW_WAY) @@ -5973,7 +5978,19 @@ int ha_connect::create(const char *name, TABLE *table_arg, DBUG_RETURN(rc); } // endif lrecl - } // endif type + } // endif type JSON + + if (type == TAB_CSV) { + const char *sep = options->separator; + + if (sep && strlen(sep) > 1) { + sprintf(g->Message, "Invalid separator %s", sep); + my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); + rc= HA_ERR_INTERNAL_ERROR; + DBUG_RETURN(rc); + } // endif sep + + } // endif type CSV // Check column types for (field= table_arg->field; *field; field++) { @@ -6761,7 +6778,7 @@ maria_declare_plugin(connect) 0x0104, /* version number (1.04) */ NULL, /* status variables */ connect_system_variables, /* system variables */ - "1.04.0005", /* string version */ - MariaDB_PLUGIN_MATURITY_BETA /* maturity */ + "1.04.0006", /* string version */ + MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */ } maria_declare_plugin_end; diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp index fc7edb84c0f..d99a021cdc9 100644 --- a/storage/connect/json.cpp +++ b/storage/connect/json.cpp @@ -594,7 +594,7 @@ PSZ Serialize(PGLOBAL g, PJSON jsp, char *fn, int pretty) if (fs) { fputs(EL, fs); fclose(fs); - str = (err) ? NULL : "Ok"; + str = (err) ? NULL : strcpy(g->Message, "Ok"); } else if (!err) { str = ((JOUTSTR*)jp)->Strp; jp->WriteChr('\0'); diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp index 40685ae0f0e..25c77cea534 100644 --- a/storage/connect/jsonudf.cpp +++ b/storage/connect/jsonudf.cpp @@ -31,6 +31,8 @@ uint GetJsonGrpSize(void); static int IsJson(UDF_ARGS *args, uint i); static PSZ MakePSZ(PGLOBAL g, UDF_ARGS *args, int i); +static uint JsonGrpSize = 10; + /* ----------------------------------- JSNX ------------------------------------ */ /*********************************************************************************/ @@ -1040,6 +1042,14 @@ static void SetChanged(PBSON bsp) } /* end of SetChanged */ /*********************************************************************************/ +/* Replaces GetJsonGrpSize not usable when CONNECT is not installed. */ +/*********************************************************************************/ +static uint GetJsonGroupSize(void) +{ + return (JsonGrpSize) ? JsonGrpSize : GetJsonGrpSize(); +} // end of GetJsonGroupSize + +/*********************************************************************************/ /* Program for SubSet re-initialization of the memory pool. */ /*********************************************************************************/ static my_bool JsonSubSet(PGLOBAL g) @@ -2394,11 +2404,50 @@ void json_object_list_deinit(UDF_INIT* initid) } // end of json_object_list_deinit /*********************************************************************************/ +/* Set the value of JsonGrpSize. */ +/*********************************************************************************/ +my_bool jsonset_grp_size_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + if (args->arg_count != 1 || args->arg_type[0] != INT_RESULT) { + strcpy(message, "This function must have 1 integer argument"); + return true; + } else + return false; + +} // end of jsonset_grp_size_init + +long long jsonset_grp_size(UDF_INIT *initid, UDF_ARGS *args, char *, char *) +{ + long long n = *(long long*)args->args[0]; + + JsonGrpSize = (uint)n; + return (long long)GetJsonGroupSize(); +} // end of jsonset_grp_size + +/*********************************************************************************/ +/* Get the value of JsonGrpSize. */ +/*********************************************************************************/ +my_bool jsonget_grp_size_init(UDF_INIT *initid, UDF_ARGS *args, char *message) +{ + if (args->arg_count != 0) { + strcpy(message, "This function must have no arguments"); + return true; + } else + return false; + +} // end of jsonget_grp_size_init + +long long jsonget_grp_size(UDF_INIT *initid, UDF_ARGS *args, char *, char *) +{ + return (long long)GetJsonGroupSize(); +} // end of jsonget_grp_size + +/*********************************************************************************/ /* Make a Json array from values coming from rows. */ /*********************************************************************************/ my_bool json_array_grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { - unsigned long reslen, memlen, n = GetJsonGrpSize(); + unsigned long reslen, memlen, n = GetJsonGroupSize(); if (args->arg_count != 1) { strcpy(message, "This function can only accept 1 argument"); @@ -2458,7 +2507,7 @@ void json_array_grp_clear(UDF_INIT *initid, char*, char*) PlugSubSet(g, g->Sarea, g->Sarea_Size); g->Activityp = (PACTIVITY)new(g) JARRAY; - g->N = GetJsonGrpSize(); + g->N = GetJsonGroupSize(); } // end of json_array_grp_clear void json_array_grp_deinit(UDF_INIT* initid) @@ -2471,7 +2520,7 @@ void json_array_grp_deinit(UDF_INIT* initid) /*********************************************************************************/ my_bool json_object_grp_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { - unsigned long reslen, memlen, n = GetJsonGrpSize(); + unsigned long reslen, memlen, n = GetJsonGroupSize(); if (args->arg_count != 2) { strcpy(message, "This function requires 2 arguments (key, value)"); @@ -2529,7 +2578,7 @@ void json_object_grp_clear(UDF_INIT *initid, char*, char*) PlugSubSet(g, g->Sarea, g->Sarea_Size); g->Activityp = (PACTIVITY)new(g) JOBJECT; - g->N = GetJsonGrpSize(); + g->N = GetJsonGroupSize(); } // end of json_object_grp_clear void json_object_grp_deinit(UDF_INIT* initid) @@ -3365,7 +3414,7 @@ my_bool jsoncontains_init(UDF_INIT *initid, UDF_ARGS *args, char *message) long long jsoncontains(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *res_length, char *is_null, char *error) { - char *p, res[256]; + char *p __attribute__((unused)), res[256]; long long n; unsigned long reslen; diff --git a/storage/connect/jsonudf.h b/storage/connect/jsonudf.h index ecbbb778214..b7e9b8ecabb 100644 --- a/storage/connect/jsonudf.h +++ b/storage/connect/jsonudf.h @@ -77,6 +77,12 @@ extern "C" { DllExport char *json_object_list(UDF_EXEC_ARGS); DllExport void json_object_list_deinit(UDF_INIT*); + DllExport my_bool jsonset_grp_size_init(UDF_INIT*, UDF_ARGS*, char*); + DllExport long long jsonset_grp_size(UDF_INIT*, UDF_ARGS*, char*, char*); + + DllExport my_bool jsonget_grp_size_init(UDF_INIT*, UDF_ARGS*, char*); + DllExport long long jsonget_grp_size(UDF_INIT*, UDF_ARGS*, char*, char*); + DllExport my_bool json_array_grp_init(UDF_INIT*, UDF_ARGS*, char*); DllExport void json_array_grp_add(UDF_INIT *, UDF_ARGS *, char *, char *); DllExport char *json_array_grp(UDF_EXEC_ARGS); diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc index 2e9085b4c87..97ad980dd6a 100644 --- a/storage/connect/mycat.cc +++ b/storage/connect/mycat.cc @@ -1,4 +1,4 @@ -/* Copyright (C) Olivier Bertrand 2004 - 2015 +/* Copyright (C) Olivier Bertrand 2004 - 2016 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,7 +18,7 @@ /* ------------- */ /* Version 1.4 */ /* */ -/* Author: Olivier Bertrand 2012 - 2015 */ +/* Author: Olivier Bertrand 2012 - 2016 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -509,30 +509,33 @@ void MYCAT::SetPath(PGLOBAL g, LPCSTR *datapath, const char *path) /* GetTableDesc: retrieve a table descriptor. */ /* Look for a table descriptor matching the name and type. */ /***********************************************************************/ -PRELDEF MYCAT::GetTableDesc(PGLOBAL g, LPCSTR name, +PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR type, PRELDEF *) { if (trace) - printf("GetTableDesc: name=%s am=%s\n", name, SVP(type)); + printf("GetTableDesc: name=%s am=%s\n", tablep->GetName(), SVP(type)); // If not specified get the type of this table if (!type) type= Hc->GetStringOption("Type","*"); - return MakeTableDesc(g, name, type); + return MakeTableDesc(g, tablep, type); } // end of GetTableDesc /***********************************************************************/ /* MakeTableDesc: make a table/view description. */ /* Note: caller must check if name already exists before calling it. */ /***********************************************************************/ -PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am) +PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am) { TABTYPE tc; + LPCSTR name = (PSZ)PlugDup(g, tablep->GetName()); + LPCSTR schema = (PSZ)PlugDup(g, tablep->GetSchema()); PRELDEF tdp= NULL; if (trace) - printf("MakeTableDesc: name=%s am=%s\n", name, SVP(am)); + printf("MakeTableDesc: name=%s schema=%s am=%s\n", + name, SVP(schema), SVP(am)); /*********************************************************************/ /* Get a unique enum identifier for types. */ @@ -571,11 +574,11 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am) case TAB_VIR: tdp= new(g) VIRDEF; break; case TAB_JSON: tdp= new(g) JSONDEF; break; default: - sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name); + sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name); } // endswitch // Do make the table/view definition - if (tdp && tdp->Define(g, this, name, am)) + if (tdp && tdp->Define(g, this, name, schema, am)) tdp= NULL; return tdp; @@ -588,20 +591,20 @@ PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type) { PRELDEF tdp; PTDB tdbp= NULL; - LPCSTR name= tablep->GetName(); +// LPCSTR name= tablep->GetName(); if (trace) - printf("GetTableDB: name=%s\n", name); + printf("GetTableDB: name=%s\n", tablep->GetName()); // Look for the description of the requested table - tdp= GetTableDesc(g, name, type); + tdp= GetTableDesc(g, tablep, type); if (tdp) { if (trace) printf("tdb=%p type=%s\n", tdp, tdp->GetType()); - if (tablep->GetQualifier()) - tdp->Database = SetPath(g, tablep->GetQualifier()); + if (tablep->GetSchema()) + tdp->Database = SetPath(g, tablep->GetSchema()); tdbp= tdp->GetTable(g, mode); } // endif tdp diff --git a/storage/connect/mycat.h b/storage/connect/mycat.h index dfcbb2f6766..05163f08f1b 100644 --- a/storage/connect/mycat.h +++ b/storage/connect/mycat.h @@ -100,15 +100,17 @@ class MYCAT : public CATALOG { //void SetDataPath(PGLOBAL g, const char *path) // {SetPath(g, &DataPath, path);} bool StoreIndex(PGLOBAL, PTABDEF) {return false;} // Temporary - PRELDEF GetTableDesc(PGLOBAL g, LPCSTR name, - LPCSTR type, PRELDEF *prp = NULL); +// PRELDEF GetTableDesc(PGLOBAL g, LPCSTR name, + PRELDEF GetTableDesc(PGLOBAL g, PTABLE tablep, + LPCSTR type, PRELDEF *prp = NULL); PTDB GetTable(PGLOBAL g, PTABLE tablep, MODE mode = MODE_READ, LPCSTR type = NULL); void ClearDB(PGLOBAL g); protected: - PRELDEF MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am); -//void SetPath(PGLOBAL g, LPCSTR *datapath, const char *path); +// PRELDEF MakeTableDesc(PGLOBAL g, LPCSTR name, LPCSTR am); + PRELDEF MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am); + //void SetPath(PGLOBAL g, LPCSTR *datapath, const char *path); // Members ha_connect *Hc; // The Connect handler diff --git a/storage/connect/mysql-test/connect/r/infoschema-9739.result b/storage/connect/mysql-test/connect/r/infoschema-9739.result new file mode 100644 index 00000000000..bcebec1d0e0 --- /dev/null +++ b/storage/connect/mysql-test/connect/r/infoschema-9739.result @@ -0,0 +1,12 @@ +Warnings: +Warning 1105 No file name. Table will use t1.xml +create table t1 (i int) engine=Connect table_type=XML; +Warnings: +Warning 1105 No file name. Table will use t1.xml +select * from information_schema.tables where create_options like '%table_type=XML%'; +TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT +Warnings: +Warning 1286 Unknown storage engine 'InnoDB' +Warning 1286 Unknown storage engine 'InnoDB' +Warning 1296 Got error 174 'File t1.xml not found' from CONNECT +drop table t1; diff --git a/storage/connect/mysql-test/connect/r/json_udf.result b/storage/connect/mysql-test/connect/r/json_udf.result index 5089022c5ea..1e83834cb8f 100644 --- a/storage/connect/mysql-test/connect/r/json_udf.result +++ b/storage/connect/mysql-test/connect/r/json_udf.result @@ -217,7 +217,9 @@ DEPARTMENT Json_Array_Grp(NAME) 2452 ["BIGHEAD","ORELLY","BIGHORN","SMITH","CHERRY"] Warnings: Warning 1105 Result truncated to json_grp_size values -SET connect_json_grp_size=30; +SELECT JsonSet_Grp_Size(30); +JsonSet_Grp_Size(30) +30 SELECT Json_Object(title, Json_Array_Grp(name) `json_names`) from t3 GROUP BY title; Json_Object(title, Json_Array_Grp(name) `json_names`) {"title":"ADMINISTRATOR","names":["GOOSEPEN","FUNNIGUY","SHRINKY"]} diff --git a/storage/connect/mysql-test/connect/r/odbc.result b/storage/connect/mysql-test/connect/r/odbc.result index 8e1951f0b68..4ca7e2095df 100644 --- a/storage/connect/mysql-test/connect/r/odbc.result +++ b/storage/connect/mysql-test/connect/r/odbc.result @@ -5,7 +5,7 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `Name` varchar(256) NOT NULL, - `Description` varchar(256) NOT NULL + `Description` varchar(256) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Sources' DROP TABLE t1; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers; @@ -13,35 +13,35 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `Description` char(128) NOT NULL, - `Attributes` varchar(256) NOT NULL + `Attributes` varchar(256) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers' DROP TABLE t1; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Tables CONNECTION='Not important'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `Table_Cat` char(128) NOT NULL, - `Table_Schema` char(128) NOT NULL, + `Table_Cat` char(128) DEFAULT NULL, + `Table_Schema` char(128) DEFAULT NULL, `Table_Name` char(128) NOT NULL, `Table_Type` char(16) NOT NULL, - `Remark` char(255) NOT NULL + `Remark` char(255) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='Not important' `TABLE_TYPE`='ODBC' `CATFUNC`='Tables' DROP TABLE t1; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Columns CONNECTION='Not important'; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( - `Table_Cat` char(128) NOT NULL, - `Table_Schema` char(128) NOT NULL, + `Table_Cat` char(128) DEFAULT NULL, + `Table_Schema` char(128) DEFAULT NULL, `Table_Name` char(128) NOT NULL, `Column_Name` char(128) NOT NULL, `Data_Type` smallint(6) NOT NULL, `Type_Name` char(30) NOT NULL, `Column_Size` int(10) NOT NULL, `Buffer_Length` int(10) NOT NULL, - `Decimal_Digits` smallint(6) NOT NULL, - `Radix` smallint(6) NOT NULL, + `Decimal_Digits` smallint(6) DEFAULT NULL, + `Radix` smallint(6) DEFAULT NULL, `Nullable` smallint(6) NOT NULL, - `Remarks` char(255) NOT NULL + `Remarks` char(255) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='Not important' `TABLE_TYPE`='ODBC' `CATFUNC`='Columns' DROP TABLE t1; diff --git a/storage/connect/mysql-test/connect/r/odbc_oracle.result b/storage/connect/mysql-test/connect/r/odbc_oracle.result index 96d8e53b8e5..8dc7dc07bb1 100644 --- a/storage/connect/mysql-test/connect/r/odbc_oracle.result +++ b/storage/connect/mysql-test/connect/r/odbc_oracle.result @@ -1,7 +1,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `Name` varchar(256) NOT NULL, - `Description` varchar(256) NOT NULL + `Description` varchar(256) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Sources' SET NAMES utf8; # @@ -14,9 +14,9 @@ TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Tables; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Table_Type Remark - MTR T1 TABLE - MTR T2 TABLE - MTR V1 VIEW +NULL MTR T1 TABLE NULL +NULL MTR T2 TABLE NULL +NULL MTR V1 VIEW NULL DROP TABLE t1; # All tables in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT @@ -24,9 +24,9 @@ TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.%'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Table_Type Remark - MTR T1 TABLE - MTR T2 TABLE - MTR V1 VIEW +NULL MTR T1 TABLE NULL +NULL MTR T2 TABLE NULL +NULL MTR V1 VIEW NULL DROP TABLE t1; # All tables "T1" in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT @@ -34,7 +34,7 @@ TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='%.T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Table_Type Remark - MTR T1 TABLE +NULL MTR T1 TABLE NULL DROP TABLE t1; # All tables "T1" in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT @@ -42,7 +42,7 @@ TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Table_Type Remark - MTR T1 TABLE +NULL MTR T1 TABLE NULL DROP TABLE t1; # Table "T1" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT @@ -50,7 +50,7 @@ TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='MTR.T1'; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Table_Type Remark - MTR T1 TABLE +NULL MTR T1 TABLE NULL DROP TABLE t1; # All tables in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT @@ -58,9 +58,9 @@ TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Tables TABNAME='MTR.%'; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Table_Type Remark - MTR T1 TABLE - MTR T2 TABLE - MTR V1 VIEW +NULL MTR T1 TABLE NULL +NULL MTR T2 TABLE NULL +NULL MTR V1 VIEW NULL DROP TABLE t1; # # Checking CATFUNC=Columns @@ -73,10 +73,10 @@ CATFUNC=Columns; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks MTR T1 A 3 DECIMAL 38 40 0 10 1 - MTR T1 B 6 NUMBER 38 40 0 0 1 - MTR T2 A 12 VARCHAR2 64 64 0 0 1 + MTR T1 B 6 NUMBER 38 40 NULL NULL 1 + MTR T2 A 12 VARCHAR2 64 64 NULL NULL 1 MTR V1 A 3 DECIMAL 38 40 0 10 1 - MTR V1 B 6 NUMBER 38 40 0 0 1 + MTR V1 B 6 NUMBER 38 40 NULL NULL 1 DROP TABLE t1; # All columns in all schemas (limited with WHERE) CREATE TABLE t1 ENGINE=CONNECT @@ -85,17 +85,17 @@ CATFUNC=Columns TABNAME='%.%'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks MTR T1 A 3 DECIMAL 38 40 0 10 1 - MTR T1 B 6 NUMBER 38 40 0 0 1 - MTR T2 A 12 VARCHAR2 64 64 0 0 1 + MTR T1 B 6 NUMBER 38 40 NULL NULL 1 + MTR T2 A 12 VARCHAR2 64 64 NULL NULL 1 MTR V1 A 3 DECIMAL 38 40 0 10 1 - MTR V1 B 6 NUMBER 38 40 0 0 1 + MTR V1 B 6 NUMBER 38 40 NULL NULL 1 DROP TABLE t1; # All tables "T1" in all schemas (limited with WHERE) CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks MTR T1 A 3 DECIMAL 38 40 0 10 1 - MTR T1 B 6 NUMBER 38 40 0 0 1 + MTR T1 B 6 NUMBER 38 40 NULL NULL 1 DROP TABLE t1; # Table "T1" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT @@ -104,7 +104,7 @@ CATFUNC=Columns TABNAME='MTR.T1'; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks MTR T1 A 3 DECIMAL 38 40 0 10 1 - MTR T1 B 6 NUMBER 38 40 0 0 1 + MTR T1 B 6 NUMBER 38 40 NULL NULL 1 DROP TABLE t1; # All tables "T1" in all schemas (filtered with WHERE) CREATE TABLE t1 ENGINE=CONNECT @@ -113,7 +113,7 @@ CATFUNC=Columns TABNAME='%.T1'; SELECT * FROM t1 WHERE Table_Schema='MTR' ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks MTR T1 A 3 DECIMAL 38 40 0 10 1 - MTR T1 B 6 NUMBER 38 40 0 0 1 + MTR T1 B 6 NUMBER 38 40 NULL NULL 1 DROP TABLE t1; # # Checking tables @@ -127,32 +127,32 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `A` decimal(40,0) DEFAULT NULL, - `B` double(40,0) DEFAULT NULL + `B` double DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='T1' SELECT * FROM t1 ORDER BY A; A B 10 1000000000 20 1000000000000 -30 1000000000000000 +30 1e15 CREATE TABLE t2 AS SELECT * FROM t1; SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( `A` decimal(40,0) DEFAULT NULL, - `B` double(40,0) DEFAULT NULL + `B` double DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 SELECT * FROM t2; A B 10 1000000000 20 1000000000000 -30 1000000000000000 +30 1e15 DROP TABLE t2; CREATE VIEW v1 AS SELECT * FROM t1; SELECT * FROM v1; A B 10 1000000000 20 1000000000000 -30 1000000000000000 +30 1e15 DROP VIEW v1; DROP TABLE t1; # Table "T1" in the schema "MTR" @@ -163,13 +163,13 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `A` decimal(40,0) DEFAULT NULL, - `B` double(40,0) DEFAULT NULL + `B` double DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.T1' SELECT * FROM t1; A B 10 1000000000 20 1000000000000 -30 1000000000000000 +30 1e15 DROP TABLE t1; # View "V1" in the schema "MTR" CREATE TABLE t1 ENGINE=CONNECT @@ -179,32 +179,32 @@ SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `A` decimal(40,0) DEFAULT NULL, - `B` double(40,0) DEFAULT NULL + `B` double DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.V1' SELECT * FROM t1; A B 10 1000000000 20 1000000000000 -30 1000000000000000 +30 1e15 CREATE TABLE t2 AS SELECT * FROM t1; SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( `A` decimal(40,0) DEFAULT NULL, - `B` double(40,0) DEFAULT NULL + `B` double DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 SELECT * FROM t2; A B 10 1000000000 20 1000000000000 -30 1000000000000000 +30 1e15 DROP TABLE t2; CREATE VIEW v1 AS SELECT * FROM t1; SELECT * FROM v1; A B 10 1000000000 20 1000000000000 -30 1000000000000000 +30 1e15 DROP VIEW v1; DROP TABLE t1; # Table "T2" in the schema "MTR" diff --git a/storage/connect/mysql-test/connect/r/odbc_postgresql.result b/storage/connect/mysql-test/connect/r/odbc_postgresql.result index 68ce03cb382..3426d23e29c 100644 --- a/storage/connect/mysql-test/connect/r/odbc_postgresql.result +++ b/storage/connect/mysql-test/connect/r/odbc_postgresql.result @@ -1,7 +1,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `Name` varchar(256) NOT NULL, - `Description` varchar(256) NOT NULL + `Description` varchar(256) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Sources' SET NAMES utf8; # @@ -99,9 +99,9 @@ Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Bu mtr public t1 a 4 int4 10 4 0 10 0 mtr public t2 a 4 int4 10 4 0 10 0 mtr public v1 a 4 int4 10 4 0 10 1 -mtr schema1 t1 a 1 bpchar 10 60 0 0 0 -mtr schema1 t2 a 1 bpchar 10 60 0 0 0 -mtr schema1 v1 a 1 bpchar 10 60 0 0 1 +mtr schema1 t1 a 1 bpchar 10 60 NULL NULL 0 +mtr schema1 t2 a 1 bpchar 10 60 NULL NULL 0 +mtr schema1 v1 a 1 bpchar 10 60 NULL NULL 1 DROP TABLE t1; # All columns in the schemas "public" and "schema1" CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.%.%'; @@ -110,16 +110,16 @@ Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Bu mtr public t1 a 4 int4 10 4 0 10 0 mtr public t2 a 4 int4 10 4 0 10 0 mtr public v1 a 4 int4 10 4 0 10 1 -mtr schema1 t1 a 1 bpchar 10 60 0 0 0 -mtr schema1 t2 a 1 bpchar 10 60 0 0 0 -mtr schema1 v1 a 1 bpchar 10 60 0 0 1 +mtr schema1 t1 a 1 bpchar 10 60 NULL NULL 0 +mtr schema1 t2 a 1 bpchar 10 60 NULL NULL 0 +mtr schema1 v1 a 1 bpchar 10 60 NULL NULL 1 DROP TABLE t1; # All tables "t1" in all schemas CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.%.t1'; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks mtr public t1 a 4 int4 10 4 0 10 0 -mtr schema1 t1 a 1 bpchar 10 60 0 0 0 +mtr schema1 t1 a 1 bpchar 10 60 NULL NULL 0 DROP TABLE t1; # Table "t1" in the schema "public" CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.public.t1'; @@ -131,14 +131,14 @@ DROP TABLE t1; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='%.schema1.t1'; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks -mtr schema1 t1 a 1 bpchar 10 60 0 0 0 +mtr schema1 t1 a 1 bpchar 10 60 NULL NULL 0 DROP TABLE t1; # All tables "t1" in all schemas (Catalog name is ignored by PostgreSQL) CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEnginePostgresql;UID=mtr;PWD=mtr' CATFUNC=Columns TABNAME='xxx.%.t1'; SELECT * FROM t1 ORDER BY Table_Schema, Table_Name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks mtr public t1 a 4 int4 10 4 0 10 0 -mtr schema1 t1 a 1 bpchar 10 60 0 0 0 +mtr schema1 t1 a 1 bpchar 10 60 NULL NULL 0 DROP TABLE t1; # # Checking tables diff --git a/storage/connect/mysql-test/connect/r/odbc_sqlite3.result b/storage/connect/mysql-test/connect/r/odbc_sqlite3.result index 24de417792d..bce69227073 100644 --- a/storage/connect/mysql-test/connect/r/odbc_sqlite3.result +++ b/storage/connect/mysql-test/connect/r/odbc_sqlite3.result @@ -1,7 +1,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `Description` char(128) NOT NULL, - `Attributes` varchar(256) NOT NULL + `Attributes` varchar(256) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers' SET NAMES utf8; CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8;; @@ -44,2420 +44,2420 @@ DROP TABLE t1; CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8; SELECT * FROM t1; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks - t1 a 12 varchar(64) 64 64 10 0 1 + t1 a 12 varchar(64) 64 64 10 0 1 NULL DROP TABLE t1; CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABNAME='t1' TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8; SELECT * FROM t1; Table_Cat Table_Schema Table_Name Table_Type Remark - t1 TABLE +NULL NULL t1 TABLE NULL DROP TABLE t1; CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8; SELECT * FROM t1 ORDER BY Table_name; Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks - t000 a 4 INT 9 10 10 0 1 - t000 b 4 INT 9 10 10 0 1 - t000 c 4 INT 9 10 10 0 1 - t000 d 4 INT 9 10 10 0 1 - t000 e 4 INT 9 10 10 0 1 - t001 a 4 INT 9 10 10 0 1 - t001 b 4 INT 9 10 10 0 1 - t001 c 4 INT 9 10 10 0 1 - t001 d 4 INT 9 10 10 0 1 - t001 e 4 INT 9 10 10 0 1 - t002 a 4 INT 9 10 10 0 1 - t002 b 4 INT 9 10 10 0 1 - t002 c 4 INT 9 10 10 0 1 - t002 d 4 INT 9 10 10 0 1 - t002 e 4 INT 9 10 10 0 1 - t003 a 4 INT 9 10 10 0 1 - t003 b 4 INT 9 10 10 0 1 - t003 c 4 INT 9 10 10 0 1 - t003 d 4 INT 9 10 10 0 1 - t003 e 4 INT 9 10 10 0 1 - t004 a 4 INT 9 10 10 0 1 - t004 b 4 INT 9 10 10 0 1 - t004 c 4 INT 9 10 10 0 1 - t004 d 4 INT 9 10 10 0 1 - t004 e 4 INT 9 10 10 0 1 - t005 a 4 INT 9 10 10 0 1 - t005 b 4 INT 9 10 10 0 1 - t005 c 4 INT 9 10 10 0 1 - t005 d 4 INT 9 10 10 0 1 - t005 e 4 INT 9 10 10 0 1 - t006 a 4 INT 9 10 10 0 1 - t006 b 4 INT 9 10 10 0 1 - t006 c 4 INT 9 10 10 0 1 - t006 d 4 INT 9 10 10 0 1 - t006 e 4 INT 9 10 10 0 1 - t007 a 4 INT 9 10 10 0 1 - t007 b 4 INT 9 10 10 0 1 - t007 c 4 INT 9 10 10 0 1 - t007 d 4 INT 9 10 10 0 1 - t007 e 4 INT 9 10 10 0 1 - t008 a 4 INT 9 10 10 0 1 - t008 b 4 INT 9 10 10 0 1 - t008 c 4 INT 9 10 10 0 1 - t008 d 4 INT 9 10 10 0 1 - t008 e 4 INT 9 10 10 0 1 - t009 a 4 INT 9 10 10 0 1 - t009 b 4 INT 9 10 10 0 1 - t009 c 4 INT 9 10 10 0 1 - t009 d 4 INT 9 10 10 0 1 - t009 e 4 INT 9 10 10 0 1 - t010 a 4 INT 9 10 10 0 1 - t010 b 4 INT 9 10 10 0 1 - t010 c 4 INT 9 10 10 0 1 - t010 d 4 INT 9 10 10 0 1 - t010 e 4 INT 9 10 10 0 1 - t011 a 4 INT 9 10 10 0 1 - t011 b 4 INT 9 10 10 0 1 - t011 c 4 INT 9 10 10 0 1 - t011 d 4 INT 9 10 10 0 1 - t011 e 4 INT 9 10 10 0 1 - t012 a 4 INT 9 10 10 0 1 - t012 b 4 INT 9 10 10 0 1 - t012 c 4 INT 9 10 10 0 1 - t012 d 4 INT 9 10 10 0 1 - t012 e 4 INT 9 10 10 0 1 - t013 a 4 INT 9 10 10 0 1 - t013 b 4 INT 9 10 10 0 1 - t013 c 4 INT 9 10 10 0 1 - t013 d 4 INT 9 10 10 0 1 - t013 e 4 INT 9 10 10 0 1 - t014 a 4 INT 9 10 10 0 1 - t014 b 4 INT 9 10 10 0 1 - t014 c 4 INT 9 10 10 0 1 - t014 d 4 INT 9 10 10 0 1 - t014 e 4 INT 9 10 10 0 1 - t015 a 4 INT 9 10 10 0 1 - t015 b 4 INT 9 10 10 0 1 - t015 c 4 INT 9 10 10 0 1 - t015 d 4 INT 9 10 10 0 1 - t015 e 4 INT 9 10 10 0 1 - t016 a 4 INT 9 10 10 0 1 - t016 b 4 INT 9 10 10 0 1 - t016 c 4 INT 9 10 10 0 1 - t016 d 4 INT 9 10 10 0 1 - t016 e 4 INT 9 10 10 0 1 - t017 a 4 INT 9 10 10 0 1 - t017 b 4 INT 9 10 10 0 1 - t017 c 4 INT 9 10 10 0 1 - t017 d 4 INT 9 10 10 0 1 - t017 e 4 INT 9 10 10 0 1 - t018 a 4 INT 9 10 10 0 1 - t018 b 4 INT 9 10 10 0 1 - t018 c 4 INT 9 10 10 0 1 - t018 d 4 INT 9 10 10 0 1 - t018 e 4 INT 9 10 10 0 1 - t019 a 4 INT 9 10 10 0 1 - t019 b 4 INT 9 10 10 0 1 - t019 c 4 INT 9 10 10 0 1 - t019 d 4 INT 9 10 10 0 1 - t019 e 4 INT 9 10 10 0 1 - t020 a 4 INT 9 10 10 0 1 - t020 b 4 INT 9 10 10 0 1 - t020 c 4 INT 9 10 10 0 1 - t020 d 4 INT 9 10 10 0 1 - t020 e 4 INT 9 10 10 0 1 - t021 a 4 INT 9 10 10 0 1 - t021 b 4 INT 9 10 10 0 1 - t021 c 4 INT 9 10 10 0 1 - t021 d 4 INT 9 10 10 0 1 - t021 e 4 INT 9 10 10 0 1 - t022 a 4 INT 9 10 10 0 1 - t022 b 4 INT 9 10 10 0 1 - t022 c 4 INT 9 10 10 0 1 - t022 d 4 INT 9 10 10 0 1 - t022 e 4 INT 9 10 10 0 1 - t023 a 4 INT 9 10 10 0 1 - t023 b 4 INT 9 10 10 0 1 - t023 c 4 INT 9 10 10 0 1 - t023 d 4 INT 9 10 10 0 1 - t023 e 4 INT 9 10 10 0 1 - t024 a 4 INT 9 10 10 0 1 - t024 b 4 INT 9 10 10 0 1 - t024 c 4 INT 9 10 10 0 1 - t024 d 4 INT 9 10 10 0 1 - t024 e 4 INT 9 10 10 0 1 - t025 a 4 INT 9 10 10 0 1 - t025 b 4 INT 9 10 10 0 1 - t025 c 4 INT 9 10 10 0 1 - t025 d 4 INT 9 10 10 0 1 - t025 e 4 INT 9 10 10 0 1 - t026 a 4 INT 9 10 10 0 1 - t026 b 4 INT 9 10 10 0 1 - t026 c 4 INT 9 10 10 0 1 - t026 d 4 INT 9 10 10 0 1 - t026 e 4 INT 9 10 10 0 1 - t027 a 4 INT 9 10 10 0 1 - t027 b 4 INT 9 10 10 0 1 - t027 c 4 INT 9 10 10 0 1 - t027 d 4 INT 9 10 10 0 1 - t027 e 4 INT 9 10 10 0 1 - t028 a 4 INT 9 10 10 0 1 - t028 b 4 INT 9 10 10 0 1 - t028 c 4 INT 9 10 10 0 1 - t028 d 4 INT 9 10 10 0 1 - t028 e 4 INT 9 10 10 0 1 - t029 a 4 INT 9 10 10 0 1 - t029 b 4 INT 9 10 10 0 1 - t029 c 4 INT 9 10 10 0 1 - t029 d 4 INT 9 10 10 0 1 - t029 e 4 INT 9 10 10 0 1 - t030 a 4 INT 9 10 10 0 1 - t030 b 4 INT 9 10 10 0 1 - t030 c 4 INT 9 10 10 0 1 - t030 d 4 INT 9 10 10 0 1 - t030 e 4 INT 9 10 10 0 1 - t031 a 4 INT 9 10 10 0 1 - t031 b 4 INT 9 10 10 0 1 - t031 c 4 INT 9 10 10 0 1 - t031 d 4 INT 9 10 10 0 1 - t031 e 4 INT 9 10 10 0 1 - t032 a 4 INT 9 10 10 0 1 - t032 b 4 INT 9 10 10 0 1 - t032 c 4 INT 9 10 10 0 1 - t032 d 4 INT 9 10 10 0 1 - t032 e 4 INT 9 10 10 0 1 - t033 a 4 INT 9 10 10 0 1 - t033 b 4 INT 9 10 10 0 1 - t033 c 4 INT 9 10 10 0 1 - t033 d 4 INT 9 10 10 0 1 - t033 e 4 INT 9 10 10 0 1 - t034 a 4 INT 9 10 10 0 1 - t034 b 4 INT 9 10 10 0 1 - t034 c 4 INT 9 10 10 0 1 - t034 d 4 INT 9 10 10 0 1 - t034 e 4 INT 9 10 10 0 1 - t035 a 4 INT 9 10 10 0 1 - t035 b 4 INT 9 10 10 0 1 - t035 c 4 INT 9 10 10 0 1 - t035 d 4 INT 9 10 10 0 1 - t035 e 4 INT 9 10 10 0 1 - t036 a 4 INT 9 10 10 0 1 - t036 b 4 INT 9 10 10 0 1 - t036 c 4 INT 9 10 10 0 1 - t036 d 4 INT 9 10 10 0 1 - t036 e 4 INT 9 10 10 0 1 - t037 a 4 INT 9 10 10 0 1 - t037 b 4 INT 9 10 10 0 1 - t037 c 4 INT 9 10 10 0 1 - t037 d 4 INT 9 10 10 0 1 - t037 e 4 INT 9 10 10 0 1 - t038 a 4 INT 9 10 10 0 1 - t038 b 4 INT 9 10 10 0 1 - t038 c 4 INT 9 10 10 0 1 - t038 d 4 INT 9 10 10 0 1 - t038 e 4 INT 9 10 10 0 1 - t039 a 4 INT 9 10 10 0 1 - t039 b 4 INT 9 10 10 0 1 - t039 c 4 INT 9 10 10 0 1 - t039 d 4 INT 9 10 10 0 1 - t039 e 4 INT 9 10 10 0 1 - t040 a 4 INT 9 10 10 0 1 - t040 b 4 INT 9 10 10 0 1 - t040 c 4 INT 9 10 10 0 1 - t040 d 4 INT 9 10 10 0 1 - t040 e 4 INT 9 10 10 0 1 - t041 a 4 INT 9 10 10 0 1 - t041 b 4 INT 9 10 10 0 1 - t041 c 4 INT 9 10 10 0 1 - t041 d 4 INT 9 10 10 0 1 - t041 e 4 INT 9 10 10 0 1 - t042 a 4 INT 9 10 10 0 1 - t042 b 4 INT 9 10 10 0 1 - t042 c 4 INT 9 10 10 0 1 - t042 d 4 INT 9 10 10 0 1 - t042 e 4 INT 9 10 10 0 1 - t043 a 4 INT 9 10 10 0 1 - t043 b 4 INT 9 10 10 0 1 - t043 c 4 INT 9 10 10 0 1 - t043 d 4 INT 9 10 10 0 1 - t043 e 4 INT 9 10 10 0 1 - t044 a 4 INT 9 10 10 0 1 - t044 b 4 INT 9 10 10 0 1 - t044 c 4 INT 9 10 10 0 1 - t044 d 4 INT 9 10 10 0 1 - t044 e 4 INT 9 10 10 0 1 - t045 a 4 INT 9 10 10 0 1 - t045 b 4 INT 9 10 10 0 1 - t045 c 4 INT 9 10 10 0 1 - t045 d 4 INT 9 10 10 0 1 - t045 e 4 INT 9 10 10 0 1 - t046 a 4 INT 9 10 10 0 1 - t046 b 4 INT 9 10 10 0 1 - t046 c 4 INT 9 10 10 0 1 - t046 d 4 INT 9 10 10 0 1 - t046 e 4 INT 9 10 10 0 1 - t047 a 4 INT 9 10 10 0 1 - t047 b 4 INT 9 10 10 0 1 - t047 c 4 INT 9 10 10 0 1 - t047 d 4 INT 9 10 10 0 1 - t047 e 4 INT 9 10 10 0 1 - t048 a 4 INT 9 10 10 0 1 - t048 b 4 INT 9 10 10 0 1 - t048 c 4 INT 9 10 10 0 1 - t048 d 4 INT 9 10 10 0 1 - t048 e 4 INT 9 10 10 0 1 - t049 a 4 INT 9 10 10 0 1 - t049 b 4 INT 9 10 10 0 1 - t049 c 4 INT 9 10 10 0 1 - t049 d 4 INT 9 10 10 0 1 - t049 e 4 INT 9 10 10 0 1 - t050 a 4 INT 9 10 10 0 1 - t050 b 4 INT 9 10 10 0 1 - t050 c 4 INT 9 10 10 0 1 - t050 d 4 INT 9 10 10 0 1 - t050 e 4 INT 9 10 10 0 1 - t051 a 4 INT 9 10 10 0 1 - t051 b 4 INT 9 10 10 0 1 - t051 c 4 INT 9 10 10 0 1 - t051 d 4 INT 9 10 10 0 1 - t051 e 4 INT 9 10 10 0 1 - t052 a 4 INT 9 10 10 0 1 - t052 b 4 INT 9 10 10 0 1 - t052 c 4 INT 9 10 10 0 1 - t052 d 4 INT 9 10 10 0 1 - t052 e 4 INT 9 10 10 0 1 - t053 a 4 INT 9 10 10 0 1 - t053 b 4 INT 9 10 10 0 1 - t053 c 4 INT 9 10 10 0 1 - t053 d 4 INT 9 10 10 0 1 - t053 e 4 INT 9 10 10 0 1 - t054 a 4 INT 9 10 10 0 1 - t054 b 4 INT 9 10 10 0 1 - t054 c 4 INT 9 10 10 0 1 - t054 d 4 INT 9 10 10 0 1 - t054 e 4 INT 9 10 10 0 1 - t055 a 4 INT 9 10 10 0 1 - t055 b 4 INT 9 10 10 0 1 - t055 c 4 INT 9 10 10 0 1 - t055 d 4 INT 9 10 10 0 1 - t055 e 4 INT 9 10 10 0 1 - t056 a 4 INT 9 10 10 0 1 - t056 b 4 INT 9 10 10 0 1 - t056 c 4 INT 9 10 10 0 1 - t056 d 4 INT 9 10 10 0 1 - t056 e 4 INT 9 10 10 0 1 - t057 a 4 INT 9 10 10 0 1 - t057 b 4 INT 9 10 10 0 1 - t057 c 4 INT 9 10 10 0 1 - t057 d 4 INT 9 10 10 0 1 - t057 e 4 INT 9 10 10 0 1 - t058 a 4 INT 9 10 10 0 1 - t058 b 4 INT 9 10 10 0 1 - t058 c 4 INT 9 10 10 0 1 - t058 d 4 INT 9 10 10 0 1 - t058 e 4 INT 9 10 10 0 1 - t059 a 4 INT 9 10 10 0 1 - t059 b 4 INT 9 10 10 0 1 - t059 c 4 INT 9 10 10 0 1 - t059 d 4 INT 9 10 10 0 1 - t059 e 4 INT 9 10 10 0 1 - t060 a 4 INT 9 10 10 0 1 - t060 b 4 INT 9 10 10 0 1 - t060 c 4 INT 9 10 10 0 1 - t060 d 4 INT 9 10 10 0 1 - t060 e 4 INT 9 10 10 0 1 - t061 a 4 INT 9 10 10 0 1 - t061 b 4 INT 9 10 10 0 1 - t061 c 4 INT 9 10 10 0 1 - t061 d 4 INT 9 10 10 0 1 - t061 e 4 INT 9 10 10 0 1 - t062 a 4 INT 9 10 10 0 1 - t062 b 4 INT 9 10 10 0 1 - t062 c 4 INT 9 10 10 0 1 - t062 d 4 INT 9 10 10 0 1 - t062 e 4 INT 9 10 10 0 1 - t063 a 4 INT 9 10 10 0 1 - t063 b 4 INT 9 10 10 0 1 - t063 c 4 INT 9 10 10 0 1 - t063 d 4 INT 9 10 10 0 1 - t063 e 4 INT 9 10 10 0 1 - t064 a 4 INT 9 10 10 0 1 - t064 b 4 INT 9 10 10 0 1 - t064 c 4 INT 9 10 10 0 1 - t064 d 4 INT 9 10 10 0 1 - t064 e 4 INT 9 10 10 0 1 - t065 a 4 INT 9 10 10 0 1 - t065 b 4 INT 9 10 10 0 1 - t065 c 4 INT 9 10 10 0 1 - t065 d 4 INT 9 10 10 0 1 - t065 e 4 INT 9 10 10 0 1 - t066 a 4 INT 9 10 10 0 1 - t066 b 4 INT 9 10 10 0 1 - t066 c 4 INT 9 10 10 0 1 - t066 d 4 INT 9 10 10 0 1 - t066 e 4 INT 9 10 10 0 1 - t067 a 4 INT 9 10 10 0 1 - t067 b 4 INT 9 10 10 0 1 - t067 c 4 INT 9 10 10 0 1 - t067 d 4 INT 9 10 10 0 1 - t067 e 4 INT 9 10 10 0 1 - t068 a 4 INT 9 10 10 0 1 - t068 b 4 INT 9 10 10 0 1 - t068 c 4 INT 9 10 10 0 1 - t068 d 4 INT 9 10 10 0 1 - t068 e 4 INT 9 10 10 0 1 - t069 a 4 INT 9 10 10 0 1 - t069 b 4 INT 9 10 10 0 1 - t069 c 4 INT 9 10 10 0 1 - t069 d 4 INT 9 10 10 0 1 - t069 e 4 INT 9 10 10 0 1 - t070 a 4 INT 9 10 10 0 1 - t070 b 4 INT 9 10 10 0 1 - t070 c 4 INT 9 10 10 0 1 - t070 d 4 INT 9 10 10 0 1 - t070 e 4 INT 9 10 10 0 1 - t071 a 4 INT 9 10 10 0 1 - t071 b 4 INT 9 10 10 0 1 - t071 c 4 INT 9 10 10 0 1 - t071 d 4 INT 9 10 10 0 1 - t071 e 4 INT 9 10 10 0 1 - t072 a 4 INT 9 10 10 0 1 - t072 b 4 INT 9 10 10 0 1 - t072 c 4 INT 9 10 10 0 1 - t072 d 4 INT 9 10 10 0 1 - t072 e 4 INT 9 10 10 0 1 - t073 a 4 INT 9 10 10 0 1 - t073 b 4 INT 9 10 10 0 1 - t073 c 4 INT 9 10 10 0 1 - t073 d 4 INT 9 10 10 0 1 - t073 e 4 INT 9 10 10 0 1 - t074 a 4 INT 9 10 10 0 1 - t074 b 4 INT 9 10 10 0 1 - t074 c 4 INT 9 10 10 0 1 - t074 d 4 INT 9 10 10 0 1 - t074 e 4 INT 9 10 10 0 1 - t075 a 4 INT 9 10 10 0 1 - t075 b 4 INT 9 10 10 0 1 - t075 c 4 INT 9 10 10 0 1 - t075 d 4 INT 9 10 10 0 1 - t075 e 4 INT 9 10 10 0 1 - t076 a 4 INT 9 10 10 0 1 - t076 b 4 INT 9 10 10 0 1 - t076 c 4 INT 9 10 10 0 1 - t076 d 4 INT 9 10 10 0 1 - t076 e 4 INT 9 10 10 0 1 - t077 a 4 INT 9 10 10 0 1 - t077 b 4 INT 9 10 10 0 1 - t077 c 4 INT 9 10 10 0 1 - t077 d 4 INT 9 10 10 0 1 - t077 e 4 INT 9 10 10 0 1 - t078 a 4 INT 9 10 10 0 1 - t078 b 4 INT 9 10 10 0 1 - t078 c 4 INT 9 10 10 0 1 - t078 d 4 INT 9 10 10 0 1 - t078 e 4 INT 9 10 10 0 1 - t079 a 4 INT 9 10 10 0 1 - t079 b 4 INT 9 10 10 0 1 - t079 c 4 INT 9 10 10 0 1 - t079 d 4 INT 9 10 10 0 1 - t079 e 4 INT 9 10 10 0 1 - t080 a 4 INT 9 10 10 0 1 - t080 b 4 INT 9 10 10 0 1 - t080 c 4 INT 9 10 10 0 1 - t080 d 4 INT 9 10 10 0 1 - t080 e 4 INT 9 10 10 0 1 - t081 a 4 INT 9 10 10 0 1 - t081 b 4 INT 9 10 10 0 1 - t081 c 4 INT 9 10 10 0 1 - t081 d 4 INT 9 10 10 0 1 - t081 e 4 INT 9 10 10 0 1 - t082 a 4 INT 9 10 10 0 1 - t082 b 4 INT 9 10 10 0 1 - t082 c 4 INT 9 10 10 0 1 - t082 d 4 INT 9 10 10 0 1 - t082 e 4 INT 9 10 10 0 1 - t083 a 4 INT 9 10 10 0 1 - t083 b 4 INT 9 10 10 0 1 - t083 c 4 INT 9 10 10 0 1 - t083 d 4 INT 9 10 10 0 1 - t083 e 4 INT 9 10 10 0 1 - t084 a 4 INT 9 10 10 0 1 - t084 b 4 INT 9 10 10 0 1 - t084 c 4 INT 9 10 10 0 1 - t084 d 4 INT 9 10 10 0 1 - t084 e 4 INT 9 10 10 0 1 - t085 a 4 INT 9 10 10 0 1 - t085 b 4 INT 9 10 10 0 1 - t085 c 4 INT 9 10 10 0 1 - t085 d 4 INT 9 10 10 0 1 - t085 e 4 INT 9 10 10 0 1 - t086 a 4 INT 9 10 10 0 1 - t086 b 4 INT 9 10 10 0 1 - t086 c 4 INT 9 10 10 0 1 - t086 d 4 INT 9 10 10 0 1 - t086 e 4 INT 9 10 10 0 1 - t087 a 4 INT 9 10 10 0 1 - t087 b 4 INT 9 10 10 0 1 - t087 c 4 INT 9 10 10 0 1 - t087 d 4 INT 9 10 10 0 1 - t087 e 4 INT 9 10 10 0 1 - t088 a 4 INT 9 10 10 0 1 - t088 b 4 INT 9 10 10 0 1 - t088 c 4 INT 9 10 10 0 1 - t088 d 4 INT 9 10 10 0 1 - t088 e 4 INT 9 10 10 0 1 - t089 a 4 INT 9 10 10 0 1 - t089 b 4 INT 9 10 10 0 1 - t089 c 4 INT 9 10 10 0 1 - t089 d 4 INT 9 10 10 0 1 - t089 e 4 INT 9 10 10 0 1 - t090 a 4 INT 9 10 10 0 1 - t090 b 4 INT 9 10 10 0 1 - t090 c 4 INT 9 10 10 0 1 - t090 d 4 INT 9 10 10 0 1 - t090 e 4 INT 9 10 10 0 1 - t091 a 4 INT 9 10 10 0 1 - t091 b 4 INT 9 10 10 0 1 - t091 c 4 INT 9 10 10 0 1 - t091 d 4 INT 9 10 10 0 1 - t091 e 4 INT 9 10 10 0 1 - t092 a 4 INT 9 10 10 0 1 - t092 b 4 INT 9 10 10 0 1 - t092 c 4 INT 9 10 10 0 1 - t092 d 4 INT 9 10 10 0 1 - t092 e 4 INT 9 10 10 0 1 - t093 a 4 INT 9 10 10 0 1 - t093 b 4 INT 9 10 10 0 1 - t093 c 4 INT 9 10 10 0 1 - t093 d 4 INT 9 10 10 0 1 - t093 e 4 INT 9 10 10 0 1 - t094 a 4 INT 9 10 10 0 1 - t094 b 4 INT 9 10 10 0 1 - t094 c 4 INT 9 10 10 0 1 - t094 d 4 INT 9 10 10 0 1 - t094 e 4 INT 9 10 10 0 1 - t095 a 4 INT 9 10 10 0 1 - t095 b 4 INT 9 10 10 0 1 - t095 c 4 INT 9 10 10 0 1 - t095 d 4 INT 9 10 10 0 1 - t095 e 4 INT 9 10 10 0 1 - t096 a 4 INT 9 10 10 0 1 - t096 b 4 INT 9 10 10 0 1 - t096 c 4 INT 9 10 10 0 1 - t096 d 4 INT 9 10 10 0 1 - t096 e 4 INT 9 10 10 0 1 - t097 a 4 INT 9 10 10 0 1 - t097 b 4 INT 9 10 10 0 1 - t097 c 4 INT 9 10 10 0 1 - t097 d 4 INT 9 10 10 0 1 - t097 e 4 INT 9 10 10 0 1 - t098 a 4 INT 9 10 10 0 1 - t098 b 4 INT 9 10 10 0 1 - t098 c 4 INT 9 10 10 0 1 - t098 d 4 INT 9 10 10 0 1 - t098 e 4 INT 9 10 10 0 1 - t099 a 4 INT 9 10 10 0 1 - t099 b 4 INT 9 10 10 0 1 - t099 c 4 INT 9 10 10 0 1 - t099 d 4 INT 9 10 10 0 1 - t099 e 4 INT 9 10 10 0 1 - t1 a 12 varchar(64) 64 64 10 0 1 - t100 a 4 INT 9 10 10 0 1 - t100 b 4 INT 9 10 10 0 1 - t100 c 4 INT 9 10 10 0 1 - t100 d 4 INT 9 10 10 0 1 - t100 e 4 INT 9 10 10 0 1 - t101 a 4 INT 9 10 10 0 1 - t101 b 4 INT 9 10 10 0 1 - t101 c 4 INT 9 10 10 0 1 - t101 d 4 INT 9 10 10 0 1 - t101 e 4 INT 9 10 10 0 1 - t102 a 4 INT 9 10 10 0 1 - t102 b 4 INT 9 10 10 0 1 - t102 c 4 INT 9 10 10 0 1 - t102 d 4 INT 9 10 10 0 1 - t102 e 4 INT 9 10 10 0 1 - t103 a 4 INT 9 10 10 0 1 - t103 b 4 INT 9 10 10 0 1 - t103 c 4 INT 9 10 10 0 1 - t103 d 4 INT 9 10 10 0 1 - t103 e 4 INT 9 10 10 0 1 - t104 a 4 INT 9 10 10 0 1 - t104 b 4 INT 9 10 10 0 1 - t104 c 4 INT 9 10 10 0 1 - t104 d 4 INT 9 10 10 0 1 - t104 e 4 INT 9 10 10 0 1 - t105 a 4 INT 9 10 10 0 1 - t105 b 4 INT 9 10 10 0 1 - t105 c 4 INT 9 10 10 0 1 - t105 d 4 INT 9 10 10 0 1 - t105 e 4 INT 9 10 10 0 1 - t106 a 4 INT 9 10 10 0 1 - t106 b 4 INT 9 10 10 0 1 - t106 c 4 INT 9 10 10 0 1 - t106 d 4 INT 9 10 10 0 1 - t106 e 4 INT 9 10 10 0 1 - t107 a 4 INT 9 10 10 0 1 - t107 b 4 INT 9 10 10 0 1 - t107 c 4 INT 9 10 10 0 1 - t107 d 4 INT 9 10 10 0 1 - t107 e 4 INT 9 10 10 0 1 - t108 a 4 INT 9 10 10 0 1 - t108 b 4 INT 9 10 10 0 1 - t108 c 4 INT 9 10 10 0 1 - t108 d 4 INT 9 10 10 0 1 - t108 e 4 INT 9 10 10 0 1 - t109 a 4 INT 9 10 10 0 1 - t109 b 4 INT 9 10 10 0 1 - t109 c 4 INT 9 10 10 0 1 - t109 d 4 INT 9 10 10 0 1 - t109 e 4 INT 9 10 10 0 1 - t110 a 4 INT 9 10 10 0 1 - t110 b 4 INT 9 10 10 0 1 - t110 c 4 INT 9 10 10 0 1 - t110 d 4 INT 9 10 10 0 1 - t110 e 4 INT 9 10 10 0 1 - t111 a 4 INT 9 10 10 0 1 - t111 b 4 INT 9 10 10 0 1 - t111 c 4 INT 9 10 10 0 1 - t111 d 4 INT 9 10 10 0 1 - t111 e 4 INT 9 10 10 0 1 - t112 a 4 INT 9 10 10 0 1 - t112 b 4 INT 9 10 10 0 1 - t112 c 4 INT 9 10 10 0 1 - t112 d 4 INT 9 10 10 0 1 - t112 e 4 INT 9 10 10 0 1 - t113 a 4 INT 9 10 10 0 1 - t113 b 4 INT 9 10 10 0 1 - t113 c 4 INT 9 10 10 0 1 - t113 d 4 INT 9 10 10 0 1 - t113 e 4 INT 9 10 10 0 1 - t114 a 4 INT 9 10 10 0 1 - t114 b 4 INT 9 10 10 0 1 - t114 c 4 INT 9 10 10 0 1 - t114 d 4 INT 9 10 10 0 1 - t114 e 4 INT 9 10 10 0 1 - t115 a 4 INT 9 10 10 0 1 - t115 b 4 INT 9 10 10 0 1 - t115 c 4 INT 9 10 10 0 1 - t115 d 4 INT 9 10 10 0 1 - t115 e 4 INT 9 10 10 0 1 - t116 a 4 INT 9 10 10 0 1 - t116 b 4 INT 9 10 10 0 1 - t116 c 4 INT 9 10 10 0 1 - t116 d 4 INT 9 10 10 0 1 - t116 e 4 INT 9 10 10 0 1 - t117 a 4 INT 9 10 10 0 1 - t117 b 4 INT 9 10 10 0 1 - t117 c 4 INT 9 10 10 0 1 - t117 d 4 INT 9 10 10 0 1 - t117 e 4 INT 9 10 10 0 1 - t118 a 4 INT 9 10 10 0 1 - t118 b 4 INT 9 10 10 0 1 - t118 c 4 INT 9 10 10 0 1 - t118 d 4 INT 9 10 10 0 1 - t118 e 4 INT 9 10 10 0 1 - t119 a 4 INT 9 10 10 0 1 - t119 b 4 INT 9 10 10 0 1 - t119 c 4 INT 9 10 10 0 1 - t119 d 4 INT 9 10 10 0 1 - t119 e 4 INT 9 10 10 0 1 - t120 a 4 INT 9 10 10 0 1 - t120 b 4 INT 9 10 10 0 1 - t120 c 4 INT 9 10 10 0 1 - t120 d 4 INT 9 10 10 0 1 - t120 e 4 INT 9 10 10 0 1 - t121 a 4 INT 9 10 10 0 1 - t121 b 4 INT 9 10 10 0 1 - t121 c 4 INT 9 10 10 0 1 - t121 d 4 INT 9 10 10 0 1 - t121 e 4 INT 9 10 10 0 1 - t122 a 4 INT 9 10 10 0 1 - t122 b 4 INT 9 10 10 0 1 - t122 c 4 INT 9 10 10 0 1 - t122 d 4 INT 9 10 10 0 1 - t122 e 4 INT 9 10 10 0 1 - t123 a 4 INT 9 10 10 0 1 - t123 b 4 INT 9 10 10 0 1 - t123 c 4 INT 9 10 10 0 1 - t123 d 4 INT 9 10 10 0 1 - t123 e 4 INT 9 10 10 0 1 - t124 a 4 INT 9 10 10 0 1 - t124 b 4 INT 9 10 10 0 1 - t124 c 4 INT 9 10 10 0 1 - t124 d 4 INT 9 10 10 0 1 - t124 e 4 INT 9 10 10 0 1 - t125 a 4 INT 9 10 10 0 1 - t125 b 4 INT 9 10 10 0 1 - t125 c 4 INT 9 10 10 0 1 - t125 d 4 INT 9 10 10 0 1 - t125 e 4 INT 9 10 10 0 1 - t126 a 4 INT 9 10 10 0 1 - t126 b 4 INT 9 10 10 0 1 - t126 c 4 INT 9 10 10 0 1 - t126 d 4 INT 9 10 10 0 1 - t126 e 4 INT 9 10 10 0 1 - t127 a 4 INT 9 10 10 0 1 - t127 b 4 INT 9 10 10 0 1 - t127 c 4 INT 9 10 10 0 1 - t127 d 4 INT 9 10 10 0 1 - t127 e 4 INT 9 10 10 0 1 - t128 a 4 INT 9 10 10 0 1 - t128 b 4 INT 9 10 10 0 1 - t128 c 4 INT 9 10 10 0 1 - t128 d 4 INT 9 10 10 0 1 - t128 e 4 INT 9 10 10 0 1 - t129 a 4 INT 9 10 10 0 1 - t129 b 4 INT 9 10 10 0 1 - t129 c 4 INT 9 10 10 0 1 - t129 d 4 INT 9 10 10 0 1 - t129 e 4 INT 9 10 10 0 1 - t130 a 4 INT 9 10 10 0 1 - t130 b 4 INT 9 10 10 0 1 - t130 c 4 INT 9 10 10 0 1 - t130 d 4 INT 9 10 10 0 1 - t130 e 4 INT 9 10 10 0 1 - t131 a 4 INT 9 10 10 0 1 - t131 b 4 INT 9 10 10 0 1 - t131 c 4 INT 9 10 10 0 1 - t131 d 4 INT 9 10 10 0 1 - t131 e 4 INT 9 10 10 0 1 - t132 a 4 INT 9 10 10 0 1 - t132 b 4 INT 9 10 10 0 1 - t132 c 4 INT 9 10 10 0 1 - t132 d 4 INT 9 10 10 0 1 - t132 e 4 INT 9 10 10 0 1 - t133 a 4 INT 9 10 10 0 1 - t133 b 4 INT 9 10 10 0 1 - t133 c 4 INT 9 10 10 0 1 - t133 d 4 INT 9 10 10 0 1 - t133 e 4 INT 9 10 10 0 1 - t134 a 4 INT 9 10 10 0 1 - t134 b 4 INT 9 10 10 0 1 - t134 c 4 INT 9 10 10 0 1 - t134 d 4 INT 9 10 10 0 1 - t134 e 4 INT 9 10 10 0 1 - t135 a 4 INT 9 10 10 0 1 - t135 b 4 INT 9 10 10 0 1 - t135 c 4 INT 9 10 10 0 1 - t135 d 4 INT 9 10 10 0 1 - t135 e 4 INT 9 10 10 0 1 - t136 a 4 INT 9 10 10 0 1 - t136 b 4 INT 9 10 10 0 1 - t136 c 4 INT 9 10 10 0 1 - t136 d 4 INT 9 10 10 0 1 - t136 e 4 INT 9 10 10 0 1 - t137 a 4 INT 9 10 10 0 1 - t137 b 4 INT 9 10 10 0 1 - t137 c 4 INT 9 10 10 0 1 - t137 d 4 INT 9 10 10 0 1 - t137 e 4 INT 9 10 10 0 1 - t138 a 4 INT 9 10 10 0 1 - t138 b 4 INT 9 10 10 0 1 - t138 c 4 INT 9 10 10 0 1 - t138 d 4 INT 9 10 10 0 1 - t138 e 4 INT 9 10 10 0 1 - t139 a 4 INT 9 10 10 0 1 - t139 b 4 INT 9 10 10 0 1 - t139 c 4 INT 9 10 10 0 1 - t139 d 4 INT 9 10 10 0 1 - t139 e 4 INT 9 10 10 0 1 - t140 a 4 INT 9 10 10 0 1 - t140 b 4 INT 9 10 10 0 1 - t140 c 4 INT 9 10 10 0 1 - t140 d 4 INT 9 10 10 0 1 - t140 e 4 INT 9 10 10 0 1 - t141 a 4 INT 9 10 10 0 1 - t141 b 4 INT 9 10 10 0 1 - t141 c 4 INT 9 10 10 0 1 - t141 d 4 INT 9 10 10 0 1 - t141 e 4 INT 9 10 10 0 1 - t142 a 4 INT 9 10 10 0 1 - t142 b 4 INT 9 10 10 0 1 - t142 c 4 INT 9 10 10 0 1 - t142 d 4 INT 9 10 10 0 1 - t142 e 4 INT 9 10 10 0 1 - t143 a 4 INT 9 10 10 0 1 - t143 b 4 INT 9 10 10 0 1 - t143 c 4 INT 9 10 10 0 1 - t143 d 4 INT 9 10 10 0 1 - t143 e 4 INT 9 10 10 0 1 - t144 a 4 INT 9 10 10 0 1 - t144 b 4 INT 9 10 10 0 1 - t144 c 4 INT 9 10 10 0 1 - t144 d 4 INT 9 10 10 0 1 - t144 e 4 INT 9 10 10 0 1 - t145 a 4 INT 9 10 10 0 1 - t145 b 4 INT 9 10 10 0 1 - t145 c 4 INT 9 10 10 0 1 - t145 d 4 INT 9 10 10 0 1 - t145 e 4 INT 9 10 10 0 1 - t146 a 4 INT 9 10 10 0 1 - t146 b 4 INT 9 10 10 0 1 - t146 c 4 INT 9 10 10 0 1 - t146 d 4 INT 9 10 10 0 1 - t146 e 4 INT 9 10 10 0 1 - t147 a 4 INT 9 10 10 0 1 - t147 b 4 INT 9 10 10 0 1 - t147 c 4 INT 9 10 10 0 1 - t147 d 4 INT 9 10 10 0 1 - t147 e 4 INT 9 10 10 0 1 - t148 a 4 INT 9 10 10 0 1 - t148 b 4 INT 9 10 10 0 1 - t148 c 4 INT 9 10 10 0 1 - t148 d 4 INT 9 10 10 0 1 - t148 e 4 INT 9 10 10 0 1 - t149 a 4 INT 9 10 10 0 1 - t149 b 4 INT 9 10 10 0 1 - t149 c 4 INT 9 10 10 0 1 - t149 d 4 INT 9 10 10 0 1 - t149 e 4 INT 9 10 10 0 1 - t150 a 4 INT 9 10 10 0 1 - t150 b 4 INT 9 10 10 0 1 - t150 c 4 INT 9 10 10 0 1 - t150 d 4 INT 9 10 10 0 1 - t150 e 4 INT 9 10 10 0 1 - t151 a 4 INT 9 10 10 0 1 - t151 b 4 INT 9 10 10 0 1 - t151 c 4 INT 9 10 10 0 1 - t151 d 4 INT 9 10 10 0 1 - t151 e 4 INT 9 10 10 0 1 - t152 a 4 INT 9 10 10 0 1 - t152 b 4 INT 9 10 10 0 1 - t152 c 4 INT 9 10 10 0 1 - t152 d 4 INT 9 10 10 0 1 - t152 e 4 INT 9 10 10 0 1 - t153 a 4 INT 9 10 10 0 1 - t153 b 4 INT 9 10 10 0 1 - t153 c 4 INT 9 10 10 0 1 - t153 d 4 INT 9 10 10 0 1 - t153 e 4 INT 9 10 10 0 1 - t154 a 4 INT 9 10 10 0 1 - t154 b 4 INT 9 10 10 0 1 - t154 c 4 INT 9 10 10 0 1 - t154 d 4 INT 9 10 10 0 1 - t154 e 4 INT 9 10 10 0 1 - t155 a 4 INT 9 10 10 0 1 - t155 b 4 INT 9 10 10 0 1 - t155 c 4 INT 9 10 10 0 1 - t155 d 4 INT 9 10 10 0 1 - t155 e 4 INT 9 10 10 0 1 - t156 a 4 INT 9 10 10 0 1 - t156 b 4 INT 9 10 10 0 1 - t156 c 4 INT 9 10 10 0 1 - t156 d 4 INT 9 10 10 0 1 - t156 e 4 INT 9 10 10 0 1 - t157 a 4 INT 9 10 10 0 1 - t157 b 4 INT 9 10 10 0 1 - t157 c 4 INT 9 10 10 0 1 - t157 d 4 INT 9 10 10 0 1 - t157 e 4 INT 9 10 10 0 1 - t158 a 4 INT 9 10 10 0 1 - t158 b 4 INT 9 10 10 0 1 - t158 c 4 INT 9 10 10 0 1 - t158 d 4 INT 9 10 10 0 1 - t158 e 4 INT 9 10 10 0 1 - t159 a 4 INT 9 10 10 0 1 - t159 b 4 INT 9 10 10 0 1 - t159 c 4 INT 9 10 10 0 1 - t159 d 4 INT 9 10 10 0 1 - t159 e 4 INT 9 10 10 0 1 - t160 a 4 INT 9 10 10 0 1 - t160 b 4 INT 9 10 10 0 1 - t160 c 4 INT 9 10 10 0 1 - t160 d 4 INT 9 10 10 0 1 - t160 e 4 INT 9 10 10 0 1 - t161 a 4 INT 9 10 10 0 1 - t161 b 4 INT 9 10 10 0 1 - t161 c 4 INT 9 10 10 0 1 - t161 d 4 INT 9 10 10 0 1 - t161 e 4 INT 9 10 10 0 1 - t162 a 4 INT 9 10 10 0 1 - t162 b 4 INT 9 10 10 0 1 - t162 c 4 INT 9 10 10 0 1 - t162 d 4 INT 9 10 10 0 1 - t162 e 4 INT 9 10 10 0 1 - t163 a 4 INT 9 10 10 0 1 - t163 b 4 INT 9 10 10 0 1 - t163 c 4 INT 9 10 10 0 1 - t163 d 4 INT 9 10 10 0 1 - t163 e 4 INT 9 10 10 0 1 - t164 a 4 INT 9 10 10 0 1 - t164 b 4 INT 9 10 10 0 1 - t164 c 4 INT 9 10 10 0 1 - t164 d 4 INT 9 10 10 0 1 - t164 e 4 INT 9 10 10 0 1 - t165 a 4 INT 9 10 10 0 1 - t165 b 4 INT 9 10 10 0 1 - t165 c 4 INT 9 10 10 0 1 - t165 d 4 INT 9 10 10 0 1 - t165 e 4 INT 9 10 10 0 1 - t166 a 4 INT 9 10 10 0 1 - t166 b 4 INT 9 10 10 0 1 - t166 c 4 INT 9 10 10 0 1 - t166 d 4 INT 9 10 10 0 1 - t166 e 4 INT 9 10 10 0 1 - t167 a 4 INT 9 10 10 0 1 - t167 b 4 INT 9 10 10 0 1 - t167 c 4 INT 9 10 10 0 1 - t167 d 4 INT 9 10 10 0 1 - t167 e 4 INT 9 10 10 0 1 - t168 a 4 INT 9 10 10 0 1 - t168 b 4 INT 9 10 10 0 1 - t168 c 4 INT 9 10 10 0 1 - t168 d 4 INT 9 10 10 0 1 - t168 e 4 INT 9 10 10 0 1 - t169 a 4 INT 9 10 10 0 1 - t169 b 4 INT 9 10 10 0 1 - t169 c 4 INT 9 10 10 0 1 - t169 d 4 INT 9 10 10 0 1 - t169 e 4 INT 9 10 10 0 1 - t170 a 4 INT 9 10 10 0 1 - t170 b 4 INT 9 10 10 0 1 - t170 c 4 INT 9 10 10 0 1 - t170 d 4 INT 9 10 10 0 1 - t170 e 4 INT 9 10 10 0 1 - t171 a 4 INT 9 10 10 0 1 - t171 b 4 INT 9 10 10 0 1 - t171 c 4 INT 9 10 10 0 1 - t171 d 4 INT 9 10 10 0 1 - t171 e 4 INT 9 10 10 0 1 - t172 a 4 INT 9 10 10 0 1 - t172 b 4 INT 9 10 10 0 1 - t172 c 4 INT 9 10 10 0 1 - t172 d 4 INT 9 10 10 0 1 - t172 e 4 INT 9 10 10 0 1 - t173 a 4 INT 9 10 10 0 1 - t173 b 4 INT 9 10 10 0 1 - t173 c 4 INT 9 10 10 0 1 - t173 d 4 INT 9 10 10 0 1 - t173 e 4 INT 9 10 10 0 1 - t174 a 4 INT 9 10 10 0 1 - t174 b 4 INT 9 10 10 0 1 - t174 c 4 INT 9 10 10 0 1 - t174 d 4 INT 9 10 10 0 1 - t174 e 4 INT 9 10 10 0 1 - t175 a 4 INT 9 10 10 0 1 - t175 b 4 INT 9 10 10 0 1 - t175 c 4 INT 9 10 10 0 1 - t175 d 4 INT 9 10 10 0 1 - t175 e 4 INT 9 10 10 0 1 - t176 a 4 INT 9 10 10 0 1 - t176 b 4 INT 9 10 10 0 1 - t176 c 4 INT 9 10 10 0 1 - t176 d 4 INT 9 10 10 0 1 - t176 e 4 INT 9 10 10 0 1 - t177 a 4 INT 9 10 10 0 1 - t177 b 4 INT 9 10 10 0 1 - t177 c 4 INT 9 10 10 0 1 - t177 d 4 INT 9 10 10 0 1 - t177 e 4 INT 9 10 10 0 1 - t178 a 4 INT 9 10 10 0 1 - t178 b 4 INT 9 10 10 0 1 - t178 c 4 INT 9 10 10 0 1 - t178 d 4 INT 9 10 10 0 1 - t178 e 4 INT 9 10 10 0 1 - t179 a 4 INT 9 10 10 0 1 - t179 b 4 INT 9 10 10 0 1 - t179 c 4 INT 9 10 10 0 1 - t179 d 4 INT 9 10 10 0 1 - t179 e 4 INT 9 10 10 0 1 - t180 a 4 INT 9 10 10 0 1 - t180 b 4 INT 9 10 10 0 1 - t180 c 4 INT 9 10 10 0 1 - t180 d 4 INT 9 10 10 0 1 - t180 e 4 INT 9 10 10 0 1 - t181 a 4 INT 9 10 10 0 1 - t181 b 4 INT 9 10 10 0 1 - t181 c 4 INT 9 10 10 0 1 - t181 d 4 INT 9 10 10 0 1 - t181 e 4 INT 9 10 10 0 1 - t182 a 4 INT 9 10 10 0 1 - t182 b 4 INT 9 10 10 0 1 - t182 c 4 INT 9 10 10 0 1 - t182 d 4 INT 9 10 10 0 1 - t182 e 4 INT 9 10 10 0 1 - t183 a 4 INT 9 10 10 0 1 - t183 b 4 INT 9 10 10 0 1 - t183 c 4 INT 9 10 10 0 1 - t183 d 4 INT 9 10 10 0 1 - t183 e 4 INT 9 10 10 0 1 - t184 a 4 INT 9 10 10 0 1 - t184 b 4 INT 9 10 10 0 1 - t184 c 4 INT 9 10 10 0 1 - t184 d 4 INT 9 10 10 0 1 - t184 e 4 INT 9 10 10 0 1 - t185 a 4 INT 9 10 10 0 1 - t185 b 4 INT 9 10 10 0 1 - t185 c 4 INT 9 10 10 0 1 - t185 d 4 INT 9 10 10 0 1 - t185 e 4 INT 9 10 10 0 1 - t186 a 4 INT 9 10 10 0 1 - t186 b 4 INT 9 10 10 0 1 - t186 c 4 INT 9 10 10 0 1 - t186 d 4 INT 9 10 10 0 1 - t186 e 4 INT 9 10 10 0 1 - t187 a 4 INT 9 10 10 0 1 - t187 b 4 INT 9 10 10 0 1 - t187 c 4 INT 9 10 10 0 1 - t187 d 4 INT 9 10 10 0 1 - t187 e 4 INT 9 10 10 0 1 - t188 a 4 INT 9 10 10 0 1 - t188 b 4 INT 9 10 10 0 1 - t188 c 4 INT 9 10 10 0 1 - t188 d 4 INT 9 10 10 0 1 - t188 e 4 INT 9 10 10 0 1 - t189 a 4 INT 9 10 10 0 1 - t189 b 4 INT 9 10 10 0 1 - t189 c 4 INT 9 10 10 0 1 - t189 d 4 INT 9 10 10 0 1 - t189 e 4 INT 9 10 10 0 1 - t190 a 4 INT 9 10 10 0 1 - t190 b 4 INT 9 10 10 0 1 - t190 c 4 INT 9 10 10 0 1 - t190 d 4 INT 9 10 10 0 1 - t190 e 4 INT 9 10 10 0 1 - t191 a 4 INT 9 10 10 0 1 - t191 b 4 INT 9 10 10 0 1 - t191 c 4 INT 9 10 10 0 1 - t191 d 4 INT 9 10 10 0 1 - t191 e 4 INT 9 10 10 0 1 - t192 a 4 INT 9 10 10 0 1 - t192 b 4 INT 9 10 10 0 1 - t192 c 4 INT 9 10 10 0 1 - t192 d 4 INT 9 10 10 0 1 - t192 e 4 INT 9 10 10 0 1 - t193 a 4 INT 9 10 10 0 1 - t193 b 4 INT 9 10 10 0 1 - t193 c 4 INT 9 10 10 0 1 - t193 d 4 INT 9 10 10 0 1 - t193 e 4 INT 9 10 10 0 1 - t194 a 4 INT 9 10 10 0 1 - t194 b 4 INT 9 10 10 0 1 - t194 c 4 INT 9 10 10 0 1 - t194 d 4 INT 9 10 10 0 1 - t194 e 4 INT 9 10 10 0 1 - t195 a 4 INT 9 10 10 0 1 - t195 b 4 INT 9 10 10 0 1 - t195 c 4 INT 9 10 10 0 1 - t195 d 4 INT 9 10 10 0 1 - t195 e 4 INT 9 10 10 0 1 - t196 a 4 INT 9 10 10 0 1 - t196 b 4 INT 9 10 10 0 1 - t196 c 4 INT 9 10 10 0 1 - t196 d 4 INT 9 10 10 0 1 - t196 e 4 INT 9 10 10 0 1 - t197 a 4 INT 9 10 10 0 1 - t197 b 4 INT 9 10 10 0 1 - t197 c 4 INT 9 10 10 0 1 - t197 d 4 INT 9 10 10 0 1 - t197 e 4 INT 9 10 10 0 1 - t198 a 4 INT 9 10 10 0 1 - t198 b 4 INT 9 10 10 0 1 - t198 c 4 INT 9 10 10 0 1 - t198 d 4 INT 9 10 10 0 1 - t198 e 4 INT 9 10 10 0 1 - t199 a 4 INT 9 10 10 0 1 - t199 b 4 INT 9 10 10 0 1 - t199 c 4 INT 9 10 10 0 1 - t199 d 4 INT 9 10 10 0 1 - t199 e 4 INT 9 10 10 0 1 - t200 a 4 INT 9 10 10 0 1 - t200 b 4 INT 9 10 10 0 1 - t200 c 4 INT 9 10 10 0 1 - t200 d 4 INT 9 10 10 0 1 - t200 e 4 INT 9 10 10 0 1 - t201 a 4 INT 9 10 10 0 1 - t201 b 4 INT 9 10 10 0 1 - t201 c 4 INT 9 10 10 0 1 - t201 d 4 INT 9 10 10 0 1 - t201 e 4 INT 9 10 10 0 1 - t202 a 4 INT 9 10 10 0 1 - t202 b 4 INT 9 10 10 0 1 - t202 c 4 INT 9 10 10 0 1 - t202 d 4 INT 9 10 10 0 1 - t202 e 4 INT 9 10 10 0 1 - t203 a 4 INT 9 10 10 0 1 - t203 b 4 INT 9 10 10 0 1 - t203 c 4 INT 9 10 10 0 1 - t203 d 4 INT 9 10 10 0 1 - t203 e 4 INT 9 10 10 0 1 - t204 a 4 INT 9 10 10 0 1 - t204 b 4 INT 9 10 10 0 1 - t204 c 4 INT 9 10 10 0 1 - t204 d 4 INT 9 10 10 0 1 - t204 e 4 INT 9 10 10 0 1 - t205 a 4 INT 9 10 10 0 1 - t205 b 4 INT 9 10 10 0 1 - t205 c 4 INT 9 10 10 0 1 - t205 d 4 INT 9 10 10 0 1 - t205 e 4 INT 9 10 10 0 1 - t206 a 4 INT 9 10 10 0 1 - t206 b 4 INT 9 10 10 0 1 - t206 c 4 INT 9 10 10 0 1 - t206 d 4 INT 9 10 10 0 1 - t206 e 4 INT 9 10 10 0 1 - t207 a 4 INT 9 10 10 0 1 - t207 b 4 INT 9 10 10 0 1 - t207 c 4 INT 9 10 10 0 1 - t207 d 4 INT 9 10 10 0 1 - t207 e 4 INT 9 10 10 0 1 - t208 a 4 INT 9 10 10 0 1 - t208 b 4 INT 9 10 10 0 1 - t208 c 4 INT 9 10 10 0 1 - t208 d 4 INT 9 10 10 0 1 - t208 e 4 INT 9 10 10 0 1 - t209 a 4 INT 9 10 10 0 1 - t209 b 4 INT 9 10 10 0 1 - t209 c 4 INT 9 10 10 0 1 - t209 d 4 INT 9 10 10 0 1 - t209 e 4 INT 9 10 10 0 1 - t210 a 4 INT 9 10 10 0 1 - t210 b 4 INT 9 10 10 0 1 - t210 c 4 INT 9 10 10 0 1 - t210 d 4 INT 9 10 10 0 1 - t210 e 4 INT 9 10 10 0 1 - t211 a 4 INT 9 10 10 0 1 - t211 b 4 INT 9 10 10 0 1 - t211 c 4 INT 9 10 10 0 1 - t211 d 4 INT 9 10 10 0 1 - t211 e 4 INT 9 10 10 0 1 - t212 a 4 INT 9 10 10 0 1 - t212 b 4 INT 9 10 10 0 1 - t212 c 4 INT 9 10 10 0 1 - t212 d 4 INT 9 10 10 0 1 - t212 e 4 INT 9 10 10 0 1 - t213 a 4 INT 9 10 10 0 1 - t213 b 4 INT 9 10 10 0 1 - t213 c 4 INT 9 10 10 0 1 - t213 d 4 INT 9 10 10 0 1 - t213 e 4 INT 9 10 10 0 1 - t214 a 4 INT 9 10 10 0 1 - t214 b 4 INT 9 10 10 0 1 - t214 c 4 INT 9 10 10 0 1 - t214 d 4 INT 9 10 10 0 1 - t214 e 4 INT 9 10 10 0 1 - t215 a 4 INT 9 10 10 0 1 - t215 b 4 INT 9 10 10 0 1 - t215 c 4 INT 9 10 10 0 1 - t215 d 4 INT 9 10 10 0 1 - t215 e 4 INT 9 10 10 0 1 - t216 a 4 INT 9 10 10 0 1 - t216 b 4 INT 9 10 10 0 1 - t216 c 4 INT 9 10 10 0 1 - t216 d 4 INT 9 10 10 0 1 - t216 e 4 INT 9 10 10 0 1 - t217 a 4 INT 9 10 10 0 1 - t217 b 4 INT 9 10 10 0 1 - t217 c 4 INT 9 10 10 0 1 - t217 d 4 INT 9 10 10 0 1 - t217 e 4 INT 9 10 10 0 1 - t218 a 4 INT 9 10 10 0 1 - t218 b 4 INT 9 10 10 0 1 - t218 c 4 INT 9 10 10 0 1 - t218 d 4 INT 9 10 10 0 1 - t218 e 4 INT 9 10 10 0 1 - t219 a 4 INT 9 10 10 0 1 - t219 b 4 INT 9 10 10 0 1 - t219 c 4 INT 9 10 10 0 1 - t219 d 4 INT 9 10 10 0 1 - t219 e 4 INT 9 10 10 0 1 - t220 a 4 INT 9 10 10 0 1 - t220 b 4 INT 9 10 10 0 1 - t220 c 4 INT 9 10 10 0 1 - t220 d 4 INT 9 10 10 0 1 - t220 e 4 INT 9 10 10 0 1 - t221 a 4 INT 9 10 10 0 1 - t221 b 4 INT 9 10 10 0 1 - t221 c 4 INT 9 10 10 0 1 - t221 d 4 INT 9 10 10 0 1 - t221 e 4 INT 9 10 10 0 1 - t222 a 4 INT 9 10 10 0 1 - t222 b 4 INT 9 10 10 0 1 - t222 c 4 INT 9 10 10 0 1 - t222 d 4 INT 9 10 10 0 1 - t222 e 4 INT 9 10 10 0 1 - t223 a 4 INT 9 10 10 0 1 - t223 b 4 INT 9 10 10 0 1 - t223 c 4 INT 9 10 10 0 1 - t223 d 4 INT 9 10 10 0 1 - t223 e 4 INT 9 10 10 0 1 - t224 a 4 INT 9 10 10 0 1 - t224 b 4 INT 9 10 10 0 1 - t224 c 4 INT 9 10 10 0 1 - t224 d 4 INT 9 10 10 0 1 - t224 e 4 INT 9 10 10 0 1 - t225 a 4 INT 9 10 10 0 1 - t225 b 4 INT 9 10 10 0 1 - t225 c 4 INT 9 10 10 0 1 - t225 d 4 INT 9 10 10 0 1 - t225 e 4 INT 9 10 10 0 1 - t226 a 4 INT 9 10 10 0 1 - t226 b 4 INT 9 10 10 0 1 - t226 c 4 INT 9 10 10 0 1 - t226 d 4 INT 9 10 10 0 1 - t226 e 4 INT 9 10 10 0 1 - t227 a 4 INT 9 10 10 0 1 - t227 b 4 INT 9 10 10 0 1 - t227 c 4 INT 9 10 10 0 1 - t227 d 4 INT 9 10 10 0 1 - t227 e 4 INT 9 10 10 0 1 - t228 a 4 INT 9 10 10 0 1 - t228 b 4 INT 9 10 10 0 1 - t228 c 4 INT 9 10 10 0 1 - t228 d 4 INT 9 10 10 0 1 - t228 e 4 INT 9 10 10 0 1 - t229 a 4 INT 9 10 10 0 1 - t229 b 4 INT 9 10 10 0 1 - t229 c 4 INT 9 10 10 0 1 - t229 d 4 INT 9 10 10 0 1 - t229 e 4 INT 9 10 10 0 1 - t230 a 4 INT 9 10 10 0 1 - t230 b 4 INT 9 10 10 0 1 - t230 c 4 INT 9 10 10 0 1 - t230 d 4 INT 9 10 10 0 1 - t230 e 4 INT 9 10 10 0 1 - t231 a 4 INT 9 10 10 0 1 - t231 b 4 INT 9 10 10 0 1 - t231 c 4 INT 9 10 10 0 1 - t231 d 4 INT 9 10 10 0 1 - t231 e 4 INT 9 10 10 0 1 - t232 a 4 INT 9 10 10 0 1 - t232 b 4 INT 9 10 10 0 1 - t232 c 4 INT 9 10 10 0 1 - t232 d 4 INT 9 10 10 0 1 - t232 e 4 INT 9 10 10 0 1 - t233 a 4 INT 9 10 10 0 1 - t233 b 4 INT 9 10 10 0 1 - t233 c 4 INT 9 10 10 0 1 - t233 d 4 INT 9 10 10 0 1 - t233 e 4 INT 9 10 10 0 1 - t234 a 4 INT 9 10 10 0 1 - t234 b 4 INT 9 10 10 0 1 - t234 c 4 INT 9 10 10 0 1 - t234 d 4 INT 9 10 10 0 1 - t234 e 4 INT 9 10 10 0 1 - t235 a 4 INT 9 10 10 0 1 - t235 b 4 INT 9 10 10 0 1 - t235 c 4 INT 9 10 10 0 1 - t235 d 4 INT 9 10 10 0 1 - t235 e 4 INT 9 10 10 0 1 - t236 a 4 INT 9 10 10 0 1 - t236 b 4 INT 9 10 10 0 1 - t236 c 4 INT 9 10 10 0 1 - t236 d 4 INT 9 10 10 0 1 - t236 e 4 INT 9 10 10 0 1 - t237 a 4 INT 9 10 10 0 1 - t237 b 4 INT 9 10 10 0 1 - t237 c 4 INT 9 10 10 0 1 - t237 d 4 INT 9 10 10 0 1 - t237 e 4 INT 9 10 10 0 1 - t238 a 4 INT 9 10 10 0 1 - t238 b 4 INT 9 10 10 0 1 - t238 c 4 INT 9 10 10 0 1 - t238 d 4 INT 9 10 10 0 1 - t238 e 4 INT 9 10 10 0 1 - t239 a 4 INT 9 10 10 0 1 - t239 b 4 INT 9 10 10 0 1 - t239 c 4 INT 9 10 10 0 1 - t239 d 4 INT 9 10 10 0 1 - t239 e 4 INT 9 10 10 0 1 - t240 a 4 INT 9 10 10 0 1 - t240 b 4 INT 9 10 10 0 1 - t240 c 4 INT 9 10 10 0 1 - t240 d 4 INT 9 10 10 0 1 - t240 e 4 INT 9 10 10 0 1 - t241 a 4 INT 9 10 10 0 1 - t241 b 4 INT 9 10 10 0 1 - t241 c 4 INT 9 10 10 0 1 - t241 d 4 INT 9 10 10 0 1 - t241 e 4 INT 9 10 10 0 1 - t242 a 4 INT 9 10 10 0 1 - t242 b 4 INT 9 10 10 0 1 - t242 c 4 INT 9 10 10 0 1 - t242 d 4 INT 9 10 10 0 1 - t242 e 4 INT 9 10 10 0 1 - t243 a 4 INT 9 10 10 0 1 - t243 b 4 INT 9 10 10 0 1 - t243 c 4 INT 9 10 10 0 1 - t243 d 4 INT 9 10 10 0 1 - t243 e 4 INT 9 10 10 0 1 - t244 a 4 INT 9 10 10 0 1 - t244 b 4 INT 9 10 10 0 1 - t244 c 4 INT 9 10 10 0 1 - t244 d 4 INT 9 10 10 0 1 - t244 e 4 INT 9 10 10 0 1 - t245 a 4 INT 9 10 10 0 1 - t245 b 4 INT 9 10 10 0 1 - t245 c 4 INT 9 10 10 0 1 - t245 d 4 INT 9 10 10 0 1 - t245 e 4 INT 9 10 10 0 1 - t246 a 4 INT 9 10 10 0 1 - t246 b 4 INT 9 10 10 0 1 - t246 c 4 INT 9 10 10 0 1 - t246 d 4 INT 9 10 10 0 1 - t246 e 4 INT 9 10 10 0 1 - t247 a 4 INT 9 10 10 0 1 - t247 b 4 INT 9 10 10 0 1 - t247 c 4 INT 9 10 10 0 1 - t247 d 4 INT 9 10 10 0 1 - t247 e 4 INT 9 10 10 0 1 - t248 a 4 INT 9 10 10 0 1 - t248 b 4 INT 9 10 10 0 1 - t248 c 4 INT 9 10 10 0 1 - t248 d 4 INT 9 10 10 0 1 - t248 e 4 INT 9 10 10 0 1 - t249 a 4 INT 9 10 10 0 1 - t249 b 4 INT 9 10 10 0 1 - t249 c 4 INT 9 10 10 0 1 - t249 d 4 INT 9 10 10 0 1 - t249 e 4 INT 9 10 10 0 1 - t250 a 4 INT 9 10 10 0 1 - t250 b 4 INT 9 10 10 0 1 - t250 c 4 INT 9 10 10 0 1 - t250 d 4 INT 9 10 10 0 1 - t250 e 4 INT 9 10 10 0 1 - t251 a 4 INT 9 10 10 0 1 - t251 b 4 INT 9 10 10 0 1 - t251 c 4 INT 9 10 10 0 1 - t251 d 4 INT 9 10 10 0 1 - t251 e 4 INT 9 10 10 0 1 - t252 a 4 INT 9 10 10 0 1 - t252 b 4 INT 9 10 10 0 1 - t252 c 4 INT 9 10 10 0 1 - t252 d 4 INT 9 10 10 0 1 - t252 e 4 INT 9 10 10 0 1 - t253 a 4 INT 9 10 10 0 1 - t253 b 4 INT 9 10 10 0 1 - t253 c 4 INT 9 10 10 0 1 - t253 d 4 INT 9 10 10 0 1 - t253 e 4 INT 9 10 10 0 1 - t254 a 4 INT 9 10 10 0 1 - t254 b 4 INT 9 10 10 0 1 - t254 c 4 INT 9 10 10 0 1 - t254 d 4 INT 9 10 10 0 1 - t254 e 4 INT 9 10 10 0 1 - t255 a 4 INT 9 10 10 0 1 - t255 b 4 INT 9 10 10 0 1 - t255 c 4 INT 9 10 10 0 1 - t255 d 4 INT 9 10 10 0 1 - t255 e 4 INT 9 10 10 0 1 - t256 a 4 INT 9 10 10 0 1 - t256 b 4 INT 9 10 10 0 1 - t256 c 4 INT 9 10 10 0 1 - t256 d 4 INT 9 10 10 0 1 - t256 e 4 INT 9 10 10 0 1 - t257 a 4 INT 9 10 10 0 1 - t257 b 4 INT 9 10 10 0 1 - t257 c 4 INT 9 10 10 0 1 - t257 d 4 INT 9 10 10 0 1 - t257 e 4 INT 9 10 10 0 1 - t258 a 4 INT 9 10 10 0 1 - t258 b 4 INT 9 10 10 0 1 - t258 c 4 INT 9 10 10 0 1 - t258 d 4 INT 9 10 10 0 1 - t258 e 4 INT 9 10 10 0 1 - t259 a 4 INT 9 10 10 0 1 - t259 b 4 INT 9 10 10 0 1 - t259 c 4 INT 9 10 10 0 1 - t259 d 4 INT 9 10 10 0 1 - t259 e 4 INT 9 10 10 0 1 - t260 a 4 INT 9 10 10 0 1 - t260 b 4 INT 9 10 10 0 1 - t260 c 4 INT 9 10 10 0 1 - t260 d 4 INT 9 10 10 0 1 - t260 e 4 INT 9 10 10 0 1 - t261 a 4 INT 9 10 10 0 1 - t261 b 4 INT 9 10 10 0 1 - t261 c 4 INT 9 10 10 0 1 - t261 d 4 INT 9 10 10 0 1 - t261 e 4 INT 9 10 10 0 1 - t262 a 4 INT 9 10 10 0 1 - t262 b 4 INT 9 10 10 0 1 - t262 c 4 INT 9 10 10 0 1 - t262 d 4 INT 9 10 10 0 1 - t262 e 4 INT 9 10 10 0 1 - t263 a 4 INT 9 10 10 0 1 - t263 b 4 INT 9 10 10 0 1 - t263 c 4 INT 9 10 10 0 1 - t263 d 4 INT 9 10 10 0 1 - t263 e 4 INT 9 10 10 0 1 - t264 a 4 INT 9 10 10 0 1 - t264 b 4 INT 9 10 10 0 1 - t264 c 4 INT 9 10 10 0 1 - t264 d 4 INT 9 10 10 0 1 - t264 e 4 INT 9 10 10 0 1 - t265 a 4 INT 9 10 10 0 1 - t265 b 4 INT 9 10 10 0 1 - t265 c 4 INT 9 10 10 0 1 - t265 d 4 INT 9 10 10 0 1 - t265 e 4 INT 9 10 10 0 1 - t266 a 4 INT 9 10 10 0 1 - t266 b 4 INT 9 10 10 0 1 - t266 c 4 INT 9 10 10 0 1 - t266 d 4 INT 9 10 10 0 1 - t266 e 4 INT 9 10 10 0 1 - t267 a 4 INT 9 10 10 0 1 - t267 b 4 INT 9 10 10 0 1 - t267 c 4 INT 9 10 10 0 1 - t267 d 4 INT 9 10 10 0 1 - t267 e 4 INT 9 10 10 0 1 - t268 a 4 INT 9 10 10 0 1 - t268 b 4 INT 9 10 10 0 1 - t268 c 4 INT 9 10 10 0 1 - t268 d 4 INT 9 10 10 0 1 - t268 e 4 INT 9 10 10 0 1 - t269 a 4 INT 9 10 10 0 1 - t269 b 4 INT 9 10 10 0 1 - t269 c 4 INT 9 10 10 0 1 - t269 d 4 INT 9 10 10 0 1 - t269 e 4 INT 9 10 10 0 1 - t270 a 4 INT 9 10 10 0 1 - t270 b 4 INT 9 10 10 0 1 - t270 c 4 INT 9 10 10 0 1 - t270 d 4 INT 9 10 10 0 1 - t270 e 4 INT 9 10 10 0 1 - t271 a 4 INT 9 10 10 0 1 - t271 b 4 INT 9 10 10 0 1 - t271 c 4 INT 9 10 10 0 1 - t271 d 4 INT 9 10 10 0 1 - t271 e 4 INT 9 10 10 0 1 - t272 a 4 INT 9 10 10 0 1 - t272 b 4 INT 9 10 10 0 1 - t272 c 4 INT 9 10 10 0 1 - t272 d 4 INT 9 10 10 0 1 - t272 e 4 INT 9 10 10 0 1 - t273 a 4 INT 9 10 10 0 1 - t273 b 4 INT 9 10 10 0 1 - t273 c 4 INT 9 10 10 0 1 - t273 d 4 INT 9 10 10 0 1 - t273 e 4 INT 9 10 10 0 1 - t274 a 4 INT 9 10 10 0 1 - t274 b 4 INT 9 10 10 0 1 - t274 c 4 INT 9 10 10 0 1 - t274 d 4 INT 9 10 10 0 1 - t274 e 4 INT 9 10 10 0 1 - t275 a 4 INT 9 10 10 0 1 - t275 b 4 INT 9 10 10 0 1 - t275 c 4 INT 9 10 10 0 1 - t275 d 4 INT 9 10 10 0 1 - t275 e 4 INT 9 10 10 0 1 - t276 a 4 INT 9 10 10 0 1 - t276 b 4 INT 9 10 10 0 1 - t276 c 4 INT 9 10 10 0 1 - t276 d 4 INT 9 10 10 0 1 - t276 e 4 INT 9 10 10 0 1 - t277 a 4 INT 9 10 10 0 1 - t277 b 4 INT 9 10 10 0 1 - t277 c 4 INT 9 10 10 0 1 - t277 d 4 INT 9 10 10 0 1 - t277 e 4 INT 9 10 10 0 1 - t278 a 4 INT 9 10 10 0 1 - t278 b 4 INT 9 10 10 0 1 - t278 c 4 INT 9 10 10 0 1 - t278 d 4 INT 9 10 10 0 1 - t278 e 4 INT 9 10 10 0 1 - t279 a 4 INT 9 10 10 0 1 - t279 b 4 INT 9 10 10 0 1 - t279 c 4 INT 9 10 10 0 1 - t279 d 4 INT 9 10 10 0 1 - t279 e 4 INT 9 10 10 0 1 - t280 a 4 INT 9 10 10 0 1 - t280 b 4 INT 9 10 10 0 1 - t280 c 4 INT 9 10 10 0 1 - t280 d 4 INT 9 10 10 0 1 - t280 e 4 INT 9 10 10 0 1 - t281 a 4 INT 9 10 10 0 1 - t281 b 4 INT 9 10 10 0 1 - t281 c 4 INT 9 10 10 0 1 - t281 d 4 INT 9 10 10 0 1 - t281 e 4 INT 9 10 10 0 1 - t282 a 4 INT 9 10 10 0 1 - t282 b 4 INT 9 10 10 0 1 - t282 c 4 INT 9 10 10 0 1 - t282 d 4 INT 9 10 10 0 1 - t282 e 4 INT 9 10 10 0 1 - t283 a 4 INT 9 10 10 0 1 - t283 b 4 INT 9 10 10 0 1 - t283 c 4 INT 9 10 10 0 1 - t283 d 4 INT 9 10 10 0 1 - t283 e 4 INT 9 10 10 0 1 - t284 a 4 INT 9 10 10 0 1 - t284 b 4 INT 9 10 10 0 1 - t284 c 4 INT 9 10 10 0 1 - t284 d 4 INT 9 10 10 0 1 - t284 e 4 INT 9 10 10 0 1 - t285 a 4 INT 9 10 10 0 1 - t285 b 4 INT 9 10 10 0 1 - t285 c 4 INT 9 10 10 0 1 - t285 d 4 INT 9 10 10 0 1 - t285 e 4 INT 9 10 10 0 1 - t286 a 4 INT 9 10 10 0 1 - t286 b 4 INT 9 10 10 0 1 - t286 c 4 INT 9 10 10 0 1 - t286 d 4 INT 9 10 10 0 1 - t286 e 4 INT 9 10 10 0 1 - t287 a 4 INT 9 10 10 0 1 - t287 b 4 INT 9 10 10 0 1 - t287 c 4 INT 9 10 10 0 1 - t287 d 4 INT 9 10 10 0 1 - t287 e 4 INT 9 10 10 0 1 - t288 a 4 INT 9 10 10 0 1 - t288 b 4 INT 9 10 10 0 1 - t288 c 4 INT 9 10 10 0 1 - t288 d 4 INT 9 10 10 0 1 - t288 e 4 INT 9 10 10 0 1 - t289 a 4 INT 9 10 10 0 1 - t289 b 4 INT 9 10 10 0 1 - t289 c 4 INT 9 10 10 0 1 - t289 d 4 INT 9 10 10 0 1 - t289 e 4 INT 9 10 10 0 1 - t290 a 4 INT 9 10 10 0 1 - t290 b 4 INT 9 10 10 0 1 - t290 c 4 INT 9 10 10 0 1 - t290 d 4 INT 9 10 10 0 1 - t290 e 4 INT 9 10 10 0 1 - t291 a 4 INT 9 10 10 0 1 - t291 b 4 INT 9 10 10 0 1 - t291 c 4 INT 9 10 10 0 1 - t291 d 4 INT 9 10 10 0 1 - t291 e 4 INT 9 10 10 0 1 - t292 a 4 INT 9 10 10 0 1 - t292 b 4 INT 9 10 10 0 1 - t292 c 4 INT 9 10 10 0 1 - t292 d 4 INT 9 10 10 0 1 - t292 e 4 INT 9 10 10 0 1 - t293 a 4 INT 9 10 10 0 1 - t293 b 4 INT 9 10 10 0 1 - t293 c 4 INT 9 10 10 0 1 - t293 d 4 INT 9 10 10 0 1 - t293 e 4 INT 9 10 10 0 1 - t294 a 4 INT 9 10 10 0 1 - t294 b 4 INT 9 10 10 0 1 - t294 c 4 INT 9 10 10 0 1 - t294 d 4 INT 9 10 10 0 1 - t294 e 4 INT 9 10 10 0 1 - t295 a 4 INT 9 10 10 0 1 - t295 b 4 INT 9 10 10 0 1 - t295 c 4 INT 9 10 10 0 1 - t295 d 4 INT 9 10 10 0 1 - t295 e 4 INT 9 10 10 0 1 - t296 a 4 INT 9 10 10 0 1 - t296 b 4 INT 9 10 10 0 1 - t296 c 4 INT 9 10 10 0 1 - t296 d 4 INT 9 10 10 0 1 - t296 e 4 INT 9 10 10 0 1 - t297 a 4 INT 9 10 10 0 1 - t297 b 4 INT 9 10 10 0 1 - t297 c 4 INT 9 10 10 0 1 - t297 d 4 INT 9 10 10 0 1 - t297 e 4 INT 9 10 10 0 1 - t298 a 4 INT 9 10 10 0 1 - t298 b 4 INT 9 10 10 0 1 - t298 c 4 INT 9 10 10 0 1 - t298 d 4 INT 9 10 10 0 1 - t298 e 4 INT 9 10 10 0 1 - t299 a 4 INT 9 10 10 0 1 - t299 b 4 INT 9 10 10 0 1 - t299 c 4 INT 9 10 10 0 1 - t299 d 4 INT 9 10 10 0 1 - t299 e 4 INT 9 10 10 0 1 - t300 a 4 INT 9 10 10 0 1 - t300 b 4 INT 9 10 10 0 1 - t300 c 4 INT 9 10 10 0 1 - t300 d 4 INT 9 10 10 0 1 - t300 e 4 INT 9 10 10 0 1 - t301 a 4 INT 9 10 10 0 1 - t301 b 4 INT 9 10 10 0 1 - t301 c 4 INT 9 10 10 0 1 - t301 d 4 INT 9 10 10 0 1 - t301 e 4 INT 9 10 10 0 1 - t302 a 4 INT 9 10 10 0 1 - t302 b 4 INT 9 10 10 0 1 - t302 c 4 INT 9 10 10 0 1 - t302 d 4 INT 9 10 10 0 1 - t302 e 4 INT 9 10 10 0 1 - t303 a 4 INT 9 10 10 0 1 - t303 b 4 INT 9 10 10 0 1 - t303 c 4 INT 9 10 10 0 1 - t303 d 4 INT 9 10 10 0 1 - t303 e 4 INT 9 10 10 0 1 - t304 a 4 INT 9 10 10 0 1 - t304 b 4 INT 9 10 10 0 1 - t304 c 4 INT 9 10 10 0 1 - t304 d 4 INT 9 10 10 0 1 - t304 e 4 INT 9 10 10 0 1 - t305 a 4 INT 9 10 10 0 1 - t305 b 4 INT 9 10 10 0 1 - t305 c 4 INT 9 10 10 0 1 - t305 d 4 INT 9 10 10 0 1 - t305 e 4 INT 9 10 10 0 1 - t306 a 4 INT 9 10 10 0 1 - t306 b 4 INT 9 10 10 0 1 - t306 c 4 INT 9 10 10 0 1 - t306 d 4 INT 9 10 10 0 1 - t306 e 4 INT 9 10 10 0 1 - t307 a 4 INT 9 10 10 0 1 - t307 b 4 INT 9 10 10 0 1 - t307 c 4 INT 9 10 10 0 1 - t307 d 4 INT 9 10 10 0 1 - t307 e 4 INT 9 10 10 0 1 - t308 a 4 INT 9 10 10 0 1 - t308 b 4 INT 9 10 10 0 1 - t308 c 4 INT 9 10 10 0 1 - t308 d 4 INT 9 10 10 0 1 - t308 e 4 INT 9 10 10 0 1 - t309 a 4 INT 9 10 10 0 1 - t309 b 4 INT 9 10 10 0 1 - t309 c 4 INT 9 10 10 0 1 - t309 d 4 INT 9 10 10 0 1 - t309 e 4 INT 9 10 10 0 1 - t310 a 4 INT 9 10 10 0 1 - t310 b 4 INT 9 10 10 0 1 - t310 c 4 INT 9 10 10 0 1 - t310 d 4 INT 9 10 10 0 1 - t310 e 4 INT 9 10 10 0 1 - t311 a 4 INT 9 10 10 0 1 - t311 b 4 INT 9 10 10 0 1 - t311 c 4 INT 9 10 10 0 1 - t311 d 4 INT 9 10 10 0 1 - t311 e 4 INT 9 10 10 0 1 - t312 a 4 INT 9 10 10 0 1 - t312 b 4 INT 9 10 10 0 1 - t312 c 4 INT 9 10 10 0 1 - t312 d 4 INT 9 10 10 0 1 - t312 e 4 INT 9 10 10 0 1 - t313 a 4 INT 9 10 10 0 1 - t313 b 4 INT 9 10 10 0 1 - t313 c 4 INT 9 10 10 0 1 - t313 d 4 INT 9 10 10 0 1 - t313 e 4 INT 9 10 10 0 1 - t314 a 4 INT 9 10 10 0 1 - t314 b 4 INT 9 10 10 0 1 - t314 c 4 INT 9 10 10 0 1 - t314 d 4 INT 9 10 10 0 1 - t314 e 4 INT 9 10 10 0 1 - t315 a 4 INT 9 10 10 0 1 - t315 b 4 INT 9 10 10 0 1 - t315 c 4 INT 9 10 10 0 1 - t315 d 4 INT 9 10 10 0 1 - t315 e 4 INT 9 10 10 0 1 - t316 a 4 INT 9 10 10 0 1 - t316 b 4 INT 9 10 10 0 1 - t316 c 4 INT 9 10 10 0 1 - t316 d 4 INT 9 10 10 0 1 - t316 e 4 INT 9 10 10 0 1 - t317 a 4 INT 9 10 10 0 1 - t317 b 4 INT 9 10 10 0 1 - t317 c 4 INT 9 10 10 0 1 - t317 d 4 INT 9 10 10 0 1 - t317 e 4 INT 9 10 10 0 1 - t318 a 4 INT 9 10 10 0 1 - t318 b 4 INT 9 10 10 0 1 - t318 c 4 INT 9 10 10 0 1 - t318 d 4 INT 9 10 10 0 1 - t318 e 4 INT 9 10 10 0 1 - t319 a 4 INT 9 10 10 0 1 - t319 b 4 INT 9 10 10 0 1 - t319 c 4 INT 9 10 10 0 1 - t319 d 4 INT 9 10 10 0 1 - t319 e 4 INT 9 10 10 0 1 - t320 a 4 INT 9 10 10 0 1 - t320 b 4 INT 9 10 10 0 1 - t320 c 4 INT 9 10 10 0 1 - t320 d 4 INT 9 10 10 0 1 - t320 e 4 INT 9 10 10 0 1 - t321 a 4 INT 9 10 10 0 1 - t321 b 4 INT 9 10 10 0 1 - t321 c 4 INT 9 10 10 0 1 - t321 d 4 INT 9 10 10 0 1 - t321 e 4 INT 9 10 10 0 1 - t322 a 4 INT 9 10 10 0 1 - t322 b 4 INT 9 10 10 0 1 - t322 c 4 INT 9 10 10 0 1 - t322 d 4 INT 9 10 10 0 1 - t322 e 4 INT 9 10 10 0 1 - t323 a 4 INT 9 10 10 0 1 - t323 b 4 INT 9 10 10 0 1 - t323 c 4 INT 9 10 10 0 1 - t323 d 4 INT 9 10 10 0 1 - t323 e 4 INT 9 10 10 0 1 - t324 a 4 INT 9 10 10 0 1 - t324 b 4 INT 9 10 10 0 1 - t324 c 4 INT 9 10 10 0 1 - t324 d 4 INT 9 10 10 0 1 - t324 e 4 INT 9 10 10 0 1 - t325 a 4 INT 9 10 10 0 1 - t325 b 4 INT 9 10 10 0 1 - t325 c 4 INT 9 10 10 0 1 - t325 d 4 INT 9 10 10 0 1 - t325 e 4 INT 9 10 10 0 1 - t326 a 4 INT 9 10 10 0 1 - t326 b 4 INT 9 10 10 0 1 - t326 c 4 INT 9 10 10 0 1 - t326 d 4 INT 9 10 10 0 1 - t326 e 4 INT 9 10 10 0 1 - t327 a 4 INT 9 10 10 0 1 - t327 b 4 INT 9 10 10 0 1 - t327 c 4 INT 9 10 10 0 1 - t327 d 4 INT 9 10 10 0 1 - t327 e 4 INT 9 10 10 0 1 - t328 a 4 INT 9 10 10 0 1 - t328 b 4 INT 9 10 10 0 1 - t328 c 4 INT 9 10 10 0 1 - t328 d 4 INT 9 10 10 0 1 - t328 e 4 INT 9 10 10 0 1 - t329 a 4 INT 9 10 10 0 1 - t329 b 4 INT 9 10 10 0 1 - t329 c 4 INT 9 10 10 0 1 - t329 d 4 INT 9 10 10 0 1 - t329 e 4 INT 9 10 10 0 1 - t330 a 4 INT 9 10 10 0 1 - t330 b 4 INT 9 10 10 0 1 - t330 c 4 INT 9 10 10 0 1 - t330 d 4 INT 9 10 10 0 1 - t330 e 4 INT 9 10 10 0 1 - t331 a 4 INT 9 10 10 0 1 - t331 b 4 INT 9 10 10 0 1 - t331 c 4 INT 9 10 10 0 1 - t331 d 4 INT 9 10 10 0 1 - t331 e 4 INT 9 10 10 0 1 - t332 a 4 INT 9 10 10 0 1 - t332 b 4 INT 9 10 10 0 1 - t332 c 4 INT 9 10 10 0 1 - t332 d 4 INT 9 10 10 0 1 - t332 e 4 INT 9 10 10 0 1 - t333 a 4 INT 9 10 10 0 1 - t333 b 4 INT 9 10 10 0 1 - t333 c 4 INT 9 10 10 0 1 - t333 d 4 INT 9 10 10 0 1 - t333 e 4 INT 9 10 10 0 1 - t334 a 4 INT 9 10 10 0 1 - t334 b 4 INT 9 10 10 0 1 - t334 c 4 INT 9 10 10 0 1 - t334 d 4 INT 9 10 10 0 1 - t334 e 4 INT 9 10 10 0 1 - t335 a 4 INT 9 10 10 0 1 - t335 b 4 INT 9 10 10 0 1 - t335 c 4 INT 9 10 10 0 1 - t335 d 4 INT 9 10 10 0 1 - t335 e 4 INT 9 10 10 0 1 - t336 a 4 INT 9 10 10 0 1 - t336 b 4 INT 9 10 10 0 1 - t336 c 4 INT 9 10 10 0 1 - t336 d 4 INT 9 10 10 0 1 - t336 e 4 INT 9 10 10 0 1 - t337 a 4 INT 9 10 10 0 1 - t337 b 4 INT 9 10 10 0 1 - t337 c 4 INT 9 10 10 0 1 - t337 d 4 INT 9 10 10 0 1 - t337 e 4 INT 9 10 10 0 1 - t338 a 4 INT 9 10 10 0 1 - t338 b 4 INT 9 10 10 0 1 - t338 c 4 INT 9 10 10 0 1 - t338 d 4 INT 9 10 10 0 1 - t338 e 4 INT 9 10 10 0 1 - t339 a 4 INT 9 10 10 0 1 - t339 b 4 INT 9 10 10 0 1 - t339 c 4 INT 9 10 10 0 1 - t339 d 4 INT 9 10 10 0 1 - t339 e 4 INT 9 10 10 0 1 - t340 a 4 INT 9 10 10 0 1 - t340 b 4 INT 9 10 10 0 1 - t340 c 4 INT 9 10 10 0 1 - t340 d 4 INT 9 10 10 0 1 - t340 e 4 INT 9 10 10 0 1 - t341 a 4 INT 9 10 10 0 1 - t341 b 4 INT 9 10 10 0 1 - t341 c 4 INT 9 10 10 0 1 - t341 d 4 INT 9 10 10 0 1 - t341 e 4 INT 9 10 10 0 1 - t342 a 4 INT 9 10 10 0 1 - t342 b 4 INT 9 10 10 0 1 - t342 c 4 INT 9 10 10 0 1 - t342 d 4 INT 9 10 10 0 1 - t342 e 4 INT 9 10 10 0 1 - t343 a 4 INT 9 10 10 0 1 - t343 b 4 INT 9 10 10 0 1 - t343 c 4 INT 9 10 10 0 1 - t343 d 4 INT 9 10 10 0 1 - t343 e 4 INT 9 10 10 0 1 - t344 a 4 INT 9 10 10 0 1 - t344 b 4 INT 9 10 10 0 1 - t344 c 4 INT 9 10 10 0 1 - t344 d 4 INT 9 10 10 0 1 - t344 e 4 INT 9 10 10 0 1 - t345 a 4 INT 9 10 10 0 1 - t345 b 4 INT 9 10 10 0 1 - t345 c 4 INT 9 10 10 0 1 - t345 d 4 INT 9 10 10 0 1 - t345 e 4 INT 9 10 10 0 1 - t346 a 4 INT 9 10 10 0 1 - t346 b 4 INT 9 10 10 0 1 - t346 c 4 INT 9 10 10 0 1 - t346 d 4 INT 9 10 10 0 1 - t346 e 4 INT 9 10 10 0 1 - t347 a 4 INT 9 10 10 0 1 - t347 b 4 INT 9 10 10 0 1 - t347 c 4 INT 9 10 10 0 1 - t347 d 4 INT 9 10 10 0 1 - t347 e 4 INT 9 10 10 0 1 - t348 a 4 INT 9 10 10 0 1 - t348 b 4 INT 9 10 10 0 1 - t348 c 4 INT 9 10 10 0 1 - t348 d 4 INT 9 10 10 0 1 - t348 e 4 INT 9 10 10 0 1 - t349 a 4 INT 9 10 10 0 1 - t349 b 4 INT 9 10 10 0 1 - t349 c 4 INT 9 10 10 0 1 - t349 d 4 INT 9 10 10 0 1 - t349 e 4 INT 9 10 10 0 1 - t350 a 4 INT 9 10 10 0 1 - t350 b 4 INT 9 10 10 0 1 - t350 c 4 INT 9 10 10 0 1 - t350 d 4 INT 9 10 10 0 1 - t350 e 4 INT 9 10 10 0 1 - t351 a 4 INT 9 10 10 0 1 - t351 b 4 INT 9 10 10 0 1 - t351 c 4 INT 9 10 10 0 1 - t351 d 4 INT 9 10 10 0 1 - t351 e 4 INT 9 10 10 0 1 - t352 a 4 INT 9 10 10 0 1 - t352 b 4 INT 9 10 10 0 1 - t352 c 4 INT 9 10 10 0 1 - t352 d 4 INT 9 10 10 0 1 - t352 e 4 INT 9 10 10 0 1 - t353 a 4 INT 9 10 10 0 1 - t353 b 4 INT 9 10 10 0 1 - t353 c 4 INT 9 10 10 0 1 - t353 d 4 INT 9 10 10 0 1 - t353 e 4 INT 9 10 10 0 1 - t354 a 4 INT 9 10 10 0 1 - t354 b 4 INT 9 10 10 0 1 - t354 c 4 INT 9 10 10 0 1 - t354 d 4 INT 9 10 10 0 1 - t354 e 4 INT 9 10 10 0 1 - t355 a 4 INT 9 10 10 0 1 - t355 b 4 INT 9 10 10 0 1 - t355 c 4 INT 9 10 10 0 1 - t355 d 4 INT 9 10 10 0 1 - t355 e 4 INT 9 10 10 0 1 - t356 a 4 INT 9 10 10 0 1 - t356 b 4 INT 9 10 10 0 1 - t356 c 4 INT 9 10 10 0 1 - t356 d 4 INT 9 10 10 0 1 - t356 e 4 INT 9 10 10 0 1 - t357 a 4 INT 9 10 10 0 1 - t357 b 4 INT 9 10 10 0 1 - t357 c 4 INT 9 10 10 0 1 - t357 d 4 INT 9 10 10 0 1 - t357 e 4 INT 9 10 10 0 1 - t358 a 4 INT 9 10 10 0 1 - t358 b 4 INT 9 10 10 0 1 - t358 c 4 INT 9 10 10 0 1 - t358 d 4 INT 9 10 10 0 1 - t358 e 4 INT 9 10 10 0 1 - t359 a 4 INT 9 10 10 0 1 - t359 b 4 INT 9 10 10 0 1 - t359 c 4 INT 9 10 10 0 1 - t359 d 4 INT 9 10 10 0 1 - t359 e 4 INT 9 10 10 0 1 - t360 a 4 INT 9 10 10 0 1 - t360 b 4 INT 9 10 10 0 1 - t360 c 4 INT 9 10 10 0 1 - t360 d 4 INT 9 10 10 0 1 - t360 e 4 INT 9 10 10 0 1 - t361 a 4 INT 9 10 10 0 1 - t361 b 4 INT 9 10 10 0 1 - t361 c 4 INT 9 10 10 0 1 - t361 d 4 INT 9 10 10 0 1 - t361 e 4 INT 9 10 10 0 1 - t362 a 4 INT 9 10 10 0 1 - t362 b 4 INT 9 10 10 0 1 - t362 c 4 INT 9 10 10 0 1 - t362 d 4 INT 9 10 10 0 1 - t362 e 4 INT 9 10 10 0 1 - t363 a 4 INT 9 10 10 0 1 - t363 b 4 INT 9 10 10 0 1 - t363 c 4 INT 9 10 10 0 1 - t363 d 4 INT 9 10 10 0 1 - t363 e 4 INT 9 10 10 0 1 - t364 a 4 INT 9 10 10 0 1 - t364 b 4 INT 9 10 10 0 1 - t364 c 4 INT 9 10 10 0 1 - t364 d 4 INT 9 10 10 0 1 - t364 e 4 INT 9 10 10 0 1 - t365 a 4 INT 9 10 10 0 1 - t365 b 4 INT 9 10 10 0 1 - t365 c 4 INT 9 10 10 0 1 - t365 d 4 INT 9 10 10 0 1 - t365 e 4 INT 9 10 10 0 1 - t366 a 4 INT 9 10 10 0 1 - t366 b 4 INT 9 10 10 0 1 - t366 c 4 INT 9 10 10 0 1 - t366 d 4 INT 9 10 10 0 1 - t366 e 4 INT 9 10 10 0 1 - t367 a 4 INT 9 10 10 0 1 - t367 b 4 INT 9 10 10 0 1 - t367 c 4 INT 9 10 10 0 1 - t367 d 4 INT 9 10 10 0 1 - t367 e 4 INT 9 10 10 0 1 - t368 a 4 INT 9 10 10 0 1 - t368 b 4 INT 9 10 10 0 1 - t368 c 4 INT 9 10 10 0 1 - t368 d 4 INT 9 10 10 0 1 - t368 e 4 INT 9 10 10 0 1 - t369 a 4 INT 9 10 10 0 1 - t369 b 4 INT 9 10 10 0 1 - t369 c 4 INT 9 10 10 0 1 - t369 d 4 INT 9 10 10 0 1 - t369 e 4 INT 9 10 10 0 1 - t370 a 4 INT 9 10 10 0 1 - t370 b 4 INT 9 10 10 0 1 - t370 c 4 INT 9 10 10 0 1 - t370 d 4 INT 9 10 10 0 1 - t370 e 4 INT 9 10 10 0 1 - t371 a 4 INT 9 10 10 0 1 - t371 b 4 INT 9 10 10 0 1 - t371 c 4 INT 9 10 10 0 1 - t371 d 4 INT 9 10 10 0 1 - t371 e 4 INT 9 10 10 0 1 - t372 a 4 INT 9 10 10 0 1 - t372 b 4 INT 9 10 10 0 1 - t372 c 4 INT 9 10 10 0 1 - t372 d 4 INT 9 10 10 0 1 - t372 e 4 INT 9 10 10 0 1 - t373 a 4 INT 9 10 10 0 1 - t373 b 4 INT 9 10 10 0 1 - t373 c 4 INT 9 10 10 0 1 - t373 d 4 INT 9 10 10 0 1 - t373 e 4 INT 9 10 10 0 1 - t374 a 4 INT 9 10 10 0 1 - t374 b 4 INT 9 10 10 0 1 - t374 c 4 INT 9 10 10 0 1 - t374 d 4 INT 9 10 10 0 1 - t374 e 4 INT 9 10 10 0 1 - t375 a 4 INT 9 10 10 0 1 - t375 b 4 INT 9 10 10 0 1 - t375 c 4 INT 9 10 10 0 1 - t375 d 4 INT 9 10 10 0 1 - t375 e 4 INT 9 10 10 0 1 - t376 a 4 INT 9 10 10 0 1 - t376 b 4 INT 9 10 10 0 1 - t376 c 4 INT 9 10 10 0 1 - t376 d 4 INT 9 10 10 0 1 - t376 e 4 INT 9 10 10 0 1 - t377 a 4 INT 9 10 10 0 1 - t377 b 4 INT 9 10 10 0 1 - t377 c 4 INT 9 10 10 0 1 - t377 d 4 INT 9 10 10 0 1 - t377 e 4 INT 9 10 10 0 1 - t378 a 4 INT 9 10 10 0 1 - t378 b 4 INT 9 10 10 0 1 - t378 c 4 INT 9 10 10 0 1 - t378 d 4 INT 9 10 10 0 1 - t378 e 4 INT 9 10 10 0 1 - t379 a 4 INT 9 10 10 0 1 - t379 b 4 INT 9 10 10 0 1 - t379 c 4 INT 9 10 10 0 1 - t379 d 4 INT 9 10 10 0 1 - t379 e 4 INT 9 10 10 0 1 - t380 a 4 INT 9 10 10 0 1 - t380 b 4 INT 9 10 10 0 1 - t380 c 4 INT 9 10 10 0 1 - t380 d 4 INT 9 10 10 0 1 - t380 e 4 INT 9 10 10 0 1 - t381 a 4 INT 9 10 10 0 1 - t381 b 4 INT 9 10 10 0 1 - t381 c 4 INT 9 10 10 0 1 - t381 d 4 INT 9 10 10 0 1 - t381 e 4 INT 9 10 10 0 1 - t382 a 4 INT 9 10 10 0 1 - t382 b 4 INT 9 10 10 0 1 - t382 c 4 INT 9 10 10 0 1 - t382 d 4 INT 9 10 10 0 1 - t382 e 4 INT 9 10 10 0 1 - t383 a 4 INT 9 10 10 0 1 - t383 b 4 INT 9 10 10 0 1 - t383 c 4 INT 9 10 10 0 1 - t383 d 4 INT 9 10 10 0 1 - t383 e 4 INT 9 10 10 0 1 - t384 a 4 INT 9 10 10 0 1 - t384 b 4 INT 9 10 10 0 1 - t384 c 4 INT 9 10 10 0 1 - t384 d 4 INT 9 10 10 0 1 - t384 e 4 INT 9 10 10 0 1 - t385 a 4 INT 9 10 10 0 1 - t385 b 4 INT 9 10 10 0 1 - t385 c 4 INT 9 10 10 0 1 - t385 d 4 INT 9 10 10 0 1 - t385 e 4 INT 9 10 10 0 1 - t386 a 4 INT 9 10 10 0 1 - t386 b 4 INT 9 10 10 0 1 - t386 c 4 INT 9 10 10 0 1 - t386 d 4 INT 9 10 10 0 1 - t386 e 4 INT 9 10 10 0 1 - t387 a 4 INT 9 10 10 0 1 - t387 b 4 INT 9 10 10 0 1 - t387 c 4 INT 9 10 10 0 1 - t387 d 4 INT 9 10 10 0 1 - t387 e 4 INT 9 10 10 0 1 - t388 a 4 INT 9 10 10 0 1 - t388 b 4 INT 9 10 10 0 1 - t388 c 4 INT 9 10 10 0 1 - t388 d 4 INT 9 10 10 0 1 - t388 e 4 INT 9 10 10 0 1 - t389 a 4 INT 9 10 10 0 1 - t389 b 4 INT 9 10 10 0 1 - t389 c 4 INT 9 10 10 0 1 - t389 d 4 INT 9 10 10 0 1 - t389 e 4 INT 9 10 10 0 1 - t390 a 4 INT 9 10 10 0 1 - t390 b 4 INT 9 10 10 0 1 - t390 c 4 INT 9 10 10 0 1 - t390 d 4 INT 9 10 10 0 1 - t390 e 4 INT 9 10 10 0 1 - t391 a 4 INT 9 10 10 0 1 - t391 b 4 INT 9 10 10 0 1 - t391 c 4 INT 9 10 10 0 1 - t391 d 4 INT 9 10 10 0 1 - t391 e 4 INT 9 10 10 0 1 - t392 a 4 INT 9 10 10 0 1 - t392 b 4 INT 9 10 10 0 1 - t392 c 4 INT 9 10 10 0 1 - t392 d 4 INT 9 10 10 0 1 - t392 e 4 INT 9 10 10 0 1 - t393 a 4 INT 9 10 10 0 1 - t393 b 4 INT 9 10 10 0 1 - t393 c 4 INT 9 10 10 0 1 - t393 d 4 INT 9 10 10 0 1 - t393 e 4 INT 9 10 10 0 1 - t394 a 4 INT 9 10 10 0 1 - t394 b 4 INT 9 10 10 0 1 - t394 c 4 INT 9 10 10 0 1 - t394 d 4 INT 9 10 10 0 1 - t394 e 4 INT 9 10 10 0 1 - t395 a 4 INT 9 10 10 0 1 - t395 b 4 INT 9 10 10 0 1 - t395 c 4 INT 9 10 10 0 1 - t395 d 4 INT 9 10 10 0 1 - t395 e 4 INT 9 10 10 0 1 - t396 a 4 INT 9 10 10 0 1 - t396 b 4 INT 9 10 10 0 1 - t396 c 4 INT 9 10 10 0 1 - t396 d 4 INT 9 10 10 0 1 - t396 e 4 INT 9 10 10 0 1 - t397 a 4 INT 9 10 10 0 1 - t397 b 4 INT 9 10 10 0 1 - t397 c 4 INT 9 10 10 0 1 - t397 d 4 INT 9 10 10 0 1 - t397 e 4 INT 9 10 10 0 1 - t398 a 4 INT 9 10 10 0 1 - t398 b 4 INT 9 10 10 0 1 - t398 c 4 INT 9 10 10 0 1 - t398 d 4 INT 9 10 10 0 1 - t398 e 4 INT 9 10 10 0 1 - t399 a 4 INT 9 10 10 0 1 - t399 b 4 INT 9 10 10 0 1 - t399 c 4 INT 9 10 10 0 1 - t399 d 4 INT 9 10 10 0 1 - t399 e 4 INT 9 10 10 0 1 + t000 a 4 INT 9 10 10 0 1 NULL + t000 b 4 INT 9 10 10 0 1 NULL + t000 c 4 INT 9 10 10 0 1 NULL + t000 d 4 INT 9 10 10 0 1 NULL + t000 e 4 INT 9 10 10 0 1 NULL + t001 a 4 INT 9 10 10 0 1 NULL + t001 b 4 INT 9 10 10 0 1 NULL + t001 c 4 INT 9 10 10 0 1 NULL + t001 d 4 INT 9 10 10 0 1 NULL + t001 e 4 INT 9 10 10 0 1 NULL + t002 a 4 INT 9 10 10 0 1 NULL + t002 b 4 INT 9 10 10 0 1 NULL + t002 c 4 INT 9 10 10 0 1 NULL + t002 d 4 INT 9 10 10 0 1 NULL + t002 e 4 INT 9 10 10 0 1 NULL + t003 a 4 INT 9 10 10 0 1 NULL + t003 b 4 INT 9 10 10 0 1 NULL + t003 c 4 INT 9 10 10 0 1 NULL + t003 d 4 INT 9 10 10 0 1 NULL + t003 e 4 INT 9 10 10 0 1 NULL + t004 a 4 INT 9 10 10 0 1 NULL + t004 b 4 INT 9 10 10 0 1 NULL + t004 c 4 INT 9 10 10 0 1 NULL + t004 d 4 INT 9 10 10 0 1 NULL + t004 e 4 INT 9 10 10 0 1 NULL + t005 a 4 INT 9 10 10 0 1 NULL + t005 b 4 INT 9 10 10 0 1 NULL + t005 c 4 INT 9 10 10 0 1 NULL + t005 d 4 INT 9 10 10 0 1 NULL + t005 e 4 INT 9 10 10 0 1 NULL + t006 a 4 INT 9 10 10 0 1 NULL + t006 b 4 INT 9 10 10 0 1 NULL + t006 c 4 INT 9 10 10 0 1 NULL + t006 d 4 INT 9 10 10 0 1 NULL + t006 e 4 INT 9 10 10 0 1 NULL + t007 a 4 INT 9 10 10 0 1 NULL + t007 b 4 INT 9 10 10 0 1 NULL + t007 c 4 INT 9 10 10 0 1 NULL + t007 d 4 INT 9 10 10 0 1 NULL + t007 e 4 INT 9 10 10 0 1 NULL + t008 a 4 INT 9 10 10 0 1 NULL + t008 b 4 INT 9 10 10 0 1 NULL + t008 c 4 INT 9 10 10 0 1 NULL + t008 d 4 INT 9 10 10 0 1 NULL + t008 e 4 INT 9 10 10 0 1 NULL + t009 a 4 INT 9 10 10 0 1 NULL + t009 b 4 INT 9 10 10 0 1 NULL + t009 c 4 INT 9 10 10 0 1 NULL + t009 d 4 INT 9 10 10 0 1 NULL + t009 e 4 INT 9 10 10 0 1 NULL + t010 a 4 INT 9 10 10 0 1 NULL + t010 b 4 INT 9 10 10 0 1 NULL + t010 c 4 INT 9 10 10 0 1 NULL + t010 d 4 INT 9 10 10 0 1 NULL + t010 e 4 INT 9 10 10 0 1 NULL + t011 a 4 INT 9 10 10 0 1 NULL + t011 b 4 INT 9 10 10 0 1 NULL + t011 c 4 INT 9 10 10 0 1 NULL + t011 d 4 INT 9 10 10 0 1 NULL + t011 e 4 INT 9 10 10 0 1 NULL + t012 a 4 INT 9 10 10 0 1 NULL + t012 b 4 INT 9 10 10 0 1 NULL + t012 c 4 INT 9 10 10 0 1 NULL + t012 d 4 INT 9 10 10 0 1 NULL + t012 e 4 INT 9 10 10 0 1 NULL + t013 a 4 INT 9 10 10 0 1 NULL + t013 b 4 INT 9 10 10 0 1 NULL + t013 c 4 INT 9 10 10 0 1 NULL + t013 d 4 INT 9 10 10 0 1 NULL + t013 e 4 INT 9 10 10 0 1 NULL + t014 a 4 INT 9 10 10 0 1 NULL + t014 b 4 INT 9 10 10 0 1 NULL + t014 c 4 INT 9 10 10 0 1 NULL + t014 d 4 INT 9 10 10 0 1 NULL + t014 e 4 INT 9 10 10 0 1 NULL + t015 a 4 INT 9 10 10 0 1 NULL + t015 b 4 INT 9 10 10 0 1 NULL + t015 c 4 INT 9 10 10 0 1 NULL + t015 d 4 INT 9 10 10 0 1 NULL + t015 e 4 INT 9 10 10 0 1 NULL + t016 a 4 INT 9 10 10 0 1 NULL + t016 b 4 INT 9 10 10 0 1 NULL + t016 c 4 INT 9 10 10 0 1 NULL + t016 d 4 INT 9 10 10 0 1 NULL + t016 e 4 INT 9 10 10 0 1 NULL + t017 a 4 INT 9 10 10 0 1 NULL + t017 b 4 INT 9 10 10 0 1 NULL + t017 c 4 INT 9 10 10 0 1 NULL + t017 d 4 INT 9 10 10 0 1 NULL + t017 e 4 INT 9 10 10 0 1 NULL + t018 a 4 INT 9 10 10 0 1 NULL + t018 b 4 INT 9 10 10 0 1 NULL + t018 c 4 INT 9 10 10 0 1 NULL + t018 d 4 INT 9 10 10 0 1 NULL + t018 e 4 INT 9 10 10 0 1 NULL + t019 a 4 INT 9 10 10 0 1 NULL + t019 b 4 INT 9 10 10 0 1 NULL + t019 c 4 INT 9 10 10 0 1 NULL + t019 d 4 INT 9 10 10 0 1 NULL + t019 e 4 INT 9 10 10 0 1 NULL + t020 a 4 INT 9 10 10 0 1 NULL + t020 b 4 INT 9 10 10 0 1 NULL + t020 c 4 INT 9 10 10 0 1 NULL + t020 d 4 INT 9 10 10 0 1 NULL + t020 e 4 INT 9 10 10 0 1 NULL + t021 a 4 INT 9 10 10 0 1 NULL + t021 b 4 INT 9 10 10 0 1 NULL + t021 c 4 INT 9 10 10 0 1 NULL + t021 d 4 INT 9 10 10 0 1 NULL + t021 e 4 INT 9 10 10 0 1 NULL + t022 a 4 INT 9 10 10 0 1 NULL + t022 b 4 INT 9 10 10 0 1 NULL + t022 c 4 INT 9 10 10 0 1 NULL + t022 d 4 INT 9 10 10 0 1 NULL + t022 e 4 INT 9 10 10 0 1 NULL + t023 a 4 INT 9 10 10 0 1 NULL + t023 b 4 INT 9 10 10 0 1 NULL + t023 c 4 INT 9 10 10 0 1 NULL + t023 d 4 INT 9 10 10 0 1 NULL + t023 e 4 INT 9 10 10 0 1 NULL + t024 a 4 INT 9 10 10 0 1 NULL + t024 b 4 INT 9 10 10 0 1 NULL + t024 c 4 INT 9 10 10 0 1 NULL + t024 d 4 INT 9 10 10 0 1 NULL + t024 e 4 INT 9 10 10 0 1 NULL + t025 a 4 INT 9 10 10 0 1 NULL + t025 b 4 INT 9 10 10 0 1 NULL + t025 c 4 INT 9 10 10 0 1 NULL + t025 d 4 INT 9 10 10 0 1 NULL + t025 e 4 INT 9 10 10 0 1 NULL + t026 a 4 INT 9 10 10 0 1 NULL + t026 b 4 INT 9 10 10 0 1 NULL + t026 c 4 INT 9 10 10 0 1 NULL + t026 d 4 INT 9 10 10 0 1 NULL + t026 e 4 INT 9 10 10 0 1 NULL + t027 a 4 INT 9 10 10 0 1 NULL + t027 b 4 INT 9 10 10 0 1 NULL + t027 c 4 INT 9 10 10 0 1 NULL + t027 d 4 INT 9 10 10 0 1 NULL + t027 e 4 INT 9 10 10 0 1 NULL + t028 a 4 INT 9 10 10 0 1 NULL + t028 b 4 INT 9 10 10 0 1 NULL + t028 c 4 INT 9 10 10 0 1 NULL + t028 d 4 INT 9 10 10 0 1 NULL + t028 e 4 INT 9 10 10 0 1 NULL + t029 a 4 INT 9 10 10 0 1 NULL + t029 b 4 INT 9 10 10 0 1 NULL + t029 c 4 INT 9 10 10 0 1 NULL + t029 d 4 INT 9 10 10 0 1 NULL + t029 e 4 INT 9 10 10 0 1 NULL + t030 a 4 INT 9 10 10 0 1 NULL + t030 b 4 INT 9 10 10 0 1 NULL + t030 c 4 INT 9 10 10 0 1 NULL + t030 d 4 INT 9 10 10 0 1 NULL + t030 e 4 INT 9 10 10 0 1 NULL + t031 a 4 INT 9 10 10 0 1 NULL + t031 b 4 INT 9 10 10 0 1 NULL + t031 c 4 INT 9 10 10 0 1 NULL + t031 d 4 INT 9 10 10 0 1 NULL + t031 e 4 INT 9 10 10 0 1 NULL + t032 a 4 INT 9 10 10 0 1 NULL + t032 b 4 INT 9 10 10 0 1 NULL + t032 c 4 INT 9 10 10 0 1 NULL + t032 d 4 INT 9 10 10 0 1 NULL + t032 e 4 INT 9 10 10 0 1 NULL + t033 a 4 INT 9 10 10 0 1 NULL + t033 b 4 INT 9 10 10 0 1 NULL + t033 c 4 INT 9 10 10 0 1 NULL + t033 d 4 INT 9 10 10 0 1 NULL + t033 e 4 INT 9 10 10 0 1 NULL + t034 a 4 INT 9 10 10 0 1 NULL + t034 b 4 INT 9 10 10 0 1 NULL + t034 c 4 INT 9 10 10 0 1 NULL + t034 d 4 INT 9 10 10 0 1 NULL + t034 e 4 INT 9 10 10 0 1 NULL + t035 a 4 INT 9 10 10 0 1 NULL + t035 b 4 INT 9 10 10 0 1 NULL + t035 c 4 INT 9 10 10 0 1 NULL + t035 d 4 INT 9 10 10 0 1 NULL + t035 e 4 INT 9 10 10 0 1 NULL + t036 a 4 INT 9 10 10 0 1 NULL + t036 b 4 INT 9 10 10 0 1 NULL + t036 c 4 INT 9 10 10 0 1 NULL + t036 d 4 INT 9 10 10 0 1 NULL + t036 e 4 INT 9 10 10 0 1 NULL + t037 a 4 INT 9 10 10 0 1 NULL + t037 b 4 INT 9 10 10 0 1 NULL + t037 c 4 INT 9 10 10 0 1 NULL + t037 d 4 INT 9 10 10 0 1 NULL + t037 e 4 INT 9 10 10 0 1 NULL + t038 a 4 INT 9 10 10 0 1 NULL + t038 b 4 INT 9 10 10 0 1 NULL + t038 c 4 INT 9 10 10 0 1 NULL + t038 d 4 INT 9 10 10 0 1 NULL + t038 e 4 INT 9 10 10 0 1 NULL + t039 a 4 INT 9 10 10 0 1 NULL + t039 b 4 INT 9 10 10 0 1 NULL + t039 c 4 INT 9 10 10 0 1 NULL + t039 d 4 INT 9 10 10 0 1 NULL + t039 e 4 INT 9 10 10 0 1 NULL + t040 a 4 INT 9 10 10 0 1 NULL + t040 b 4 INT 9 10 10 0 1 NULL + t040 c 4 INT 9 10 10 0 1 NULL + t040 d 4 INT 9 10 10 0 1 NULL + t040 e 4 INT 9 10 10 0 1 NULL + t041 a 4 INT 9 10 10 0 1 NULL + t041 b 4 INT 9 10 10 0 1 NULL + t041 c 4 INT 9 10 10 0 1 NULL + t041 d 4 INT 9 10 10 0 1 NULL + t041 e 4 INT 9 10 10 0 1 NULL + t042 a 4 INT 9 10 10 0 1 NULL + t042 b 4 INT 9 10 10 0 1 NULL + t042 c 4 INT 9 10 10 0 1 NULL + t042 d 4 INT 9 10 10 0 1 NULL + t042 e 4 INT 9 10 10 0 1 NULL + t043 a 4 INT 9 10 10 0 1 NULL + t043 b 4 INT 9 10 10 0 1 NULL + t043 c 4 INT 9 10 10 0 1 NULL + t043 d 4 INT 9 10 10 0 1 NULL + t043 e 4 INT 9 10 10 0 1 NULL + t044 a 4 INT 9 10 10 0 1 NULL + t044 b 4 INT 9 10 10 0 1 NULL + t044 c 4 INT 9 10 10 0 1 NULL + t044 d 4 INT 9 10 10 0 1 NULL + t044 e 4 INT 9 10 10 0 1 NULL + t045 a 4 INT 9 10 10 0 1 NULL + t045 b 4 INT 9 10 10 0 1 NULL + t045 c 4 INT 9 10 10 0 1 NULL + t045 d 4 INT 9 10 10 0 1 NULL + t045 e 4 INT 9 10 10 0 1 NULL + t046 a 4 INT 9 10 10 0 1 NULL + t046 b 4 INT 9 10 10 0 1 NULL + t046 c 4 INT 9 10 10 0 1 NULL + t046 d 4 INT 9 10 10 0 1 NULL + t046 e 4 INT 9 10 10 0 1 NULL + t047 a 4 INT 9 10 10 0 1 NULL + t047 b 4 INT 9 10 10 0 1 NULL + t047 c 4 INT 9 10 10 0 1 NULL + t047 d 4 INT 9 10 10 0 1 NULL + t047 e 4 INT 9 10 10 0 1 NULL + t048 a 4 INT 9 10 10 0 1 NULL + t048 b 4 INT 9 10 10 0 1 NULL + t048 c 4 INT 9 10 10 0 1 NULL + t048 d 4 INT 9 10 10 0 1 NULL + t048 e 4 INT 9 10 10 0 1 NULL + t049 a 4 INT 9 10 10 0 1 NULL + t049 b 4 INT 9 10 10 0 1 NULL + t049 c 4 INT 9 10 10 0 1 NULL + t049 d 4 INT 9 10 10 0 1 NULL + t049 e 4 INT 9 10 10 0 1 NULL + t050 a 4 INT 9 10 10 0 1 NULL + t050 b 4 INT 9 10 10 0 1 NULL + t050 c 4 INT 9 10 10 0 1 NULL + t050 d 4 INT 9 10 10 0 1 NULL + t050 e 4 INT 9 10 10 0 1 NULL + t051 a 4 INT 9 10 10 0 1 NULL + t051 b 4 INT 9 10 10 0 1 NULL + t051 c 4 INT 9 10 10 0 1 NULL + t051 d 4 INT 9 10 10 0 1 NULL + t051 e 4 INT 9 10 10 0 1 NULL + t052 a 4 INT 9 10 10 0 1 NULL + t052 b 4 INT 9 10 10 0 1 NULL + t052 c 4 INT 9 10 10 0 1 NULL + t052 d 4 INT 9 10 10 0 1 NULL + t052 e 4 INT 9 10 10 0 1 NULL + t053 a 4 INT 9 10 10 0 1 NULL + t053 b 4 INT 9 10 10 0 1 NULL + t053 c 4 INT 9 10 10 0 1 NULL + t053 d 4 INT 9 10 10 0 1 NULL + t053 e 4 INT 9 10 10 0 1 NULL + t054 a 4 INT 9 10 10 0 1 NULL + t054 b 4 INT 9 10 10 0 1 NULL + t054 c 4 INT 9 10 10 0 1 NULL + t054 d 4 INT 9 10 10 0 1 NULL + t054 e 4 INT 9 10 10 0 1 NULL + t055 a 4 INT 9 10 10 0 1 NULL + t055 b 4 INT 9 10 10 0 1 NULL + t055 c 4 INT 9 10 10 0 1 NULL + t055 d 4 INT 9 10 10 0 1 NULL + t055 e 4 INT 9 10 10 0 1 NULL + t056 a 4 INT 9 10 10 0 1 NULL + t056 b 4 INT 9 10 10 0 1 NULL + t056 c 4 INT 9 10 10 0 1 NULL + t056 d 4 INT 9 10 10 0 1 NULL + t056 e 4 INT 9 10 10 0 1 NULL + t057 a 4 INT 9 10 10 0 1 NULL + t057 b 4 INT 9 10 10 0 1 NULL + t057 c 4 INT 9 10 10 0 1 NULL + t057 d 4 INT 9 10 10 0 1 NULL + t057 e 4 INT 9 10 10 0 1 NULL + t058 a 4 INT 9 10 10 0 1 NULL + t058 b 4 INT 9 10 10 0 1 NULL + t058 c 4 INT 9 10 10 0 1 NULL + t058 d 4 INT 9 10 10 0 1 NULL + t058 e 4 INT 9 10 10 0 1 NULL + t059 a 4 INT 9 10 10 0 1 NULL + t059 b 4 INT 9 10 10 0 1 NULL + t059 c 4 INT 9 10 10 0 1 NULL + t059 d 4 INT 9 10 10 0 1 NULL + t059 e 4 INT 9 10 10 0 1 NULL + t060 a 4 INT 9 10 10 0 1 NULL + t060 b 4 INT 9 10 10 0 1 NULL + t060 c 4 INT 9 10 10 0 1 NULL + t060 d 4 INT 9 10 10 0 1 NULL + t060 e 4 INT 9 10 10 0 1 NULL + t061 a 4 INT 9 10 10 0 1 NULL + t061 b 4 INT 9 10 10 0 1 NULL + t061 c 4 INT 9 10 10 0 1 NULL + t061 d 4 INT 9 10 10 0 1 NULL + t061 e 4 INT 9 10 10 0 1 NULL + t062 a 4 INT 9 10 10 0 1 NULL + t062 b 4 INT 9 10 10 0 1 NULL + t062 c 4 INT 9 10 10 0 1 NULL + t062 d 4 INT 9 10 10 0 1 NULL + t062 e 4 INT 9 10 10 0 1 NULL + t063 a 4 INT 9 10 10 0 1 NULL + t063 b 4 INT 9 10 10 0 1 NULL + t063 c 4 INT 9 10 10 0 1 NULL + t063 d 4 INT 9 10 10 0 1 NULL + t063 e 4 INT 9 10 10 0 1 NULL + t064 a 4 INT 9 10 10 0 1 NULL + t064 b 4 INT 9 10 10 0 1 NULL + t064 c 4 INT 9 10 10 0 1 NULL + t064 d 4 INT 9 10 10 0 1 NULL + t064 e 4 INT 9 10 10 0 1 NULL + t065 a 4 INT 9 10 10 0 1 NULL + t065 b 4 INT 9 10 10 0 1 NULL + t065 c 4 INT 9 10 10 0 1 NULL + t065 d 4 INT 9 10 10 0 1 NULL + t065 e 4 INT 9 10 10 0 1 NULL + t066 a 4 INT 9 10 10 0 1 NULL + t066 b 4 INT 9 10 10 0 1 NULL + t066 c 4 INT 9 10 10 0 1 NULL + t066 d 4 INT 9 10 10 0 1 NULL + t066 e 4 INT 9 10 10 0 1 NULL + t067 a 4 INT 9 10 10 0 1 NULL + t067 b 4 INT 9 10 10 0 1 NULL + t067 c 4 INT 9 10 10 0 1 NULL + t067 d 4 INT 9 10 10 0 1 NULL + t067 e 4 INT 9 10 10 0 1 NULL + t068 a 4 INT 9 10 10 0 1 NULL + t068 b 4 INT 9 10 10 0 1 NULL + t068 c 4 INT 9 10 10 0 1 NULL + t068 d 4 INT 9 10 10 0 1 NULL + t068 e 4 INT 9 10 10 0 1 NULL + t069 a 4 INT 9 10 10 0 1 NULL + t069 b 4 INT 9 10 10 0 1 NULL + t069 c 4 INT 9 10 10 0 1 NULL + t069 d 4 INT 9 10 10 0 1 NULL + t069 e 4 INT 9 10 10 0 1 NULL + t070 a 4 INT 9 10 10 0 1 NULL + t070 b 4 INT 9 10 10 0 1 NULL + t070 c 4 INT 9 10 10 0 1 NULL + t070 d 4 INT 9 10 10 0 1 NULL + t070 e 4 INT 9 10 10 0 1 NULL + t071 a 4 INT 9 10 10 0 1 NULL + t071 b 4 INT 9 10 10 0 1 NULL + t071 c 4 INT 9 10 10 0 1 NULL + t071 d 4 INT 9 10 10 0 1 NULL + t071 e 4 INT 9 10 10 0 1 NULL + t072 a 4 INT 9 10 10 0 1 NULL + t072 b 4 INT 9 10 10 0 1 NULL + t072 c 4 INT 9 10 10 0 1 NULL + t072 d 4 INT 9 10 10 0 1 NULL + t072 e 4 INT 9 10 10 0 1 NULL + t073 a 4 INT 9 10 10 0 1 NULL + t073 b 4 INT 9 10 10 0 1 NULL + t073 c 4 INT 9 10 10 0 1 NULL + t073 d 4 INT 9 10 10 0 1 NULL + t073 e 4 INT 9 10 10 0 1 NULL + t074 a 4 INT 9 10 10 0 1 NULL + t074 b 4 INT 9 10 10 0 1 NULL + t074 c 4 INT 9 10 10 0 1 NULL + t074 d 4 INT 9 10 10 0 1 NULL + t074 e 4 INT 9 10 10 0 1 NULL + t075 a 4 INT 9 10 10 0 1 NULL + t075 b 4 INT 9 10 10 0 1 NULL + t075 c 4 INT 9 10 10 0 1 NULL + t075 d 4 INT 9 10 10 0 1 NULL + t075 e 4 INT 9 10 10 0 1 NULL + t076 a 4 INT 9 10 10 0 1 NULL + t076 b 4 INT 9 10 10 0 1 NULL + t076 c 4 INT 9 10 10 0 1 NULL + t076 d 4 INT 9 10 10 0 1 NULL + t076 e 4 INT 9 10 10 0 1 NULL + t077 a 4 INT 9 10 10 0 1 NULL + t077 b 4 INT 9 10 10 0 1 NULL + t077 c 4 INT 9 10 10 0 1 NULL + t077 d 4 INT 9 10 10 0 1 NULL + t077 e 4 INT 9 10 10 0 1 NULL + t078 a 4 INT 9 10 10 0 1 NULL + t078 b 4 INT 9 10 10 0 1 NULL + t078 c 4 INT 9 10 10 0 1 NULL + t078 d 4 INT 9 10 10 0 1 NULL + t078 e 4 INT 9 10 10 0 1 NULL + t079 a 4 INT 9 10 10 0 1 NULL + t079 b 4 INT 9 10 10 0 1 NULL + t079 c 4 INT 9 10 10 0 1 NULL + t079 d 4 INT 9 10 10 0 1 NULL + t079 e 4 INT 9 10 10 0 1 NULL + t080 a 4 INT 9 10 10 0 1 NULL + t080 b 4 INT 9 10 10 0 1 NULL + t080 c 4 INT 9 10 10 0 1 NULL + t080 d 4 INT 9 10 10 0 1 NULL + t080 e 4 INT 9 10 10 0 1 NULL + t081 a 4 INT 9 10 10 0 1 NULL + t081 b 4 INT 9 10 10 0 1 NULL + t081 c 4 INT 9 10 10 0 1 NULL + t081 d 4 INT 9 10 10 0 1 NULL + t081 e 4 INT 9 10 10 0 1 NULL + t082 a 4 INT 9 10 10 0 1 NULL + t082 b 4 INT 9 10 10 0 1 NULL + t082 c 4 INT 9 10 10 0 1 NULL + t082 d 4 INT 9 10 10 0 1 NULL + t082 e 4 INT 9 10 10 0 1 NULL + t083 a 4 INT 9 10 10 0 1 NULL + t083 b 4 INT 9 10 10 0 1 NULL + t083 c 4 INT 9 10 10 0 1 NULL + t083 d 4 INT 9 10 10 0 1 NULL + t083 e 4 INT 9 10 10 0 1 NULL + t084 a 4 INT 9 10 10 0 1 NULL + t084 b 4 INT 9 10 10 0 1 NULL + t084 c 4 INT 9 10 10 0 1 NULL + t084 d 4 INT 9 10 10 0 1 NULL + t084 e 4 INT 9 10 10 0 1 NULL + t085 a 4 INT 9 10 10 0 1 NULL + t085 b 4 INT 9 10 10 0 1 NULL + t085 c 4 INT 9 10 10 0 1 NULL + t085 d 4 INT 9 10 10 0 1 NULL + t085 e 4 INT 9 10 10 0 1 NULL + t086 a 4 INT 9 10 10 0 1 NULL + t086 b 4 INT 9 10 10 0 1 NULL + t086 c 4 INT 9 10 10 0 1 NULL + t086 d 4 INT 9 10 10 0 1 NULL + t086 e 4 INT 9 10 10 0 1 NULL + t087 a 4 INT 9 10 10 0 1 NULL + t087 b 4 INT 9 10 10 0 1 NULL + t087 c 4 INT 9 10 10 0 1 NULL + t087 d 4 INT 9 10 10 0 1 NULL + t087 e 4 INT 9 10 10 0 1 NULL + t088 a 4 INT 9 10 10 0 1 NULL + t088 b 4 INT 9 10 10 0 1 NULL + t088 c 4 INT 9 10 10 0 1 NULL + t088 d 4 INT 9 10 10 0 1 NULL + t088 e 4 INT 9 10 10 0 1 NULL + t089 a 4 INT 9 10 10 0 1 NULL + t089 b 4 INT 9 10 10 0 1 NULL + t089 c 4 INT 9 10 10 0 1 NULL + t089 d 4 INT 9 10 10 0 1 NULL + t089 e 4 INT 9 10 10 0 1 NULL + t090 a 4 INT 9 10 10 0 1 NULL + t090 b 4 INT 9 10 10 0 1 NULL + t090 c 4 INT 9 10 10 0 1 NULL + t090 d 4 INT 9 10 10 0 1 NULL + t090 e 4 INT 9 10 10 0 1 NULL + t091 a 4 INT 9 10 10 0 1 NULL + t091 b 4 INT 9 10 10 0 1 NULL + t091 c 4 INT 9 10 10 0 1 NULL + t091 d 4 INT 9 10 10 0 1 NULL + t091 e 4 INT 9 10 10 0 1 NULL + t092 a 4 INT 9 10 10 0 1 NULL + t092 b 4 INT 9 10 10 0 1 NULL + t092 c 4 INT 9 10 10 0 1 NULL + t092 d 4 INT 9 10 10 0 1 NULL + t092 e 4 INT 9 10 10 0 1 NULL + t093 a 4 INT 9 10 10 0 1 NULL + t093 b 4 INT 9 10 10 0 1 NULL + t093 c 4 INT 9 10 10 0 1 NULL + t093 d 4 INT 9 10 10 0 1 NULL + t093 e 4 INT 9 10 10 0 1 NULL + t094 a 4 INT 9 10 10 0 1 NULL + t094 b 4 INT 9 10 10 0 1 NULL + t094 c 4 INT 9 10 10 0 1 NULL + t094 d 4 INT 9 10 10 0 1 NULL + t094 e 4 INT 9 10 10 0 1 NULL + t095 a 4 INT 9 10 10 0 1 NULL + t095 b 4 INT 9 10 10 0 1 NULL + t095 c 4 INT 9 10 10 0 1 NULL + t095 d 4 INT 9 10 10 0 1 NULL + t095 e 4 INT 9 10 10 0 1 NULL + t096 a 4 INT 9 10 10 0 1 NULL + t096 b 4 INT 9 10 10 0 1 NULL + t096 c 4 INT 9 10 10 0 1 NULL + t096 d 4 INT 9 10 10 0 1 NULL + t096 e 4 INT 9 10 10 0 1 NULL + t097 a 4 INT 9 10 10 0 1 NULL + t097 b 4 INT 9 10 10 0 1 NULL + t097 c 4 INT 9 10 10 0 1 NULL + t097 d 4 INT 9 10 10 0 1 NULL + t097 e 4 INT 9 10 10 0 1 NULL + t098 a 4 INT 9 10 10 0 1 NULL + t098 b 4 INT 9 10 10 0 1 NULL + t098 c 4 INT 9 10 10 0 1 NULL + t098 d 4 INT 9 10 10 0 1 NULL + t098 e 4 INT 9 10 10 0 1 NULL + t099 a 4 INT 9 10 10 0 1 NULL + t099 b 4 INT 9 10 10 0 1 NULL + t099 c 4 INT 9 10 10 0 1 NULL + t099 d 4 INT 9 10 10 0 1 NULL + t099 e 4 INT 9 10 10 0 1 NULL + t1 a 12 varchar(64) 64 64 10 0 1 NULL + t100 a 4 INT 9 10 10 0 1 NULL + t100 b 4 INT 9 10 10 0 1 NULL + t100 c 4 INT 9 10 10 0 1 NULL + t100 d 4 INT 9 10 10 0 1 NULL + t100 e 4 INT 9 10 10 0 1 NULL + t101 a 4 INT 9 10 10 0 1 NULL + t101 b 4 INT 9 10 10 0 1 NULL + t101 c 4 INT 9 10 10 0 1 NULL + t101 d 4 INT 9 10 10 0 1 NULL + t101 e 4 INT 9 10 10 0 1 NULL + t102 a 4 INT 9 10 10 0 1 NULL + t102 b 4 INT 9 10 10 0 1 NULL + t102 c 4 INT 9 10 10 0 1 NULL + t102 d 4 INT 9 10 10 0 1 NULL + t102 e 4 INT 9 10 10 0 1 NULL + t103 a 4 INT 9 10 10 0 1 NULL + t103 b 4 INT 9 10 10 0 1 NULL + t103 c 4 INT 9 10 10 0 1 NULL + t103 d 4 INT 9 10 10 0 1 NULL + t103 e 4 INT 9 10 10 0 1 NULL + t104 a 4 INT 9 10 10 0 1 NULL + t104 b 4 INT 9 10 10 0 1 NULL + t104 c 4 INT 9 10 10 0 1 NULL + t104 d 4 INT 9 10 10 0 1 NULL + t104 e 4 INT 9 10 10 0 1 NULL + t105 a 4 INT 9 10 10 0 1 NULL + t105 b 4 INT 9 10 10 0 1 NULL + t105 c 4 INT 9 10 10 0 1 NULL + t105 d 4 INT 9 10 10 0 1 NULL + t105 e 4 INT 9 10 10 0 1 NULL + t106 a 4 INT 9 10 10 0 1 NULL + t106 b 4 INT 9 10 10 0 1 NULL + t106 c 4 INT 9 10 10 0 1 NULL + t106 d 4 INT 9 10 10 0 1 NULL + t106 e 4 INT 9 10 10 0 1 NULL + t107 a 4 INT 9 10 10 0 1 NULL + t107 b 4 INT 9 10 10 0 1 NULL + t107 c 4 INT 9 10 10 0 1 NULL + t107 d 4 INT 9 10 10 0 1 NULL + t107 e 4 INT 9 10 10 0 1 NULL + t108 a 4 INT 9 10 10 0 1 NULL + t108 b 4 INT 9 10 10 0 1 NULL + t108 c 4 INT 9 10 10 0 1 NULL + t108 d 4 INT 9 10 10 0 1 NULL + t108 e 4 INT 9 10 10 0 1 NULL + t109 a 4 INT 9 10 10 0 1 NULL + t109 b 4 INT 9 10 10 0 1 NULL + t109 c 4 INT 9 10 10 0 1 NULL + t109 d 4 INT 9 10 10 0 1 NULL + t109 e 4 INT 9 10 10 0 1 NULL + t110 a 4 INT 9 10 10 0 1 NULL + t110 b 4 INT 9 10 10 0 1 NULL + t110 c 4 INT 9 10 10 0 1 NULL + t110 d 4 INT 9 10 10 0 1 NULL + t110 e 4 INT 9 10 10 0 1 NULL + t111 a 4 INT 9 10 10 0 1 NULL + t111 b 4 INT 9 10 10 0 1 NULL + t111 c 4 INT 9 10 10 0 1 NULL + t111 d 4 INT 9 10 10 0 1 NULL + t111 e 4 INT 9 10 10 0 1 NULL + t112 a 4 INT 9 10 10 0 1 NULL + t112 b 4 INT 9 10 10 0 1 NULL + t112 c 4 INT 9 10 10 0 1 NULL + t112 d 4 INT 9 10 10 0 1 NULL + t112 e 4 INT 9 10 10 0 1 NULL + t113 a 4 INT 9 10 10 0 1 NULL + t113 b 4 INT 9 10 10 0 1 NULL + t113 c 4 INT 9 10 10 0 1 NULL + t113 d 4 INT 9 10 10 0 1 NULL + t113 e 4 INT 9 10 10 0 1 NULL + t114 a 4 INT 9 10 10 0 1 NULL + t114 b 4 INT 9 10 10 0 1 NULL + t114 c 4 INT 9 10 10 0 1 NULL + t114 d 4 INT 9 10 10 0 1 NULL + t114 e 4 INT 9 10 10 0 1 NULL + t115 a 4 INT 9 10 10 0 1 NULL + t115 b 4 INT 9 10 10 0 1 NULL + t115 c 4 INT 9 10 10 0 1 NULL + t115 d 4 INT 9 10 10 0 1 NULL + t115 e 4 INT 9 10 10 0 1 NULL + t116 a 4 INT 9 10 10 0 1 NULL + t116 b 4 INT 9 10 10 0 1 NULL + t116 c 4 INT 9 10 10 0 1 NULL + t116 d 4 INT 9 10 10 0 1 NULL + t116 e 4 INT 9 10 10 0 1 NULL + t117 a 4 INT 9 10 10 0 1 NULL + t117 b 4 INT 9 10 10 0 1 NULL + t117 c 4 INT 9 10 10 0 1 NULL + t117 d 4 INT 9 10 10 0 1 NULL + t117 e 4 INT 9 10 10 0 1 NULL + t118 a 4 INT 9 10 10 0 1 NULL + t118 b 4 INT 9 10 10 0 1 NULL + t118 c 4 INT 9 10 10 0 1 NULL + t118 d 4 INT 9 10 10 0 1 NULL + t118 e 4 INT 9 10 10 0 1 NULL + t119 a 4 INT 9 10 10 0 1 NULL + t119 b 4 INT 9 10 10 0 1 NULL + t119 c 4 INT 9 10 10 0 1 NULL + t119 d 4 INT 9 10 10 0 1 NULL + t119 e 4 INT 9 10 10 0 1 NULL + t120 a 4 INT 9 10 10 0 1 NULL + t120 b 4 INT 9 10 10 0 1 NULL + t120 c 4 INT 9 10 10 0 1 NULL + t120 d 4 INT 9 10 10 0 1 NULL + t120 e 4 INT 9 10 10 0 1 NULL + t121 a 4 INT 9 10 10 0 1 NULL + t121 b 4 INT 9 10 10 0 1 NULL + t121 c 4 INT 9 10 10 0 1 NULL + t121 d 4 INT 9 10 10 0 1 NULL + t121 e 4 INT 9 10 10 0 1 NULL + t122 a 4 INT 9 10 10 0 1 NULL + t122 b 4 INT 9 10 10 0 1 NULL + t122 c 4 INT 9 10 10 0 1 NULL + t122 d 4 INT 9 10 10 0 1 NULL + t122 e 4 INT 9 10 10 0 1 NULL + t123 a 4 INT 9 10 10 0 1 NULL + t123 b 4 INT 9 10 10 0 1 NULL + t123 c 4 INT 9 10 10 0 1 NULL + t123 d 4 INT 9 10 10 0 1 NULL + t123 e 4 INT 9 10 10 0 1 NULL + t124 a 4 INT 9 10 10 0 1 NULL + t124 b 4 INT 9 10 10 0 1 NULL + t124 c 4 INT 9 10 10 0 1 NULL + t124 d 4 INT 9 10 10 0 1 NULL + t124 e 4 INT 9 10 10 0 1 NULL + t125 a 4 INT 9 10 10 0 1 NULL + t125 b 4 INT 9 10 10 0 1 NULL + t125 c 4 INT 9 10 10 0 1 NULL + t125 d 4 INT 9 10 10 0 1 NULL + t125 e 4 INT 9 10 10 0 1 NULL + t126 a 4 INT 9 10 10 0 1 NULL + t126 b 4 INT 9 10 10 0 1 NULL + t126 c 4 INT 9 10 10 0 1 NULL + t126 d 4 INT 9 10 10 0 1 NULL + t126 e 4 INT 9 10 10 0 1 NULL + t127 a 4 INT 9 10 10 0 1 NULL + t127 b 4 INT 9 10 10 0 1 NULL + t127 c 4 INT 9 10 10 0 1 NULL + t127 d 4 INT 9 10 10 0 1 NULL + t127 e 4 INT 9 10 10 0 1 NULL + t128 a 4 INT 9 10 10 0 1 NULL + t128 b 4 INT 9 10 10 0 1 NULL + t128 c 4 INT 9 10 10 0 1 NULL + t128 d 4 INT 9 10 10 0 1 NULL + t128 e 4 INT 9 10 10 0 1 NULL + t129 a 4 INT 9 10 10 0 1 NULL + t129 b 4 INT 9 10 10 0 1 NULL + t129 c 4 INT 9 10 10 0 1 NULL + t129 d 4 INT 9 10 10 0 1 NULL + t129 e 4 INT 9 10 10 0 1 NULL + t130 a 4 INT 9 10 10 0 1 NULL + t130 b 4 INT 9 10 10 0 1 NULL + t130 c 4 INT 9 10 10 0 1 NULL + t130 d 4 INT 9 10 10 0 1 NULL + t130 e 4 INT 9 10 10 0 1 NULL + t131 a 4 INT 9 10 10 0 1 NULL + t131 b 4 INT 9 10 10 0 1 NULL + t131 c 4 INT 9 10 10 0 1 NULL + t131 d 4 INT 9 10 10 0 1 NULL + t131 e 4 INT 9 10 10 0 1 NULL + t132 a 4 INT 9 10 10 0 1 NULL + t132 b 4 INT 9 10 10 0 1 NULL + t132 c 4 INT 9 10 10 0 1 NULL + t132 d 4 INT 9 10 10 0 1 NULL + t132 e 4 INT 9 10 10 0 1 NULL + t133 a 4 INT 9 10 10 0 1 NULL + t133 b 4 INT 9 10 10 0 1 NULL + t133 c 4 INT 9 10 10 0 1 NULL + t133 d 4 INT 9 10 10 0 1 NULL + t133 e 4 INT 9 10 10 0 1 NULL + t134 a 4 INT 9 10 10 0 1 NULL + t134 b 4 INT 9 10 10 0 1 NULL + t134 c 4 INT 9 10 10 0 1 NULL + t134 d 4 INT 9 10 10 0 1 NULL + t134 e 4 INT 9 10 10 0 1 NULL + t135 a 4 INT 9 10 10 0 1 NULL + t135 b 4 INT 9 10 10 0 1 NULL + t135 c 4 INT 9 10 10 0 1 NULL + t135 d 4 INT 9 10 10 0 1 NULL + t135 e 4 INT 9 10 10 0 1 NULL + t136 a 4 INT 9 10 10 0 1 NULL + t136 b 4 INT 9 10 10 0 1 NULL + t136 c 4 INT 9 10 10 0 1 NULL + t136 d 4 INT 9 10 10 0 1 NULL + t136 e 4 INT 9 10 10 0 1 NULL + t137 a 4 INT 9 10 10 0 1 NULL + t137 b 4 INT 9 10 10 0 1 NULL + t137 c 4 INT 9 10 10 0 1 NULL + t137 d 4 INT 9 10 10 0 1 NULL + t137 e 4 INT 9 10 10 0 1 NULL + t138 a 4 INT 9 10 10 0 1 NULL + t138 b 4 INT 9 10 10 0 1 NULL + t138 c 4 INT 9 10 10 0 1 NULL + t138 d 4 INT 9 10 10 0 1 NULL + t138 e 4 INT 9 10 10 0 1 NULL + t139 a 4 INT 9 10 10 0 1 NULL + t139 b 4 INT 9 10 10 0 1 NULL + t139 c 4 INT 9 10 10 0 1 NULL + t139 d 4 INT 9 10 10 0 1 NULL + t139 e 4 INT 9 10 10 0 1 NULL + t140 a 4 INT 9 10 10 0 1 NULL + t140 b 4 INT 9 10 10 0 1 NULL + t140 c 4 INT 9 10 10 0 1 NULL + t140 d 4 INT 9 10 10 0 1 NULL + t140 e 4 INT 9 10 10 0 1 NULL + t141 a 4 INT 9 10 10 0 1 NULL + t141 b 4 INT 9 10 10 0 1 NULL + t141 c 4 INT 9 10 10 0 1 NULL + t141 d 4 INT 9 10 10 0 1 NULL + t141 e 4 INT 9 10 10 0 1 NULL + t142 a 4 INT 9 10 10 0 1 NULL + t142 b 4 INT 9 10 10 0 1 NULL + t142 c 4 INT 9 10 10 0 1 NULL + t142 d 4 INT 9 10 10 0 1 NULL + t142 e 4 INT 9 10 10 0 1 NULL + t143 a 4 INT 9 10 10 0 1 NULL + t143 b 4 INT 9 10 10 0 1 NULL + t143 c 4 INT 9 10 10 0 1 NULL + t143 d 4 INT 9 10 10 0 1 NULL + t143 e 4 INT 9 10 10 0 1 NULL + t144 a 4 INT 9 10 10 0 1 NULL + t144 b 4 INT 9 10 10 0 1 NULL + t144 c 4 INT 9 10 10 0 1 NULL + t144 d 4 INT 9 10 10 0 1 NULL + t144 e 4 INT 9 10 10 0 1 NULL + t145 a 4 INT 9 10 10 0 1 NULL + t145 b 4 INT 9 10 10 0 1 NULL + t145 c 4 INT 9 10 10 0 1 NULL + t145 d 4 INT 9 10 10 0 1 NULL + t145 e 4 INT 9 10 10 0 1 NULL + t146 a 4 INT 9 10 10 0 1 NULL + t146 b 4 INT 9 10 10 0 1 NULL + t146 c 4 INT 9 10 10 0 1 NULL + t146 d 4 INT 9 10 10 0 1 NULL + t146 e 4 INT 9 10 10 0 1 NULL + t147 a 4 INT 9 10 10 0 1 NULL + t147 b 4 INT 9 10 10 0 1 NULL + t147 c 4 INT 9 10 10 0 1 NULL + t147 d 4 INT 9 10 10 0 1 NULL + t147 e 4 INT 9 10 10 0 1 NULL + t148 a 4 INT 9 10 10 0 1 NULL + t148 b 4 INT 9 10 10 0 1 NULL + t148 c 4 INT 9 10 10 0 1 NULL + t148 d 4 INT 9 10 10 0 1 NULL + t148 e 4 INT 9 10 10 0 1 NULL + t149 a 4 INT 9 10 10 0 1 NULL + t149 b 4 INT 9 10 10 0 1 NULL + t149 c 4 INT 9 10 10 0 1 NULL + t149 d 4 INT 9 10 10 0 1 NULL + t149 e 4 INT 9 10 10 0 1 NULL + t150 a 4 INT 9 10 10 0 1 NULL + t150 b 4 INT 9 10 10 0 1 NULL + t150 c 4 INT 9 10 10 0 1 NULL + t150 d 4 INT 9 10 10 0 1 NULL + t150 e 4 INT 9 10 10 0 1 NULL + t151 a 4 INT 9 10 10 0 1 NULL + t151 b 4 INT 9 10 10 0 1 NULL + t151 c 4 INT 9 10 10 0 1 NULL + t151 d 4 INT 9 10 10 0 1 NULL + t151 e 4 INT 9 10 10 0 1 NULL + t152 a 4 INT 9 10 10 0 1 NULL + t152 b 4 INT 9 10 10 0 1 NULL + t152 c 4 INT 9 10 10 0 1 NULL + t152 d 4 INT 9 10 10 0 1 NULL + t152 e 4 INT 9 10 10 0 1 NULL + t153 a 4 INT 9 10 10 0 1 NULL + t153 b 4 INT 9 10 10 0 1 NULL + t153 c 4 INT 9 10 10 0 1 NULL + t153 d 4 INT 9 10 10 0 1 NULL + t153 e 4 INT 9 10 10 0 1 NULL + t154 a 4 INT 9 10 10 0 1 NULL + t154 b 4 INT 9 10 10 0 1 NULL + t154 c 4 INT 9 10 10 0 1 NULL + t154 d 4 INT 9 10 10 0 1 NULL + t154 e 4 INT 9 10 10 0 1 NULL + t155 a 4 INT 9 10 10 0 1 NULL + t155 b 4 INT 9 10 10 0 1 NULL + t155 c 4 INT 9 10 10 0 1 NULL + t155 d 4 INT 9 10 10 0 1 NULL + t155 e 4 INT 9 10 10 0 1 NULL + t156 a 4 INT 9 10 10 0 1 NULL + t156 b 4 INT 9 10 10 0 1 NULL + t156 c 4 INT 9 10 10 0 1 NULL + t156 d 4 INT 9 10 10 0 1 NULL + t156 e 4 INT 9 10 10 0 1 NULL + t157 a 4 INT 9 10 10 0 1 NULL + t157 b 4 INT 9 10 10 0 1 NULL + t157 c 4 INT 9 10 10 0 1 NULL + t157 d 4 INT 9 10 10 0 1 NULL + t157 e 4 INT 9 10 10 0 1 NULL + t158 a 4 INT 9 10 10 0 1 NULL + t158 b 4 INT 9 10 10 0 1 NULL + t158 c 4 INT 9 10 10 0 1 NULL + t158 d 4 INT 9 10 10 0 1 NULL + t158 e 4 INT 9 10 10 0 1 NULL + t159 a 4 INT 9 10 10 0 1 NULL + t159 b 4 INT 9 10 10 0 1 NULL + t159 c 4 INT 9 10 10 0 1 NULL + t159 d 4 INT 9 10 10 0 1 NULL + t159 e 4 INT 9 10 10 0 1 NULL + t160 a 4 INT 9 10 10 0 1 NULL + t160 b 4 INT 9 10 10 0 1 NULL + t160 c 4 INT 9 10 10 0 1 NULL + t160 d 4 INT 9 10 10 0 1 NULL + t160 e 4 INT 9 10 10 0 1 NULL + t161 a 4 INT 9 10 10 0 1 NULL + t161 b 4 INT 9 10 10 0 1 NULL + t161 c 4 INT 9 10 10 0 1 NULL + t161 d 4 INT 9 10 10 0 1 NULL + t161 e 4 INT 9 10 10 0 1 NULL + t162 a 4 INT 9 10 10 0 1 NULL + t162 b 4 INT 9 10 10 0 1 NULL + t162 c 4 INT 9 10 10 0 1 NULL + t162 d 4 INT 9 10 10 0 1 NULL + t162 e 4 INT 9 10 10 0 1 NULL + t163 a 4 INT 9 10 10 0 1 NULL + t163 b 4 INT 9 10 10 0 1 NULL + t163 c 4 INT 9 10 10 0 1 NULL + t163 d 4 INT 9 10 10 0 1 NULL + t163 e 4 INT 9 10 10 0 1 NULL + t164 a 4 INT 9 10 10 0 1 NULL + t164 b 4 INT 9 10 10 0 1 NULL + t164 c 4 INT 9 10 10 0 1 NULL + t164 d 4 INT 9 10 10 0 1 NULL + t164 e 4 INT 9 10 10 0 1 NULL + t165 a 4 INT 9 10 10 0 1 NULL + t165 b 4 INT 9 10 10 0 1 NULL + t165 c 4 INT 9 10 10 0 1 NULL + t165 d 4 INT 9 10 10 0 1 NULL + t165 e 4 INT 9 10 10 0 1 NULL + t166 a 4 INT 9 10 10 0 1 NULL + t166 b 4 INT 9 10 10 0 1 NULL + t166 c 4 INT 9 10 10 0 1 NULL + t166 d 4 INT 9 10 10 0 1 NULL + t166 e 4 INT 9 10 10 0 1 NULL + t167 a 4 INT 9 10 10 0 1 NULL + t167 b 4 INT 9 10 10 0 1 NULL + t167 c 4 INT 9 10 10 0 1 NULL + t167 d 4 INT 9 10 10 0 1 NULL + t167 e 4 INT 9 10 10 0 1 NULL + t168 a 4 INT 9 10 10 0 1 NULL + t168 b 4 INT 9 10 10 0 1 NULL + t168 c 4 INT 9 10 10 0 1 NULL + t168 d 4 INT 9 10 10 0 1 NULL + t168 e 4 INT 9 10 10 0 1 NULL + t169 a 4 INT 9 10 10 0 1 NULL + t169 b 4 INT 9 10 10 0 1 NULL + t169 c 4 INT 9 10 10 0 1 NULL + t169 d 4 INT 9 10 10 0 1 NULL + t169 e 4 INT 9 10 10 0 1 NULL + t170 a 4 INT 9 10 10 0 1 NULL + t170 b 4 INT 9 10 10 0 1 NULL + t170 c 4 INT 9 10 10 0 1 NULL + t170 d 4 INT 9 10 10 0 1 NULL + t170 e 4 INT 9 10 10 0 1 NULL + t171 a 4 INT 9 10 10 0 1 NULL + t171 b 4 INT 9 10 10 0 1 NULL + t171 c 4 INT 9 10 10 0 1 NULL + t171 d 4 INT 9 10 10 0 1 NULL + t171 e 4 INT 9 10 10 0 1 NULL + t172 a 4 INT 9 10 10 0 1 NULL + t172 b 4 INT 9 10 10 0 1 NULL + t172 c 4 INT 9 10 10 0 1 NULL + t172 d 4 INT 9 10 10 0 1 NULL + t172 e 4 INT 9 10 10 0 1 NULL + t173 a 4 INT 9 10 10 0 1 NULL + t173 b 4 INT 9 10 10 0 1 NULL + t173 c 4 INT 9 10 10 0 1 NULL + t173 d 4 INT 9 10 10 0 1 NULL + t173 e 4 INT 9 10 10 0 1 NULL + t174 a 4 INT 9 10 10 0 1 NULL + t174 b 4 INT 9 10 10 0 1 NULL + t174 c 4 INT 9 10 10 0 1 NULL + t174 d 4 INT 9 10 10 0 1 NULL + t174 e 4 INT 9 10 10 0 1 NULL + t175 a 4 INT 9 10 10 0 1 NULL + t175 b 4 INT 9 10 10 0 1 NULL + t175 c 4 INT 9 10 10 0 1 NULL + t175 d 4 INT 9 10 10 0 1 NULL + t175 e 4 INT 9 10 10 0 1 NULL + t176 a 4 INT 9 10 10 0 1 NULL + t176 b 4 INT 9 10 10 0 1 NULL + t176 c 4 INT 9 10 10 0 1 NULL + t176 d 4 INT 9 10 10 0 1 NULL + t176 e 4 INT 9 10 10 0 1 NULL + t177 a 4 INT 9 10 10 0 1 NULL + t177 b 4 INT 9 10 10 0 1 NULL + t177 c 4 INT 9 10 10 0 1 NULL + t177 d 4 INT 9 10 10 0 1 NULL + t177 e 4 INT 9 10 10 0 1 NULL + t178 a 4 INT 9 10 10 0 1 NULL + t178 b 4 INT 9 10 10 0 1 NULL + t178 c 4 INT 9 10 10 0 1 NULL + t178 d 4 INT 9 10 10 0 1 NULL + t178 e 4 INT 9 10 10 0 1 NULL + t179 a 4 INT 9 10 10 0 1 NULL + t179 b 4 INT 9 10 10 0 1 NULL + t179 c 4 INT 9 10 10 0 1 NULL + t179 d 4 INT 9 10 10 0 1 NULL + t179 e 4 INT 9 10 10 0 1 NULL + t180 a 4 INT 9 10 10 0 1 NULL + t180 b 4 INT 9 10 10 0 1 NULL + t180 c 4 INT 9 10 10 0 1 NULL + t180 d 4 INT 9 10 10 0 1 NULL + t180 e 4 INT 9 10 10 0 1 NULL + t181 a 4 INT 9 10 10 0 1 NULL + t181 b 4 INT 9 10 10 0 1 NULL + t181 c 4 INT 9 10 10 0 1 NULL + t181 d 4 INT 9 10 10 0 1 NULL + t181 e 4 INT 9 10 10 0 1 NULL + t182 a 4 INT 9 10 10 0 1 NULL + t182 b 4 INT 9 10 10 0 1 NULL + t182 c 4 INT 9 10 10 0 1 NULL + t182 d 4 INT 9 10 10 0 1 NULL + t182 e 4 INT 9 10 10 0 1 NULL + t183 a 4 INT 9 10 10 0 1 NULL + t183 b 4 INT 9 10 10 0 1 NULL + t183 c 4 INT 9 10 10 0 1 NULL + t183 d 4 INT 9 10 10 0 1 NULL + t183 e 4 INT 9 10 10 0 1 NULL + t184 a 4 INT 9 10 10 0 1 NULL + t184 b 4 INT 9 10 10 0 1 NULL + t184 c 4 INT 9 10 10 0 1 NULL + t184 d 4 INT 9 10 10 0 1 NULL + t184 e 4 INT 9 10 10 0 1 NULL + t185 a 4 INT 9 10 10 0 1 NULL + t185 b 4 INT 9 10 10 0 1 NULL + t185 c 4 INT 9 10 10 0 1 NULL + t185 d 4 INT 9 10 10 0 1 NULL + t185 e 4 INT 9 10 10 0 1 NULL + t186 a 4 INT 9 10 10 0 1 NULL + t186 b 4 INT 9 10 10 0 1 NULL + t186 c 4 INT 9 10 10 0 1 NULL + t186 d 4 INT 9 10 10 0 1 NULL + t186 e 4 INT 9 10 10 0 1 NULL + t187 a 4 INT 9 10 10 0 1 NULL + t187 b 4 INT 9 10 10 0 1 NULL + t187 c 4 INT 9 10 10 0 1 NULL + t187 d 4 INT 9 10 10 0 1 NULL + t187 e 4 INT 9 10 10 0 1 NULL + t188 a 4 INT 9 10 10 0 1 NULL + t188 b 4 INT 9 10 10 0 1 NULL + t188 c 4 INT 9 10 10 0 1 NULL + t188 d 4 INT 9 10 10 0 1 NULL + t188 e 4 INT 9 10 10 0 1 NULL + t189 a 4 INT 9 10 10 0 1 NULL + t189 b 4 INT 9 10 10 0 1 NULL + t189 c 4 INT 9 10 10 0 1 NULL + t189 d 4 INT 9 10 10 0 1 NULL + t189 e 4 INT 9 10 10 0 1 NULL + t190 a 4 INT 9 10 10 0 1 NULL + t190 b 4 INT 9 10 10 0 1 NULL + t190 c 4 INT 9 10 10 0 1 NULL + t190 d 4 INT 9 10 10 0 1 NULL + t190 e 4 INT 9 10 10 0 1 NULL + t191 a 4 INT 9 10 10 0 1 NULL + t191 b 4 INT 9 10 10 0 1 NULL + t191 c 4 INT 9 10 10 0 1 NULL + t191 d 4 INT 9 10 10 0 1 NULL + t191 e 4 INT 9 10 10 0 1 NULL + t192 a 4 INT 9 10 10 0 1 NULL + t192 b 4 INT 9 10 10 0 1 NULL + t192 c 4 INT 9 10 10 0 1 NULL + t192 d 4 INT 9 10 10 0 1 NULL + t192 e 4 INT 9 10 10 0 1 NULL + t193 a 4 INT 9 10 10 0 1 NULL + t193 b 4 INT 9 10 10 0 1 NULL + t193 c 4 INT 9 10 10 0 1 NULL + t193 d 4 INT 9 10 10 0 1 NULL + t193 e 4 INT 9 10 10 0 1 NULL + t194 a 4 INT 9 10 10 0 1 NULL + t194 b 4 INT 9 10 10 0 1 NULL + t194 c 4 INT 9 10 10 0 1 NULL + t194 d 4 INT 9 10 10 0 1 NULL + t194 e 4 INT 9 10 10 0 1 NULL + t195 a 4 INT 9 10 10 0 1 NULL + t195 b 4 INT 9 10 10 0 1 NULL + t195 c 4 INT 9 10 10 0 1 NULL + t195 d 4 INT 9 10 10 0 1 NULL + t195 e 4 INT 9 10 10 0 1 NULL + t196 a 4 INT 9 10 10 0 1 NULL + t196 b 4 INT 9 10 10 0 1 NULL + t196 c 4 INT 9 10 10 0 1 NULL + t196 d 4 INT 9 10 10 0 1 NULL + t196 e 4 INT 9 10 10 0 1 NULL + t197 a 4 INT 9 10 10 0 1 NULL + t197 b 4 INT 9 10 10 0 1 NULL + t197 c 4 INT 9 10 10 0 1 NULL + t197 d 4 INT 9 10 10 0 1 NULL + t197 e 4 INT 9 10 10 0 1 NULL + t198 a 4 INT 9 10 10 0 1 NULL + t198 b 4 INT 9 10 10 0 1 NULL + t198 c 4 INT 9 10 10 0 1 NULL + t198 d 4 INT 9 10 10 0 1 NULL + t198 e 4 INT 9 10 10 0 1 NULL + t199 a 4 INT 9 10 10 0 1 NULL + t199 b 4 INT 9 10 10 0 1 NULL + t199 c 4 INT 9 10 10 0 1 NULL + t199 d 4 INT 9 10 10 0 1 NULL + t199 e 4 INT 9 10 10 0 1 NULL + t200 a 4 INT 9 10 10 0 1 NULL + t200 b 4 INT 9 10 10 0 1 NULL + t200 c 4 INT 9 10 10 0 1 NULL + t200 d 4 INT 9 10 10 0 1 NULL + t200 e 4 INT 9 10 10 0 1 NULL + t201 a 4 INT 9 10 10 0 1 NULL + t201 b 4 INT 9 10 10 0 1 NULL + t201 c 4 INT 9 10 10 0 1 NULL + t201 d 4 INT 9 10 10 0 1 NULL + t201 e 4 INT 9 10 10 0 1 NULL + t202 a 4 INT 9 10 10 0 1 NULL + t202 b 4 INT 9 10 10 0 1 NULL + t202 c 4 INT 9 10 10 0 1 NULL + t202 d 4 INT 9 10 10 0 1 NULL + t202 e 4 INT 9 10 10 0 1 NULL + t203 a 4 INT 9 10 10 0 1 NULL + t203 b 4 INT 9 10 10 0 1 NULL + t203 c 4 INT 9 10 10 0 1 NULL + t203 d 4 INT 9 10 10 0 1 NULL + t203 e 4 INT 9 10 10 0 1 NULL + t204 a 4 INT 9 10 10 0 1 NULL + t204 b 4 INT 9 10 10 0 1 NULL + t204 c 4 INT 9 10 10 0 1 NULL + t204 d 4 INT 9 10 10 0 1 NULL + t204 e 4 INT 9 10 10 0 1 NULL + t205 a 4 INT 9 10 10 0 1 NULL + t205 b 4 INT 9 10 10 0 1 NULL + t205 c 4 INT 9 10 10 0 1 NULL + t205 d 4 INT 9 10 10 0 1 NULL + t205 e 4 INT 9 10 10 0 1 NULL + t206 a 4 INT 9 10 10 0 1 NULL + t206 b 4 INT 9 10 10 0 1 NULL + t206 c 4 INT 9 10 10 0 1 NULL + t206 d 4 INT 9 10 10 0 1 NULL + t206 e 4 INT 9 10 10 0 1 NULL + t207 a 4 INT 9 10 10 0 1 NULL + t207 b 4 INT 9 10 10 0 1 NULL + t207 c 4 INT 9 10 10 0 1 NULL + t207 d 4 INT 9 10 10 0 1 NULL + t207 e 4 INT 9 10 10 0 1 NULL + t208 a 4 INT 9 10 10 0 1 NULL + t208 b 4 INT 9 10 10 0 1 NULL + t208 c 4 INT 9 10 10 0 1 NULL + t208 d 4 INT 9 10 10 0 1 NULL + t208 e 4 INT 9 10 10 0 1 NULL + t209 a 4 INT 9 10 10 0 1 NULL + t209 b 4 INT 9 10 10 0 1 NULL + t209 c 4 INT 9 10 10 0 1 NULL + t209 d 4 INT 9 10 10 0 1 NULL + t209 e 4 INT 9 10 10 0 1 NULL + t210 a 4 INT 9 10 10 0 1 NULL + t210 b 4 INT 9 10 10 0 1 NULL + t210 c 4 INT 9 10 10 0 1 NULL + t210 d 4 INT 9 10 10 0 1 NULL + t210 e 4 INT 9 10 10 0 1 NULL + t211 a 4 INT 9 10 10 0 1 NULL + t211 b 4 INT 9 10 10 0 1 NULL + t211 c 4 INT 9 10 10 0 1 NULL + t211 d 4 INT 9 10 10 0 1 NULL + t211 e 4 INT 9 10 10 0 1 NULL + t212 a 4 INT 9 10 10 0 1 NULL + t212 b 4 INT 9 10 10 0 1 NULL + t212 c 4 INT 9 10 10 0 1 NULL + t212 d 4 INT 9 10 10 0 1 NULL + t212 e 4 INT 9 10 10 0 1 NULL + t213 a 4 INT 9 10 10 0 1 NULL + t213 b 4 INT 9 10 10 0 1 NULL + t213 c 4 INT 9 10 10 0 1 NULL + t213 d 4 INT 9 10 10 0 1 NULL + t213 e 4 INT 9 10 10 0 1 NULL + t214 a 4 INT 9 10 10 0 1 NULL + t214 b 4 INT 9 10 10 0 1 NULL + t214 c 4 INT 9 10 10 0 1 NULL + t214 d 4 INT 9 10 10 0 1 NULL + t214 e 4 INT 9 10 10 0 1 NULL + t215 a 4 INT 9 10 10 0 1 NULL + t215 b 4 INT 9 10 10 0 1 NULL + t215 c 4 INT 9 10 10 0 1 NULL + t215 d 4 INT 9 10 10 0 1 NULL + t215 e 4 INT 9 10 10 0 1 NULL + t216 a 4 INT 9 10 10 0 1 NULL + t216 b 4 INT 9 10 10 0 1 NULL + t216 c 4 INT 9 10 10 0 1 NULL + t216 d 4 INT 9 10 10 0 1 NULL + t216 e 4 INT 9 10 10 0 1 NULL + t217 a 4 INT 9 10 10 0 1 NULL + t217 b 4 INT 9 10 10 0 1 NULL + t217 c 4 INT 9 10 10 0 1 NULL + t217 d 4 INT 9 10 10 0 1 NULL + t217 e 4 INT 9 10 10 0 1 NULL + t218 a 4 INT 9 10 10 0 1 NULL + t218 b 4 INT 9 10 10 0 1 NULL + t218 c 4 INT 9 10 10 0 1 NULL + t218 d 4 INT 9 10 10 0 1 NULL + t218 e 4 INT 9 10 10 0 1 NULL + t219 a 4 INT 9 10 10 0 1 NULL + t219 b 4 INT 9 10 10 0 1 NULL + t219 c 4 INT 9 10 10 0 1 NULL + t219 d 4 INT 9 10 10 0 1 NULL + t219 e 4 INT 9 10 10 0 1 NULL + t220 a 4 INT 9 10 10 0 1 NULL + t220 b 4 INT 9 10 10 0 1 NULL + t220 c 4 INT 9 10 10 0 1 NULL + t220 d 4 INT 9 10 10 0 1 NULL + t220 e 4 INT 9 10 10 0 1 NULL + t221 a 4 INT 9 10 10 0 1 NULL + t221 b 4 INT 9 10 10 0 1 NULL + t221 c 4 INT 9 10 10 0 1 NULL + t221 d 4 INT 9 10 10 0 1 NULL + t221 e 4 INT 9 10 10 0 1 NULL + t222 a 4 INT 9 10 10 0 1 NULL + t222 b 4 INT 9 10 10 0 1 NULL + t222 c 4 INT 9 10 10 0 1 NULL + t222 d 4 INT 9 10 10 0 1 NULL + t222 e 4 INT 9 10 10 0 1 NULL + t223 a 4 INT 9 10 10 0 1 NULL + t223 b 4 INT 9 10 10 0 1 NULL + t223 c 4 INT 9 10 10 0 1 NULL + t223 d 4 INT 9 10 10 0 1 NULL + t223 e 4 INT 9 10 10 0 1 NULL + t224 a 4 INT 9 10 10 0 1 NULL + t224 b 4 INT 9 10 10 0 1 NULL + t224 c 4 INT 9 10 10 0 1 NULL + t224 d 4 INT 9 10 10 0 1 NULL + t224 e 4 INT 9 10 10 0 1 NULL + t225 a 4 INT 9 10 10 0 1 NULL + t225 b 4 INT 9 10 10 0 1 NULL + t225 c 4 INT 9 10 10 0 1 NULL + t225 d 4 INT 9 10 10 0 1 NULL + t225 e 4 INT 9 10 10 0 1 NULL + t226 a 4 INT 9 10 10 0 1 NULL + t226 b 4 INT 9 10 10 0 1 NULL + t226 c 4 INT 9 10 10 0 1 NULL + t226 d 4 INT 9 10 10 0 1 NULL + t226 e 4 INT 9 10 10 0 1 NULL + t227 a 4 INT 9 10 10 0 1 NULL + t227 b 4 INT 9 10 10 0 1 NULL + t227 c 4 INT 9 10 10 0 1 NULL + t227 d 4 INT 9 10 10 0 1 NULL + t227 e 4 INT 9 10 10 0 1 NULL + t228 a 4 INT 9 10 10 0 1 NULL + t228 b 4 INT 9 10 10 0 1 NULL + t228 c 4 INT 9 10 10 0 1 NULL + t228 d 4 INT 9 10 10 0 1 NULL + t228 e 4 INT 9 10 10 0 1 NULL + t229 a 4 INT 9 10 10 0 1 NULL + t229 b 4 INT 9 10 10 0 1 NULL + t229 c 4 INT 9 10 10 0 1 NULL + t229 d 4 INT 9 10 10 0 1 NULL + t229 e 4 INT 9 10 10 0 1 NULL + t230 a 4 INT 9 10 10 0 1 NULL + t230 b 4 INT 9 10 10 0 1 NULL + t230 c 4 INT 9 10 10 0 1 NULL + t230 d 4 INT 9 10 10 0 1 NULL + t230 e 4 INT 9 10 10 0 1 NULL + t231 a 4 INT 9 10 10 0 1 NULL + t231 b 4 INT 9 10 10 0 1 NULL + t231 c 4 INT 9 10 10 0 1 NULL + t231 d 4 INT 9 10 10 0 1 NULL + t231 e 4 INT 9 10 10 0 1 NULL + t232 a 4 INT 9 10 10 0 1 NULL + t232 b 4 INT 9 10 10 0 1 NULL + t232 c 4 INT 9 10 10 0 1 NULL + t232 d 4 INT 9 10 10 0 1 NULL + t232 e 4 INT 9 10 10 0 1 NULL + t233 a 4 INT 9 10 10 0 1 NULL + t233 b 4 INT 9 10 10 0 1 NULL + t233 c 4 INT 9 10 10 0 1 NULL + t233 d 4 INT 9 10 10 0 1 NULL + t233 e 4 INT 9 10 10 0 1 NULL + t234 a 4 INT 9 10 10 0 1 NULL + t234 b 4 INT 9 10 10 0 1 NULL + t234 c 4 INT 9 10 10 0 1 NULL + t234 d 4 INT 9 10 10 0 1 NULL + t234 e 4 INT 9 10 10 0 1 NULL + t235 a 4 INT 9 10 10 0 1 NULL + t235 b 4 INT 9 10 10 0 1 NULL + t235 c 4 INT 9 10 10 0 1 NULL + t235 d 4 INT 9 10 10 0 1 NULL + t235 e 4 INT 9 10 10 0 1 NULL + t236 a 4 INT 9 10 10 0 1 NULL + t236 b 4 INT 9 10 10 0 1 NULL + t236 c 4 INT 9 10 10 0 1 NULL + t236 d 4 INT 9 10 10 0 1 NULL + t236 e 4 INT 9 10 10 0 1 NULL + t237 a 4 INT 9 10 10 0 1 NULL + t237 b 4 INT 9 10 10 0 1 NULL + t237 c 4 INT 9 10 10 0 1 NULL + t237 d 4 INT 9 10 10 0 1 NULL + t237 e 4 INT 9 10 10 0 1 NULL + t238 a 4 INT 9 10 10 0 1 NULL + t238 b 4 INT 9 10 10 0 1 NULL + t238 c 4 INT 9 10 10 0 1 NULL + t238 d 4 INT 9 10 10 0 1 NULL + t238 e 4 INT 9 10 10 0 1 NULL + t239 a 4 INT 9 10 10 0 1 NULL + t239 b 4 INT 9 10 10 0 1 NULL + t239 c 4 INT 9 10 10 0 1 NULL + t239 d 4 INT 9 10 10 0 1 NULL + t239 e 4 INT 9 10 10 0 1 NULL + t240 a 4 INT 9 10 10 0 1 NULL + t240 b 4 INT 9 10 10 0 1 NULL + t240 c 4 INT 9 10 10 0 1 NULL + t240 d 4 INT 9 10 10 0 1 NULL + t240 e 4 INT 9 10 10 0 1 NULL + t241 a 4 INT 9 10 10 0 1 NULL + t241 b 4 INT 9 10 10 0 1 NULL + t241 c 4 INT 9 10 10 0 1 NULL + t241 d 4 INT 9 10 10 0 1 NULL + t241 e 4 INT 9 10 10 0 1 NULL + t242 a 4 INT 9 10 10 0 1 NULL + t242 b 4 INT 9 10 10 0 1 NULL + t242 c 4 INT 9 10 10 0 1 NULL + t242 d 4 INT 9 10 10 0 1 NULL + t242 e 4 INT 9 10 10 0 1 NULL + t243 a 4 INT 9 10 10 0 1 NULL + t243 b 4 INT 9 10 10 0 1 NULL + t243 c 4 INT 9 10 10 0 1 NULL + t243 d 4 INT 9 10 10 0 1 NULL + t243 e 4 INT 9 10 10 0 1 NULL + t244 a 4 INT 9 10 10 0 1 NULL + t244 b 4 INT 9 10 10 0 1 NULL + t244 c 4 INT 9 10 10 0 1 NULL + t244 d 4 INT 9 10 10 0 1 NULL + t244 e 4 INT 9 10 10 0 1 NULL + t245 a 4 INT 9 10 10 0 1 NULL + t245 b 4 INT 9 10 10 0 1 NULL + t245 c 4 INT 9 10 10 0 1 NULL + t245 d 4 INT 9 10 10 0 1 NULL + t245 e 4 INT 9 10 10 0 1 NULL + t246 a 4 INT 9 10 10 0 1 NULL + t246 b 4 INT 9 10 10 0 1 NULL + t246 c 4 INT 9 10 10 0 1 NULL + t246 d 4 INT 9 10 10 0 1 NULL + t246 e 4 INT 9 10 10 0 1 NULL + t247 a 4 INT 9 10 10 0 1 NULL + t247 b 4 INT 9 10 10 0 1 NULL + t247 c 4 INT 9 10 10 0 1 NULL + t247 d 4 INT 9 10 10 0 1 NULL + t247 e 4 INT 9 10 10 0 1 NULL + t248 a 4 INT 9 10 10 0 1 NULL + t248 b 4 INT 9 10 10 0 1 NULL + t248 c 4 INT 9 10 10 0 1 NULL + t248 d 4 INT 9 10 10 0 1 NULL + t248 e 4 INT 9 10 10 0 1 NULL + t249 a 4 INT 9 10 10 0 1 NULL + t249 b 4 INT 9 10 10 0 1 NULL + t249 c 4 INT 9 10 10 0 1 NULL + t249 d 4 INT 9 10 10 0 1 NULL + t249 e 4 INT 9 10 10 0 1 NULL + t250 a 4 INT 9 10 10 0 1 NULL + t250 b 4 INT 9 10 10 0 1 NULL + t250 c 4 INT 9 10 10 0 1 NULL + t250 d 4 INT 9 10 10 0 1 NULL + t250 e 4 INT 9 10 10 0 1 NULL + t251 a 4 INT 9 10 10 0 1 NULL + t251 b 4 INT 9 10 10 0 1 NULL + t251 c 4 INT 9 10 10 0 1 NULL + t251 d 4 INT 9 10 10 0 1 NULL + t251 e 4 INT 9 10 10 0 1 NULL + t252 a 4 INT 9 10 10 0 1 NULL + t252 b 4 INT 9 10 10 0 1 NULL + t252 c 4 INT 9 10 10 0 1 NULL + t252 d 4 INT 9 10 10 0 1 NULL + t252 e 4 INT 9 10 10 0 1 NULL + t253 a 4 INT 9 10 10 0 1 NULL + t253 b 4 INT 9 10 10 0 1 NULL + t253 c 4 INT 9 10 10 0 1 NULL + t253 d 4 INT 9 10 10 0 1 NULL + t253 e 4 INT 9 10 10 0 1 NULL + t254 a 4 INT 9 10 10 0 1 NULL + t254 b 4 INT 9 10 10 0 1 NULL + t254 c 4 INT 9 10 10 0 1 NULL + t254 d 4 INT 9 10 10 0 1 NULL + t254 e 4 INT 9 10 10 0 1 NULL + t255 a 4 INT 9 10 10 0 1 NULL + t255 b 4 INT 9 10 10 0 1 NULL + t255 c 4 INT 9 10 10 0 1 NULL + t255 d 4 INT 9 10 10 0 1 NULL + t255 e 4 INT 9 10 10 0 1 NULL + t256 a 4 INT 9 10 10 0 1 NULL + t256 b 4 INT 9 10 10 0 1 NULL + t256 c 4 INT 9 10 10 0 1 NULL + t256 d 4 INT 9 10 10 0 1 NULL + t256 e 4 INT 9 10 10 0 1 NULL + t257 a 4 INT 9 10 10 0 1 NULL + t257 b 4 INT 9 10 10 0 1 NULL + t257 c 4 INT 9 10 10 0 1 NULL + t257 d 4 INT 9 10 10 0 1 NULL + t257 e 4 INT 9 10 10 0 1 NULL + t258 a 4 INT 9 10 10 0 1 NULL + t258 b 4 INT 9 10 10 0 1 NULL + t258 c 4 INT 9 10 10 0 1 NULL + t258 d 4 INT 9 10 10 0 1 NULL + t258 e 4 INT 9 10 10 0 1 NULL + t259 a 4 INT 9 10 10 0 1 NULL + t259 b 4 INT 9 10 10 0 1 NULL + t259 c 4 INT 9 10 10 0 1 NULL + t259 d 4 INT 9 10 10 0 1 NULL + t259 e 4 INT 9 10 10 0 1 NULL + t260 a 4 INT 9 10 10 0 1 NULL + t260 b 4 INT 9 10 10 0 1 NULL + t260 c 4 INT 9 10 10 0 1 NULL + t260 d 4 INT 9 10 10 0 1 NULL + t260 e 4 INT 9 10 10 0 1 NULL + t261 a 4 INT 9 10 10 0 1 NULL + t261 b 4 INT 9 10 10 0 1 NULL + t261 c 4 INT 9 10 10 0 1 NULL + t261 d 4 INT 9 10 10 0 1 NULL + t261 e 4 INT 9 10 10 0 1 NULL + t262 a 4 INT 9 10 10 0 1 NULL + t262 b 4 INT 9 10 10 0 1 NULL + t262 c 4 INT 9 10 10 0 1 NULL + t262 d 4 INT 9 10 10 0 1 NULL + t262 e 4 INT 9 10 10 0 1 NULL + t263 a 4 INT 9 10 10 0 1 NULL + t263 b 4 INT 9 10 10 0 1 NULL + t263 c 4 INT 9 10 10 0 1 NULL + t263 d 4 INT 9 10 10 0 1 NULL + t263 e 4 INT 9 10 10 0 1 NULL + t264 a 4 INT 9 10 10 0 1 NULL + t264 b 4 INT 9 10 10 0 1 NULL + t264 c 4 INT 9 10 10 0 1 NULL + t264 d 4 INT 9 10 10 0 1 NULL + t264 e 4 INT 9 10 10 0 1 NULL + t265 a 4 INT 9 10 10 0 1 NULL + t265 b 4 INT 9 10 10 0 1 NULL + t265 c 4 INT 9 10 10 0 1 NULL + t265 d 4 INT 9 10 10 0 1 NULL + t265 e 4 INT 9 10 10 0 1 NULL + t266 a 4 INT 9 10 10 0 1 NULL + t266 b 4 INT 9 10 10 0 1 NULL + t266 c 4 INT 9 10 10 0 1 NULL + t266 d 4 INT 9 10 10 0 1 NULL + t266 e 4 INT 9 10 10 0 1 NULL + t267 a 4 INT 9 10 10 0 1 NULL + t267 b 4 INT 9 10 10 0 1 NULL + t267 c 4 INT 9 10 10 0 1 NULL + t267 d 4 INT 9 10 10 0 1 NULL + t267 e 4 INT 9 10 10 0 1 NULL + t268 a 4 INT 9 10 10 0 1 NULL + t268 b 4 INT 9 10 10 0 1 NULL + t268 c 4 INT 9 10 10 0 1 NULL + t268 d 4 INT 9 10 10 0 1 NULL + t268 e 4 INT 9 10 10 0 1 NULL + t269 a 4 INT 9 10 10 0 1 NULL + t269 b 4 INT 9 10 10 0 1 NULL + t269 c 4 INT 9 10 10 0 1 NULL + t269 d 4 INT 9 10 10 0 1 NULL + t269 e 4 INT 9 10 10 0 1 NULL + t270 a 4 INT 9 10 10 0 1 NULL + t270 b 4 INT 9 10 10 0 1 NULL + t270 c 4 INT 9 10 10 0 1 NULL + t270 d 4 INT 9 10 10 0 1 NULL + t270 e 4 INT 9 10 10 0 1 NULL + t271 a 4 INT 9 10 10 0 1 NULL + t271 b 4 INT 9 10 10 0 1 NULL + t271 c 4 INT 9 10 10 0 1 NULL + t271 d 4 INT 9 10 10 0 1 NULL + t271 e 4 INT 9 10 10 0 1 NULL + t272 a 4 INT 9 10 10 0 1 NULL + t272 b 4 INT 9 10 10 0 1 NULL + t272 c 4 INT 9 10 10 0 1 NULL + t272 d 4 INT 9 10 10 0 1 NULL + t272 e 4 INT 9 10 10 0 1 NULL + t273 a 4 INT 9 10 10 0 1 NULL + t273 b 4 INT 9 10 10 0 1 NULL + t273 c 4 INT 9 10 10 0 1 NULL + t273 d 4 INT 9 10 10 0 1 NULL + t273 e 4 INT 9 10 10 0 1 NULL + t274 a 4 INT 9 10 10 0 1 NULL + t274 b 4 INT 9 10 10 0 1 NULL + t274 c 4 INT 9 10 10 0 1 NULL + t274 d 4 INT 9 10 10 0 1 NULL + t274 e 4 INT 9 10 10 0 1 NULL + t275 a 4 INT 9 10 10 0 1 NULL + t275 b 4 INT 9 10 10 0 1 NULL + t275 c 4 INT 9 10 10 0 1 NULL + t275 d 4 INT 9 10 10 0 1 NULL + t275 e 4 INT 9 10 10 0 1 NULL + t276 a 4 INT 9 10 10 0 1 NULL + t276 b 4 INT 9 10 10 0 1 NULL + t276 c 4 INT 9 10 10 0 1 NULL + t276 d 4 INT 9 10 10 0 1 NULL + t276 e 4 INT 9 10 10 0 1 NULL + t277 a 4 INT 9 10 10 0 1 NULL + t277 b 4 INT 9 10 10 0 1 NULL + t277 c 4 INT 9 10 10 0 1 NULL + t277 d 4 INT 9 10 10 0 1 NULL + t277 e 4 INT 9 10 10 0 1 NULL + t278 a 4 INT 9 10 10 0 1 NULL + t278 b 4 INT 9 10 10 0 1 NULL + t278 c 4 INT 9 10 10 0 1 NULL + t278 d 4 INT 9 10 10 0 1 NULL + t278 e 4 INT 9 10 10 0 1 NULL + t279 a 4 INT 9 10 10 0 1 NULL + t279 b 4 INT 9 10 10 0 1 NULL + t279 c 4 INT 9 10 10 0 1 NULL + t279 d 4 INT 9 10 10 0 1 NULL + t279 e 4 INT 9 10 10 0 1 NULL + t280 a 4 INT 9 10 10 0 1 NULL + t280 b 4 INT 9 10 10 0 1 NULL + t280 c 4 INT 9 10 10 0 1 NULL + t280 d 4 INT 9 10 10 0 1 NULL + t280 e 4 INT 9 10 10 0 1 NULL + t281 a 4 INT 9 10 10 0 1 NULL + t281 b 4 INT 9 10 10 0 1 NULL + t281 c 4 INT 9 10 10 0 1 NULL + t281 d 4 INT 9 10 10 0 1 NULL + t281 e 4 INT 9 10 10 0 1 NULL + t282 a 4 INT 9 10 10 0 1 NULL + t282 b 4 INT 9 10 10 0 1 NULL + t282 c 4 INT 9 10 10 0 1 NULL + t282 d 4 INT 9 10 10 0 1 NULL + t282 e 4 INT 9 10 10 0 1 NULL + t283 a 4 INT 9 10 10 0 1 NULL + t283 b 4 INT 9 10 10 0 1 NULL + t283 c 4 INT 9 10 10 0 1 NULL + t283 d 4 INT 9 10 10 0 1 NULL + t283 e 4 INT 9 10 10 0 1 NULL + t284 a 4 INT 9 10 10 0 1 NULL + t284 b 4 INT 9 10 10 0 1 NULL + t284 c 4 INT 9 10 10 0 1 NULL + t284 d 4 INT 9 10 10 0 1 NULL + t284 e 4 INT 9 10 10 0 1 NULL + t285 a 4 INT 9 10 10 0 1 NULL + t285 b 4 INT 9 10 10 0 1 NULL + t285 c 4 INT 9 10 10 0 1 NULL + t285 d 4 INT 9 10 10 0 1 NULL + t285 e 4 INT 9 10 10 0 1 NULL + t286 a 4 INT 9 10 10 0 1 NULL + t286 b 4 INT 9 10 10 0 1 NULL + t286 c 4 INT 9 10 10 0 1 NULL + t286 d 4 INT 9 10 10 0 1 NULL + t286 e 4 INT 9 10 10 0 1 NULL + t287 a 4 INT 9 10 10 0 1 NULL + t287 b 4 INT 9 10 10 0 1 NULL + t287 c 4 INT 9 10 10 0 1 NULL + t287 d 4 INT 9 10 10 0 1 NULL + t287 e 4 INT 9 10 10 0 1 NULL + t288 a 4 INT 9 10 10 0 1 NULL + t288 b 4 INT 9 10 10 0 1 NULL + t288 c 4 INT 9 10 10 0 1 NULL + t288 d 4 INT 9 10 10 0 1 NULL + t288 e 4 INT 9 10 10 0 1 NULL + t289 a 4 INT 9 10 10 0 1 NULL + t289 b 4 INT 9 10 10 0 1 NULL + t289 c 4 INT 9 10 10 0 1 NULL + t289 d 4 INT 9 10 10 0 1 NULL + t289 e 4 INT 9 10 10 0 1 NULL + t290 a 4 INT 9 10 10 0 1 NULL + t290 b 4 INT 9 10 10 0 1 NULL + t290 c 4 INT 9 10 10 0 1 NULL + t290 d 4 INT 9 10 10 0 1 NULL + t290 e 4 INT 9 10 10 0 1 NULL + t291 a 4 INT 9 10 10 0 1 NULL + t291 b 4 INT 9 10 10 0 1 NULL + t291 c 4 INT 9 10 10 0 1 NULL + t291 d 4 INT 9 10 10 0 1 NULL + t291 e 4 INT 9 10 10 0 1 NULL + t292 a 4 INT 9 10 10 0 1 NULL + t292 b 4 INT 9 10 10 0 1 NULL + t292 c 4 INT 9 10 10 0 1 NULL + t292 d 4 INT 9 10 10 0 1 NULL + t292 e 4 INT 9 10 10 0 1 NULL + t293 a 4 INT 9 10 10 0 1 NULL + t293 b 4 INT 9 10 10 0 1 NULL + t293 c 4 INT 9 10 10 0 1 NULL + t293 d 4 INT 9 10 10 0 1 NULL + t293 e 4 INT 9 10 10 0 1 NULL + t294 a 4 INT 9 10 10 0 1 NULL + t294 b 4 INT 9 10 10 0 1 NULL + t294 c 4 INT 9 10 10 0 1 NULL + t294 d 4 INT 9 10 10 0 1 NULL + t294 e 4 INT 9 10 10 0 1 NULL + t295 a 4 INT 9 10 10 0 1 NULL + t295 b 4 INT 9 10 10 0 1 NULL + t295 c 4 INT 9 10 10 0 1 NULL + t295 d 4 INT 9 10 10 0 1 NULL + t295 e 4 INT 9 10 10 0 1 NULL + t296 a 4 INT 9 10 10 0 1 NULL + t296 b 4 INT 9 10 10 0 1 NULL + t296 c 4 INT 9 10 10 0 1 NULL + t296 d 4 INT 9 10 10 0 1 NULL + t296 e 4 INT 9 10 10 0 1 NULL + t297 a 4 INT 9 10 10 0 1 NULL + t297 b 4 INT 9 10 10 0 1 NULL + t297 c 4 INT 9 10 10 0 1 NULL + t297 d 4 INT 9 10 10 0 1 NULL + t297 e 4 INT 9 10 10 0 1 NULL + t298 a 4 INT 9 10 10 0 1 NULL + t298 b 4 INT 9 10 10 0 1 NULL + t298 c 4 INT 9 10 10 0 1 NULL + t298 d 4 INT 9 10 10 0 1 NULL + t298 e 4 INT 9 10 10 0 1 NULL + t299 a 4 INT 9 10 10 0 1 NULL + t299 b 4 INT 9 10 10 0 1 NULL + t299 c 4 INT 9 10 10 0 1 NULL + t299 d 4 INT 9 10 10 0 1 NULL + t299 e 4 INT 9 10 10 0 1 NULL + t300 a 4 INT 9 10 10 0 1 NULL + t300 b 4 INT 9 10 10 0 1 NULL + t300 c 4 INT 9 10 10 0 1 NULL + t300 d 4 INT 9 10 10 0 1 NULL + t300 e 4 INT 9 10 10 0 1 NULL + t301 a 4 INT 9 10 10 0 1 NULL + t301 b 4 INT 9 10 10 0 1 NULL + t301 c 4 INT 9 10 10 0 1 NULL + t301 d 4 INT 9 10 10 0 1 NULL + t301 e 4 INT 9 10 10 0 1 NULL + t302 a 4 INT 9 10 10 0 1 NULL + t302 b 4 INT 9 10 10 0 1 NULL + t302 c 4 INT 9 10 10 0 1 NULL + t302 d 4 INT 9 10 10 0 1 NULL + t302 e 4 INT 9 10 10 0 1 NULL + t303 a 4 INT 9 10 10 0 1 NULL + t303 b 4 INT 9 10 10 0 1 NULL + t303 c 4 INT 9 10 10 0 1 NULL + t303 d 4 INT 9 10 10 0 1 NULL + t303 e 4 INT 9 10 10 0 1 NULL + t304 a 4 INT 9 10 10 0 1 NULL + t304 b 4 INT 9 10 10 0 1 NULL + t304 c 4 INT 9 10 10 0 1 NULL + t304 d 4 INT 9 10 10 0 1 NULL + t304 e 4 INT 9 10 10 0 1 NULL + t305 a 4 INT 9 10 10 0 1 NULL + t305 b 4 INT 9 10 10 0 1 NULL + t305 c 4 INT 9 10 10 0 1 NULL + t305 d 4 INT 9 10 10 0 1 NULL + t305 e 4 INT 9 10 10 0 1 NULL + t306 a 4 INT 9 10 10 0 1 NULL + t306 b 4 INT 9 10 10 0 1 NULL + t306 c 4 INT 9 10 10 0 1 NULL + t306 d 4 INT 9 10 10 0 1 NULL + t306 e 4 INT 9 10 10 0 1 NULL + t307 a 4 INT 9 10 10 0 1 NULL + t307 b 4 INT 9 10 10 0 1 NULL + t307 c 4 INT 9 10 10 0 1 NULL + t307 d 4 INT 9 10 10 0 1 NULL + t307 e 4 INT 9 10 10 0 1 NULL + t308 a 4 INT 9 10 10 0 1 NULL + t308 b 4 INT 9 10 10 0 1 NULL + t308 c 4 INT 9 10 10 0 1 NULL + t308 d 4 INT 9 10 10 0 1 NULL + t308 e 4 INT 9 10 10 0 1 NULL + t309 a 4 INT 9 10 10 0 1 NULL + t309 b 4 INT 9 10 10 0 1 NULL + t309 c 4 INT 9 10 10 0 1 NULL + t309 d 4 INT 9 10 10 0 1 NULL + t309 e 4 INT 9 10 10 0 1 NULL + t310 a 4 INT 9 10 10 0 1 NULL + t310 b 4 INT 9 10 10 0 1 NULL + t310 c 4 INT 9 10 10 0 1 NULL + t310 d 4 INT 9 10 10 0 1 NULL + t310 e 4 INT 9 10 10 0 1 NULL + t311 a 4 INT 9 10 10 0 1 NULL + t311 b 4 INT 9 10 10 0 1 NULL + t311 c 4 INT 9 10 10 0 1 NULL + t311 d 4 INT 9 10 10 0 1 NULL + t311 e 4 INT 9 10 10 0 1 NULL + t312 a 4 INT 9 10 10 0 1 NULL + t312 b 4 INT 9 10 10 0 1 NULL + t312 c 4 INT 9 10 10 0 1 NULL + t312 d 4 INT 9 10 10 0 1 NULL + t312 e 4 INT 9 10 10 0 1 NULL + t313 a 4 INT 9 10 10 0 1 NULL + t313 b 4 INT 9 10 10 0 1 NULL + t313 c 4 INT 9 10 10 0 1 NULL + t313 d 4 INT 9 10 10 0 1 NULL + t313 e 4 INT 9 10 10 0 1 NULL + t314 a 4 INT 9 10 10 0 1 NULL + t314 b 4 INT 9 10 10 0 1 NULL + t314 c 4 INT 9 10 10 0 1 NULL + t314 d 4 INT 9 10 10 0 1 NULL + t314 e 4 INT 9 10 10 0 1 NULL + t315 a 4 INT 9 10 10 0 1 NULL + t315 b 4 INT 9 10 10 0 1 NULL + t315 c 4 INT 9 10 10 0 1 NULL + t315 d 4 INT 9 10 10 0 1 NULL + t315 e 4 INT 9 10 10 0 1 NULL + t316 a 4 INT 9 10 10 0 1 NULL + t316 b 4 INT 9 10 10 0 1 NULL + t316 c 4 INT 9 10 10 0 1 NULL + t316 d 4 INT 9 10 10 0 1 NULL + t316 e 4 INT 9 10 10 0 1 NULL + t317 a 4 INT 9 10 10 0 1 NULL + t317 b 4 INT 9 10 10 0 1 NULL + t317 c 4 INT 9 10 10 0 1 NULL + t317 d 4 INT 9 10 10 0 1 NULL + t317 e 4 INT 9 10 10 0 1 NULL + t318 a 4 INT 9 10 10 0 1 NULL + t318 b 4 INT 9 10 10 0 1 NULL + t318 c 4 INT 9 10 10 0 1 NULL + t318 d 4 INT 9 10 10 0 1 NULL + t318 e 4 INT 9 10 10 0 1 NULL + t319 a 4 INT 9 10 10 0 1 NULL + t319 b 4 INT 9 10 10 0 1 NULL + t319 c 4 INT 9 10 10 0 1 NULL + t319 d 4 INT 9 10 10 0 1 NULL + t319 e 4 INT 9 10 10 0 1 NULL + t320 a 4 INT 9 10 10 0 1 NULL + t320 b 4 INT 9 10 10 0 1 NULL + t320 c 4 INT 9 10 10 0 1 NULL + t320 d 4 INT 9 10 10 0 1 NULL + t320 e 4 INT 9 10 10 0 1 NULL + t321 a 4 INT 9 10 10 0 1 NULL + t321 b 4 INT 9 10 10 0 1 NULL + t321 c 4 INT 9 10 10 0 1 NULL + t321 d 4 INT 9 10 10 0 1 NULL + t321 e 4 INT 9 10 10 0 1 NULL + t322 a 4 INT 9 10 10 0 1 NULL + t322 b 4 INT 9 10 10 0 1 NULL + t322 c 4 INT 9 10 10 0 1 NULL + t322 d 4 INT 9 10 10 0 1 NULL + t322 e 4 INT 9 10 10 0 1 NULL + t323 a 4 INT 9 10 10 0 1 NULL + t323 b 4 INT 9 10 10 0 1 NULL + t323 c 4 INT 9 10 10 0 1 NULL + t323 d 4 INT 9 10 10 0 1 NULL + t323 e 4 INT 9 10 10 0 1 NULL + t324 a 4 INT 9 10 10 0 1 NULL + t324 b 4 INT 9 10 10 0 1 NULL + t324 c 4 INT 9 10 10 0 1 NULL + t324 d 4 INT 9 10 10 0 1 NULL + t324 e 4 INT 9 10 10 0 1 NULL + t325 a 4 INT 9 10 10 0 1 NULL + t325 b 4 INT 9 10 10 0 1 NULL + t325 c 4 INT 9 10 10 0 1 NULL + t325 d 4 INT 9 10 10 0 1 NULL + t325 e 4 INT 9 10 10 0 1 NULL + t326 a 4 INT 9 10 10 0 1 NULL + t326 b 4 INT 9 10 10 0 1 NULL + t326 c 4 INT 9 10 10 0 1 NULL + t326 d 4 INT 9 10 10 0 1 NULL + t326 e 4 INT 9 10 10 0 1 NULL + t327 a 4 INT 9 10 10 0 1 NULL + t327 b 4 INT 9 10 10 0 1 NULL + t327 c 4 INT 9 10 10 0 1 NULL + t327 d 4 INT 9 10 10 0 1 NULL + t327 e 4 INT 9 10 10 0 1 NULL + t328 a 4 INT 9 10 10 0 1 NULL + t328 b 4 INT 9 10 10 0 1 NULL + t328 c 4 INT 9 10 10 0 1 NULL + t328 d 4 INT 9 10 10 0 1 NULL + t328 e 4 INT 9 10 10 0 1 NULL + t329 a 4 INT 9 10 10 0 1 NULL + t329 b 4 INT 9 10 10 0 1 NULL + t329 c 4 INT 9 10 10 0 1 NULL + t329 d 4 INT 9 10 10 0 1 NULL + t329 e 4 INT 9 10 10 0 1 NULL + t330 a 4 INT 9 10 10 0 1 NULL + t330 b 4 INT 9 10 10 0 1 NULL + t330 c 4 INT 9 10 10 0 1 NULL + t330 d 4 INT 9 10 10 0 1 NULL + t330 e 4 INT 9 10 10 0 1 NULL + t331 a 4 INT 9 10 10 0 1 NULL + t331 b 4 INT 9 10 10 0 1 NULL + t331 c 4 INT 9 10 10 0 1 NULL + t331 d 4 INT 9 10 10 0 1 NULL + t331 e 4 INT 9 10 10 0 1 NULL + t332 a 4 INT 9 10 10 0 1 NULL + t332 b 4 INT 9 10 10 0 1 NULL + t332 c 4 INT 9 10 10 0 1 NULL + t332 d 4 INT 9 10 10 0 1 NULL + t332 e 4 INT 9 10 10 0 1 NULL + t333 a 4 INT 9 10 10 0 1 NULL + t333 b 4 INT 9 10 10 0 1 NULL + t333 c 4 INT 9 10 10 0 1 NULL + t333 d 4 INT 9 10 10 0 1 NULL + t333 e 4 INT 9 10 10 0 1 NULL + t334 a 4 INT 9 10 10 0 1 NULL + t334 b 4 INT 9 10 10 0 1 NULL + t334 c 4 INT 9 10 10 0 1 NULL + t334 d 4 INT 9 10 10 0 1 NULL + t334 e 4 INT 9 10 10 0 1 NULL + t335 a 4 INT 9 10 10 0 1 NULL + t335 b 4 INT 9 10 10 0 1 NULL + t335 c 4 INT 9 10 10 0 1 NULL + t335 d 4 INT 9 10 10 0 1 NULL + t335 e 4 INT 9 10 10 0 1 NULL + t336 a 4 INT 9 10 10 0 1 NULL + t336 b 4 INT 9 10 10 0 1 NULL + t336 c 4 INT 9 10 10 0 1 NULL + t336 d 4 INT 9 10 10 0 1 NULL + t336 e 4 INT 9 10 10 0 1 NULL + t337 a 4 INT 9 10 10 0 1 NULL + t337 b 4 INT 9 10 10 0 1 NULL + t337 c 4 INT 9 10 10 0 1 NULL + t337 d 4 INT 9 10 10 0 1 NULL + t337 e 4 INT 9 10 10 0 1 NULL + t338 a 4 INT 9 10 10 0 1 NULL + t338 b 4 INT 9 10 10 0 1 NULL + t338 c 4 INT 9 10 10 0 1 NULL + t338 d 4 INT 9 10 10 0 1 NULL + t338 e 4 INT 9 10 10 0 1 NULL + t339 a 4 INT 9 10 10 0 1 NULL + t339 b 4 INT 9 10 10 0 1 NULL + t339 c 4 INT 9 10 10 0 1 NULL + t339 d 4 INT 9 10 10 0 1 NULL + t339 e 4 INT 9 10 10 0 1 NULL + t340 a 4 INT 9 10 10 0 1 NULL + t340 b 4 INT 9 10 10 0 1 NULL + t340 c 4 INT 9 10 10 0 1 NULL + t340 d 4 INT 9 10 10 0 1 NULL + t340 e 4 INT 9 10 10 0 1 NULL + t341 a 4 INT 9 10 10 0 1 NULL + t341 b 4 INT 9 10 10 0 1 NULL + t341 c 4 INT 9 10 10 0 1 NULL + t341 d 4 INT 9 10 10 0 1 NULL + t341 e 4 INT 9 10 10 0 1 NULL + t342 a 4 INT 9 10 10 0 1 NULL + t342 b 4 INT 9 10 10 0 1 NULL + t342 c 4 INT 9 10 10 0 1 NULL + t342 d 4 INT 9 10 10 0 1 NULL + t342 e 4 INT 9 10 10 0 1 NULL + t343 a 4 INT 9 10 10 0 1 NULL + t343 b 4 INT 9 10 10 0 1 NULL + t343 c 4 INT 9 10 10 0 1 NULL + t343 d 4 INT 9 10 10 0 1 NULL + t343 e 4 INT 9 10 10 0 1 NULL + t344 a 4 INT 9 10 10 0 1 NULL + t344 b 4 INT 9 10 10 0 1 NULL + t344 c 4 INT 9 10 10 0 1 NULL + t344 d 4 INT 9 10 10 0 1 NULL + t344 e 4 INT 9 10 10 0 1 NULL + t345 a 4 INT 9 10 10 0 1 NULL + t345 b 4 INT 9 10 10 0 1 NULL + t345 c 4 INT 9 10 10 0 1 NULL + t345 d 4 INT 9 10 10 0 1 NULL + t345 e 4 INT 9 10 10 0 1 NULL + t346 a 4 INT 9 10 10 0 1 NULL + t346 b 4 INT 9 10 10 0 1 NULL + t346 c 4 INT 9 10 10 0 1 NULL + t346 d 4 INT 9 10 10 0 1 NULL + t346 e 4 INT 9 10 10 0 1 NULL + t347 a 4 INT 9 10 10 0 1 NULL + t347 b 4 INT 9 10 10 0 1 NULL + t347 c 4 INT 9 10 10 0 1 NULL + t347 d 4 INT 9 10 10 0 1 NULL + t347 e 4 INT 9 10 10 0 1 NULL + t348 a 4 INT 9 10 10 0 1 NULL + t348 b 4 INT 9 10 10 0 1 NULL + t348 c 4 INT 9 10 10 0 1 NULL + t348 d 4 INT 9 10 10 0 1 NULL + t348 e 4 INT 9 10 10 0 1 NULL + t349 a 4 INT 9 10 10 0 1 NULL + t349 b 4 INT 9 10 10 0 1 NULL + t349 c 4 INT 9 10 10 0 1 NULL + t349 d 4 INT 9 10 10 0 1 NULL + t349 e 4 INT 9 10 10 0 1 NULL + t350 a 4 INT 9 10 10 0 1 NULL + t350 b 4 INT 9 10 10 0 1 NULL + t350 c 4 INT 9 10 10 0 1 NULL + t350 d 4 INT 9 10 10 0 1 NULL + t350 e 4 INT 9 10 10 0 1 NULL + t351 a 4 INT 9 10 10 0 1 NULL + t351 b 4 INT 9 10 10 0 1 NULL + t351 c 4 INT 9 10 10 0 1 NULL + t351 d 4 INT 9 10 10 0 1 NULL + t351 e 4 INT 9 10 10 0 1 NULL + t352 a 4 INT 9 10 10 0 1 NULL + t352 b 4 INT 9 10 10 0 1 NULL + t352 c 4 INT 9 10 10 0 1 NULL + t352 d 4 INT 9 10 10 0 1 NULL + t352 e 4 INT 9 10 10 0 1 NULL + t353 a 4 INT 9 10 10 0 1 NULL + t353 b 4 INT 9 10 10 0 1 NULL + t353 c 4 INT 9 10 10 0 1 NULL + t353 d 4 INT 9 10 10 0 1 NULL + t353 e 4 INT 9 10 10 0 1 NULL + t354 a 4 INT 9 10 10 0 1 NULL + t354 b 4 INT 9 10 10 0 1 NULL + t354 c 4 INT 9 10 10 0 1 NULL + t354 d 4 INT 9 10 10 0 1 NULL + t354 e 4 INT 9 10 10 0 1 NULL + t355 a 4 INT 9 10 10 0 1 NULL + t355 b 4 INT 9 10 10 0 1 NULL + t355 c 4 INT 9 10 10 0 1 NULL + t355 d 4 INT 9 10 10 0 1 NULL + t355 e 4 INT 9 10 10 0 1 NULL + t356 a 4 INT 9 10 10 0 1 NULL + t356 b 4 INT 9 10 10 0 1 NULL + t356 c 4 INT 9 10 10 0 1 NULL + t356 d 4 INT 9 10 10 0 1 NULL + t356 e 4 INT 9 10 10 0 1 NULL + t357 a 4 INT 9 10 10 0 1 NULL + t357 b 4 INT 9 10 10 0 1 NULL + t357 c 4 INT 9 10 10 0 1 NULL + t357 d 4 INT 9 10 10 0 1 NULL + t357 e 4 INT 9 10 10 0 1 NULL + t358 a 4 INT 9 10 10 0 1 NULL + t358 b 4 INT 9 10 10 0 1 NULL + t358 c 4 INT 9 10 10 0 1 NULL + t358 d 4 INT 9 10 10 0 1 NULL + t358 e 4 INT 9 10 10 0 1 NULL + t359 a 4 INT 9 10 10 0 1 NULL + t359 b 4 INT 9 10 10 0 1 NULL + t359 c 4 INT 9 10 10 0 1 NULL + t359 d 4 INT 9 10 10 0 1 NULL + t359 e 4 INT 9 10 10 0 1 NULL + t360 a 4 INT 9 10 10 0 1 NULL + t360 b 4 INT 9 10 10 0 1 NULL + t360 c 4 INT 9 10 10 0 1 NULL + t360 d 4 INT 9 10 10 0 1 NULL + t360 e 4 INT 9 10 10 0 1 NULL + t361 a 4 INT 9 10 10 0 1 NULL + t361 b 4 INT 9 10 10 0 1 NULL + t361 c 4 INT 9 10 10 0 1 NULL + t361 d 4 INT 9 10 10 0 1 NULL + t361 e 4 INT 9 10 10 0 1 NULL + t362 a 4 INT 9 10 10 0 1 NULL + t362 b 4 INT 9 10 10 0 1 NULL + t362 c 4 INT 9 10 10 0 1 NULL + t362 d 4 INT 9 10 10 0 1 NULL + t362 e 4 INT 9 10 10 0 1 NULL + t363 a 4 INT 9 10 10 0 1 NULL + t363 b 4 INT 9 10 10 0 1 NULL + t363 c 4 INT 9 10 10 0 1 NULL + t363 d 4 INT 9 10 10 0 1 NULL + t363 e 4 INT 9 10 10 0 1 NULL + t364 a 4 INT 9 10 10 0 1 NULL + t364 b 4 INT 9 10 10 0 1 NULL + t364 c 4 INT 9 10 10 0 1 NULL + t364 d 4 INT 9 10 10 0 1 NULL + t364 e 4 INT 9 10 10 0 1 NULL + t365 a 4 INT 9 10 10 0 1 NULL + t365 b 4 INT 9 10 10 0 1 NULL + t365 c 4 INT 9 10 10 0 1 NULL + t365 d 4 INT 9 10 10 0 1 NULL + t365 e 4 INT 9 10 10 0 1 NULL + t366 a 4 INT 9 10 10 0 1 NULL + t366 b 4 INT 9 10 10 0 1 NULL + t366 c 4 INT 9 10 10 0 1 NULL + t366 d 4 INT 9 10 10 0 1 NULL + t366 e 4 INT 9 10 10 0 1 NULL + t367 a 4 INT 9 10 10 0 1 NULL + t367 b 4 INT 9 10 10 0 1 NULL + t367 c 4 INT 9 10 10 0 1 NULL + t367 d 4 INT 9 10 10 0 1 NULL + t367 e 4 INT 9 10 10 0 1 NULL + t368 a 4 INT 9 10 10 0 1 NULL + t368 b 4 INT 9 10 10 0 1 NULL + t368 c 4 INT 9 10 10 0 1 NULL + t368 d 4 INT 9 10 10 0 1 NULL + t368 e 4 INT 9 10 10 0 1 NULL + t369 a 4 INT 9 10 10 0 1 NULL + t369 b 4 INT 9 10 10 0 1 NULL + t369 c 4 INT 9 10 10 0 1 NULL + t369 d 4 INT 9 10 10 0 1 NULL + t369 e 4 INT 9 10 10 0 1 NULL + t370 a 4 INT 9 10 10 0 1 NULL + t370 b 4 INT 9 10 10 0 1 NULL + t370 c 4 INT 9 10 10 0 1 NULL + t370 d 4 INT 9 10 10 0 1 NULL + t370 e 4 INT 9 10 10 0 1 NULL + t371 a 4 INT 9 10 10 0 1 NULL + t371 b 4 INT 9 10 10 0 1 NULL + t371 c 4 INT 9 10 10 0 1 NULL + t371 d 4 INT 9 10 10 0 1 NULL + t371 e 4 INT 9 10 10 0 1 NULL + t372 a 4 INT 9 10 10 0 1 NULL + t372 b 4 INT 9 10 10 0 1 NULL + t372 c 4 INT 9 10 10 0 1 NULL + t372 d 4 INT 9 10 10 0 1 NULL + t372 e 4 INT 9 10 10 0 1 NULL + t373 a 4 INT 9 10 10 0 1 NULL + t373 b 4 INT 9 10 10 0 1 NULL + t373 c 4 INT 9 10 10 0 1 NULL + t373 d 4 INT 9 10 10 0 1 NULL + t373 e 4 INT 9 10 10 0 1 NULL + t374 a 4 INT 9 10 10 0 1 NULL + t374 b 4 INT 9 10 10 0 1 NULL + t374 c 4 INT 9 10 10 0 1 NULL + t374 d 4 INT 9 10 10 0 1 NULL + t374 e 4 INT 9 10 10 0 1 NULL + t375 a 4 INT 9 10 10 0 1 NULL + t375 b 4 INT 9 10 10 0 1 NULL + t375 c 4 INT 9 10 10 0 1 NULL + t375 d 4 INT 9 10 10 0 1 NULL + t375 e 4 INT 9 10 10 0 1 NULL + t376 a 4 INT 9 10 10 0 1 NULL + t376 b 4 INT 9 10 10 0 1 NULL + t376 c 4 INT 9 10 10 0 1 NULL + t376 d 4 INT 9 10 10 0 1 NULL + t376 e 4 INT 9 10 10 0 1 NULL + t377 a 4 INT 9 10 10 0 1 NULL + t377 b 4 INT 9 10 10 0 1 NULL + t377 c 4 INT 9 10 10 0 1 NULL + t377 d 4 INT 9 10 10 0 1 NULL + t377 e 4 INT 9 10 10 0 1 NULL + t378 a 4 INT 9 10 10 0 1 NULL + t378 b 4 INT 9 10 10 0 1 NULL + t378 c 4 INT 9 10 10 0 1 NULL + t378 d 4 INT 9 10 10 0 1 NULL + t378 e 4 INT 9 10 10 0 1 NULL + t379 a 4 INT 9 10 10 0 1 NULL + t379 b 4 INT 9 10 10 0 1 NULL + t379 c 4 INT 9 10 10 0 1 NULL + t379 d 4 INT 9 10 10 0 1 NULL + t379 e 4 INT 9 10 10 0 1 NULL + t380 a 4 INT 9 10 10 0 1 NULL + t380 b 4 INT 9 10 10 0 1 NULL + t380 c 4 INT 9 10 10 0 1 NULL + t380 d 4 INT 9 10 10 0 1 NULL + t380 e 4 INT 9 10 10 0 1 NULL + t381 a 4 INT 9 10 10 0 1 NULL + t381 b 4 INT 9 10 10 0 1 NULL + t381 c 4 INT 9 10 10 0 1 NULL + t381 d 4 INT 9 10 10 0 1 NULL + t381 e 4 INT 9 10 10 0 1 NULL + t382 a 4 INT 9 10 10 0 1 NULL + t382 b 4 INT 9 10 10 0 1 NULL + t382 c 4 INT 9 10 10 0 1 NULL + t382 d 4 INT 9 10 10 0 1 NULL + t382 e 4 INT 9 10 10 0 1 NULL + t383 a 4 INT 9 10 10 0 1 NULL + t383 b 4 INT 9 10 10 0 1 NULL + t383 c 4 INT 9 10 10 0 1 NULL + t383 d 4 INT 9 10 10 0 1 NULL + t383 e 4 INT 9 10 10 0 1 NULL + t384 a 4 INT 9 10 10 0 1 NULL + t384 b 4 INT 9 10 10 0 1 NULL + t384 c 4 INT 9 10 10 0 1 NULL + t384 d 4 INT 9 10 10 0 1 NULL + t384 e 4 INT 9 10 10 0 1 NULL + t385 a 4 INT 9 10 10 0 1 NULL + t385 b 4 INT 9 10 10 0 1 NULL + t385 c 4 INT 9 10 10 0 1 NULL + t385 d 4 INT 9 10 10 0 1 NULL + t385 e 4 INT 9 10 10 0 1 NULL + t386 a 4 INT 9 10 10 0 1 NULL + t386 b 4 INT 9 10 10 0 1 NULL + t386 c 4 INT 9 10 10 0 1 NULL + t386 d 4 INT 9 10 10 0 1 NULL + t386 e 4 INT 9 10 10 0 1 NULL + t387 a 4 INT 9 10 10 0 1 NULL + t387 b 4 INT 9 10 10 0 1 NULL + t387 c 4 INT 9 10 10 0 1 NULL + t387 d 4 INT 9 10 10 0 1 NULL + t387 e 4 INT 9 10 10 0 1 NULL + t388 a 4 INT 9 10 10 0 1 NULL + t388 b 4 INT 9 10 10 0 1 NULL + t388 c 4 INT 9 10 10 0 1 NULL + t388 d 4 INT 9 10 10 0 1 NULL + t388 e 4 INT 9 10 10 0 1 NULL + t389 a 4 INT 9 10 10 0 1 NULL + t389 b 4 INT 9 10 10 0 1 NULL + t389 c 4 INT 9 10 10 0 1 NULL + t389 d 4 INT 9 10 10 0 1 NULL + t389 e 4 INT 9 10 10 0 1 NULL + t390 a 4 INT 9 10 10 0 1 NULL + t390 b 4 INT 9 10 10 0 1 NULL + t390 c 4 INT 9 10 10 0 1 NULL + t390 d 4 INT 9 10 10 0 1 NULL + t390 e 4 INT 9 10 10 0 1 NULL + t391 a 4 INT 9 10 10 0 1 NULL + t391 b 4 INT 9 10 10 0 1 NULL + t391 c 4 INT 9 10 10 0 1 NULL + t391 d 4 INT 9 10 10 0 1 NULL + t391 e 4 INT 9 10 10 0 1 NULL + t392 a 4 INT 9 10 10 0 1 NULL + t392 b 4 INT 9 10 10 0 1 NULL + t392 c 4 INT 9 10 10 0 1 NULL + t392 d 4 INT 9 10 10 0 1 NULL + t392 e 4 INT 9 10 10 0 1 NULL + t393 a 4 INT 9 10 10 0 1 NULL + t393 b 4 INT 9 10 10 0 1 NULL + t393 c 4 INT 9 10 10 0 1 NULL + t393 d 4 INT 9 10 10 0 1 NULL + t393 e 4 INT 9 10 10 0 1 NULL + t394 a 4 INT 9 10 10 0 1 NULL + t394 b 4 INT 9 10 10 0 1 NULL + t394 c 4 INT 9 10 10 0 1 NULL + t394 d 4 INT 9 10 10 0 1 NULL + t394 e 4 INT 9 10 10 0 1 NULL + t395 a 4 INT 9 10 10 0 1 NULL + t395 b 4 INT 9 10 10 0 1 NULL + t395 c 4 INT 9 10 10 0 1 NULL + t395 d 4 INT 9 10 10 0 1 NULL + t395 e 4 INT 9 10 10 0 1 NULL + t396 a 4 INT 9 10 10 0 1 NULL + t396 b 4 INT 9 10 10 0 1 NULL + t396 c 4 INT 9 10 10 0 1 NULL + t396 d 4 INT 9 10 10 0 1 NULL + t396 e 4 INT 9 10 10 0 1 NULL + t397 a 4 INT 9 10 10 0 1 NULL + t397 b 4 INT 9 10 10 0 1 NULL + t397 c 4 INT 9 10 10 0 1 NULL + t397 d 4 INT 9 10 10 0 1 NULL + t397 e 4 INT 9 10 10 0 1 NULL + t398 a 4 INT 9 10 10 0 1 NULL + t398 b 4 INT 9 10 10 0 1 NULL + t398 c 4 INT 9 10 10 0 1 NULL + t398 d 4 INT 9 10 10 0 1 NULL + t398 e 4 INT 9 10 10 0 1 NULL + t399 a 4 INT 9 10 10 0 1 NULL + t399 b 4 INT 9 10 10 0 1 NULL + t399 c 4 INT 9 10 10 0 1 NULL + t399 d 4 INT 9 10 10 0 1 NULL + t399 e 4 INT 9 10 10 0 1 NULL DROP TABLE t1; CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABLE_TYPE=ODBC CONNECTION='Driver=SQLite3 ODBC Driver;Database=MTR_SUITE_DIR/std_data/test.sqlite3;NoWCHAR=yes' CHARSET=utf8 DATA_CHARSET=utf8; SELECT * FROM t1 ORDER BY Table_name; Table_Cat Table_Schema Table_Name Table_Type Remark - t000 TABLE - t001 TABLE - t002 TABLE - t003 TABLE - t004 TABLE - t005 TABLE - t006 TABLE - t007 TABLE - t008 TABLE - t009 TABLE - t010 TABLE - t011 TABLE - t012 TABLE - t013 TABLE - t014 TABLE - t015 TABLE - t016 TABLE - t017 TABLE - t018 TABLE - t019 TABLE - t020 TABLE - t021 TABLE - t022 TABLE - t023 TABLE - t024 TABLE - t025 TABLE - t026 TABLE - t027 TABLE - t028 TABLE - t029 TABLE - t030 TABLE - t031 TABLE - t032 TABLE - t033 TABLE - t034 TABLE - t035 TABLE - t036 TABLE - t037 TABLE - t038 TABLE - t039 TABLE - t040 TABLE - t041 TABLE - t042 TABLE - t043 TABLE - t044 TABLE - t045 TABLE - t046 TABLE - t047 TABLE - t048 TABLE - t049 TABLE - t050 TABLE - t051 TABLE - t052 TABLE - t053 TABLE - t054 TABLE - t055 TABLE - t056 TABLE - t057 TABLE - t058 TABLE - t059 TABLE - t060 TABLE - t061 TABLE - t062 TABLE - t063 TABLE - t064 TABLE - t065 TABLE - t066 TABLE - t067 TABLE - t068 TABLE - t069 TABLE - t070 TABLE - t071 TABLE - t072 TABLE - t073 TABLE - t074 TABLE - t075 TABLE - t076 TABLE - t077 TABLE - t078 TABLE - t079 TABLE - t080 TABLE - t081 TABLE - t082 TABLE - t083 TABLE - t084 TABLE - t085 TABLE - t086 TABLE - t087 TABLE - t088 TABLE - t089 TABLE - t090 TABLE - t091 TABLE - t092 TABLE - t093 TABLE - t094 TABLE - t095 TABLE - t096 TABLE - t097 TABLE - t098 TABLE - t099 TABLE - t1 TABLE - t100 TABLE - t101 TABLE - t102 TABLE - t103 TABLE - t104 TABLE - t105 TABLE - t106 TABLE - t107 TABLE - t108 TABLE - t109 TABLE - t110 TABLE - t111 TABLE - t112 TABLE - t113 TABLE - t114 TABLE - t115 TABLE - t116 TABLE - t117 TABLE - t118 TABLE - t119 TABLE - t120 TABLE - t121 TABLE - t122 TABLE - t123 TABLE - t124 TABLE - t125 TABLE - t126 TABLE - t127 TABLE - t128 TABLE - t129 TABLE - t130 TABLE - t131 TABLE - t132 TABLE - t133 TABLE - t134 TABLE - t135 TABLE - t136 TABLE - t137 TABLE - t138 TABLE - t139 TABLE - t140 TABLE - t141 TABLE - t142 TABLE - t143 TABLE - t144 TABLE - t145 TABLE - t146 TABLE - t147 TABLE - t148 TABLE - t149 TABLE - t150 TABLE - t151 TABLE - t152 TABLE - t153 TABLE - t154 TABLE - t155 TABLE - t156 TABLE - t157 TABLE - t158 TABLE - t159 TABLE - t160 TABLE - t161 TABLE - t162 TABLE - t163 TABLE - t164 TABLE - t165 TABLE - t166 TABLE - t167 TABLE - t168 TABLE - t169 TABLE - t170 TABLE - t171 TABLE - t172 TABLE - t173 TABLE - t174 TABLE - t175 TABLE - t176 TABLE - t177 TABLE - t178 TABLE - t179 TABLE - t180 TABLE - t181 TABLE - t182 TABLE - t183 TABLE - t184 TABLE - t185 TABLE - t186 TABLE - t187 TABLE - t188 TABLE - t189 TABLE - t190 TABLE - t191 TABLE - t192 TABLE - t193 TABLE - t194 TABLE - t195 TABLE - t196 TABLE - t197 TABLE - t198 TABLE - t199 TABLE - t200 TABLE - t201 TABLE - t202 TABLE - t203 TABLE - t204 TABLE - t205 TABLE - t206 TABLE - t207 TABLE - t208 TABLE - t209 TABLE - t210 TABLE - t211 TABLE - t212 TABLE - t213 TABLE - t214 TABLE - t215 TABLE - t216 TABLE - t217 TABLE - t218 TABLE - t219 TABLE - t220 TABLE - t221 TABLE - t222 TABLE - t223 TABLE - t224 TABLE - t225 TABLE - t226 TABLE - t227 TABLE - t228 TABLE - t229 TABLE - t230 TABLE - t231 TABLE - t232 TABLE - t233 TABLE - t234 TABLE - t235 TABLE - t236 TABLE - t237 TABLE - t238 TABLE - t239 TABLE - t240 TABLE - t241 TABLE - t242 TABLE - t243 TABLE - t244 TABLE - t245 TABLE - t246 TABLE - t247 TABLE - t248 TABLE - t249 TABLE - t250 TABLE - t251 TABLE - t252 TABLE - t253 TABLE - t254 TABLE - t255 TABLE - t256 TABLE - t257 TABLE - t258 TABLE - t259 TABLE - t260 TABLE - t261 TABLE - t262 TABLE - t263 TABLE - t264 TABLE - t265 TABLE - t266 TABLE - t267 TABLE - t268 TABLE - t269 TABLE - t270 TABLE - t271 TABLE - t272 TABLE - t273 TABLE - t274 TABLE - t275 TABLE - t276 TABLE - t277 TABLE - t278 TABLE - t279 TABLE - t280 TABLE - t281 TABLE - t282 TABLE - t283 TABLE - t284 TABLE - t285 TABLE - t286 TABLE - t287 TABLE - t288 TABLE - t289 TABLE - t290 TABLE - t291 TABLE - t292 TABLE - t293 TABLE - t294 TABLE - t295 TABLE - t296 TABLE - t297 TABLE - t298 TABLE - t299 TABLE - t300 TABLE - t301 TABLE - t302 TABLE - t303 TABLE - t304 TABLE - t305 TABLE - t306 TABLE - t307 TABLE - t308 TABLE - t309 TABLE - t310 TABLE - t311 TABLE - t312 TABLE - t313 TABLE - t314 TABLE - t315 TABLE - t316 TABLE - t317 TABLE - t318 TABLE - t319 TABLE - t320 TABLE - t321 TABLE - t322 TABLE - t323 TABLE - t324 TABLE - t325 TABLE - t326 TABLE - t327 TABLE - t328 TABLE - t329 TABLE - t330 TABLE - t331 TABLE - t332 TABLE - t333 TABLE - t334 TABLE - t335 TABLE - t336 TABLE - t337 TABLE - t338 TABLE - t339 TABLE - t340 TABLE - t341 TABLE - t342 TABLE - t343 TABLE - t344 TABLE - t345 TABLE - t346 TABLE - t347 TABLE - t348 TABLE - t349 TABLE - t350 TABLE - t351 TABLE - t352 TABLE - t353 TABLE - t354 TABLE - t355 TABLE - t356 TABLE - t357 TABLE - t358 TABLE - t359 TABLE - t360 TABLE - t361 TABLE - t362 TABLE - t363 TABLE - t364 TABLE - t365 TABLE - t366 TABLE - t367 TABLE - t368 TABLE - t369 TABLE - t370 TABLE - t371 TABLE - t372 TABLE - t373 TABLE - t374 TABLE - t375 TABLE - t376 TABLE - t377 TABLE - t378 TABLE - t379 TABLE - t380 TABLE - t381 TABLE - t382 TABLE - t383 TABLE - t384 TABLE - t385 TABLE - t386 TABLE - t387 TABLE - t388 TABLE - t389 TABLE - t390 TABLE - t391 TABLE - t392 TABLE - t393 TABLE - t394 TABLE - t395 TABLE - t396 TABLE - t397 TABLE - t398 TABLE - t399 TABLE +NULL NULL t000 TABLE NULL +NULL NULL t001 TABLE NULL +NULL NULL t002 TABLE NULL +NULL NULL t003 TABLE NULL +NULL NULL t004 TABLE NULL +NULL NULL t005 TABLE NULL +NULL NULL t006 TABLE NULL +NULL NULL t007 TABLE NULL +NULL NULL t008 TABLE NULL +NULL NULL t009 TABLE NULL +NULL NULL t010 TABLE NULL +NULL NULL t011 TABLE NULL +NULL NULL t012 TABLE NULL +NULL NULL t013 TABLE NULL +NULL NULL t014 TABLE NULL +NULL NULL t015 TABLE NULL +NULL NULL t016 TABLE NULL +NULL NULL t017 TABLE NULL +NULL NULL t018 TABLE NULL +NULL NULL t019 TABLE NULL +NULL NULL t020 TABLE NULL +NULL NULL t021 TABLE NULL +NULL NULL t022 TABLE NULL +NULL NULL t023 TABLE NULL +NULL NULL t024 TABLE NULL +NULL NULL t025 TABLE NULL +NULL NULL t026 TABLE NULL +NULL NULL t027 TABLE NULL +NULL NULL t028 TABLE NULL +NULL NULL t029 TABLE NULL +NULL NULL t030 TABLE NULL +NULL NULL t031 TABLE NULL +NULL NULL t032 TABLE NULL +NULL NULL t033 TABLE NULL +NULL NULL t034 TABLE NULL +NULL NULL t035 TABLE NULL +NULL NULL t036 TABLE NULL +NULL NULL t037 TABLE NULL +NULL NULL t038 TABLE NULL +NULL NULL t039 TABLE NULL +NULL NULL t040 TABLE NULL +NULL NULL t041 TABLE NULL +NULL NULL t042 TABLE NULL +NULL NULL t043 TABLE NULL +NULL NULL t044 TABLE NULL +NULL NULL t045 TABLE NULL +NULL NULL t046 TABLE NULL +NULL NULL t047 TABLE NULL +NULL NULL t048 TABLE NULL +NULL NULL t049 TABLE NULL +NULL NULL t050 TABLE NULL +NULL NULL t051 TABLE NULL +NULL NULL t052 TABLE NULL +NULL NULL t053 TABLE NULL +NULL NULL t054 TABLE NULL +NULL NULL t055 TABLE NULL +NULL NULL t056 TABLE NULL +NULL NULL t057 TABLE NULL +NULL NULL t058 TABLE NULL +NULL NULL t059 TABLE NULL +NULL NULL t060 TABLE NULL +NULL NULL t061 TABLE NULL +NULL NULL t062 TABLE NULL +NULL NULL t063 TABLE NULL +NULL NULL t064 TABLE NULL +NULL NULL t065 TABLE NULL +NULL NULL t066 TABLE NULL +NULL NULL t067 TABLE NULL +NULL NULL t068 TABLE NULL +NULL NULL t069 TABLE NULL +NULL NULL t070 TABLE NULL +NULL NULL t071 TABLE NULL +NULL NULL t072 TABLE NULL +NULL NULL t073 TABLE NULL +NULL NULL t074 TABLE NULL +NULL NULL t075 TABLE NULL +NULL NULL t076 TABLE NULL +NULL NULL t077 TABLE NULL +NULL NULL t078 TABLE NULL +NULL NULL t079 TABLE NULL +NULL NULL t080 TABLE NULL +NULL NULL t081 TABLE NULL +NULL NULL t082 TABLE NULL +NULL NULL t083 TABLE NULL +NULL NULL t084 TABLE NULL +NULL NULL t085 TABLE NULL +NULL NULL t086 TABLE NULL +NULL NULL t087 TABLE NULL +NULL NULL t088 TABLE NULL +NULL NULL t089 TABLE NULL +NULL NULL t090 TABLE NULL +NULL NULL t091 TABLE NULL +NULL NULL t092 TABLE NULL +NULL NULL t093 TABLE NULL +NULL NULL t094 TABLE NULL +NULL NULL t095 TABLE NULL +NULL NULL t096 TABLE NULL +NULL NULL t097 TABLE NULL +NULL NULL t098 TABLE NULL +NULL NULL t099 TABLE NULL +NULL NULL t1 TABLE NULL +NULL NULL t100 TABLE NULL +NULL NULL t101 TABLE NULL +NULL NULL t102 TABLE NULL +NULL NULL t103 TABLE NULL +NULL NULL t104 TABLE NULL +NULL NULL t105 TABLE NULL +NULL NULL t106 TABLE NULL +NULL NULL t107 TABLE NULL +NULL NULL t108 TABLE NULL +NULL NULL t109 TABLE NULL +NULL NULL t110 TABLE NULL +NULL NULL t111 TABLE NULL +NULL NULL t112 TABLE NULL +NULL NULL t113 TABLE NULL +NULL NULL t114 TABLE NULL +NULL NULL t115 TABLE NULL +NULL NULL t116 TABLE NULL +NULL NULL t117 TABLE NULL +NULL NULL t118 TABLE NULL +NULL NULL t119 TABLE NULL +NULL NULL t120 TABLE NULL +NULL NULL t121 TABLE NULL +NULL NULL t122 TABLE NULL +NULL NULL t123 TABLE NULL +NULL NULL t124 TABLE NULL +NULL NULL t125 TABLE NULL +NULL NULL t126 TABLE NULL +NULL NULL t127 TABLE NULL +NULL NULL t128 TABLE NULL +NULL NULL t129 TABLE NULL +NULL NULL t130 TABLE NULL +NULL NULL t131 TABLE NULL +NULL NULL t132 TABLE NULL +NULL NULL t133 TABLE NULL +NULL NULL t134 TABLE NULL +NULL NULL t135 TABLE NULL +NULL NULL t136 TABLE NULL +NULL NULL t137 TABLE NULL +NULL NULL t138 TABLE NULL +NULL NULL t139 TABLE NULL +NULL NULL t140 TABLE NULL +NULL NULL t141 TABLE NULL +NULL NULL t142 TABLE NULL +NULL NULL t143 TABLE NULL +NULL NULL t144 TABLE NULL +NULL NULL t145 TABLE NULL +NULL NULL t146 TABLE NULL +NULL NULL t147 TABLE NULL +NULL NULL t148 TABLE NULL +NULL NULL t149 TABLE NULL +NULL NULL t150 TABLE NULL +NULL NULL t151 TABLE NULL +NULL NULL t152 TABLE NULL +NULL NULL t153 TABLE NULL +NULL NULL t154 TABLE NULL +NULL NULL t155 TABLE NULL +NULL NULL t156 TABLE NULL +NULL NULL t157 TABLE NULL +NULL NULL t158 TABLE NULL +NULL NULL t159 TABLE NULL +NULL NULL t160 TABLE NULL +NULL NULL t161 TABLE NULL +NULL NULL t162 TABLE NULL +NULL NULL t163 TABLE NULL +NULL NULL t164 TABLE NULL +NULL NULL t165 TABLE NULL +NULL NULL t166 TABLE NULL +NULL NULL t167 TABLE NULL +NULL NULL t168 TABLE NULL +NULL NULL t169 TABLE NULL +NULL NULL t170 TABLE NULL +NULL NULL t171 TABLE NULL +NULL NULL t172 TABLE NULL +NULL NULL t173 TABLE NULL +NULL NULL t174 TABLE NULL +NULL NULL t175 TABLE NULL +NULL NULL t176 TABLE NULL +NULL NULL t177 TABLE NULL +NULL NULL t178 TABLE NULL +NULL NULL t179 TABLE NULL +NULL NULL t180 TABLE NULL +NULL NULL t181 TABLE NULL +NULL NULL t182 TABLE NULL +NULL NULL t183 TABLE NULL +NULL NULL t184 TABLE NULL +NULL NULL t185 TABLE NULL +NULL NULL t186 TABLE NULL +NULL NULL t187 TABLE NULL +NULL NULL t188 TABLE NULL +NULL NULL t189 TABLE NULL +NULL NULL t190 TABLE NULL +NULL NULL t191 TABLE NULL +NULL NULL t192 TABLE NULL +NULL NULL t193 TABLE NULL +NULL NULL t194 TABLE NULL +NULL NULL t195 TABLE NULL +NULL NULL t196 TABLE NULL +NULL NULL t197 TABLE NULL +NULL NULL t198 TABLE NULL +NULL NULL t199 TABLE NULL +NULL NULL t200 TABLE NULL +NULL NULL t201 TABLE NULL +NULL NULL t202 TABLE NULL +NULL NULL t203 TABLE NULL +NULL NULL t204 TABLE NULL +NULL NULL t205 TABLE NULL +NULL NULL t206 TABLE NULL +NULL NULL t207 TABLE NULL +NULL NULL t208 TABLE NULL +NULL NULL t209 TABLE NULL +NULL NULL t210 TABLE NULL +NULL NULL t211 TABLE NULL +NULL NULL t212 TABLE NULL +NULL NULL t213 TABLE NULL +NULL NULL t214 TABLE NULL +NULL NULL t215 TABLE NULL +NULL NULL t216 TABLE NULL +NULL NULL t217 TABLE NULL +NULL NULL t218 TABLE NULL +NULL NULL t219 TABLE NULL +NULL NULL t220 TABLE NULL +NULL NULL t221 TABLE NULL +NULL NULL t222 TABLE NULL +NULL NULL t223 TABLE NULL +NULL NULL t224 TABLE NULL +NULL NULL t225 TABLE NULL +NULL NULL t226 TABLE NULL +NULL NULL t227 TABLE NULL +NULL NULL t228 TABLE NULL +NULL NULL t229 TABLE NULL +NULL NULL t230 TABLE NULL +NULL NULL t231 TABLE NULL +NULL NULL t232 TABLE NULL +NULL NULL t233 TABLE NULL +NULL NULL t234 TABLE NULL +NULL NULL t235 TABLE NULL +NULL NULL t236 TABLE NULL +NULL NULL t237 TABLE NULL +NULL NULL t238 TABLE NULL +NULL NULL t239 TABLE NULL +NULL NULL t240 TABLE NULL +NULL NULL t241 TABLE NULL +NULL NULL t242 TABLE NULL +NULL NULL t243 TABLE NULL +NULL NULL t244 TABLE NULL +NULL NULL t245 TABLE NULL +NULL NULL t246 TABLE NULL +NULL NULL t247 TABLE NULL +NULL NULL t248 TABLE NULL +NULL NULL t249 TABLE NULL +NULL NULL t250 TABLE NULL +NULL NULL t251 TABLE NULL +NULL NULL t252 TABLE NULL +NULL NULL t253 TABLE NULL +NULL NULL t254 TABLE NULL +NULL NULL t255 TABLE NULL +NULL NULL t256 TABLE NULL +NULL NULL t257 TABLE NULL +NULL NULL t258 TABLE NULL +NULL NULL t259 TABLE NULL +NULL NULL t260 TABLE NULL +NULL NULL t261 TABLE NULL +NULL NULL t262 TABLE NULL +NULL NULL t263 TABLE NULL +NULL NULL t264 TABLE NULL +NULL NULL t265 TABLE NULL +NULL NULL t266 TABLE NULL +NULL NULL t267 TABLE NULL +NULL NULL t268 TABLE NULL +NULL NULL t269 TABLE NULL +NULL NULL t270 TABLE NULL +NULL NULL t271 TABLE NULL +NULL NULL t272 TABLE NULL +NULL NULL t273 TABLE NULL +NULL NULL t274 TABLE NULL +NULL NULL t275 TABLE NULL +NULL NULL t276 TABLE NULL +NULL NULL t277 TABLE NULL +NULL NULL t278 TABLE NULL +NULL NULL t279 TABLE NULL +NULL NULL t280 TABLE NULL +NULL NULL t281 TABLE NULL +NULL NULL t282 TABLE NULL +NULL NULL t283 TABLE NULL +NULL NULL t284 TABLE NULL +NULL NULL t285 TABLE NULL +NULL NULL t286 TABLE NULL +NULL NULL t287 TABLE NULL +NULL NULL t288 TABLE NULL +NULL NULL t289 TABLE NULL +NULL NULL t290 TABLE NULL +NULL NULL t291 TABLE NULL +NULL NULL t292 TABLE NULL +NULL NULL t293 TABLE NULL +NULL NULL t294 TABLE NULL +NULL NULL t295 TABLE NULL +NULL NULL t296 TABLE NULL +NULL NULL t297 TABLE NULL +NULL NULL t298 TABLE NULL +NULL NULL t299 TABLE NULL +NULL NULL t300 TABLE NULL +NULL NULL t301 TABLE NULL +NULL NULL t302 TABLE NULL +NULL NULL t303 TABLE NULL +NULL NULL t304 TABLE NULL +NULL NULL t305 TABLE NULL +NULL NULL t306 TABLE NULL +NULL NULL t307 TABLE NULL +NULL NULL t308 TABLE NULL +NULL NULL t309 TABLE NULL +NULL NULL t310 TABLE NULL +NULL NULL t311 TABLE NULL +NULL NULL t312 TABLE NULL +NULL NULL t313 TABLE NULL +NULL NULL t314 TABLE NULL +NULL NULL t315 TABLE NULL +NULL NULL t316 TABLE NULL +NULL NULL t317 TABLE NULL +NULL NULL t318 TABLE NULL +NULL NULL t319 TABLE NULL +NULL NULL t320 TABLE NULL +NULL NULL t321 TABLE NULL +NULL NULL t322 TABLE NULL +NULL NULL t323 TABLE NULL +NULL NULL t324 TABLE NULL +NULL NULL t325 TABLE NULL +NULL NULL t326 TABLE NULL +NULL NULL t327 TABLE NULL +NULL NULL t328 TABLE NULL +NULL NULL t329 TABLE NULL +NULL NULL t330 TABLE NULL +NULL NULL t331 TABLE NULL +NULL NULL t332 TABLE NULL +NULL NULL t333 TABLE NULL +NULL NULL t334 TABLE NULL +NULL NULL t335 TABLE NULL +NULL NULL t336 TABLE NULL +NULL NULL t337 TABLE NULL +NULL NULL t338 TABLE NULL +NULL NULL t339 TABLE NULL +NULL NULL t340 TABLE NULL +NULL NULL t341 TABLE NULL +NULL NULL t342 TABLE NULL +NULL NULL t343 TABLE NULL +NULL NULL t344 TABLE NULL +NULL NULL t345 TABLE NULL +NULL NULL t346 TABLE NULL +NULL NULL t347 TABLE NULL +NULL NULL t348 TABLE NULL +NULL NULL t349 TABLE NULL +NULL NULL t350 TABLE NULL +NULL NULL t351 TABLE NULL +NULL NULL t352 TABLE NULL +NULL NULL t353 TABLE NULL +NULL NULL t354 TABLE NULL +NULL NULL t355 TABLE NULL +NULL NULL t356 TABLE NULL +NULL NULL t357 TABLE NULL +NULL NULL t358 TABLE NULL +NULL NULL t359 TABLE NULL +NULL NULL t360 TABLE NULL +NULL NULL t361 TABLE NULL +NULL NULL t362 TABLE NULL +NULL NULL t363 TABLE NULL +NULL NULL t364 TABLE NULL +NULL NULL t365 TABLE NULL +NULL NULL t366 TABLE NULL +NULL NULL t367 TABLE NULL +NULL NULL t368 TABLE NULL +NULL NULL t369 TABLE NULL +NULL NULL t370 TABLE NULL +NULL NULL t371 TABLE NULL +NULL NULL t372 TABLE NULL +NULL NULL t373 TABLE NULL +NULL NULL t374 TABLE NULL +NULL NULL t375 TABLE NULL +NULL NULL t376 TABLE NULL +NULL NULL t377 TABLE NULL +NULL NULL t378 TABLE NULL +NULL NULL t379 TABLE NULL +NULL NULL t380 TABLE NULL +NULL NULL t381 TABLE NULL +NULL NULL t382 TABLE NULL +NULL NULL t383 TABLE NULL +NULL NULL t384 TABLE NULL +NULL NULL t385 TABLE NULL +NULL NULL t386 TABLE NULL +NULL NULL t387 TABLE NULL +NULL NULL t388 TABLE NULL +NULL NULL t389 TABLE NULL +NULL NULL t390 TABLE NULL +NULL NULL t391 TABLE NULL +NULL NULL t392 TABLE NULL +NULL NULL t393 TABLE NULL +NULL NULL t394 TABLE NULL +NULL NULL t395 TABLE NULL +NULL NULL t396 TABLE NULL +NULL NULL t397 TABLE NULL +NULL NULL t398 TABLE NULL +NULL NULL t399 TABLE NULL DROP TABLE t1; diff --git a/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result b/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result index 06b4239bd69..f9045e73862 100644 --- a/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result +++ b/storage/connect/mysql-test/connect/r/odbc_sqlite3_grant.result @@ -1,7 +1,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `Description` char(128) NOT NULL, - `Attributes` varchar(256) NOT NULL + `Attributes` varchar(256) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers' SET NAMES utf8; GRANT ALL PRIVILEGES ON *.* TO user@localhost; diff --git a/storage/connect/mysql-test/connect/r/odbc_xls.result b/storage/connect/mysql-test/connect/r/odbc_xls.result index 8c560ef013a..d379cb5b4bb 100644 --- a/storage/connect/mysql-test/connect/r/odbc_xls.result +++ b/storage/connect/mysql-test/connect/r/odbc_xls.result @@ -1,7 +1,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `Name` varchar(256) NOT NULL, - `Description` varchar(256) NOT NULL + `Description` varchar(256) DEFAULT NULL ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Sources' CREATE TABLE contact (Nom VARCHAR(128), Fonction VARCHAR(128), Company VARCHAR(128), Repertoire VARCHAR(30)) ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineXLS;DBQ=DATADIR/test/contacts.xls';; SELECT Nom, Fonction FROM contact WHERE Repertoire='ascii'; @@ -16,11 +16,11 @@ DROP TABLE contact; CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Tables TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineXLS;DBQ=DATADIR/test/contacts.xls' CHARSET=utf8 DATA_CHARSET=latin1;; SELECT * FROM t1 WHERE Table_name='CONTACT'; Table_Cat Table_Schema Table_Name Table_Type Remark -DATADIR/test/contacts CONTACT TABLE +DATADIR/test/contacts NULL CONTACT TABLE NULL DROP TABLE t1; CREATE TABLE t1 ENGINE=CONNECT CATFUNC=Columns TABLE_TYPE=ODBC CONNECTION='DSN=ConnectEngineXLS;DBQ=DATADIR/test/contacts.xls' CHARSET=utf8 DATA_CHARSET=latin1;; SELECT * FROM t1 WHERE Table_name='CONTACT' AND Column_name IN ('Nom','Fonction'); Table_Cat Table_Schema Table_Name Column_Name Data_Type Type_Name Column_Size Buffer_Length Decimal_Digits Radix Nullable Remarks -DATADIR/test/contacts CONTACT Nom 12 VARCHAR 255 510 0 0 1 -DATADIR/test/contacts CONTACT Fonction 12 VARCHAR 255 510 0 0 1 +DATADIR/test/contacts NULL CONTACT Nom 12 VARCHAR 255 510 NULL NULL 1 NULL +DATADIR/test/contacts NULL CONTACT Fonction 12 VARCHAR 255 510 NULL NULL 1 NULL DROP TABLE t1; diff --git a/storage/connect/mysql-test/connect/r/tbl.result b/storage/connect/mysql-test/connect/r/tbl.result index bc77516c22d..f51b4dfa57f 100644 --- a/storage/connect/mysql-test/connect/r/tbl.result +++ b/storage/connect/mysql-test/connect/r/tbl.result @@ -44,8 +44,8 @@ ta message 1 Testing 2 myisam table 3 t4 -CREATE TABLE total (tabname CHAR(8) NOT NULL SPECIAL='TABID', ta TINYINT NOT NULL FLAG=1, message CHAR(20)) engine=CONNECT table_type=TBL table_list='t1,t2,t3,t4' option_list='port=PORT'; -select * from total; +CREATE TABLE total (tabname CHAR(8) NOT NULL SPECIAL='TABID', ta TINYINT NOT NULL FLAG=1, message CHAR(20)) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2,t3,t4' OPTION_LIST='port=PORT'; +SELECT * FROM total; tabname ta message t1 1 Testing t1 2 dos table @@ -59,15 +59,15 @@ t3 3 t3 t4 1 Testing t4 2 myisam table t4 3 t4 -select * from total where tabname = 't2'; +SELECT * FROM total WHERE tabname = 't2'; tabname ta message t2 1 Testing t2 2 NULL t2 3 t2 -select * from total where tabname = 't2' and ta = 3; +SELECT * FROM total WHERE tabname = 't2' AND ta = 3; tabname ta message t2 3 t2 -select * from total where tabname in ('t1','t4'); +SELECT * FROM total WHERE tabname IN ('t1','t4'); tabname ta message t1 1 Testing t1 2 dos table @@ -75,11 +75,11 @@ t1 3 t1 t4 1 Testing t4 2 myisam table t4 3 t4 -select * from total where ta = 3 and tabname in ('t1','t2'); +SELECT * FROM total WHERE ta = 3 AND tabname IN ('t1','t2'); tabname ta message t1 3 t1 t2 3 t2 -select * from total where tabname <> 't2'; +SELECT * FROM total WHERE tabname <> 't2'; tabname ta message t1 1 Testing t1 2 dos table @@ -90,12 +90,12 @@ t3 3 t3 t4 1 Testing t4 2 myisam table t4 3 t4 -select * from total where tabname != 't2' and ta = 3; +SELECT * FROM total WHERE tabname != 't2' AND ta = 3; tabname ta message t1 3 t1 t3 3 t3 t4 3 t4 -select * from total where tabname not in ('t2','t3'); +SELECT * FROM total WHERE tabname NOT IN ('t2','t3'); tabname ta message t1 1 Testing t1 2 dos table @@ -103,11 +103,11 @@ t1 3 t1 t4 1 Testing t4 2 myisam table t4 3 t4 -select * from total where ta = 3 and tabname in ('t2','t3'); +SELECT * FROM total WHERE ta = 3 AND tabname IN ('t2','t3'); tabname ta message t2 3 t2 t3 3 t3 -select * from total where ta = 3 or tabname in ('t2','t4'); +SELECT * FROM total WHERE ta = 3 OR tabname IN ('t2','t4'); tabname ta message t1 3 t1 t2 1 Testing @@ -117,7 +117,7 @@ t3 3 t3 t4 1 Testing t4 2 myisam table t4 3 t4 -select * from total where not tabname = 't2'; +SELECT * FROM total WHERE NOT tabname = 't2'; tabname ta message t1 1 Testing t1 2 dos table @@ -128,7 +128,7 @@ t3 3 t3 t4 1 Testing t4 2 myisam table t4 3 t4 -select * from total where tabname = 't2' or tabname = 't1'; +SELECT * FROM total WHERE tabname = 't2' OR tabname = 't1'; tabname ta message t1 1 Testing t1 2 dos table @@ -141,3 +141,22 @@ DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; DROP TABLE t4; +# +# Checking thread TBL tables +# +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL SRCDEF='select 11 as v'; +SELECT * FROM t1; +v +11 +CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL SRCDEF='select 22 as v'; +SELECT * FROM t2; +v +22 +CREATE TABLE total (v BIGINT(20) UNSIGNED NOT NULL) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2' OPTION_LIST='thread=yes,port=PORT';; +SELECT * FROM total order by v desc; +v +22 +11 +DROP TABLE total; +DROP TABLE t1; +DROP TABLE t2; diff --git a/storage/connect/mysql-test/connect/t/infoschema-9739.test b/storage/connect/mysql-test/connect/t/infoschema-9739.test new file mode 100644 index 00000000000..e9eb7fb796e --- /dev/null +++ b/storage/connect/mysql-test/connect/t/infoschema-9739.test @@ -0,0 +1,9 @@ +# +# MDEV-9739 Assertion `m_status == DA_ERROR || m_status == DA_OK' failed in Diagnostics_area::message() ; connect.xml* tests fail in buildbot +# + +--source have_libxml2.inc + +create table t1 (i int) engine=Connect table_type=XML; +select * from information_schema.tables where create_options like '%table_type=XML%'; +drop table t1; diff --git a/storage/connect/mysql-test/connect/t/json_udf.inc b/storage/connect/mysql-test/connect/t/json_udf.inc index f17d59832f3..2ade7ad02fe 100644 --- a/storage/connect/mysql-test/connect/t/json_udf.inc +++ b/storage/connect/mysql-test/connect/t/json_udf.inc @@ -20,6 +20,8 @@ if (!$HA_CONNECT_SO) { --eval CREATE FUNCTION json_object_delete RETURNS STRING SONAME '$HA_CONNECT_SO'; --eval CREATE FUNCTION json_object_list RETURNS STRING SONAME '$HA_CONNECT_SO'; --eval CREATE FUNCTION jsonvalue RETURNS STRING SONAME '$HA_CONNECT_SO'; +--eval CREATE FUNCTION jsonset_grp_size RETURNS INTEGER SONAME '$HA_CONNECT_SO'; +--eval CREATE FUNCTION jsonget_grp_size RETURNS INTEGER SONAME '$HA_CONNECT_SO'; --eval CREATE AGGREGATE FUNCTION json_array_grp RETURNS STRING SONAME '$HA_CONNECT_SO'; --eval CREATE AGGREGATE FUNCTION json_object_grp RETURNS STRING SONAME '$HA_CONNECT_SO'; --eval CREATE FUNCTION jsonget_string RETURNS STRING SONAME '$HA_CONNECT_SO'; diff --git a/storage/connect/mysql-test/connect/t/json_udf.test b/storage/connect/mysql-test/connect/t/json_udf.test index cfd1fdae258..d11e2fd7cf6 100644 --- a/storage/connect/mysql-test/connect/t/json_udf.test +++ b/storage/connect/mysql-test/connect/t/json_udf.test @@ -108,7 +108,8 @@ CREATE TABLE t3 ( SELECT Json_Object(SERIALNO, NAME, TITLE, SALARY) FROM t3 WHERE NAME = 'MERCHANT'; SELECT DEPARTMENT, Json_Array_Grp(NAME) FROM t3 GROUP BY DEPARTMENT; -SET connect_json_grp_size=30; +#SET connect_json_grp_size=30; Deprecated +SELECT JsonSet_Grp_Size(30); SELECT Json_Object(title, Json_Array_Grp(name) `json_names`) from t3 GROUP BY title; SELECT Json_Array(DEPARTMENT, Json_Array_Grp(NAME)) FROM t3 GROUP BY DEPARTMENT; SELECT Json_Object(DEPARTMENT, Json_Array_Grp(NAME) json_NAMES) FROM t3 GROUP BY DEPARTMENT; diff --git a/storage/connect/mysql-test/connect/t/json_udf2.inc b/storage/connect/mysql-test/connect/t/json_udf2.inc index f62b178b003..4c74e2c11f2 100644 --- a/storage/connect/mysql-test/connect/t/json_udf2.inc +++ b/storage/connect/mysql-test/connect/t/json_udf2.inc @@ -11,6 +11,8 @@ DROP FUNCTION json_object_add; DROP FUNCTION json_object_delete; DROP FUNCTION json_object_list; DROP FUNCTION jsonvalue; +DROP FUNCTION jsonset_grp_size; +DROP FUNCTION jsonget_grp_size; DROP FUNCTION json_array_grp; DROP FUNCTION json_object_grp; DROP FUNCTION jsonget_string; diff --git a/storage/connect/mysql-test/connect/t/tbl.test b/storage/connect/mysql-test/connect/t/tbl.test index 43c506c9403..3dc4b2e64b0 100644 --- a/storage/connect/mysql-test/connect/t/tbl.test +++ b/storage/connect/mysql-test/connect/t/tbl.test @@ -31,23 +31,40 @@ INSERT INTO t4 (message) VALUES ('Testing'),('myisam table'),('t4'); SELECT * FROM t4; --replace_result $PORT PORT ---eval CREATE TABLE total (tabname CHAR(8) NOT NULL SPECIAL='TABID', ta TINYINT NOT NULL FLAG=1, message CHAR(20)) engine=CONNECT table_type=TBL table_list='t1,t2,t3,t4' option_list='port=$PORT' - -select * from total; -select * from total where tabname = 't2'; -select * from total where tabname = 't2' and ta = 3; -select * from total where tabname in ('t1','t4'); -select * from total where ta = 3 and tabname in ('t1','t2'); -select * from total where tabname <> 't2'; -select * from total where tabname != 't2' and ta = 3; -select * from total where tabname not in ('t2','t3'); -select * from total where ta = 3 and tabname in ('t2','t3'); -select * from total where ta = 3 or tabname in ('t2','t4'); -select * from total where not tabname = 't2'; -select * from total where tabname = 't2' or tabname = 't1'; +--eval CREATE TABLE total (tabname CHAR(8) NOT NULL SPECIAL='TABID', ta TINYINT NOT NULL FLAG=1, message CHAR(20)) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2,t3,t4' OPTION_LIST='port=$PORT' + +SELECT * FROM total; +SELECT * FROM total WHERE tabname = 't2'; +SELECT * FROM total WHERE tabname = 't2' AND ta = 3; +SELECT * FROM total WHERE tabname IN ('t1','t4'); +SELECT * FROM total WHERE ta = 3 AND tabname IN ('t1','t2'); +SELECT * FROM total WHERE tabname <> 't2'; +SELECT * FROM total WHERE tabname != 't2' AND ta = 3; +SELECT * FROM total WHERE tabname NOT IN ('t2','t3'); +SELECT * FROM total WHERE ta = 3 AND tabname IN ('t2','t3'); +SELECT * FROM total WHERE ta = 3 OR tabname IN ('t2','t4'); +SELECT * FROM total WHERE NOT tabname = 't2'; +SELECT * FROM total WHERE tabname = 't2' OR tabname = 't1'; DROP TABLE total; DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; DROP TABLE t4; + +--echo # +--echo # Checking thread TBL tables +--echo # +CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=MYSQL SRCDEF='select 11 as v'; +SELECT * FROM t1; + +CREATE TABLE t2 ENGINE=CONNECT TABLE_TYPE=MYSQL SRCDEF='select 22 as v'; +SELECT * FROM t2; + +--replace_result $PORT PORT +--eval CREATE TABLE total (v BIGINT(20) UNSIGNED NOT NULL) ENGINE=CONNECT TABLE_TYPE=TBL TABLE_LIST='t1,t2' OPTION_LIST='thread=yes,port=$PORT'; +SELECT * FROM total order by v desc; + +DROP TABLE total; +DROP TABLE t1; +DROP TABLE t2; diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp index 1ccdf231970..55ccbdbada1 100644 --- a/storage/connect/odbconn.cpp +++ b/storage/connect/odbconn.cpp @@ -1,7 +1,7 @@ /************ Odbconn C++ Functions Source Code File (.CPP) ************/ /* Name: ODBCONN.CPP Version 2.2 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 1998-2015 */ +/* (C) Copyright to the author Olivier BERTRAND 1998-2016 */ /* */ /* This file contains the ODBC connection classes functions. */ /***********************************************************************/ @@ -314,8 +314,10 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table, FLD_TYPE, FLD_TYPENAME, FLD_PREC, FLD_LENGTH, FLD_SCALE, FLD_RADIX, FLD_NULL, FLD_REM}; unsigned int length[] = {0, 0, 0, 0, 6, 0, 10, 10, 6, 6, 6, 0}; - int n, ncol = 12; - PQRYRES qrp; + bool b[] = {true,true,false,false,false,false,false,false,true,true,false,true}; + int i, n, ncol = 12; + PCOLRES crp; + PQRYRES qrp; CATPARM *cap; ODBConn *ocp = NULL; @@ -363,6 +365,10 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *db, char *table, qrp = PlgAllocResult(g, ncol, maxres, IDS_COLUMNS, buftyp, fldtyp, length, false, true); + for (i = 0, crp = qrp->Colresp; crp; i++, crp = crp->Next) + if (b[i]) + crp->Kdata->SetNullable(true); + if (info || !qrp) // Info table return qrp; @@ -495,8 +501,10 @@ PQRYRES ODBCDrivers(PGLOBAL g, int maxres, bool info) int buftyp[] = {TYPE_STRING, TYPE_STRING}; XFLD fldtyp[] = {FLD_NAME, FLD_REM}; unsigned int length[] = {128, 256}; - int ncol = 2; - PQRYRES qrp; + bool b[] = {false, true}; + int i, ncol = 2; + PCOLRES crp; + PQRYRES qrp; ODBConn *ocp = NULL; /************************************************************************/ @@ -520,7 +528,11 @@ PQRYRES ODBCDrivers(PGLOBAL g, int maxres, bool info) qrp = PlgAllocResult(g, ncol, maxres, IDS_DRIVER, buftyp, fldtyp, length, false, true); - /************************************************************************/ + for (i = 0, crp = qrp->Colresp; crp; i++, crp = crp->Next) + if (b[i]) + crp->Kdata->SetNullable(true); + + /************************************************************************/ /* Now get the results into blocks. */ /************************************************************************/ if (!info && qrp && ocp->GetDrivers(qrp)) @@ -542,8 +554,10 @@ PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info) int buftyp[] = {TYPE_STRING, TYPE_STRING}; XFLD fldtyp[] = {FLD_NAME, FLD_REM}; unsigned int length[] = {0, 256}; - int n = 0, ncol = 2; - PQRYRES qrp; + bool b[] = {false, true}; + int i, n = 0, ncol = 2; + PCOLRES crp; + PQRYRES qrp; ODBConn *ocp = NULL; /************************************************************************/ @@ -571,7 +585,11 @@ PQRYRES ODBCDataSources(PGLOBAL g, int maxres, bool info) qrp = PlgAllocResult(g, ncol, maxres, IDS_DSRC, buftyp, fldtyp, length, false, true); - /************************************************************************/ + for (i = 0, crp = qrp->Colresp; crp; i++, crp = crp->Next) + if (b[i]) + crp->Kdata->SetNullable(true); + + /************************************************************************/ /* Now get the results into blocks. */ /************************************************************************/ if (!info && qrp && ocp->GetDataSources(qrp)) @@ -595,8 +613,10 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat, XFLD fldtyp[] = {FLD_CAT, FLD_SCHEM, FLD_NAME, FLD_TYPE, FLD_REM}; unsigned int length[] = {0, 0, 0, 16, 0}; - int n, ncol = 5; - PQRYRES qrp; + bool b[] ={ true, true, false, false, true }; + int i, n, ncol = 5; + PCOLRES crp; + PQRYRES qrp; CATPARM *cap; ODBConn *ocp = NULL; @@ -638,7 +658,11 @@ PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *db, char *tabpat, qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES, buftyp, fldtyp, length, false, true); - if (info || !qrp) + for (i = 0, crp = qrp->Colresp; crp; i++, crp = crp->Next) + if (b[i]) + crp->Kdata->SetNullable(true); + + if (info || !qrp) return qrp; if (!(cap = AllocCatInfo(g, CAT_TAB, db, tabpat, qrp))) @@ -1734,7 +1758,9 @@ bool ODBConn::BindParam(ODBCCOL *colp) SQLLEN *strlen = colp->GetStrLen(); SQLRETURN rc; +#if 0 try { + // This function is often not or badly implemented by data sources rc = SQLDescribeParam(m_hstmt, n, &sqlt, &colsize, &dec, &nul); if (!Check(rc)) @@ -1742,11 +1768,12 @@ bool ODBConn::BindParam(ODBCCOL *colp) } catch(DBX *x) { sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0)); +#endif // 0 colsize = colp->GetPrecision(); sqlt = GetSQLType(buftype); - dec = IsTypeChar(buftype) ? 0 : colp->GetScale(); - nul = SQL_NULLABLE_UNKNOWN; - } // end try/catch + dec = IsTypeNum(buftype) ? colp->GetScale() : 0; + nul = colp->IsNullable() ? SQL_NULLABLE : SQL_NO_NULLS; +//} // end try/catch buf = colp->GetBuffer(0); len = IsTypeChar(buftype) ? colp->GetBuflen() : 0; @@ -2249,7 +2276,7 @@ int ODBConn::GetCatInfo(CATPARM *cap) rc = SQLTables(hstmt, name.ptr(2), name.length(2), name.ptr(1), name.length(1), name.ptr(0), name.length(0), - cap->Pat, SQL_NTS); + cap->Pat, cap->Pat ? SQL_NTS : 0); break; case CAT_COL: // rc = SQLSetStmtAttr(hstmt, SQL_ATTR_METADATA_ID, @@ -2258,7 +2285,7 @@ int ODBConn::GetCatInfo(CATPARM *cap) rc = SQLColumns(hstmt, name.ptr(2), name.length(2), name.ptr(1), name.length(1), name.ptr(0), name.length(0), - cap->Pat, SQL_NTS); + cap->Pat, cap->Pat ? SQL_NTS : 0); break; case CAT_KEY: fnc = "SQLPrimaryKeys"; diff --git a/storage/connect/plgcnx.h b/storage/connect/plgcnx.h index a1208f9b885..1b341bc5275 100644 --- a/storage/connect/plgcnx.h +++ b/storage/connect/plgcnx.h @@ -25,7 +25,7 @@ enum FNRC {RC_LICENSE = 7, /* PLGConnect prompt for license key */ RC_SUCCESS = 0, /* Successful function (must be 0) */ RC_MEMORY = -1, /* Storage allocation error */ RC_TRUNCATED = -2, /* Result has been truncated */ - RC_TIMEOUT = -3, /* Connection timeout occured */ + RC_TIMEOUT = -3, /* Connection timeout occurred */ RC_TOOBIG = -4, /* Data is too big for connection */ RC_KEY = -5, /* Null ptr to key in Connect */ /* or bad key in other functions */ diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index 8f9328c0b2f..e455bc8f1a5 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -1,11 +1,11 @@ /************* RelDef CPP Program Source Code File (.CPP) **************/ /* PROGRAM NAME: RELDEF */ /* ------------- */ -/* Version 1.4 */ +/* Version 1.5 */ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 2004-2015 */ +/* (C) Copyright to the author Olivier BERTRAND 2004-2016 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -37,6 +37,7 @@ #include "plgdbsem.h" #include "reldef.h" #include "colblk.h" +#include "tabcol.h" #include "filamap.h" #include "filamfix.h" #include "filamvct.h" @@ -217,11 +218,13 @@ TABDEF::TABDEF(void) /***********************************************************************/ /* Define: initialize the table definition block from XDB file. */ /***********************************************************************/ -bool TABDEF::Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am) +bool TABDEF::Define(PGLOBAL g, PCATLG cat, + LPCSTR name, LPCSTR schema, LPCSTR am) { int poff = 0; - Name = (PSZ)PlugDup(g, name); + Name = (PSZ)name; + Schema = (PSZ)schema; Cat = cat; Hc = ((MYCAT*)cat)->GetHandler(); Catfunc = GetFuncID(GetStringCatInfo(g, "Catfunc", NULL)); @@ -569,7 +572,7 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) } // endif Cbuf // Here "OEM" should be replace by a more useful value - if (xdefp->Define(g, cat, Name, "OEM")) + if (xdefp->Define(g, cat, Name, Schema, "OEM")) return NULL; // Ok, return external block diff --git a/storage/connect/reldef.h b/storage/connect/reldef.h index dada5716dbe..bc1bd2ddd74 100644 --- a/storage/connect/reldef.h +++ b/storage/connect/reldef.h @@ -1,7 +1,7 @@ /*************** RelDef H Declares Source Code File (.H) ***************/ -/* Name: RELDEF.H Version 1.5 */ +/* Name: RELDEF.H Version 1.6 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2004-2015 */ +/* (C) Copyright to the author Olivier BERTRAND 2004-2016 */ /* */ /* This file contains the DEF classes definitions. */ /***********************************************************************/ @@ -50,7 +50,8 @@ class DllExport RELDEF : public BLOCK { // Relation definition block int GetCharCatInfo(PSZ what, PSZ sdef, char *buf, int size); char *GetStringCatInfo(PGLOBAL g, PSZ what, PSZ sdef); virtual int Indexable(void) {return 0;} - virtual bool Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am) = 0; + virtual bool Define(PGLOBAL g, PCATLG cat, + LPCSTR name, LPCSTR schema, LPCSTR am) = 0; virtual PTDB GetTable(PGLOBAL g, MODE mode) = 0; protected: @@ -97,8 +98,9 @@ class DllExport TABDEF : public RELDEF { /* Logical table descriptor */ int GetColCatInfo(PGLOBAL g); void SetIndexInfo(void); bool DropTable(PGLOBAL g, PSZ name); - virtual bool Define(PGLOBAL g, PCATLG cat, LPCSTR name, LPCSTR am); - virtual bool DefineAM(PGLOBAL, LPCSTR, int) = 0; + virtual bool Define(PGLOBAL g, PCATLG cat, + LPCSTR name, LPCSTR schema, LPCSTR am); + virtual bool DefineAM(PGLOBAL, LPCSTR, int) = 0; protected: // Members diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp index 7906f6c9219..98633f49d23 100644 --- a/storage/connect/tabdos.cpp +++ b/storage/connect/tabdos.cpp @@ -184,7 +184,7 @@ bool DOSDEF::GetOptFileName(PGLOBAL g, char *filename) } // end of GetOptFileName /***********************************************************************/ -/* After an optimize error occured, remove all set optimize values. */ +/* After an optimize error occurred, remove all set optimize values. */ /***********************************************************************/ void DOSDEF::RemoveOptValues(PGLOBAL g) { diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp index 933e072c1bb..c21bb1660ea 100644 --- a/storage/connect/table.cpp +++ b/storage/connect/table.cpp @@ -1,7 +1,7 @@ /************** Table C++ Functions Source Code File (.CPP) ************/ /* Name: TABLE.CPP Version 2.7 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 1999-2015 */ +/* (C) Copyright to the author Olivier BERTRAND 1999-2016 */ /* */ /* This file contains the TBX, TDB and OPJOIN classes functions. */ /***********************************************************************/ @@ -518,7 +518,8 @@ bool TDBCAT::InitCol(PGLOBAL g) sprintf(g->Message, "Invalid flag %d for column %s", colp->Flag, colp->Name); return true; - } // endif Crp + } else if (crp->Fld == FLD_SCALE || crp->Fld == FLD_RADIX) + colp->Value->SetNullable(true); } // endfor colp @@ -586,11 +587,14 @@ CATCOL::CATCOL(PCOLDEF cdp, PTDB tdbp, int n) /***********************************************************************/ void CATCOL::ReadColumn(PGLOBAL) { + bool b = (!Crp->Kdata || Crp->Kdata->IsNull(Tdbp->N)); + // Get the value of the Name or Description property - if (Crp->Kdata) + if (!b) Value->SetValue_pvblk(Crp->Kdata, Tdbp->N); else Value->Reset(); + Value->SetNull(b); } // end of ReadColumn diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index 658f3513b07..47497f465e3 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -334,7 +334,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int) Delayed = !!GetIntCatInfo("Delayed", 0); } else { // MYSQL access from a PROXY table - Database = GetStringCatInfo(g, "Database", "*"); + Database = GetStringCatInfo(g, "Database", Schema ? Schema : PlugDup(g, "*")); Isview = GetBoolCatInfo("View", false); // We must get other connection parms from the calling table @@ -806,7 +806,7 @@ int TDBMYSQL::GetMaxSize(PGLOBAL g) else if (!Cardinality(NULL)) MaxSize = 10; // To make MySQL happy else if ((MaxSize = Cardinality(g)) < 0) - MaxSize = 12; // So we can see an error occured + MaxSize = 12; // So we can see an error occurred } // endif MaxSize diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp index fd9a049a05a..c555f2a5abb 100644 --- a/storage/connect/tabodbc.cpp +++ b/storage/connect/tabodbc.cpp @@ -5,7 +5,7 @@ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 2000-2015 */ +/* (C) Copyright to the author Olivier BERTRAND 2000-2016 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -818,7 +818,7 @@ int TDBODBC::GetMaxSize(PGLOBAL g) else if (!Cardinality(NULL)) MaxSize = 10; // To make MySQL happy else if ((MaxSize = Cardinality(g)) < 0) - MaxSize = 12; // So we can see an error occured + MaxSize = 12; // So we can see an error occurred } // endif MaxSize @@ -912,19 +912,21 @@ bool TDBODBC::OpenDB(PGLOBAL g) if ((n = Ocp->GetResultSize(Query->GetStr(), Cnp)) < 0) { strcpy(g->Message, "Cannot get result size"); return true; - } // endif n + } else if (n) { + Ocp->m_Rows = n; - Ocp->m_Rows = n; + if ((Qrp = Ocp->AllocateResult(g))) + Memory = 2; // Must be filled + else { + strcpy(g->Message, "Result set memory allocation failed"); + return true; + } // endif n - if ((Qrp = Ocp->AllocateResult(g))) - Memory = 2; // Must be filled - else { - strcpy(g->Message, "Result set memory allocation failed"); - return true; - } // endif n + } else // Void result + Memory = 0; - Ocp->m_Rows = 0; - } else + Ocp->m_Rows = 0; + } else return true; } // endif Memory diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp index b628e26d3c7..256b454741c 100644 --- a/storage/connect/tabpivot.cpp +++ b/storage/connect/tabpivot.cpp @@ -348,7 +348,7 @@ bool PIVOTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) return TRUE; Tabname = (char*)Tablep->GetName(); - DB = (char*)Tablep->GetQualifier(); + DB = (char*)Tablep->GetSchema(); Tabsrc = (char*)Tablep->GetSrc(); Host = GetStringCatInfo(g, "Host", "localhost"); @@ -529,7 +529,7 @@ bool TDBPIVOT::GetSourceTable(PGLOBAL g) // Get the new table description block of this source table PTABLE tablep = new(g) XTAB("whatever", Tabsrc); - tablep->SetQualifier(Database); + tablep->SetSchema(Database); if (!(Tdbp = GetSubTable(g, tablep, true))) return true; diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index 7f979eaf4be..36849146746 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -5,7 +5,7 @@ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to PlugDB Software Development 2008-2015 */ +/* (C) Copyright to PlugDB Software Development 2008-2016 */ /* Author: Olivier BERTRAND */ /* */ /* WHAT THIS PROGRAM DOES: */ @@ -130,10 +130,10 @@ bool TBLDEF::DefineAM(PGLOBAL g, LPCSTR, int) // Allocate the TBLIST block for that table tbl = new(g) XTAB(pn, def); - tbl->SetQualifier(pdb); + tbl->SetSchema(pdb); if (trace) - htrc("TBL: Name=%s db=%s\n", tbl->GetName(), tbl->GetQualifier()); + htrc("TBL: Name=%s db=%s\n", tbl->GetName(), tbl->GetSchema()); // Link the blocks if (Tablep) @@ -607,7 +607,7 @@ void TDBTBM::ResetDB(void) for (PTABLE tabp = Tablist; tabp; tabp = tabp->GetNext()) ((PTDBASE)tabp->GetTo_Tdb())->ResetDB(); - Tdbp = (PTDBASE)Tablist->GetTo_Tdb(); + Tdbp = (Tablist) ? (PTDBASE)Tablist->GetTo_Tdb() : NULL; Crp = 0; } // end of ResetDB @@ -679,7 +679,7 @@ bool TDBTBM::OpenDB(PGLOBAL g) /* Table already open, replace it at its beginning. */ /*******************************************************************/ ResetDB(); - return Tdbp->OpenDB(g); // Re-open fist table + return (Tdbp) ? Tdbp->OpenDB(g) : false; // Re-open fist table } // endif use #if 0 diff --git a/storage/connect/tabtbl.h b/storage/connect/tabtbl.h index 9d3f297f9e7..3a5ec45d025 100644 --- a/storage/connect/tabtbl.h +++ b/storage/connect/tabtbl.h @@ -138,7 +138,8 @@ class DllExport TDBTBM : public TDBTBL { virtual void ResetDB(void); // Database routines - virtual int GetMaxSize(PGLOBAL g) {return 10;} // Temporary + virtual int Cardinality(PGLOBAL g) { return 10; } + virtual int GetMaxSize(PGLOBAL g) { return 10; } // Temporary virtual int RowNumber(PGLOBAL g, bool b = FALSE); virtual bool OpenDB(PGLOBAL g); virtual int ReadDB(PGLOBAL g); diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp index 331a7f45d4d..4069cdbed2a 100644 --- a/storage/connect/tabutil.cpp +++ b/storage/connect/tabutil.cpp @@ -1,7 +1,7 @@ /************* Tabutil cpp Declares Source Code File (.CPP) ************/ /* Name: TABUTIL.CPP Version 1.1 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2013 - 2015 */ +/* (C) Copyright to the author Olivier BERTRAND 2013 - 2016 */ /* */ /* Utility function used by the PROXY, XCOL, OCCUR, and TBL tables. */ /***********************************************************************/ @@ -118,7 +118,7 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, FLD_LENGTH, FLD_SCALE, FLD_RADIX, FLD_NULL, FLD_REM, FLD_NO, FLD_CHARSET}; unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 32, 32}; - char *fld, *colname, *chset, *fmt, v; + char *pn, *tn, *fld, *colname, *chset, *fmt, v; int i, n, ncol = sizeof(buftyp) / sizeof(int); int prec, len, type, scale; int zconv = GetConvSize(); @@ -130,7 +130,16 @@ PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db, PCOLRES crp; if (!info) { - if (!(s = GetTableShare(g, thd, db, name, mysql))) { + // Analyze the table name, it may have the format: [dbname.]tabname + if (strchr((char*)name, '.')) { + tn = (char*)PlugDup(g, name); + pn = strchr(tn, '.'); + *pn++ = 0; + db = tn; + name = pn; + } // endif pn + + if (!(s = GetTableShare(g, thd, db, name, mysql))) { return NULL; } else if (s->is_view) { strcpy(g->Message, "Use MYSQL type to see columns from a view"); @@ -315,7 +324,7 @@ bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR, int) } // endif pn Tablep = new(g) XTAB(tab, def); - Tablep->SetQualifier(db); + Tablep->SetSchema(db); return false; } // end of DefineAM @@ -379,12 +388,12 @@ PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b) LPCSTR cdb, curdb = hc->GetDBName(NULL); THD *thd = (hc->GetTable())->in_use; - db = (char*)tabp->GetQualifier(); + db = (char*)(tabp->GetSchema() ? tabp->GetSchema() : curdb); name = (char*)tabp->GetName(); // Check for eventual loop for (PTABLE tp = To_Table; tp; tp = tp->Next) { - cdb = (tp->Qualifier) ? tp->Qualifier : curdb; + cdb = (tp->Schema) ? tp->Schema : curdb; if (!stricmp(name, tp->Name) && !stricmp(db, cdb)) { sprintf(g->Message, "Table %s.%s pointing on itself", db, name); @@ -423,7 +432,7 @@ PTDBASE TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b) } // endif Define if (db) - ((PTDBMY)tdbp)->SetDatabase(tabp->GetQualifier()); + ((PTDBMY)tdbp)->SetDatabase(tabp->GetSchema()); if (Mode == MODE_UPDATE || Mode == MODE_DELETE) tdbp->SetName(Name); // For Make_Command @@ -757,7 +766,7 @@ void PRXCOL::WriteColumn(PGLOBAL g) /***********************************************************************/ TDBTBC::TDBTBC(PPRXDEF tdp) : TDBCAT(tdp) { - Db = (PSZ)tdp->Tablep->GetQualifier(); + Db = (PSZ)tdp->Tablep->GetSchema(); Tab = (PSZ)tdp->Tablep->GetName(); } // end of TDBTBC constructor diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h index f6eb7258a77..c3cad79b234 100644 --- a/storage/connect/valblk.h +++ b/storage/connect/valblk.h @@ -73,7 +73,8 @@ class VALBLK : public BLOCK { virtual void SetNull(int n, bool b) {if (To_Nulls) {To_Nulls[n] = (b) ? '*' : 0;}} virtual bool IsNull(int n) {return To_Nulls && To_Nulls[n];} - virtual void SetNullable(bool b); + virtual bool IsNullable(void) {return Nullable;} + virtual void SetNullable(bool b); virtual bool IsUnsigned(void) {return Unsigned;} virtual bool Init(PGLOBAL g, bool check) = 0; virtual int GetVlen(void) = 0; diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index f9597cb842b..64d0e13e8c4 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -989,7 +989,7 @@ uchar TYPVAL<uchar>::MinMaxVal(bool b) {return (b) ? UINT_MAX8 : 0;} /***********************************************************************/ -/* SafeAdd: adds a value and test whether overflow/underflow occured. */ +/* SafeAdd: adds a value and test whether overflow/underflow occurred. */ /***********************************************************************/ template <class TYPE> TYPE TYPVAL<TYPE>::SafeAdd(TYPE n1, TYPE n2) @@ -1017,7 +1017,7 @@ inline double TYPVAL<double>::SafeAdd(double n1, double n2) } // end of SafeAdd /***********************************************************************/ -/* SafeMult: multiply values and test whether overflow occured. */ +/* SafeMult: multiply values and test whether overflow occurred. */ /***********************************************************************/ template <class TYPE> TYPE TYPVAL<TYPE>::SafeMult(TYPE n1, TYPE n2) @@ -1344,10 +1344,13 @@ bool TYPVAL<PSZ>::SetValue_pval(PVAL valp, bool chktype) /***********************************************************************/ bool TYPVAL<PSZ>::SetValue_char(char *p, int n) { - bool rc; + bool rc = false; - if (p && n > 0) { - rc = n > Len; + if (!p || n == 0) { + Reset(); + Null = Nullable; + } else if (p != Strp) { + rc = n > Len; if ((n = MY_MIN(n, Len))) { strncpy(Strp, p, n); @@ -1366,10 +1369,6 @@ bool TYPVAL<PSZ>::SetValue_char(char *p, int n) Reset(); Null = false; - } else { - rc = false; - Reset(); - Null = Nullable; } // endif p return rc; @@ -1380,12 +1379,12 @@ bool TYPVAL<PSZ>::SetValue_char(char *p, int n) /***********************************************************************/ void TYPVAL<PSZ>::SetValue_psz(PSZ s) { - if (s) { - strncpy(Strp, s, Len); + if (!s) { + Reset(); + Null = Nullable; + } else if (s != Strp) { + strncpy(Strp, s, Len); Null = false; - } else { - Reset(); - Null = Nullable; } // endif s } // end of SetValue_psz @@ -1643,7 +1642,7 @@ bool TYPVAL<PSZ>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op) assert(np == 1 || np == 2); if (np == 2) - strncpy(Strp, p[0], Len); + SetValue_psz(p[0]); if ((i = Len - (signed)strlen(Strp)) > 0) strncat(Strp, p[np - 1], i); @@ -1651,11 +1650,11 @@ bool TYPVAL<PSZ>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op) break; case OP_MIN: assert(np == 2); - strcpy(Strp, (strcmp(p[0], p[1]) < 0) ? p[0] : p[1]); + SetValue_psz((strcmp(p[0], p[1]) < 0) ? p[0] : p[1]); break; case OP_MAX: assert(np == 2); - strcpy(Strp, (strcmp(p[0], p[1]) > 0) ? p[0] : p[1]); + SetValue_psz((strcmp(p[0], p[1]) > 0) ? p[0] : p[1]); break; default: // sprintf(g->Message, MSG(BAD_EXP_OPER), op); diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h index 000b46b2bb2..127c6053a53 100644 --- a/storage/csv/ha_tina.h +++ b/storage/csv/ha_tina.h @@ -71,7 +71,7 @@ class ha_tina: public handler File update_temp_file; String buffer; /* - The chain contains "holes" in the file, occured because of + The chain contains "holes" in the file, occurred because of deletes/updates. It is used in rnd_end() to get rid of them in the end of the query. */ diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 0bf4d766d64..478a8f1cfaa 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -2016,7 +2016,7 @@ void ha_federated::start_bulk_insert(ha_rows rows, uint flags) @return Operation status @retval 0 No error - @retval != 0 Error occured at remote server. Also sets my_errno. + @retval != 0 Error occurred at remote server. Also sets my_errno. */ int ha_federated::end_bulk_insert() diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index 5834e70c2e5..890d1bff292 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -2157,7 +2157,7 @@ void ha_federatedx::start_bulk_insert(ha_rows rows, uint flags) @return Operation status @retval 0 No error - @retval != 0 Error occured at remote server. Also sets my_errno. + @retval != 0 Error occurred at remote server. Also sets my_errno. */ int ha_federatedx::end_bulk_insert() diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 68d5dd325ff..be5b04787dd 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -777,6 +777,10 @@ btr_root_get( buf_block_t* root = btr_root_block_get(index, RW_X_LATCH, mtr); + if (root && root->page.encrypted == true) { + root = NULL; + } + return(root ? buf_block_get_frame(root) : NULL); } diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index f4e7c0d0c6b..bd424b7b598 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -4674,10 +4674,10 @@ corrupt: ib_push_warning((void *)NULL, DB_DECRYPTION_FAILED, "Table in tablespace %lu encrypted." - "However key management plugin or used key_id %lu is not found or" + "However key management plugin or used key_id %u is not found or" " used encryption algorithm or method does not match." " Can't continue opening the table.", - bpage->key_version); + (ulint)bpage->space, bpage->key_version); if (bpage->space > TRX_SYS_SPACE) { if (corrupted) { @@ -4701,10 +4701,19 @@ corrupt: } if (uncompressed && !recv_no_ibuf_operations) { - ibuf_merge_or_delete_for_page( - (buf_block_t*) bpage, bpage->space, - bpage->offset, buf_page_get_zip_size(bpage), - TRUE); + if (bpage && bpage->encrypted) { + fprintf(stderr, + "InnoDB: Warning: Table in tablespace %lu encrypted." + "However key management plugin or used key_id %u is not found or" + " used encryption algorithm or method does not match." + " Can't continue opening the table.\n", + (ulint)bpage->space, bpage->key_version); + } else { + ibuf_merge_or_delete_for_page( + (buf_block_t*) bpage, bpage->space, + bpage->offset, buf_page_get_zip_size(bpage), + TRUE); + } } } else { /* io_type == BUF_IO_WRITE */ @@ -6156,6 +6165,7 @@ buf_page_decrypt_after_read( bool page_compressed = fil_page_is_compressed(dst_frame); bool page_compressed_encrypted = fil_page_is_compressed_encrypted(dst_frame); buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + bool success = true; /* If page is encrypted read post-encryption checksum */ if (!page_compressed_encrypted && key_version != 0) { @@ -6214,16 +6224,21 @@ buf_page_decrypt_after_read( } /* decrypt using crypt_buf to dst_frame */ - fil_space_decrypt(bpage->space, - slot->crypt_buf, - size, - dst_frame); + byte* res = fil_space_decrypt(bpage->space, + slot->crypt_buf, + size, + dst_frame); + + if (!res) { + bpage->encrypted = true; + success = false; + } #ifdef UNIV_DEBUG fil_page_type_validate(dst_frame); #endif } - if (page_compressed_encrypted) { + if (page_compressed_encrypted && success) { if (!slot) { slot = buf_pool_reserve_tmp_slot(buf_pool, page_compressed); } @@ -6236,11 +6251,11 @@ buf_page_decrypt_after_read( dst_frame, size, &bpage->write_size); - } #ifdef UNIV_DEBUG - fil_page_type_validate(dst_frame); + fil_page_type_validate(dst_frame); #endif + } /* Mark this slot as free */ if (slot) { @@ -6250,5 +6265,5 @@ buf_page_decrypt_after_read( bpage->key_version = key_version; - return (TRUE); + return (success); } diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index 9748b35e93b..6f3aca0e1fb 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -163,6 +163,25 @@ buf_load_status( va_end(ap); } +/** Returns the directory path where the buffer pool dump file will be created. +@return directory path */ +static +const char* +get_buf_dump_dir() +{ + const char* dump_dir; + + /* The dump file should be created in the default data directory if + innodb_data_home_dir is set as an empty string. */ + if (strcmp(srv_data_home, "") == 0) { + dump_dir = fil_path_to_mysql_datadir; + } else { + dump_dir = srv_data_home; + } + + return(dump_dir); +} + /*****************************************************************//** Perform a buffer pool dump into the file specified by innodb_buffer_pool_filename. If any errors occur then the value of @@ -186,7 +205,7 @@ buf_dump( int ret; ut_snprintf(full_filename, sizeof(full_filename), - "%s%c%s", srv_data_home, SRV_PATH_SEPARATOR, + "%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR, srv_buf_dump_filename); ut_snprintf(tmp_filename, sizeof(tmp_filename), @@ -471,7 +490,7 @@ buf_load() buf_load_abort_flag = FALSE; ut_snprintf(full_filename, sizeof(full_filename), - "%s%c%s", srv_data_home, SRV_PATH_SEPARATOR, + "%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR, srv_buf_dump_filename); buf_load_status(STATUS_NOTICE, diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc index 1a1dd29a202..573357b54ee 100644 --- a/storage/innobase/dict/dict0boot.cc +++ b/storage/innobase/dict/dict0boot.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -450,27 +451,29 @@ dict_boot(void) /* Initialize the insert buffer table and index for each tablespace */ - ibuf_init_at_db_start(); - dberr_t err = DB_SUCCESS; - if (srv_read_only_mode && !ibuf_is_empty()) { + err = ibuf_init_at_db_start(); - ib_logf(IB_LOG_LEVEL_ERROR, - "Change buffer must be empty when --innodb-read-only " - "is set!"); + if (err == DB_SUCCESS) { + if (srv_read_only_mode && !ibuf_is_empty()) { - err = DB_ERROR; - } else { - /* Load definitions of other indexes on system tables */ + ib_logf(IB_LOG_LEVEL_ERROR, + "Change buffer must be empty when --innodb-read-only " + "is set!"); - dict_load_sys_table(dict_sys->sys_tables); - dict_load_sys_table(dict_sys->sys_columns); - dict_load_sys_table(dict_sys->sys_indexes); - dict_load_sys_table(dict_sys->sys_fields); - } + err = DB_ERROR; + } else { + /* Load definitions of other indexes on system tables */ - mutex_exit(&(dict_sys->mutex)); + dict_load_sys_table(dict_sys->sys_tables); + dict_load_sys_table(dict_sys->sys_columns); + dict_load_sys_table(dict_sys->sys_indexes); + dict_load_sys_table(dict_sys->sys_fields); + } + + mutex_exit(&(dict_sys->mutex)); + } return(err); } diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 2b728353d99..c51deb0a048 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -1116,7 +1116,7 @@ dict_init(void) &dict_operation_lock, SYNC_DICT_OPERATION); if (!srv_read_only_mode) { - dict_foreign_err_file = os_file_create_tmpfile(); + dict_foreign_err_file = os_file_create_tmpfile(NULL); ut_a(dict_foreign_err_file); mutex_create(dict_foreign_err_mutex_key, diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 12ead09d829..5c283f693d5 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2009, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2009, 2015, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1488,7 +1488,6 @@ on the leaf page. when comparing records @param[out] n_diff number of distinct records @param[out] n_external_pages number of external pages -@param[in,out] mtr mini-transaction @return number of distinct records on the leaf page */ static void @@ -1496,8 +1495,7 @@ dict_stats_analyze_index_below_cur( const btr_cur_t* cur, ulint n_prefix, ib_uint64_t* n_diff, - ib_uint64_t* n_external_pages, - mtr_t* mtr) + ib_uint64_t* n_external_pages) { dict_index_t* index; ulint space; @@ -1511,6 +1509,7 @@ dict_stats_analyze_index_below_cur( ulint* offsets2; ulint* offsets_rec; ulint size; + mtr_t mtr; index = btr_cur_get_index(cur); @@ -1549,12 +1548,14 @@ dict_stats_analyze_index_below_cur( function without analyzing any leaf pages */ *n_external_pages = 0; + mtr_start(&mtr); + /* descend to the leaf level on the B-tree */ for (;;) { block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL /* no guessed block */, - BUF_GET, __FILE__, __LINE__, mtr); + BUF_GET, __FILE__, __LINE__, &mtr); page = buf_block_get_frame(block); @@ -1576,6 +1577,8 @@ dict_stats_analyze_index_below_cur( ut_a(*n_diff > 0); if (*n_diff == 1) { + mtr_commit(&mtr); + /* page has all keys equal and the end of the page was reached by dict_stats_scan_page(), no need to descend to the leaf level */ @@ -1600,7 +1603,7 @@ dict_stats_analyze_index_below_cur( } /* make sure we got a leaf page as a result from the above loop */ - ut_ad(btr_page_get_level(page, mtr) == 0); + ut_ad(btr_page_get_level(page, &mtr) == 0); /* scan the leaf page and find the number of distinct keys, when looking only at the first n_prefix columns; also estimate @@ -1617,6 +1620,7 @@ dict_stats_analyze_index_below_cur( __func__, page_no, n_diff); #endif + mtr_commit(&mtr); mem_heap_free(heap); } @@ -1826,8 +1830,7 @@ dict_stats_analyze_index_for_n_prefix( dict_stats_analyze_index_below_cur(btr_pcur_get_btr_cur(&pcur), n_prefix, &n_diff_on_leaf_page, - &n_external_pages, - mtr); + &n_external_pages); /* We adjust n_diff_on_leaf_page here to avoid counting one record twice - once as the last on some page and once diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 100f304bf6f..ceffa950739 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -1,6 +1,6 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (C) 2014, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -662,7 +662,7 @@ fil_space_encrypt( return src_frame; } - ut_ad(crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF); + ut_a(crypt_data != NULL && crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF); byte* tmp = fil_encrypt_buf(crypt_data, space, offset, lsn, src_frame, zip_size, dst_frame); @@ -712,21 +712,37 @@ fil_space_decrypt( ulint page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE); uint key_version = mach_read_from_4(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); bool page_compressed = (page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED); - + ulint offset = mach_read_from_4(src_frame + FIL_PAGE_OFFSET); + ulint space = mach_read_from_4(src_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); + ib_uint64_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN); *err = DB_SUCCESS; if (key_version == ENCRYPTION_KEY_NOT_ENCRYPTED) { return false; } - ut_ad(crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF); + if (crypt_data == NULL) { + if (!(space == 0 && offset == 0) && key_version != 0) { + /* FIL_PAGE_FILE_FLUSH_LSN field i.e. + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + should be only defined for the + first page in a system tablespace + data file (ibdata*, not *.ibd), if not + clear it. */ +#ifdef UNIV_DEBUG + ib_logf(IB_LOG_LEVEL_WARN, + "Page on space %lu offset %lu has key_version %u" + " when it shoud be undefined.", + space, offset, key_version); +#endif + mach_write_to_4(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0); + } + return false; + } - /* read space & offset & lsn */ - ulint space = mach_read_from_4( - src_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - ulint offset = mach_read_from_4( - src_frame + FIL_PAGE_OFFSET); - ib_uint64_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN); + ut_a(crypt_data != NULL && crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF); + + /* read space & lsn */ ulint header_len = FIL_PAGE_DATA; if (page_compressed) { @@ -799,6 +815,7 @@ fil_space_decrypt( byte* src_frame) /*!< in/out: page buffer */ { dberr_t err = DB_SUCCESS; + byte* res = NULL; bool encrypted = fil_space_decrypt( fil_space_get_crypt_data(space), @@ -807,13 +824,17 @@ fil_space_decrypt( src_frame, &err); - if (encrypted) { - /* Copy the decrypted page back to page buffer, not - really any other options. */ - memcpy(src_frame, tmp_frame, page_size); + if (err == DB_SUCCESS) { + if (encrypted) { + /* Copy the decrypted page back to page buffer, not + really any other options. */ + memcpy(src_frame, tmp_frame, page_size); + } + + res = src_frame; } - return src_frame; + return res; } /****************************************************************** @@ -2294,6 +2315,10 @@ fil_crypt_set_thread_cnt( /*=====================*/ uint new_cnt) /*!< in: New key rotation thread count */ { + if (!fil_crypt_threads_inited) { + fil_crypt_threads_init(); + } + if (new_cnt > srv_n_fil_crypt_threads) { uint add = new_cnt - srv_n_fil_crypt_threads; srv_n_fil_crypt_threads = new_cnt; @@ -2358,15 +2383,18 @@ void fil_crypt_threads_init() /*====================*/ { - fil_crypt_event = os_event_create(); - fil_crypt_threads_event = os_event_create(); - mutex_create(fil_crypt_threads_mutex_key, - &fil_crypt_threads_mutex, SYNC_NO_ORDER_CHECK); - - uint cnt = srv_n_fil_crypt_threads; - srv_n_fil_crypt_threads = 0; - fil_crypt_set_thread_cnt(cnt); - fil_crypt_threads_inited = true; + ut_ad(mutex_own(&fil_system->mutex)); + if (!fil_crypt_threads_inited) { + fil_crypt_event = os_event_create(); + fil_crypt_threads_event = os_event_create(); + mutex_create(fil_crypt_threads_mutex_key, + &fil_crypt_threads_mutex, SYNC_NO_ORDER_CHECK); + + uint cnt = srv_n_fil_crypt_threads; + srv_n_fil_crypt_threads = 0; + fil_crypt_threads_inited = true; + fil_crypt_set_thread_cnt(cnt); + } } /********************************************************************* @@ -2389,6 +2417,7 @@ fil_crypt_threads_cleanup() { os_event_free(fil_crypt_event); os_event_free(fil_crypt_threads_event); + fil_crypt_threads_inited = false; } /********************************************************************* @@ -2493,6 +2522,7 @@ fil_space_crypt_get_status( mutex_enter(&crypt_data->mutex); status->keyserver_requests = crypt_data->keyserver_requests; status->min_key_version = crypt_data->min_key_version; + status->key_id = crypt_data->key_id; if (crypt_data->rotate_state.active_threads > 0 || crypt_data->rotate_state.flushing) { diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 928c72cf546..d918b21d779 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2015, Oracle and/or its affiliates. -Copyright (c) 2013, 2015, MariaDB Corporation. +Copyright (c) 2013, 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -3207,10 +3207,12 @@ fil_create_link_file( } link_filepath = fil_make_isl_name(tablename); - + /* Note that OS_FILE_READ_WRITE_CACHED used here to avoid + unnecessary errors on O_DIRECT, link files are not really + a data files. */ file = os_file_create_simple_no_error_handling( innodb_file_data_key, link_filepath, - OS_FILE_CREATE, OS_FILE_READ_WRITE, &success, 0); + OS_FILE_CREATE, OS_FILE_READ_WRITE_CACHED, &success, 0); if (!success) { /* The following call will print an error message */ diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index cc4a4f9f1a8..ee06f9432b8 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -6274,7 +6274,7 @@ fts_fake_hex_to_dec( #ifdef _WIN32 ret = sscanf(tmp_id, "%016llu", &dec_id); #else - ret = sscanf(tmp_id, "%016"PRIu64, &dec_id); + ret = sscanf(tmp_id, "%016" PRIu64, &dec_id); #endif /* _WIN32 */ ut_ad(ret == 1); diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index e096b8bf6d6..00b3b4682c3 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -580,7 +580,7 @@ fts_zip_read_word( #ifdef UNIV_DEBUG ulint i; #endif - byte len = 0; + short len = 0; void* null = NULL; byte* ptr = word->f_str; int flush = Z_NO_FLUSH; @@ -590,7 +590,7 @@ fts_zip_read_word( return(NULL); } - zip->zp->next_out = &len; + zip->zp->next_out = reinterpret_cast<byte*>(&len); zip->zp->avail_out = sizeof(len); while (zip->status == Z_OK && zip->zp->avail_out > 0) { @@ -598,7 +598,7 @@ fts_zip_read_word( /* Finished decompressing block. */ if (zip->zp->avail_in == 0) { - /* Free the block thats been decompressed. */ + /* Free the block that's been decompressed. */ if (zip->pos > 0) { ulint prev = zip->pos - 1; @@ -688,11 +688,12 @@ fts_fetch_index_words( fts_zip_t* zip = static_cast<fts_zip_t*>(user_arg); que_node_t* exp = sel_node->select_list; dfield_t* dfield = que_node_get_val(exp); - byte len = (byte) dfield_get_len(dfield); + short len = static_cast<short>(dfield_get_len(dfield)); void* data = dfield_get_data(dfield); /* Skip the duplicate words. */ - if (zip->word.f_len == len && !memcmp(zip->word.f_str, data, len)) { + if (zip->word.f_len == static_cast<ulint>(len) + && !memcmp(zip->word.f_str, data, len)) { return(TRUE); } @@ -706,7 +707,7 @@ fts_fetch_index_words( ut_a(zip->zp->next_in == NULL); /* The string is prefixed by len. */ - zip->zp->next_in = &len; + zip->zp->next_in = reinterpret_cast<byte*>(&len); zip->zp->avail_in = sizeof(len); /* Compress the word, create output blocks as necessary. */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 3c8287a7be4..5edb6dc5190 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. +Copyright (c) 2013, 2016, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -33,6 +33,8 @@ this program; if not, write to the Free Software Foundation, Inc., *****************************************************************************/ +#define lower_case_file_system lower_case_file_system_server +#define mysql_unpacked_real_data_home mysql_unpacked_real_data_home_server #include <sql_table.h> // explain_filename, nz2, EXPLAIN_PARTITIONS_AS_COMMENT, // EXPLAIN_FILENAME_MAX_EXTRA_LENGTH @@ -44,6 +46,11 @@ this program; if not, write to the Free Software Foundation, Inc., #include <table_cache.h> #include <my_check_opt.h> +#undef lower_case_file_system +#undef mysql_unpacked_real_data_home +MYSQL_PLUGIN_IMPORT extern my_bool lower_case_file_system; +MYSQL_PLUGIN_IMPORT extern char mysql_unpacked_real_data_home[]; + #ifdef _WIN32 #include <io.h> #endif @@ -553,6 +560,67 @@ ib_cb_t innodb_api_cb[] = { (ib_cb_t) ib_trx_read_only }; +/** + Test a file path whether it is same as mysql data directory path. + + @param path null terminated character string + + @return + @retval TRUE The path is different from mysql data directory. + @retval FALSE The path is same as mysql data directory. +*/ +static bool is_mysql_datadir_path(const char *path) +{ + if (path == NULL) + return false; + + char mysql_data_dir[FN_REFLEN], path_dir[FN_REFLEN]; + convert_dirname(path_dir, path, NullS); + convert_dirname(mysql_data_dir, mysql_unpacked_real_data_home, NullS); + size_t mysql_data_home_len= dirname_length(mysql_data_dir); + size_t path_len = dirname_length(path_dir); + + if (path_len < mysql_data_home_len) + return true; + + if (!lower_case_file_system) + return(memcmp(mysql_data_dir, path_dir, mysql_data_home_len)); + + return(files_charset_info->coll->strnncoll(files_charset_info, + (uchar *) path_dir, path_len, + (uchar *) mysql_data_dir, + mysql_data_home_len, + TRUE)); + +} + + +static int mysql_tmpfile_path(const char *path, const char *prefix) +{ + DBUG_ASSERT(path != NULL); + DBUG_ASSERT((strlen(path) + strlen(prefix)) <= FN_REFLEN); + + char filename[FN_REFLEN]; + File fd = create_temp_file(filename, path, prefix, +#ifdef __WIN__ + O_BINARY | O_TRUNC | O_SEQUENTIAL | + O_SHORT_LIVED | +#endif /* __WIN__ */ + O_CREAT | O_EXCL | O_RDWR | O_TEMPORARY, + MYF(MY_WME)); + if (fd >= 0) { +#ifndef __WIN__ + /* + This can be removed once the following bug is fixed: + Bug #28903 create_temp_file() doesn't honor O_TEMPORARY option + (file not removed) (Unix) + */ + unlink(filename); +#endif /* !__WIN__ */ + } + + return fd; +} static void innodb_remember_check_sysvar_funcs(); mysql_var_check_func check_sysvar_enum; @@ -588,7 +656,6 @@ ha_create_table_option innodb_table_option_list[]= HA_TOPTION_END }; - /*************************************************************//** Check whether valid argument given to innodb_ft_*_stopword_table. This function is registered as a callback with MySQL. @@ -604,6 +671,108 @@ innodb_stopword_table_validate( for update function */ struct st_mysql_value* value); /*!< in: incoming string */ +/** Validate passed-in "value" is a valid directory name. +This function is registered as a callback with MySQL. +@param[in,out] thd thread handle +@param[in] var pointer to system variable +@param[out] save immediate result for update +@param[in] value incoming string +@return 0 for valid name */ +static +int +innodb_tmpdir_validate( + THD* thd, + struct st_mysql_sys_var* var, + void* save, + struct st_mysql_value* value) +{ + + char* alter_tmp_dir; + char* innodb_tmp_dir; + char buff[OS_FILE_MAX_PATH]; + int len = sizeof(buff); + char tmp_abs_path[FN_REFLEN + 2]; + + ut_ad(save != NULL); + ut_ad(value != NULL); + + if (check_global_access(thd, FILE_ACL)) { + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: FILE Permissions required"); + *static_cast<const char**>(save) = NULL; + return(1); + } + + alter_tmp_dir = (char*) value->val_str(value, buff, &len); + + if (!alter_tmp_dir) { + *static_cast<const char**>(save) = alter_tmp_dir; + return(0); + } + + if (strlen(alter_tmp_dir) > FN_REFLEN) { + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "Path length should not exceed %d bytes", FN_REFLEN); + *static_cast<const char**>(save) = NULL; + return(1); + } + + my_realpath(tmp_abs_path, alter_tmp_dir, 0); + size_t tmp_abs_len = strlen(tmp_abs_path); + + if (my_access(tmp_abs_path, F_OK)) { + + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: Path doesn't exist."); + *static_cast<const char**>(save) = NULL; + return(1); + } else if (my_access(tmp_abs_path, R_OK | W_OK)) { + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: Server doesn't have permission in " + "the given location."); + *static_cast<const char**>(save) = NULL; + return(1); + } + + MY_STAT stat_info_dir; + + if (my_stat(tmp_abs_path, &stat_info_dir, MYF(0))) { + if ((stat_info_dir.st_mode & S_IFDIR) != S_IFDIR) { + + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "Given path is not a directory. "); + *static_cast<const char**>(save) = NULL; + return(1); + } + } + + if (!is_mysql_datadir_path(tmp_abs_path)) { + + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "InnoDB: Path Location should not be same as " + "mysql data directory location."); + *static_cast<const char**>(save) = NULL; + return(1); + } + + innodb_tmp_dir = static_cast<char*>( + thd_memdup(thd, tmp_abs_path, tmp_abs_len + 1)); + *static_cast<const char**>(save) = innodb_tmp_dir; + return(0); +} + /** "GEN_CLUST_INDEX" is the name reserved for InnoDB default system clustered index when there is no primary key. */ const char innobase_index_reserve_name[] = "GEN_CLUST_INDEX"; @@ -617,16 +786,6 @@ innobase_map_isolation_level( /*=========================*/ enum_tx_isolation iso); /*!< in: MySQL isolation level code */ -/******************************************************************//** -Maps a MySQL trx isolation level code to the InnoDB isolation level code -@return InnoDB isolation level */ -static inline -ulint -innobase_map_isolation_level( -/*=========================*/ - enum_tx_isolation iso); /*!< in: MySQL isolation level code - */ - /*************************************************************//** Check for a valid value of innobase_compression_algorithm. @return 0 for valid innodb_compression_algorithm. */ @@ -688,6 +847,11 @@ static MYSQL_THDVAR_STR(ft_user_stopword_table, "User supplied stopword table name, effective in the session level.", innodb_stopword_table_validate, NULL, NULL); +static MYSQL_THDVAR_STR(tmpdir, + PLUGIN_VAR_OPCMDARG|PLUGIN_VAR_MEMALLOC, + "Directory for temporary non-tablespace files.", + innodb_tmpdir_validate, NULL, NULL); + static SHOW_VAR innodb_status_variables[]= { {"buffer_pool_dump_status", (char*) &export_vars.innodb_buffer_pool_dump_status, SHOW_CHAR}, @@ -763,12 +927,6 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG}, {"os_log_written", (char*) &export_vars.innodb_os_log_written, SHOW_LONGLONG}, - {"os_merge_buffers_written", - (char*) &export_vars.innodb_merge_buffers_written, SHOW_LONGLONG}, - {"os_merge_buffers_read", - (char*) &export_vars.innodb_merge_buffers_read, SHOW_LONGLONG}, - {"os_merge_buffers_merged", - (char*) &export_vars.innodb_merge_buffers_merged, SHOW_LONGLONG}, {"page_size", (char*) &export_vars.innodb_page_size, SHOW_LONG}, {"pages_created", @@ -1273,7 +1431,6 @@ Normalizes a table name string. A normalized name consists of the database name catenated to '/' and table name. An example: test/mytable. On Windows normalization puts both the database name and the table name always to lower case if "set_lower_case" is set to TRUE. */ -static void normalize_table_name_low( /*=====================*/ @@ -1543,6 +1700,26 @@ thd_supports_xa( return(THDVAR(thd, support_xa)); } +/** Get the value of innodb_tmpdir. +@param[in] thd thread handle, or NULL to query + the global innodb_tmpdir. +@retval NULL if innodb_tmpdir="" */ +UNIV_INTERN +const char* +thd_innodb_tmpdir( + THD* thd) +{ +#ifdef UNIV_SYNC_DEBUG + ut_ad(!sync_thread_levels_nonempty_trx(false)); +#endif /* UNIV_SYNC_DEBUG */ + + const char* tmp_dir = THDVAR(thd, tmpdir); + if (tmp_dir != NULL && *tmp_dir == '\0') { + tmp_dir = NULL; + } + + return(tmp_dir); +} /******************************************************************//** Returns the lock wait timeout for the current connection. @return the lock wait timeout, in seconds */ @@ -2082,13 +2259,14 @@ innobase_get_lower_case_table_names(void) return(lower_case_table_names); } -/*********************************************************************//** -Creates a temporary file. +/** Create a temporary file in the location specified by the parameter +path. If the path is null, then it will be created in tmpdir. +@param[in] path location for creating temporary file @return temporary file descriptor, or < 0 on error */ UNIV_INTERN int -innobase_mysql_tmpfile(void) -/*========================*/ +innobase_mysql_tmpfile( + const char* path) { #ifdef WITH_INNODB_DISALLOW_WRITES os_event_wait(srv_allow_writes_event); @@ -2101,7 +2279,11 @@ innobase_mysql_tmpfile(void) return(-1); ); - fd = mysql_tmpfile("ib"); + if (path == NULL) { + fd = mysql_tmpfile("ib"); + } else { + fd = mysql_tmpfile_path(path, "ib"); + } if (fd >= 0) { /* Copy the file descriptor, so that the additional resources @@ -3030,6 +3212,13 @@ ha_innobase::reset_template(void) ut_ad(prebuilt->magic_n == ROW_PREBUILT_ALLOCATED); ut_ad(prebuilt->magic_n2 == prebuilt->magic_n); + /* Force table to be freed in close_thread_table(). */ + DBUG_EXECUTE_IF("free_table_in_fts_query", + if (prebuilt->in_fts_query) { + table->m_needs_reopen = true; + } + ); + prebuilt->keep_other_fields_on_keyread = 0; prebuilt->read_just_key = 0; prebuilt->in_fts_query = 0; @@ -4866,7 +5055,6 @@ Normalizes a table name string. A normalized name consists of the database name catenated to '/' and table name. Example: test/mytable. On Windows normalization puts both the database name and the table name always to lower case if "set_lower_case" is set to TRUE. */ -static void normalize_table_name_low( /*=====================*/ @@ -8105,7 +8293,7 @@ report_error: wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && wsrep_on(user_thd) && !wsrep_consistency_check(user_thd) && - !wsrep_thd_skip_append_keys(user_thd)) + !wsrep_thd_ignore_table(user_thd)) { if (wsrep_append_keys(user_thd, false, record, NULL)) { @@ -8627,7 +8815,7 @@ func_exit: if (error == DB_SUCCESS && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && wsrep_on(user_thd) && - !wsrep_thd_skip_append_keys(user_thd)) + !wsrep_thd_ignore_table(user_thd)) { DBUG_PRINT("wsrep", ("update row key")); @@ -8693,7 +8881,7 @@ ha_innobase::delete_row( if (error == DB_SUCCESS && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && wsrep_on(user_thd) && - !wsrep_thd_skip_append_keys(user_thd)) + !wsrep_thd_ignore_table(user_thd)) { if (wsrep_append_keys(user_thd, false, record, NULL)) { DBUG_PRINT("wsrep", ("delete fail")); @@ -17707,15 +17895,12 @@ innobase_fts_close_ranking( { fts_result_t* result; - ((NEW_FT_INFO*) fts_hdl)->ft_prebuilt->in_fts_query = false; - result = ((NEW_FT_INFO*) fts_hdl)->ft_result; fts_query_free_result(result); my_free((uchar*) fts_hdl); - return; } @@ -18144,6 +18329,15 @@ wsrep_innobase_kill_one_trx( (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); wsrep_thd_LOCK(thd); + DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock", + { + const char act[]= + "now " + "wait_for signal.wsrep_after_BF_victim_lock"; + DBUG_ASSERT(!debug_sync_set_action(bf_thd, + STRING_WITH_LEN(act))); + };); + if (wsrep_thd_query_state(thd) == QUERY_EXITING) { WSREP_DEBUG("kill trx EXITING for %lu", victim_trx->id); @@ -19680,6 +19874,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(sync_array_size), MYSQL_SYSVAR(compression_failure_threshold_pct), MYSQL_SYSVAR(compression_pad_pct_max), + MYSQL_SYSVAR(simulate_comp_failures), #ifdef UNIV_DEBUG MYSQL_SYSVAR(trx_rseg_n_slots_debug), MYSQL_SYSVAR(limit_optimistic_insert_debug), @@ -19687,7 +19882,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(fil_make_page_dirty_debug), MYSQL_SYSVAR(saved_page_number_debug), #endif /* UNIV_DEBUG */ - MYSQL_SYSVAR(simulate_comp_failures), + MYSQL_SYSVAR(tmpdir), MYSQL_SYSVAR(force_primary_key), MYSQL_SYSVAR(fatal_semaphore_wait_threshold), /* Table page compression feature */ @@ -19732,7 +19927,7 @@ maria_declare_plugin(innobase) innodb_status_variables_export,/* status variables */ innobase_system_variables, /* system variables */ INNODB_VERSION_STR, /* string version */ - MariaDB_PLUGIN_MATURITY_BETA /* maturity */ + MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */ }, i_s_innodb_trx, i_s_innodb_locks, diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 0087b220d2f..332c5f319fa 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -201,12 +201,14 @@ innobase_fulltext_exist( /*******************************************************************//** Determine if ALTER TABLE needs to rebuild the table. @param ha_alter_info the DDL operation +@param altered_table MySQL original table @return whether it is necessary to rebuild the table */ static __attribute__((nonnull, warn_unused_result)) bool innobase_need_rebuild( /*==================*/ - const Alter_inplace_info* ha_alter_info) + const Alter_inplace_info* ha_alter_info, + const TABLE* altered_table) { if (ha_alter_info->handler_flags == Alter_inplace_info::CHANGE_CREATE_OPTION @@ -218,6 +220,34 @@ innobase_need_rebuild( return(false); } + /* If alter table changes column name and adds a new + index, we need to check is this new index created + to new column name. This is because column name + changes are done normally after creating indexes. */ + if ((ha_alter_info->handler_flags + & Alter_inplace_info::ALTER_COLUMN_NAME) && + ((ha_alter_info->handler_flags + & Alter_inplace_info::ADD_INDEX) || + (ha_alter_info->handler_flags + & Alter_inplace_info::ADD_FOREIGN_KEY))) { + for (ulint i = 0; i < ha_alter_info->key_count; i++) { + const KEY* key = &ha_alter_info->key_info_buffer[ + ha_alter_info->index_add_buffer[i]]; + + for (ulint j = 0; j < key->user_defined_key_parts; j++) { + const KEY_PART_INFO* key_part = &(key->key_part[j]); + const Field* field = altered_table->field[key_part->fieldnr]; + + /* Field used on added index is renamed on + this same alter table. We need table + rebuild. */ + if (field->flags & FIELD_IS_RENAMED) { + return (true); + } + } + } + } + return(!!(ha_alter_info->handler_flags & INNOBASE_ALTER_REBUILD)); } @@ -555,7 +585,7 @@ ha_innobase::check_if_supported_inplace_alter( operation is possible. */ } else if (((ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX) - || innobase_need_rebuild(ha_alter_info)) + || innobase_need_rebuild(ha_alter_info, table)) && (innobase_fulltext_exist(altered_table))) { /* Refuse to rebuild the table online, if fulltext indexes are to survive the rebuild. */ @@ -1558,7 +1588,8 @@ innobase_create_index_def( index_def_t* index, /*!< out: index definition */ mem_heap_t* heap, /*!< in: heap where memory is allocated */ - const Field** fields) /*!z in: MySQL table fields */ + const Field** fields) /*!< in: MySQL table fields + */ { const KEY* key = &keys[key_number]; ulint i; @@ -1853,9 +1884,11 @@ innobase_create_key_defs( bool& add_fts_doc_id, /*!< in: whether we need to add new DOC ID column for FTS index */ - bool& add_fts_doc_idx) + bool& add_fts_doc_idx, /*!< in: whether we need to add new DOC ID index for FTS index */ + const TABLE* table) + /*!< in: MySQL table that is being altered */ { index_def_t* indexdef; index_def_t* indexdefs; @@ -1905,7 +1938,8 @@ innobase_create_key_defs( } const bool rebuild = new_primary || add_fts_doc_id - || innobase_need_rebuild(ha_alter_info); + || innobase_need_rebuild(ha_alter_info, table); + /* Reserve one more space if new_primary is true, and we might need to add the FTS_DOC_ID_INDEX */ indexdef = indexdefs = static_cast<index_def_t*>( @@ -2738,11 +2772,16 @@ prepare_inplace_alter_table_dict( ctx->num_to_add_index = ha_alter_info->index_add_count; + ut_ad(ctx->prebuilt->trx->mysql_thd != NULL); + const char* path = thd_innodb_tmpdir( + ctx->prebuilt->trx->mysql_thd); + index_defs = innobase_create_key_defs( ctx->heap, ha_alter_info, altered_table, ctx->num_to_add_index, num_fts_index, row_table_got_default_clust_index(ctx->new_table), - fts_doc_id_col, add_fts_doc_id, add_fts_doc_id_idx); + fts_doc_id_col, add_fts_doc_id, add_fts_doc_id_idx, + old_table); new_clustered = DICT_CLUSTERED & index_defs[0].ind_type; @@ -2755,7 +2794,7 @@ prepare_inplace_alter_table_dict( /* This is not an online operation (LOCK=NONE). */ } else if (ctx->add_autoinc == ULINT_UNDEFINED && num_fts_index == 0 - && (!innobase_need_rebuild(ha_alter_info) + && (!innobase_need_rebuild(ha_alter_info, old_table) || !innobase_fulltext_exist(altered_table))) { /* InnoDB can perform an online operation (LOCK=NONE). */ } else { @@ -2772,7 +2811,7 @@ prepare_inplace_alter_table_dict( is just copied from old table and stored in indexdefs[0] */ DBUG_ASSERT(!add_fts_doc_id || new_clustered); DBUG_ASSERT(!!new_clustered == - (innobase_need_rebuild(ha_alter_info) + (innobase_need_rebuild(ha_alter_info, old_table) || add_fts_doc_id)); /* Allocate memory for dictionary index definitions */ @@ -3032,7 +3071,7 @@ prepare_inplace_alter_table_dict( add_cols, ctx->heap); ctx->add_cols = add_cols; } else { - DBUG_ASSERT(!innobase_need_rebuild(ha_alter_info)); + DBUG_ASSERT(!innobase_need_rebuild(ha_alter_info, old_table)); if (!ctx->new_table->fts && innobase_fulltext_exist(altered_table)) { @@ -3053,7 +3092,7 @@ prepare_inplace_alter_table_dict( ctx->add_index[a] = row_merge_create_index( ctx->trx, ctx->new_table, - &index_defs[a]); + &index_defs[a], ctx->col_names); add_key_nums[a] = index_defs[a].key_number; @@ -3090,8 +3129,10 @@ prepare_inplace_alter_table_dict( error = DB_OUT_OF_MEMORY; goto error_handling;); rw_lock_x_lock(&ctx->add_index[a]->lock); + bool ok = row_log_allocate(ctx->add_index[a], - NULL, true, NULL, NULL); + NULL, true, NULL, + NULL, path); rw_lock_x_unlock(&ctx->add_index[a]->lock); if (!ok) { @@ -3117,7 +3158,7 @@ prepare_inplace_alter_table_dict( clust_index, ctx->new_table, !(ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX), - ctx->add_cols, ctx->col_map); + ctx->add_cols, ctx->col_map, path); rw_lock_x_unlock(&clust_index->lock); if (!ok) { @@ -3914,7 +3955,7 @@ err_exit: if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA) || (ha_alter_info->handler_flags == Alter_inplace_info::CHANGE_CREATE_OPTION - && !innobase_need_rebuild(ha_alter_info))) { + && !innobase_need_rebuild(ha_alter_info, table))) { if (heap) { ha_alter_info->handler_ctx @@ -4088,7 +4129,7 @@ ok_exit: if (ha_alter_info->handler_flags == Alter_inplace_info::CHANGE_CREATE_OPTION - && !innobase_need_rebuild(ha_alter_info)) { + && !innobase_need_rebuild(ha_alter_info, table)) { goto ok_exit; } @@ -4110,6 +4151,7 @@ ok_exit: files and merge sort. */ DBUG_EXECUTE_IF("innodb_OOM_inplace_alter", error = DB_OUT_OF_MEMORY; goto oom;); + error = row_merge_build_indexes( prebuilt->trx, prebuilt->table, ctx->new_table, @@ -4800,9 +4842,11 @@ commit_get_autoinc( Field* autoinc_field = old_table->found_next_number_field; + KEY* autoinc_key = + old_table->key_info + old_table->s->next_number_index; - dict_index_t* index = dict_table_get_index_on_first_col( - ctx->old_table, autoinc_field->field_index); + dict_index_t* index = dict_table_get_index_on_name( + ctx->old_table, autoinc_key->name); max_autoinc = ha_alter_info->create_info->auto_increment_value; diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index ef69e7df29d..0bb10f435af 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2015, Oracle and/or its affiliates. -Copyrigth (c) 2014, 2015, MariaDB Corporation +Copyrigth (c) 2014, 2016, MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -783,7 +783,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_trx = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */ @@ -1043,7 +1043,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_locks = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */ @@ -1226,7 +1226,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /*******************************************************************//** @@ -1562,7 +1562,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset = @@ -1612,7 +1612,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic tables @@ -1912,7 +1912,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_per_index = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_per_index_reset = @@ -1962,7 +1962,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_per_index_reset = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table information_schema.innodb_cmpmem. */ @@ -2205,7 +2205,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset = @@ -2255,7 +2255,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_metrics */ @@ -2779,7 +2779,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_metrics = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_ft_default_stopword */ static ST_FIELD_INFO i_s_stopword_fields_info[] = @@ -2892,7 +2892,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_ft_default_stopword = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_DELETED @@ -3060,7 +3060,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_ft_deleted = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /*******************************************************************//** @@ -3143,7 +3143,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_ft_being_deleted = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHED and @@ -3432,7 +3432,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_ft_index_cache = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /*******************************************************************//** @@ -3867,7 +3867,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_ft_index_table = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG */ @@ -4065,7 +4065,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_ft_config = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */ @@ -4614,7 +4614,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_stats = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */ @@ -5326,7 +5326,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_page = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = @@ -5873,7 +5873,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_page_lru = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /*******************************************************************//** @@ -6167,7 +6167,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tables = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /** SYS_TABLESTATS ***********************************************/ @@ -6457,7 +6457,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tablestats = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /** SYS_INDEXES **************************************************/ @@ -6709,7 +6709,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_indexes = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /** SYS_COLUMNS **************************************************/ @@ -6946,7 +6946,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_columns = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /** SYS_FIELDS ***************************************************/ @@ -7156,7 +7156,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_fields = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /** SYS_FOREIGN ********************************************/ @@ -7381,7 +7381,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_foreign = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /** SYS_FOREIGN_COLS ********************************************/ @@ -7598,7 +7598,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_foreign_cols = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /** SYS_TABLESPACES ********************************************/ @@ -7866,7 +7866,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tablespaces = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /** SYS_DATAFILES ************************************************/ @@ -8055,7 +8055,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_datafiles = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /** TABLESPACES_ENCRYPTION ********************************************/ @@ -8134,6 +8134,15 @@ static ST_FIELD_INFO innodb_tablespaces_encryption_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, +#define TABLESPACES_ENCRYPTION_CURRENT_KEY_ID 8 + {STRUCT_FLD(field_name, "CURRENT_KEY_ID"), + STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + END_OF_ST_FIELD_INFO }; @@ -8172,6 +8181,8 @@ i_s_dict_fill_tablespaces_encryption( status.min_key_version)); OK(fields[TABLESPACES_ENCRYPTION_CURRENT_KEY_VERSION]->store( status.current_key_version)); + OK(fields[TABLESPACES_ENCRYPTION_CURRENT_KEY_ID]->store( + status.key_id)); if (status.rotating) { fields[TABLESPACES_ENCRYPTION_KEY_ROTATION_PAGE_NUMBER]->set_notnull(); OK(fields[TABLESPACES_ENCRYPTION_KEY_ROTATION_PAGE_NUMBER]->store( @@ -8338,7 +8349,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_encryption = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA) + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA) }; /** TABLESPACES_SCRUBBING ********************************************/ @@ -8637,7 +8648,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_scrubbing = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA) + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA) }; /** INNODB_MUTEXES *********************************************/ @@ -8851,7 +8862,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_mutexes = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /** SYS_SEMAPHORE_WAITS ************************************************/ @@ -9128,5 +9139,5 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_semaphore_waits = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index c1e5051dc6f..9e8d8659739 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -383,12 +384,18 @@ ibuf_header_page_get( buf_block_t* block; ut_ad(!ibuf_inside(mtr)); + page_t* page = NULL; block = buf_page_get( IBUF_SPACE_ID, 0, FSP_IBUF_HEADER_PAGE_NO, RW_X_LATCH, mtr); - buf_block_dbg_add_level(block, SYNC_IBUF_HEADER); - return(buf_block_get_frame(block)); + if (!block->page.encrypted) { + buf_block_dbg_add_level(block, SYNC_IBUF_HEADER); + + page = buf_block_get_frame(block); + } + + return page; } /******************************************************************//** @@ -500,9 +507,10 @@ ibuf_size_update( /******************************************************************//** Creates the insert buffer data structure at a database startup and initializes -the data structures for the insert buffer. */ +the data structures for the insert buffer. +@return DB_SUCCESS or failure */ UNIV_INTERN -void +dberr_t ibuf_init_at_db_start(void) /*=======================*/ { @@ -513,7 +521,7 @@ ibuf_init_at_db_start(void) dict_index_t* index; ulint n_used; page_t* header_page; - dberr_t error; + dberr_t error= DB_SUCCESS; ibuf = static_cast<ibuf_t*>(mem_zalloc(sizeof(ibuf_t))); @@ -543,6 +551,10 @@ ibuf_init_at_db_start(void) header_page = ibuf_header_page_get(&mtr); + if (!header_page) { + return (DB_DECRYPTION_FAILED); + } + fseg_n_reserved_pages(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, &n_used, &mtr); ibuf_enter(&mtr); @@ -593,6 +605,7 @@ ibuf_init_at_db_start(void) ut_a(error == DB_SUCCESS); ibuf->index = dict_table_get_first_index(table); + return (error); } /*********************************************************************//** diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h index cf2e022c006..fdc413e7520 100644 --- a/storage/innobase/include/fil0crypt.h +++ b/storage/innobase/include/fil0crypt.h @@ -1,6 +1,6 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (c) 2015, MariaDB Corporation. +Copyright (c) 2015, 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -212,6 +212,7 @@ bool fil_space_check_encryption_read( /*============================*/ ulint space); /*!< in: tablespace id */ + /****************************************************************** Decrypt a page @return true if page is decrypted, false if not. */ @@ -226,7 +227,6 @@ fil_space_decrypt( dberr_t* err); /*!< in: out: DB_SUCCESS or error code */ - /********************************************************************* Encrypt buffer page @return encrypted page, or original not encrypted page if encrypt @@ -253,7 +253,8 @@ fil_space_decrypt( ulint space, /*!< in: tablespace id */ byte* src_frame, /*!< in: page frame */ ulint page_size, /*!< in: size of data to encrypt */ - byte* dst_frame); /*!< in: where to decrypt to */ + byte* dst_frame) /*!< in: where to decrypt to */ + __attribute__((warn_unused_result)); /********************************************************************* fil_space_verify_crypt_checksum @@ -332,6 +333,7 @@ struct fil_space_crypt_status_t { uint min_key_version; /*!< min key version */ uint current_key_version;/*!< current key version */ uint keyserver_requests;/*!< no of key requests to key server */ + ulint key_id; /*!< current key_id */ bool rotating; /*!< is key rotation ongoing */ bool flushing; /*!< is flush at end of rotation ongoing */ ulint rotate_next_page_number; /*!< next page if key rotating */ diff --git a/storage/innobase/include/fil0fil.ic b/storage/innobase/include/fil0fil.ic index a0bfb271d39..5654d8f6178 100644 --- a/storage/innobase/include/fil0fil.ic +++ b/storage/innobase/include/fil0fil.ic @@ -146,9 +146,9 @@ fil_page_type_validate( /* Dump out the page info */ fprintf(stderr, "InnoDB: Space %lu offset %lu name %s page_type %lu page_type_name %s\n" - "InnoDB: key_version %u page_compressed %d page_compressed_encrypted %d lsn %lu compressed_len %lu\n", + "InnoDB: key_version %u page_compressed %d page_compressed_encrypted %d lsn %llu compressed_len %lu\n", space, offset, rspace->name, page_type, fil_get_page_type_name(page_type), - key_version, page_compressed, page_compressed_encrypted, lsn, compressed_len); + key_version, page_compressed, page_compressed_encrypted, (ulonglong)lsn, compressed_len); fflush(stderr); ut_ad(page_type == FIL_PAGE_PAGE_COMPRESSED || diff --git a/storage/innobase/include/fts0priv.ic b/storage/innobase/include/fts0priv.ic index 2d07c60f980..ec61691870b 100644 --- a/storage/innobase/include/fts0priv.ic +++ b/storage/innobase/include/fts0priv.ic @@ -53,7 +53,7 @@ fts_write_object_id( /* Use this to construct old(5.6.14 and 5.7.3) windows ambiguous aux table names */ DBUG_EXECUTE_IF("innodb_test_wrong_windows_fts_aux_table_name", - return(sprintf(str, "%016"PRIu64, id));); + return(sprintf(str, "%016" PRIu64, id));); DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", return(sprintf(str, UINT64PFx, id));); @@ -66,7 +66,7 @@ fts_write_object_id( // FIXME: Use ut_snprintf(), so does following one. return(sprintf(str, "%016llu", id)); #else /* _WIN32 */ - return(sprintf(str, "%016"PRIu64, id)); + return(sprintf(str, "%016" PRIu64, id)); #endif /* _WIN32 */ } diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 59abb0863d9..427bfaf2c05 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2006, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2006, 2015, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -351,6 +351,15 @@ thd_supports_xa( THD* thd); /*!< in: thread handle, or NULL to query the global innodb_supports_xa */ +/** Get status of innodb_tmpdir. +@param[in] thd thread handle, or NULL to query + the global innodb_tmpdir. +@retval NULL if innodb_tmpdir="" */ +UNIV_INTERN +const char* +thd_innodb_tmpdir( + THD* thd); + /******************************************************************//** Returns the lock wait timeout for the current connection. @return the lock wait timeout, in seconds */ @@ -634,6 +643,7 @@ ib_push_warning( ulint error, /*!< in: error code to push as warning */ const char *format,/*!< in: warning message */ ...); + /********************************************************************//** Helper function to push warnings from InnoDB internals to SQL-layer. */ UNIV_INTERN @@ -643,4 +653,19 @@ ib_push_warning( ulint error, /*!< in: error code to push as warning */ const char *format,/*!< in: warning message */ ...); + +/*****************************************************************//** +Normalizes a table name string. A normalized name consists of the +database name catenated to '/' and table name. An example: +test/mytable. On Windows normalization puts both the database name and the +table name always to lower case if "set_lower_case" is set to TRUE. */ +void +normalize_table_name_low( +/*=====================*/ + char* norm_name, /*!< out: normalized name as a + null-terminated string */ + const char* name, /*!< in: table name string */ + ibool set_lower_case); /*!< in: TRUE if we want to set + name to lower case */ + #endif /* HA_INNODB_PROTOTYPES_H */ diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h index 9c3b686c998..badafe6befd 100644 --- a/storage/innobase/include/ibuf0ibuf.h +++ b/storage/innobase/include/ibuf0ibuf.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -91,9 +92,10 @@ separately committed mini-transaction, because in crash recovery, the free bits could momentarily be set too high. */ /******************************************************************//** -Creates the insert buffer data structure at a database startup. */ +Creates the insert buffer data structure at a database startup. +@return DB_SUCCESS or failure */ UNIV_INTERN -void +dberr_t ibuf_init_at_db_start(void); /*=======================*/ /*********************************************************************//** diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index e4a06fcc532..292953854f7 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -498,6 +498,18 @@ use these free frames to read in pages when we start applying the log records to the database. */ extern ulint recv_n_pool_free_frames; +/******************************************************//** +Checks the 4-byte checksum to the trailer checksum field of a log +block. We also accept a log block in the old format before +InnoDB-3.23.52 where the checksum field contains the log block number. +@return TRUE if ok, or if the log block may be in the format of InnoDB +version predating 3.23.52 */ +ibool +log_block_checksum_is_ok_or_old_format( +/*===================================*/ + const byte* block, /*!< in: pointer to a log block */ + bool print_err); /*!< in print error ? */ + #ifndef UNIV_NONINL #include "log0recv.ic" #endif diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index c630e91e815..dff5ebd524c 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -128,7 +128,10 @@ enum os_file_create_t { #define OS_FILE_READ_ONLY 333 #define OS_FILE_READ_WRITE 444 #define OS_FILE_READ_ALLOW_DELETE 555 /* for mysqlbackup */ - +#define OS_FILE_READ_WRITE_CACHED 666 /* OS_FILE_READ_WRITE but never + O_DIRECT. Only for + os_file_create_simple_no_error_handling + currently. */ /* Options for file_create */ #define OS_FILE_AIO 61 #define OS_FILE_NORMAL 62 @@ -435,14 +438,19 @@ UNIV_INTERN void os_io_init_simple(void); /*===================*/ -/***********************************************************************//** -Creates a temporary file. This function is like tmpfile(3), but -the temporary file is created in the MySQL temporary directory. -@return temporary file handle, or NULL on error */ + +/** Create a temporary file. This function is like tmpfile(3), but +the temporary file is created in the given parameter path. If the path +is null then it will create the file in the mysql server configuration +parameter (--tmpdir). +@param[in] path location for creating temporary file +@return temporary file handle, or NULL on error */ +UNIV_INTERN FILE* -os_file_create_tmpfile(void); -/*========================*/ +os_file_create_tmpfile( + const char* path); + #endif /* !UNIV_HOTBACKUP */ /***********************************************************************//** The os_file_opendir() function opens a directory stream corresponding to the @@ -537,7 +545,7 @@ UNIV_INTERN void os_file_set_nocache( /*================*/ - int fd, /*!< in: file descriptor to alter */ + os_file_t fd, /*!< in: file descriptor to alter */ const char* file_name, /*!< in: file name, used in the diagnostic message */ const char* operation_name);/*!< in: "open" or "create"; used in the @@ -1271,14 +1279,14 @@ os_file_get_status( file can be opened in RW mode */ #if !defined(UNIV_HOTBACKUP) -/*********************************************************************//** -Creates a temporary file that will be deleted on close. -This function is defined in ha_innodb.cc. -@return temporary file descriptor, or < 0 on error */ +/** Create a temporary file in the location specified by the parameter +path. If the path is null, then it will be created in tmpdir. +@param[in] path location for creating temporary file +@return temporary file descriptor, or < 0 on error */ UNIV_INTERN int -innobase_mysql_tmpfile(void); -/*========================*/ +innobase_mysql_tmpfile( + const char* path); #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/include/row0log.h b/storage/innobase/include/row0log.h index f105838eece..e127504c484 100644 --- a/storage/innobase/include/row0log.h +++ b/storage/innobase/include/row0log.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -55,8 +55,9 @@ row_log_allocate( const dtuple_t* add_cols, /*!< in: default values of added columns, or NULL */ - const ulint* col_map)/*!< in: mapping of old column + const ulint* col_map,/*!< in: mapping of old column numbers to new ones, or NULL if !table */ + const char* path) /*!< in: where to create temporary file */ __attribute__((nonnull(1), warn_unused_result)); /******************************************************//** diff --git a/storage/innobase/include/row0merge.h b/storage/innobase/include/row0merge.h index 196543f25e1..53164b5197f 100644 --- a/storage/innobase/include/row0merge.h +++ b/storage/innobase/include/row0merge.h @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, MariaDB Corporation. +Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2015, 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -187,14 +187,14 @@ void row_merge_drop_temp_indexes(void); /*=============================*/ -/*********************************************************************//** -Creates temporary merge files, and if UNIV_PFS_IO defined, register -the file descriptor with Performance Schema. +/** Create temporary merge files in the given paramater path, and if +UNIV_PFS_IO defined, register the file descriptor with Performance Schema. +@param[in] path location for creating temporary merge files. @return File descriptor */ UNIV_INTERN int -row_merge_file_create_low(void) -/*===========================*/ +row_merge_file_create_low( + const char* path) __attribute__((warn_unused_result)); /*********************************************************************//** Destroy a merge file. And de-register the file from Performance Schema @@ -268,8 +268,11 @@ row_merge_create_index( /*===================*/ trx_t* trx, /*!< in/out: trx (sets error_state) */ dict_table_t* table, /*!< in: the index is on this table */ - const index_def_t* index_def); + const index_def_t* index_def, /*!< in: the index definition */ + const char** col_names); + /*! in: column names if columns are + renamed or NULL */ /*********************************************************************//** Check if a transaction can use an index. @return TRUE if index can be used by the transaction else FALSE */ @@ -369,15 +372,17 @@ row_merge_buf_empty( /*================*/ row_merge_buf_t* buf) /*!< in,own: sort buffer */ __attribute__((warn_unused_result, nonnull)); -/*********************************************************************//** -Create a merge file. + +/** Create a merge file in the given location. +@param[out] merge_file merge file structure +@param[in] path location for creating temporary file @return file descriptor, or -1 on failure */ UNIV_INTERN int row_merge_file_create( -/*==================*/ - merge_file_t* merge_file) /*!< out: merge file structure */ - __attribute__((nonnull)); + merge_file_t* merge_file, + const char* path); + /*********************************************************************//** Merge disk files. @return DB_SUCCESS or error code */ diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h index 8673a51b10f..422cfc3eaf6 100644 --- a/storage/innobase/include/srv0mon.h +++ b/storage/innobase/include/srv0mon.h @@ -2,7 +2,7 @@ Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. +Copyright (c) 2013, 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -263,9 +263,6 @@ enum monitor_id_t { MONITOR_OVLD_OS_LOG_FSYNC, MONITOR_OVLD_OS_LOG_PENDING_FSYNC, MONITOR_OVLD_OS_LOG_PENDING_WRITES, - MONITOR_MERGE_BLOCKS_WRITTEN, - MONITOR_MERGE_BLOCKS_READ, - MONITOR_MERGE_BLOCKS_MERGED, /* Transaction related counters */ MONITOR_MODULE_TRX, diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index d8e7d484a18..9a6107f4330 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -3,7 +3,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. +Copyright (c) 2013, 2016, MariaDB Corporation Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -174,15 +174,6 @@ struct srv_stats_t { /** Number of system rows inserted */ ulint_ctr_64_t n_system_rows_inserted; - /** Number of merge buffers written */ - ulint_ctr_64_t merge_buffers_written; - - /** Number of merge buffers read */ - ulint_ctr_64_t merge_buffers_read; - - /** Number of merge buffers merged */ - ulint_ctr_64_t merge_buffers_merged; - /** Number of times secondary index lookup triggered cluster lookup */ ulint_ctr_64_t n_sec_rec_cluster_reads; @@ -1001,9 +992,6 @@ struct export_var_t{ ulint innodb_purge_view_trx_id_age; /*!< rw_max_trx_id - purged view's min trx_id */ #endif /* UNIV_DEBUG */ - ib_int64_t innodb_merge_buffers_written; - ib_int64_t innodb_merge_buffers_read; - ib_int64_t innodb_merge_buffers_merged; ib_int64_t innodb_page_compression_saved;/*!< Number of bytes saved by page compression */ diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index a957b2cc98f..c2451fa8c21 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -45,7 +45,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MINOR 6 -#define INNODB_VERSION_BUGFIX 27 +#define INNODB_VERSION_BUGFIX 29 /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 184b1a375ce..165db2d33ed 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -638,7 +638,7 @@ lock_sys_create( lock_sys->rec_hash = hash_create(n_cells); if (!srv_read_only_mode) { - lock_latest_err_file = os_file_create_tmpfile(); + lock_latest_err_file = os_file_create_tmpfile(NULL); ut_a(lock_latest_err_file); } } diff --git a/storage/innobase/lock/lock0wait.cc b/storage/innobase/lock/lock0wait.cc index 4f4a0eb223b..a87adcf94c0 100644 --- a/storage/innobase/lock/lock0wait.cc +++ b/storage/innobase/lock/lock0wait.cc @@ -33,6 +33,8 @@ Created 25/5/2010 Sunny Bains #include "ha_prototypes.h" #include "lock0priv.h" +#include <mysql/service_wsrep.h> + /*********************************************************************//** Print the contents of the lock_sys_t::waiting_threads array. */ static @@ -184,6 +186,28 @@ lock_wait_table_reserve_slot( return(NULL); } +#ifdef WITH_WSREP +/*********************************************************************//** +check if lock timeout was for priority thread, +as a side effect trigger lock monitor +@return false for regular lock timeout */ +static ibool +wsrep_is_BF_lock_timeout( +/*====================*/ + trx_t* trx) /* in: trx to check for lock priority */ +{ + if (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + fprintf(stderr, "WSREP: BF lock wait long\n"); + srv_print_innodb_monitor = TRUE; + srv_print_innodb_lock_monitor = TRUE; + os_event_set(srv_monitor_event); + return TRUE; + } + return FALSE; + } +#endif /* WITH_WSREP */ + /***************************************************************//** Puts a user OS thread to wait for a lock to be released. If an error occurs during the wait trx->error_state associated with thr is @@ -371,9 +395,17 @@ lock_wait_suspend_thread( if (lock_wait_timeout < 100000000 && wait_time > (double) lock_wait_timeout) { +#ifdef WITH_WSREP + if (!wsrep_on(trx->mysql_thd) || + (!wsrep_is_BF_lock_timeout(trx) && + trx->error_state != DB_DEADLOCK)) { +#endif /* WITH_WSREP */ trx->error_state = DB_LOCK_WAIT_TIMEOUT; +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ MONITOR_INC(MONITOR_TIMEOUT); } @@ -457,8 +489,13 @@ lock_wait_check_and_cancel( if (trx->lock.wait_lock) { ut_a(trx->lock.que_state == TRX_QUE_LOCK_WAIT); - +#ifdef WITH_WSREP + if (!wsrep_is_BF_lock_timeout(trx)) { +#endif /* WITH_WSREP */ lock_cancel_waiting_and_release(trx->lock.wait_lock); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ } lock_mutex_exit(); diff --git a/storage/innobase/log/log0crypt.cc b/storage/innobase/log/log0crypt.cc index e90533c2e76..852148899e9 100644 --- a/storage/innobase/log/log0crypt.cc +++ b/storage/innobase/log/log0crypt.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (C) 2014, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -36,6 +36,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com #include "my_crypt.h" +/* Used for debugging */ +// #define DEBUG_CRYPT 1 #define UNENCRYPTED_KEY_VER 0 /* If true, enable redo log encryption. */ @@ -97,16 +99,24 @@ get_crypt_info( { /* so that no one is modifying array while we search */ ut_ad(mutex_own(&(log_sys->mutex))); + size_t items = crypt_info.size(); /* a log block only stores 4-bytes of checkpoint no */ checkpoint_no &= 0xFFFFFFFF; - for (size_t i = 0; i < crypt_info.size(); i++) { + for (size_t i = 0; i < items; i++) { struct crypt_info_t* it = &crypt_info[i]; if (it->checkpoint_no == checkpoint_no) { return it; } } + + /* If checkpoint contains more than one key and we did not + find the correct one use the first one. */ + if (items) { + return (&crypt_info[0]); + } + return NULL; } @@ -131,7 +141,8 @@ log_blocks_crypt( const byte* block, /*!< in: blocks before encrypt/decrypt*/ ulint size, /*!< in: size of block */ byte* dst_block, /*!< out: blocks after encrypt/decrypt */ - int what) /*!< in: encrypt or decrypt*/ + int what, /*!< in: encrypt or decrypt*/ + const crypt_info_t* crypt_info) /*!< in: crypt info or NULL */ { byte *log_block = (byte*)block; Crypt_result rc = MY_AES_OK; @@ -146,7 +157,8 @@ log_blocks_crypt( lsn_t log_block_start_lsn = log_block_get_start_lsn( lsn, log_block_no); - const crypt_info_t* info = get_crypt_info(log_block); + const crypt_info_t* info = crypt_info == NULL ? get_crypt_info(log_block) : + crypt_info; #ifdef DEBUG_CRYPT fprintf(stderr, "%s %lu chkpt: %lu key: %u lsn: %lu\n", @@ -156,12 +168,21 @@ log_blocks_crypt( info ? info->key_version : 0, log_block_start_lsn); #endif + /* If no key is found from checkpoint assume the log_block + to be unencrypted. If checkpoint contains the encryption key + compare log_block current checksum, if checksum matches, + block can't be encrypted. */ if (info == NULL || - info->key_version == UNENCRYPTED_KEY_VER) { + info->key_version == UNENCRYPTED_KEY_VER || + (log_block_checksum_is_ok_or_old_format(log_block, false) && + what == ENCRYPTION_FLAG_DECRYPT)) { memcpy(dst_block, log_block, OS_FILE_LOG_BLOCK_SIZE); goto next; } + ut_ad(what == ENCRYPTION_FLAG_DECRYPT ? !log_block_checksum_is_ok_or_old_format(log_block, false) : + log_block_checksum_is_ok_or_old_format(log_block, false)); + // Assume log block header is not encrypted memcpy(dst_block, log_block, LOG_BLOCK_HDR_SIZE); @@ -292,7 +313,7 @@ log_blocks_encrypt( const ulint size, /*!< in: size of blocks, must be multiple of a log block */ byte* dst_block) /*!< out: blocks after encryption */ { - return log_blocks_crypt(block, size, dst_block, ENCRYPTION_FLAG_ENCRYPT); + return log_blocks_crypt(block, size, dst_block, ENCRYPTION_FLAG_ENCRYPT, NULL); } /*********************************************************************//** @@ -355,14 +376,16 @@ log_encrypt_before_write( return; } - if (info->key_version == UNENCRYPTED_KEY_VER) { + /* If the key is not encrypted or user has requested not to + encrypt, do not change log block. */ + if (info->key_version == UNENCRYPTED_KEY_VER || !srv_encrypt_log) { return; } byte* dst_frame = (byte*)malloc(size); //encrypt log blocks content - Crypt_result result = log_blocks_crypt(block, size, dst_frame, ENCRYPTION_FLAG_ENCRYPT); + Crypt_result result = log_blocks_crypt(block, size, dst_frame, ENCRYPTION_FLAG_ENCRYPT, NULL); if (result == MY_AES_OK) { ut_ad(block[0] == dst_frame[0]); @@ -388,7 +411,7 @@ log_decrypt_after_read( byte* dst_frame = (byte*)malloc(size); // decrypt log blocks content - Crypt_result result = log_blocks_crypt(frame, size, dst_frame, ENCRYPTION_FLAG_DECRYPT); + Crypt_result result = log_blocks_crypt(frame, size, dst_frame, ENCRYPTION_FLAG_DECRYPT, NULL); if (result == MY_AES_OK) { memcpy(frame, dst_frame, size); diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index fd3646a1691..31104b395c1 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. -Copyright (c) 2013, SkySQL Ab. All Rights Reserved. +Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -52,6 +52,9 @@ Created 12/9/1995 Heikki Tuuri #include "trx0roll.h" #include "srv0mon.h" +/* Used for debugging */ +// #define DEBUG_CRYPT 1 + /* General philosophy of InnoDB redo-logs: @@ -2358,8 +2361,24 @@ loop: (ulint) (source_offset % UNIV_PAGE_SIZE), len, buf, NULL, 0); +#ifdef DEBUG_CRYPT + fprintf(stderr, "BEFORE DECRYPT: block: %lu checkpoint: %lu %.8lx %.8lx offset %lu\n", + log_block_get_hdr_no(buf), + log_block_get_checkpoint_no(buf), + log_block_calc_checksum(buf), + log_block_get_checksum(buf), source_offset); +#endif + log_decrypt_after_read(buf, len); +#ifdef DEBUG_CRYPT + fprintf(stderr, "AFTER DECRYPT: block: %lu checkpoint: %lu %.8lx %.8lx\n", + log_block_get_hdr_no(buf), + log_block_get_checkpoint_no(buf), + log_block_calc_checksum(buf), + log_block_get_checksum(buf)); +#endif + start_lsn += len; buf += len; diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index c84e8277f07..2304f4885c2 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2,7 +2,7 @@ Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -923,11 +923,11 @@ block. We also accept a log block in the old format before InnoDB-3.23.52 where the checksum field contains the log block number. @return TRUE if ok, or if the log block may be in the format of InnoDB version predating 3.23.52 */ -static ibool log_block_checksum_is_ok_or_old_format( /*===================================*/ - const byte* block) /*!< in: pointer to a log block */ + const byte* block, /*!< in: pointer to a log block */ + bool print_err) /*!< in print error ? */ { #ifdef UNIV_LOG_DEBUG return(TRUE); @@ -950,11 +950,13 @@ log_block_checksum_is_ok_or_old_format( return(TRUE); } - fprintf(stderr, "BROKEN: block: %lu checkpoint: %lu %.8lx %.8lx\n", - log_block_get_hdr_no(block), - log_block_get_checkpoint_no(block), - log_block_calc_checksum(block), - log_block_get_checksum(block)); + if (print_err) { + fprintf(stderr, "BROKEN: block: %lu checkpoint: %lu %.8lx %.8lx\n", + log_block_get_hdr_no(block), + log_block_get_checkpoint_no(block), + log_block_calc_checksum(block), + log_block_get_checksum(block)); + } return(FALSE); } @@ -2664,6 +2666,7 @@ recv_scan_log_recs( ibool finished; ulint data_len; ibool more_data; + bool maybe_encrypted=false; ut_ad(start_lsn % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0); @@ -2678,6 +2681,8 @@ recv_scan_log_recs( *err = DB_SUCCESS; do { + log_crypt_err_t log_crypt_err; + no = log_block_get_hdr_no(log_block); /* fprintf(stderr, "Log block header no %lu\n", no); @@ -2686,12 +2691,11 @@ recv_scan_log_recs( log_block_convert_lsn_to_no(scanned_lsn)); */ if (no != log_block_convert_lsn_to_no(scanned_lsn) - || !log_block_checksum_is_ok_or_old_format(log_block)) { - log_crypt_err_t log_crypt_err; + || !log_block_checksum_is_ok_or_old_format(log_block, true)) { if (no == log_block_convert_lsn_to_no(scanned_lsn) && !log_block_checksum_is_ok_or_old_format( - log_block)) { + log_block, true)) { fprintf(stderr, "InnoDB: Log block no %lu at" " lsn " LSN_PF " has\n" @@ -2705,12 +2709,14 @@ recv_scan_log_recs( log_block)); } + maybe_encrypted = log_crypt_block_maybe_encrypted(log_block, + &log_crypt_err); + /* Garbage or an incompletely written log block */ finished = TRUE; - if (log_crypt_block_maybe_encrypted(log_block, - &log_crypt_err)) { + if (maybe_encrypted) { /* Log block maybe encrypted finish processing*/ log_crypt_print_error(log_crypt_err); *err = DB_ERROR; diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 2b9e877e765..3a0bd1fc328 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. +Copyright (c) 2013, 2016, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are @@ -918,19 +918,20 @@ os_io_init_simple(void) } } -/***********************************************************************//** -Creates a temporary file. This function is like tmpfile(3), but -the temporary file is created in the MySQL temporary directory. -@return temporary file handle, or NULL on error */ +/** Create a temporary file. This function is like tmpfile(3), but +the temporary file is created in the given parameter path. If the path +is null then it will create the file in the mysql server configuration +parameter (--tmpdir). +@param[in] path location for creating temporary file +@return temporary file handle, or NULL on error */ UNIV_INTERN FILE* -os_file_create_tmpfile(void) -/*========================*/ +os_file_create_tmpfile( + const char* path) { FILE* file = NULL; - int fd; WAIT_ALLOW_WRITES(); - fd = innobase_mysql_tmpfile(); + int fd = innobase_mysql_tmpfile(path); ut_ad(!srv_read_only_mode); @@ -1349,7 +1350,8 @@ os_file_create_simple_func( access = GENERIC_READ; - } else if (access_type == OS_FILE_READ_WRITE) { + } else if (access_type == OS_FILE_READ_WRITE + || access_type == OS_FILE_READ_WRITE_CACHED) { access = GENERIC_READ | GENERIC_WRITE; } else { ib_logf(IB_LOG_LEVEL_ERROR, @@ -1453,7 +1455,8 @@ os_file_create_simple_func( #ifdef USE_FILE_LOCK if (!srv_read_only_mode && *success - && access_type == OS_FILE_READ_WRITE + && (access_type == OS_FILE_READ_WRITE + || access_type == OS_FILE_READ_WRITE_CACHED) && os_file_lock(file, name)) { *success = FALSE; @@ -1467,6 +1470,31 @@ os_file_create_simple_func( return(file); } +/** Disable OS I/O caching on the file if the file type and server +configuration requires it. +@param file handle to the file +@param name name of the file, for diagnostics +@param mode_str operation on the file, for diagnostics +@param type OS_LOG_FILE or OS_DATA_FILE +@param access_type if OS_FILE_READ_WRITE_CACHED, then caching will be disabled +unconditionally, ignored otherwise */ +static +void +os_file_set_nocache_if_needed(os_file_t file, const char* name, + const char *mode_str, ulint type, + ulint access_type) +{ + if (srv_read_only_mode || access_type == OS_FILE_READ_WRITE_CACHED) { + return; + } + + if (type == OS_DATA_FILE + && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT + || (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC))) { + os_file_set_nocache(file, name, mode_str); + } +} + /****************************************************************//** NOTE! Use the corresponding macro os_file_create_simple_no_error_handling(), not directly this function! @@ -1522,7 +1550,8 @@ os_file_create_simple_no_error_handling_func( access = GENERIC_READ; } else if (srv_read_only_mode) { access = GENERIC_READ; - } else if (access_type == OS_FILE_READ_WRITE) { + } else if (access_type == OS_FILE_READ_WRITE + || access_type == OS_FILE_READ_WRITE_CACHED) { access = GENERIC_READ | GENERIC_WRITE; } else if (access_type == OS_FILE_READ_ALLOW_DELETE) { @@ -1594,7 +1623,8 @@ os_file_create_simple_no_error_handling_func( } else { ut_a(access_type == OS_FILE_READ_WRITE - || access_type == OS_FILE_READ_ALLOW_DELETE); + || access_type == OS_FILE_READ_ALLOW_DELETE + || access_type == OS_FILE_READ_WRITE_CACHED); create_flag = O_RDWR; } @@ -1626,18 +1656,16 @@ os_file_create_simple_no_error_handling_func( /* This function is always called for data files, we should disable OS caching (O_DIRECT) here as we do in os_file_create_func(), so we open the same file in the same mode, see man page of open(2). */ - if (!srv_read_only_mode - && *success - && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT - || srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) { - - os_file_set_nocache(file, name, mode_str); + if (*success) { + os_file_set_nocache_if_needed(file, name, mode_str, + OS_DATA_FILE, access_type); } #ifdef USE_FILE_LOCK if (!srv_read_only_mode && *success - && access_type == OS_FILE_READ_WRITE + && (access_type == OS_FILE_READ_WRITE + || access_type == OS_FILE_READ_WRITE_CACHED) && os_file_lock(file, name)) { *success = FALSE; @@ -1676,7 +1704,7 @@ UNIV_INTERN void os_file_set_nocache( /*================*/ - int fd /*!< in: file descriptor to alter */ + os_file_t fd /*!< in: file descriptor to alter */ __attribute__((unused)), const char* file_name /*!< in: used in the diagnostic message */ @@ -2006,13 +2034,8 @@ os_file_create_func( /* We disable OS caching (O_DIRECT) only on data files */ - if (!srv_read_only_mode - && *success - && type != OS_LOG_FILE - && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT - || srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) { - - os_file_set_nocache(file, name, mode_str); + if (*success) { + os_file_set_nocache_if_needed(file, name, mode_str, type, 0); } #ifdef USE_FILE_LOCK @@ -2925,7 +2948,7 @@ try_again: "Error in system call pread(). The operating" " system error number is %lu.",(ulint) errno); } else { - /* Partial read occured */ + /* Partial read occurred */ ib_logf(IB_LOG_LEVEL_ERROR, "Tried to read " ULINTPF " bytes at offset " UINT64PF ". Was only able to read %ld.", @@ -3056,7 +3079,7 @@ try_again: "Error in system call pread(). The operating" " system error number is %lu.",(ulint) errno); } else { - /* Partial read occured */ + /* Partial read occurred */ ib_logf(IB_LOG_LEVEL_ERROR, "Tried to read " ULINTPF " bytes at offset " UINT64PF ". Was only able to read %ld.", @@ -3910,7 +3933,7 @@ os_aio_native_aio_supported(void) return(FALSE); } else if (!srv_read_only_mode) { /* Now check if tmpdir supports native aio ops. */ - fd = innobase_mysql_tmpfile(); + fd = innobase_mysql_tmpfile(NULL); if (fd < 0) { ib_logf(IB_LOG_LEVEL_WARN, diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 4c021973b9a..9e340f24213 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, MariaDB Corporation. +Copyright (c) 2010, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2015, 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -237,6 +237,9 @@ row_fts_psort_info_init( crypt_data = NULL; } + ut_ad(trx->mysql_thd != NULL); + const char* path = thd_innodb_tmpdir(trx->mysql_thd); + /* There will be FTS_NUM_AUX_INDEX number of "sort buckets" for each parallel sort thread. Each "sort bucket" holds records for a particular "FTS index partition" */ @@ -258,8 +261,8 @@ row_fts_psort_info_init( psort_info[j].merge_buf[i] = row_merge_buf_create( dup->index); - if (row_merge_file_create(psort_info[j].merge_file[i]) - < 0) { + if (row_merge_file_create(psort_info[j].merge_file[i], + path) < 0) { goto func_exit; } @@ -659,6 +662,11 @@ fts_parallel_tokenization( dberr_t error = DB_SUCCESS; fil_space_crypt_t* crypt_data = NULL; + ut_ad(psort_info->psort_common->trx->mysql_thd != NULL); + + const char* path = thd_innodb_tmpdir( + psort_info->psort_common->trx->mysql_thd); + ut_ad(psort_info); buf = psort_info->merge_buf; @@ -902,7 +910,7 @@ exit: continue; } - tmpfd[i] = row_merge_file_create_low(); + tmpfd[i] = row_merge_file_create_low(path); if (tmpfd[i] < 0) { error = DB_OUT_OF_MEMORY; goto func_exit; diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 16de943f901..bddc81d9fb3 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -198,8 +198,25 @@ struct row_log_t { or by index->lock X-latch only */ row_log_buf_t head; /*!< reader context; protected by MDL only; modifiable by row_log_apply_ops() */ + const char* path; /*!< where to create temporary file during + log operation */ }; +/** Create the file or online log if it does not exist. +@param[in,out] log online rebuild log +@return file descriptor. */ +static __attribute__((warn_unused_result)) +int +row_log_tmpfile( + row_log_t* log) +{ + DBUG_ENTER("row_log_tmpfile"); + if (log->fd < 0) { + log->fd = row_merge_file_create_low(log->path); + } + + DBUG_RETURN(log->fd); +} /** Allocate the memory for the log buffer. @param[in,out] log_buf Buffer used for log operation @@ -344,6 +361,12 @@ row_log_online_op( log->tail.buf, avail_size); } UNIV_MEM_ASSERT_RW(log->tail.block, srv_sort_buf_size); + + if (row_log_tmpfile(log) < 0) { + log->error = DB_OUT_OF_MEMORY; + goto err_exit; + } + ret = os_file_write( "(modification log)", OS_FILE_FROM_FD(log->fd), @@ -454,6 +477,12 @@ row_log_table_close_func( log->tail.buf, avail); } UNIV_MEM_ASSERT_RW(log->tail.block, srv_sort_buf_size); + + if (row_log_tmpfile(log) < 0) { + log->error = DB_OUT_OF_MEMORY; + goto err_exit; + } + ret = os_file_write( "(modification log)", OS_FILE_FROM_FD(log->fd), @@ -473,6 +502,7 @@ write_failed: log->tail.total += size; UNIV_MEM_INVALID(log->tail.buf, sizeof log->tail.buf); +err_exit: mutex_exit(&log->mutex); os_atomic_increment_ulint(&onlineddl_rowlog_rows, 1); @@ -2544,7 +2574,8 @@ corruption: if (index->online_log->head.blocks) { #ifdef HAVE_FTRUNCATE /* Truncate the file in order to save space. */ - if (ftruncate(index->online_log->fd, 0) == -1) { + if (index->online_log->fd != -1 + && ftruncate(index->online_log->fd, 0) == -1) { fprintf(stderr, "InnoDB: Error: Truncate of file " "\'%s\' failed with error %d:%s\n", index->name + 1, errno, strerror(errno)); @@ -2863,8 +2894,9 @@ row_log_allocate( const dtuple_t* add_cols, /*!< in: default values of added columns, or NULL */ - const ulint* col_map)/*!< in: mapping of old column + const ulint* col_map,/*!< in: mapping of old column numbers to new ones, or NULL if !table */ + const char* path) /*!< in: where to create temporary file */ { row_log_t* log; DBUG_ENTER("row_log_allocate"); @@ -2883,11 +2915,7 @@ row_log_allocate( DBUG_RETURN(false); } - log->fd = row_merge_file_create_low(); - if (log->fd < 0) { - ut_free(log); - DBUG_RETURN(false); - } + log->fd = -1; mutex_create(index_online_log_key, &log->mutex, SYNC_INDEX_ONLINE_LOG); log->blobs = NULL; @@ -2902,6 +2930,7 @@ row_log_allocate( log->tail.block = log->head.block = NULL; log->head.blocks = log->head.bytes = 0; log->head.total = 0; + log->path = path; dict_index_set_online_status(index, ONLINE_INDEX_CREATION); index->online_log = log; @@ -3379,7 +3408,8 @@ corruption: if (index->online_log->head.blocks) { #ifdef HAVE_FTRUNCATE /* Truncate the file in order to save space. */ - if (ftruncate(index->online_log->fd, 0) == -1) { + if (index->online_log->fd != -1 + && ftruncate(index->online_log->fd, 0) == -1) { fprintf(stderr, "InnoDB: Error: Truncate of file " "\'%s\' failed with error %d:%s\n", index->name + 1, errno, strerror(errno)); diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 13eeaeb72fa..294facf9723 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1,7 +1,6 @@ /***************************************************************************** Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2015, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -969,7 +968,6 @@ row_merge_read( success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf, ofs, srv_sort_buf_size); - srv_stats.merge_buffers_read.inc(); /* For encrypted tables, decrypt data after reading and copy data */ if (crypt_data && crypt_buf) { @@ -1025,7 +1023,6 @@ row_merge_write( } ret = os_file_write("(merge)", OS_FILE_FROM_FD(fd), out_buf, ofs, buf_len); - srv_stats.merge_buffers_written.inc(); #ifdef UNIV_DEBUG if (row_merge_print_block_write) { @@ -1390,52 +1387,101 @@ row_merge_write_eof( return(&block[0]); } -/********************************************************************//** -Reads clustered index of the table and create temporary files +/** Create a temporary file if it has not been created already. +@param[in,out] tmpfd temporary file handle +@param[in] path path to create temporary file +@return file descriptor, or -1 on failure */ +static __attribute__((warn_unused_result)) +int +row_merge_tmpfile_if_needed( + int* tmpfd, + const char* path) +{ + if (*tmpfd < 0) { + *tmpfd = row_merge_file_create_low(path); + } + + return(*tmpfd); +} + +/** Create a temporary file for merge sort if it was not created already. +@param[in,out] file merge file structure +@param[in,out] tmpfd temporary file structure +@param[in] nrec number of records in the file +@param[in] path path to create temporary files +@return file descriptor, or -1 on failure */ +static __attribute__((warn_unused_result)) +int +row_merge_file_create_if_needed( + merge_file_t* file, + int* tmpfd, + ulint nrec, + const char* path) +{ + ut_ad(file->fd < 0 || *tmpfd >=0); + if (file->fd < 0 && row_merge_file_create(file, path) >= 0) { + if (row_merge_tmpfile_if_needed(tmpfd, path) < 0) { + return(-1); + } + + file->n_rec = nrec; + } + + ut_ad(file->fd < 0 || *tmpfd >=0); + return(file->fd); +} + +/** Reads clustered index of the table and create temporary files containing the index entries for the indexes to be built. -@return DB_SUCCESS or error */ +@param[in] trx transaction +@param[in,out] table MySQL table object, for reporting erroneous + records +@param[in] old_table table where rows are read from +@param[in] new_table table where indexes are created; identical to + old_table unless creating a PRIMARY KEY +@param[in] online true if creating indexes online +@param[in] index indexes to be created +@param[in] fts_sort_idx full-text index to be created, or NULL +@param[in] psort_info parallel sort info for fts_sort_idx creation, + or NULL +@param[in] files temporary files +@param[in] key_numbers MySQL key numbers to create +@param[in] n_index number of indexes to create +@param[in] add_cols default values of added columns, or NULL +@param[in] col_map mapping of old column numbers to new ones, or + NULL if old_table == new_table +@param[in] add_autoinc number of added AUTO_INCREMENT columns, or + ULINT_UNDEFINED if none is added +@param[in,out] sequence autoinc sequence +@param[in,out] block file buffer +@param[in,out] tmpfd temporary file handle +@param[in] pct_cost percent of task weight out of total alter job +@param[in] crypt_data crypt data or NULL +@param[in,out] crypt_block crypted file buffer +return DB_SUCCESS or error */ static __attribute__((nonnull(1,2,3,4,6,9,10,16), warn_unused_result)) dberr_t row_merge_read_clustered_index( -/*===========================*/ - trx_t* trx, /*!< in: transaction */ - struct TABLE* table, /*!< in/out: MySQL table object, - for reporting erroneous records */ - const dict_table_t* old_table,/*!< in: table where rows are - read from */ - const dict_table_t* new_table,/*!< in: table where indexes are - created; identical to old_table - unless creating a PRIMARY KEY */ - bool online, /*!< in: true if creating indexes - online */ - dict_index_t** index, /*!< in: indexes to be created */ + trx_t* trx, + struct TABLE* table, + const dict_table_t* old_table, + const dict_table_t* new_table, + bool online, + dict_index_t** index, dict_index_t* fts_sort_idx, - /*!< in: full-text index to be created, - or NULL */ fts_psort_t* psort_info, - /*!< in: parallel sort info for - fts_sort_idx creation, or NULL */ - merge_file_t* files, /*!< in: temporary files */ + merge_file_t* files, const ulint* key_numbers, - /*!< in: MySQL key numbers to create */ - ulint n_index,/*!< in: number of indexes to create */ + ulint n_index, const dtuple_t* add_cols, - /*!< in: default values of - added columns, or NULL */ - const ulint* col_map,/*!< in: mapping of old column - numbers to new ones, or NULL - if old_table == new_table */ + const ulint* col_map, ulint add_autoinc, - /*!< in: number of added - AUTO_INCREMENT column, or - ULINT_UNDEFINED if none is added */ - ib_sequence_t& sequence,/*!< in/out: autoinc sequence */ - row_merge_block_t* block, /*!< in/out: file buffer */ - float pct_cost, /*!< in: percent of task weight - out of total alter job */ - fil_space_crypt_t* crypt_data,/*!< in: crypt data or NULL */ - row_merge_block_t* crypt_block)/*!< in: in/out: crypted file - buffer */ + ib_sequence_t& sequence, + row_merge_block_t* block, + int* tmpfd, + float pct_cost, + fil_space_crypt_t* crypt_data, + row_merge_block_t* crypt_block) { dict_index_t* clust_index; /* Clustered index */ mem_heap_t* row_heap; /* Heap memory to create @@ -1478,6 +1524,9 @@ row_merge_read_clustered_index( DEBUG_FTS_SORT_PRINT("FTS_SORT: Start Create Index\n"); #endif + ut_ad(trx->mysql_thd != NULL); + const char* path = thd_innodb_tmpdir(trx->mysql_thd); + /* Create and initialize memory for record buffers */ merge_buf = static_cast<row_merge_buf_t**>( @@ -1908,7 +1957,7 @@ write_buffers: /* We have enough data tuples to form a block. Sort them and write to disk. */ - if (UNIV_LIKELY(buf->n_tuples)) { + if (buf->n_tuples) { if (dict_index_is_unique(buf->index)) { row_merge_dup_t dup = { buf->index, table, col_map, 0}; @@ -1949,8 +1998,16 @@ write_buffers: dict_index_get_lock(buf->index)); } - /* Do not write empty buffers to temporary file */ - if (buf->n_tuples) { + if (buf->n_tuples > 0) { + + if (row_merge_file_create_if_needed( + file, tmpfd, buf->n_tuples, path) < 0) { + err = DB_OUT_OF_MEMORY; + trx->error_key_num = i; + break; + } + + ut_ad(file->n_rec > 0); row_merge_buf_write(buf, file, block); @@ -2016,6 +2073,7 @@ write_buffers: func_exit: mtr_commit(&mtr); + mem_heap_free(row_heap); if (nonnull) { @@ -2277,8 +2335,6 @@ done1: b2, of->fd, &of->offset, crypt_data, crypt_block ? &crypt_block[2 * srv_sort_buf_size] : NULL, space); - srv_stats.merge_buffers_merged.inc(); - return(b2 ? DB_SUCCESS : DB_CORRUPTION); } @@ -3346,14 +3402,15 @@ row_merge_drop_temp_indexes(void) trx_free_for_background(trx); } -/*********************************************************************//** -Creates temporary merge files, and if UNIV_PFS_IO defined, register -the file descriptor with Performance Schema. -@return file descriptor, or -1 on failure */ + +/** Create temporary merge files in the given paramater path, and if +UNIV_PFS_IO defined, register the file descriptor with Performance Schema. +@param[in] path location for creating temporary merge files. +@return File descriptor */ UNIV_INTERN int -row_merge_file_create_low(void) -/*===========================*/ +row_merge_file_create_low( + const char* path) { int fd; #ifdef UNIV_PFS_IO @@ -3367,7 +3424,7 @@ row_merge_file_create_low(void) "Innodb Merge Temp File", __FILE__, __LINE__); #endif - fd = innobase_mysql_tmpfile(); + fd = innobase_mysql_tmpfile(path); #ifdef UNIV_PFS_IO register_pfs_file_open_end(locker, fd); #endif @@ -3380,22 +3437,24 @@ row_merge_file_create_low(void) return(fd); } -/*********************************************************************//** -Create a merge file. + +/** Create a merge file in the given location. +@param[out] merge_file merge file structure +@param[in] path location for creating temporary file @return file descriptor, or -1 on failure */ UNIV_INTERN int row_merge_file_create( -/*==================*/ - merge_file_t* merge_file) /*!< out: merge file structure */ + merge_file_t* merge_file, + const char* path) { - merge_file->fd = row_merge_file_create_low(); + merge_file->fd = row_merge_file_create_low(path); merge_file->offset = 0; merge_file->n_rec = 0; if (merge_file->fd >= 0) { if (srv_disable_sort_file_cache) { - os_file_set_nocache(merge_file->fd, + os_file_set_nocache((os_file_t)merge_file->fd, "row0merge.cc", "sort"); } } @@ -3739,8 +3798,11 @@ row_merge_create_index( /*===================*/ trx_t* trx, /*!< in/out: trx (sets error_state) */ dict_table_t* table, /*!< in: the index is on this table */ - const index_def_t* index_def) + const index_def_t* index_def, /*!< in: the index definition */ + const char** col_names) + /*! in: column names if columns are + renamed or NULL */ { dict_index_t* index; dberr_t err; @@ -3760,9 +3822,24 @@ row_merge_create_index( for (i = 0; i < n_fields; i++) { index_field_t* ifield = &index_def->fields[i]; - const char * col_name = ifield->col_name ? - dict_table_get_col_name_for_mysql(table, ifield->col_name) : - dict_table_get_col_name(table, ifield->col_no); + const char * col_name; + + /* + Alter table renaming a column and then adding a index + to this new name e.g ALTER TABLE t + CHANGE COLUMN b c INT NOT NULL, ADD UNIQUE INDEX (c); + requires additional check as column names are not yet + changed when new index definitions are created. Table's + new column names are on a array of column name pointers + if any of the column names are changed. */ + + if (col_names && col_names[i]) { + col_name = col_names[i]; + } else { + col_name = ifield->col_name ? + dict_table_get_col_name_for_mysql(table, ifield->col_name) : + dict_table_get_col_name(table, ifield->col_no); + } dict_mem_index_add_field( index, @@ -3942,10 +4019,6 @@ row_merge_build_indexes( total_dynamic_cost = COST_BUILD_INDEX_DYNAMIC * n_indexes; for (i = 0; i < n_indexes; i++) { - if (row_merge_file_create(&merge_files[i]) < 0) { - error = DB_OUT_OF_MEMORY; - goto func_exit; - } if (indexes[i]->type & DICT_FTS) { ibool opt_doc_id_size = FALSE; @@ -3974,13 +4047,6 @@ row_merge_build_indexes( } } - tmpfd = row_merge_file_create_low(); - - if (tmpfd < 0) { - error = DB_OUT_OF_MEMORY; - goto func_exit; - } - /* Reset the MySQL row buffer that is used when reporting duplicate keys. */ innobase_rec_reset(table); @@ -4006,11 +4072,11 @@ row_merge_build_indexes( secondary index entries for merge sort */ error = row_merge_read_clustered_index( - trx, table, old_table, new_table, online, indexes, - fts_sort_idx, psort_info, merge_files, key_numbers, - n_indexes, add_cols, col_map, - add_autoinc, sequence, block, pct_cost, - crypt_data, crypt_block); + trx, table, old_table, new_table, online, indexes, + fts_sort_idx, psort_info, merge_files, key_numbers, + n_indexes, add_cols, col_map, + add_autoinc, sequence, block, &tmpfd, + pct_cost, crypt_data, crypt_block); pct_progress += pct_cost; @@ -4103,71 +4169,67 @@ wait_again: #ifdef FTS_INTERNAL_DIAG_PRINT DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n"); #endif - } else { - /* Sorting and inserting is required only if - there really is records */ - if (UNIV_LIKELY(merge_files[i].n_rec)) { - char buf[3 * NAME_LEN]; - char *bufend; - row_merge_dup_t dup = { - sort_idx, table, col_map, 0}; + } else if (merge_files[i].fd != -1) { + char buf[3 * NAME_LEN]; + char *bufend; + row_merge_dup_t dup = { + sort_idx, table, col_map, 0}; - pct_cost = (COST_BUILD_INDEX_STATIC + - (total_dynamic_cost * merge_files[i].offset / - total_index_blocks)) / - (total_static_cost + total_dynamic_cost) - * PCT_COST_MERGESORT_INDEX * 100; + pct_cost = (COST_BUILD_INDEX_STATIC + + (total_dynamic_cost * merge_files[i].offset / + total_index_blocks)) / + (total_static_cost + total_dynamic_cost) + * PCT_COST_MERGESORT_INDEX * 100; + + bufend = innobase_convert_name(buf, sizeof buf, + indexes[i]->name, strlen(indexes[i]->name), + trx ? trx->mysql_thd : NULL, + FALSE); - bufend = innobase_convert_name(buf, sizeof buf, - indexes[i]->name, strlen(indexes[i]->name), - trx ? trx->mysql_thd : NULL, - FALSE); + buf[bufend - buf]='\0'; - buf[bufend - buf]='\0'; + sql_print_information("InnoDB: Online DDL : Start merge-sorting" + " index %s (%lu / %lu), estimated cost : %2.4f", + buf, (i+1), n_indexes, pct_cost); - sql_print_information("InnoDB: Online DDL : Start merge-sorting" - " index %s (%lu / %lu), estimated cost : %2.4f", - buf, (i+1), n_indexes, pct_cost); + error = row_merge_sort( + trx, &dup, &merge_files[i], + block, &tmpfd, true, + pct_progress, pct_cost, + crypt_data, crypt_block, new_table->space); - error = row_merge_sort( - trx, &dup, &merge_files[i], - block, &tmpfd, true, - pct_progress, pct_cost, - crypt_data, crypt_block, new_table->space); + pct_progress += pct_cost; + sql_print_information("InnoDB: Online DDL : End of " + " merge-sorting index %s (%lu / %lu)", + buf, (i+1), n_indexes); + + DBUG_EXECUTE_IF( + "ib_merge_wait_after_sort", + os_thread_sleep(20000000);); /* 20 sec */ + + if (error == DB_SUCCESS) { + pct_cost = (COST_BUILD_INDEX_STATIC + + (total_dynamic_cost * merge_files[i].offset / + total_index_blocks)) / + (total_static_cost + total_dynamic_cost) * + PCT_COST_INSERT_INDEX * 100; + + sql_print_information("InnoDB: Online DDL : Start " + "building index %s (%lu / %lu), estimated " + "cost : %2.4f", buf, (i+1), + n_indexes, pct_cost); + + error = row_merge_insert_index_tuples( + trx->id, sort_idx, old_table, + merge_files[i].fd, block, + merge_files[i].n_rec, pct_progress, pct_cost, + crypt_data, crypt_block, new_table->space); pct_progress += pct_cost; - sql_print_information("InnoDB: Online DDL : End of " - " merge-sorting index %s (%lu / %lu)", + sql_print_information("InnoDB: Online DDL : " + "End of building index %s (%lu / %lu)", buf, (i+1), n_indexes); - - DBUG_EXECUTE_IF( - "ib_merge_wait_after_sort", - os_thread_sleep(20000000);); /* 20 sec */ - - if (error == DB_SUCCESS) { - pct_cost = (COST_BUILD_INDEX_STATIC + - (total_dynamic_cost * merge_files[i].offset / - total_index_blocks)) / - (total_static_cost + total_dynamic_cost) * - PCT_COST_INSERT_INDEX * 100; - - sql_print_information("InnoDB: Online DDL : Start " - "building index %s (%lu / %lu), estimated " - "cost : %2.4f", buf, (i+1), - n_indexes, pct_cost); - - error = row_merge_insert_index_tuples( - trx->id, sort_idx, old_table, - merge_files[i].fd, block, - merge_files[i].n_rec, pct_progress, pct_cost, - crypt_data, crypt_block, new_table->space); - pct_progress += pct_cost; - - sql_print_information("InnoDB: Online DDL : " - "End of building index %s (%lu / %lu)", - buf, (i+1), n_indexes); - } } } diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index cf07362cdbf..24d25a0b2c8 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -4879,6 +4879,7 @@ row_rename_table_for_mysql( pars_info_t* info = NULL; int retry; bool aux_fts_rename = false; + char* is_part = NULL; ut_a(old_name != NULL); ut_a(new_name != NULL); @@ -4916,6 +4917,55 @@ row_rename_table_for_mysql( table = dict_table_open_on_name(old_name, dict_locked, FALSE, DICT_ERR_IGNORE_NONE); + /* We look for pattern #P# to see if the table is partitioned + MySQL table. */ +#ifdef __WIN__ + is_part = strstr((char *)old_name, (char *)"#p#"); +#else + is_part = strstr((char *)old_name, (char *)"#P#"); +#endif /* __WIN__ */ + + /* MySQL partition engine hard codes the file name + separator as "#P#". The text case is fixed even if + lower_case_table_names is set to 1 or 2. This is true + for sub-partition names as well. InnoDB always + normalises file names to lower case on Windows, this + can potentially cause problems when copying/moving + tables between platforms. + + 1) If boot against an installation from Windows + platform, then its partition table name could + be all be in lower case in system tables. So we + will need to check lower case name when load table. + + 2) If we boot an installation from other case + sensitive platform in Windows, we might need to + check the existence of table name without lowering + case them in the system table. */ + if (!table && + is_part && + innobase_get_lower_case_table_names() == 1) { + char par_case_name[MAX_FULL_NAME_LEN + 1]; +#ifndef __WIN__ + /* Check for the table using lower + case name, including the partition + separator "P" */ + memcpy(par_case_name, old_name, + strlen(old_name)); + par_case_name[strlen(old_name)] = 0; + innobase_casedn_str(par_case_name); +#else + /* On Windows platfrom, check + whether there exists table name in + system table whose name is + not being normalized to lower case */ + normalize_table_name_low( + par_case_name, old_name, FALSE); +#endif + table = dict_table_open_on_name(par_case_name, dict_locked, FALSE, + DICT_ERR_IGNORE_NONE); + } + if (!table) { err = DB_TABLE_NOT_FOUND; ut_print_timestamp(stderr); diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index 0054070eed5..1d6a4c008e8 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -2,7 +2,7 @@ Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2015, MariaDB Corporation +Copyright (c) 2013, 2016, MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -715,24 +715,6 @@ static monitor_info_t innodb_counter_info[] = MONITOR_EXISTING | MONITOR_DEFAULT_ON), MONITOR_DEFAULT_START, MONITOR_OVLD_OS_LOG_PENDING_WRITES}, - {"os_merge_blocks_written", "os", - "Number of merge blocks written (innodb_os_merge_blocks_written)", - static_cast<monitor_type_t>( - MONITOR_EXISTING | MONITOR_DEFAULT_ON), - MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_WRITTEN}, - - {"os_merge_blocks_read", "os", - "Number of merge blocks read (innodb_os_merge_blocks_read)", - static_cast<monitor_type_t>( - MONITOR_EXISTING | MONITOR_DEFAULT_ON), - MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_READ}, - - {"os_merge_blocks_merged", "os", - "Number of merge blocks merged (innodb_os_merge_blocks_merged)", - static_cast<monitor_type_t>( - MONITOR_EXISTING | MONITOR_DEFAULT_ON), - MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_MERGED}, - /* ========== Counters for Transaction Module ========== */ {"module_trx", "transaction", "Transaction Manager", MONITOR_MODULE, @@ -1790,21 +1772,6 @@ srv_mon_process_existing_counter( update_min = TRUE; break; - /* innodb_os_merge_blocks_written */ - case MONITOR_MERGE_BLOCKS_WRITTEN: - value = srv_stats.merge_buffers_written; - break; - - /* innodb_os_merge_blocks_read */ - case MONITOR_MERGE_BLOCKS_READ: - value = srv_stats.merge_buffers_read; - break; - - /* innodb_os_merge_blocks_merged */ - case MONITOR_MERGE_BLOCKS_MERGED: - value = srv_stats.merge_buffers_merged; - break; - /* innodb_log_waits */ case MONITOR_OVLD_LOG_WAITS: value = srv_stats.log_waits; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index d8e8a615c07..c28f889dfcc 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1,9 +1,9 @@ /***************************************************************************** -Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. +Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1647,10 +1647,6 @@ srv_export_innodb_status(void) } #endif /* UNIV_DEBUG */ - export_vars.innodb_merge_buffers_written = srv_stats.merge_buffers_written; - export_vars.innodb_merge_buffers_read = srv_stats.merge_buffers_read; - export_vars.innodb_merge_buffers_merged = srv_stats.merge_buffers_merged; - export_vars.innodb_sec_rec_cluster_reads = srv_stats.n_sec_rec_cluster_reads; export_vars.innodb_sec_rec_cluster_reads_avoided = @@ -1860,6 +1856,8 @@ exit_func: /*********************************************************************//** A thread which prints warnings about semaphore waits which have lasted too long. These can be used to track bugs which cause hangs. +Note: In order to make sync_arr_wake_threads_if_sema_free work as expected, +we should avoid waiting any mutexes in this function! @return a dummy parameter */ extern "C" UNIV_INTERN os_thread_ret_t @@ -1899,23 +1897,21 @@ loop: /* Try to track a strange bug reported by Harald Fuchs and others, where the lsn seems to decrease at times */ - /* We have to use nowait to ensure we don't block */ - new_lsn= log_get_lsn_nowait(); - - if (new_lsn && new_lsn < old_lsn) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: old log sequence number " LSN_PF - " was greater\n" - "InnoDB: than the new log sequence number " LSN_PF "!\n" - "InnoDB: Please submit a bug report" - " to http://bugs.mysql.com\n", - old_lsn, new_lsn); - ut_ad(0); - } + if (log_peek_lsn(&new_lsn)) { + if (new_lsn < old_lsn) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Error: old log sequence number " LSN_PF + " was greater\n" + "InnoDB: than the new log sequence number " LSN_PF "!\n" + "InnoDB: Please submit a bug report" + " to http://bugs.mysql.com\n", + old_lsn, new_lsn); + ut_ad(0); + } - if (new_lsn) old_lsn = new_lsn; + } if (difftime(time(NULL), srv_last_monitor_time) > 60) { /* We referesh InnoDB Monitor values so that averages are diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 8c54d6eb083..4a457ae6f00 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1915,7 +1915,7 @@ innobase_start_or_create_for_mysql(void) } } else { srv_monitor_file_name = NULL; - srv_monitor_file = os_file_create_tmpfile(); + srv_monitor_file = os_file_create_tmpfile(NULL); if (!srv_monitor_file) { return(DB_ERROR); @@ -1925,7 +1925,7 @@ innobase_start_or_create_for_mysql(void) mutex_create(srv_dict_tmpfile_mutex_key, &srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION); - srv_dict_tmpfile = os_file_create_tmpfile(); + srv_dict_tmpfile = os_file_create_tmpfile(NULL); if (!srv_dict_tmpfile) { return(DB_ERROR); @@ -1934,7 +1934,7 @@ innobase_start_or_create_for_mysql(void) mutex_create(srv_misc_tmpfile_mutex_key, &srv_misc_tmpfile_mutex, SYNC_ANY_LATCH); - srv_misc_tmpfile = os_file_create_tmpfile(); + srv_misc_tmpfile = os_file_create_tmpfile(NULL); if (!srv_misc_tmpfile) { return(DB_ERROR); @@ -2984,7 +2984,9 @@ files_checked: fts_optimize_init(); /* Create thread(s) that handles key rotation */ + fil_system_enter(); fil_crypt_threads_init(); + fil_system_exit(); /* Create the log scrub thread */ if (srv_scrub_log) diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc index 2e1737da3ec..7eb3d0bd6f2 100644 --- a/storage/innobase/sync/sync0sync.cc +++ b/storage/innobase/sync/sync0sync.cc @@ -422,7 +422,13 @@ mutex_validate( const ib_mutex_t* mutex) /*!< in: mutex */ { ut_a(mutex); - ut_a(mutex->magic_n == MUTEX_MAGIC_N); + + if (mutex->magic_n != MUTEX_MAGIC_N) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Mutex %p not initialized file %s line %lu.", + mutex, mutex->cfile_name, mutex->cline); + } + ut_ad(mutex->magic_n == MUTEX_MAGIC_N); return(TRUE); } diff --git a/storage/innobase/ut/crc32_power8/crc32.S b/storage/innobase/ut/crc32_power8/crc32.S index 52046bb9002..b064ce3dc96 100644 --- a/storage/innobase/ut/crc32_power8/crc32.S +++ b/storage/innobase/ut/crc32_power8/crc32.S @@ -67,14 +67,13 @@ #define off96 r30 #define off112 r31 -#define const1 v25 -#define const2 v26 +#define const1 v24 +#define const2 v25 -#define byteswap v27 -#define mask_32bit v28 -#define mask_64bit v29 -#define zeroes v30 -#define ones v31 +#define byteswap v26 +#define mask_32bit v27 +#define mask_64bit v28 +#define zeroes v29 #ifdef BYTESWAP_DATA #define VPERM(A, B, C, D) vperm A, B, C, D @@ -101,13 +100,28 @@ FUNC_START(__crc32_vpmsum) li off112,112 li r0,0 + /* Enough room for saving 10 non volatile VMX registers */ + subi r6,r1,56+10*16 + subi r7,r1,56+2*16 + + stvx v20,0,r6 + stvx v21,off16,r6 + stvx v22,off32,r6 + stvx v23,off48,r6 + stvx v24,off64,r6 + stvx v25,off80,r6 + stvx v26,off96,r6 + stvx v27,off112,r6 + stvx v28,0,r7 + stvx v29,off16,r7 + mr r10,r3 vxor zeroes,zeroes,zeroes - vspltisw ones,-1 + vspltisw v0,-1 - vsldoi mask_32bit,zeroes,ones,4 - vsldoi mask_64bit,zeroes,ones,8 + vsldoi mask_32bit,zeroes,v0,4 + vsldoi mask_64bit,zeroes,v0,8 /* Get the initial value into v8 */ vxor v8,v8,v8 @@ -570,6 +584,21 @@ FUNC_START(__crc32_vpmsum) vsldoi v0,v0,zeroes,4 /* shift result into top 64 bits of */ #endif +.Lout: + subi r6,r1,56+10*16 + subi r7,r1,56+2*16 + + lvx v20,0,r6 + lvx v21,off16,r6 + lvx v22,off32,r6 + lvx v23,off48,r6 + lvx v24,off64,r6 + lvx v25,off80,r6 + lvx v26,off96,r6 + lvx v27,off112,r6 + lvx v28,0,r7 + lvx v29,off16,r7 + /* Get it into r3 */ MFVRD(r3, v0) @@ -739,6 +768,8 @@ FUNC_START(__crc32_vpmsum) .Lzero: mr r3,r10 blr + b .Lout + FUNC_END(__crc32_vpmsum) #endif /* __powerpc__ */ diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index 7c144ac52a4..60d57b95d86 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -1249,7 +1249,7 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size, DBUG_ASSERT(size <= FULL_PAGE_SIZE(share)); - if (insert_order) + if (insert_order && bitmap->page == share->last_insert_bitmap) { uint last_insert_page= share->last_insert_page; uint byte= 6 * (last_insert_page / 16); @@ -1315,6 +1315,7 @@ found: { share->last_insert_page= ((uint) (best_data - bitmap->map)) / 6 * 16 + best_pos; + share->last_insert_bitmap= bitmap->page; } fill_block(bitmap, block, best_data, best_pos, best_bits, FULL_HEAD_PAGE); DBUG_RETURN(0); @@ -1614,6 +1615,16 @@ static my_bool find_head(MARIA_HA *info, uint length, uint position) */ block= dynamic_element(&info->bitmap_blocks, position, MARIA_BITMAP_BLOCK *); + if (info->s->base.extra_options & MA_EXTRA_OPTIONS_INSERT_ORDER) + { + if (bitmap->page != info->s->last_insert_bitmap && + _ma_change_bitmap_page(info, bitmap, + info->s->last_insert_bitmap)) + return 1; + /* Don't allocate any blocks from earlier pages */ + info->s->state.first_bitmap_with_space= info->s->last_insert_bitmap; + } + /* We need to have DIRENTRY_SIZE here to take into account that we may need an extra directory entry for the row @@ -3115,6 +3126,10 @@ static my_bool _ma_bitmap_create_missing(MARIA_HA *info, bzero(bitmap->map, bitmap->block_size); bitmap->used_size= 0; #ifndef DBUG_OFF + /* + Make a copy of the page to be able to print out bitmap changes during + debugging + */ memcpy(bitmap->map + bitmap->block_size, bitmap->map, bitmap->block_size); #endif diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index b517588f959..5035df26b18 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -6635,17 +6635,6 @@ static void copy_data_file_state(MARIA_STATE_INFO *to, } -/* Return 1 if block is full of zero's */ - -static my_bool zero_filled_block(uchar *tmp, uint length) -{ - while (length--) - if (*(tmp++) != 0) - return 0; - return 1; -} - - /* Read 'safely' next record while scanning table. @@ -6753,8 +6742,7 @@ read_next_page: sometimes be found at end of a bitmap when we wrote a big record last that was moved to the next bitmap. */ - if (!zero_filled_block(info->scan.page_buff, share->block_size) || - _ma_check_bitmap_data(info, UNALLOCATED_PAGE, 0, + if (_ma_check_bitmap_data(info, UNALLOCATED_PAGE, 0, _ma_bitmap_get_page_bits(info, &share->bitmap, page))) diff --git a/storage/maria/ma_crypt.c b/storage/maria/ma_crypt.c index 55fa8430d22..cc605d79933 100644 --- a/storage/maria/ma_crypt.c +++ b/storage/maria/ma_crypt.c @@ -182,10 +182,10 @@ ma_crypt_read(MARIA_SHARE* share, uchar *buff) return buff + 2 + iv_length; } -static int ma_encrypt(MARIA_CRYPT_DATA *, const uchar *, uchar *, uint, - uint, LSN, uint *); -static int ma_decrypt(MARIA_CRYPT_DATA *, const uchar *, uchar *, uint, - uint, LSN, uint); +static int ma_encrypt(MARIA_SHARE *, MARIA_CRYPT_DATA *, const uchar *, + uchar *, uint, uint, LSN, uint *); +static int ma_decrypt(MARIA_SHARE *, MARIA_CRYPT_DATA *, const uchar *, + uchar *, uint, uint, LSN, uint); static my_bool ma_crypt_pre_read_hook(PAGECACHE_IO_HOOK_ARGS *args) { @@ -227,7 +227,7 @@ static my_bool ma_crypt_data_post_read_hook(int res, /* 1 - copy head */ memcpy(dst, src, head); /* 2 - decrypt page */ - res= ma_decrypt(share->crypt_data, + res= ma_decrypt(share, share->crypt_data, src + head, dst + head, size - (head + tail), pageno, lsn, key_version); /* 3 - copy tail */ @@ -294,9 +294,9 @@ static my_bool ma_crypt_data_pre_write_hook(PAGECACHE_IO_HOOK_ARGS *args) /* 1 - copy head */ memcpy(dst, src, head); /* 2 - encrypt page */ - if (ma_encrypt(share->crypt_data, + if (ma_encrypt(share, share->crypt_data, src + head, dst + head, size - (head + tail), pageno, lsn, - &key_version)) + &key_version)) return 1; /* 3 - copy tail */ memcpy(dst + size - tail, src + size - tail, tail); @@ -361,7 +361,7 @@ static my_bool ma_crypt_index_post_read_hook(int res, /* 1 - copy head */ memcpy(dst, src, head); /* 2 - decrypt page */ - res= ma_decrypt(share->crypt_data, + res= ma_decrypt(share, share->crypt_data, src + head, dst + head, size, pageno, lsn, key_version); /* 3 - copy tail */ memcpy(dst + block_size - tail, src + block_size - tail, tail); @@ -414,9 +414,12 @@ static my_bool ma_crypt_index_pre_write_hook(PAGECACHE_IO_HOOK_ARGS *args) /* 1 - copy head */ memcpy(dst, src, head); /* 2 - encrypt page */ - if (ma_encrypt(share->crypt_data, + if (ma_encrypt(share, share->crypt_data, src + head, dst + head, size, pageno, lsn, &key_version)) + { + my_free(crypt_buf); return 1; + } /* 3 - copy tail */ memcpy(dst + block_size - tail, src + block_size - tail, tail); /* 4 - store key version */ @@ -444,19 +447,26 @@ void ma_crypt_set_index_pagecache_callbacks(PAGECACHE_FILE *file, file->post_write_hook= ma_crypt_post_write_hook; } -static int ma_encrypt(MARIA_CRYPT_DATA *crypt_data, - const uchar *src, uchar *dst, uint size, - uint pageno, LSN lsn, - uint *key_version) +static int ma_encrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data, + const uchar *src, uchar *dst, uint size, + uint pageno, LSN lsn, + uint *key_version) { int rc; - uint32 dstlen; + uint32 dstlen= 0; /* Must be set because of error message */ *key_version = encryption_key_get_latest_version(crypt_data->scheme.key_id); if (*key_version == ENCRYPTION_KEY_VERSION_INVALID) { - my_printf_error(HA_ERR_GENERIC, "Unknown key id %u. Can't continue!", - MYF(ME_FATALERROR|ME_NOREFRESH), crypt_data->scheme.key_id); + /* + We use this error for both encryption and decryption, as in normal + cases it should be impossible to get an error here. + */ + my_errno= HA_ERR_DECRYPTION_FAILED; + my_printf_error(HA_ERR_DECRYPTION_FAILED, + "Unknown key id %u. Can't continue!", + MYF(ME_FATALERROR|ME_NOREFRESH), + crypt_data->scheme.key_id); return 1; } @@ -464,40 +474,43 @@ static int ma_encrypt(MARIA_CRYPT_DATA *crypt_data, &crypt_data->scheme, *key_version, crypt_data->space, pageno, lsn); - DBUG_ASSERT(rc == MY_AES_OK); - DBUG_ASSERT(dstlen == size); + /* The following can only fail if the encryption key is wrong */ + DBUG_ASSERT(!my_assert_on_error || rc == MY_AES_OK); + DBUG_ASSERT(!my_assert_on_error || dstlen == size); if (! (rc == MY_AES_OK && dstlen == size)) { - my_printf_error(HA_ERR_GENERIC, - "failed to encrypt! rc: %d, dstlen: %u size: %u\n", + my_errno= HA_ERR_DECRYPTION_FAILED; + my_printf_error(HA_ERR_DECRYPTION_FAILED, + "failed to encrypt '%s' rc: %d dstlen: %u size: %u\n", MYF(ME_FATALERROR|ME_NOREFRESH), - rc, dstlen, size); + share->open_file_name.str, rc, dstlen, size); return 1; } return 0; } -static int ma_decrypt(MARIA_CRYPT_DATA *crypt_data, +static int ma_decrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data, const uchar *src, uchar *dst, uint size, uint pageno, LSN lsn, uint key_version) { int rc; - uint32 dstlen; + uint32 dstlen= 0; /* Must be set because of error message */ rc= encryption_scheme_decrypt(src, size, dst, &dstlen, &crypt_data->scheme, key_version, crypt_data->space, pageno, lsn); - DBUG_ASSERT(rc == MY_AES_OK); - DBUG_ASSERT(dstlen == size); + DBUG_ASSERT(!my_assert_on_error || rc == MY_AES_OK); + DBUG_ASSERT(!my_assert_on_error || dstlen == size); if (! (rc == MY_AES_OK && dstlen == size)) { - my_printf_error(HA_ERR_GENERIC, - "failed to encrypt! rc: %d, dstlen: %u size: %u\n", + my_errno= HA_ERR_DECRYPTION_FAILED; + my_printf_error(HA_ERR_DECRYPTION_FAILED, + "failed to decrypt '%s' rc: %d dstlen: %u size: %u\n", MYF(ME_FATALERROR|ME_NOREFRESH), - rc, dstlen, size); + share->open_file_name.str, rc, dstlen, size); return 1; } return 0; diff --git a/storage/maria/ma_packrec.c b/storage/maria/ma_packrec.c index a541a657ed2..6a4e7ea99cf 100644 --- a/storage/maria/ma_packrec.c +++ b/storage/maria/ma_packrec.c @@ -1204,7 +1204,7 @@ static void decode_bytes(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff, /* This means that the Huffman code must be longer than table_bits. */ pos=decode_tree->table+low_byte; bits-=table_bits; - /* NOTE: decode_bytes_test_bit() is a macro wich contains a break !!! */ + /* NOTE: decode_bytes_test_bit() is a macro which contains a break !!! */ for (;;) { low_byte=(uint) (bit_buff->current_byte >> (bits-8)); diff --git a/storage/maria/ma_pagecache.c b/storage/maria/ma_pagecache.c index bba99703119..ade91a159ca 100644 --- a/storage/maria/ma_pagecache.c +++ b/storage/maria/ma_pagecache.c @@ -1077,7 +1077,7 @@ static inline void dec_counter_for_resize_op(PAGECACHE *pagecache) { DBUG_PRINT("signal", ("thread %s %ld", last_thread->next->name, - last_thread->next->id)); + (ulong) last_thread->next->id)); pagecache_pthread_cond_signal(&last_thread->next->suspend); } } @@ -1341,7 +1341,8 @@ static void link_block(PAGECACHE *pagecache, PAGECACHE_BLOCK_LINK *block, */ if ((PAGECACHE_HASH_LINK *) thread->keycache_link == hash_link) { - DBUG_PRINT("signal", ("thread: %s %ld", thread->name, thread->id)); + DBUG_PRINT("signal", ("thread: %s %ld", thread->name, + (ulong) thread->id)); pagecache_pthread_cond_signal(&thread->suspend); wqueue_unlink_from_queue(&pagecache->waiting_for_block, thread); block->requests++; @@ -1579,7 +1580,7 @@ static inline void wait_for_readers(PAGECACHE *pagecache DBUG_ENTER("wait_for_readers"); DBUG_PRINT("wait", ("suspend thread: %s %ld block: %u", - thread->name, thread->id, + thread->name, (ulong) thread->id, PCBLOCK_NUMBER(pagecache, block))); block->condvar= &thread->suspend; pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); @@ -1604,7 +1605,7 @@ static void wait_for_flush(PAGECACHE *pagecache do { DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -1671,7 +1672,8 @@ static void unlink_hash(PAGECACHE *pagecache, PAGECACHE_HASH_LINK *hash_link) if (page->file.file == hash_link->file.file && page->pageno == hash_link->pageno) { - DBUG_PRINT("signal", ("thread %s %ld", thread->name, thread->id)); + DBUG_PRINT("signal", ("thread %s %ld", thread->name, + (ulong) thread->id)); pagecache_pthread_cond_signal(&thread->suspend); wqueue_unlink_from_queue(&pagecache->waiting_for_hash_link, thread); } @@ -1811,7 +1813,7 @@ restart: thread->keycache_link= (void *) &page; wqueue_link_into_queue(&pagecache->waiting_for_hash_link, thread); DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); thread->keycache_link= NULL; @@ -1991,7 +1993,8 @@ restart: do { DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, + (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -2082,7 +2085,8 @@ restart: do { DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, + (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -2355,7 +2359,7 @@ static my_bool pagecache_wait_lock(PAGECACHE *pagecache, do { DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -2755,7 +2759,8 @@ static void read_block(PAGECACHE *pagecache, do { DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, + (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -4549,7 +4554,7 @@ static int flush_pagecache_blocks_int(PAGECACHE *pagecache, { DBUG_PRINT("wait", ("(1) suspend thread %s %ld", - thread->name, thread->id)); + thread->name, (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -4710,7 +4715,7 @@ restart: { DBUG_PRINT("wait", ("(2) suspend thread %s %ld", - thread->name, thread->id)); + thread->name, (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -4914,7 +4919,8 @@ my_bool pagecache_collect_changed_blocks_with_lsn(PAGECACHE *pagecache, do { DBUG_PRINT("wait", - ("suspend thread %s %ld", thread->name, thread->id)); + ("suspend thread %s %ld", thread->name, + (ulong) thread->id)); pagecache_pthread_cond_wait(&thread->suspend, &pagecache->cache_lock); } @@ -5057,7 +5063,8 @@ static void pagecache_dump(PAGECACHE *pagecache) PAGECACHE_PAGE *page; uint i; - fprintf(pagecache_dump_file, "thread: %s %ld\n", thread->name, thread->id); + fprintf(pagecache_dump_file, "thread: %s %ld\n", thread->name, + (ulong) thread->id); i=0; thread=last=waiting_for_hash_link.last_thread; @@ -5069,7 +5076,7 @@ static void pagecache_dump(PAGECACHE *pagecache) page= (PAGECACHE_PAGE *) thread->keycache_link; fprintf(pagecache_dump_file, "thread: %s %ld, (file,pageno)=(%u,%lu)\n", - thread->name, thread->id, + thread->name, (ulong) thread->id, (uint) page->file.file,(ulong) page->pageno); if (++i == MAX_QUEUE_LEN) break; @@ -5086,7 +5093,7 @@ static void pagecache_dump(PAGECACHE *pagecache) hash_link= (PAGECACHE_HASH_LINK *) thread->keycache_link; fprintf(pagecache_dump_file, "thread: %s %u hash_link:%u (file,pageno)=(%u,%lu)\n", - thread->name, thread->id, + thread->name, (ulong) thread->id, (uint) PAGECACHE_HASH_LINK_NUMBER(pagecache, hash_link), (uint) hash_link->file.file,(ulong) hash_link->pageno); if (++i == MAX_QUEUE_LEN) @@ -5116,7 +5123,7 @@ static void pagecache_dump(PAGECACHE *pagecache) { thread=thread->next; fprintf(pagecache_dump_file, - "thread: %s %ld\n", thread->name, thread->id); + "thread: %s %ld\n", thread->name, (ulong) thread->id); if (++i == MAX_QUEUE_LEN) break; } diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c index 967d4a151be..ef6e8506ac6 100644 --- a/storage/maria/ma_sort.c +++ b/storage/maria/ma_sort.c @@ -90,6 +90,27 @@ static inline int my_var_write(MARIA_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs); /* + Sets the appropriate read and write methods for the MARIA_SORT_PARAM + based on the variable length key flag. +*/ +static void set_sort_param_read_write(MARIA_SORT_PARAM *sort_param) +{ + if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY) + { + sort_param->write_keys= write_keys_varlen; + sort_param->read_to_buffer= read_to_buffer_varlen; + sort_param->write_key= write_merge_key_varlen; + } + else + { + sort_param->write_keys= write_keys; + sort_param->read_to_buffer= read_to_buffer; + sort_param->write_key= write_merge_key; + } +} + + +/* Creates a index of sorted keys SYNOPSIS @@ -118,18 +139,7 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages, (ulong) sortbuff_size, info->key_length, (ulong) info->sort_info->max_records)); - if (info->keyinfo->flag & HA_VAR_LENGTH_KEY) - { - info->write_keys= write_keys_varlen; - info->read_to_buffer= read_to_buffer_varlen; - info->write_key=write_merge_key_varlen; - } - else - { - info->write_keys= write_keys; - info->read_to_buffer=read_to_buffer; - info->write_key=write_merge_key; - } + set_sort_param_read_write(info); my_b_clear(&tempfile); my_b_clear(&tempfile_for_exceptions); @@ -378,18 +388,7 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg) if (sort_param->sort_info->got_error) goto err; - if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY) - { - sort_param->write_keys= write_keys_varlen; - sort_param->read_to_buffer= read_to_buffer_varlen; - sort_param->write_key= write_merge_key_varlen; - } - else - { - sort_param->write_keys= write_keys; - sort_param->read_to_buffer= read_to_buffer; - sort_param->write_key= write_merge_key; - } + set_sort_param_read_write(sort_param); my_b_clear(&sort_param->tempfile); my_b_clear(&sort_param->tempfile_for_exceptions); @@ -614,18 +613,9 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param) { if (got_error) continue; - if (sinfo->keyinfo->flag & HA_VAR_LENGTH_KEY) - { - sinfo->write_keys=write_keys_varlen; - sinfo->read_to_buffer=read_to_buffer_varlen; - sinfo->write_key=write_merge_key_varlen; - } - else - { - sinfo->write_keys=write_keys; - sinfo->read_to_buffer=read_to_buffer; - sinfo->write_key=write_merge_key; - } + + set_sort_param_read_write(sinfo); + if (sinfo->buffpek.elements) { uint maxbuffer=sinfo->buffpek.elements-1; diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 676927b119a..7337b01a981 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -523,6 +523,7 @@ typedef struct st_maria_share Keep of track of last insert page, used to implement insert order */ uint last_insert_page; + pgcache_page_no_t last_insert_bitmap; } MARIA_SHARE; diff --git a/storage/mroonga/mrn_table.cpp b/storage/mroonga/mrn_table.cpp index af07dc09cf3..144dbe0c530 100644 --- a/storage/mroonga/mrn_table.cpp +++ b/storage/mroonga/mrn_table.cpp @@ -278,7 +278,7 @@ void mrn_get_partition_info(const char *table_name, uint table_name_length, #define MRN_PARAM_STR(title_name, param_name) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info", ("mroonga "title_name" start")); \ + DBUG_PRINT("info", ("mroonga " title_name " start")); \ if (!share->param_name) \ { \ if ((share->param_name = mrn_get_string_between_quote( \ @@ -290,7 +290,7 @@ void mrn_get_partition_info(const char *table_name, uint table_name_length, MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info", ("mroonga "title_name"=%s", share->param_name)); \ + DBUG_PRINT("info", ("mroonga " title_name "=%s", share->param_name)); \ } \ break; \ } @@ -298,7 +298,7 @@ void mrn_get_partition_info(const char *table_name, uint table_name_length, #define MRN_PARAM_STR_LIST(title_name, param_name, param_pos) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info", ("mroonga "title_name" start")); \ + DBUG_PRINT("info", ("mroonga " title_name " start")); \ if (share->param_name && !share->param_name[param_pos]) \ { \ if ((share->param_name[param_pos] = mrn_get_string_between_quote( \ @@ -311,7 +311,7 @@ void mrn_get_partition_info(const char *table_name, uint table_name_length, MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info", ("mroonga "title_name"[%d]=%s", param_pos, \ + DBUG_PRINT("info", ("mroonga " title_name "[%d]=%s", param_pos, \ share->param_name[param_pos])); \ } \ break; \ @@ -1015,10 +1015,7 @@ TABLE_SHARE *mrn_get_table_share(TABLE_LIST *table_list, int *error) share = get_table_share(thd, table_list, key, key_length, 0, error, hash_value); #elif defined(MRN_HAVE_TDC_ACQUIRE_SHARE) - share = tdc_acquire_share(thd, table_list->db, table_list->table_name, key, - key_length, - table_list->mdl_request.key.tc_hash_value(), - GTS_TABLE, NULL); + share = tdc_acquire_share(thd, table_list, GTS_TABLE); #else share = get_table_share(thd, table_list, key, key_length, 0, error); #endif diff --git a/storage/mroonga/vendor/groonga/lib/com.c b/storage/mroonga/vendor/groonga/lib/com.c index a7450ec31f0..a16a446022c 100644 --- a/storage/mroonga/vendor/groonga/lib/com.c +++ b/storage/mroonga/vendor/groonga/lib/com.c @@ -348,7 +348,7 @@ grn_com_event_add(grn_ctx *ctx, grn_com_event *ev, grn_sock fd, int events, grn_ struct epoll_event e; memset(&e, 0, sizeof(struct epoll_event)); e.data.fd = (fd); - e.events = (__uint32_t) events; + e.events = (uint32_t) events; if (epoll_ctl(ev->epfd, EPOLL_CTL_ADD, (fd), &e) == -1) { SERR("epoll_ctl"); return ctx->rc; @@ -396,7 +396,7 @@ grn_com_event_mod(grn_ctx *ctx, grn_com_event *ev, grn_sock fd, int events, grn_ struct epoll_event e; memset(&e, 0, sizeof(struct epoll_event)); e.data.fd = (fd); - e.events = (__uint32_t) events; + e.events = (uint32_t) events; if (epoll_ctl(ev->epfd, EPOLL_CTL_MOD, (fd), &e) == -1) { SERR("epoll_ctl"); return ctx->rc; diff --git a/storage/mroonga/vendor/groonga/lib/grn_com.h b/storage/mroonga/vendor/groonga/lib/grn_com.h index 203ed56c88d..e5ad58981cf 100644 --- a/storage/mroonga/vendor/groonga/lib/grn_com.h +++ b/storage/mroonga/vendor/groonga/lib/grn_com.h @@ -83,7 +83,11 @@ GRN_API grn_com_queue_entry *grn_com_queue_deque(grn_ctx *ctx, grn_com_queue *q) # define GRN_COM_POLLIN EVFILT_READ # define GRN_COM_POLLOUT EVFILT_WRITE # else /* USE_KQUEUE */ -# include <sys/poll.h> +# if defined(HAVE_POLL_H) +# include <poll.h> +# elif defined(HAVE_SYS_POLL_H) +# include <sys/poll.h> +# endif /* defined(HAVE_POLL_H) */ # define GRN_COM_POLLIN POLLIN # define GRN_COM_POLLOUT POLLOUT # endif /* USE_KQUEUE */ diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index cbf411544b6..812166ce1cc 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -637,7 +637,7 @@ void _mi_report_crashed(MI_INFO *file, const char *message, char buf[1024]; mysql_mutex_lock(&file->s->intern_lock); if ((cur_thd= (THD*) file->in_use.data)) - sql_print_error("Got an error from thread_id=%lu, %s:%d", cur_thd->thread_id, + sql_print_error("Got an error from thread_id=%lld, %s:%d", cur_thd->thread_id, sfile, sline); else sql_print_error("Got an error from unknown thread, %s:%d", sfile, sline); @@ -2409,7 +2409,7 @@ maria_declare_plugin_end; @return The error code. The engine_data and engine_callback will be set to 0. @retval TRUE Success - @retval FALSE An error occured + @retval FALSE An error occurred */ my_bool ha_myisam::register_query_cache_table(THD *thd, char *table_name, diff --git a/storage/myisam/mi_packrec.c b/storage/myisam/mi_packrec.c index 3687cfc2179..fc32bb7e518 100644 --- a/storage/myisam/mi_packrec.c +++ b/storage/myisam/mi_packrec.c @@ -1158,7 +1158,7 @@ static void decode_bytes(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,uchar *to, /* This means that the Huffman code must be longer than table_bits. */ pos=decode_tree->table+low_byte; bits-=table_bits; - /* NOTE: decode_bytes_test_bit() is a macro wich contains a break !!! */ + /* NOTE: decode_bytes_test_bit() is a macro which contains a break !!! */ for (;;) { low_byte=(uint) (bit_buff->current_byte >> (bits-8)); diff --git a/storage/myisam/myisamlog.c b/storage/myisam/myisamlog.c index d549dd76037..7ce03ca9485 100644 --- a/storage/myisam/myisamlog.c +++ b/storage/myisam/myisamlog.c @@ -266,7 +266,7 @@ static void get_options(register int *argc, register char ***argv) puts(" -u \"update\" -v \"verbose\" -w \"write file\""); puts(" -D \"myisam compiled with DBUG\" -P \"processes\""); puts("\nOne can give a second and a third '-v' for more verbose."); - puts("Normaly one does a update (-u)."); + puts("Normally one does a update (-u)."); puts("If a recover is done all writes and all possibly updates and deletes is done\nand errors are only counted."); puts("If one gives table names as arguments only these tables will be updated\n"); help=1; diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index 604910e5099..f490e5f0b44 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -86,6 +86,28 @@ static int write_merge_key_varlen(MI_SORT_PARAM *info, static inline int my_var_write(MI_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs); + +/* + Sets the appropriate read and write methods for the MI_SORT_PARAM + based on the variable length key flag. +*/ +static void set_sort_param_read_write(MI_SORT_PARAM *sort_param) +{ + if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY) + { + sort_param->write_keys= write_keys_varlen; + sort_param->read_to_buffer= read_to_buffer_varlen; + sort_param->write_key= write_merge_key_varlen; + } + else + { + sort_param->write_keys= write_keys; + sort_param->read_to_buffer= read_to_buffer; + sort_param->write_key= write_merge_key; + } +} + + /* Creates a index of sorted keys @@ -113,18 +135,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, DBUG_ENTER("_create_index_by_sort"); DBUG_PRINT("enter",("sort_length: %u", info->key_length)); - if (info->keyinfo->flag & HA_VAR_LENGTH_KEY) - { - info->write_keys=write_keys_varlen; - info->read_to_buffer=read_to_buffer_varlen; - info->write_key= write_merge_key_varlen; - } - else - { - info->write_keys=write_keys; - info->read_to_buffer=read_to_buffer; - info->write_key=write_merge_key; - } + set_sort_param_read_write(info); my_b_clear(&tempfile); my_b_clear(&tempfile_for_exceptions); @@ -333,7 +344,6 @@ static ha_rows find_all_keys(MI_SORT_PARAM *info, ha_rows keys, DBUG_RETURN((*maxbuffer)*(keys-1)+idx); } /* find_all_keys */ - /* Search after all keys and place them in a temp. file */ pthread_handler_t thr_find_all_keys(void *arg) @@ -357,18 +367,7 @@ pthread_handler_t thr_find_all_keys(void *arg) if (sort_param->sort_info->got_error) goto err; - if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY) - { - sort_param->write_keys= write_keys_varlen; - sort_param->read_to_buffer= read_to_buffer_varlen; - sort_param->write_key= write_merge_key_varlen; - } - else - { - sort_param->write_keys= write_keys; - sort_param->read_to_buffer= read_to_buffer; - sort_param->write_key= write_merge_key; - } + set_sort_param_read_write(sort_param); my_b_clear(&sort_param->tempfile); my_b_clear(&sort_param->tempfile_for_exceptions); @@ -593,18 +592,9 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) { if (got_error) continue; - if (sinfo->keyinfo->flag & HA_VAR_LENGTH_KEY) - { - sinfo->write_keys=write_keys_varlen; - sinfo->read_to_buffer=read_to_buffer_varlen; - sinfo->write_key=write_merge_key_varlen; - } - else - { - sinfo->write_keys=write_keys; - sinfo->read_to_buffer=read_to_buffer; - sinfo->write_key=write_merge_key; - } + + set_sort_param_read_write(sinfo); + if (sinfo->buffpek.elements) { uint maxbuffer=sinfo->buffpek.elements-1; diff --git a/storage/oqgraph/graphcore.cc b/storage/oqgraph/graphcore.cc index 73433fc8219..4346b94805c 100644 --- a/storage/oqgraph/graphcore.cc +++ b/storage/oqgraph/graphcore.cc @@ -1036,11 +1036,11 @@ int stack_cursor::fetch_row(const row &row_info, row &result, optional<EdgeWeight> w; optional<Vertex> v; result= row_info; - if ((result.seq_indicator= seq= last.sequence())) + if ((result.seq_indicator= static_cast<bool>(seq= last.sequence()))) result.seq= *seq; - if ((result.link_indicator= v= last.vertex())) + if ((result.link_indicator= static_cast<bool>(v= last.vertex()))) result.link= get(boost::vertex_index, share->g, *v); - if ((result.weight_indicator= w= last.weight())) + if ((result.weight_indicator= static_cast<bool>(w= last.weight()))) result.weight= *w; return oqgraph::OK; } diff --git a/storage/oqgraph/ha_oqgraph.cc b/storage/oqgraph/ha_oqgraph.cc index e220d64d962..78a0079a5ab 100644 --- a/storage/oqgraph/ha_oqgraph.cc +++ b/storage/oqgraph/ha_oqgraph.cc @@ -1,5 +1,6 @@ /* Copyright (C) 2007-2015 Arjen G Lentz & Antony T Curtis for Open Query Copyright (C) 2013-2015 Andrew McDonnell + Copyright (C) 2014 Sergei Golubchik Portions of this file copyright (C) 2000-2006 MySQL AB This program is free software; you can redistribute it and/or modify @@ -752,6 +753,10 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked) int ha_oqgraph::close(void) { DBUG_PRINT( "oq-debug", ("close()")); + if (graph->get_thd() != current_thd) { + DBUG_PRINT( "oq-debug", ("index_next_same g->table->in_use: 0x%lx <-- current_thd 0x%lx", (long) graph->get_thd(), (long) current_thd)); + graph->set_thd(current_thd); + } oqgraph::free(graph); graph= 0; oqgraph::free(graph_share); graph_share= 0; @@ -1371,6 +1376,6 @@ maria_declare_plugin(oqgraph) oqgraph_status, /* status variables */ oqgraph_sysvars, /* system variables */ "3.0", - MariaDB_PLUGIN_MATURITY_BETA + MariaDB_PLUGIN_MATURITY_GAMMA } maria_declare_plugin_end; diff --git a/storage/oqgraph/mysql-test/oqgraph/general.inc b/storage/oqgraph/mysql-test/oqgraph/general.inc index 357a8c786ee..f27b7585dd7 100644 --- a/storage/oqgraph/mysql-test/oqgraph/general.inc +++ b/storage/oqgraph/mysql-test/oqgraph/general.inc @@ -14,7 +14,7 @@ eval CREATE TABLE graph_base ( INDEX (to_id) ) ENGINE= $oqgraph_use_table_type ; - +# Since late June 2014 OQGraph supports 'assisted discovery' as per https://mariadb.atlassian.net/browse/MDEV-5871 CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' ORIGID='from_id', DESTID='to_id'; # Regression for MDEV-5891 diff --git a/storage/oqgraph/mysql-test/oqgraph/regression_mdev5871.result b/storage/oqgraph/mysql-test/oqgraph/regression_mdev5871.result new file mode 100644 index 00000000000..d2dfc46d5ff --- /dev/null +++ b/storage/oqgraph/mysql-test/oqgraph/regression_mdev5871.result @@ -0,0 +1,86 @@ +DROP TABLE IF EXISTS graph_base; +DROP TABLE IF EXISTS graph; +CREATE TABLE graph_base ( +from_id INT UNSIGNED NOT NULL, +to_id INT UNSIGNED NOT NULL, +weight DOUBLE NOT NULL, +PRIMARY KEY (from_id,to_id), +INDEX (to_id) +) ENGINE=MyISAM; +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' ORIGID='from_id' DESTID='to_id'; +DESCRIBE graph; +Field Type Null Key Default Extra +latch varchar(32) YES MUL NULL +origid bigint(20) unsigned YES NULL +destid bigint(20) unsigned YES NULL +weight double YES NULL +seq bigint(20) unsigned YES NULL +linkid bigint(20) unsigned YES NULL +DROP TABLE IF EXISTS graph; +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' ORIGID='from_id' DESTID='to_id' WEIGHT='weight'; +DESCRIBE graph; +Field Type Null Key Default Extra +latch varchar(32) YES MUL NULL +origid bigint(20) unsigned YES NULL +destid bigint(20) unsigned YES NULL +weight double YES NULL +seq bigint(20) unsigned YES NULL +linkid bigint(20) unsigned YES NULL +DROP TABLE IF EXISTS graph; +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base_xxx' ORIGID='from_id' DESTID='to_id_xxx' WEIGHT='weight'; +# Expect 'Table 'test.graph_base_xxx' doesn't exist' +DESCRIBE graph; +ERROR 42S02: Table 'test.graph_base_xxx' doesn't exist +DROP TABLE IF EXISTS graph; +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' ORIGID='from_id' DESTID='to_id' WEIGHT='weight_xxx'; +# Expect 'Invalid OQGRAPH backing store description ('graph.weight' attribute not set to a valid column of 'graph_base')' +DESCRIBE graph; +ERROR HY000: Got error -1 'Invalid OQGRAPH backing store ('graph.weight' attribute not set to a valid column of 'graph_base')' from OQGRAPH +DROP TABLE IF EXISTS graph; +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' ORIGID='from_id' DESTID='to_id_xxx' WEIGHT='weight'; +# Expect 'Invalid OQGRAPH backing store description ('graph.destid' attribute not set to a valid column of 'graph_base')' +DESCRIBE graph; +ERROR HY000: Got error -1 'Invalid OQGRAPH backing store ('graph.destid' attribute not set to a valid column of 'graph_base')' from OQGRAPH +DROP TABLE IF EXISTS graph; +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' ORIGID='from_id_xxx' DESTID='to_id' WEIGHT='weight'; +# Expect 'Invalid OQGRAPH backing store description ('graph.origid' attribute not set to a valid column of 'graph_base')' +DESCRIBE graph; +ERROR HY000: Got error -1 'Invalid OQGRAPH backing store ('graph.origid' attribute not set to a valid column of 'graph_base')' from OQGRAPH +DROP TABLE IF EXISTS graph; +CREATE TABLE graph ENGINE=OQGRAPH; +# Expect: 'Invalid OQGRAPH backing store description (unspecified or empty data_table attribute)' +DESCRIBE graph; +ERROR HY000: Got error -1 'Invalid OQGRAPH backing store description (unspecified or empty data_table attribute)' from OQGRAPH +DROP TABLE IF EXISTS graph; +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base'; +# Expect: 'Invalid OQGRAPH backing store description (unspecified or empty origid attribute)' +DESCRIBE graph; +ERROR HY000: Got error -1 'Invalid OQGRAPH backing store description (unspecified or empty origid attribute)' from OQGRAPH +DROP TABLE IF EXISTS graph; +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' ORIGID='from_id'; +# Expect: 'Invalid OQGRAPH backing store description (unspecified or empty destid attribute)' +DESCRIBE graph; +ERROR HY000: Got error -1 'Invalid OQGRAPH backing store description (unspecified or empty destid attribute)' from OQGRAPH +DROP TABLE IF EXISTS graph; +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' DESTID='to_id'; +# Expect: 'Invalid OQGRAPH backing store description (unspecified or empty origid attribute)' +DESCRIBE graph; +ERROR HY000: Got error -1 'Invalid OQGRAPH backing store description (unspecified or empty origid attribute)' from OQGRAPH +DROP TABLE IF EXISTS graph; +CREATE TABLE graph ENGINE=OQGRAPH ORIGID='from_id'; +# Expect: 'Invalid OQGRAPH backing store description (unspecified or empty data_table attribute)' +DESCRIBE graph; +ERROR HY000: Got error -1 'Invalid OQGRAPH backing store description (unspecified or empty data_table attribute)' from OQGRAPH +DROP TABLE IF EXISTS graph; +CREATE TABLE graph ENGINE=OQGRAPH DESTID='to_id'; +# Expect: 'Invalid OQGRAPH backing store description (unspecified or empty data_table attribute)' +DESCRIBE graph; +ERROR HY000: Got error -1 'Invalid OQGRAPH backing store description (unspecified or empty data_table attribute)' from OQGRAPH +DROP TABLE IF EXISTS graph; +CREATE TABLE graph ENGINE=OQGRAPH ORIGID='from_id', DESTID='to_id'; +# Expect: 'Invalid OQGRAPH backing store description (unspecified or empty data_table attribute)' +DESCRIBE graph; +ERROR HY000: Got error -1 'Invalid OQGRAPH backing store description (unspecified or empty data_table attribute)' from OQGRAPH +DROP TABLE IF EXISTS graph; +DROP TABLE IF EXISTS graph; +DROP TABLE IF EXISTS graph_base; diff --git a/storage/oqgraph/mysql-test/oqgraph/regression_mdev5871.test b/storage/oqgraph/mysql-test/oqgraph/regression_mdev5871.test new file mode 100644 index 00000000000..15d1eff0142 --- /dev/null +++ b/storage/oqgraph/mysql-test/oqgraph/regression_mdev5871.test @@ -0,0 +1,121 @@ +--disable_warnings +DROP TABLE IF EXISTS graph_base; +DROP TABLE IF EXISTS graph; +--enable_warnings + +CREATE TABLE graph_base ( + from_id INT UNSIGNED NOT NULL, + to_id INT UNSIGNED NOT NULL, + weight DOUBLE NOT NULL, + PRIMARY KEY (from_id,to_id), + INDEX (to_id) + ) ENGINE=MyISAM; + +# Since late June 2014 OQGraph supports 'assisted discovery' as per https://mariadb.atlassian.net/browse/MDEV-5871 + +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' ORIGID='from_id' DESTID='to_id'; +DESCRIBE graph; +--disable_warnings +DROP TABLE IF EXISTS graph; +--enable_warnings + +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' ORIGID='from_id' DESTID='to_id' WEIGHT='weight'; +DESCRIBE graph; +--disable_warnings +DROP TABLE IF EXISTS graph; +--enable_warnings + +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base_xxx' ORIGID='from_id' DESTID='to_id_xxx' WEIGHT='weight'; +--echo # Expect 'Table 'test.graph_base_xxx' doesn't exist' +--error 1146 +DESCRIBE graph; +--disable_warnings +DROP TABLE IF EXISTS graph; +--enable_warnings + +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' ORIGID='from_id' DESTID='to_id' WEIGHT='weight_xxx'; +--echo # Expect 'Invalid OQGRAPH backing store description ('graph.weight' attribute not set to a valid column of 'graph_base')' +--error 1296 +DESCRIBE graph; +--disable_warnings +DROP TABLE IF EXISTS graph; +--enable_warnings + +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' ORIGID='from_id' DESTID='to_id_xxx' WEIGHT='weight'; +--echo # Expect 'Invalid OQGRAPH backing store description ('graph.destid' attribute not set to a valid column of 'graph_base')' +--error 1296 +DESCRIBE graph; +--disable_warnings +DROP TABLE IF EXISTS graph; +--enable_warnings + +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' ORIGID='from_id_xxx' DESTID='to_id' WEIGHT='weight'; +--echo # Expect 'Invalid OQGRAPH backing store description ('graph.origid' attribute not set to a valid column of 'graph_base')' +--error 1296 +DESCRIBE graph; +--disable_warnings +DROP TABLE IF EXISTS graph; +--enable_warnings + +# The following combinations should be invalid +CREATE TABLE graph ENGINE=OQGRAPH; +--echo # Expect: 'Invalid OQGRAPH backing store description (unspecified or empty data_table attribute)' +--error 1296 +DESCRIBE graph; +--disable_warnings +DROP TABLE IF EXISTS graph; +--enable_warnings + +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base'; +--echo # Expect: 'Invalid OQGRAPH backing store description (unspecified or empty origid attribute)' +--error 1296 +DESCRIBE graph; +--disable_warnings +DROP TABLE IF EXISTS graph; +--enable_warnings + +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' ORIGID='from_id'; +--echo # Expect: 'Invalid OQGRAPH backing store description (unspecified or empty destid attribute)' +--error 1296 +DESCRIBE graph; +--disable_warnings +DROP TABLE IF EXISTS graph; +--enable_warnings + +CREATE TABLE graph ENGINE=OQGRAPH DATA_TABLE='graph_base' DESTID='to_id'; +--echo # Expect: 'Invalid OQGRAPH backing store description (unspecified or empty origid attribute)' +--error 1296 +DESCRIBE graph; +--disable_warnings +DROP TABLE IF EXISTS graph; +--enable_warnings + +CREATE TABLE graph ENGINE=OQGRAPH ORIGID='from_id'; +--echo # Expect: 'Invalid OQGRAPH backing store description (unspecified or empty data_table attribute)' +--error 1296 +DESCRIBE graph; +--disable_warnings +DROP TABLE IF EXISTS graph; +--enable_warnings + +CREATE TABLE graph ENGINE=OQGRAPH DESTID='to_id'; +--echo # Expect: 'Invalid OQGRAPH backing store description (unspecified or empty data_table attribute)' +--error 1296 +DESCRIBE graph; +--disable_warnings +DROP TABLE IF EXISTS graph; +--enable_warnings + +CREATE TABLE graph ENGINE=OQGRAPH ORIGID='from_id', DESTID='to_id'; +--echo # Expect: 'Invalid OQGRAPH backing store description (unspecified or empty data_table attribute)' +--error 1296 +DESCRIBE graph; +--disable_warnings +DROP TABLE IF EXISTS graph; +--enable_warnings + +--disable_warnings +DROP TABLE IF EXISTS graph; +DROP TABLE IF EXISTS graph_base; +--enable_warnings + diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc index dcdd9b90c56..2a87ffba999 100644 --- a/storage/perfschema/ha_perfschema.cc +++ b/storage/perfschema/ha_perfschema.cc @@ -225,7 +225,7 @@ maria_declare_plugin(perfschema) 0x0001, pfs_status_vars, NULL, - "5.6.27", + "5.6.29", MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; diff --git a/storage/perfschema/pfs.cc b/storage/perfschema/pfs.cc index dd61df5f861..dbe3241cfe8 100644 --- a/storage/perfschema/pfs.cc +++ b/storage/perfschema/pfs.cc @@ -1444,7 +1444,9 @@ static void register_statement_v1(const char *category, for (; count>0; count--, info++) { - DBUG_ASSERT(info->m_name != NULL); + if (info->m_name == NULL) + continue; + len= strlen(info->m_name); full_length= prefix_length + len; if (likely(full_length <= PFS_MAX_INFO_NAME_LENGTH)) diff --git a/storage/perfschema/table_session_connect.cc b/storage/perfschema/table_session_connect.cc index bbe99ffa794..17c608a7f4c 100644 --- a/storage/perfschema/table_session_connect.cc +++ b/storage/perfschema/table_session_connect.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -220,7 +220,8 @@ void table_session_connect::make_row(PFS_thread *pfs, uint ordinal) &m_row.m_attr_value_length)) { /* we don't expect internal threads to have connection attributes */ - DBUG_ASSERT(pfs->m_processlist_id != 0); + if (pfs->m_processlist_id == 0) + return; m_row.m_ordinal_position= ordinal; m_row.m_process_id= pfs->m_processlist_id; diff --git a/storage/sequence/mysql-test/sequence/group_by.result b/storage/sequence/mysql-test/sequence/group_by.result index 86bb158d9fc..b3b56338aef 100644 --- a/storage/sequence/mysql-test/sequence/group_by.result +++ b/storage/sequence/mysql-test/sequence/group_by.result @@ -85,4 +85,10 @@ id select_type table type possible_keys key key_len ref rows Extra explain select count(*) from seq_1_to_15_step_2 group by mod(seq,2); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE seq_1_to_15_step_2 index NULL PRIMARY 8 NULL 8 Using index; Using temporary; Using filesort -drop table seq_1_to_15_step_2; +create temporary table t1 select * from seq_1_to_3; +select count(NULL) from t1; +count(NULL) +0 +select count(NULL) from seq_1_to_3; +count(NULL) +0 diff --git a/storage/sequence/mysql-test/sequence/group_by.test b/storage/sequence/mysql-test/sequence/group_by.test index 870afd9ed89..b2e04037a8b 100644 --- a/storage/sequence/mysql-test/sequence/group_by.test +++ b/storage/sequence/mysql-test/sequence/group_by.test @@ -39,4 +39,9 @@ explain select count(*) from seq_1_to_15_step_2, seq_1_to_15_step_2 as t2; explain select count(*) from seq_1_to_15_step_2 where seq > 0; explain select count(*) from seq_1_to_15_step_2 group by mod(seq,2); -drop table seq_1_to_15_step_2; +# +# MDEV-9550 COUNT(NULL) returns incorrect result with sequence storage engine +# +create temporary table t1 select * from seq_1_to_3; +select count(NULL) from t1; +select count(NULL) from seq_1_to_3; diff --git a/storage/sequence/sequence.cc b/storage/sequence/sequence.cc index 7b20615b15f..8d9465f08c5 100644 --- a/storage/sequence/sequence.cc +++ b/storage/sequence/sequence.cc @@ -452,7 +452,11 @@ int ha_seq_group_by_handler::next_row() switch (item_sum->sum_func()) { case Item_sum::COUNT_FUNC: { - field->store((longlong) elements, 1); + Item *arg0= ((Item_sum*) item_sum)->get_arg(0); + if (arg0->basic_const_item() && arg0->is_null()) + field->store(0LL, 1); + else + field->store((longlong) elements, 1); break; } case Item_sum::SUM_FUNC: diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index 568d3695781..541ccf62260 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -634,8 +634,10 @@ protected: void SendFloat ( float v ) { SendDword ( sphF2DW(v) ); } }; +#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION template int CSphSEQuery::ParseArray<uint32> ( uint32 **, const char * ); template int CSphSEQuery::ParseArray<longlong> ( longlong **, const char * ); +#endif ////////////////////////////////////////////////////////////////////////////// @@ -1411,6 +1413,14 @@ static bool myismagic ( char c ) return c=='@'; } +static bool myisjson ( char c ) +{ + return + c=='.' || + c=='[' || + c==']'; +} + bool CSphSEQuery::ParseField ( char * sField ) { @@ -1622,7 +1632,7 @@ bool CSphSEQuery::ParseField ( char * sField ) break; tFilter.m_sAttrName = sValue; - while ( (*sValue) && ( myisattr(*sValue) || myismagic(*sValue) ) ) + while ( (*sValue) && ( myisattr(*sValue) || myismagic(*sValue) || myisjson(*sValue) ) ) sValue++; if ( !*sValue ) break; diff --git a/storage/sphinx/mysql-test/sphinx/sphinx.result b/storage/sphinx/mysql-test/sphinx/sphinx.result index 5fe11f4671b..3536ba42af8 100644 --- a/storage/sphinx/mysql-test/sphinx/sphinx.result +++ b/storage/sphinx/mysql-test/sphinx/sphinx.result @@ -4,17 +4,20 @@ id w q 1 2 test 2 2 test 4 1 test +5 1 test drop table ts; create table ts ( id bigint unsigned not null, w int not null, q varchar(255) not null, index(q) ) engine=sphinx connection="sphinx://127.0.0.1:SPHINXSEARCH_PORT/*"; select * from ts where q='test;filter=gid,1;mode=extended'; id w q -1 2421 test;filter=gid,1;mode=extended -2 2421 test;filter=gid,1;mode=extended +1 2379 test;filter=gid,1;mode=extended +2 2379 test;filter=gid,1;mode=extended +5 1412 test;filter=gid,1;mode=extended select * from ts where q='test|one;mode=extended'; id w q -1 3595 test|one;mode=extended -2 2460 test|one;mode=extended -4 1471 test|one;mode=extended +1 3579 test|one;mode=extended +2 2439 test|one;mode=extended +4 1456 test|one;mode=extended +5 1456 test|one;mode=extended select * from ts where q='test;offset=1;limit=1'; id w q 2 2 test;offset=1;limit=1 @@ -32,10 +35,11 @@ id w q gid _sph_count 2 1 1 0 3 1 2 0 4 1 2 0 +5 1 1 0 select * from ts where q=';groupby=attr:gid'; id w q gid _sph_count 3 1 ;groupby=attr:gid 2 2 -1 1 ;groupby=attr:gid 1 2 +1 1 ;groupby=attr:gid 1 3 explain select * from ts where q=';groupby=attr:gid'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE ts ref q q 257 const 3 Using where with pushed condition @@ -54,3 +58,20 @@ show status like "sphinx_word%"; Variable_name Value Sphinx_word_count 0 Sphinx_words +create table ts ( id bigint unsigned not null, w int not null, q varchar(255) not null, index(q) ) engine=sphinx connection="sphinx://127.0.0.1:SPHINXSEARCH_PORT/*"; +select * from ts where q=';filter=meta.foo_count,100'; +id w q +1 1 ;filter=meta.foo_count,100 +select * from ts where q='test;filter=meta.sub.int,7'; +id w q +5 1 test;filter=meta.sub.int,7 +select * from ts where q=';filter=meta.sub.list[0],4'; +id w q +select * from ts where q=';filter=meta.sub.list[1],4'; +id w q +5 1 ;filter=meta.sub.list[1],4 +select * from ts where q='test;range=meta.foo_count,100,500'; +id w q +1 2 test;range=meta.foo_count,100,500 +5 1 test;range=meta.foo_count,100,500 +drop table ts; diff --git a/storage/sphinx/mysql-test/sphinx/sphinx.test b/storage/sphinx/mysql-test/sphinx/sphinx.test index 126131209c5..fe388f7ddd2 100644 --- a/storage/sphinx/mysql-test/sphinx/sphinx.test +++ b/storage/sphinx/mysql-test/sphinx/sphinx.test @@ -32,3 +32,12 @@ drop table ts; show status like "sphinx_total%"; show status like "sphinx_word%"; + +--replace_result $SPHINXSEARCH_PORT SPHINXSEARCH_PORT +eval create table ts ( id bigint unsigned not null, w int not null, q varchar(255) not null, index(q) ) engine=sphinx connection="sphinx://127.0.0.1:$SPHINXSEARCH_PORT/*"; +select * from ts where q=';filter=meta.foo_count,100'; +select * from ts where q='test;filter=meta.sub.int,7'; +select * from ts where q=';filter=meta.sub.list[0],4'; +select * from ts where q=';filter=meta.sub.list[1],4'; +select * from ts where q='test;range=meta.foo_count,100,500'; +drop table ts; diff --git a/storage/sphinx/mysql-test/sphinx/testdata.xml b/storage/sphinx/mysql-test/sphinx/testdata.xml index e0d7394190f..7ef05bce808 100644 --- a/storage/sphinx/mysql-test/sphinx/testdata.xml +++ b/storage/sphinx/mysql-test/sphinx/testdata.xml @@ -5,12 +5,14 @@ <sphinx:field name="title"/> <sphinx:field name="content"/> <sphinx:attr name="gid" type="int"/> +<sphinx:attr name="meta" type="json"/> </sphinx:schema> <sphinx:document id="1"> <title>test one</title> <content>this is my test document number one. also checking search within phrases.</content> <gid>1</gid> +<meta>{ "foo_count": 100 }</meta> </sphinx:document> <sphinx:document id="2"> @@ -31,5 +33,12 @@ <gid>2</gid> </sphinx:document> +<sphinx:document id="5"> +<title>doc number five</title> +<content>this is to test json filtering</content> +<gid>1</gid> +<meta>{ "foo_count": 200, "sub": { "list": [ 3, 4 ], "int": 7 } }</meta> +</sphinx:document> + </sphinx:docset> diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index c5c47064403..681a3fb144c 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -37,8 +37,6 @@ #include "spd_ping_table.h" #include "spd_malloc.h" -extern ulong *spd_db_att_thread_id; - extern handlerton *spider_hton_ptr; extern SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE]; pthread_mutex_t spider_conn_id_mutex; @@ -2269,9 +2267,7 @@ void *spider_bg_conn_action( my_thread_end(); DBUG_RETURN(NULL); } - pthread_mutex_lock(&LOCK_thread_count); - thd->thread_id = (*spd_db_att_thread_id)++; - pthread_mutex_unlock(&LOCK_thread_count); + thd->thread_id = next_thread_id(); #ifdef HAVE_PSI_INTERFACE mysql_thread_set_psi_id(thd->thread_id); #endif @@ -2782,9 +2778,7 @@ void *spider_bg_sts_action( #endif DBUG_RETURN(NULL); } - pthread_mutex_lock(&LOCK_thread_count); - thd->thread_id = (*spd_db_att_thread_id)++; - pthread_mutex_unlock(&LOCK_thread_count); + thd->thread_id = next_thread_id(); #ifdef HAVE_PSI_INTERFACE mysql_thread_set_psi_id(thd->thread_id); #endif @@ -3164,9 +3158,7 @@ void *spider_bg_crd_action( #endif DBUG_RETURN(NULL); } - pthread_mutex_lock(&LOCK_thread_count); - thd->thread_id = (*spd_db_att_thread_id)++; - pthread_mutex_unlock(&LOCK_thread_count); + thd->thread_id = next_thread_id(); #ifdef HAVE_PSI_INTERFACE mysql_thread_set_psi_id(thd->thread_id); #endif @@ -3653,9 +3645,7 @@ void *spider_bg_mon_action( my_thread_end(); DBUG_RETURN(NULL); } - pthread_mutex_lock(&LOCK_thread_count); - thd->thread_id = (*spd_db_att_thread_id)++; - pthread_mutex_unlock(&LOCK_thread_count); + thd->thread_id = next_thread_id(); #ifdef HAVE_PSI_INTERFACE mysql_thread_set_psi_id(thd->thread_id); #endif diff --git a/storage/spider/spd_copy_tables.cc b/storage/spider/spd_copy_tables.cc index c01549f8e99..7e7845635af 100644 --- a/storage/spider/spd_copy_tables.cc +++ b/storage/spider/spd_copy_tables.cc @@ -81,7 +81,7 @@ int spider_udf_set_copy_tables_param_default( #define SPIDER_PARAM_STR(title_name, param_name) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (!copy_tables->param_name) \ { \ if ((copy_tables->param_name = spider_get_string_between_quote( \ @@ -94,14 +94,14 @@ int spider_udf_set_copy_tables_param_default( MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"=%s", copy_tables->param_name)); \ + DBUG_PRINT("info",("spider " title_name "=%s", copy_tables->param_name)); \ } \ break; \ } #define SPIDER_PARAM_HINT_WITH_MAX(title_name, param_name, check_length, max_size, min_val, max_val) \ if (!strncasecmp(tmp_ptr, title_name, check_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ DBUG_PRINT("info",("spider max_size=%d", max_size)); \ int hint_num = atoi(tmp_ptr + check_length) - 1; \ DBUG_PRINT("info",("spider hint_num=%d", hint_num)); \ @@ -131,7 +131,7 @@ int spider_udf_set_copy_tables_param_default( MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"[%d]=%d", hint_num, \ + DBUG_PRINT("info",("spider " title_name "[%d]=%d", hint_num, \ copy_tables->param_name[hint_num])); \ } else { \ error_num = ER_SPIDER_INVALID_UDF_PARAM_NUM; \ @@ -144,7 +144,7 @@ int spider_udf_set_copy_tables_param_default( #define SPIDER_PARAM_INT_WITH_MAX(title_name, param_name, min_val, max_val) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (copy_tables->param_name == -1) \ { \ if ((tmp_ptr2 = spider_get_string_between_quote( \ @@ -161,14 +161,14 @@ int spider_udf_set_copy_tables_param_default( MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"=%d", copy_tables->param_name)); \ + DBUG_PRINT("info",("spider " title_name "=%d", copy_tables->param_name)); \ } \ break; \ } #define SPIDER_PARAM_INT(title_name, param_name, min_val) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (copy_tables->param_name == -1) \ { \ if ((tmp_ptr2 = spider_get_string_between_quote( \ @@ -183,14 +183,14 @@ int spider_udf_set_copy_tables_param_default( MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"=%d", copy_tables->param_name)); \ + DBUG_PRINT("info",("spider " title_name "=%d", copy_tables->param_name)); \ } \ break; \ } #define SPIDER_PARAM_LONGLONG(title_name, param_name, min_val) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (copy_tables->param_name == -1) \ { \ if ((tmp_ptr2 = spider_get_string_between_quote( \ @@ -206,7 +206,7 @@ int spider_udf_set_copy_tables_param_default( MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"=%lld", \ + DBUG_PRINT("info",("spider " title_name "=%lld", \ copy_tables->param_name)); \ } \ break; \ diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index 9f46e55ca09..69a05dc94fb 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -737,7 +737,8 @@ int spider_db_errorno( "to %ld: %d %s\n", l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - current_thd->thread_id, error_num, conn->db_conn->get_error()); + (ulong) current_thd->thread_id, error_num, + conn->db_conn->get_error()); } if (!conn->mta_conn_mutex_unlock_later) { @@ -757,7 +758,8 @@ int spider_db_errorno( "to %ld: %d %s\n", l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - current_thd->thread_id, error_num, conn->db_conn->get_error()); + (ulong) current_thd->thread_id, error_num, + conn->db_conn->get_error()); } if (!conn->mta_conn_mutex_unlock_later) { diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index c4da0194357..a41a943cd04 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -1717,7 +1717,7 @@ int spider_db_mysql::exec_query( l_time->tm_hour, l_time->tm_min, l_time->tm_sec, security_ctx->user ? security_ctx->user : "system user", security_ctx->host_or_ip, - thd->thread_id, + (ulong) thd->thread_id, tmp_query_str.c_ptr_safe()); } if (log_result_error_with_sql & 1) @@ -1731,7 +1731,7 @@ int spider_db_mysql::exec_query( "sql: %s\n", l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - thd->thread_id, conn->tgt_host, db_conn->thread_id, + (ulong) thd->thread_id, conn->tgt_host, (ulong) db_conn->thread_id, tmp_query_str.c_ptr_safe()); } } @@ -1745,7 +1745,7 @@ int spider_db_mysql::exec_query( "affected_rows: %llu id: %llu status: %u warning_count: %u\n", l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - conn->tgt_host, db_conn->thread_id, thd->thread_id, + conn->tgt_host, (ulong) db_conn->thread_id, (ulong) thd->thread_id, db_conn->affected_rows, db_conn->insert_id, db_conn->server_status, db_conn->warning_count); if (spider_param_log_result_errors() >= 3) @@ -1760,7 +1760,7 @@ int spider_db_mysql::exec_query( "affected_rows: %llu id: %llu status: %u warning_count: %u\n", l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - conn->tgt_host, db_conn->thread_id, thd->thread_id, + conn->tgt_host, (ulong) db_conn->thread_id, (ulong) thd->thread_id, db_conn->affected_rows, db_conn->insert_id, db_conn->server_status, db_conn->warning_count); } @@ -1889,8 +1889,8 @@ void spider_db_mysql::print_warnings( "from [%s] %ld to %ld: %s %s %s\n", l_time->tm_year + 1900, l_time->tm_mon + 1, l_time->tm_mday, l_time->tm_hour, l_time->tm_min, l_time->tm_sec, - conn->tgt_host, db_conn->thread_id, - current_thd->thread_id, row[0], row[1], row[2]); + conn->tgt_host, (ulong) db_conn->thread_id, + (ulong) current_thd->thread_id, row[0], row[1], row[2]); row = mysql_fetch_row(res); } if (res) @@ -4041,7 +4041,7 @@ int spider_db_mysql_util::open_item_func( { Item_func_conv_charset *item_func_conv_charset = (Item_func_conv_charset *)item_func; - CHARSET_INFO *conv_charset = item_func_conv_charset->conv_charset; + CHARSET_INFO *conv_charset = item_func_conv_charset->collation.collation; uint cset_length = strlen(conv_charset->csname); if (str->reserve(SPIDER_SQL_USING_LEN + cset_length)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); diff --git a/storage/spider/spd_direct_sql.cc b/storage/spider/spd_direct_sql.cc index 7de31e34e94..c0eb7806bb0 100644 --- a/storage/spider/spd_direct_sql.cc +++ b/storage/spider/spd_direct_sql.cc @@ -896,7 +896,7 @@ error: #define SPIDER_PARAM_STR(title_name, param_name) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (!direct_sql->param_name) \ { \ if ((direct_sql->param_name = spider_get_string_between_quote( \ @@ -909,14 +909,14 @@ error: MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"=%s", direct_sql->param_name)); \ + DBUG_PRINT("info",("spider " title_name "=%s", direct_sql->param_name)); \ } \ break; \ } #define SPIDER_PARAM_HINT_WITH_MAX(title_name, param_name, check_length, max_size, min_val, max_val) \ if (!strncasecmp(tmp_ptr, title_name, check_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ DBUG_PRINT("info",("spider max_size=%d", max_size)); \ int hint_num = atoi(tmp_ptr + check_length) - 1; \ DBUG_PRINT("info",("spider hint_num=%d", hint_num)); \ @@ -946,7 +946,7 @@ error: MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"[%d]=%d", hint_num, \ + DBUG_PRINT("info",("spider " title_name "[%d]=%d", hint_num, \ direct_sql->param_name[hint_num])); \ } else { \ error_num = ER_SPIDER_INVALID_CONNECT_INFO_NUM; \ @@ -959,7 +959,7 @@ error: #define SPIDER_PARAM_INT_WITH_MAX(title_name, param_name, min_val, max_val) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (direct_sql->param_name == -1) \ { \ if ((tmp_ptr2 = spider_get_string_between_quote( \ @@ -976,7 +976,7 @@ error: MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"=%d", \ + DBUG_PRINT("info",("spider " title_name "=%d", \ (int) direct_sql->param_name)); \ } \ break; \ @@ -984,7 +984,7 @@ error: #define SPIDER_PARAM_INT(title_name, param_name, min_val) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (direct_sql->param_name == -1) \ { \ if ((tmp_ptr2 = spider_get_string_between_quote( \ @@ -999,14 +999,14 @@ error: MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"=%d", direct_sql->param_name)); \ + DBUG_PRINT("info",("spider " title_name "=%d", direct_sql->param_name)); \ } \ break; \ } #define SPIDER_PARAM_LONGLONG(title_name, param_name, min_val) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (direct_sql->param_name == -1) \ { \ if ((tmp_ptr2 = spider_get_string_between_quote( \ @@ -1022,7 +1022,7 @@ error: MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"=%lld", \ + DBUG_PRINT("info",("spider " title_name "=%lld", \ direct_sql->param_name)); \ } \ break; \ diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index a9aea90dcdd..d981dc6002b 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -41,7 +41,6 @@ #include "spd_direct_sql.h" #include "spd_malloc.h" -ulong *spd_db_att_thread_id; #ifdef SPIDER_XID_USES_xid_cache_iterate #else #ifdef XID_CACHE_IS_SPLITTED @@ -1500,7 +1499,7 @@ static int spider_set_ll_value( #define SPIDER_PARAM_STR(title_name, param_name) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (!share->param_name) \ { \ if ((share->param_name = spider_get_string_between_quote( \ @@ -1512,7 +1511,7 @@ static int spider_set_ll_value( MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"=%s", share->param_name)); \ + DBUG_PRINT("info",("spider " title_name "=%s", share->param_name)); \ } \ break; \ } @@ -1521,7 +1520,7 @@ static int spider_set_ll_value( #define SPIDER_PARAM_STR_LIST(title_name, param_name) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (!share->param_name) \ { \ if ((tmp_ptr2 = spider_get_string_between_quote( \ @@ -1547,7 +1546,7 @@ static int spider_set_ll_value( #define SPIDER_PARAM_HINT(title_name, param_name, check_length, max_size, append_method) \ if (!strncasecmp(tmp_ptr, title_name, check_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ DBUG_PRINT("info",("spider max_size=%d", max_size)); \ int hint_num = atoi(tmp_ptr + check_length); \ DBUG_PRINT("info",("spider hint_num=%d", hint_num)); \ @@ -1566,7 +1565,7 @@ static int spider_set_ll_value( if ((error_num = \ append_method(&share->param_name[hint_num], hint_str))) \ goto error; \ - DBUG_PRINT("info",("spider "title_name"[%d]=%s", hint_num, \ + DBUG_PRINT("info",("spider " title_name "[%d]=%s", hint_num, \ share->param_name[hint_num].ptr())); \ } else { \ error_num = ER_SPIDER_INVALID_CONNECT_INFO_NUM; \ @@ -1579,7 +1578,7 @@ static int spider_set_ll_value( #define SPIDER_PARAM_NUMHINT(title_name, param_name, check_length, max_size, append_method) \ if (!strncasecmp(tmp_ptr, title_name, check_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ DBUG_PRINT("info",("spider max_size=%d", max_size)); \ int hint_num = atoi(tmp_ptr + check_length); \ DBUG_PRINT("info",("spider hint_num=%d", hint_num)); \ @@ -1598,7 +1597,7 @@ static int spider_set_ll_value( if ((error_num = \ append_method(&share->param_name[hint_num], hint_str))) \ goto error; \ - DBUG_PRINT("info",("spider "title_name"[%d]=%lld", hint_num, \ + DBUG_PRINT("info",("spider " title_name "[%d]=%lld", hint_num, \ share->param_name[hint_num])); \ } else { \ error_num = ER_SPIDER_INVALID_CONNECT_INFO_NUM; \ @@ -1613,7 +1612,7 @@ static int spider_set_ll_value( min_val, max_val) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (!share->param_name) \ { \ if ((tmp_ptr2 = spider_get_string_between_quote( \ @@ -1640,7 +1639,7 @@ static int spider_set_ll_value( min_val, max_val) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (!share->param_name) \ { \ if ((tmp_ptr2 = spider_get_string_between_quote( \ @@ -1665,7 +1664,7 @@ static int spider_set_ll_value( #define SPIDER_PARAM_INT_WITH_MAX(title_name, param_name, min_val, max_val) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (share->param_name == -1) \ { \ if ((tmp_ptr2 = spider_get_string_between_quote( \ @@ -1682,14 +1681,14 @@ static int spider_set_ll_value( MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"=%d", share->param_name)); \ + DBUG_PRINT("info",("spider " title_name "=%d", share->param_name)); \ } \ break; \ } #define SPIDER_PARAM_INT(title_name, param_name, min_val) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (share->param_name == -1) \ { \ if ((tmp_ptr2 = spider_get_string_between_quote( \ @@ -1704,14 +1703,14 @@ static int spider_set_ll_value( MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"=%d", share->param_name)); \ + DBUG_PRINT("info",("spider " title_name "=%d", share->param_name)); \ } \ break; \ } #define SPIDER_PARAM_DOUBLE(title_name, param_name, min_val) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (share->param_name == -1) \ { \ if ((tmp_ptr2 = spider_get_string_between_quote( \ @@ -1726,14 +1725,14 @@ static int spider_set_ll_value( MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"=%f", share->param_name)); \ + DBUG_PRINT("info",("spider " title_name "=%f", share->param_name)); \ } \ break; \ } #define SPIDER_PARAM_LONGLONG(title_name, param_name, min_val) \ if (!strncasecmp(tmp_ptr, title_name, title_length)) \ { \ - DBUG_PRINT("info",("spider "title_name" start")); \ + DBUG_PRINT("info",("spider " title_name " start")); \ if (share->param_name == -1) \ { \ if ((tmp_ptr2 = spider_get_string_between_quote( \ @@ -1748,7 +1747,7 @@ static int spider_set_ll_value( MYF(0), tmp_ptr); \ goto error; \ } \ - DBUG_PRINT("info",("spider "title_name"=%lld", share->param_name)); \ + DBUG_PRINT("info",("spider " title_name "=%lld", share->param_name)); \ } \ break; \ } @@ -6327,8 +6326,6 @@ int spider_db_init( #ifdef _WIN32 HMODULE current_module = GetModuleHandle(NULL); - spd_db_att_thread_id = (ulong *) - GetProcAddress(current_module, "?thread_id@@3KA"); #ifdef SPIDER_XID_USES_xid_cache_iterate #else #ifdef XID_CACHE_IS_SPLITTED @@ -6362,7 +6359,6 @@ int spider_db_init( spd_abort_loop = (bool volatile *) GetProcAddress(current_module, "?abort_loop@@3_NC"); #else - spd_db_att_thread_id = &thread_id; #ifdef SPIDER_XID_USES_xid_cache_iterate #else #ifdef XID_CACHE_IS_SPLITTED diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index d7127fa0084..b376265c1e7 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -2683,7 +2683,8 @@ int spider_initinal_xa_recover( FALSE, open_tables_backup, TRUE, &error_num)) ) goto error_open_table; - init_read_record(read_record, thd, table_xa, NULL, TRUE, FALSE, FALSE); + init_read_record(read_record, thd, table_xa, NULL, NULL, TRUE, FALSE, + FALSE); } SPD_INIT_ALLOC_ROOT(&mem_root, 4096, 0, MYF(MY_WME)); while ((!(read_record->read_record(read_record))) && cnt < (int) len) diff --git a/storage/tokudb/CMakeLists.txt b/storage/tokudb/CMakeLists.txt index 2b605d14677..a64974d7330 100644 --- a/storage/tokudb/CMakeLists.txt +++ b/storage/tokudb/CMakeLists.txt @@ -1,18 +1,15 @@ SET(TOKUDB_VERSION 5.6.26-74.0) # PerconaFT only supports x86-64 and cmake-2.8.9+ -IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND - NOT CMAKE_VERSION VERSION_LESS "2.8.9") +IF(CMAKE_VERSION VERSION_LESS "2.8.9") + MESSAGE(STATUS "CMake 2.8.9 or higher is required by TokuDB") +ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR + CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64") CHECK_CXX_SOURCE_COMPILES( " struct a {int b; int c; }; struct a d = { .b=1, .c=2 }; int main() { return 0; } " TOKUDB_OK) -ELSE() - IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND - CMAKE_VERSION VERSION_LESS "2.8.9") - MESSAGE(STATUS "CMake 2.8.9 or higher is required by TokuDB") - ENDIF() ENDIF() IF(NOT TOKUDB_OK) @@ -34,7 +31,7 @@ MY_CHECK_AND_SET_COMPILER_FLAG("-Wno-vla") MY_CHECK_AND_SET_COMPILER_FLAG("-Wno-vla" DEBUG) ############################################ -SET(TOKUDB_DEB_FILES "usr/lib/mysql/plugin/ha_tokudb.so\netc/mysql/conf.d/tokudb.cnf\nusr/bin/tokuftdump\nusr/share/doc/mariadb-server-10.2/README-TOKUDB\nusr/share/doc/mariadb-server-10.2/README.md" PARENT_SCOPE) +SET(TOKUDB_DEB_FILES "usr/lib/mysql/plugin/ha_tokudb.so\netc/mysql/conf.d/tokudb.cnf\nusr/bin/tokuftdump" PARENT_SCOPE) MARK_AS_ADVANCED(BUILDNAME) MARK_AS_ADVANCED(BUILD_TESTING) MARK_AS_ADVANCED(CMAKE_TOKUDB_REVISION) diff --git a/storage/tokudb/PerconaFT/buildheader/CMakeLists.txt b/storage/tokudb/PerconaFT/buildheader/CMakeLists.txt index 5da3c98ff48..6d5cbb94358 100644 --- a/storage/tokudb/PerconaFT/buildheader/CMakeLists.txt +++ b/storage/tokudb/PerconaFT/buildheader/CMakeLists.txt @@ -1,6 +1,6 @@ set_directory_properties(PROPERTIES INCLUDE_DIRECTORIES "") -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/runcat.sh" "#!/bin/bash +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/runcat.sh" "#!/bin/sh out=$1; shift exec \"$@\" >$out") @@ -8,7 +8,7 @@ add_executable(make_tdb make_tdb.cc) set_property(TARGET make_tdb APPEND PROPERTY COMPILE_DEFINITIONS _GNU_SOURCE) add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/db.h" - COMMAND bash runcat.sh "${CMAKE_CURRENT_BINARY_DIR}/db.h" $<TARGET_FILE:make_tdb> + COMMAND sh runcat.sh "${CMAKE_CURRENT_BINARY_DIR}/db.h" $<TARGET_FILE:make_tdb> DEPENDS make_tdb) add_custom_target(install_tdb_h DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/db.h") diff --git a/storage/tokudb/PerconaFT/cmake_modules/TokuFeatureDetection.cmake b/storage/tokudb/PerconaFT/cmake_modules/TokuFeatureDetection.cmake index 4c5004cd6a5..e3c900fbadb 100644 --- a/storage/tokudb/PerconaFT/cmake_modules/TokuFeatureDetection.cmake +++ b/storage/tokudb/PerconaFT/cmake_modules/TokuFeatureDetection.cmake @@ -93,7 +93,7 @@ if (NOT HAVE_BACKTRACE_WITHOUT_EXECINFO) if (HAVE_BACKTRACE_WITH_EXECINFO) list(APPEND EXTRA_SYSTEM_LIBS execinfo) else () - message(FATAL_ERROR "Cannot find backtrace(), even with -lexecinfo.") + message(WARNING "Cannot find backtrace(), even with -lexecinfo.") endif () endif () diff --git a/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar_hidden.result b/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar_hidden.result index 640c7badc71..6269b8f2d71 100644 --- a/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar_hidden.result +++ b/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar_hidden.result @@ -182,14 +182,14 @@ a b c d e f 3 30 200 2000 20000 200000 explain select * from t1 where b > "0"; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index b b NULL NULL NULL; Using where; Using index +1 SIMPLE t1 <type> b b NULL NULL NULL; Using where; Using index select * from t1 where b > "0"; a b c d e f 2 20 100 1000 10000 100000 3 30 200 2000 20000 200000 explain select * from t1 where d > "0"; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index d d NULL NULL NULL; Using where; Using index +1 SIMPLE t1 <type> d d NULL NULL NULL; Using where; Using index select * from t1 where d > "0"; a b c d e f 2 20 100 1000 10000 100000 diff --git a/storage/tokudb/mysql-test/tokudb/t/change_column_bin.py b/storage/tokudb/mysql-test/tokudb/t/change_column_bin.py index 0ddee301d1b..b94a80ec7be 100644 --- a/storage/tokudb/mysql-test/tokudb/t/change_column_bin.py +++ b/storage/tokudb/mysql-test/tokudb/t/change_column_bin.py @@ -24,6 +24,7 @@ def gen_test(n): def main(): print "# this test is generated by change_bin.py" print "# test binary expansion is hot" + print "--source include/big_test.inc" print "--disable_warnings" print "DROP TABLE IF EXISTS t,ti;" print "--enable_warnings" diff --git a/storage/tokudb/mysql-test/tokudb/t/change_column_bin.test b/storage/tokudb/mysql-test/tokudb/t/change_column_bin.test index 0365c155302..6053a263cf0 100644 --- a/storage/tokudb/mysql-test/tokudb/t/change_column_bin.test +++ b/storage/tokudb/mysql-test/tokudb/t/change_column_bin.test @@ -1,6 +1,7 @@ source include/have_tokudb.inc; # this test is generated by change_bin.py # test binary expansion is hot +--source include/big_test.inc --disable_warnings DROP TABLE IF EXISTS t,ti; --enable_warnings diff --git a/storage/tokudb/mysql-test/tokudb/t/change_column_char.py b/storage/tokudb/mysql-test/tokudb/t/change_column_char.py index 99d99d1c017..7481d9092f2 100644 --- a/storage/tokudb/mysql-test/tokudb/t/change_column_char.py +++ b/storage/tokudb/mysql-test/tokudb/t/change_column_char.py @@ -24,6 +24,7 @@ def gen_test(n): def main(): print "# this test is generated by change_char.py" print "# test char expansion" + print "--source include/big_test.inc" print "--disable_warnings" print "DROP TABLE IF EXISTS t,ti;" print "--enable_warnings" diff --git a/storage/tokudb/mysql-test/tokudb/t/change_column_char.test b/storage/tokudb/mysql-test/tokudb/t/change_column_char.test index 8a0b0a9abd8..977420ad07e 100644 --- a/storage/tokudb/mysql-test/tokudb/t/change_column_char.test +++ b/storage/tokudb/mysql-test/tokudb/t/change_column_char.test @@ -1,6 +1,7 @@ source include/have_tokudb.inc; # this test is generated by change_char.py # test char expansion +--source include/big_test.inc --disable_warnings DROP TABLE IF EXISTS t,ti; --enable_warnings diff --git a/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar_hidden.test b/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar_hidden.test index d1be871c7d2..e9bb18a586e 100644 --- a/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar_hidden.test +++ b/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar_hidden.test @@ -82,11 +82,11 @@ alter table t1 add key d(d,a) clustering=yes, add key b(b) clustering=yes; explain select * from t1; select * from t1; ---replace_column 7 NULL 9 NULL; +--replace_column 4 <type> 7 NULL 9 NULL; explain select * from t1 where b > "0"; select * from t1 where b > "0"; ---replace_column 7 NULL 9 NULL; +--replace_column 4 <type> 7 NULL 9 NULL; explain select * from t1 where d > "0"; select * from t1 where d > "0"; diff --git a/storage/xtradb/btr/btr0btr.cc b/storage/xtradb/btr/btr0btr.cc index c8018e6582b..caa35d31109 100644 --- a/storage/xtradb/btr/btr0btr.cc +++ b/storage/xtradb/btr/btr0btr.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. Copyright (c) 2014, 2015, MariaDB Corporation @@ -796,6 +796,10 @@ btr_root_get( buf_block_t* root = btr_root_block_get(index, RW_X_LATCH, mtr); + if (root && root->page.encrypted == true) { + root = NULL; + } + return(root ? buf_block_get_frame(root) : NULL); } @@ -2281,7 +2285,7 @@ the tuple. It is assumed that mtr contains an x-latch on the tree. NOTE that the operation of this function must always succeed, we cannot reverse it: therefore enough free disk space must be guaranteed to be available before this function is called. -@return inserted record */ +@return inserted record or NULL if run out of space */ UNIV_INTERN rec_t* btr_root_raise_and_insert( @@ -2342,6 +2346,11 @@ btr_root_raise_and_insert( level = btr_page_get_level(root, mtr); new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr); + + if (new_block == NULL && os_has_said_disk_full) { + return(NULL); + } + new_page = buf_block_get_frame(new_block); new_page_zip = buf_block_get_page_zip(new_block); ut_a(!new_page_zip == !root_page_zip); @@ -3126,7 +3135,7 @@ this function is called. NOTE: jonaso added support for calling function with tuple == NULL which cause it to only split a page. -@return inserted record */ +@return inserted record or NULL if run out of space */ UNIV_INTERN rec_t* btr_page_split_and_insert( @@ -3240,9 +3249,18 @@ func_start: } } + DBUG_EXECUTE_IF("disk_is_full", + os_has_said_disk_full = true; + return(NULL);); + /* 2. Allocate a new page to the index */ new_block = btr_page_alloc(cursor->index, hint_page_no, direction, btr_page_get_level(page, mtr), mtr, mtr); + + if (new_block == NULL && os_has_said_disk_full) { + return(NULL); + } + new_page = buf_block_get_frame(new_block); new_page_zip = buf_block_get_page_zip(new_block); btr_page_create(new_block, new_page_zip, cursor->index, diff --git a/storage/xtradb/btr/btr0cur.cc b/storage/xtradb/btr/btr0cur.cc index c949bcae476..5bb94dfce2a 100644 --- a/storage/xtradb/btr/btr0cur.cc +++ b/storage/xtradb/btr/btr0cur.cc @@ -1785,6 +1785,10 @@ btr_cur_pessimistic_insert( flags, cursor, offsets, heap, entry, n_ext, mtr); } + if (*rec == NULL && os_has_said_disk_full) { + return(DB_OUT_OF_FILE_SPACE); + } + ut_ad(page_rec_get_next(btr_cur_get_rec(cursor)) == *rec); if (!(flags & BTR_NO_LOCKING_FLAG)) { diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc index 72d078b3139..556096ca7e4 100644 --- a/storage/xtradb/buf/buf0buf.cc +++ b/storage/xtradb/buf/buf0buf.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -4790,10 +4790,10 @@ corrupt: ib_push_warning(innobase_get_trx(), DB_DECRYPTION_FAILED, "Table in tablespace %lu encrypted." - "However key management plugin or used key_id %lu is not found or" + "However key management plugin or used key_id %u is not found or" " used encryption algorithm or method does not match." " Can't continue opening the table.", - bpage->key_version); + (ulint)bpage->space, bpage->key_version); if (bpage->space > TRX_SYS_SPACE) { if (corrupted) { @@ -4827,17 +4827,26 @@ corrupt: block = NULL; update_ibuf_bitmap = FALSE; - } else { block = (buf_block_t *) bpage; update_ibuf_bitmap = TRUE; } - ibuf_merge_or_delete_for_page( - block, bpage->space, - bpage->offset, buf_page_get_zip_size(bpage), - update_ibuf_bitmap); + if (bpage && bpage->encrypted) { + fprintf(stderr, + "InnoDB: Warning: Table in tablespace %lu encrypted." + "However key management plugin or used key_id %u is not found or" + " used encryption algorithm or method does not match." + " Can't continue opening the table.\n", + (ulint)bpage->space, bpage->key_version); + } else { + ibuf_merge_or_delete_for_page( + block, bpage->space, + bpage->offset, buf_page_get_zip_size(bpage), + update_ibuf_bitmap); + } + } } else { /* io_type == BUF_IO_WRITE */ @@ -6333,6 +6342,7 @@ buf_page_decrypt_after_read( bool page_compressed = fil_page_is_compressed(dst_frame); bool page_compressed_encrypted = fil_page_is_compressed_encrypted(dst_frame); buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + bool success = true; /* If page is encrypted read post-encryption checksum */ if (!page_compressed_encrypted && key_version != 0) { @@ -6391,16 +6401,21 @@ buf_page_decrypt_after_read( } /* decrypt using crypt_buf to dst_frame */ - fil_space_decrypt(bpage->space, - slot->crypt_buf, - size, - dst_frame); + byte* res = fil_space_decrypt(bpage->space, + slot->crypt_buf, + size, + dst_frame); + + if (!res) { + bpage->encrypted = true; + success = false; + } #ifdef UNIV_DEBUG fil_page_type_validate(dst_frame); #endif } - if (page_compressed_encrypted) { + if (page_compressed_encrypted && success) { if (!slot) { slot = buf_pool_reserve_tmp_slot(buf_pool, page_compressed); } @@ -6413,11 +6428,11 @@ buf_page_decrypt_after_read( dst_frame, size, &bpage->write_size); - } #ifdef UNIV_DEBUG - fil_page_type_validate(dst_frame); + fil_page_type_validate(dst_frame); #endif + } /* Mark this slot as free */ if (slot) { @@ -6427,5 +6442,5 @@ buf_page_decrypt_after_read( bpage->key_version = key_version; - return (TRUE); + return (success); } diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc index 037d94dd514..5d64b75784a 100644 --- a/storage/xtradb/buf/buf0flu.cc +++ b/storage/xtradb/buf/buf0flu.cc @@ -2251,7 +2251,7 @@ Clears up tail of the LRU lists: * Flush dirty pages at the tail of LRU to the disk The depth to which we scan each buffer pool is controlled by dynamic config parameter innodb_LRU_scan_depth. -@return total pages flushed */ +@return number of pages flushed */ UNIV_INTERN ulint buf_flush_LRU_tail(void) @@ -2671,19 +2671,24 @@ static void page_cleaner_adapt_lru_sleep_time( /*==============================*/ - ulint* lru_sleep_time) /*!< in/out: desired page cleaner thread sleep + ulint* lru_sleep_time, /*!< in/out: desired page cleaner thread sleep time for LRU flushes */ + ulint lru_n_flushed) /*!< in: number of flushed in previous batch */ + { ulint free_len = buf_get_total_free_list_length(); ulint max_free_len = srv_LRU_scan_depth * srv_buf_pool_instances; - if (free_len < max_free_len / 100) { + if (free_len < max_free_len / 100 && lru_n_flushed) { - /* Free lists filled less than 1%, no sleep */ + /* Free lists filled less than 1% + and iteration was able to flush, no sleep */ *lru_sleep_time = 0; - } else if (free_len > max_free_len / 5) { + } else if (free_len > max_free_len / 5 + || (free_len < max_free_len / 100 && lru_n_flushed == 0)) { - /* Free lists filled more than 20%, sleep a bit more */ + /* Free lists filled more than 20% + or no pages flushed in previous batch, sleep a bit more */ *lru_sleep_time += 50; if (*lru_sleep_time > srv_cleaner_max_lru_time) *lru_sleep_time = srv_cleaner_max_lru_time; @@ -2885,6 +2890,7 @@ DECLARE_THREAD(buf_flush_lru_manager_thread)( { ulint next_loop_time = ut_time_ms() + 1000; ulint lru_sleep_time = srv_cleaner_max_lru_time; + ulint lru_n_flushed = 1; #ifdef UNIV_PFS_THREAD pfs_register_thread(buf_lru_manager_thread_key); @@ -2911,11 +2917,11 @@ DECLARE_THREAD(buf_flush_lru_manager_thread)( page_cleaner_sleep_if_needed(next_loop_time); - page_cleaner_adapt_lru_sleep_time(&lru_sleep_time); + page_cleaner_adapt_lru_sleep_time(&lru_sleep_time, lru_n_flushed); next_loop_time = ut_time_ms() + lru_sleep_time; - buf_flush_LRU_tail(); + lru_n_flushed = buf_flush_LRU_tail(); } buf_lru_manager_is_active = false; diff --git a/storage/xtradb/dict/dict0boot.cc b/storage/xtradb/dict/dict0boot.cc index 94a3af2852b..0a21264e23d 100644 --- a/storage/xtradb/dict/dict0boot.cc +++ b/storage/xtradb/dict/dict0boot.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -456,27 +457,29 @@ dict_boot(void) /* Initialize the insert buffer table and index for each tablespace */ - ibuf_init_at_db_start(); - dberr_t err = DB_SUCCESS; - if (srv_read_only_mode && !ibuf_is_empty()) { + err = ibuf_init_at_db_start(); - ib_logf(IB_LOG_LEVEL_ERROR, - "Change buffer must be empty when --innodb-read-only " - "is set!"); + if (err == DB_SUCCESS) { + if (srv_read_only_mode && !ibuf_is_empty()) { - err = DB_ERROR; - } else { - /* Load definitions of other indexes on system tables */ + ib_logf(IB_LOG_LEVEL_ERROR, + "Change buffer must be empty when --innodb-read-only " + "is set!"); - dict_load_sys_table(dict_sys->sys_tables); - dict_load_sys_table(dict_sys->sys_columns); - dict_load_sys_table(dict_sys->sys_indexes); - dict_load_sys_table(dict_sys->sys_fields); - } + err = DB_ERROR; + } else { + /* Load definitions of other indexes on system tables */ - mutex_exit(&(dict_sys->mutex)); + dict_load_sys_table(dict_sys->sys_tables); + dict_load_sys_table(dict_sys->sys_columns); + dict_load_sys_table(dict_sys->sys_indexes); + dict_load_sys_table(dict_sys->sys_fields); + } + + mutex_exit(&(dict_sys->mutex)); + } return(err); } diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc index f6621473077..206038d36c9 100644 --- a/storage/xtradb/dict/dict0dict.cc +++ b/storage/xtradb/dict/dict0dict.cc @@ -1659,10 +1659,13 @@ dict_table_rename_in_cache( to preserve the original table name in constraints which reference it */ { + dberr_t err; dict_foreign_t* foreign; dict_index_t* index; ulint fold; char old_name[MAX_FULL_NAME_LEN + 1]; + os_file_type_t ftype; + ibool exists; ut_ad(mutex_own(&(dict_sys->mutex))); @@ -1700,8 +1703,6 @@ dict_table_rename_in_cache( .ibd file and rebuild the .isl file if needed. */ if (dict_table_is_discarded(table)) { - os_file_type_t type; - ibool exists; char* filepath; ut_ad(table->space != TRX_SYS_SPACE); @@ -1720,7 +1721,7 @@ dict_table_rename_in_cache( fil_delete_tablespace(table->space, BUF_REMOVE_ALL_NO_WRITE); /* Delete any temp file hanging around. */ - if (os_file_status(filepath, &exists, &type) + if (os_file_status(filepath, &exists, &ftype) && exists && !os_file_delete_if_exists(innodb_file_temp_key, filepath)) { @@ -1732,8 +1733,6 @@ dict_table_rename_in_cache( mem_free(filepath); } else if (table->space != TRX_SYS_SPACE) { - char* new_path = NULL; - if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: trying to rename a" @@ -1747,34 +1746,43 @@ dict_table_rename_in_cache( } return(DB_ERROR); + } - } else if (DICT_TF_HAS_DATA_DIR(table->flags)) { - char* old_path; - - old_path = fil_space_get_first_path(table->space); + char* new_path = NULL; + char* old_path = fil_space_get_first_path(table->space); + if (DICT_TF_HAS_DATA_DIR(table->flags)) { new_path = os_file_make_new_pathname( old_path, new_name); - mem_free(old_path); - - dberr_t err = fil_create_link_file( - new_name, new_path); - + err = fil_create_link_file(new_name, new_path); if (err != DB_SUCCESS) { mem_free(new_path); + mem_free(old_path); return(DB_TABLESPACE_EXISTS); } + } else { + new_path = fil_make_ibd_name(new_name, false); + } + + /* New filepath must not exist. */ + err = fil_rename_tablespace_check( + table->space, old_path, new_path, false); + if (err != DB_SUCCESS) { + mem_free(old_path); + mem_free(new_path); + return(err); } ibool success = fil_rename_tablespace( old_name, table->space, new_name, new_path); + mem_free(old_path); + mem_free(new_path); + /* If the tablespace is remote, a new .isl file was created If success, delete the old one. If not, delete the new one. */ - if (new_path) { - - mem_free(new_path); + if (DICT_TF_HAS_DATA_DIR(table->flags)) { fil_delete_link_file(success ? old_name : new_name); } diff --git a/storage/xtradb/fil/fil0crypt.cc b/storage/xtradb/fil/fil0crypt.cc index 100f304bf6f..ceffa950739 100644 --- a/storage/xtradb/fil/fil0crypt.cc +++ b/storage/xtradb/fil/fil0crypt.cc @@ -1,6 +1,6 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (C) 2014, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -662,7 +662,7 @@ fil_space_encrypt( return src_frame; } - ut_ad(crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF); + ut_a(crypt_data != NULL && crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF); byte* tmp = fil_encrypt_buf(crypt_data, space, offset, lsn, src_frame, zip_size, dst_frame); @@ -712,21 +712,37 @@ fil_space_decrypt( ulint page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE); uint key_version = mach_read_from_4(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); bool page_compressed = (page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED); - + ulint offset = mach_read_from_4(src_frame + FIL_PAGE_OFFSET); + ulint space = mach_read_from_4(src_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); + ib_uint64_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN); *err = DB_SUCCESS; if (key_version == ENCRYPTION_KEY_NOT_ENCRYPTED) { return false; } - ut_ad(crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF); + if (crypt_data == NULL) { + if (!(space == 0 && offset == 0) && key_version != 0) { + /* FIL_PAGE_FILE_FLUSH_LSN field i.e. + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + should be only defined for the + first page in a system tablespace + data file (ibdata*, not *.ibd), if not + clear it. */ +#ifdef UNIV_DEBUG + ib_logf(IB_LOG_LEVEL_WARN, + "Page on space %lu offset %lu has key_version %u" + " when it shoud be undefined.", + space, offset, key_version); +#endif + mach_write_to_4(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0); + } + return false; + } - /* read space & offset & lsn */ - ulint space = mach_read_from_4( - src_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - ulint offset = mach_read_from_4( - src_frame + FIL_PAGE_OFFSET); - ib_uint64_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN); + ut_a(crypt_data != NULL && crypt_data->encryption != FIL_SPACE_ENCRYPTION_OFF); + + /* read space & lsn */ ulint header_len = FIL_PAGE_DATA; if (page_compressed) { @@ -799,6 +815,7 @@ fil_space_decrypt( byte* src_frame) /*!< in/out: page buffer */ { dberr_t err = DB_SUCCESS; + byte* res = NULL; bool encrypted = fil_space_decrypt( fil_space_get_crypt_data(space), @@ -807,13 +824,17 @@ fil_space_decrypt( src_frame, &err); - if (encrypted) { - /* Copy the decrypted page back to page buffer, not - really any other options. */ - memcpy(src_frame, tmp_frame, page_size); + if (err == DB_SUCCESS) { + if (encrypted) { + /* Copy the decrypted page back to page buffer, not + really any other options. */ + memcpy(src_frame, tmp_frame, page_size); + } + + res = src_frame; } - return src_frame; + return res; } /****************************************************************** @@ -2294,6 +2315,10 @@ fil_crypt_set_thread_cnt( /*=====================*/ uint new_cnt) /*!< in: New key rotation thread count */ { + if (!fil_crypt_threads_inited) { + fil_crypt_threads_init(); + } + if (new_cnt > srv_n_fil_crypt_threads) { uint add = new_cnt - srv_n_fil_crypt_threads; srv_n_fil_crypt_threads = new_cnt; @@ -2358,15 +2383,18 @@ void fil_crypt_threads_init() /*====================*/ { - fil_crypt_event = os_event_create(); - fil_crypt_threads_event = os_event_create(); - mutex_create(fil_crypt_threads_mutex_key, - &fil_crypt_threads_mutex, SYNC_NO_ORDER_CHECK); - - uint cnt = srv_n_fil_crypt_threads; - srv_n_fil_crypt_threads = 0; - fil_crypt_set_thread_cnt(cnt); - fil_crypt_threads_inited = true; + ut_ad(mutex_own(&fil_system->mutex)); + if (!fil_crypt_threads_inited) { + fil_crypt_event = os_event_create(); + fil_crypt_threads_event = os_event_create(); + mutex_create(fil_crypt_threads_mutex_key, + &fil_crypt_threads_mutex, SYNC_NO_ORDER_CHECK); + + uint cnt = srv_n_fil_crypt_threads; + srv_n_fil_crypt_threads = 0; + fil_crypt_threads_inited = true; + fil_crypt_set_thread_cnt(cnt); + } } /********************************************************************* @@ -2389,6 +2417,7 @@ fil_crypt_threads_cleanup() { os_event_free(fil_crypt_event); os_event_free(fil_crypt_threads_event); + fil_crypt_threads_inited = false; } /********************************************************************* @@ -2493,6 +2522,7 @@ fil_space_crypt_get_status( mutex_enter(&crypt_data->mutex); status->keyserver_requests = crypt_data->keyserver_requests; status->min_key_version = crypt_data->min_key_version; + status->key_id = crypt_data->key_id; if (crypt_data->rotate_state.active_threads > 0 || crypt_data->rotate_state.flushing) { diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index 65827717230..b60a0e9ddaf 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -2994,6 +2994,48 @@ fil_make_isl_name( return(filename); } +/** Test if a tablespace file can be renamed to a new filepath by checking +if that the old filepath exists and the new filepath does not exist. +@param[in] space_id tablespace id +@param[in] old_path old filepath +@param[in] new_path new filepath +@param[in] is_discarded whether the tablespace is discarded +@return innodb error code */ +dberr_t +fil_rename_tablespace_check( + ulint space_id, + const char* old_path, + const char* new_path, + bool is_discarded) +{ + ulint exists = false; + os_file_type_t ftype; + + if (!is_discarded + && os_file_status(old_path, &exists, &ftype) + && !exists) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Cannot rename '%s' to '%s' for space ID %lu" + " because the source file does not exist.", + old_path, new_path, space_id); + + return(DB_TABLESPACE_NOT_FOUND); + } + + exists = false; + if (!os_file_status(new_path, &exists, &ftype) || exists) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Cannot rename '%s' to '%s' for space ID %lu" + " because the target file exists." + " Remove the target file and try again.", + old_path, new_path, space_id); + + return(DB_TABLESPACE_EXISTS); + } + + return(DB_SUCCESS); +} + /*******************************************************************//** Renames a single-table tablespace. The tablespace must be cached in the tablespace memory cache. @@ -3198,9 +3240,12 @@ fil_create_link_file( link_filepath = fil_make_isl_name(tablename); + /* Note that OS_FILE_READ_WRITE_CACHED used here to avoid + unnecessary errors on O_DIRECT, link files are not really + a data files. */ file = os_file_create_simple_no_error_handling( innodb_file_data_key, link_filepath, - OS_FILE_CREATE, OS_FILE_READ_WRITE, &success, 0); + OS_FILE_CREATE, OS_FILE_READ_WRITE_CACHED, &success, 0); if (!success) { /* The following call will print an error message */ @@ -6918,31 +6963,110 @@ fil_get_space_names( return(err); } -/****************************************************************//** -Generate redo logs for swapping two .ibd files */ +/** Generate redo log for swapping two .ibd files +@param[in] old_table old table +@param[in] new_table new table +@param[in] tmp_name temporary table name +@param[in,out] mtr mini-transaction +@return innodb error code */ UNIV_INTERN -void +dberr_t fil_mtr_rename_log( -/*===============*/ - ulint old_space_id, /*!< in: tablespace id of the old - table. */ - const char* old_name, /*!< in: old table name */ - ulint new_space_id, /*!< in: tablespace id of the new - table */ - const char* new_name, /*!< in: new table name */ - const char* tmp_name, /*!< in: temp table name used while - swapping */ - mtr_t* mtr) /*!< in/out: mini-transaction */ + const dict_table_t* old_table, + const dict_table_t* new_table, + const char* tmp_name, + mtr_t* mtr) { - if (old_space_id != TRX_SYS_SPACE) { - fil_op_write_log(MLOG_FILE_RENAME, old_space_id, - 0, 0, old_name, tmp_name, mtr); + dberr_t err = DB_SUCCESS; + char* old_path; + + /* If neither table is file-per-table, + there will be no renaming of files. */ + if (old_table->space == TRX_SYS_SPACE + && new_table->space == TRX_SYS_SPACE) { + return(DB_SUCCESS); + } + + if (DICT_TF_HAS_DATA_DIR(old_table->flags)) { + old_path = os_file_make_remote_pathname( + old_table->data_dir_path, old_table->name, "ibd"); + } else { + old_path = fil_make_ibd_name(old_table->name, false); + } + if (old_path == NULL) { + return(DB_OUT_OF_MEMORY); + } + + if (old_table->space != TRX_SYS_SPACE) { + char* tmp_path; + + if (DICT_TF_HAS_DATA_DIR(old_table->flags)) { + tmp_path = os_file_make_remote_pathname( + old_table->data_dir_path, tmp_name, "ibd"); + } + else { + tmp_path = fil_make_ibd_name(tmp_name, false); + } + + if (tmp_path == NULL) { + mem_free(old_path); + return(DB_OUT_OF_MEMORY); + } + + /* Temp filepath must not exist. */ + err = fil_rename_tablespace_check( + old_table->space, old_path, tmp_path, + dict_table_is_discarded(old_table)); + mem_free(tmp_path); + if (err != DB_SUCCESS) { + mem_free(old_path); + return(err); + } + + fil_op_write_log(MLOG_FILE_RENAME, old_table->space, + 0, 0, old_table->name, tmp_name, mtr); } - if (new_space_id != TRX_SYS_SPACE) { - fil_op_write_log(MLOG_FILE_RENAME, new_space_id, - 0, 0, new_name, old_name, mtr); + if (new_table->space != TRX_SYS_SPACE) { + + /* Destination filepath must not exist unless this ALTER + TABLE starts and ends with a file_per-table tablespace. */ + if (old_table->space == TRX_SYS_SPACE) { + char* new_path = NULL; + + if (DICT_TF_HAS_DATA_DIR(new_table->flags)) { + new_path = os_file_make_remote_pathname( + new_table->data_dir_path, + new_table->name, "ibd"); + } + else { + new_path = fil_make_ibd_name( + new_table->name, false); + } + + if (new_path == NULL) { + mem_free(old_path); + return(DB_OUT_OF_MEMORY); + } + + err = fil_rename_tablespace_check( + new_table->space, new_path, old_path, + dict_table_is_discarded(new_table)); + mem_free(new_path); + if (err != DB_SUCCESS) { + mem_free(old_path); + return(err); + } + } + + fil_op_write_log(MLOG_FILE_RENAME, new_table->space, + 0, 0, new_table->name, old_table->name, mtr); + } + + mem_free(old_path); + + return(err); } /************************************************************************* diff --git a/storage/xtradb/fsp/fsp0fsp.cc b/storage/xtradb/fsp/fsp0fsp.cc index 9af25b53a90..790232edb66 100644 --- a/storage/xtradb/fsp/fsp0fsp.cc +++ b/storage/xtradb/fsp/fsp0fsp.cc @@ -961,10 +961,20 @@ fsp_try_extend_data_file( } } else { /* We extend single-table tablespaces first one extent - at a time, but for bigger tablespaces more. It is not - enough to extend always by one extent, because some - extents are frag page extents. */ + at a time, but 4 at a time for bigger tablespaces. It is + not enough to extend always by one extent, because we need + to add at least one extent to FSP_FREE. + A single extent descriptor page will track many extents. + And the extent that uses its extent descriptor page is + put onto the FSP_FREE_FRAG list. Extents that do not + use their extent descriptor page are added to FSP_FREE. + The physical page size is used to determine how many + extents are tracked on one extent descriptor page. */ ulint extent_size; /*!< one megabyte, in pages */ + ulint threshold; /*!< The size of the tablespace + (in number of pages) where we + start allocating more than one + extent at a time. */ if (!zip_size) { extent_size = FSP_EXTENT_SIZE; @@ -973,6 +983,14 @@ fsp_try_extend_data_file( * UNIV_PAGE_SIZE / zip_size; } + /* Threshold is set at 32mb except when the page + size is small enough that it must be done sooner. + For page size less than 4k, we may reach the + extent contains extent descriptor page before + 32 mb. */ + threshold = ut_min((32 * extent_size), + (zip_size ? zip_size : UNIV_PAGE_SIZE)); + if (size < extent_size) { /* Let us first extend the file to extent_size */ success = fsp_try_extend_data_file_with_pages( @@ -989,7 +1007,7 @@ fsp_try_extend_data_file( size = extent_size; } - if (size < 32 * extent_size) { + if (size < threshold) { size_increase = extent_size; } else { /* Below in fsp_fill_free_list() we assume diff --git a/storage/xtradb/fts/fts0fts.cc b/storage/xtradb/fts/fts0fts.cc index 7a381f4ca05..712dfa264d4 100644 --- a/storage/xtradb/fts/fts0fts.cc +++ b/storage/xtradb/fts/fts0fts.cc @@ -6274,7 +6274,7 @@ fts_fake_hex_to_dec( #ifdef _WIN32 ret = sscanf(tmp_id, "%016llu", &dec_id); #else - ret = sscanf(tmp_id, "%016"PRIu64, &dec_id); + ret = sscanf(tmp_id, "%016" PRIu64, &dec_id); #endif /* _WIN32 */ ut_ad(ret == 1); diff --git a/storage/xtradb/fts/fts0opt.cc b/storage/xtradb/fts/fts0opt.cc index e096b8bf6d6..0703b050848 100644 --- a/storage/xtradb/fts/fts0opt.cc +++ b/storage/xtradb/fts/fts0opt.cc @@ -598,7 +598,7 @@ fts_zip_read_word( /* Finished decompressing block. */ if (zip->zp->avail_in == 0) { - /* Free the block thats been decompressed. */ + /* Free the block that's been decompressed. */ if (zip->pos > 0) { ulint prev = zip->pos - 1; diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index c50d3fd934b..b6d259c8bda 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -1,11 +1,10 @@ /***************************************************************************** Copyright (c) 2000, 2015, Oracle and/or its affiliates. -Copyright (c) 2013, 2015, MariaDB Corporation. +Copyright (c) 2013, 2016, MariaDB Corporation. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -944,12 +943,6 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG}, {"os_log_written", (char*) &export_vars.innodb_os_log_written, SHOW_LONGLONG}, - {"os_merge_buffers_written", - (char*) &export_vars.innodb_merge_buffers_written, SHOW_LONGLONG}, - {"os_merge_buffers_read", - (char*) &export_vars.innodb_merge_buffers_read, SHOW_LONGLONG}, - {"os_merge_buffers_merged", - (char*) &export_vars.innodb_merge_buffers_merged, SHOW_LONGLONG}, {"page_size", (char*) &export_vars.innodb_page_size, SHOW_LONG}, {"pages_created", @@ -1490,7 +1483,6 @@ Normalizes a table name string. A normalized name consists of the database name catenated to '/' and table name. An example: test/mytable. On Windows normalization puts both the database name and the table name always to lower case if "set_lower_case" is set to TRUE. */ -static void normalize_table_name_low( /*=====================*/ @@ -5386,7 +5378,6 @@ Normalizes a table name string. A normalized name consists of the database name catenated to '/' and table name. Example: test/mytable. On Windows normalization puts both the database name and the table name always to lower case if "set_lower_case" is set to TRUE. */ -static void normalize_table_name_low( /*=====================*/ @@ -8323,7 +8314,13 @@ ha_innobase::write_row( ha_statistic_increment(&SSV::ha_write_count); - if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) { + if (share->ib_table != prebuilt->table) { + fprintf(stderr, + "InnoDB: Warning: share->ib_table %p prebuilt->table %p table %s is_corrupt %lu.", + share->ib_table, prebuilt->table, prebuilt->table->name, prebuilt->table->is_corrupt); + } + + if (UNIV_UNLIKELY(share->ib_table && share->ib_table->is_corrupt)) { DBUG_RETURN(HA_ERR_CRASHED); } @@ -8651,7 +8648,7 @@ report_error: wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && wsrep_on(user_thd) && !wsrep_consistency_check(user_thd) && - !wsrep_thd_skip_append_keys(user_thd)) + !wsrep_thd_ignore_table(user_thd)) { if (wsrep_append_keys(user_thd, false, record, NULL)) { @@ -8670,7 +8667,13 @@ wsrep_error: func_exit: innobase_active_small(); - if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) { + if (share->ib_table != prebuilt->table) { + fprintf(stderr, + "InnoDB: Warning: share->ib_table %p prebuilt->table %p table %s is_corrupt %lu.", + share->ib_table, prebuilt->table, prebuilt->table->name, prebuilt->table->is_corrupt); + } + + if (UNIV_UNLIKELY(share->ib_table && share->ib_table->is_corrupt)) { DBUG_RETURN(HA_ERR_CRASHED); } @@ -9084,7 +9087,13 @@ ha_innobase::update_row( ha_statistic_increment(&SSV::ha_update_count); - if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) { + if (share->ib_table != prebuilt->table) { + fprintf(stderr, + "InnoDB: Warning: share->ib_table %p prebuilt->table %p table %s is_corrupt %lu.", + share->ib_table, prebuilt->table, prebuilt->table->name, prebuilt->table->is_corrupt); + } + + if (UNIV_UNLIKELY(share->ib_table && share->ib_table->is_corrupt)) { DBUG_RETURN(HA_ERR_CRASHED); } @@ -9185,7 +9194,7 @@ func_exit: if (error == DB_SUCCESS && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && wsrep_on(user_thd) && - !wsrep_thd_skip_append_keys(user_thd)) + !wsrep_thd_ignore_table(user_thd)) { DBUG_PRINT("wsrep", ("update row key")); @@ -9199,7 +9208,13 @@ func_exit: wsrep_error: #endif /* WITH_WSREP */ - if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) { + if (share->ib_table != prebuilt->table) { + fprintf(stderr, + "InnoDB: Warning: share->ib_table %p prebuilt->table %p table %s is_corrupt %lu.", + share->ib_table, prebuilt->table, prebuilt->table->name, prebuilt->table->is_corrupt); + } + + if (UNIV_UNLIKELY(share->ib_table && share->ib_table->is_corrupt)) { DBUG_RETURN(HA_ERR_CRASHED); } @@ -9265,7 +9280,7 @@ ha_innobase::delete_row( if (error == DB_SUCCESS && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && wsrep_on(user_thd) && - !wsrep_thd_skip_append_keys(user_thd)) + !wsrep_thd_ignore_table(user_thd)) { if (wsrep_append_keys(user_thd, false, record, NULL)) { DBUG_PRINT("wsrep", ("delete fail")); @@ -12721,7 +12736,13 @@ ha_innobase::truncate() update_thd(ha_thd()); - if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) { + if (share->ib_table != prebuilt->table) { + fprintf(stderr, + "InnoDB: Warning: share->ib_table %p prebuilt->table %p table %s is_corrupt %lu.", + share->ib_table, prebuilt->table, prebuilt->table->name, prebuilt->table->is_corrupt); + } + + if (UNIV_UNLIKELY(share->ib_table && share->ib_table->is_corrupt)) { DBUG_RETURN(HA_ERR_CRASHED); } @@ -12736,7 +12757,13 @@ ha_innobase::truncate() err = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx); - if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) { + if (share->ib_table != prebuilt->table) { + fprintf(stderr, + "InnoDB: Warning: share->ib_table %p prebuilt->table %p table %s is_corrupt %lu.", + share->ib_table, prebuilt->table, prebuilt->table->name, prebuilt->table->is_corrupt); + } + + if (UNIV_UNLIKELY(share->ib_table && share->ib_table->is_corrupt)) { DBUG_RETURN(HA_ERR_CRASHED); } @@ -14126,7 +14153,13 @@ ha_innobase::analyze( { int ret; - if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) { + if (share->ib_table != prebuilt->table) { + fprintf(stderr, + "InnoDB: Warning: share->ib_table %p prebuilt->table %p table %s is_corrupt %lu.", + share->ib_table, prebuilt->table, prebuilt->table->name, prebuilt->table->is_corrupt); + } + + if (UNIV_UNLIKELY(share->ib_table && share->ib_table->is_corrupt)) { return(HA_ADMIN_CORRUPT); } @@ -14136,7 +14169,13 @@ ha_innobase::analyze( HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE, true /* this is ANALYZE */); - if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) { + if (share->ib_table != prebuilt->table) { + fprintf(stderr, + "InnoDB: Warning: share->ib_table %p prebuilt->table %p table %s is_corrupt %lu.", + share->ib_table, prebuilt->table, prebuilt->table->name, prebuilt->table->is_corrupt); + } + + if (UNIV_UNLIKELY(share->ib_table && share->ib_table->is_corrupt)) { return(HA_ADMIN_CORRUPT); } @@ -15345,7 +15384,13 @@ ha_innobase::transactional_table_lock( update_thd(thd); - if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) { + if (share->ib_table != prebuilt->table) { + fprintf(stderr, + "InnoDB: Warning: share->ib_table %p prebuilt->table %p table %s is_corrupt %lu.", + share->ib_table, prebuilt->table, prebuilt->table->name, prebuilt->table->is_corrupt); + } + + if (UNIV_UNLIKELY(share->ib_table && share->ib_table->is_corrupt)) { DBUG_RETURN(HA_ERR_CRASHED); } @@ -18445,7 +18490,6 @@ innodb_sched_priority_purge_update( return; } - ut_ad(purge_sys->state == PURGE_STATE_RUN); for (ulint i = 0; i < srv_n_purge_threads; i++) { ulint nice = os_thread_get_priority(srv_purge_tids[i]); ulint actual_priority @@ -19203,6 +19247,15 @@ wsrep_innobase_kill_one_trx( (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); wsrep_thd_LOCK(thd); + DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock", + { + const char act[]= + "now " + "wait_for signal.wsrep_after_BF_victim_lock"; + DBUG_ASSERT(!debug_sync_set_action(bf_thd, + STRING_WITH_LEN(act))); + };); + if (wsrep_thd_query_state(thd) == QUERY_EXITING) { WSREP_DEBUG("kill trx EXITING for %lu", victim_trx->id); @@ -21070,7 +21123,7 @@ maria_declare_plugin(xtradb) innodb_status_variables_export,/* status variables */ innobase_system_variables, /* system variables */ INNODB_VERSION_STR, /* string version */ - MariaDB_PLUGIN_MATURITY_BETA /* maturity */ + MariaDB_PLUGIN_MATURITY_GAMMA /* maturity */ }, i_s_xtradb_read_view, i_s_xtradb_internal_hash_tables, diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 7ea581f99a2..c0d85451a9e 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -167,10 +167,13 @@ my_error_innodb( /* TODO: report the row, as we do for DB_DUPLICATE_KEY */ my_error(ER_INVALID_USE_OF_NULL, MYF(0)); break; + case DB_TABLESPACE_EXISTS: + my_error(ER_TABLESPACE_EXISTS, MYF(0), table); + break; + #ifdef UNIV_DEBUG case DB_SUCCESS: case DB_DUPLICATE_KEY: - case DB_TABLESPACE_EXISTS: case DB_ONLINE_LOG_TOO_BIG: /* These codes should not be passed here. */ ut_error; @@ -202,12 +205,14 @@ innobase_fulltext_exist( /*******************************************************************//** Determine if ALTER TABLE needs to rebuild the table. @param ha_alter_info the DDL operation +@param altered_table MySQL original table @return whether it is necessary to rebuild the table */ static __attribute__((nonnull, warn_unused_result)) bool innobase_need_rebuild( /*==================*/ - const Alter_inplace_info* ha_alter_info) + const Alter_inplace_info* ha_alter_info, + const TABLE* altered_table) { if (ha_alter_info->handler_flags == Alter_inplace_info::CHANGE_CREATE_OPTION @@ -219,6 +224,34 @@ innobase_need_rebuild( return(false); } + /* If alter table changes column name and adds a new + index, we need to check is this new index created + to new column name. This is because column name + changes are done normally after creating indexes. */ + if ((ha_alter_info->handler_flags + & Alter_inplace_info::ALTER_COLUMN_NAME) && + ((ha_alter_info->handler_flags + & Alter_inplace_info::ADD_INDEX) || + (ha_alter_info->handler_flags + & Alter_inplace_info::ADD_FOREIGN_KEY))) { + for (ulint i = 0; i < ha_alter_info->key_count; i++) { + const KEY* key = &ha_alter_info->key_info_buffer[ + ha_alter_info->index_add_buffer[i]]; + + for (ulint j = 0; j < key->user_defined_key_parts; j++) { + const KEY_PART_INFO* key_part = &(key->key_part[j]); + const Field* field = altered_table->field[key_part->fieldnr]; + + /* Field used on added index is renamed on + this same alter table. We need table + rebuild. */ + if (field->flags & FIELD_IS_RENAMED) { + return (true); + } + } + } + } + return(!!(ha_alter_info->handler_flags & INNOBASE_ALTER_REBUILD)); } @@ -557,7 +590,7 @@ ha_innobase::check_if_supported_inplace_alter( operation is possible. */ } else if (((ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX) - || innobase_need_rebuild(ha_alter_info)) + || innobase_need_rebuild(ha_alter_info, table)) && (innobase_fulltext_exist(altered_table))) { /* Refuse to rebuild the table online, if fulltext indexes are to survive the rebuild. */ @@ -1558,7 +1591,8 @@ innobase_create_index_def( index_def_t* index, /*!< out: index definition */ mem_heap_t* heap, /*!< in: heap where memory is allocated */ - const Field** fields) /*!z in: MySQL table fields */ + const Field** fields) /*!< in: MySQL table fields + */ { const KEY* key = &keys[key_number]; ulint i; @@ -1854,9 +1888,11 @@ innobase_create_key_defs( bool& add_fts_doc_id, /*!< in: whether we need to add new DOC ID column for FTS index */ - bool& add_fts_doc_idx) + bool& add_fts_doc_idx, /*!< in: whether we need to add new DOC ID index for FTS index */ + const TABLE* table) + /*!< in: MySQL table that is being altered */ { index_def_t* indexdef; index_def_t* indexdefs; @@ -1906,7 +1942,8 @@ innobase_create_key_defs( } const bool rebuild = new_primary || add_fts_doc_id - || innobase_need_rebuild(ha_alter_info); + || innobase_need_rebuild(ha_alter_info, table); + /* Reserve one more space if new_primary is true, and we might need to add the FTS_DOC_ID_INDEX */ indexdef = indexdefs = static_cast<index_def_t*>( @@ -2744,7 +2781,8 @@ prepare_inplace_alter_table_dict( ctx->heap, ha_alter_info, altered_table, ctx->num_to_add_index, num_fts_index, row_table_got_default_clust_index(ctx->new_table), - fts_doc_id_col, add_fts_doc_id, add_fts_doc_id_idx); + fts_doc_id_col, add_fts_doc_id, add_fts_doc_id_idx, + old_table); new_clustered = DICT_CLUSTERED & index_defs[0].ind_type; @@ -2757,7 +2795,7 @@ prepare_inplace_alter_table_dict( /* This is not an online operation (LOCK=NONE). */ } else if (ctx->add_autoinc == ULINT_UNDEFINED && num_fts_index == 0 - && (!innobase_need_rebuild(ha_alter_info) + && (!innobase_need_rebuild(ha_alter_info, old_table) || !innobase_fulltext_exist(altered_table))) { /* InnoDB can perform an online operation (LOCK=NONE). */ } else { @@ -2774,7 +2812,7 @@ prepare_inplace_alter_table_dict( is just copied from old table and stored in indexdefs[0] */ DBUG_ASSERT(!add_fts_doc_id || new_clustered); DBUG_ASSERT(!!new_clustered == - (innobase_need_rebuild(ha_alter_info) + (innobase_need_rebuild(ha_alter_info, old_table) || add_fts_doc_id)); /* Allocate memory for dictionary index definitions */ @@ -3034,7 +3072,7 @@ prepare_inplace_alter_table_dict( add_cols, ctx->heap); ctx->add_cols = add_cols; } else { - DBUG_ASSERT(!innobase_need_rebuild(ha_alter_info)); + DBUG_ASSERT(!innobase_need_rebuild(ha_alter_info, old_table)); if (!ctx->new_table->fts && innobase_fulltext_exist(altered_table)) { @@ -3055,7 +3093,7 @@ prepare_inplace_alter_table_dict( ctx->add_index[a] = row_merge_create_index( ctx->trx, ctx->new_table, - &index_defs[a]); + &index_defs[a], ctx->col_names); add_key_nums[a] = index_defs[a].key_number; @@ -3925,7 +3963,7 @@ err_exit: if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA) || (ha_alter_info->handler_flags == Alter_inplace_info::CHANGE_CREATE_OPTION - && !innobase_need_rebuild(ha_alter_info))) { + && !innobase_need_rebuild(ha_alter_info, table))) { if (heap) { ha_alter_info->handler_ctx @@ -4099,7 +4137,7 @@ ok_exit: if (ha_alter_info->handler_flags == Alter_inplace_info::CHANGE_CREATE_OPTION - && !innobase_need_rebuild(ha_alter_info)) { + && !innobase_need_rebuild(ha_alter_info, table)) { goto ok_exit; } @@ -4811,9 +4849,11 @@ commit_get_autoinc( Field* autoinc_field = old_table->found_next_number_field; + KEY* autoinc_key = + old_table->key_info + old_table->s->next_number_index; - dict_index_t* index = dict_table_get_index_on_first_col( - ctx->old_table, autoinc_field->field_index); + dict_index_t* index = dict_table_get_index_on_name( + ctx->old_table, autoinc_key->name); max_autoinc = ha_alter_info->create_info->auto_increment_value; @@ -5221,6 +5261,61 @@ commit_cache_rebuild( DBUG_VOID_RETURN; } +/** Store the column number of the columns in a list belonging +to indexes which are not being dropped. +@param[in] ctx In-place ALTER TABLE context +@param[out] drop_col_list list which will be set, containing columns + which is part of index being dropped */ +static +void +get_col_list_to_be_dropped( + ha_innobase_inplace_ctx* ctx, + std::set<ulint>& drop_col_list) +{ + for (ulint index_count = 0; index_count < ctx->num_to_drop_index; + index_count++) { + dict_index_t* index = ctx->drop_index[index_count]; + + for (ulint col = 0; col < index->n_user_defined_cols; col++) { + ulint col_no = dict_index_get_nth_col_no(index, col); + drop_col_list.insert(col_no); + } + } +} + +/** For each column, which is part of an index which is not going to be +dropped, it checks if the column number of the column is same as col_no +argument passed. +@param[in] table table object +@param[in] col_no column number of the column which is to be checked +@retval true column exists +@retval false column does not exist. */ +static +bool +check_col_exists_in_indexes( + const dict_table_t* table, + ulint col_no) +{ + for (dict_index_t* index = dict_table_get_first_index(table); index; + index = dict_table_get_next_index(index)) { + + if (index->to_be_dropped) { + continue; + } + + for (ulint col = 0; col < index->n_user_defined_cols; col++) { + + ulint index_col_no = dict_index_get_nth_col_no( + index, col); + if (col_no == index_col_no) { + return(true); + } + } + } + + return(false); +} + /** Commit the changes made during prepare_inplace_alter_table() and inplace_alter_table() inside the data dictionary tables, when not rebuilding the table. @@ -5356,6 +5451,20 @@ commit_cache_norebuild( DBUG_ASSERT(!ctx->need_rebuild()); + std::set<ulint> drop_list; + std::set<ulint>::const_iterator col_it; + + /* Check if the column, part of an index to be dropped is part of any + other index which is not being dropped. If it so, then set the ord_part + of the column to 0. */ + get_col_list_to_be_dropped(ctx, drop_list); + + for(col_it = drop_list.begin(); col_it != drop_list.end(); ++col_it) { + if (!check_col_exists_in_indexes(ctx->new_table, *col_it)) { + ctx->new_table->cols[*col_it].ord_part = 0; + } + } + for (ulint i = 0; i < ctx->num_to_add_index; i++) { dict_index_t* index = ctx->add_index[i]; DBUG_ASSERT(dict_index_get_online_status(index) @@ -5556,6 +5665,7 @@ ha_innobase::commit_inplace_alter_table( Alter_inplace_info* ha_alter_info, bool commit) { + dberr_t error; ha_innobase_inplace_ctx* ctx0 = static_cast<ha_innobase_inplace_ctx*> (ha_alter_info->handler_ctx); @@ -5637,7 +5747,7 @@ ha_innobase::commit_inplace_alter_table( transactions collected during crash recovery could be holding InnoDB locks only, not MySQL locks. */ - dberr_t error = row_merge_lock_table( + error = row_merge_lock_table( prebuilt->trx, ctx->old_table, LOCK_X); if (error != DB_SUCCESS) { @@ -5772,14 +5882,20 @@ ha_innobase::commit_inplace_alter_table( = static_cast<ha_innobase_inplace_ctx*>(*pctx); DBUG_ASSERT(ctx->need_rebuild()); - /* Generate the redo log for the file - operations that will be performed in - commit_cache_rebuild(). */ - fil_mtr_rename_log(ctx->old_table->space, - ctx->old_table->name, - ctx->new_table->space, - ctx->new_table->name, - ctx->tmp_name, &mtr); + /* Check for any possible problems for any + file operations that will be performed in + commit_cache_rebuild(), and if none, generate + the redo log for these operations. */ + error = fil_mtr_rename_log(ctx->old_table, + ctx->new_table, + ctx->tmp_name, &mtr); + if (error != DB_SUCCESS) { + /* Out of memory or a problem will occur + when renaming files. */ + fail = true; + my_error_innodb(error, ctx->old_table->name, + ctx->old_table->flags); + } DBUG_INJECT_CRASH("ib_commit_inplace_crash", crash_inject_count++); } @@ -5792,18 +5908,25 @@ ha_innobase::commit_inplace_alter_table( DBUG_EXECUTE_IF("innodb_alter_commit_crash_before_commit", log_buffer_flush_to_disk(); DBUG_SUICIDE();); - ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); ut_ad(!trx->fts_trx); - ut_ad(trx->insert_undo || trx->update_undo); - /* The following call commits the - mini-transaction, making the data dictionary - transaction committed at mtr.end_lsn. The - transaction becomes 'durable' by the time when - log_buffer_flush_to_disk() returns. In the - logical sense the commit in the file-based - data structures happens here. */ - trx_commit_low(trx, &mtr); + if (fail) { + mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); + mtr_commit(&mtr); + trx_rollback_for_mysql(trx); + } else { + /* The following call commits the + mini-transaction, making the data dictionary + transaction committed at mtr.end_lsn. The + transaction becomes 'durable' by the time when + log_buffer_flush_to_disk() returns. In the + logical sense the commit in the file-based + data structures happens here. */ + ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); + ut_ad(trx->insert_undo || trx->update_undo); + + trx_commit_low(trx, &mtr); + } /* If server crashes here, the dictionary in InnoDB and MySQL will differ. The .ibd files @@ -5825,7 +5948,6 @@ ha_innobase::commit_inplace_alter_table( update the in-memory structures, close some handles, release temporary files, and (unless we rolled back) update persistent statistics. */ - dberr_t error = DB_SUCCESS; for (inplace_alter_handler_ctx** pctx = ctx_array; *pctx; pctx++) { diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc index e124cb98f99..a131a50458a 100644 --- a/storage/xtradb/handler/i_s.cc +++ b/storage/xtradb/handler/i_s.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyrigth (c) 2014, 2015, MariaDB Corporation +Copyrigth (c) 2014, 2016, MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -792,7 +792,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_trx = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */ @@ -1050,7 +1050,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_locks = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */ @@ -1231,7 +1231,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_lock_waits = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /*******************************************************************//** @@ -1565,7 +1565,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset = @@ -1613,7 +1613,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_cmp_reset = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /* Fields of the dynamic tables @@ -1912,7 +1912,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_per_index = STRUCT_FLD(system_vars, NULL), STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_per_index_reset = @@ -1961,7 +1961,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_per_index_reset = STRUCT_FLD(system_vars, NULL), STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table information_schema.innodb_cmpmem. */ @@ -2203,7 +2203,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset = @@ -2251,7 +2251,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_metrics */ @@ -2774,7 +2774,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_metrics = STRUCT_FLD(system_vars, NULL), STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_ft_default_stopword */ static ST_FIELD_INFO i_s_stopword_fields_info[] = @@ -2886,7 +2886,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_default_stopword = STRUCT_FLD(system_vars, NULL), STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_DELETED @@ -3053,7 +3053,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_deleted = STRUCT_FLD(system_vars, NULL), STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /*******************************************************************//** @@ -3135,7 +3135,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_being_deleted = STRUCT_FLD(system_vars, NULL), STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHED and @@ -3423,7 +3423,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_index_cache = STRUCT_FLD(system_vars, NULL), STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /*******************************************************************//** @@ -3857,7 +3857,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_index_table = STRUCT_FLD(system_vars, NULL), STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG */ @@ -4054,7 +4054,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_config = STRUCT_FLD(system_vars, NULL), STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */ @@ -4601,7 +4601,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_stats = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */ @@ -5310,7 +5310,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_page = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = @@ -5855,7 +5855,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_page_lru = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /*******************************************************************//** @@ -6147,7 +6147,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tables = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /** SYS_TABLESTATS ***********************************************/ @@ -6435,7 +6435,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_tablestats = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /** SYS_INDEXES **************************************************/ @@ -6685,7 +6685,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_indexes = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /** SYS_COLUMNS **************************************************/ @@ -6920,7 +6920,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_columns = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /** SYS_FIELDS ***************************************************/ @@ -7128,7 +7128,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_fields = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /** SYS_FOREIGN ********************************************/ @@ -7351,7 +7351,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_foreign = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /** SYS_FOREIGN_COLS ********************************************/ @@ -7566,7 +7566,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_sys_foreign_cols = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /** SYS_TABLESPACES ********************************************/ @@ -7833,7 +7833,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tablespaces = STRUCT_FLD(system_vars, NULL), STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /** SYS_DATAFILES ************************************************/ @@ -8020,7 +8020,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_datafiles = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; static ST_FIELD_INFO i_s_innodb_changed_pages_info[] = @@ -8389,7 +8389,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_changed_pages = STRUCT_FLD(version, 0x0100 /* 1.0 */), STRUCT_FLD(status_vars, NULL), STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /** TABLESPACES_ENCRYPTION ********************************************/ @@ -8468,6 +8468,15 @@ static ST_FIELD_INFO innodb_tablespaces_encryption_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, +#define TABLESPACES_ENCRYPTION_CURRENT_KEY_ID 8 + {STRUCT_FLD(field_name, "CURRENT_KEY_ID"), + STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + END_OF_ST_FIELD_INFO }; @@ -8506,6 +8515,8 @@ i_s_dict_fill_tablespaces_encryption( status.min_key_version)); OK(fields[TABLESPACES_ENCRYPTION_CURRENT_KEY_VERSION]->store( status.current_key_version)); + OK(fields[TABLESPACES_ENCRYPTION_CURRENT_KEY_ID]->store( + status.key_id)); if (status.rotating) { fields[TABLESPACES_ENCRYPTION_KEY_ROTATION_PAGE_NUMBER]->set_notnull(); OK(fields[TABLESPACES_ENCRYPTION_KEY_ROTATION_PAGE_NUMBER]->store( @@ -8670,7 +8681,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_encryption = /* struct st_mysql_sys_var** */ STRUCT_FLD(system_vars, NULL), - INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_BETA + INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_GAMMA }; /** TABLESPACES_SCRUBBING ********************************************/ @@ -8969,7 +8980,7 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_tablespaces_scrubbing = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA) + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA) }; /** INNODB_MUTEXES *********************************************/ @@ -9183,7 +9194,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_mutexes = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; /** SYS_SEMAPHORE_WAITS ************************************************/ @@ -9460,7 +9471,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_semaphore_waits = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; static ST_FIELD_INFO innodb_changed_page_bitmaps_fields_info[] = @@ -9584,6 +9595,6 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_changed_page_bitmaps = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; diff --git a/storage/xtradb/handler/xtradb_i_s.cc b/storage/xtradb/handler/xtradb_i_s.cc index 207682e3154..a0ff959013a 100644 --- a/storage/xtradb/handler/xtradb_i_s.cc +++ b/storage/xtradb/handler/xtradb_i_s.cc @@ -176,7 +176,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_xtradb_read_view = STRUCT_FLD(status_vars, NULL), STRUCT_FLD(system_vars, NULL), STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; static ST_FIELD_INFO xtradb_internal_hash_tables_fields_info[] = @@ -381,7 +381,7 @@ UNIV_INTERN struct st_mysql_plugin i_s_xtradb_internal_hash_tables = STRUCT_FLD(status_vars, NULL), STRUCT_FLD(system_vars, NULL), STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; @@ -514,5 +514,5 @@ UNIV_INTERN struct st_mysql_plugin i_s_xtradb_rseg = STRUCT_FLD(status_vars, NULL), STRUCT_FLD(system_vars, NULL), STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA), }; diff --git a/storage/xtradb/ibuf/ibuf0ibuf.cc b/storage/xtradb/ibuf/ibuf0ibuf.cc index 9ee22d4d0f7..bac2a92dd0b 100644 --- a/storage/xtradb/ibuf/ibuf0ibuf.cc +++ b/storage/xtradb/ibuf/ibuf0ibuf.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -384,12 +385,18 @@ ibuf_header_page_get( buf_block_t* block; ut_ad(!ibuf_inside(mtr)); + page_t* page = NULL; block = buf_page_get( IBUF_SPACE_ID, 0, FSP_IBUF_HEADER_PAGE_NO, RW_X_LATCH, mtr); - buf_block_dbg_add_level(block, SYNC_IBUF_HEADER); - return(buf_block_get_frame(block)); + if (!block->page.encrypted) { + buf_block_dbg_add_level(block, SYNC_IBUF_HEADER); + + page = buf_block_get_frame(block); + } + + return page; } /******************************************************************//** @@ -540,9 +547,10 @@ ibuf_size_update( /******************************************************************//** Creates the insert buffer data structure at a database startup and initializes -the data structures for the insert buffer. */ +the data structures for the insert buffer. +@return DB_SUCCESS or failure */ UNIV_INTERN -void +dberr_t ibuf_init_at_db_start(void) /*=======================*/ { @@ -553,7 +561,7 @@ ibuf_init_at_db_start(void) dict_index_t* index; ulint n_used; page_t* header_page; - dberr_t error; + dberr_t error= DB_SUCCESS; ibuf = static_cast<ibuf_t*>(mem_zalloc(sizeof(ibuf_t))); @@ -583,6 +591,10 @@ ibuf_init_at_db_start(void) header_page = ibuf_header_page_get(&mtr); + if (!header_page) { + return (DB_DECRYPTION_FAILED); + } + fseg_n_reserved_pages(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, &n_used, &mtr); ibuf_enter(&mtr); @@ -634,6 +646,7 @@ ibuf_init_at_db_start(void) ut_a(error == DB_SUCCESS); ibuf->index = dict_table_get_first_index(table); + return (error); } /*********************************************************************//** diff --git a/storage/xtradb/include/buf0flu.h b/storage/xtradb/include/buf0flu.h index c51010e33bc..87ce7d88bdf 100644 --- a/storage/xtradb/include/buf0flu.h +++ b/storage/xtradb/include/buf0flu.h @@ -211,7 +211,7 @@ Clears up tail of the LRU lists: * Flush dirty pages at the tail of LRU to the disk The depth to which we scan each buffer pool is controlled by dynamic config parameter innodb_LRU_scan_depth. -@return total pages flushed */ +@return number of pages flushed */ UNIV_INTERN ulint buf_flush_LRU_tail(void); diff --git a/storage/xtradb/include/fil0crypt.h b/storage/xtradb/include/fil0crypt.h index c42a0cf7e3f..5deed1f001c 100644 --- a/storage/xtradb/include/fil0crypt.h +++ b/storage/xtradb/include/fil0crypt.h @@ -1,6 +1,6 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (c) 2015, MariaDB Corporation. +Copyright (c) 2015, 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -212,6 +212,7 @@ bool fil_space_check_encryption_read( /*============================*/ ulint space); /*!< in: tablespace id */ + /****************************************************************** Decrypt a page @return true if page is decrypted, false if not. */ @@ -226,7 +227,6 @@ fil_space_decrypt( dberr_t* err); /*!< in: out: DB_SUCCESS or error code */ - /********************************************************************* Encrypt buffer page @return encrypted page, or original not encrypted page if encrypt @@ -253,7 +253,8 @@ fil_space_decrypt( ulint space, /*!< in: tablespace id */ byte* src_frame, /*!< in: page frame */ ulint page_size, /*!< in: size of data to encrypt */ - byte* dst_frame); /*!< in: where to decrypt to */ + byte* dst_frame) /*!< in: where to decrypt to */ + __attribute__((warn_unused_result)); /********************************************************************* fil_space_verify_crypt_checksum @@ -332,6 +333,7 @@ struct fil_space_crypt_status_t { uint min_key_version; /*!< min key version */ uint current_key_version;/*!< current key version */ uint keyserver_requests;/*!< no of key requests to key server */ + ulint key_id; /*!< current key_id */ bool rotating; /*!< is key rotation ongoing */ bool flushing; /*!< is flush at end of rotation ongoing */ ulint rotate_next_page_number; /*!< next page if key rotating */ diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index 2a3995519a7..973882a50b4 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2015, MariaDB Corporation. +Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2013, 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -699,6 +699,21 @@ fil_discard_tablespace( ulint id) /*!< in: space id */ __attribute__((warn_unused_result)); #endif /* !UNIV_HOTBACKUP */ + +/** Test if a tablespace file can be renamed to a new filepath by checking +if that the old filepath exists and the new filepath does not exist. +@param[in] space_id tablespace id +@param[in] old_path old filepath +@param[in] new_path new filepath +@param[in] is_discarded whether the tablespace is discarded +@return innodb error code */ +dberr_t +fil_rename_tablespace_check( + ulint space_id, + const char* old_path, + const char* new_path, + bool is_discarded); + /*******************************************************************//** Renames a single-table tablespace. The tablespace must be cached in the tablespace memory cache. @@ -1223,21 +1238,19 @@ fil_get_space_names( /*!< in/out: Vector for collecting the names. */ __attribute__((warn_unused_result)); -/****************************************************************//** -Generate redo logs for swapping two .ibd files */ +/** Generate redo log for swapping two .ibd files +@param[in] old_table old table +@param[in] new_table new table +@param[in] tmp_name temporary table name +@param[in,out] mtr mini-transaction +@return innodb error code */ UNIV_INTERN -void +dberr_t fil_mtr_rename_log( -/*===============*/ - ulint old_space_id, /*!< in: tablespace id of the old - table. */ - const char* old_name, /*!< in: old table name */ - ulint new_space_id, /*!< in: tablespace id of the new - table */ - const char* new_name, /*!< in: new table name */ - const char* tmp_name, /*!< in: temp table name used while - swapping */ - mtr_t* mtr) /*!< in/out: mini-transaction */ + const dict_table_t* old_table, + const dict_table_t* new_table, + const char* tmp_name, + mtr_t* mtr) __attribute__((nonnull)); /*******************************************************************//** diff --git a/storage/xtradb/include/fil0fil.ic b/storage/xtradb/include/fil0fil.ic index ec3b7e85e91..7ccc69b9561 100644 --- a/storage/xtradb/include/fil0fil.ic +++ b/storage/xtradb/include/fil0fil.ic @@ -147,9 +147,9 @@ fil_page_type_validate( /* Dump out the page info */ fprintf(stderr, "InnoDB: Space %lu offset %lu name %s page_type %lu page_type_name %s\n" - "InnoDB: key_version %u page_compressed %d page_compressed_encrypted %d lsn %lu compressed_len %lu\n", + "InnoDB: key_version %u page_compressed %d page_compressed_encrypted %d lsn %llu compressed_len %lu\n", space, offset, rspace->name, page_type, fil_get_page_type_name(page_type), - key_version, page_compressed, page_compressed_encrypted, lsn, compressed_len); + key_version, page_compressed, page_compressed_encrypted, (ulonglong)lsn, compressed_len); fflush(stderr); ut_ad(page_type == FIL_PAGE_PAGE_COMPRESSED || diff --git a/storage/xtradb/include/fts0priv.ic b/storage/xtradb/include/fts0priv.ic index 2d07c60f980..ec61691870b 100644 --- a/storage/xtradb/include/fts0priv.ic +++ b/storage/xtradb/include/fts0priv.ic @@ -53,7 +53,7 @@ fts_write_object_id( /* Use this to construct old(5.6.14 and 5.7.3) windows ambiguous aux table names */ DBUG_EXECUTE_IF("innodb_test_wrong_windows_fts_aux_table_name", - return(sprintf(str, "%016"PRIu64, id));); + return(sprintf(str, "%016" PRIu64, id));); DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", return(sprintf(str, UINT64PFx, id));); @@ -66,7 +66,7 @@ fts_write_object_id( // FIXME: Use ut_snprintf(), so does following one. return(sprintf(str, "%016llu", id)); #else /* _WIN32 */ - return(sprintf(str, "%016"PRIu64, id)); + return(sprintf(str, "%016" PRIu64, id)); #endif /* _WIN32 */ } diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index 9ec6a7ff4b4..a9c003d5bb1 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -655,4 +655,18 @@ ib_push_warning( ulint error, /*!< in: error code to push as warning */ const char *format,/*!< in: warning message */ ...); + +/*****************************************************************//** +Normalizes a table name string. A normalized name consists of the +database name catenated to '/' and table name. An example: +test/mytable. On Windows normalization puts both the database name and the +table name always to lower case if "set_lower_case" is set to TRUE. */ +void +normalize_table_name_low( +/*=====================*/ + char* norm_name, /*!< out: normalized name as a + null-terminated string */ + const char* name, /*!< in: table name string */ + ibool set_lower_case); /*!< in: TRUE if we want to set + name to lower case */ #endif /* HA_INNODB_PROTOTYPES_H */ diff --git a/storage/xtradb/include/ibuf0ibuf.h b/storage/xtradb/include/ibuf0ibuf.h index ac16b10e097..3c8fa874dcf 100644 --- a/storage/xtradb/include/ibuf0ibuf.h +++ b/storage/xtradb/include/ibuf0ibuf.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -91,9 +92,10 @@ separately committed mini-transaction, because in crash recovery, the free bits could momentarily be set too high. */ /******************************************************************//** -Creates the insert buffer data structure at a database startup. */ +Creates the insert buffer data structure at a database startup. +@return DB_SUCCESS or failure */ UNIV_INTERN -void +dberr_t ibuf_init_at_db_start(void); /*=======================*/ /*********************************************************************//** diff --git a/storage/xtradb/include/log0recv.h b/storage/xtradb/include/log0recv.h index b23a140aac2..8fc5daaef1d 100644 --- a/storage/xtradb/include/log0recv.h +++ b/storage/xtradb/include/log0recv.h @@ -43,7 +43,8 @@ UNIV_INTERN ibool log_block_checksum_is_ok_or_old_format( /*===================================*/ - const byte* block); /*!< in: pointer to a log block */ + const byte* block, /*!< in: pointer to a log block */ + bool print_err); /*!< in print error ? */ /*******************************************************//** Calculates the new value for lsn when more data is added to the log. */ diff --git a/storage/xtradb/include/row0merge.h b/storage/xtradb/include/row0merge.h index 196543f25e1..3e3459b8703 100644 --- a/storage/xtradb/include/row0merge.h +++ b/storage/xtradb/include/row0merge.h @@ -268,8 +268,11 @@ row_merge_create_index( /*===================*/ trx_t* trx, /*!< in/out: trx (sets error_state) */ dict_table_t* table, /*!< in: the index is on this table */ - const index_def_t* index_def); + const index_def_t* index_def, /*!< in: the index definition */ + const char** col_names); + /*! in: column names if columns are + renamed or NULL */ /*********************************************************************//** Check if a transaction can use an index. @return TRUE if index can be used by the transaction else FALSE */ diff --git a/storage/xtradb/include/srv0mon.h b/storage/xtradb/include/srv0mon.h index 658cd94d1ec..33ae7749ca5 100644 --- a/storage/xtradb/include/srv0mon.h +++ b/storage/xtradb/include/srv0mon.h @@ -2,7 +2,7 @@ Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. +Copyright (c) 2013, 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -263,9 +263,6 @@ enum monitor_id_t { MONITOR_OVLD_OS_LOG_FSYNC, MONITOR_OVLD_OS_LOG_PENDING_FSYNC, MONITOR_OVLD_OS_LOG_PENDING_WRITES, - MONITOR_MERGE_BLOCKS_WRITTEN, - MONITOR_MERGE_BLOCKS_READ, - MONITOR_MERGE_BLOCKS_MERGED, /* Transaction related counters */ MONITOR_MODULE_TRX, diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 9a3bf4e74ae..a2d300957ba 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -3,7 +3,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. +Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -186,13 +186,6 @@ struct srv_stats_t { /** Number of lock waits that have been up to max time (i.e.) lock wait timeout */ ulint_ctr_1_t n_lock_max_wait_time; - - /** Number of merge buffers written */ - ulint_ctr_64_t merge_buffers_written; - /** Number of merge buffers read */ - ulint_ctr_64_t merge_buffers_read; - /** Number of merge buffers merged */ - ulint_ctr_64_t merge_buffers_merged; }; extern const char* srv_main_thread_op_info; @@ -1214,9 +1207,6 @@ struct export_var_t{ ulint innodb_purge_view_trx_id_age; /*!< rw_max_trx_id - purged view's min trx_id */ #endif /* UNIV_DEBUG */ - ib_int64_t innodb_merge_buffers_written; - ib_int64_t innodb_merge_buffers_read; - ib_int64_t innodb_merge_buffers_merged; ib_int64_t innodb_page_compression_saved;/*!< Number of bytes saved by page compression */ diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index dabaee4110c..f4a0da12476 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -45,10 +45,10 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MINOR 6 -#define INNODB_VERSION_BUGFIX 26 +#define INNODB_VERSION_BUGFIX 28 #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 76.0 +#define PERCONA_INNODB_VERSION 76.1 #endif /* Enable UNIV_LOG_ARCHIVE in XtraDB */ diff --git a/storage/xtradb/lock/lock0wait.cc b/storage/xtradb/lock/lock0wait.cc index 2482c88d3b7..a87adcf94c0 100644 --- a/storage/xtradb/lock/lock0wait.cc +++ b/storage/xtradb/lock/lock0wait.cc @@ -396,7 +396,9 @@ lock_wait_suspend_thread( if (lock_wait_timeout < 100000000 && wait_time > (double) lock_wait_timeout) { #ifdef WITH_WSREP - if (!wsrep_is_BF_lock_timeout(trx)) { + if (!wsrep_on(trx->mysql_thd) || + (!wsrep_is_BF_lock_timeout(trx) && + trx->error_state != DB_DEADLOCK)) { #endif /* WITH_WSREP */ trx->error_state = DB_LOCK_WAIT_TIMEOUT; diff --git a/storage/xtradb/log/log0crypt.cc b/storage/xtradb/log/log0crypt.cc index e90533c2e76..852148899e9 100644 --- a/storage/xtradb/log/log0crypt.cc +++ b/storage/xtradb/log/log0crypt.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (C) 2014, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -36,6 +36,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com #include "my_crypt.h" +/* Used for debugging */ +// #define DEBUG_CRYPT 1 #define UNENCRYPTED_KEY_VER 0 /* If true, enable redo log encryption. */ @@ -97,16 +99,24 @@ get_crypt_info( { /* so that no one is modifying array while we search */ ut_ad(mutex_own(&(log_sys->mutex))); + size_t items = crypt_info.size(); /* a log block only stores 4-bytes of checkpoint no */ checkpoint_no &= 0xFFFFFFFF; - for (size_t i = 0; i < crypt_info.size(); i++) { + for (size_t i = 0; i < items; i++) { struct crypt_info_t* it = &crypt_info[i]; if (it->checkpoint_no == checkpoint_no) { return it; } } + + /* If checkpoint contains more than one key and we did not + find the correct one use the first one. */ + if (items) { + return (&crypt_info[0]); + } + return NULL; } @@ -131,7 +141,8 @@ log_blocks_crypt( const byte* block, /*!< in: blocks before encrypt/decrypt*/ ulint size, /*!< in: size of block */ byte* dst_block, /*!< out: blocks after encrypt/decrypt */ - int what) /*!< in: encrypt or decrypt*/ + int what, /*!< in: encrypt or decrypt*/ + const crypt_info_t* crypt_info) /*!< in: crypt info or NULL */ { byte *log_block = (byte*)block; Crypt_result rc = MY_AES_OK; @@ -146,7 +157,8 @@ log_blocks_crypt( lsn_t log_block_start_lsn = log_block_get_start_lsn( lsn, log_block_no); - const crypt_info_t* info = get_crypt_info(log_block); + const crypt_info_t* info = crypt_info == NULL ? get_crypt_info(log_block) : + crypt_info; #ifdef DEBUG_CRYPT fprintf(stderr, "%s %lu chkpt: %lu key: %u lsn: %lu\n", @@ -156,12 +168,21 @@ log_blocks_crypt( info ? info->key_version : 0, log_block_start_lsn); #endif + /* If no key is found from checkpoint assume the log_block + to be unencrypted. If checkpoint contains the encryption key + compare log_block current checksum, if checksum matches, + block can't be encrypted. */ if (info == NULL || - info->key_version == UNENCRYPTED_KEY_VER) { + info->key_version == UNENCRYPTED_KEY_VER || + (log_block_checksum_is_ok_or_old_format(log_block, false) && + what == ENCRYPTION_FLAG_DECRYPT)) { memcpy(dst_block, log_block, OS_FILE_LOG_BLOCK_SIZE); goto next; } + ut_ad(what == ENCRYPTION_FLAG_DECRYPT ? !log_block_checksum_is_ok_or_old_format(log_block, false) : + log_block_checksum_is_ok_or_old_format(log_block, false)); + // Assume log block header is not encrypted memcpy(dst_block, log_block, LOG_BLOCK_HDR_SIZE); @@ -292,7 +313,7 @@ log_blocks_encrypt( const ulint size, /*!< in: size of blocks, must be multiple of a log block */ byte* dst_block) /*!< out: blocks after encryption */ { - return log_blocks_crypt(block, size, dst_block, ENCRYPTION_FLAG_ENCRYPT); + return log_blocks_crypt(block, size, dst_block, ENCRYPTION_FLAG_ENCRYPT, NULL); } /*********************************************************************//** @@ -355,14 +376,16 @@ log_encrypt_before_write( return; } - if (info->key_version == UNENCRYPTED_KEY_VER) { + /* If the key is not encrypted or user has requested not to + encrypt, do not change log block. */ + if (info->key_version == UNENCRYPTED_KEY_VER || !srv_encrypt_log) { return; } byte* dst_frame = (byte*)malloc(size); //encrypt log blocks content - Crypt_result result = log_blocks_crypt(block, size, dst_frame, ENCRYPTION_FLAG_ENCRYPT); + Crypt_result result = log_blocks_crypt(block, size, dst_frame, ENCRYPTION_FLAG_ENCRYPT, NULL); if (result == MY_AES_OK) { ut_ad(block[0] == dst_frame[0]); @@ -388,7 +411,7 @@ log_decrypt_after_read( byte* dst_frame = (byte*)malloc(size); // decrypt log blocks content - Crypt_result result = log_blocks_crypt(frame, size, dst_frame, ENCRYPTION_FLAG_DECRYPT); + Crypt_result result = log_blocks_crypt(frame, size, dst_frame, ENCRYPTION_FLAG_DECRYPT, NULL); if (result == MY_AES_OK) { memcpy(frame, dst_frame, size); diff --git a/storage/xtradb/log/log0log.cc b/storage/xtradb/log/log0log.cc index 853afe70100..36531f3c6f4 100644 --- a/storage/xtradb/log/log0log.cc +++ b/storage/xtradb/log/log0log.cc @@ -2,6 +2,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. +Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -33,10 +34,13 @@ Created 12/9/1995 Heikki Tuuri #include "config.h" #ifdef HAVE_ALLOCA_H #include "alloca.h" -#elif defined(HAVE_MALLOC_H) +#elif defined(HAVE_MALLOC_H) #include "malloc.h" #endif +/* Used for debugging */ +// #define DEBUG_CRYPT 1 + #include "log0log.h" #ifdef UNIV_NONINL @@ -1394,7 +1398,6 @@ log_group_file_header_flush( Stores a 4-byte checksum to the trailer checksum field of a log block before writing it to a log file. This checksum is used in recovery to check the consistency of a log block. */ -static void log_block_store_checksum( /*=====================*/ @@ -1512,6 +1515,14 @@ loop: log_encrypt_before_write(log_sys->next_checkpoint_no, buf, write_len); +#ifdef DEBUG_CRYPT + fprintf(stderr, "WRITE: block: %lu checkpoint: %lu %.8lx %.8lx\n", + log_block_get_hdr_no(buf), + log_block_get_checkpoint_no(buf), + log_block_calc_checksum(buf), + log_block_get_checksum(buf)); +#endif + fil_io(OS_FILE_WRITE | OS_FILE_LOG, true, group->space_id, 0, (ulint) (next_offset / UNIV_PAGE_SIZE), (ulint) (next_offset % UNIV_PAGE_SIZE), write_len, buf, @@ -2320,7 +2331,10 @@ log_checkpoint( * the checkpoint info has been written and THEN blocks will be encrypted * with new key */ - log_crypt_set_ver_and_key(log_sys->next_checkpoint_no + 1); + if (srv_encrypt_log) { + log_crypt_set_ver_and_key(log_sys->next_checkpoint_no + 1); + } + log_groups_write_checkpoint_info(); MONITOR_INC(MONITOR_NUM_CHECKPOINT); @@ -2585,8 +2599,24 @@ loop: mutex_enter(&log_sys->mutex); } +#ifdef DEBUG_CRYPT + fprintf(stderr, "BEFORE DECRYPT: block: %lu checkpoint: %lu %.8lx %.8lx offset %lu\n", + log_block_get_hdr_no(buf), + log_block_get_checkpoint_no(buf), + log_block_calc_checksum(buf), + log_block_get_checksum(buf), source_offset); +#endif + log_decrypt_after_read(buf, len); +#ifdef DEBUG_CRYPT + fprintf(stderr, "AFTER DECRYPT: block: %lu checkpoint: %lu %.8lx %.8lx\n", + log_block_get_hdr_no(buf), + log_block_get_checkpoint_no(buf), + log_block_calc_checksum(buf), + log_block_get_checksum(buf)); +#endif + if (release_mutex) { mutex_exit(&log_sys->mutex); } diff --git a/storage/xtradb/log/log0online.cc b/storage/xtradb/log/log0online.cc index 92f03f0e6a9..51a9fa8f6c5 100644 --- a/storage/xtradb/log/log0online.cc +++ b/storage/xtradb/log/log0online.cc @@ -905,7 +905,7 @@ log_online_is_valid_log_seg( const byte* log_block) /*!< in: read log data */ { ibool checksum_is_ok - = log_block_checksum_is_ok_or_old_format(log_block); + = log_block_checksum_is_ok_or_old_format(log_block, true); if (!checksum_is_ok) { diff --git a/storage/xtradb/log/log0recv.cc b/storage/xtradb/log/log0recv.cc index b0e69107723..f98adbbca08 100644 --- a/storage/xtradb/log/log0recv.cc +++ b/storage/xtradb/log/log0recv.cc @@ -2,7 +2,7 @@ Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -43,7 +43,7 @@ Created 9/20/1997 Heikki Tuuri #include "config.h" #ifdef HAVE_ALLOCA_H #include "alloca.h" -#elif defined(HAVE_MALLOC_H) +#elif defined(HAVE_MALLOC_H) #include "malloc.h" #endif @@ -849,6 +849,10 @@ not_consistent: fprintf(stderr, "InnoDB: No valid checkpoint found.\n" + "InnoDB: If you are attempting downgrade" + " from MySQL 5.7.9 or later,\n" + "InnoDB: please refer to " REFMAN + "upgrading-downgrading.html\n" "InnoDB: If this error appears when you are" " creating an InnoDB database,\n" "InnoDB: the problem may be that during" @@ -928,7 +932,8 @@ UNIV_INTERN ibool log_block_checksum_is_ok_or_old_format( /*===================================*/ - const byte* block) /*!< in: pointer to a log block */ + const byte* block, /*!< in: pointer to a log block */ + bool print_err) /*!< in print if error found */ { #ifdef UNIV_LOG_DEBUG return(TRUE); @@ -1011,11 +1016,13 @@ log_block_checksum_is_ok_or_old_format( return(TRUE); } - fprintf(stderr, "BROKEN: block: %lu checkpoint: %lu %.8lx %.8lx\n", - log_block_get_hdr_no(block), - log_block_get_checkpoint_no(block), - log_block_calc_checksum(block), - log_block_get_checksum(block)); + if (print_err) { + fprintf(stderr, "BROKEN: block: %lu checkpoint: %lu %.8lx %.8lx\n", + log_block_get_hdr_no(block), + log_block_get_checkpoint_no(block), + log_block_calc_checksum(block), + log_block_get_checksum(block)); + } return(FALSE); } @@ -2730,6 +2737,7 @@ recv_scan_log_recs( ibool finished; ulint data_len; ibool more_data; + bool maybe_encrypted=false; ut_ad(start_lsn % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0); @@ -2744,6 +2752,8 @@ recv_scan_log_recs( *err = DB_SUCCESS; do { + log_crypt_err_t log_crypt_err; + no = log_block_get_hdr_no(log_block); /* fprintf(stderr, "Log block header no %lu\n", no); @@ -2751,13 +2761,13 @@ recv_scan_log_recs( fprintf(stderr, "Scanned lsn no %lu\n", log_block_convert_lsn_to_no(scanned_lsn)); */ + if (no != log_block_convert_lsn_to_no(scanned_lsn) - || !log_block_checksum_is_ok_or_old_format(log_block)) { - log_crypt_err_t log_crypt_err; + || !log_block_checksum_is_ok_or_old_format(log_block, true)) { if (no == log_block_convert_lsn_to_no(scanned_lsn) && !log_block_checksum_is_ok_or_old_format( - log_block)) { + log_block, true)) { fprintf(stderr, "InnoDB: Log block no %lu at" " lsn " LSN_PF " has\n" @@ -2771,12 +2781,14 @@ recv_scan_log_recs( log_block)); } + maybe_encrypted = log_crypt_block_maybe_encrypted(log_block, + &log_crypt_err); + /* Garbage or an incompletely written log block */ finished = TRUE; - if (log_crypt_block_maybe_encrypted(log_block, - &log_crypt_err)) { + if (maybe_encrypted) { /* Log block maybe encrypted finish processing*/ log_crypt_print_error(log_crypt_err); *err = DB_ERROR; @@ -2786,12 +2798,13 @@ recv_scan_log_recs( /* Stop if we encounter a garbage log block */ if (!srv_force_recovery) { fputs("InnoDB: Set innodb_force_recovery" - " to ignore this error.\n", stderr); + " to ignore this error.\n", stderr); *err = DB_ERROR; return (TRUE); } break; + } if (log_block_get_flush_bit(log_block)) { diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc index 7f13c1656ee..b2b3e256211 100644 --- a/storage/xtradb/os/os0file.cc +++ b/storage/xtradb/os/os0file.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. +Copyright (c) 2013, 2016, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are @@ -1422,7 +1422,8 @@ os_file_create_simple_func( access = GENERIC_READ; - } else if (access_type == OS_FILE_READ_WRITE) { + } else if (access_type == OS_FILE_READ_WRITE + || access_type == OS_FILE_READ_WRITE_CACHED) { access = GENERIC_READ | GENERIC_WRITE; } else { ib_logf(IB_LOG_LEVEL_ERROR, @@ -1526,7 +1527,8 @@ os_file_create_simple_func( #ifdef USE_FILE_LOCK if (!srv_read_only_mode && *success - && access_type == OS_FILE_READ_WRITE + && (access_type == OS_FILE_READ_WRITE + || access_type == OS_FILE_READ_WRITE_CACHED) && os_file_lock(file, name)) { *success = FALSE; @@ -1554,15 +1556,16 @@ os_file_set_nocache_if_needed(os_file_t file, const char* name, const char *mode_str, ulint type, ulint access_type) { - if (srv_read_only_mode || access_type == OS_FILE_READ_WRITE_CACHED) + if (srv_read_only_mode || access_type == OS_FILE_READ_WRITE_CACHED) { return; + } if (srv_unix_file_flush_method == SRV_UNIX_ALL_O_DIRECT - || (type != OS_LOG_FILE + || (type == OS_LOG_FILE && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT - || (srv_unix_file_flush_method - == SRV_UNIX_O_DIRECT_NO_FSYNC)))) + || (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)))) { os_file_set_nocache(file, name, mode_str); + } } /****************************************************************//** @@ -2154,8 +2157,9 @@ os_file_create_func( } while (retry); - if (*success) { + /* We disable OS caching (O_DIRECT) only on data files */ + if (*success) { os_file_set_nocache_if_needed(file, name, mode_str, type, 0); } @@ -3144,7 +3148,7 @@ try_again: "Error in system call pread(). The operating" " system error number is %lu.",(ulint) errno); } else { - /* Partial read occured */ + /* Partial read occurred */ ib_logf(IB_LOG_LEVEL_ERROR, "Tried to read " ULINTPF " bytes at offset " UINT64PF ". Was only able to read %ld.", @@ -3248,7 +3252,7 @@ try_again: "Error in system call pread(). The operating" " system error number is %lu.",(ulint) errno); } else { - /* Partial read occured */ + /* Partial read occurred */ ib_logf(IB_LOG_LEVEL_ERROR, "Tried to read " ULINTPF " bytes at offset " UINT64PF ". Was only able to read %ld.", diff --git a/storage/xtradb/row/row0import.cc b/storage/xtradb/row/row0import.cc index ac6380e5a27..893ffcab3da 100644 --- a/storage/xtradb/row/row0import.cc +++ b/storage/xtradb/row/row0import.cc @@ -2070,8 +2070,20 @@ PageConverter::validate( return(IMPORT_PAGE_STATUS_CORRUPTED); } else if (offset > 0 && page_get_page_no(page) == 0) { - const byte* b = page; - const byte* e = b + m_page_size; + ulint checksum; + + checksum = mach_read_from_4(page + FIL_PAGE_SPACE_OR_CHKSUM); + if (checksum != 0) { + /* Checksum check passed in buf_page_is_corrupted(). */ + ib_logf(IB_LOG_LEVEL_WARN, + "%s: Page %lu checksum %lu should be zero.", + m_filepath, (ulong) (offset / m_page_size), + checksum); + } + + const byte* b = page + FIL_PAGE_OFFSET; + const byte* e = page + m_page_size + - FIL_PAGE_END_LSN_OLD_CHKSUM; /* If the page number is zero and offset > 0 then the entire page MUST consist of zeroes. If not then diff --git a/storage/xtradb/row/row0log.cc b/storage/xtradb/row/row0log.cc index 7014b8b99d2..b0c6f881f81 100644 --- a/storage/xtradb/row/row0log.cc +++ b/storage/xtradb/row/row0log.cc @@ -1462,6 +1462,7 @@ row_log_table_apply_insert_low( dtuple_t* entry; const row_log_t*log = dup->index->online_log; dict_index_t* index = dict_table_get_first_index(log->table); + ulint n_index = 0; ut_ad(dtuple_validate(row)); ut_ad(trx_id); @@ -1497,6 +1498,8 @@ row_log_table_apply_insert_low( } do { + n_index++; + if (!(index = dict_table_get_next_index(index))) { break; } @@ -1509,6 +1512,12 @@ row_log_table_apply_insert_low( error = row_ins_sec_index_entry_low( flags, BTR_MODIFY_TREE, index, offsets_heap, heap, entry, trx_id, thr); + + /* Report correct index name for duplicate key error. */ + if (error == DB_DUPLICATE_KEY) { + thr_get_trx(thr)->error_key_num = n_index; + } + } while (error == DB_SUCCESS); return(error); @@ -1816,6 +1825,7 @@ row_log_table_apply_update( mtr_t mtr; btr_pcur_t pcur; dberr_t error; + ulint n_index = 0; ut_ad(dtuple_get_n_fields_cmp(old_pk) == dict_index_get_n_unique(index)); @@ -2091,6 +2101,8 @@ func_exit_committed: break; } + n_index++; + if (index->type & DICT_FTS) { continue; } @@ -2134,6 +2146,11 @@ func_exit_committed: BTR_MODIFY_TREE, index, offsets_heap, heap, entry, trx_id, thr); + /* Report correct index name for duplicate key error. */ + if (error == DB_DUPLICATE_KEY) { + thr_get_trx(thr)->error_key_num = n_index; + } + mtr_start(&mtr); } diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc index ad3e7619c8a..8d7fcd7388c 100644 --- a/storage/xtradb/row/row0merge.cc +++ b/storage/xtradb/row/row0merge.cc @@ -1,7 +1,6 @@ /***************************************************************************** Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2015, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -971,7 +970,6 @@ row_merge_read( success = os_file_read_no_error_handling(OS_FILE_FROM_FD(fd), buf, ofs, srv_sort_buf_size); - srv_stats.merge_buffers_read.inc(); /* For encrypted tables, decrypt data after reading and copy data */ if (crypt_data && crypt_buf) { @@ -1027,7 +1025,6 @@ row_merge_write( } ret = os_file_write("(merge)", OS_FILE_FROM_FD(fd), out_buf, ofs, buf_len); - srv_stats.merge_buffers_written.inc(); #ifdef UNIV_DEBUG if (row_merge_print_block_write) { @@ -1916,7 +1913,7 @@ write_buffers: /* We have enough data tuples to form a block. Sort them and write to disk. */ - if (UNIV_LIKELY(buf->n_tuples)) { + if (buf->n_tuples) { if (dict_index_is_unique(buf->index)) { row_merge_dup_t dup = { buf->index, table, col_map, 0}; @@ -1957,17 +1954,13 @@ write_buffers: dict_index_get_lock(buf->index)); } - /* Do not write empty buffers to temporary file */ - if (buf->n_tuples) { - - row_merge_buf_write(buf, file, block); + row_merge_buf_write(buf, file, block); - if (!row_merge_write(file->fd, file->offset++, block, - crypt_data, crypt_block, new_table->space)) { - err = DB_TEMP_FILE_WRITE_FAILURE; - trx->error_key_num = i; - break; - } + if (!row_merge_write(file->fd, file->offset++, block, + crypt_data, crypt_block, new_table->space)) { + err = DB_TEMP_FILE_WRITE_FAILURE; + trx->error_key_num = i; + break; } UNIV_MEM_INVALID(&block[0], srv_sort_buf_size); @@ -2284,8 +2277,6 @@ done1: b2, of->fd, &of->offset, crypt_data, crypt_block ? &crypt_block[2 * srv_sort_buf_size] : NULL, space); - srv_stats.merge_buffers_merged.inc(); - return(b2 ? DB_SUCCESS : DB_CORRUPTION); } @@ -3746,8 +3737,11 @@ row_merge_create_index( /*===================*/ trx_t* trx, /*!< in/out: trx (sets error_state) */ dict_table_t* table, /*!< in: the index is on this table */ - const index_def_t* index_def) + const index_def_t* index_def, /*!< in: the index definition */ + const char** col_names) + /*! in: column names if columns are + renamed or NULL */ { dict_index_t* index; dberr_t err; @@ -3767,9 +3761,24 @@ row_merge_create_index( for (i = 0; i < n_fields; i++) { index_field_t* ifield = &index_def->fields[i]; - const char * col_name = ifield->col_name ? - dict_table_get_col_name_for_mysql(table, ifield->col_name) : - dict_table_get_col_name(table, ifield->col_no); + const char * col_name; + + /* + Alter table renaming a column and then adding a index + to this new name e.g ALTER TABLE t + CHANGE COLUMN b c INT NOT NULL, ADD UNIQUE INDEX (c); + requires additional check as column names are not yet + changed when new index definitions are created. Table's + new column names are on a array of column name pointers + if any of the column names are changed. */ + + if (col_names && col_names[i]) { + col_name = col_names[i]; + } else { + col_name = ifield->col_name ? + dict_table_get_col_name_for_mysql(table, ifield->col_name) : + dict_table_get_col_name(table, ifield->col_no); + } dict_mem_index_add_field( index, @@ -4110,71 +4119,67 @@ wait_again: #ifdef FTS_INTERNAL_DIAG_PRINT DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n"); #endif - } else { - /* Sorting and inserting is required only if - there really is records */ - if (UNIV_LIKELY(merge_files[i].n_rec)) { - char buf[3 * NAME_LEN]; - char *bufend; - row_merge_dup_t dup = { - sort_idx, table, col_map, 0}; + } else if (UNIV_LIKELY(merge_files[i].n_rec)) { + char buf[3 * NAME_LEN]; + char *bufend; + row_merge_dup_t dup = { + sort_idx, table, col_map, 0}; - pct_cost = (COST_BUILD_INDEX_STATIC + - (total_dynamic_cost * merge_files[i].offset / - total_index_blocks)) / - (total_static_cost + total_dynamic_cost) - * PCT_COST_MERGESORT_INDEX * 100; + pct_cost = (COST_BUILD_INDEX_STATIC + + (total_dynamic_cost * merge_files[i].offset / + total_index_blocks)) / + (total_static_cost + total_dynamic_cost) + * PCT_COST_MERGESORT_INDEX * 100; + + bufend = innobase_convert_name(buf, sizeof buf, + indexes[i]->name, strlen(indexes[i]->name), + trx ? trx->mysql_thd : NULL, + FALSE); - bufend = innobase_convert_name(buf, sizeof buf, - indexes[i]->name, strlen(indexes[i]->name), - trx ? trx->mysql_thd : NULL, - FALSE); + buf[bufend - buf]='\0'; - buf[bufend - buf]='\0'; + sql_print_information("InnoDB: Online DDL : Start merge-sorting" + " index %s (%lu / %lu), estimated cost : %2.4f", + buf, (i+1), n_indexes, pct_cost); - sql_print_information("InnoDB: Online DDL : Start merge-sorting" - " index %s (%lu / %lu), estimated cost : %2.4f", - buf, (i+1), n_indexes, pct_cost); + error = row_merge_sort( + trx, &dup, &merge_files[i], + block, &tmpfd, true, + pct_progress, pct_cost, + crypt_data, crypt_block, new_table->space); - error = row_merge_sort( - trx, &dup, &merge_files[i], - block, &tmpfd, true, - pct_progress, pct_cost, - crypt_data, crypt_block, new_table->space); + pct_progress += pct_cost; + + sql_print_information("InnoDB: Online DDL : End of " + " merge-sorting index %s (%lu / %lu)", + buf, (i+1), n_indexes); + + DBUG_EXECUTE_IF( + "ib_merge_wait_after_sort", + os_thread_sleep(20000000);); /* 20 sec */ + if (error == DB_SUCCESS) { + pct_cost = (COST_BUILD_INDEX_STATIC + + (total_dynamic_cost * merge_files[i].offset / + total_index_blocks)) / + (total_static_cost + total_dynamic_cost) * + PCT_COST_INSERT_INDEX * 100; + + sql_print_information("InnoDB: Online DDL : Start " + "building index %s (%lu / %lu), estimated " + "cost : %2.4f", buf, (i+1), + n_indexes, pct_cost); + + error = row_merge_insert_index_tuples( + trx->id, sort_idx, old_table, + merge_files[i].fd, block, + merge_files[i].n_rec, pct_progress, pct_cost, + crypt_data, crypt_block, new_table->space); pct_progress += pct_cost; - sql_print_information("InnoDB: Online DDL : End of " - " merge-sorting index %s (%lu / %lu)", + sql_print_information("InnoDB: Online DDL : " + "End of building index %s (%lu / %lu)", buf, (i+1), n_indexes); - - DBUG_EXECUTE_IF( - "ib_merge_wait_after_sort", - os_thread_sleep(20000000);); /* 20 sec */ - - if (error == DB_SUCCESS) { - pct_cost = (COST_BUILD_INDEX_STATIC + - (total_dynamic_cost * merge_files[i].offset / - total_index_blocks)) / - (total_static_cost + total_dynamic_cost) * - PCT_COST_INSERT_INDEX * 100; - - sql_print_information("InnoDB: Online DDL : Start " - "building index %s (%lu / %lu), estimated " - "cost : %2.4f", buf, (i+1), - n_indexes, pct_cost); - - error = row_merge_insert_index_tuples( - trx->id, sort_idx, old_table, - merge_files[i].fd, block, - merge_files[i].n_rec, pct_progress, pct_cost, - crypt_data, crypt_block, new_table->space); - pct_progress += pct_cost; - - sql_print_information("InnoDB: Online DDL : " - "End of building index %s (%lu / %lu)", - buf, (i+1), n_indexes); - } } } diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index 55e685ac19c..9427b20daf9 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -4894,6 +4894,7 @@ row_rename_table_for_mysql( pars_info_t* info = NULL; int retry; bool aux_fts_rename = false; + char* is_part = NULL; ut_a(old_name != NULL); ut_a(new_name != NULL); @@ -4931,6 +4932,55 @@ row_rename_table_for_mysql( table = dict_table_open_on_name(old_name, dict_locked, FALSE, DICT_ERR_IGNORE_NONE); + /* We look for pattern #P# to see if the table is partitioned + MySQL table. */ +#ifdef __WIN__ + is_part = strstr((char *)old_name, (char *)"#p#"); +#else + is_part = strstr((char *)old_name, (char *)"#P#"); +#endif /* __WIN__ */ + + /* MySQL partition engine hard codes the file name + separator as "#P#". The text case is fixed even if + lower_case_table_names is set to 1 or 2. This is true + for sub-partition names as well. InnoDB always + normalises file names to lower case on Windows, this + can potentially cause problems when copying/moving + tables between platforms. + + 1) If boot against an installation from Windows + platform, then its partition table name could + be all be in lower case in system tables. So we + will need to check lower case name when load table. + + 2) If we boot an installation from other case + sensitive platform in Windows, we might need to + check the existence of table name without lowering + case them in the system table. */ + if (!table && + is_part && + innobase_get_lower_case_table_names() == 1) { + char par_case_name[MAX_FULL_NAME_LEN + 1]; +#ifndef __WIN__ + /* Check for the table using lower + case name, including the partition + separator "P" */ + memcpy(par_case_name, old_name, + strlen(old_name)); + par_case_name[strlen(old_name)] = 0; + innobase_casedn_str(par_case_name); +#else + /* On Windows platfrom, check + whether there exists table name in + system table whose name is + not being normalized to lower case */ + normalize_table_name_low( + par_case_name, old_name, FALSE); +#endif + table = dict_table_open_on_name(par_case_name, dict_locked, FALSE, + DICT_ERR_IGNORE_NONE); + } + if (!table) { err = DB_TABLE_NOT_FOUND; ut_print_timestamp(stderr); diff --git a/storage/xtradb/row/row0sel.cc b/storage/xtradb/row/row0sel.cc index 35719391fae..2bebfb7a0f1 100644 --- a/storage/xtradb/row/row0sel.cc +++ b/storage/xtradb/row/row0sel.cc @@ -3751,12 +3751,6 @@ row_search_for_mysql( ut_error; } - /* init null bytes with default values as they might be - left uninitialized in some cases and these uninited bytes - might be copied into mysql record buffer that leads to - valgrind warnings */ - memcpy(buf, prebuilt->default_rec, prebuilt->null_bitmap_len); - #if 0 /* August 19, 2005 by Heikki: temporarily disable this error print until the cursor lock count is done correctly. diff --git a/storage/xtradb/srv/srv0mon.cc b/storage/xtradb/srv/srv0mon.cc index 597e7cadc6a..e72868c6450 100644 --- a/storage/xtradb/srv/srv0mon.cc +++ b/storage/xtradb/srv/srv0mon.cc @@ -2,7 +2,7 @@ Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. +Copyright (c) 2013, 2016, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -715,24 +715,6 @@ static monitor_info_t innodb_counter_info[] = MONITOR_EXISTING | MONITOR_DEFAULT_ON), MONITOR_DEFAULT_START, MONITOR_OVLD_OS_LOG_PENDING_WRITES}, - {"os_merge_blocks_written", "os", - "Number of merge blocks written (innodb_os_merge_blocks_written)", - static_cast<monitor_type_t>( - MONITOR_EXISTING | MONITOR_DEFAULT_ON), - MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_WRITTEN}, - - {"os_merge_blocks_read", "os", - "Number of merge blocks read (innodb_os_merge_blocks_read)", - static_cast<monitor_type_t>( - MONITOR_EXISTING | MONITOR_DEFAULT_ON), - MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_READ}, - - {"os_merge_blocks_merged", "os", - "Number of merge blocks merged (innodb_os_merge_blocks_merged)", - static_cast<monitor_type_t>( - MONITOR_EXISTING | MONITOR_DEFAULT_ON), - MONITOR_DEFAULT_START, MONITOR_MERGE_BLOCKS_MERGED}, - /* ========== Counters for Transaction Module ========== */ {"module_trx", "transaction", "Transaction Manager", MONITOR_MODULE, @@ -1790,21 +1772,6 @@ srv_mon_process_existing_counter( update_min = TRUE; break; - /* innodb_os_merge_blocks_written */ - case MONITOR_MERGE_BLOCKS_WRITTEN: - value = srv_stats.merge_buffers_written; - break; - - /* innodb_os_merge_blocks_read */ - case MONITOR_MERGE_BLOCKS_READ: - value = srv_stats.merge_buffers_read; - break; - - /* innodb_os_merge_blocks_merged */ - case MONITOR_MERGE_BLOCKS_MERGED: - value = srv_stats.merge_buffers_merged; - break; - /* innodb_log_waits */ case MONITOR_OVLD_LOG_WAITS: value = srv_stats.log_waits; diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index 2164451225b..794b119a090 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -3,7 +3,7 @@ Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. +Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -2034,10 +2034,6 @@ srv_export_innodb_status(void) } #endif /* UNIV_DEBUG */ - export_vars.innodb_merge_buffers_written = srv_stats.merge_buffers_written; - export_vars.innodb_merge_buffers_read = srv_stats.merge_buffers_read; - export_vars.innodb_merge_buffers_merged = srv_stats.merge_buffers_merged; - export_vars.innodb_sec_rec_cluster_reads = srv_stats.n_sec_rec_cluster_reads; export_vars.innodb_sec_rec_cluster_reads_avoided = diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc index 6e45725098c..17f9e53e76f 100644 --- a/storage/xtradb/srv/srv0start.cc +++ b/storage/xtradb/srv/srv0start.cc @@ -188,6 +188,9 @@ static const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES = #define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD #define SRV_MAX_N_PENDING_SYNC_IOS 100 +/** The round off to MB is similar as done in srv_parse_megabytes() */ +#define CALC_NUMBER_OF_PAGES(size) ((size) / (1024 * 1024)) * \ + ((1024 * 1024) / (UNIV_PAGE_SIZE)) #ifdef UNIV_PFS_THREAD /* Keys to register InnoDB threads with performance schema */ UNIV_INTERN mysql_pfs_key_t io_handler_thread_key; @@ -1020,10 +1023,16 @@ open_or_create_data_files( size_check: size = os_file_get_size(files[i]); ut_a(size != (os_offset_t) -1); - /* Round size downward to megabytes */ - rounded_size_pages = (ulint) - (size >> UNIV_PAGE_SIZE_SHIFT); + /* Under some error conditions like disk full + narios or file size reaching filesystem + limit the data file could contain an incomplete + extent at the end. When we extend a data file + and if some failure happens, then also the data + file could contain an incomplete extent. So we + need to round the size downward to a megabyte.*/ + + rounded_size_pages = (ulint) CALC_NUMBER_OF_PAGES(size); if (i == srv_n_data_files - 1 && srv_auto_extend_last_data_file) { @@ -3076,7 +3085,9 @@ files_checked: fts_optimize_init(); /* Create thread(s) that handles key rotation */ + fil_system_enter(); fil_crypt_threads_init(); + fil_system_exit(); /* Create the log scrub thread */ if (srv_scrub_log) diff --git a/storage/xtradb/sync/sync0sync.cc b/storage/xtradb/sync/sync0sync.cc index 14b332a2185..702dd240f16 100644 --- a/storage/xtradb/sync/sync0sync.cc +++ b/storage/xtradb/sync/sync0sync.cc @@ -482,7 +482,13 @@ mutex_validate( const ib_mutex_t* mutex) /*!< in: mutex */ { ut_a(mutex); - ut_a(mutex->magic_n == MUTEX_MAGIC_N); + + if (mutex->magic_n != MUTEX_MAGIC_N) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Mutex %p not initialized file %s line %lu.", + mutex, mutex->cfile_name, mutex->cline); + } + ut_ad(mutex->magic_n == MUTEX_MAGIC_N); return(TRUE); } @@ -1651,34 +1657,49 @@ sync_print_wait_info( /*=================*/ FILE* file) /*!< in: file where to print */ { + // Sum counter values once + ib_int64_t mutex_spin_wait_count_val + = static_cast<ib_int64_t>(mutex_spin_wait_count); + ib_int64_t mutex_spin_round_count_val + = static_cast<ib_int64_t>(mutex_spin_round_count); + ib_int64_t mutex_os_wait_count_val + = static_cast<ib_int64_t>(mutex_os_wait_count); + ib_int64_t rw_s_spin_wait_count_val + = static_cast<ib_int64_t>(rw_lock_stats.rw_s_spin_wait_count); + ib_int64_t rw_s_spin_round_count_val + = static_cast<ib_int64_t>(rw_lock_stats.rw_s_spin_round_count); + ib_int64_t rw_s_os_wait_count_val + = static_cast<ib_int64_t>(rw_lock_stats.rw_s_os_wait_count); + ib_int64_t rw_x_spin_wait_count_val + = static_cast<ib_int64_t>(rw_lock_stats.rw_x_spin_wait_count); + ib_int64_t rw_x_spin_round_count_val + = static_cast<ib_int64_t>(rw_lock_stats.rw_x_spin_round_count); + ib_int64_t rw_x_os_wait_count_val + = static_cast<ib_int64_t>(rw_lock_stats.rw_x_os_wait_count); + fprintf(file, - "Mutex spin waits " UINT64PF ", rounds " UINT64PF ", " - "OS waits " UINT64PF "\n" - "RW-shared spins " UINT64PF ", rounds " UINT64PF ", " - "OS waits " UINT64PF "\n" - "RW-excl spins " UINT64PF ", rounds " UINT64PF ", " - "OS waits " UINT64PF "\n", - (ib_uint64_t) mutex_spin_wait_count, - (ib_uint64_t) mutex_spin_round_count, - (ib_uint64_t) mutex_os_wait_count, - (ib_uint64_t) rw_lock_stats.rw_s_spin_wait_count, - (ib_uint64_t) rw_lock_stats.rw_s_spin_round_count, - (ib_uint64_t) rw_lock_stats.rw_s_os_wait_count, - (ib_uint64_t) rw_lock_stats.rw_x_spin_wait_count, - (ib_uint64_t) rw_lock_stats.rw_x_spin_round_count, - (ib_uint64_t) rw_lock_stats.rw_x_os_wait_count); + "Mutex spin waits " INT64PF ", rounds " INT64PF ", " + "OS waits " INT64PF "\n" + "RW-shared spins " INT64PF ", rounds " INT64PF ", " + "OS waits " INT64PF "\n" + "RW-excl spins " INT64PF ", rounds " INT64PF ", " + "OS waits " INT64PF "\n", + mutex_spin_wait_count_val, mutex_spin_round_count_val, + mutex_os_wait_count_val, + rw_s_spin_wait_count_val, rw_s_spin_round_count_val, + rw_s_os_wait_count_val, + rw_x_spin_wait_count_val, rw_x_spin_round_count_val, + rw_x_os_wait_count_val); fprintf(file, "Spin rounds per wait: %.2f mutex, %.2f RW-shared, " "%.2f RW-excl\n", - (double) mutex_spin_round_count / - (mutex_spin_wait_count ? mutex_spin_wait_count : 1), - (double) rw_lock_stats.rw_s_spin_round_count / - (rw_lock_stats.rw_s_spin_wait_count - ? rw_lock_stats.rw_s_spin_wait_count : 1), - (double) rw_lock_stats.rw_x_spin_round_count / - (rw_lock_stats.rw_x_spin_wait_count - ? rw_lock_stats.rw_x_spin_wait_count : 1)); + (double) mutex_spin_round_count_val / + (mutex_spin_wait_count_val ? mutex_spin_wait_count_val : 1LL), + (double) rw_s_spin_round_count_val / + (rw_s_spin_wait_count_val ? rw_s_spin_wait_count_val : 1LL), + (double) rw_x_spin_round_count_val / + (rw_x_spin_wait_count_val ? rw_x_spin_wait_count_val : 1LL)); } /*******************************************************************//** diff --git a/storage/xtradb/ut/crc32_power8/crc32.S b/storage/xtradb/ut/crc32_power8/crc32.S index 52046bb9002..b064ce3dc96 100644 --- a/storage/xtradb/ut/crc32_power8/crc32.S +++ b/storage/xtradb/ut/crc32_power8/crc32.S @@ -67,14 +67,13 @@ #define off96 r30 #define off112 r31 -#define const1 v25 -#define const2 v26 +#define const1 v24 +#define const2 v25 -#define byteswap v27 -#define mask_32bit v28 -#define mask_64bit v29 -#define zeroes v30 -#define ones v31 +#define byteswap v26 +#define mask_32bit v27 +#define mask_64bit v28 +#define zeroes v29 #ifdef BYTESWAP_DATA #define VPERM(A, B, C, D) vperm A, B, C, D @@ -101,13 +100,28 @@ FUNC_START(__crc32_vpmsum) li off112,112 li r0,0 + /* Enough room for saving 10 non volatile VMX registers */ + subi r6,r1,56+10*16 + subi r7,r1,56+2*16 + + stvx v20,0,r6 + stvx v21,off16,r6 + stvx v22,off32,r6 + stvx v23,off48,r6 + stvx v24,off64,r6 + stvx v25,off80,r6 + stvx v26,off96,r6 + stvx v27,off112,r6 + stvx v28,0,r7 + stvx v29,off16,r7 + mr r10,r3 vxor zeroes,zeroes,zeroes - vspltisw ones,-1 + vspltisw v0,-1 - vsldoi mask_32bit,zeroes,ones,4 - vsldoi mask_64bit,zeroes,ones,8 + vsldoi mask_32bit,zeroes,v0,4 + vsldoi mask_64bit,zeroes,v0,8 /* Get the initial value into v8 */ vxor v8,v8,v8 @@ -570,6 +584,21 @@ FUNC_START(__crc32_vpmsum) vsldoi v0,v0,zeroes,4 /* shift result into top 64 bits of */ #endif +.Lout: + subi r6,r1,56+10*16 + subi r7,r1,56+2*16 + + lvx v20,0,r6 + lvx v21,off16,r6 + lvx v22,off32,r6 + lvx v23,off48,r6 + lvx v24,off64,r6 + lvx v25,off80,r6 + lvx v26,off96,r6 + lvx v27,off112,r6 + lvx v28,0,r7 + lvx v29,off16,r7 + /* Get it into r3 */ MFVRD(r3, v0) @@ -739,6 +768,8 @@ FUNC_START(__crc32_vpmsum) .Lzero: mr r3,r10 blr + b .Lout + FUNC_END(__crc32_vpmsum) #endif /* __powerpc__ */ diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index d6a9695afbf..962931913a2 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -45,8 +45,6 @@ #define isbig5code(c,d) (isbig5head(c) && isbig5tail(d)) #define big5code(c,d) (((uchar)(c) <<8) | (uchar)(d)) -#define big5head(e) ((uchar)(e>>8)) -#define big5tail(e) ((uchar)(e&0xff)) #define MY_FUNCTION_NAME(x) my_ ## x ## _big5 #define IS_MB1_CHAR(x) ((uchar) (x) < 0x80) @@ -850,93 +848,6 @@ static uint16 big5strokexfrm(uint16 i) } -static size_t -my_strnxfrm_big5(CHARSET_INFO *cs, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags) -{ - uchar *d0= dst; - uchar *de= dst + dstlen; - const uchar *se= src + srclen; - const uchar *sort_order= cs->sort_order; - - for (; dst < de && src < se && nweights; nweights--) - { - if (cs->cset->ismbchar(cs, (const char*) src, (const char*) se)) - { - /* - Note, it is safe not to check (src < se) - in the code below, because ismbchar() would - not return TRUE if src was too short - */ - uint16 e= big5strokexfrm((uint16) big5code(*src, *(src + 1))); - *dst++= big5head(e); - if (dst < de) - *dst++= big5tail(e); - src+= 2; - } - else - *dst++= sort_order ? sort_order[*src++] : *src++; - } - return my_strxfrm_pad_desc_and_reverse(cs, d0, dst, de, nweights, flags, 0); -} - -#if 0 -static int my_strcoll_big5(const uchar *s1, const uchar *s2) -{ - - while (*s1 && *s2) - { - if (*(s1+1) && *(s2+1) && isbig5code(*s1,*(s1+1)) && isbig5code(*s2, *(s2+1))) - { - if (*s1 != *s2 || *(s1+1) != *(s2+1)) - return ((int) big5code(*s1,*(s1+1)) - - (int) big5code(*s2,*(s2+1))); - s1 +=2; - s2 +=2; - } else if (sort_order_big5[(uchar) *s1++] != sort_order_big5[(uchar) *s2++]) - return ((int) sort_order_big5[(uchar) s1[-1]] - - (int) sort_order_big5[(uchar) s2[-1]]); - } - return 0; -} - -static int my_strxfrm_big5(uchar *dest, const uchar *src, int len) -{ - uint16 e; - uchar *d = dest; - - if (len < 1) return 0; - if (!*src) - { - *d = '\0'; - return 0; - } - while (*src && (len > 1)) - { - if (*(src+1) && isbig5code(*src, *(src+1))) - { - e = big5strokexfrm((uint16) big5code(*src, *(src+1))); - *d++ = big5head(e); - *d++ = big5tail(e); - src +=2; - len--; - } else - *d++ = sort_order_big5[(uchar) *src++]; - } - *d = '\0'; - return (int) (d-dest); -} -#endif - - -static uint ismbchar_big5(CHARSET_INFO *cs __attribute__((unused)), - const char* p, const char *e) -{ - return (isbig5head(*(p)) && (e)-(p)>1 && isbig5tail(*((p)+1))? 2: 0); -} - - static uint mbcharlen_big5(CHARSET_INFO *cs __attribute__((unused)), uint c) { return (isbig5head(c)? 2 : 1); @@ -6774,6 +6685,8 @@ my_mb_wc_big5(CHARSET_INFO *cs __attribute__((unused)), #define MY_FUNCTION_NAME(x) my_ ## x ## _big5_chinese_ci #define WEIGHT_MB1(x) (sort_order_big5[(uchar) (x)]) #define WEIGHT_MB2(x,y) (big5code(x, y)) +#define WEIGHT_MB2_FRM(x,y) (big5strokexfrm((uint16) WEIGHT_MB2(x, y))) +#define DEFINE_STRNXFRM #include "strcoll.ic" @@ -6788,7 +6701,7 @@ static MY_COLLATION_HANDLER my_collation_handler_big5_chinese_ci= NULL, /* init */ my_strnncoll_big5_chinese_ci, my_strnncollsp_big5_chinese_ci, - my_strnxfrm_big5, + my_strnxfrm_big5_chinese_ci, my_strnxfrmlen_simple, my_like_range_mb, my_wildcmp_mb, @@ -6818,7 +6731,6 @@ static MY_COLLATION_HANDLER my_collation_handler_big5_bin= static MY_CHARSET_HANDLER my_charset_big5_handler= { NULL, /* init */ - ismbchar_big5, mbcharlen_big5, my_numchars_mb, my_charpos_mb, diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 0be6ae95577..1027255af55 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -521,7 +521,6 @@ static MY_COLLATION_HANDLER my_collation_binary_handler = static MY_CHARSET_HANDLER my_charset_handler= { NULL, /* init */ - NULL, /* ismbchar */ my_mbcharlen_8bit, /* mbcharlen */ my_numchars_8bit, my_charpos_8bit, diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c index 9bf206f1de7..2163662269d 100644 --- a/strings/ctype-cp932.c +++ b/strings/ctype-cp932.c @@ -191,12 +191,6 @@ static const uchar sort_order_cp932[]= #include "ctype-mb.ic" -static uint ismbchar_cp932(CHARSET_INFO *cs __attribute__((unused)), - const char* p, const char *e) -{ - return (iscp932head((uchar) *p) && (e-p)>1 && iscp932tail((uchar)p[1]) ? 2: 0); -} - static uint mbcharlen_cp932(CHARSET_INFO *cs __attribute__((unused)),uint c) { return (iscp932head((uchar) c) ? 2 : 1); @@ -34693,7 +34687,6 @@ static MY_COLLATION_HANDLER my_collation_handler_cp932_bin= static MY_CHARSET_HANDLER my_charset_handler= { NULL, /* init */ - ismbchar_cp932, mbcharlen_cp932, my_numchars_mb, my_charpos_mb, diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index 1f13ab66284..19ed586ea49 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -210,14 +210,6 @@ static const uchar sort_order_euc_kr[]= #include "ctype-mb.ic" -static uint ismbchar_euc_kr(CHARSET_INFO *cs __attribute__((unused)), - const char* p, const char *e) -{ - return ((*(uchar*)(p)<0x80)? 0:\ - iseuc_kr_head(*(p)) && (e)-(p)>1 && iseuc_kr_tail(*((p)+1))? 2:\ - 0); -} - static uint mbcharlen_euc_kr(CHARSET_INFO *cs __attribute__((unused)),uint c) { return (iseuc_kr_head(c) ? 2 : 1); @@ -9987,7 +9979,6 @@ static MY_COLLATION_HANDLER my_collation_handler_euckr_bin= static MY_CHARSET_HANDLER my_charset_handler= { NULL, /* init */ - ismbchar_euc_kr, mbcharlen_euc_kr, my_numchars_mb, my_charpos_mb, diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c index 82c4bb5a4e8..52494b7dfb3 100644 --- a/strings/ctype-eucjpms.c +++ b/strings/ctype-eucjpms.c @@ -220,16 +220,6 @@ static const uchar sort_order_eucjpms[]= #include "strcoll.ic" -static uint ismbchar_eucjpms(CHARSET_INFO *cs __attribute__((unused)), - const char* p, const char *e) -{ - return ((*(uchar*)(p)<0x80)? 0:\ - iseucjpms(*(p)) && (e)-(p)>1 && iseucjpms(*((p)+1))? 2:\ - iseucjpms_ss2(*(p)) && (e)-(p)>1 && iskata(*((p)+1))? 2:\ - iseucjpms_ss3(*(p)) && (e)-(p)>2 && iseucjpms(*((p)+1)) && iseucjpms(*((p)+2))? 3:\ - 0); -} - static uint mbcharlen_eucjpms(CHARSET_INFO *cs __attribute__((unused)),uint c) { return (iseucjpms(c)? 2: iseucjpms_ss2(c)? 2: iseucjpms_ss3(c)? 3: 1); @@ -67520,7 +67510,6 @@ static MY_COLLATION_HANDLER my_collation_eucjpms_bin_handler = static MY_CHARSET_HANDLER my_charset_handler= { NULL, /* init */ - ismbchar_eucjpms, mbcharlen_eucjpms, my_numchars_mb, my_charpos_mb, diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index b0e275fe93d..a77237c1791 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -173,12 +173,6 @@ static const uchar sort_order_gb2312[]= #include "ctype-mb.ic" -static uint ismbchar_gb2312(CHARSET_INFO *cs __attribute__((unused)), - const char* p, const char *e) -{ - return (isgb2312head(*(p)) && (e)-(p)>1 && isgb2312tail(*((p)+1))? 2: 0); -} - static uint mbcharlen_gb2312(CHARSET_INFO *cs __attribute__((unused)),uint c) { return (isgb2312head(c)? 2 : 1); @@ -6391,7 +6385,6 @@ static MY_COLLATION_HANDLER my_collation_handler_gb2312_bin= static MY_CHARSET_HANDLER my_charset_handler= { NULL, /* init */ - ismbchar_gb2312, mbcharlen_gb2312, my_numchars_mb, my_charpos_mb, diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index 37b003f1899..e4e015a59d2 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -3451,44 +3451,6 @@ static uint16 gbksortorder(uint16 i) } -static size_t -my_strnxfrm_gbk(CHARSET_INFO *cs, - uchar *dst, size_t dstlen, uint nweights, - const uchar *src, size_t srclen, uint flags) -{ - uchar *d0= dst; - uchar *de= dst + dstlen; - const uchar *se= src + srclen; - const uchar *sort_order= cs->sort_order; - - for (; dst < de && src < se && nweights; nweights--) - { - if (cs->cset->ismbchar(cs, (const char*) src, (const char*) se)) - { - /* - Note, it is safe not to check (src < se) - in the code below, because ismbchar() would - not return TRUE if src was too short - */ - uint16 e= gbksortorder((uint16) gbkcode(*src, *(src + 1))); - *dst++= gbkhead(e); - if (dst < de) - *dst++= gbktail(e); - src+= 2; - } - else - *dst++= sort_order ? sort_order[*src++] : *src++; - } - return my_strxfrm_pad_desc_and_reverse(cs, d0, dst, de, nweights, flags, 0); -} - - -static uint ismbchar_gbk(CHARSET_INFO *cs __attribute__((unused)), - const char* p, const char *e) -{ - return (isgbkhead(*(p)) && (e)-(p)>1 && isgbktail(*((p)+1))? 2: 0); -} - static uint mbcharlen_gbk(CHARSET_INFO *cs __attribute__((unused)),uint c) { return (isgbkhead(c)? 2 : 1); @@ -10658,6 +10620,7 @@ my_mb_wc_gbk(CHARSET_INFO *cs __attribute__((unused)), #define MY_FUNCTION_NAME(x) my_ ## x ## _gbk_chinese_ci #define WEIGHT_MB1(x) (sort_order_gbk[(uchar) (x)]) #define WEIGHT_MB2(x,y) (gbksortorder(gbkcode(x,y))) +#define DEFINE_STRNXFRM #include "strcoll.ic" @@ -10672,7 +10635,7 @@ static MY_COLLATION_HANDLER my_collation_handler_gbk_chinese_ci= NULL, /* init */ my_strnncoll_gbk_chinese_ci, my_strnncollsp_gbk_chinese_ci, - my_strnxfrm_gbk, + my_strnxfrm_gbk_chinese_ci, my_strnxfrmlen_simple, my_like_range_mb, my_wildcmp_mb, @@ -10703,7 +10666,6 @@ static MY_COLLATION_HANDLER my_collation_handler_gbk_bin= static MY_CHARSET_HANDLER my_charset_handler= { NULL, /* init */ - ismbchar_gbk, mbcharlen_gbk, my_numchars_mb, my_charpos_mb, diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index 26c66d60071..cf8f9bb7e28 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -396,7 +396,6 @@ int my_wc_mb_latin1(CHARSET_INFO *cs __attribute__((unused)), static MY_CHARSET_HANDLER my_charset_handler= { NULL, /* init */ - NULL, my_mbcharlen_8bit, my_numchars_8bit, my_charpos_8bit, diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index eef283d2925..3fa66cb0b2f 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -571,93 +571,6 @@ uint my_instr_mb(CHARSET_INFO *cs, } -/* BINARY collations handlers for MB charsets */ - -int -my_strnncoll_mb_bin(CHARSET_INFO * cs __attribute__((unused)), - const uchar *s, size_t slen, - const uchar *t, size_t tlen, - my_bool t_is_prefix) -{ - size_t len=MY_MIN(slen,tlen); - int cmp= memcmp(s,t,len); - return cmp ? cmp : (int) ((t_is_prefix ? len : slen) - tlen); -} - - -/* - Compare two strings. - - SYNOPSIS - my_strnncollsp_mb_bin() - cs Chararacter set - s String to compare - slen Length of 's' - t String to compare - tlen Length of 't' - diff_if_only_endspace_difference - Set to 1 if the strings should be regarded as different - if they only difference in end space - - NOTE - This function is used for character strings with binary collations. - The shorter string is extended with end space to be as long as the longer - one. - - RETURN - A negative number if s < t - A positive number if s > t - 0 if strings are equal -*/ - -int -my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)), - const uchar *a, size_t a_length, - const uchar *b, size_t b_length, - my_bool diff_if_only_endspace_difference) -{ - const uchar *end; - size_t length; - int res; - -#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE - diff_if_only_endspace_difference= 0; -#endif - - end= a + (length= MY_MIN(a_length, b_length)); - while (a < end) - { - if (*a++ != *b++) - return ((int) a[-1] - (int) b[-1]); - } - res= 0; - if (a_length != b_length) - { - int swap= 1; - if (diff_if_only_endspace_difference) - res= 1; /* Assume 'a' is bigger */ - /* - Check the next not space character of the longer key. If it's < ' ', - then it's smaller than the other key. - */ - if (a_length < b_length) - { - /* put shorter key in s */ - a_length= b_length; - a= b; - swap= -1; /* swap sign of result */ - res= -res; - } - for (end= a + a_length-length; a < end ; a++) - { - if (*a != ' ') - return (*a < ' ') ? -swap : swap; - } - } - return res; -} - - /* Copy one non-ascii character. "dst" must have enough room for the character. @@ -668,7 +581,7 @@ my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)), */ #define my_strnxfrm_mb_non_ascii_char(cs, dst, src, se) \ { \ - switch (cs->cset->ismbchar(cs, (const char*) src, (const char*) se)) { \ + switch (my_ismbchar(cs, (const char *) src, (const char *) se)) { \ case 4: \ *dst++= *src++; \ /* fall through */ \ @@ -740,8 +653,8 @@ my_strnxfrm_mb(CHARSET_INFO *cs, for (; src < se && nweights && dst < de; nweights--) { int chlen; - if (*src < 128 || - !(chlen= cs->cset->ismbchar(cs, (const char*) src, (const char*) se))) + if (*src < 128 || !(chlen= my_ismbchar(cs, (const char *) src, + (const char *) se))) { /* Single byte character */ *dst++= sort_order ? sort_order[*src++] : *src++; diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 288f5fdd49d..b205b1abc20 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -1926,7 +1926,6 @@ my_strxfrm_pad_desc_and_reverse(CHARSET_INFO *cs, MY_CHARSET_HANDLER my_charset_8bit_handler= { my_cset_init_8bit, - NULL, /* ismbchar */ my_mbcharlen_8bit, /* mbcharlen */ my_numchars_8bit, my_charpos_8bit, diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 629e1cd8309..ebcea22d242 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -192,12 +192,6 @@ static const uchar sort_order_sjis[]= #include "ctype-mb.ic" -static uint ismbchar_sjis(CHARSET_INFO *cs __attribute__((unused)), - const char* p, const char *e) -{ - return (issjishead((uchar) *p) && (e-p)>1 && issjistail((uchar)p[1]) ? 2: 0); -} - static uint mbcharlen_sjis(CHARSET_INFO *cs __attribute__((unused)),uint c) { return (issjishead((uchar) c) ? 2 : 1); @@ -34072,7 +34066,6 @@ static MY_COLLATION_HANDLER my_collation_handler_sjis_bin= static MY_CHARSET_HANDLER my_charset_handler= { NULL, /* init */ - ismbchar_sjis, mbcharlen_sjis, my_numchars_mb, my_charpos_mb, diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index a1ca320835d..6315b05ea96 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -860,7 +860,6 @@ static MY_COLLATION_HANDLER my_collation_ci_handler = static MY_CHARSET_HANDLER my_charset_handler= { NULL, /* init */ - NULL, /* ismbchar */ my_mbcharlen_8bit, /* mbcharlen */ my_numchars_8bit, my_charpos_8bit, diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index cae85f38c12..74e474cc28c 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1413,15 +1413,6 @@ my_casedn_utf16(CHARSET_INFO *cs, char *src, size_t srclen, } -static uint -my_ismbchar_utf16(CHARSET_INFO *cs, const char *b, const char *e) -{ - my_wc_t wc; - int res= cs->cset->mb_wc(cs, &wc, (const uchar *) b, (const uchar *) e); - return (uint) (res > 0 ? res : 0); -} - - static int my_charlen_utf16(CHARSET_INFO *cs, const uchar *str, const uchar *end) { @@ -1456,7 +1447,7 @@ my_numchars_utf16(CHARSET_INFO *cs, size_t nchars= 0; for ( ; ; nchars++) { - size_t charlen= my_ismbchar_utf16(cs, b, e); + size_t charlen= my_ismbchar(cs, b, e); if (!charlen) break; b+= charlen; @@ -1576,7 +1567,6 @@ static MY_COLLATION_HANDLER my_collation_utf16_bin_handler = MY_CHARSET_HANDLER my_charset_utf16_handler= { NULL, /* init */ - my_ismbchar_utf16, /* ismbchar */ my_mbcharlen_utf16, /* mbcharlen */ my_numchars_utf16, my_charpos_utf16, @@ -1799,7 +1789,6 @@ static MY_COLLATION_HANDLER my_collation_utf16le_bin_handler = static MY_CHARSET_HANDLER my_charset_utf16le_handler= { NULL, /* init */ - my_ismbchar_utf16, my_mbcharlen_utf16, my_numchars_utf16, my_charpos_utf16, @@ -2075,15 +2064,6 @@ my_casedn_utf32(CHARSET_INFO *cs, char *src, size_t srclen, } -static uint -my_ismbchar_utf32(CHARSET_INFO *cs __attribute__((unused)), - const char *b, - const char *e) -{ - return b + 4 > e || !IS_UTF32_MBHEAD4(b[0], b[1]) ? 0 : 4; -} - - static int my_charlen_utf32(CHARSET_INFO *cs __attribute__((unused)), const uchar *b, const uchar *e) @@ -2545,7 +2525,6 @@ static MY_COLLATION_HANDLER my_collation_utf32_bin_handler = MY_CHARSET_HANDLER my_charset_utf32_handler= { NULL, /* init */ - my_ismbchar_utf32, my_mbcharlen_utf32, my_numchars_utf32, my_charpos_utf32, @@ -2883,14 +2862,6 @@ my_fill_ucs2(CHARSET_INFO *cs __attribute__((unused)), } -static uint my_ismbchar_ucs2(CHARSET_INFO *cs __attribute__((unused)), - const char *b, - const char *e) -{ - return b + 2 > e ? 0 : 2; -} - - static uint my_mbcharlen_ucs2(CHARSET_INFO *cs __attribute__((unused)) , uint c __attribute__((unused))) { @@ -3032,7 +3003,6 @@ static MY_COLLATION_HANDLER my_collation_ucs2_bin_handler = MY_CHARSET_HANDLER my_charset_ucs2_handler= { NULL, /* init */ - my_ismbchar_ucs2, /* ismbchar */ my_mbcharlen_ucs2, /* mbcharlen */ my_numchars_ucs2, my_charpos_ucs2, diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index 308f5f0f7d1..67e68901573 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -219,16 +219,6 @@ static const uchar sort_order_ujis[]= #include "strcoll.ic" -static uint ismbchar_ujis(CHARSET_INFO *cs __attribute__((unused)), - const char* p, const char *e) -{ - return ((*(uchar*)(p)<0x80)? 0:\ - isujis(*(p)) && (e)-(p)>1 && isujis(*((p)+1))? 2:\ - isujis_ss2(*(p)) && (e)-(p)>1 && iskata(*((p)+1))? 2:\ - isujis_ss3(*(p)) && (e)-(p)>2 && isujis(*((p)+1)) && isujis(*((p)+2))? 3:\ - 0); -} - static uint mbcharlen_ujis(CHARSET_INFO *cs __attribute__((unused)),uint c) { return (isujis(c)? 2: isujis_ss2(c)? 2: isujis_ss3(c)? 3: 1); @@ -67264,7 +67254,6 @@ static MY_COLLATION_HANDLER my_collation_ujis_bin_handler = static MY_CHARSET_HANDLER my_charset_handler= { NULL, /* init */ - ismbchar_ujis, mbcharlen_ujis, my_numchars_mb, my_charpos_mb, diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index c0865157ad5..c0014b95d15 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -5426,12 +5426,6 @@ my_weight_mb3_utf8_general_mysql500_ci(uchar b0, uchar b1, uchar b2) #include "strcoll.ic" -static uint my_ismbchar_utf8(CHARSET_INFO *cs,const char *b, const char *e) -{ - int res= my_charlen_utf8(cs, (const uchar*) b, (const uchar*) e); - return (res>1) ? res : 0; -} - static uint my_mbcharlen_utf8(CHARSET_INFO *cs __attribute__((unused)), uint c) { @@ -5497,7 +5491,6 @@ static MY_COLLATION_HANDLER my_collation_utf8_bin_handler = MY_CHARSET_HANDLER my_charset_utf8_handler= { NULL, /* init */ - my_ismbchar_utf8, my_mbcharlen_utf8, my_numchars_mb, my_charpos_mb, @@ -7044,15 +7037,6 @@ my_charlen_filename(CHARSET_INFO *cs, const uchar *str, const uchar *end) } -static uint -my_ismbchar_filename(CHARSET_INFO *cs, const char *str, const char *end) -{ - my_wc_t wc; - int rc= my_mb_wc_filename(cs, &wc, (const uchar *) str, (const uchar *) end); - return rc > 1 ? rc : 0; -} - - #define MY_FUNCTION_NAME(x) my_ ## x ## _filename #define CHARLEN(cs,str,end) my_charlen_filename(cs,str,end) #define DEFINE_WELL_FORMED_CHAR_LENGTH_USING_CHARLEN @@ -7081,7 +7065,6 @@ static MY_COLLATION_HANDLER my_collation_filename_handler = static MY_CHARSET_HANDLER my_charset_filename_handler= { NULL, /* init */ - my_ismbchar_filename, my_mbcharlen_utf8, my_numchars_mb, my_charpos_mb, @@ -7793,14 +7776,6 @@ size_t my_well_formed_len_utf8mb4(CHARSET_INFO *cs, static uint -my_ismbchar_utf8mb4(CHARSET_INFO *cs, const char *b, const char *e) -{ - int res= my_charlen_utf8mb4(cs, (const uchar*) b, (const uchar*) e); - return (res > 1) ? res : 0; -} - - -static uint my_mbcharlen_utf8mb4(CHARSET_INFO *cs __attribute__((unused)), uint c) { if (c < 0x80) @@ -7852,7 +7827,6 @@ static MY_COLLATION_HANDLER my_collation_utf8mb4_bin_handler = MY_CHARSET_HANDLER my_charset_utf8mb4_handler= { NULL, /* init */ - my_ismbchar_utf8mb4, my_mbcharlen_utf8mb4, my_numchars_mb, my_charpos_mb, diff --git a/strings/ctype.c b/strings/ctype.c index f871a219245..620c7e13503 100644 --- a/strings/ctype.c +++ b/strings/ctype.c @@ -1030,19 +1030,18 @@ my_charset_is_ascii_compatible(CHARSET_INFO *cs) @return Number of bytes copied to 'to' string */ -static uint32 -my_convert_internal(char *to, uint32 to_length, - CHARSET_INFO *to_cs, - const char *from, uint32 from_length, - CHARSET_INFO *from_cs, uint *errors) +uint32 +my_convert_using_func(char *to, uint32 to_length, + CHARSET_INFO *to_cs, my_charset_conv_wc_mb wc_mb, + const char *from, uint32 from_length, + CHARSET_INFO *from_cs, my_charset_conv_mb_wc mb_wc, + uint *errors) { int cnvres; my_wc_t wc; const uchar *from_end= (const uchar*) from + from_length; char *to_start= to; uchar *to_end= (uchar*) to + to_length; - my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc; - my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb; uint error_count= 0; while (1) @@ -1119,8 +1118,11 @@ my_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, immediately switch to slow mb_wc->wc_mb method. */ if ((to_cs->state | from_cs->state) & MY_CS_NONASCII) - return my_convert_internal(to, to_length, to_cs, - from, from_length, from_cs, errors); + return my_convert_using_func(to, to_length, + to_cs, to_cs->cset->wc_mb, + from, from_length, + from_cs, from_cs->cset->mb_wc, + errors); length= length2= MY_MIN(to_length, from_length); @@ -1152,9 +1154,11 @@ my_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, uint32 copied_length= length2 - length; to_length-= copied_length; from_length-= copied_length; - return copied_length + my_convert_internal(to, to_length, to_cs, - from, from_length, from_cs, - errors); + return copied_length + my_convert_using_func(to, to_length, to_cs, + to_cs->cset->wc_mb, + from, from_length, from_cs, + from_cs->cset->mb_wc, + errors); } } diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c index 1584a9e2cef..4178b20789d 100644 --- a/strings/my_vsnprintf.c +++ b/strings/my_vsnprintf.c @@ -831,7 +831,7 @@ void my_strerror(char *buf, size_t len, int nr) (defined _XOPEN_SOURCE && (_XOPEN_SOURCE >= 600))) && \ ! defined _GNU_SOURCE strerror_r(nr, buf, len); /* I can build with or without GNU */ -#elif defined _GNU_SOURCE +#elif defined(__GLIBC__) && defined (_GNU_SOURCE) char *r= strerror_r(nr, buf, len); if (r != buf) /* Want to help, GNU? */ strmake(buf, r, len - 1); /* Then don't. */ diff --git a/strings/str2int.c b/strings/str2int.c index ec89503af5e..fe6cd6b793e 100644 --- a/strings/str2int.c +++ b/strings/str2int.c @@ -45,7 +45,7 @@ easy task. Coping with integer overflow and the asymmetric range of twos complement machines is anything but easy. - So that users of atoi and atol can check whether an error occured, + So that users of atoi and atol can check whether an error occurred, I have taken a wholly unprecedented step: errno is CLEARED if this call has no problems. */ diff --git a/strings/strcoll.ic b/strings/strcoll.ic index 4bced593a23..4ce362c1675 100644 --- a/strings/strcoll.ic +++ b/strings/strcoll.ic @@ -262,6 +262,45 @@ MY_FUNCTION_NAME(strnncollsp)(CHARSET_INFO *cs __attribute__((unused)), return 0; } + +#ifdef DEFINE_STRNXFRM +#ifndef WEIGHT_MB2_FRM +#define WEIGHT_MB2_FRM(x,y) WEIGHT_MB2(x,y) +#endif + +static size_t +MY_FUNCTION_NAME(strnxfrm)(CHARSET_INFO *cs, + uchar *dst, size_t dstlen, uint nweights, + const uchar *src, size_t srclen, uint flags) +{ + uchar *d0= dst; + uchar *de= dst + dstlen; + const uchar *se= src + srclen; + const uchar *sort_order= cs->sort_order; + + for (; dst < de && src < se && nweights; nweights--) + { + if (my_charlen(cs, (const char *) src, (const char *) se) > 1) + { + /* + Note, it is safe not to check (src < se) + in the code below, because my_charlen() would + not return 2 if src was too short + */ + uint16 e= WEIGHT_MB2_FRM(src[0], src[1]); + *dst++= (uchar) (e >> 8); + if (dst < de) + *dst++= (uchar) (e & 0xFF); + src+= 2; + } + else + *dst++= sort_order ? sort_order[*src++] : *src++; + } + return my_strxfrm_pad_desc_and_reverse(cs, d0, dst, de, nweights, flags, 0); +} +#endif /* DEFINE_STRNXFRM */ + + /* We usually include this file at least two times from the same source file, for the _ci and the _bin collations. Prepare for the second inclusion. @@ -273,3 +312,5 @@ MY_FUNCTION_NAME(strnncollsp)(CHARSET_INFO *cs __attribute__((unused)), #undef WEIGHT_MB3 #undef WEIGHT_MB4 #undef WEIGHT_PAD_SPACE +#undef WEIGHT_MB2_FRM +#undef DEFINE_STRNXFRM diff --git a/tests/async_queries.c b/tests/async_queries.c index 75229eec4b4..76e884e6a69 100644 --- a/tests/async_queries.c +++ b/tests/async_queries.c @@ -265,7 +265,7 @@ again: { if (mysql_errno(&sd->mysql)) { - /* An error occured. */ + /* An error occurred. */ printf("%d | Error: %s\n", sd->index, mysql_error(&sd->mysql)); } else diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index a1a52e832dd..7cc59f6aca5 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -422,6 +422,55 @@ static void test_prepare_simple() mysql_stmt_close(stmt); + /* show create */ + strmov(query, "SHOW CREATE TABLE test_prepare_simple"); + stmt= mysql_simple_prepare(mysql, query); + check_stmt(stmt); + DIE_UNLESS(mysql_stmt_field_count(stmt) == 2); + mysql_stmt_close(stmt); + + /* show create database */ + strmov(query, "SHOW CREATE DATABASE test"); + stmt= mysql_simple_prepare(mysql, query); + check_stmt(stmt); + DIE_UNLESS(mysql_stmt_field_count(stmt) == 2); + mysql_stmt_close(stmt); + + /* show grants */ + strmov(query, "SHOW GRANTS"); + stmt= mysql_simple_prepare(mysql, query); + check_stmt(stmt); + DIE_UNLESS(mysql_stmt_field_count(stmt) == 1); + mysql_stmt_close(stmt); + + /* show slave status */ + strmov(query, "SHOW SLAVE STATUS"); + stmt= mysql_simple_prepare(mysql, query); + check_stmt(stmt); + DIE_UNLESS(mysql_stmt_field_count(stmt) == 47); + mysql_stmt_close(stmt); + + /* show master status */ + strmov(query, "SHOW MASTER STATUS"); + stmt= mysql_simple_prepare(mysql, query); + check_stmt(stmt); + DIE_UNLESS(mysql_stmt_field_count(stmt) == 4); + mysql_stmt_close(stmt); + + /* show create procedure */ + strmov(query, "SHOW CREATE PROCEDURE e1;"); + stmt= mysql_simple_prepare(mysql, query); + check_stmt(stmt); + DIE_UNLESS(mysql_stmt_field_count(stmt) == 6); + mysql_stmt_close(stmt); + + /* show create function */ + strmov(query, "SHOW CREATE FUNCTION e1;"); + stmt= mysql_simple_prepare(mysql, query); + check_stmt(stmt); + DIE_UNLESS(mysql_stmt_field_count(stmt) == 6); + mysql_stmt_close(stmt); + /* now fetch the results ..*/ rc= mysql_commit(mysql); myquery(rc); @@ -11732,10 +11781,10 @@ static void test_bug5315() rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); DIE_UNLESS(rc == 0); if (!opt_silent) - printf("Excuting mysql_change_user\n"); + printf("Executing mysql_change_user\n"); mysql_change_user(mysql, opt_user, opt_password, current_db); if (!opt_silent) - printf("Excuting mysql_stmt_execute\n"); + printf("Executing mysql_stmt_execute\n"); rc= mysql_stmt_execute(stmt); DIE_UNLESS(rc != 0); if (rc) @@ -11745,10 +11794,10 @@ static void test_bug5315() } /* check that connection is OK */ if (!opt_silent) - printf("Excuting mysql_stmt_close\n"); + printf("Executing mysql_stmt_close\n"); mysql_stmt_close(stmt); if (!opt_silent) - printf("Excuting mysql_stmt_init\n"); + printf("Executing mysql_stmt_init\n"); stmt= mysql_stmt_init(mysql); rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); DIE_UNLESS(rc == 0); @@ -15336,7 +15385,7 @@ static void test_mysql_insert_id() myheader("test_mysql_insert_id"); - rc= mysql_query(mysql, "drop table if exists t1"); + rc= mysql_query(mysql, "drop table if exists t1,t2"); myquery(rc); /* table without auto_increment column */ rc= mysql_query(mysql, "create table t1 (f1 int, f2 varchar(255), key(f1))"); @@ -18699,8 +18748,11 @@ static void test_progress_reporting() myheader("test_progress_reporting"); - conn= client_connect(CLIENT_PROGRESS, MYSQL_PROTOCOL_TCP, 0); - DIE_UNLESS(conn->client_flag & CLIENT_PROGRESS); + + conn= client_connect(CLIENT_PROGRESS_OBSOLETE, MYSQL_PROTOCOL_TCP, 0); + if (!(conn->server_capabilities & CLIENT_PROGRESS_OBSOLETE)) + return; + DIE_UNLESS(conn->client_flag & CLIENT_PROGRESS_OBSOLETE); mysql_options(conn, MYSQL_PROGRESS_CALLBACK, (void*) report_progress); rc= mysql_query(conn, "set @save=@@global.progress_report_time"); diff --git a/tests/nonblock-wrappers.h b/tests/nonblock-wrappers.h index 3ed470b3400..d6f42511f3a 100644 --- a/tests/nonblock-wrappers.h +++ b/tests/nonblock-wrappers.h @@ -30,7 +30,7 @@ /* Run the appropriate poll() syscall to wait for the event that libmysql - requested. Return which event(s) occured. + requested. Return which event(s) occurred. */ static int wait_for_mysql(MYSQL *mysql, int status) diff --git a/unittest/mysys/CMakeLists.txt b/unittest/mysys/CMakeLists.txt index 9455ad83849..ad5195a843e 100644 --- a/unittest/mysys/CMakeLists.txt +++ b/unittest/mysys/CMakeLists.txt @@ -13,9 +13,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -MY_ADD_TESTS(bitmap base64 my_vsnprintf my_atomic my_rdtsc lf my_malloc aes - my_getopt +MY_ADD_TESTS(bitmap base64 my_atomic my_rdtsc lf my_malloc my_getopt dynstring + aes LINK_LIBRARIES mysys) +MY_ADD_TESTS(my_vsnprintf LINK_LIBRARIES strings mysys) ADD_DEFINITIONS(${SSL_DEFINES}) diff --git a/unittest/mysys/dynstring-t.c b/unittest/mysys/dynstring-t.c new file mode 100644 index 00000000000..fed8488da2c --- /dev/null +++ b/unittest/mysys/dynstring-t.c @@ -0,0 +1,74 @@ +/* Copyright (c) 2016, MariaDB + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +//#include <my_global.h> +#include <m_string.h> +#include <my_sys.h> +#include <tap.h> + +DYNAMIC_STRING str1; + +static void check(const char *res) +{ + ok(strcmp(str1.str, res) == 0, "strcmp: %s", str1.str); + str1.length= 0; +} + +int main(void) +{ + plan(23); + + IF_WIN(skip_all("Test of POSIX shell escaping rules, not for CMD.EXE\n"), ); + + ok(init_dynamic_string(&str1, NULL, 0, 32) == 0, "init"); + + ok(dynstr_append_os_quoted(&str1, "test1", NULL) == 0, "append"); + check("'test1'"); + + ok(dynstr_append_os_quoted(&str1, "con", "cat", NULL) == 0, "append"); + check("'concat'"); + + ok(dynstr_append_os_quoted(&str1, "", NULL) == 0, "append"); + check("''"); + + ok(dynstr_append_os_quoted(&str1, "space inside", NULL) == 0, "append"); + check("'space inside'"); + + ok(dynstr_append_os_quoted(&str1, "single'quote", NULL) == 0, "append"); + check("'single'\"'\"'quote'"); + + ok(dynstr_append_os_quoted(&str1, "many'single'quotes", NULL) == 0, "append"); + check("'many'\"'\"'single'\"'\"'quotes'"); + + ok(dynstr_append_os_quoted(&str1, "'single quoted'", NULL) == 0, "append"); + check("''\"'\"'single quoted'\"'\"''"); + + ok(dynstr_append_os_quoted(&str1, "double\"quote", NULL) == 0, "append"); + check("'double\"quote'"); + + ok(dynstr_append_os_quoted(&str1, "mixed\"single'and\"double'quotes", NULL) == 0, "append"); + check("'mixed\"single'\"'\"'and\"double'\"'\"'quotes'"); + + ok(dynstr_append_os_quoted(&str1, "back\\space", NULL) == 0, "append"); + check("'back\\space'"); + + ok(dynstr_append_os_quoted(&str1, "backspace\\'and\\\"quote", NULL) == 0, "append"); + check("'backspace\\'\"'\"'and\\\"quote'"); + + dynstr_free(&str1); + + return exit_status(); +} + diff --git a/unittest/mysys/ma_dyncol-t.c b/unittest/mysys/ma_dyncol-t.c index 51e84bc4e40..b3fff638b65 100644 --- a/unittest/mysys/ma_dyncol-t.c +++ b/unittest/mysys/ma_dyncol-t.c @@ -691,13 +691,54 @@ err: mariadb_dyncol_free(&str2); } +static void test_mdev_9773() +{ + int rc; + uint i; + uint num_keys[5]= {1,2,3,4,5}; + char const *strval[]= {"Val1", "Val2", "Val3", "Val4", "Val5"}; + DYNAMIC_COLUMN_VALUE vals[5]; + DYNAMIC_COLUMN dynstr; + uint unpack_columns= 0; + MYSQL_LEX_STRING *unpack_keys= 0; + DYNAMIC_COLUMN_VALUE *unpack_vals= 0; + + for (i = 0; i < 5; i++) + { + vals[i].type= DYN_COL_STRING; + vals[i].x.string.value.str= (char *)strval[i]; + vals[i].x.string.value.length= strlen(strval[i]); + vals[i].x.string.charset= &my_charset_latin1; + } + + mariadb_dyncol_init(&dynstr); + + /* create numeric */ + rc= mariadb_dyncol_create_many_num(&dynstr, 5, num_keys, vals, 1); + + if (rc == ER_DYNCOL_OK) + rc= mariadb_dyncol_unpack(&dynstr, &unpack_columns, &unpack_keys, + &unpack_vals); + ok (rc == ER_DYNCOL_OK && unpack_columns == 5, "5 fields unpacked"); + for (i = 0; i < unpack_columns; i++) + { + ok(memcmp(unpack_vals[i].x.string.value.str, + vals[i].x.string.value.str, vals[i].x.string.value.length) == 0, + "unpack %u", i); + } + + my_free(unpack_keys); + my_free(unpack_vals); + mariadb_dyncol_free(&dynstr); +} + int main(int argc __attribute__((unused)), char **argv) { uint i; char *big_string= (char *)malloc(1024*1024); MY_INIT(argv[0]); - plan(62); + plan(68); if (!big_string) exit(1); @@ -830,6 +871,7 @@ int main(int argc __attribute__((unused)), char **argv) } test_mdev_4994(); test_mdev_4995(); + test_mdev_9773(); my_end(0); return exit_status(); diff --git a/unittest/strings/CMakeLists.txt b/unittest/strings/CMakeLists.txt index 10791edfb61..245747538c9 100644 --- a/unittest/strings/CMakeLists.txt +++ b/unittest/strings/CMakeLists.txt @@ -1,3 +1,3 @@ -MY_ADD_TESTS(strings LINK_LIBRARIES strings) +MY_ADD_TESTS(strings LINK_LIBRARIES strings mysys) diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index ca4669f81ba..3117cdf82ae 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -17,6 +17,10 @@ #include "vio_priv.h" #ifdef HAVE_OPENSSL +#ifndef HAVE_YASSL +#include <openssl/dh.h> +#include <openssl/bn.h> +#endif static my_bool ssl_algorithms_added = FALSE; static my_bool ssl_error_strings_loaded= FALSE; diff --git a/win/packaging/CPackWixConfig.cmake b/win/packaging/CPackWixConfig.cmake index 58a2ef44eef..6df49678d52 100644 --- a/win/packaging/CPackWixConfig.cmake +++ b/win/packaging/CPackWixConfig.cmake @@ -9,7 +9,7 @@ IF(ESSENTIALS) ENDIF() ELSE() SET(CPACK_COMPONENTS_USED - "Server;Client;Development;SharedLibraries;Embedded;Documentation;IniFiles;Readme;Debuginfo;Common;connect-engine") + "Server;Client;Development;SharedLibraries;Embedded;Documentation;IniFiles;Readme;Debuginfo;Common;connect-engine;ClientPlugins;gssapi-server;gssapi-client;aws-key-management") ENDIF() SET( WIX_FEATURE_MySQLServer_EXTRA_FEATURES "DBInstance;SharedClientServerComponents") @@ -54,20 +54,15 @@ SET(CPACK_COMPONENT_GROUP_MYSQLSERVER_DESCRIPTION "Install server") SET(CPACK_COMPONENT_DEBUGBINARIES_DESCRIPTION "Debug/trace versions of executables and libraries" ) #SET(CPACK_COMPONENT_DEBUGBINARIES_WIX_LEVEL 2) - - - #Subfeature "Data Files" - SET(CPACK_COMPONENT_DATAFILES_GROUP "MySQLServer") - SET(CPACK_COMPONENT_DATAFILES_DISPLAY_NAME "Server data files") - SET(CPACK_COMPONENT_DATAFILES_DESCRIPTION "Server data files" ) - SET(CPACK_COMPONENT_DATAFILES_HIDDEN 1) - #Subfeature "Connect Engine" - SET(CPACK_COMPONENT_CONNECT-ENGINE_GROUP "MySQLServer") - SET(CPACK_COMPONENT_CONNECT-ENGINE_DISPLAY_NAME "Server data files") - SET(CPACK_COMPONENT_CONNECT-ENGINE_DESCRIPTION "Server data files" ) - SET(CPACK_COMPONENT_CONNECT-ENGINE_HIDDEN 1) + #Miscellaneous (hidden) components, part of server / or client programs + FOREACH(comp connect-engine ClientPlugins gssapi-server gssapi-client aws-key-management) + STRING(TOUPPER "${comp}" comp) + SET(CPACK_COMPONENT_${comp}_GROUP "MySQLServer") + SET(CPACK_COMPONENT_${comp}_HIDDEN 1) + ENDFOREACH() + #Feature "Devel" SET(CPACK_COMPONENT_GROUP_DEVEL_DISPLAY_NAME "Development Components") SET(CPACK_COMPONENT_GROUP_DEVEL_DESCRIPTION "Installs C/C++ header files and libraries") diff --git a/win/packaging/ca/CMakeLists.txt b/win/packaging/ca/CMakeLists.txt index c57ae4b2113..04d5408b9c9 100644 --- a/win/packaging/ca/CMakeLists.txt +++ b/win/packaging/ca/CMakeLists.txt @@ -18,9 +18,6 @@ SET(WIXCA_SOURCES CustomAction.cpp CustomAction.def) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql) - - - ADD_VERSION_INFO(wixca SHARED WIXCA_SOURCES) ADD_LIBRARY(wixca SHARED EXCLUDE_FROM_ALL ${WIXCA_SOURCES}) TARGET_LINK_LIBRARIES(wixca ${WIX_WCAUTIL_LIBRARY} ${WIX_DUTIL_LIBRARY} |