diff options
621 files changed, 14751 insertions, 4364 deletions
diff --git a/.bzrignore b/.bzrignore index 68d45ea93b0..f757e602563 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1139,3 +1139,4 @@ libmysqld/gcalc_slicescan.cc libmysqld/gcalc_tools.cc sql/share/errmsg.sys sql/share/mysql +install_manifest.txt diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index b0d6f97284d..b59c8a1a6e1 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -148,6 +148,7 @@ fi # Override -DFORCE_INIT_OF_VARS from debug_cflags. It enables the macro # LINT_INIT(), which is only useful for silencing spurious warnings # of static analysis tools. We want LINT_INIT() to be a no-op in Valgrind. +valgrind_flags="-DHAVE_valgrind -USAFEMALLOC" valgrind_flags="$valgrind_flags -UFORCE_INIT_OF_VARS -Wno-uninitialized" valgrind_flags="$valgrind_flags -DMYSQL_SERVER_SUFFIX=-valgrind-max" valgrind_configs="--with-valgrind" diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e137382da4..41ee9b199b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright (c) 2006, 2011, Oracle and/or its affiliates. -# Copyright (c) 2008-2011 Monty Program Ab +# Copyright (c) 2006, 2012, Oracle and/or its affiliates. +# Copyright (c) 2008, 2012 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 @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=5 -MYSQL_VERSION_PATCH=21 +MYSQL_VERSION_PATCH=23 MYSQL_VERSION_EXTRA= diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index fb8b123b9d6..3f53158572f 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2011, 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 diff --git a/client/mysql_plugin.c b/client/mysql_plugin.c index 15f67e2b3e7..f4e3111b7b7 100644 --- a/client/mysql_plugin.c +++ b/client/mysql_plugin.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2011, 2012, 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 @@ -100,6 +100,7 @@ int main(int argc,char *argv[]) char operation[16]; MY_INIT(argv[0]); + sf_leaking_memory=1; /* don't report memory leaks on early exits */ plugin_data.name= 0; // initialize name /* diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 23c969face4..d7f311fcb69 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -255,7 +255,7 @@ get_one_option(int optid, const struct my_option *opt, puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2010")); puts("MariaDB utility for upgrading databases to new MariaDB versions.\n"); my_print_help(my_long_options); - exit(0); + die(0); break; case '#': diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index b12ea164aab..c36c8a16881 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -307,6 +307,7 @@ int main(int argc,char *argv[]) MY_INIT(argv[0]); mysql_init(&mysql); + sf_leaking_memory=1; /* don't report memory leaks on early exits */ if ((error= load_defaults("my",load_default_groups,&argc,&argv))) goto err1; save_argv = argv; /* Save for free_defaults */ @@ -329,6 +330,8 @@ int main(int argc,char *argv[]) (void) signal(SIGINT,endprog); /* Here if abort */ (void) signal(SIGTERM,endprog); /* Here if abort */ + sf_leaking_memory=0; /* from now on we cleanup properly */ + if (opt_compress) mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS); if (opt_connect_timeout) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index f983c952c4c..39ceb423968 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -975,6 +975,7 @@ int main(int argc, char **argv) char **defaults_argv; MY_INIT(argv[0]); + sf_leaking_memory=1; /* don't report memory leaks on early exits */ /* ** Check out the args */ @@ -984,6 +985,7 @@ int main(int argc, char **argv) defaults_argv= argv; if (get_options(&argc, &argv)) goto end1; + sf_leaking_memory=0; /* from now on we cleanup properly */ ret= EX_MYSQLERR; if (dbConnect(current_host, current_user, opt_password)) diff --git a/client/mysqldump.c b/client/mysqldump.c index 1de67e6da08..6834d16bde7 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2000, 2012, 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 @@ -590,17 +590,17 @@ void check_io(FILE *file) static void print_version(void) { - printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,DUMP_VERSION, + printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname_short,DUMP_VERSION, MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); } /* print_version */ static void short_usage_sub(void) { - printf("Usage: %s [OPTIONS] database [tables]\n", my_progname); + printf("Usage: %s [OPTIONS] database [tables]\n", my_progname_short); printf("OR %s [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]\n", - my_progname); - printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname); + my_progname_short); + printf("OR %s [OPTIONS] --all-databases [OPTIONS]\n", my_progname_short); } @@ -620,7 +620,7 @@ static void usage(void) static void short_usage(void) { short_usage_sub(); - printf("For more options, use %s --help\n", my_progname); + printf("For more options, use %s --help\n", my_progname_short); } @@ -947,7 +947,7 @@ static int get_options(int *argc, char ***argv) fields_terminated)) { fprintf(stderr, - "%s: You must use option --tab with --fields-...\n", my_progname); + "%s: You must use option --tab with --fields-...\n", my_progname_short); return(EX_USAGE); } @@ -965,7 +965,7 @@ static int get_options(int *argc, char ***argv) if (opt_single_transaction && opt_lock_all_tables) { fprintf(stderr, "%s: You can't use --single-transaction and " - "--lock-all-tables at the same time.\n", my_progname); + "--lock-all-tables at the same time.\n", my_progname_short); return(EX_USAGE); } if (opt_master_data) @@ -977,14 +977,14 @@ static int get_options(int *argc, char ***argv) lock_tables= 0; if (enclosed && opt_enclosed) { - fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname); + fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname_short); return(EX_USAGE); } if ((opt_databases || opt_alldbs) && path) { fprintf(stderr, "%s: --databases or --all-databases can't be used with --tab.\n", - my_progname); + my_progname_short); return(EX_USAGE); } if (strcmp(default_charset, charset_info->csname) && @@ -1036,7 +1036,7 @@ static void die(int error_num, const char* fmt_reason, ...) my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args); va_end(args); - fprintf(stderr, "%s: %s\n", my_progname, buffer); + fprintf(stderr, "%s: %s\n", my_progname_short, buffer); fflush(stderr); ignore_errors= 0; /* force the exit */ @@ -1070,7 +1070,7 @@ static void maybe_die(int error_num, const char* fmt_reason, ...) my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args); va_end(args); - fprintf(stderr, "%s: %s\n", my_progname, buffer); + fprintf(stderr, "%s: %s\n", my_progname_short, buffer); fflush(stderr); maybe_exit(error_num); @@ -2152,7 +2152,7 @@ static uint dump_events_for_db(char *db) if (create_delimiter(row[3], delimiter, sizeof(delimiter)) == NULL) { fprintf(stderr, "%s: Warning: Can't create delimiter for event '%s'\n", - my_progname, event_name); + my_progname_short, event_name); DBUG_RETURN(1); } @@ -2367,10 +2367,10 @@ static uint dump_routines_for_db(char *db) { if (opt_xml) { - if (i) // Procedures. + if (i) /* Procedures. */ print_xml_row(sql_file, "routine", routine_res, &row, "Create Procedure"); - else // Functions. + else /* Functions. */ print_xml_row(sql_file, "routine", routine_res, &row, "Create Function"); continue; @@ -2766,7 +2766,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, else { verbose_msg("%s: Warning: Can't set SQL_QUOTE_SHOW_CREATE option (%s)\n", - my_progname, mysql_error(mysql)); + my_progname_short, mysql_error(mysql)); my_snprintf(query_buff, sizeof(query_buff), show_fields_stmt, db, table); @@ -2877,7 +2877,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, goto continue_xml; } fprintf(stderr, "%s: Can't get keys for table %s (%s)\n", - my_progname, result_table, mysql_error(mysql)); + my_progname_short, result_table, mysql_error(mysql)); if (path) my_fclose(sql_file, MYF(MY_WME)); DBUG_RETURN(0); @@ -3533,7 +3533,7 @@ static void dump_table(char *table, char *db) if (mysql_num_fields(res) != num_fields) { fprintf(stderr,"%s: Error in field count for table: %s ! Aborting.\n", - my_progname, result_table); + my_progname_short, result_table); error= EX_CONSCHECK; goto err; } @@ -3798,7 +3798,7 @@ static void dump_table(char *table, char *db) { my_snprintf(buf, sizeof(buf), "%s: Error %d: %s when dumping table %s at row: %ld\n", - my_progname, + my_progname_short, mysql_errno(mysql), mysql_error(mysql), result_table, @@ -3992,8 +3992,8 @@ static int dump_tablespaces(char* ts_where) DBUG_RETURN(0); } - my_printf_error(0, "Error: '%s' when trying to dump tablespaces", - MYF(0), mysql_error(mysql)); + fprintf(stderr, "%s: Error: '%s' when trying to dump tablespaces\n", + my_progname_short, mysql_error(mysql)); DBUG_RETURN(1); } @@ -4138,8 +4138,8 @@ static int dump_all_databases() if (mysql_query(mysql, "SHOW DATABASES") || !(tableres= mysql_store_result(mysql))) { - my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s", - MYF(0), mysql_error(mysql)); + fprintf(stderr, "%s: Error: Couldn't execute 'SHOW DATABASES': %s\n", + my_progname_short, mysql_error(mysql)); return 1; } while ((row= mysql_fetch_row(tableres))) @@ -4666,8 +4666,8 @@ static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos) if (!ignore_errors) { /* SHOW MASTER STATUS reports nothing and --force is not enabled */ - my_printf_error(0, "Error: Binlogging on server not active", - MYF(0)); + fprintf(stderr, "%s: Error: Binlogging on server not active\n", + my_progname_short); maybe_exit(EX_MYSQLERR); return 1; } @@ -4750,7 +4750,7 @@ static int do_show_slave_status(MYSQL *mysql_con) if (!ignore_errors) { /* SHOW SLAVE STATUS reports nothing and --force is not enabled */ - my_printf_error(0, "Error: Slave not set up", MYF(0)); + fprintf(stderr, "%s: Error: Slave not set up\n", my_progname_short); } mysql_free_result(slave); return 1; @@ -4810,7 +4810,7 @@ static int do_start_slave_sql(MYSQL *mysql_con) /* now, start slave if stopped */ if (mysql_query_with_error_report(mysql_con, 0, "START SLAVE")) { - my_printf_error(0, "Error: Unable to start slave", MYF(0)); + fprintf(stderr, "%s: Error: Unable to start slave\n", my_progname_short); return 1; } return(0); @@ -5452,8 +5452,9 @@ int main(int argc, char **argv) char bin_log_name[FN_REFLEN]; int exit_code; int consistent_binlog_pos= 0; - MY_INIT("mysqldump"); + MY_INIT(argv[0]); + sf_leaking_memory=1; /* don't report memory leaks on early exits */ compatible_mode_normal_str[0]= 0; default_charset= (char *)mysql_universal_client_charset; bzero((char*) &ignore_table, sizeof(ignore_table)); @@ -5464,6 +5465,7 @@ int main(int argc, char **argv) free_resources(); exit(exit_code); } + sf_leaking_memory=0; /* from now on we cleanup properly */ /* Disable comments in xml mode if 'comments' option is not explicitly used. diff --git a/client/mysqlimport.c b/client/mysqlimport.c index e721b841f06..e4e34f786d7 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -613,6 +613,7 @@ int main(int argc, char **argv) { int error=0; MY_INIT(argv[0]); + sf_leaking_memory=1; /* don't report memory leaks on early exits */ if (load_defaults("my",load_default_groups,&argc,&argv)) return 1; @@ -623,6 +624,7 @@ int main(int argc, char **argv) free_defaults(argv_to_free); return(1); } + sf_leaking_memory=0; /* from now on we cleanup properly */ #ifdef HAVE_LIBPTHREAD if (opt_use_threads && !lock_tables) diff --git a/client/mysqlshow.c b/client/mysqlshow.c index f80f747b1ad..d0db2020998 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -67,11 +67,13 @@ int main(int argc, char **argv) char *wild; MYSQL mysql; MY_INIT(argv[0]); + sf_leaking_memory=1; /* don't report memory leaks on early exits */ if (load_defaults("my",load_default_groups,&argc,&argv)) exit(1); get_options(&argc,&argv); + sf_leaking_memory=0; /* from now on we cleanup properly */ wild=0; if (argc) { diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 955a31c1872..27c26cf9b64 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -317,6 +317,7 @@ int main(int argc, char **argv) option_string *eptr; MY_INIT(argv[0]); + sf_leaking_memory=1; /* don't report memory leaks on early exits */ if (load_defaults("my",load_default_groups,&argc,&argv)) { @@ -330,6 +331,7 @@ int main(int argc, char **argv) my_end(0); exit(1); } + sf_leaking_memory=0; /* from now on we cleanup properly */ /* Seed the random number generator if we will be using it. */ if (auto_generate_sql) diff --git a/client/sql_string.cc.dontuse b/client/sql_string.cc.dontuse index 8d1e19de71c..64219886dd0 100644 --- a/client/sql_string.cc.dontuse +++ b/client/sql_string.cc.dontuse @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2010, Oracle and/or its affiliates. + Copyright (c) 2000, 2011, 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 diff --git a/cmake/abi_check.cmake b/cmake/abi_check.cmake index 9948f526b7a..cca595c5635 100644 --- a/cmake/abi_check.cmake +++ b/cmake/abi_check.cmake @@ -55,6 +55,17 @@ IF(CMAKE_COMPILER_IS_GNUCC AND RUN_ABI_CHECK) VERBATIM ) + ADD_CUSTOM_TARGET(abi_update + COMMAND ${CMAKE_COMMAND} + -DCOMPILER=${COMPILER} + -DABI_UPDATE=1 + -DSOURCE_DIR=${CMAKE_SOURCE_DIR} + -DBINARY_DIR=${CMAKE_BINARY_DIR} + "-DABI_HEADERS=${API_PREPROCESSOR_HEADER}" + -P ${CMAKE_SOURCE_DIR}/cmake/do_abi_check.cmake + VERBATIM + ) + ADD_CUSTOM_TARGET(abi_check_all COMMAND ${CMAKE_COMMAND} -DCOMPILER=${COMPILER} diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake index 6760f2c9c63..87fe47cac12 100644 --- a/cmake/build_configurations/mysql_release.cmake +++ b/cmake/build_configurations/mysql_release.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2011, 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 diff --git a/cmake/do_abi_check.cmake b/cmake/do_abi_check.cmake index e42f11abde2..c831aaf8b52 100644 --- a/cmake/do_abi_check.cmake +++ b/cmake/do_abi_check.cmake @@ -75,8 +75,12 @@ FOREACH(file ${ABI_HEADERS}) EXECUTE_PROCESS( COMMAND diff -w ${file}.pp ${abi_check_out} RESULT_VARIABLE result) IF(NOT ${result} EQUAL 0) - MESSAGE(FATAL_ERROR - "ABI check found difference between ${file}.pp and ${abi_check_out}") + IF(ABI_UPDATE) + EXECUTE_PROCESS(COMMAND mv -v ${abi_check_out} ${file}.pp) + ELSE(ABI_UPDATE) + MESSAGE(FATAL_ERROR + "ABI check found difference between ${file}.pp and ${abi_check_out}") + ENDIF(ABI_UPDATE) ENDIF() FILE(REMOVE ${abi_check_out}) ENDFOREACH() diff --git a/cmake/install_layout.cmake b/cmake/install_layout.cmake index 38d3fd3d01e..76e78e8b72f 100644 --- a/cmake/install_layout.cmake +++ b/cmake/install_layout.cmake @@ -115,7 +115,7 @@ SET(INSTALL_SCRIPTDIR_STANDALONE "scripts") SET(INSTALL_LIBDIR_STANDALONE "lib") SET(INSTALL_PLUGINDIR_STANDALONE "lib/plugin") # -SET(INSTALL_INCLUDEDIR_STANDALONE "include") +SET(INSTALL_INCLUDEDIR_STANDALONE "include/mysql") # SET(INSTALL_DOCDIR_STANDALONE "docs") SET(INSTALL_DOCREADMEDIR_STANDALONE ".") @@ -198,7 +198,7 @@ SET(INSTALL_SCRIPTDIR_SVR4 "scripts") SET(INSTALL_LIBDIR_SVR4 "lib") SET(INSTALL_PLUGINDIR_SVR4 "lib/plugin") # -SET(INSTALL_INCLUDEDIR_SVR4 "include") +SET(INSTALL_INCLUDEDIR_SVR4 "include/mysql") # SET(INSTALL_DOCDIR_SVR4 "docs") SET(INSTALL_DOCREADMEDIR_SVR4 ".") diff --git a/cmake/install_macros.cmake b/cmake/install_macros.cmake index c668b38eef3..14e43ee5e95 100644 --- a/cmake/install_macros.cmake +++ b/cmake/install_macros.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2011, 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 @@ -40,17 +40,26 @@ FUNCTION (INSTALL_DEBUG_SYMBOLS) IF(CMAKE_GENERATOR MATCHES "Visual Studio") STRING(REPLACE "${CMAKE_CFG_INTDIR}" "\${CMAKE_INSTALL_CONFIG_NAME}" pdb_location ${pdb_location}) ENDIF() - IF(ARG_COMPONENT STREQUAL "Server" AND (target MATCHES "mysqld" OR type MATCHES "MODULE")) - #MESSAGE("PDB: ${targets}") - SET(comp Server) - ELSEIF(ARG_COMPONENT MATCHES Development - OR ARG_COMPONENT MATCHES SharedLibraries - OR ARG_COMPONENT MATCHES Embedded) + + set(comp "") + IF(ARG_COMPONENT STREQUAL "Server") + IF(target MATCHES "mysqld" OR type MATCHES "MODULE") + #MESSAGE("PDB: ${targets}") + SET(comp Server) + ENDIF() + ENDIF() + + IF(NOT comp MATCHES Server) + IF(ARG_COMPONENT MATCHES Development + OR ARG_COMPONENT MATCHES SharedLibraries + OR ARG_COMPONENT MATCHES Embedded) + SET(comp Debuginfo) + ENDIF() + ENDIF() - SET(comp Debuginfo) - ELSE() + IF(NOT comp) SET(comp Debuginfo_archive_only) # not in MSI - ENDIF() + ENDIF() INSTALL(FILES ${pdb_location} DESTINATION ${ARG_INSTALL_LOCATION} COMPONENT ${comp}) ENDFOREACH() ENDIF() diff --git a/cmake/make_dist.cmake.in b/cmake/make_dist.cmake.in index 5aa1fc8fd0e..1b347e41836 100644 --- a/cmake/make_dist.cmake.in +++ b/cmake/make_dist.cmake.in @@ -120,8 +120,13 @@ CONFIGURE_FILE(${CMAKE_BINARY_DIR}/sql/sql_yacc.cc ${PACKAGE_DIR}/sql/sql_yacc.cc COPYONLY) # Copy spec files -CONFIGURE_FILE(${CMAKE_BINARY_DIR}/support-files/mysql.${VERSION}.spec - ${PACKAGE_DIR}/support-files/mysql.${VERSION}.spec COPYONLY) +SET(SPECFILENAME "mysql.${VERSION}.spec") +IF("${VERSION}" MATCHES "-ndb-") + STRING(REGEX REPLACE "^.*-ndb-" "" NDBVERSION "${VERSION}") + SET(SPECFILENAME "mysql-cluster-${NDBVERSION}.spec") +ENDIF() +CONFIGURE_FILE(${CMAKE_BINARY_DIR}/support-files/${SPECFILENAME} + ${PACKAGE_DIR}/support-files/${SPECFILENAME} COPYONLY) # Add documentation, if user has specified where to find them IF(MYSQL_DOCS_LOCATION) diff --git a/cmake/mysql_version.cmake b/cmake/mysql_version.cmake index 4a9f35e6b35..5f60cb68101 100644 --- a/cmake/mysql_version.cmake +++ b/cmake/mysql_version.cmake @@ -57,7 +57,10 @@ MACRO(GET_MYSQL_VERSION) MESSAGE("-- MariaDB ${VERSION}") SET(MYSQL_BASE_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}" CACHE INTERNAL "MySQL Base version") SET(MYSQL_NO_DASH_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}") - STRING(REPLACE "-" "_" MYSQL_RPM_VERSION "${VERSION}") + # Use NDBVERSION irregardless of whether this is Cluster or not, if not + # then the regex will be ignored anyway. + STRING(REGEX REPLACE "^.*-ndb-" "" NDBVERSION "${VERSION}") + STRING(REPLACE "-" "_" MYSQL_RPM_VERSION "${NDBVERSION}") MATH(EXPR MYSQL_VERSION_ID "10000*${MAJOR_VERSION} + 100*${MINOR_VERSION} + ${PATCH_VERSION}") MARK_AS_ADVANCED(VERSION MYSQL_VERSION_ID MYSQL_BASE_VERSION) SET(CPACK_PACKAGE_VERSION_MAJOR ${MAJOR_VERSION}) @@ -93,6 +96,10 @@ ENDIF() IF(NOT CPACK_SOURCE_PACKAGE_FILE_NAME) SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-${VERSION}") + IF("${VERSION}" MATCHES "-ndb-") + STRING(REGEX REPLACE "^.*-ndb-" "" NDBVERSION "${VERSION}") + SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mysql-cluster-gpl-${NDBVERSION}") + ENDIF() ENDIF() SET(CPACK_PACKAGE_CONTACT "MariaDB team <info@montyprogram.com>") SET(CPACK_PACKAGE_VENDOR "Monty Program AB") diff --git a/cmake/os/WindowsCache.cmake b/cmake/os/WindowsCache.cmake index fb3d3d88678..8456cd69b0b 100644 --- a/cmake/os/WindowsCache.cmake +++ b/cmake/os/WindowsCache.cmake @@ -137,6 +137,7 @@ SET(HAVE_PATHS_H CACHE INTERNAL "") SET(HAVE_PCLOSE CACHE INTERNAL "") SET(HAVE_PERROR 1 CACHE INTERNAL "") SET(HAVE_PEERCRED CACHE INTERNAL "") +SET(HAVE_PAM_APPL_H CACHE INTERNAL "") SET(HAVE_POLL_H CACHE INTERNAL "") SET(HAVE_POPEN CACHE INTERNAL "") SET(HAVE_POLL CACHE INTERNAL "") @@ -248,6 +249,7 @@ SET(HAVE_STRING_H 1 CACHE INTERNAL "") SET(HAVE_STRLCAT CACHE INTERNAL "") SET(HAVE_STRLCPY CACHE INTERNAL "") SET(HAVE_STRNCASECMP CACHE INTERNAL "") +SET(HAVE_STRNDUP CACHE INTERNAL "") IF(MSVC_VERSION GREATER 1310) SET(HAVE_STRNLEN 1 CACHE INTERNAL "") ENDIF() diff --git a/cmake/package_name.cmake b/cmake/package_name.cmake index 212fa99d7f0..5c99a110e7c 100644 --- a/cmake/package_name.cmake +++ b/cmake/package_name.cmake @@ -123,8 +123,15 @@ IF(NOT VERSION) SET(PRODUCT_TAG) ENDIF() - SET(package_name "mariadb${PRODUCT_TAG}-${VERSION}-${SYSTEM_NAME_AND_PROCESSOR}") - + IF("${VERSION}" MATCHES "-ndb-") + STRING(REGEX REPLACE "^.*-ndb-" "" NDBVERSION "${VERSION}") + SET(package_name "mysql-cluster${PRODUCT_TAG}-${NDBVERSION}-${SYSTEM_NAME_AND_PROCESSOR}") + ELSE() + SET(package_name "mariadb${PRODUCT_TAG}-${VERSION}-${SYSTEM_NAME_AND_PROCESSOR}") + ENDIF() + + MESSAGE("-- Packaging as: ${package_name}") + # Sometimes package suffix is added (something like "-icc-glibc23") IF(PACKAGE_SUFFIX) SET(package_name "${package_name}${PACKAGE_SUFFIX}") diff --git a/cmake/readline.cmake b/cmake/readline.cmake index 49ab92f8bdb..fd2e690fab9 100644 --- a/cmake/readline.cmake +++ b/cmake/readline.cmake @@ -210,7 +210,10 @@ MACRO (MYSQL_CHECK_READLINE) IF(WITH_READLINE) MYSQL_USE_BUNDLED_READLINE() ELSE() - MYSQL_FIND_SYSTEM_READLINE() + # OSX includes incompatible readline lib + IF (NOT APPLE) + MYSQL_FIND_SYSTEM_READLINE() + ENDIF() IF(NOT USE_NEW_READLINE_INTERFACE) MYSQL_FIND_SYSTEM_LIBEDIT() IF(NOT USE_LIBEDIT_INTERFACE) diff --git a/cmd-line-utils/libedit/chartype.h b/cmd-line-utils/libedit/chartype.h index 40012afb47d..576abe13ad5 100644 --- a/cmd-line-utils/libedit/chartype.h +++ b/cmd-line-utils/libedit/chartype.h @@ -49,7 +49,7 @@ TODO : Verify if FreeBSD & AIX stores ISO 10646 in wchar_t. */ #if !defined(__NetBSD__) && !defined(__sun) \ && !(defined(__APPLE__) && defined(__MACH__)) \ - && !defined(__FreeBSD__) && !defined(_AIX) + && !defined(__FreeBSD__) && !defined(_AIX) && !defined(__OpenBSD__) #ifndef __STDC_ISO_10646__ /* In many places it is assumed that the first 127 code points are ASCII * compatible, so ensure wchar_t indeed does ISO 10646 and not some other diff --git a/cmd-line-utils/libedit/np/unvis.c b/cmd-line-utils/libedit/np/unvis.c index 812d280b2d8..a911720ad35 100644 --- a/cmd-line-utils/libedit/np/unvis.c +++ b/cmd-line-utils/libedit/np/unvis.c @@ -64,7 +64,7 @@ static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93"; #include "np/vis.h" #ifdef __weak_alias -__weak_alias(strnunvisx,_strnunvisx) +__weak_alias(strnunvisx,_strnunvisx); #endif #if !HAVE_VIS diff --git a/cmd-line-utils/libedit/np/vis.c b/cmd-line-utils/libedit/np/vis.c index d7cc37b4f47..884a7894332 100644 --- a/cmd-line-utils/libedit/np/vis.c +++ b/cmd-line-utils/libedit/np/vis.c @@ -77,7 +77,7 @@ #include <stdlib.h> #ifdef __weak_alias -__weak_alias(strvisx,_strvisx) +__weak_alias(strvisx,_strvisx); #endif #if !HAVE_VIS || !HAVE_SVIS diff --git a/config.h.cmake b/config.h.cmake index 529e1c7ad1d..d03ad91189c 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -589,6 +589,8 @@ #cmakedefine WITH_MYISAM_STORAGE_ENGINE 1 #cmakedefine WITH_MYISAMMRG_STORAGE_ENGINE 1 #cmakedefine WITH_HEAP_STORAGE_ENGINE 1 +#cmakedefine WITH_INNOBASE_STORAGE_ENGINE 1 +#cmakedefine WITH_XTRADB_STORAGE_ENGINE 1 #cmakedefine WITH_CSV_STORAGE_ENGINE 1 #cmakedefine WITH_PARTITION_STORAGE_ENGINE 1 #cmakedefine WITH_PERFSCHEMA_STORAGE_ENGINE 1 diff --git a/configure.cmake b/configure.cmake index 66ee73ddc03..bf2a08386ab 100644 --- a/configure.cmake +++ b/configure.cmake @@ -149,7 +149,9 @@ IF(UNIX) SET(CMAKE_REQUIRED_LIBRARIES ${LIBM} ${LIBNSL} ${LIBBIND} ${LIBCRYPT} ${LIBSOCKET} ${LIBDL} ${CMAKE_THREAD_LIBS_INIT} ${LIBRT}) - LIST(REMOVE_DUPLICATES CMAKE_REQUIRED_LIBRARIES) + IF(CMAKE_REQUIRED_LIBRARIES) + LIST(REMOVE_DUPLICATES CMAKE_REQUIRED_LIBRARIES) + ENDIF() LINK_LIBRARIES(${CMAKE_THREAD_LIBS_INIT}) OPTION(WITH_LIBWRAP "Compile with tcp wrappers support" OFF) @@ -397,6 +399,7 @@ CHECK_FUNCTION_EXISTS (pread HAVE_PREAD) CHECK_FUNCTION_EXISTS (pthread_attr_create HAVE_PTHREAD_ATTR_CREATE) CHECK_FUNCTION_EXISTS (pthread_attr_getstacksize HAVE_PTHREAD_ATTR_GETSTACKSIZE) CHECK_FUNCTION_EXISTS (pthread_attr_setscope HAVE_PTHREAD_ATTR_SETSCOPE) +CHECK_FUNCTION_EXISTS (pthread_attr_getguardsize HAVE_PTHREAD_ATTR_GETGUARDSIZE) CHECK_FUNCTION_EXISTS (pthread_attr_setstacksize HAVE_PTHREAD_ATTR_SETSTACKSIZE) CHECK_FUNCTION_EXISTS (pthread_condattr_create HAVE_PTHREAD_CONDATTR_CREATE) CHECK_FUNCTION_EXISTS (pthread_condattr_setclock HAVE_PTHREAD_CONDATTR_SETCLOCK) @@ -435,7 +438,6 @@ CHECK_FUNCTION_EXISTS (strlcat HAVE_STRLCAT) CHECK_FUNCTION_EXISTS (strsignal HAVE_STRSIGNAL) CHECK_FUNCTION_EXISTS (fgetln HAVE_FGETLN) CHECK_FUNCTION_EXISTS (strpbrk HAVE_STRPBRK) -CHECK_FUNCTION_EXISTS (strsep HAVE_STRSEP) CHECK_FUNCTION_EXISTS (strstr HAVE_STRSTR) CHECK_FUNCTION_EXISTS (strtok_r HAVE_STRTOK_R) CHECK_FUNCTION_EXISTS (strtol HAVE_STRTOL) diff --git a/dbug/CMakeLists.txt b/dbug/CMakeLists.txt index a4f30f75f97..fddf234a4f1 100644 --- a/dbug/CMakeLists.txt +++ b/dbug/CMakeLists.txt @@ -27,7 +27,7 @@ TARGET_LINK_LIBRARIES(tests dbug) ADD_EXECUTABLE(factorial my_main.c factorial.c) TARGET_LINK_LIBRARIES(factorial dbug) -IF(NOT WIN32) +IF(NOT WIN32 AND NOT CMAKE_GENERATOR MATCHES Xcode) FIND_PROGRAM(GROFF groff) FIND_PROGRAM(NROFF nroff) SET(OUTPUT_INC output1.r output2.r output3.r output4.r output5.r) @@ -63,5 +63,5 @@ IF(NOT WIN32) ADD_CUSTOM_TARGET(t ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/user.t) ENDIF(NROFF) -ENDIF(NOT WIN32) +ENDIF() diff --git a/dbug/dbug.c b/dbug/dbug.c index 799c6bc8113..af0a937ff07 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -172,6 +172,20 @@ struct link { #define NOT_MATCHED 0 /* + * Debugging settings can be shared between threads. + * But FILE* streams cannot normally be shared - what if + * one thread closes a stream, while another thread still uses it? + * As a workaround, we have shared FILE pointers with reference counters + */ +typedef struct { + FILE *file; + uint used; +} sFILE; + +sFILE shared_stdout = { 0, 1 << 30 }, *sstdout = &shared_stdout; +sFILE shared_stderr = { 0, 1 << 30 }, *sstderr = &shared_stderr; + +/* * Debugging settings can be pushed or popped off of a * stack which is implemented as a linked list. Note * that the head of the list is the current settings and the @@ -186,7 +200,7 @@ struct settings { uint maxdepth; /* Current maximum trace depth */ uint delay; /* Delay after each output line */ uint sub_level; /* Sub this from code_state->level */ - FILE *out_file; /* Current output stream */ + sFILE *out_file; /* Current output stream */ char name[FN_REFLEN]; /* Name of output file */ struct link *functions; /* List of functions */ struct link *keywords; /* List of debug keywords */ @@ -251,11 +265,11 @@ static void FreeList(struct link *linkp); /* OpenClose debug output stream */ static void DBUGOpenFile(CODE_STATE *,const char *, const char *, int); -static void DBUGCloseFile(CODE_STATE *cs, FILE *fp); +static void DBUGCloseFile(CODE_STATE *cs, sFILE *new_value); /* Push current debug settings */ static void PushState(CODE_STATE *cs); /* Free memory associated with debug state. */ -static void FreeState (CODE_STATE *cs, struct settings *state, int free_state); +static void FreeState (CODE_STATE *cs, int free_state); /* Test for tracing enabled */ static int DoTrace(CODE_STATE *cs); /* @@ -328,9 +342,11 @@ static CODE_STATE *code_state(void) if (!init_done) { init_done=TRUE; + sstdout->file= stdout; + sstderr->file= stderr; pthread_mutex_init(&THR_LOCK_dbug, NULL); bzero(&init_settings, sizeof(init_settings)); - init_settings.out_file=stderr; + init_settings.out_file= sstderr; init_settings.flags=OPEN_APPEND; } @@ -455,12 +471,12 @@ static int DbugParse(CODE_STATE *cs, const char *control) rel= control[0] == '+' || control[0] == '-'; if ((!rel || (!stack->out_file && !stack->next))) { - FreeState(cs, stack, 0); + FreeState(cs, 0); stack->flags= 0; stack->delay= 0; stack->maxdepth= 0; stack->sub_level= 0; - stack->out_file= stderr; + stack->out_file= sstderr; stack->functions= NULL; stack->keywords= NULL; stack->processes= NULL; @@ -472,22 +488,17 @@ static int DbugParse(CODE_STATE *cs, const char *control) stack->maxdepth= stack->next->maxdepth; stack->sub_level= stack->next->sub_level; strcpy(stack->name, stack->next->name); + stack->out_file= stack->next->out_file; + stack->out_file->used++; if (stack->next == &init_settings) { - /* - Never share with the global parent - it can change under your feet. - - Reset out_file to stderr to prevent sharing of trace files between - global and session settings. - */ - stack->out_file= stderr; + /* never share with the global parent - it can change under your feet */ stack->functions= ListCopy(init_settings.functions); stack->keywords= ListCopy(init_settings.keywords); stack->processes= ListCopy(init_settings.processes); } else { - stack->out_file= stack->next->out_file; stack->functions= stack->next->functions; stack->keywords= stack->next->keywords; stack->processes= stack->next->processes; @@ -581,10 +592,8 @@ static int DbugParse(CODE_STATE *cs, const char *control) case 'o': if (sign < 0) { - if (!is_shared(stack, out_file)) - DBUGCloseFile(cs, stack->out_file); + DBUGCloseFile(cs, sstderr); stack->flags &= ~FLUSH_ON_WRITE; - stack->out_file= stderr; break; } if (c == 'a' || c == 'A') @@ -884,18 +893,15 @@ void _db_set_init_(const char *control) void _db_pop_() { - struct settings *discard; uint old_fflags; CODE_STATE *cs; get_code_state_or_return; - discard= cs->stack; - if (discard != &init_settings) + if (cs->stack != &init_settings) { old_fflags=fflags(cs); - cs->stack= discard->next; - FreeState(cs, discard, 1); + FreeState(cs, 1); FixTraceFlags(old_fflags, cs); } } @@ -1009,7 +1015,7 @@ int _db_explain_ (CODE_STATE *cs, char *buf, size_t len) op_str_to_buf( ((cs->stack->flags & FLUSH_ON_WRITE ? 0 : 32) | (cs->stack->flags & OPEN_APPEND ? 'A' : 'O')), - cs->stack->name, cs->stack->out_file != stderr); + cs->stack->name, cs->stack->out_file != sstderr); op_list_to_buf('p', cs->stack->processes, cs->stack->processes); op_bool_to_buf('P', cs->stack->flags & PROCESS_ON); op_bool_to_buf('r', cs->stack->sub_level != 0); @@ -1125,7 +1131,7 @@ void _db_enter_(const char *_func_, const char *_file_, pthread_mutex_lock(&THR_LOCK_dbug); DoPrefix(cs, _line_); Indent(cs, cs->level); - (void) fprintf(cs->stack->out_file, ">%s\n", cs->func); + (void) fprintf(cs->stack->out_file->file, ">%s\n", cs->func); DbugFlush(cs); /* This does a unlock */ } break; @@ -1182,7 +1188,7 @@ void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_) pthread_mutex_lock(&THR_LOCK_dbug); DoPrefix(cs, _line_); Indent(cs, cs->level); - (void) fprintf(cs->stack->out_file, "<%s\n", cs->func); + (void) fprintf(cs->stack->out_file->file, "<%s\n", cs->func); DbugFlush(cs); } } @@ -1271,9 +1277,9 @@ void _db_doprnt_(const char *format,...) if (TRACING) Indent(cs, cs->level + 1); else - (void) fprintf(cs->stack->out_file, "%s: ", cs->func); - (void) fprintf(cs->stack->out_file, "%s: ", cs->u_keyword); - DbugVfprintf(cs->stack->out_file, format, args); + (void) fprintf(cs->stack->out_file->file, "%s: ", cs->func); + (void) fprintf(cs->stack->out_file->file, "%s: ", cs->u_keyword); + DbugVfprintf(cs->stack->out_file->file, format, args); DbugFlush(cs); errno=save_errno; } @@ -1333,9 +1339,9 @@ void _db_dump_(uint _line_, const char *keyword, } else { - fprintf(cs->stack->out_file, "%s: ", cs->func); + fprintf(cs->stack->out_file->file, "%s: ", cs->func); } - (void) fprintf(cs->stack->out_file, "%s: Memory: 0x%lx Bytes: (%ld)\n", + (void) fprintf(cs->stack->out_file->file, "%s: Memory: 0x%lx Bytes: (%ld)\n", keyword, (ulong) memory, (long) length); pos=0; @@ -1344,14 +1350,14 @@ void _db_dump_(uint _line_, const char *keyword, uint tmp= *((unsigned char*) memory++); if ((pos+=3) >= 80) { - fputc('\n',cs->stack->out_file); + fputc('\n',cs->stack->out_file->file); pos=3; } - fputc(_dig_vec_upper[((tmp >> 4) & 15)], cs->stack->out_file); - fputc(_dig_vec_upper[tmp & 15], cs->stack->out_file); - fputc(' ',cs->stack->out_file); + fputc(_dig_vec_upper[((tmp >> 4) & 15)], cs->stack->out_file->file); + fputc(_dig_vec_upper[tmp & 15], cs->stack->out_file->file); + fputc(' ',cs->stack->out_file->file); } - (void) fputc('\n',cs->stack->out_file); + (void) fputc('\n',cs->stack->out_file->file); DbugFlush(cs); } else if (!cs->locked) @@ -1578,8 +1584,9 @@ static void PushState(CODE_STATE *cs) * state. If free_state is set, also free 'state' * */ -static void FreeState(CODE_STATE *cs, struct settings *state, int free_state) +static void FreeState(CODE_STATE *cs, int free_state) { + struct settings *state= cs->stack; if (!is_shared(state, keywords)) FreeList(state->keywords); if (!is_shared(state, functions)) @@ -1587,13 +1594,14 @@ static void FreeState(CODE_STATE *cs, struct settings *state, int free_state) if (!is_shared(state, processes)) FreeList(state->processes); - if (!is_shared(state, out_file)) - DBUGCloseFile(cs, state->out_file); - else - (void) fflush(state->out_file); + DBUGCloseFile(cs, NULL); if (free_state) - free((void*) state); + { + struct settings *next= state->next; + free(state); + cs->stack= next; + } } @@ -1616,9 +1624,7 @@ static void FreeState(CODE_STATE *cs, struct settings *state, int free_state) */ void _db_end_() { - struct settings *discard; - static struct settings tmp; - CODE_STATE *cs; + CODE_STATE *cs, dummy_cs; /* Set _dbug_on_ to be able to do full reset even when DEBUGGER_OFF was called after dbug was initialized @@ -1627,24 +1633,18 @@ void _db_end_() cs= code_state(); if (cs) - while ((discard= cs->stack)) - { - if (discard == &init_settings) - break; - cs->stack= discard->next; - FreeState(cs, discard, 1); - } - tmp= init_settings; - - init_settings.flags= OPEN_APPEND; - init_settings.out_file= stderr; - init_settings.maxdepth= 0; - init_settings.delay= 0; - init_settings.sub_level= 0; - init_settings.functions= 0; - init_settings.keywords= 0; - init_settings.processes= 0; - FreeState(cs, &tmp, 0); + { + while (cs->stack && cs->stack != &init_settings) + FreeState(cs, 1); + } + else + { + cs= &dummy_cs; + bzero(cs, sizeof(*cs)); + } + + cs->stack= &init_settings; + FreeState(cs, 0); } @@ -1683,7 +1683,7 @@ FILE *_db_fp_(void) { CODE_STATE *cs; get_code_state_or_return NULL; - return cs->stack->out_file; + return cs->stack->out_file->file; } /* @@ -1744,9 +1744,9 @@ static void Indent(CODE_STATE *cs, int indent) for (count= 0; count < indent ; count++) { if ((count % INDENT) == 0) - fputc('|',cs->stack->out_file); + fputc('|',cs->stack->out_file->file); else - fputc(' ',cs->stack->out_file); + fputc(' ',cs->stack->out_file->file); } } @@ -1805,10 +1805,10 @@ static void DoPrefix(CODE_STATE *cs, uint _line_) cs->lineno++; if (cs->stack->flags & PID_ON) { - (void) fprintf(cs->stack->out_file, "%-7s: ", my_thread_name()); + (void) fprintf(cs->stack->out_file->file, "%-7s: ", my_thread_name()); } if (cs->stack->flags & NUMBER_ON) - (void) fprintf(cs->stack->out_file, "%5d: ", cs->lineno); + (void) fprintf(cs->stack->out_file->file, "%5d: ", cs->lineno); if (cs->stack->flags & TIMESTAMP_ON) { #ifdef __WIN__ @@ -1816,7 +1816,7 @@ static void DoPrefix(CODE_STATE *cs, uint _line_) in system ticks, 10 ms intervals. See my_getsystime.c for high res */ SYSTEMTIME loc_t; GetLocalTime(&loc_t); - (void) fprintf (cs->stack->out_file, + (void) fprintf (cs->stack->out_file->file, /* "%04d-%02d-%02d " */ "%02d:%02d:%02d.%06d ", /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/ @@ -1828,7 +1828,7 @@ static void DoPrefix(CODE_STATE *cs, uint _line_) { if ((tm_p= localtime((const time_t *)&tv.tv_sec))) { - (void) fprintf (cs->stack->out_file, + (void) fprintf (cs->stack->out_file->file, /* "%04d-%02d-%02d " */ "%02d:%02d:%02d.%06d ", /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/ @@ -1839,13 +1839,13 @@ static void DoPrefix(CODE_STATE *cs, uint _line_) #endif } if (cs->stack->flags & PROCESS_ON) - (void) fprintf(cs->stack->out_file, "%s: ", cs->process); + (void) fprintf(cs->stack->out_file->file, "%s: ", cs->process); if (cs->stack->flags & FILE_ON) - (void) fprintf(cs->stack->out_file, "%14s: ", BaseName(cs->file)); + (void) fprintf(cs->stack->out_file->file, "%14s: ", BaseName(cs->file)); if (cs->stack->flags & LINE_ON) - (void) fprintf(cs->stack->out_file, "%5d: ", _line_); + (void) fprintf(cs->stack->out_file->file, "%5d: ", _line_); if (cs->stack->flags & DEPTH_ON) - (void) fprintf(cs->stack->out_file, "%4d: ", cs->level); + (void) fprintf(cs->stack->out_file->file, "%4d: ", cs->level); } @@ -1884,9 +1884,7 @@ static void DBUGOpenFile(CODE_STATE *cs, name=cs->stack->name; if (strcmp(name, "-") == 0) { - if (!is_shared(cs->stack, out_file)) - DBUGCloseFile(cs, cs->stack->out_file); - cs->stack->out_file= stdout; + DBUGCloseFile(cs, sstdout); cs->stack->flags |= FLUSH_ON_WRITE; cs->stack->name[0]=0; } @@ -1908,9 +1906,10 @@ static void DBUGOpenFile(CODE_STATE *cs, } else { - if (!is_shared(cs->stack, out_file)) - DBUGCloseFile(cs, cs->stack->out_file); - cs->stack->out_file= fp; + sFILE *sfp= (sFILE *)DbugMalloc(sizeof(sFILE)); + sfp->file= fp; + sfp->used= 1; + DBUGCloseFile(cs, sfp); } } } @@ -1934,16 +1933,30 @@ static void DBUGOpenFile(CODE_STATE *cs, * */ -static void DBUGCloseFile(CODE_STATE *cs, FILE *fp) +static void DBUGCloseFile(CODE_STATE *cs, sFILE *new_value) { - if (cs && fp && fp != stderr && fp != stdout && fclose(fp) == EOF) + sFILE *fp; + if (!cs || !cs->stack || !cs->stack->out_file) + return; + if (!cs->locked) + pthread_mutex_lock(&THR_LOCK_dbug); + + fp= cs->stack->out_file; + if (--fp->used == 0) { - if (!cs->locked) - pthread_mutex_lock(&THR_LOCK_dbug); - (void) fprintf(cs->stack->out_file, ERR_CLOSE, cs->process); - perror(""); - DbugFlush(cs); + if (fclose(fp->file) == EOF) + { + (void) fprintf(stderr, ERR_CLOSE, cs->process); + perror(""); + } + else + { + free(fp); + } } + cs->stack->out_file= new_value; + if (!cs->locked) + pthread_mutex_unlock(&THR_LOCK_dbug); } @@ -2111,7 +2124,7 @@ static void DbugFlush(CODE_STATE *cs) { if (cs->stack->flags & FLUSH_ON_WRITE) { - (void) fflush(cs->stack->out_file); + (void) fflush(cs->stack->out_file->file); if (cs->stack->delay) (void) Delay(cs->stack->delay); } @@ -2126,7 +2139,7 @@ void _db_flush_() { CODE_STATE *cs; get_code_state_or_return; - (void) fflush(cs->stack->out_file); + (void) fflush(cs->stack->out_file->file); } diff --git a/dbug/tests.c b/dbug/tests.c index 5950c5fa583..657ed638a5a 100644 --- a/dbug/tests.c +++ b/dbug/tests.c @@ -38,10 +38,10 @@ int func1() int main (int argc, char *argv[]) { - int i; #ifdef DBUG_OFF return 1; -#endif +#else + int i; if (argc == 1) return 0; @@ -83,4 +83,5 @@ int main (int argc, char *argv[]) DBUG_SET(""); /* to not have my_end() in the traces */ my_end(0); return 0; +#endif /* DBUG_OFF */ } diff --git a/debian/dist/Debian/rules b/debian/dist/Debian/rules index 457502882c4..5cb22ae60d6 100755 --- a/debian/dist/Debian/rules +++ b/debian/dist/Debian/rules @@ -169,8 +169,6 @@ install: build # libmysqlclient-dev: forgotten header file since 3.23.25? cp $(BUILDDIR)/include/my_config.h $(TMP)/usr/include/mysql/ cp include/my_dir.h $(TMP)/usr/include/mysql/ - mv $(TMP)/usr/include/mysql/mysql/*.h $(TMP)/usr/include/mysql/ - mv $(TMP)/usr/include/mysql/mysql/psi $(TMP)/usr/include/mysql/ # mysql-common: We provide our own version of this package for # completeness, but we can use an existing version; mariadb-specic diff --git a/debian/dist/Ubuntu/rules b/debian/dist/Ubuntu/rules index 69e1cba2893..592b2e4d7d1 100755 --- a/debian/dist/Ubuntu/rules +++ b/debian/dist/Ubuntu/rules @@ -169,8 +169,6 @@ install: build # libmysqlclient-dev: forgotten header file since 3.23.25? cp $(BUILDDIR)/include/my_config.h $(TMP)/usr/include/mysql/ cp include/my_dir.h $(TMP)/usr/include/mysql/ - mv $(TMP)/usr/include/mysql/mysql/*.h $(TMP)/usr/include/mysql/ - mv $(TMP)/usr/include/mysql/mysql/psi $(TMP)/usr/include/mysql/ # mysql-common: We provide our own version of this package for # completeness, but we can use an existing version; mariadb-specic diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c index a25381c4808..8a16e677cb9 100644 --- a/extra/my_print_defaults.c +++ b/extra/my_print_defaults.c @@ -67,7 +67,7 @@ static struct my_option my_long_options[] = {"defaults-extra-file", 'e', "Read this file after the global config file and before the config " "file in the users home directory; should be the first option", - &my_defaults_extra_file, &my_defaults_extra_file, 0, + (void *)&my_defaults_extra_file, (void *)&my_defaults_extra_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"defaults-group-suffix", 'g', "In addition to the given groups, read also groups with this suffix", @@ -75,8 +75,8 @@ static struct my_option my_long_options[] = 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"extra-file", 'e', "Deprecated. Synonym for --defaults-extra-file.", - &my_defaults_extra_file, - &my_defaults_extra_file, 0, GET_STR, + (void *)&my_defaults_extra_file, + (void *)&my_defaults_extra_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"no-defaults", 'n', "Return an empty string (useful for scripts).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/extra/yassl/INSTALL b/extra/yassl/INSTALL index 54caf7c190f..5458714e1e2 100644 --- a/extra/yassl/INSTALL +++ b/extra/yassl/INSTALL @@ -1,13 +1,19 @@ -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software -Foundation, Inc. +Installation Instructions +************************* - This file is free documentation; the Free Software Foundation gives +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006 Free Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== - These are generic installation instructions. +Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses @@ -20,9 +26,9 @@ debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. (Caching is +the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale -cache files.) +cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail @@ -32,20 +38,17 @@ some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You only need -`configure.ac' if you want to change it or regenerate `configure' using -a newer version of `autoconf'. +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. + `./configure' to configure the package for your system. - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. 2. Type `make' to compile the package. @@ -67,51 +70,49 @@ The simplest way to compile this package is: Compilers and Options ===================== - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. Run `./configure --help' -for details on some of the pertinent environment variables. +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: - ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== - You can compile the package for more than one kind of computer at the +You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the +own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. - If you have to use a `make' that does not support the `VPATH' -variable, you have to compile the package for one architecture at a -time in the source code directory. After you have installed the -package for one architecture, use `make distclean' before reconfiguring -for another architecture. + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. Installation Names ================== - By default, `make install' will install the package's files in -`/usr/local/bin', `/usr/local/man', etc. You can specify an -installation prefix other than `/usr/local' by giving `configure' the -option `--prefix=PATH'. +By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you -give `configure' the option `--exec-prefix=PATH', the package will use -PATH as the prefix for installing programs and libraries. -Documentation and other data files will still use the regular prefix. +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give -options like `--bindir=PATH' to specify different values for particular +options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. @@ -122,7 +123,7 @@ option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= - Some packages pay attention to `--enable-FEATURE' options to +Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The @@ -137,11 +138,11 @@ you can use the `configure' options `--x-includes=DIR' and Specifying the System Type ========================== - There may be some features `configure' cannot figure out -automatically, but needs to determine by the type of machine the package -will run on. Usually, assuming the package is built to be run on the -_same_ architectures, `configure' can figure that out, but if it prints -a message saying it cannot guess the machine type, give it the +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: @@ -156,7 +157,7 @@ where SYSTEM can have one of these forms: need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should -use the `--target=TYPE' option to select the type of system they will +use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a @@ -167,9 +168,9 @@ eventually be run) with `--host=TYPE'. Sharing Defaults ================ - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. @@ -178,7 +179,7 @@ A warning: not all `configure' scripts look for a site script. Defining Variables ================== - Variables not defined in a site shell script can be set in the +Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set @@ -186,14 +187,18 @@ them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc -will cause the specified gcc to be used as the C compiler (unless it is +causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + `configure' Invocation ====================== - `configure' recognizes the following options to control how it -operates. +`configure' recognizes the following options to control how it operates. `--help' `-h' diff --git a/extra/yassl/README b/extra/yassl/README index 6c4d101efc0..7720a9453dd 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -1,3 +1,120 @@ +*** Note, Please read *** + +yaSSL takes a different approach to certificate verification than OpenSSL does. +The default policy for the client is to verify the server, this means that if +you don't load CAs to verify the server you'll get a connect error, unable to +verify. It you want to mimic OpenSSL behavior of not verifying the server and +reducing security you can do this by calling: + +SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); + +before calling SSL_new(); + +*** end Note *** + +yaSSL Release notes, version 2.1.2 (9/2/2011) + + This release of yaSSL contains bug fixes, better non-blocking support with + SSL_write, and OpenSSL RSA public key format support. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 2.0.0 (7/6/2010) + + This release of yaSSL contains bug fixes, new testing certs, + and a security patch for a potential heap overflow on forged application + data processing. Vulnerability discovered by Matthieu Bonetti from VUPEN + Security http://www.vupen.com. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.9.9 (1/26/2010) + + This release of yaSSL contains bug fixes, the removal of assert() s and + a security patch for a buffer overflow possibility in certificate name + processing. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.9.8 (10/14/09) + + This release of yaSSL contains bug fixes and adds new stream ciphers + Rabbit and HC-128 + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.9.6 (11/13/08) + + This release of yaSSL contains bug fixes, adds autconf shared library + support and has better server suite detection based on certficate and + private key. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.9.2 (9/24/08) + + This release of yaSSL contains bug fixes and improved certificate verify + callback support. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.8.8 (5/7/08) + + This release of yaSSL contains bug fixes, and better socket handling. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.8.6 (1/31/08) + + This release of yaSSL contains bug fixes, and fixes security problems + associated with using SSL 2.0 client hellos and improper input handling. + Please upgrade to this version if you are using a previous one. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.7.5 (10/15/07) + + This release of yaSSL contains bug fixes, adds MSVC 2005 project support, + GCC 4.2 support, IPV6 support and test, and new test certificates. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.7.2 (8/20/07) + + This release of yaSSL contains bug fixes and adds initial OpenVPN support. + Just configure at this point and beginning of build. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + +*****************yaSSL Release notes, version 1.6.8 (4/16/07) + + This release of yaSSL contains bug fixes and adds SHA-256, SHA-512, SHA-224, + and SHA-384. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0 and note in 1.5.8. + + *****************yaSSL Release notes, version 1.6.0 (2/22/07) This release of yaSSL contains bug fixes, portability enhancements, and @@ -13,7 +130,7 @@ See libcurl build instructions below under 1.3.0 and note in 1.5.8. - Since yaSSL now supports zlib, as does libcur, the libcurl build test can + Since yaSSL now supports zlib, as does libcurl, the libcurl build test can fail if yaSSL is built with zlib support since the zlib library isn't passed. You can do two things to fix this: @@ -518,7 +635,7 @@ in the source and include files. ********************* Contact: please send comments or questions to Todd A Ouska at todd@yassl.com -and/or Larry Stefonic at larry@yassl.com or 425-741-6858. +and/or Larry Stefonic at larry@yassl.com. diff --git a/extra/yassl/certs/ca-cert.pem b/extra/yassl/certs/ca-cert.pem index e353d118712..6a0cf898e53 100644 --- a/extra/yassl/certs/ca-cert.pem +++ b/extra/yassl/certs/ca-cert.pem @@ -1,53 +1,56 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 0 (0x0) + Serial Number: + 8a:37:22:65:73:f5:aa:e8 Signature Algorithm: md5WithRSAEncryption - Issuer: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com + Issuer: C=US, ST=Montana, L=Bozeman, O=sawtooth, OU=consulting, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com Validity - Not Before: Mar 7 03:10:11 2005 GMT - Not After : Apr 1 03:10:11 2046 GMT - Subject: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com + Not Before: Jun 30 18:47:10 2010 GMT + Not After : Mar 26 18:47:10 2013 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=sawtooth, OU=consulting, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (512 bit) Modulus (512 bit): - 00:ef:c1:e3:9a:3c:6e:6e:cb:26:6f:05:be:e0:cb: - 57:a0:4b:68:e6:1b:f9:95:db:01:92:aa:6e:a6:b5: - 2d:b1:2b:50:fd:db:13:f2:c5:d8:b8:4f:75:28:53: - 72:e8:e5:11:9d:bb:c3:4f:4f:09:fd:4c:e7:46:d5: - 1d:bb:35:02:af + 00:97:30:b9:1a:92:ef:25:4f:ca:4c:11:31:95:1a: + e1:c0:10:19:0a:20:b9:37:80:1a:57:38:02:4e:1b: + c5:0f:28:4f:da:e3:c9:16:aa:50:bd:4a:fb:b7:71: + c7:35:cc:63:81:c1:dd:9d:33:f9:38:16:88:32:a0: + aa:56:23:03:a3 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - 1D:EF:A1:B8:81:78:12:47:E8:57:06:08:74:18:F7:D3:AA:D8:F7:BD + 3B:66:FD:A0:40:C6:F4:E2:70:CF:21:1A:0C:4F:67:FE:B7:4B:42:09 X509v3 Authority Key Identifier: - keyid:1D:EF:A1:B8:81:78:12:47:E8:57:06:08:74:18:F7:D3:AA:D8:F7:BD - DirName:/C=US/ST=Oregon/L=Portland/O=sawtooth/CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com - serial:00 + keyid:3B:66:FD:A0:40:C6:F4:E2:70:CF:21:1A:0C:4F:67:FE:B7:4B:42:09 + DirName:/C=US/ST=Montana/L=Bozeman/O=sawtooth/OU=consulting/CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com + serial:8A:37:22:65:73:F5:AA:E8 X509v3 Basic Constraints: CA:TRUE Signature Algorithm: md5WithRSAEncryption - d9:77:e3:07:d9:2e:ec:2f:9b:8e:9e:ca:b4:00:0b:ef:c7:74: - cb:f4:f6:44:2f:02:75:17:a5:74:3e:26:b2:26:fd:1f:ab:3a: - df:d5:e3:05:14:08:d0:8c:1d:c9:3e:e1:59:6f:b3:38:5d:af: - 78:60:e3:c5:6a:69:96:80:7d:00 + 32:65:a2:b1:dc:6d:e0:8d:8b:c8:58:29:8e:b8:18:4b:62:88: + 13:67:f8:6c:75:46:75:8f:8a:19:a6:a3:d5:3c:fc:57:4e:7a: + 68:a9:fc:93:dc:ae:29:7d:bb:4e:ec:ea:55:fa:a4:e3:00:61: + f4:b0:34:6d:d1:d5:a4:64:24:f8 -----BEGIN CERTIFICATE----- -MIIC7zCCApmgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBiTELMAkGA1UEBhMCVVMx -DzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxhbmQxETAPBgNVBAoTCHNh -d3Rvb3RoMSQwIgYDVQQDExt3d3cuc2F3dG9vdGgtY29uc3VsdGluZy5jb20xHTAb -BgkqhkiG9w0BCQEWDmluZm9AeWFzc2wuY29tMB4XDTA1MDMwNzAzMTAxMVoXDTQ2 -MDQwMTAzMTAxMVowgYkxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIEwZPcmVnb24xETAP -BgNVBAcTCFBvcnRsYW5kMREwDwYDVQQKEwhzYXd0b290aDEkMCIGA1UEAxMbd3d3 -LnNhd3Rvb3RoLWNvbnN1bHRpbmcuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlh -c3NsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDvweOaPG5uyyZvBb7gy1eg -S2jmG/mV2wGSqm6mtS2xK1D92xPyxdi4T3UoU3Lo5RGdu8NPTwn9TOdG1R27NQKv -AgMBAAGjgekwgeYwHQYDVR0OBBYEFB3vobiBeBJH6FcGCHQY99Oq2Pe9MIG2BgNV -HSMEga4wgauAFB3vobiBeBJH6FcGCHQY99Oq2Pe9oYGPpIGMMIGJMQswCQYDVQQG -EwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDERMA8GA1UE -ChMIc2F3dG9vdGgxJDAiBgNVBAMTG3d3dy5zYXd0b290aC1jb25zdWx0aW5nLmNv -bTEdMBsGCSqGSIb3DQEJARYOaW5mb0B5YXNzbC5jb22CAQAwDAYDVR0TBAUwAwEB -/zANBgkqhkiG9w0BAQQFAANBANl34wfZLuwvm46eyrQAC+/HdMv09kQvAnUXpXQ+ -JrIm/R+rOt/V4wUUCNCMHck+4Vlvszhdr3hg48VqaZaAfQA= +MIIDQDCCAuqgAwIBAgIJAIo3ImVz9aroMA0GCSqGSIb3DQEBBAUAMIGeMQswCQYD +VQQGEwJVUzEQMA4GA1UECBMHTW9udGFuYTEQMA4GA1UEBxMHQm96ZW1hbjERMA8G +A1UEChMIc2F3dG9vdGgxEzARBgNVBAsTCmNvbnN1bHRpbmcxJDAiBgNVBAMTG3d3 +dy5zYXd0b290aC1jb25zdWx0aW5nLmNvbTEdMBsGCSqGSIb3DQEJARYOaW5mb0B5 +YXNzbC5jb20wHhcNMTAwNjMwMTg0NzEwWhcNMTMwMzI2MTg0NzEwWjCBnjELMAkG +A1UEBhMCVVMxEDAOBgNVBAgTB01vbnRhbmExEDAOBgNVBAcTB0JvemVtYW4xETAP +BgNVBAoTCHNhd3Rvb3RoMRMwEQYDVQQLEwpjb25zdWx0aW5nMSQwIgYDVQQDExt3 +d3cuc2F3dG9vdGgtY29uc3VsdGluZy5jb20xHTAbBgkqhkiG9w0BCQEWDmluZm9A +eWFzc2wuY29tMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJcwuRqS7yVPykwRMZUa +4cAQGQoguTeAGlc4Ak4bxQ8oT9rjyRaqUL1K+7dxxzXMY4HB3Z0z+TgWiDKgqlYj +A6MCAwEAAaOCAQcwggEDMB0GA1UdDgQWBBQ7Zv2gQMb04nDPIRoMT2f+t0tCCTCB +0wYDVR0jBIHLMIHIgBQ7Zv2gQMb04nDPIRoMT2f+t0tCCaGBpKSBoTCBnjELMAkG +A1UEBhMCVVMxEDAOBgNVBAgTB01vbnRhbmExEDAOBgNVBAcTB0JvemVtYW4xETAP +BgNVBAoTCHNhd3Rvb3RoMRMwEQYDVQQLEwpjb25zdWx0aW5nMSQwIgYDVQQDExt3 +d3cuc2F3dG9vdGgtY29uc3VsdGluZy5jb20xHTAbBgkqhkiG9w0BCQEWDmluZm9A +eWFzc2wuY29tggkAijciZXP1qugwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQF +AANBADJlorHcbeCNi8hYKY64GEtiiBNn+Gx1RnWPihmmo9U8/FdOemip/JPcril9 +u07s6lX6pOMAYfSwNG3R1aRkJPg= -----END CERTIFICATE----- diff --git a/extra/yassl/certs/ca-key.pem b/extra/yassl/certs/ca-key.pem new file mode 100644 index 00000000000..45d7b149857 --- /dev/null +++ b/extra/yassl/certs/ca-key.pem @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBOQIBAAJBAJcwuRqS7yVPykwRMZUa4cAQGQoguTeAGlc4Ak4bxQ8oT9rjyRaq +UL1K+7dxxzXMY4HB3Z0z+TgWiDKgqlYjA6MCAwEAAQJAEQ9TY7c+uuQU/J5YDO4a +mRR37tegbq3Kyxqrz+p8QuhqLDtVh13GaF7rVU70vyNHm+cgihUyzho/PViAkPBo +qQIhAMU8/RDhDLgL5BxID4sxKIVBtg+imFSbyKVyg7oQLUcXAiEAxDu94O45Cf4a +np9R0thumY/QqWpCkycWAB7fFEuaf1UCIEH+bg4/vqm2ENUFp23DPPOZUPlaRe3J +UhFJh5mx3/RxAiBq++8vfHFYg1Lb/BxOCXVy/zdRxf753ytdcXdJx1Y56QIgVgpN +FNfYJofQfWaP96sjlc0usrT28uceHx0QmHqolVc= +-----END RSA PRIVATE KEY----- diff --git a/extra/yassl/certs/client-cert.der b/extra/yassl/certs/client-cert.der Binary files differindex c2a75119e54..9c2ef138bf6 100644 --- a/extra/yassl/certs/client-cert.der +++ b/extra/yassl/certs/client-cert.der diff --git a/extra/yassl/certs/client-cert.pem b/extra/yassl/certs/client-cert.pem index 4d2bbff7ca5..7acc9a850d5 100644 --- a/extra/yassl/certs/client-cert.pem +++ b/extra/yassl/certs/client-cert.pem @@ -1,52 +1,55 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 0 (0x0) + Serial Number: + c5:d7:6c:11:36:f0:35:e1 Signature Algorithm: md5WithRSAEncryption - Issuer: C=US, ST=Oregon, L=Portland, O=yaSSL, CN=www.yassl.com/emailAddress=info@yassl.com + Issuer: C=US, ST=Oregon, L=Portland, O=yaSSL, OU=programming, CN=www.yassl.com/emailAddress=info@yassl.com Validity - Not Before: Mar 7 03:00:31 2005 GMT - Not After : Apr 1 03:00:31 2046 GMT - Subject: C=US, ST=Oregon, L=Portland, O=yaSSL, CN=www.yassl.com/emailAddress=info@yassl.com + Not Before: Jun 30 18:39:39 2010 GMT + Not After : Mar 26 18:39:40 2013 GMT + Subject: C=US, ST=Oregon, L=Portland, O=yaSSL, OU=programming, CN=www.yassl.com/emailAddress=info@yassl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (512 bit) Modulus (512 bit): - 00:cd:1f:78:47:f8:b8:d6:08:bf:bd:7c:23:61:86: - 36:28:ac:ee:3c:a8:9a:94:e6:d5:26:e8:71:50:b2: - 26:8b:1c:1e:3f:75:b2:d3:b3:67:95:0c:fd:76:28: - 65:d5:ce:12:82:9e:06:00:a2:09:dd:ce:3a:26:dd: - 46:2a:a0:45:71 + 00:bd:51:4a:14:fd:6a:19:84:0c:33:38:fc:27:32: + 9c:97:0b:fc:a4:18:60:69:4e:d9:d8:78:50:0b:e9: + 20:5d:d6:1d:70:1c:0c:24:9f:23:82:cc:3a:01:d5: + 97:17:b2:73:6c:86:cf:b5:f1:e5:ce:68:0c:d9:a2: + 12:39:7c:f2:53 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - AE:25:5E:FA:4D:A3:5B:2B:87:DE:F1:2A:F5:42:C0:FF:CE:B5:B4:AD + 5C:F7:29:21:69:7A:09:78:9E:7B:CD:53:42:02:EC:CE:29:0D:11:DF X509v3 Authority Key Identifier: - keyid:AE:25:5E:FA:4D:A3:5B:2B:87:DE:F1:2A:F5:42:C0:FF:CE:B5:B4:AD - DirName:/C=US/ST=Oregon/L=Portland/O=yaSSL/CN=www.yassl.com/emailAddress=info@yassl.com - serial:00 + keyid:5C:F7:29:21:69:7A:09:78:9E:7B:CD:53:42:02:EC:CE:29:0D:11:DF + DirName:/C=US/ST=Oregon/L=Portland/O=yaSSL/OU=programming/CN=www.yassl.com/emailAddress=info@yassl.com + serial:C5:D7:6C:11:36:F0:35:E1 X509v3 Basic Constraints: CA:TRUE Signature Algorithm: md5WithRSAEncryption - 59:19:ae:1b:4e:65:9e:ca:f1:b8:3d:ff:c7:5e:15:86:10:97: - 8c:3e:22:32:ab:4e:75:a7:70:83:f2:fb:2f:af:fe:26:28:e9: - 4f:d4:c9:49:7c:6f:51:7e:2a:ff:a0:5b:25:45:2e:66:d9:0d: - 92:94:e5:b8:60:c6:67:1a:f3:03 + b4:a5:f1:71:26:4d:b9:ff:54:f3:09:1f:ac:e1:19:59:e5:ec: + 57:e3:f1:0b:b2:8f:f3:29:eb:6b:c6:fa:27:33:3e:91:d0:77: + 43:c9:ce:1e:0f:71:07:a9:f7:26:e0:7e:ff:30:7d:52:0a:e1: + 80:48:46:bb:99:e9:d9:77:ce:75 -----BEGIN CERTIFICATE----- -MIICtzCCAmGgAwIBAgIBADANBgkqhkiG9w0BAQQFADB4MQswCQYDVQQGEwJVUzEP -MA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDEOMAwGA1UEChMFeWFT -U0wxFjAUBgNVBAMTDXd3dy55YXNzbC5jb20xHTAbBgkqhkiG9w0BCQEWDmluZm9A -eWFzc2wuY29tMB4XDTA1MDMwNzAzMDAzMVoXDTQ2MDQwMTAzMDAzMVoweDELMAkG -A1UEBhMCVVMxDzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxhbmQxDjAM -BgNVBAoTBXlhU1NMMRYwFAYDVQQDEw13d3cueWFzc2wuY29tMR0wGwYJKoZIhvcN -AQkBFg5pbmZvQHlhc3NsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDNH3hH -+LjWCL+9fCNhhjYorO48qJqU5tUm6HFQsiaLHB4/dbLTs2eVDP12KGXVzhKCngYA -ogndzjom3UYqoEVxAgMBAAGjgdUwgdIwHQYDVR0OBBYEFK4lXvpNo1srh97xKvVC -wP/OtbStMIGiBgNVHSMEgZowgZeAFK4lXvpNo1srh97xKvVCwP/OtbStoXykejB4 -MQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFu -ZDEOMAwGA1UEChMFeWFTU0wxFjAUBgNVBAMTDXd3dy55YXNzbC5jb20xHTAbBgkq -hkiG9w0BCQEWDmluZm9AeWFzc2wuY29tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZI -hvcNAQEEBQADQQBZGa4bTmWeyvG4Pf/HXhWGEJeMPiIyq051p3CD8vsvr/4mKOlP -1MlJfG9Rfir/oFslRS5m2Q2SlOW4YMZnGvMD +MIIDDjCCArigAwIBAgIJAMXXbBE28DXhMA0GCSqGSIb3DQEBBAUAMIGOMQswCQYD +VQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDEOMAwG +A1UEChMFeWFTU0wxFDASBgNVBAsTC3Byb2dyYW1taW5nMRYwFAYDVQQDEw13d3cu +eWFzc2wuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlhc3NsLmNvbTAeFw0xMDA2 +MzAxODM5MzlaFw0xMzAzMjYxODM5NDBaMIGOMQswCQYDVQQGEwJVUzEPMA0GA1UE +CBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDEOMAwGA1UEChMFeWFTU0wxFDAS +BgNVBAsTC3Byb2dyYW1taW5nMRYwFAYDVQQDEw13d3cueWFzc2wuY29tMR0wGwYJ +KoZIhvcNAQkBFg5pbmZvQHlhc3NsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgC +QQC9UUoU/WoZhAwzOPwnMpyXC/ykGGBpTtnYeFAL6SBd1h1wHAwknyOCzDoB1ZcX +snNshs+18eXOaAzZohI5fPJTAgMBAAGjgfYwgfMwHQYDVR0OBBYEFFz3KSFpegl4 +nnvNU0IC7M4pDRHfMIHDBgNVHSMEgbswgbiAFFz3KSFpegl4nnvNU0IC7M4pDRHf +oYGUpIGRMIGOMQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQH +EwhQb3J0bGFuZDEOMAwGA1UEChMFeWFTU0wxFDASBgNVBAsTC3Byb2dyYW1taW5n +MRYwFAYDVQQDEw13d3cueWFzc2wuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlh +c3NsLmNvbYIJAMXXbBE28DXhMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQAD +QQC0pfFxJk25/1TzCR+s4RlZ5exX4/ELso/zKetrxvonMz6R0HdDyc4eD3EHqfcm +4H7/MH1SCuGASEa7menZd851 -----END CERTIFICATE----- diff --git a/extra/yassl/certs/client-key.der b/extra/yassl/certs/client-key.der Binary files differindex 6e8b432a07c..649406c4417 100644 --- a/extra/yassl/certs/client-key.der +++ b/extra/yassl/certs/client-key.der diff --git a/extra/yassl/certs/client-key.pem b/extra/yassl/certs/client-key.pem index 6898b2796fa..92c052fef84 100644 --- a/extra/yassl/certs/client-key.pem +++ b/extra/yassl/certs/client-key.pem @@ -1,9 +1,9 @@ -----BEGIN RSA PRIVATE KEY----- -MIIBOgIBAAJBAM0feEf4uNYIv718I2GGNiis7jyompTm1SbocVCyJoscHj91stOz -Z5UM/XYoZdXOEoKeBgCiCd3OOibdRiqgRXECAwEAAQJAXwa6OVVvg7Bv63+MAI0l -n/hlMfLGEj9R9gFvJXwywPSEQhijOZmedpHALufFPNHtwba9dmbqMkBAw9JDaAgg -QQIhAO+mBaSmoG5AYVKYQZiASe/2wMZjaQSN+zFLyF97OX8ZAiEA2x5iRmXUkbOT -8Td/vx8R9mq9W5CJu+cN+SWGwTYhPBkCIGZFM6NQeKaUUvQshdHO7b66Twpa4jZP -YSNoc9pLe/4BAiB+jIvBkKo2A/rbg2waG32qTXdTXKTPiuA9Fnk/OV30cQIhANuA -uMdo+T+rYcNGJ1hCYKDe9JWBpNfSQ+H/A7sWuW8L +MIIBPAIBAAJBAL1RShT9ahmEDDM4/CcynJcL/KQYYGlO2dh4UAvpIF3WHXAcDCSf +I4LMOgHVlxeyc2yGz7Xx5c5oDNmiEjl88lMCAwEAAQJAVGHWLlLhpqvXsEEXCvWh +HCYono+K8YVGzhiaPSTU212fCoQryIxsXQKGBjhFdZm96DZWp+Vd/t/u+B4ZeaqY ++QIhAOBEfbFtdZqk5OmbbRsRVPI7+YYmubgY1TVIPqmxHQ4NAiEA2BrTQkjOb3ul +A/SZO04fJUZsm7Ng92FWHDJsRancSd8CIQCmGbQqZBK1TamJZ6dAY+7RViAx/p6Q +vjuzMeXPUrFdRQIhAMkfBhg9bCqjFyt8PBPOm/vz8+ZgZlE0/JAXeV7IPCVfAiEA +gZwCFm1ghGxmaoB424YC4DHeDeN/g9xwJHT7EuM9Mvc= -----END RSA PRIVATE KEY----- diff --git a/extra/yassl/certs/client-keyEnc.pem b/extra/yassl/certs/client-keyEnc.pem new file mode 100644 index 00000000000..f6b857fc48c --- /dev/null +++ b/extra/yassl/certs/client-keyEnc.pem @@ -0,0 +1,12 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-CBC,B9D8FB94E38635AB + +e7bVyzL1RF6p7hl8GDaOrRTcgB4ip+pWWUcnNf6y2tsuAQx/c/Bd5c9ZDc3L5AXC +oOAzWYB+ay1vWkmAQB4ivFS5QzGDf8870d4FbOejwmgPhiHdZNw5xNwscAN6ps0v +dFaUrR9nzWmbycsQCjXZGIZtGFCtXkA8Gdl5OMO4o+rzM0muNPS5fb++x7oNl1YG +gjReu2sQ85dPfMlnoHhr8Pz9LBcxVyOmcqtmT0SOSuPcoj6aDtcZ+EY9MQf6SR9E +ysmrJKMtp+ABgXglAj5hbT0dMpoJ2KpJYk62JAh/A6DDyv5YYUI0W57xY5+QzaV+ +YXnIvqwLjJ3cXEV4YH7ozLHAESgnAAUoQsin42rrRKt7GxjSdBoFhWjH69V2nl65 +LYRNjE1O5BBEX+rz0S+fe2ZZgT17kUr7eLZCq15J+L5xWQ7R4ERc0w== +-----END RSA PRIVATE KEY----- diff --git a/extra/yassl/certs/client-keyEnc3.pem b/extra/yassl/certs/client-keyEnc3.pem new file mode 100644 index 00000000000..0097c0760a5 --- /dev/null +++ b/extra/yassl/certs/client-keyEnc3.pem @@ -0,0 +1,12 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,BDE979D13CCC0ABD + +N7yz2JV13EmQ7MZPL5wamid5+G1V1gp8FKqMemAC5JDxonS/W9oViMLUcxbfPTDx +FznKdYSVTIQ7vv3ofmDG4MEyV/2C568N2kdtAw+jTfrZFN+IU9CI+W+In/nacirF +02sAcvDMofustnooKNOO7/iyb5+3vRvEt5vSSRQn5WuSQ9sUKjuzoLs/lbf7fyAt +4NeqfI3rYBZXxiUOLITOGXzGNRuFoY+o2uDCfelLAJ8uhiVG6ME3LeJEo1dT5lZ8 +CSJOLPasKg0iG4V7olM4j9FvAfZr48RRsSfUen756Jo2HpI4bad8LKhFYIdNs2Au +WwKLmjpo6QB9hBmRshR04rEXPdrgTqLBExCE08PyaGYnWU8ggWritCeBzDQFj/n4 +sI+NO0Mymuvg98e5RpO52lg3Xnqv9RIK3guLFOmI6aEHC0PS4WwOEQ== +-----END RSA PRIVATE KEY----- diff --git a/extra/yassl/certs/dsa-cert.pem b/extra/yassl/certs/dsa-cert.pem index 788d263bb9f..ed1138dad01 100644 --- a/extra/yassl/certs/dsa-cert.pem +++ b/extra/yassl/certs/dsa-cert.pem @@ -1,13 +1,14 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 0 (0x0) + Serial Number: + ce:df:23:31:64:b4:13:da Signature Algorithm: dsaWithSHA1 - Issuer: C=US, ST=Oregon, L=Portland, O=yaSSL DSA, CN=yaSSL DSA/emailAddress=info@yassl.com + Issuer: C=US, ST=Oregon, L=Portland, O=yaSSL, OU=testing, CN=www.yassl.com/emailAddress=info@yassl.com Validity - Not Before: Mar 7 03:22:00 2005 GMT - Not After : Apr 1 03:22:00 2046 GMT - Subject: C=US, ST=Oregon, L=Portland, O=yaSSL DSA, CN=yaSSL DSA/emailAddress=info@yassl.com + Not Before: Jun 30 18:56:38 2010 GMT + Not After : Mar 26 18:56:39 2013 GMT + Subject: C=US, ST=Oregon, L=Portland, O=yaSSL, OU=testing, CN=www.yassl.com/emailAddress=info@yassl.com Subject Public Key Info: Public Key Algorithm: dsaEncryption DSA Public Key: @@ -37,32 +38,33 @@ Certificate: BE:F9:8C:5D:D6:1C:B4:EE:81:DD:36:56:0A:21:E4:61:44:73:E9:E2 X509v3 Authority Key Identifier: keyid:BE:F9:8C:5D:D6:1C:B4:EE:81:DD:36:56:0A:21:E4:61:44:73:E9:E2 - DirName:/C=US/ST=Oregon/L=Portland/O=yaSSL DSA/CN=yaSSL DSA/emailAddress=info@yassl.com - serial:00 + DirName:/C=US/ST=Oregon/L=Portland/O=yaSSL/OU=testing/CN=www.yassl.com/emailAddress=info@yassl.com + serial:CE:DF:23:31:64:B4:13:DA X509v3 Basic Constraints: CA:TRUE Signature Algorithm: dsaWithSHA1 - 30:2c:02:14:7e:5e:94:fc:7f:ca:81:ab:b3:32:f7:21:83:48: - 48:5f:0a:f1:13:ca:02:14:73:54:32:14:51:22:bf:0b:ec:d7: - 6a:6a:fa:a7:1d:46:b4:c2:a3:b5 + 30:2d:02:14:00:a3:21:20:34:6a:2c:f9:fb:76:d7:20:c9:c0: + 35:1b:64:9a:c2:83:02:15:00:a4:59:ac:6d:da:85:48:ff:f5: + 0d:49:72:c8:cd:91:fc:ec:2f:5c:63 -----BEGIN CERTIFICATE----- -MIIDMjCCAvKgAwIBAgIBADAJBgcqhkjOOAQDMHgxCzAJBgNVBAYTAlVTMQ8wDQYD -VQQIEwZPcmVnb24xETAPBgNVBAcTCFBvcnRsYW5kMRIwEAYDVQQKEwl5YVNTTCBE -U0ExEjAQBgNVBAMTCXlhU1NMIERTQTEdMBsGCSqGSIb3DQEJARYOaW5mb0B5YXNz -bC5jb20wHhcNMDUwMzA3MDMyMjAwWhcNNDYwNDAxMDMyMjAwWjB4MQswCQYDVQQG -EwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDESMBAGA1UE -ChMJeWFTU0wgRFNBMRIwEAYDVQQDEwl5YVNTTCBEU0ExHTAbBgkqhkiG9w0BCQEW -DmluZm9AeWFzc2wuY29tMIHwMIGoBgcqhkjOOAQBMIGcAkEAmSlpgMk8mGhFqYL+ -Z+uViMW0DNYmRZUZLKAgW37faencww/zYQolm/IhAWrNqow358pm21b0D3160Ri5 -Qv0bEQIVAK0lKasKnwkcwa0DIHZ/prfdTQMJAkASiJna59ALk5vm7jwhf5yztI2l -jOI3gD8X0YFPvfBxtjIIVN2/AeKzdwZkdYoE1nk5sQIDA8YGdOWQBQoQRhkxA0MA -AkAEhKAmMXIM6E9dUxdisYDKwBZfwx7qxdmYOPm+VlNHaM4IIlccuw13kc9bNu3z -JIKQis2QfNt3+Rctc3Pvu7mCo4HVMIHSMB0GA1UdDgQWBBS++Yxd1hy07oHdNlYK -IeRhRHPp4jCBogYDVR0jBIGaMIGXgBS++Yxd1hy07oHdNlYKIeRhRHPp4qF8pHow -eDELMAkGA1UEBhMCVVMxDzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxh -bmQxEjAQBgNVBAoTCXlhU1NMIERTQTESMBAGA1UEAxMJeWFTU0wgRFNBMR0wGwYJ -KoZIhvcNAQkBFg5pbmZvQHlhc3NsLmNvbYIBADAMBgNVHRMEBTADAQH/MAkGByqG -SM44BAMDLwAwLAIUfl6U/H/KgauzMvchg0hIXwrxE8oCFHNUMhRRIr8L7Ndqavqn -HUa0wqO1 +MIIDfjCCAz2gAwIBAgIJAM7fIzFktBPaMAkGByqGSM44BAMwgYoxCzAJBgNVBAYT +AlVTMQ8wDQYDVQQIEwZPcmVnb24xETAPBgNVBAcTCFBvcnRsYW5kMQ4wDAYDVQQK +EwV5YVNTTDEQMA4GA1UECxMHdGVzdGluZzEWMBQGA1UEAxMNd3d3Lnlhc3NsLmNv +bTEdMBsGCSqGSIb3DQEJARYOaW5mb0B5YXNzbC5jb20wHhcNMTAwNjMwMTg1NjM4 +WhcNMTMwMzI2MTg1NjM5WjCBijELMAkGA1UEBhMCVVMxDzANBgNVBAgTBk9yZWdv +bjERMA8GA1UEBxMIUG9ydGxhbmQxDjAMBgNVBAoTBXlhU1NMMRAwDgYDVQQLEwd0 +ZXN0aW5nMRYwFAYDVQQDEw13d3cueWFzc2wuY29tMR0wGwYJKoZIhvcNAQkBFg5p +bmZvQHlhc3NsLmNvbTCB8DCBqAYHKoZIzjgEATCBnAJBAJkpaYDJPJhoRamC/mfr +lYjFtAzWJkWVGSygIFt+32np3MMP82EKJZvyIQFqzaqMN+fKZttW9A99etEYuUL9 +GxECFQCtJSmrCp8JHMGtAyB2f6a33U0DCQJAEoiZ2ufQC5Ob5u48IX+cs7SNpYzi +N4A/F9GBT73wcbYyCFTdvwHis3cGZHWKBNZ5ObECAwPGBnTlkAUKEEYZMQNDAAJA +BISgJjFyDOhPXVMXYrGAysAWX8Me6sXZmDj5vlZTR2jOCCJXHLsNd5HPWzbt8ySC +kIrNkHzbd/kXLXNz77u5gqOB8jCB7zAdBgNVHQ4EFgQUvvmMXdYctO6B3TZWCiHk +YURz6eIwgb8GA1UdIwSBtzCBtIAUvvmMXdYctO6B3TZWCiHkYURz6eKhgZCkgY0w +gYoxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIEwZPcmVnb24xETAPBgNVBAcTCFBvcnRs +YW5kMQ4wDAYDVQQKEwV5YVNTTDEQMA4GA1UECxMHdGVzdGluZzEWMBQGA1UEAxMN +d3d3Lnlhc3NsLmNvbTEdMBsGCSqGSIb3DQEJARYOaW5mb0B5YXNzbC5jb22CCQDO +3yMxZLQT2jAMBgNVHRMEBTADAQH/MAkGByqGSM44BAMDMAAwLQIUAKMhIDRqLPn7 +dtcgycA1G2SawoMCFQCkWaxt2oVI//UNSXLIzZH87C9cYw== -----END CERTIFICATE----- diff --git a/extra/yassl/certs/dsa512.der b/extra/yassl/certs/dsa512.der Binary files differindex fe79ccb612b..027bedeffb1 100644 --- a/extra/yassl/certs/dsa512.der +++ b/extra/yassl/certs/dsa512.der diff --git a/extra/yassl/certs/server-cert.pem b/extra/yassl/certs/server-cert.pem index 30608f5f65b..1ec53c02628 100644 --- a/extra/yassl/certs/server-cert.pem +++ b/extra/yassl/certs/server-cert.pem @@ -3,36 +3,37 @@ Certificate: Version: 1 (0x0) Serial Number: 1 (0x1) Signature Algorithm: md5WithRSAEncryption - Issuer: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com + Issuer: C=US, ST=Montana, L=Bozeman, O=sawtooth, OU=consulting, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com Validity - Not Before: Mar 8 03:00:47 2005 GMT - Not After : Apr 2 03:00:47 2046 GMT - Subject: C=US, ST=Oregon, L=Portland, O=taoSoftDev, CN=www.taosoftdev.com/emailAddress=info@yassl.com + Not Before: Jun 30 18:52:17 2010 GMT + Not After : Mar 26 18:52:17 2013 GMT + Subject: C=US, ST=Montana, L=Bozeman, O=yaSSL, OU=support, CN=www.yassl.com/emailAddress=info@yassl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (512 bit) Modulus (512 bit): - 00:a4:68:bb:bc:b7:27:5f:3c:f5:78:c6:1a:af:b9: - 95:fc:7e:61:1f:a8:81:0a:ca:43:88:9a:03:e0:d0: - a6:79:70:16:34:b9:7c:75:54:ca:70:19:66:38:be: - 6e:28:7e:a5:ff:6b:3c:83:2f:39:42:c3:15:f3:bd: - f2:25:93:22:e7 + 00:c6:7b:c0:68:81:2f:de:82:3f:f9:ac:c3:86:4a: + 66:b7:ec:d4:f1:f6:64:21:ff:f5:a2:34:42:d0:38: + 9f:c6:dd:3b:6e:26:65:6a:54:96:dd:d2:7b:eb:36: + a2:ae:7e:2a:9e:7e:56:a5:b6:87:9f:15:c7:18:66: + 7e:16:77:e2:a7 Exponent: 65537 (0x10001) Signature Algorithm: md5WithRSAEncryption - 36:72:12:3b:ac:e4:58:83:09:86:4f:71:2a:3a:0d:8a:05:27: - 75:f3:3e:62:4f:ab:b8:70:20:cd:ad:70:ab:91:11:68:f8:82: - 33:e2:78:85:a8:16:f5:66:bd:68:2c:5a:26:15:12:1e:6e:83: - c7:6d:62:b9:c3:ff:e1:86:e4:e6 + 58:a9:98:e7:16:52:4c:40:e7:e1:47:92:19:1b:3a:8f:97:6c: + 7b:b7:b0:cb:20:6d:ad:b5:d3:47:58:d8:e4:f2:3e:32:e9:ef: + 87:77:e5:54:36:f4:8d:50:8d:07:b4:77:45:ea:9d:a4:33:36: + 9b:0b:e0:74:58:11:c5:01:7b:4d -----BEGIN CERTIFICATE----- -MIIB9zCCAaECAQEwDQYJKoZIhvcNAQEEBQAwgYkxCzAJBgNVBAYTAlVTMQ8wDQYD -VQQIEwZPcmVnb24xETAPBgNVBAcTCFBvcnRsYW5kMREwDwYDVQQKEwhzYXd0b290 -aDEkMCIGA1UEAxMbd3d3LnNhd3Rvb3RoLWNvbnN1bHRpbmcuY29tMR0wGwYJKoZI -hvcNAQkBFg5pbmZvQHlhc3NsLmNvbTAeFw0wNTAzMDgwMzAwNDdaFw00NjA0MDIw -MzAwNDdaMIGCMQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQH -EwhQb3J0bGFuZDETMBEGA1UEChMKdGFvU29mdERldjEbMBkGA1UEAxMSd3d3LnRh -b3NvZnRkZXYuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlhc3NsLmNvbTBcMA0G -CSqGSIb3DQEBAQUAA0sAMEgCQQCkaLu8tydfPPV4xhqvuZX8fmEfqIEKykOImgPg -0KZ5cBY0uXx1VMpwGWY4vm4ofqX/azyDLzlCwxXzvfIlkyLnAgMBAAEwDQYJKoZI -hvcNAQEEBQADQQA2chI7rORYgwmGT3EqOg2KBSd18z5iT6u4cCDNrXCrkRFo+IIz -4niFqBb1Zr1oLFomFRIeboPHbWK5w//hhuTm +MIICFDCCAb4CAQEwDQYJKoZIhvcNAQEEBQAwgZ4xCzAJBgNVBAYTAlVTMRAwDgYD +VQQIEwdNb250YW5hMRAwDgYDVQQHEwdCb3plbWFuMREwDwYDVQQKEwhzYXd0b290 +aDETMBEGA1UECxMKY29uc3VsdGluZzEkMCIGA1UEAxMbd3d3LnNhd3Rvb3RoLWNv +bnN1bHRpbmcuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlhc3NsLmNvbTAeFw0x +MDA2MzAxODUyMTdaFw0xMzAzMjYxODUyMTdaMIGKMQswCQYDVQQGEwJVUzEQMA4G +A1UECBMHTW9udGFuYTEQMA4GA1UEBxMHQm96ZW1hbjEOMAwGA1UEChMFeWFTU0wx +EDAOBgNVBAsTB3N1cHBvcnQxFjAUBgNVBAMTDXd3dy55YXNzbC5jb20xHTAbBgkq +hkiG9w0BCQEWDmluZm9AeWFzc2wuY29tMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJB +AMZ7wGiBL96CP/msw4ZKZrfs1PH2ZCH/9aI0QtA4n8bdO24mZWpUlt3Se+s2oq5+ +Kp5+VqW2h58VxxhmfhZ34qcCAwEAATANBgkqhkiG9w0BAQQFAANBAFipmOcWUkxA +5+FHkhkbOo+XbHu3sMsgba2100dY2OTyPjLp74d35VQ29I1QjQe0d0XqnaQzNpsL +4HRYEcUBe00= -----END CERTIFICATE----- diff --git a/extra/yassl/certs/server-key.pem b/extra/yassl/certs/server-key.pem index d6055c4cfd8..154d661b1df 100644 --- a/extra/yassl/certs/server-key.pem +++ b/extra/yassl/certs/server-key.pem @@ -1,9 +1,9 @@ -----BEGIN RSA PRIVATE KEY----- -MIIBOQIBAAJBAKRou7y3J1889XjGGq+5lfx+YR+ogQrKQ4iaA+DQpnlwFjS5fHVU -ynAZZji+bih+pf9rPIMvOULDFfO98iWTIucCAwEAAQJABLVvMw931DV1vljGKORC -1HF2LKbx0zJJzt7CX6z6J54vcE79K3NYXdU6o7/j1WTtfD47tFG+4ljGvSYPmrCI -2QIhANfiY6is6JUJGGgeMxyWeQRPXfaE9Yrk6OhxHhpYf5CTAiEAwvWraeLPy/NE -B+0w80mh8tCv2tpuKaYMOG53XpYX3N0CIDy/Bj3rUZLGOWjqvoUXzjupPY5lgVYw -7Vyin87YAiUjAiAgM8X5em5KSMc+6+2+8bWfTtsNMjEqDfRMyepLpE0SvQIgTSYL -WWfcZoRUPDM9GEuQ40nifVNjobzvjTW4aYyHCEI= +MIIBOwIBAAJBAMZ7wGiBL96CP/msw4ZKZrfs1PH2ZCH/9aI0QtA4n8bdO24mZWpU +lt3Se+s2oq5+Kp5+VqW2h58VxxhmfhZ34qcCAwEAAQJBAJSbGxgjgV+rTZL2Ev58 +viN/IoB25cm/Bn4Heu7DNn2A2kpdGX2cCaf7rEQoIKCiHxvopvxOcd/7nLS/gNli +dCECIQD/cX/9fvB1Uajw0fmvwNON9+3P9uJSqpig90zL32pwjQIhAMbqee9TBMN4 +TxXbgWqA92PrCXe8WDZ3PwoJqdR6MRUDAiEAny+TDF1z6hiWiGTCDgXDkKBlwgjf +p5aKgR077XzwLu0CICVpWEGg1ZaF/CnaPP7w/pZ2UDOK4vRrfRnAM4bY7H5NAiBS +1eXJ/MCZ2uPfpl7XK2BU9P69KdKUk5WHxdRchVvcDg== -----END RSA PRIVATE KEY----- diff --git a/extra/yassl/certs/server-keyEnc.pem b/extra/yassl/certs/server-keyEnc.pem new file mode 100644 index 00000000000..d3500a1b647 --- /dev/null +++ b/extra/yassl/certs/server-keyEnc.pem @@ -0,0 +1,12 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-CBC,08132C1FFF5BC8CC + +gsvuAsGmB8AkR23M25w4E6wuywfBey1Jqh3g71gJcnsUYwynex9dvfAU0lTowOXh +sb7ld1KNjEMzrht9AC1IC0iE1rLqvRQZOdJ7h3n7aHZQ4a/HjcwAhqJq0ZW45m6Q +mpoO5fRISjx2VbKFRUz6Xj2x0/do3IjQhpuUDVrTFFe1sEySM6APZ6CVpcnTOyPR +ADyLDKzOi2E+sj1UXs58pct56FaqTIZPUEflICU3k6q9FPU6gsYANRLfzegclkv4 +JAx6mKVSJuYnjCCppx8WBwGJa1J1GcYRJ3qFfdbUzL4bcXTvoFkJEnDkHsXgDUS6 +xmT0XGT3IMaW8cwQ8KD8m5YYI/L26Mas/w3eA2ekyMR8pYICjXp/YZtcKxxkQSVE +Uv/+D+20KbNAHIW5Mrxf61cX/CggGEbVP8ZhDY1flh8= +-----END RSA PRIVATE KEY----- diff --git a/extra/yassl/certs/taoCert.txt b/extra/yassl/certs/taoCert.txt index 585293e4f2b..f1132c0b5b8 100644 --- a/extra/yassl/certs/taoCert.txt +++ b/extra/yassl/certs/taoCert.txt @@ -47,4 +47,16 @@ to convert rsa private PEM to DER : b) openssl rsa -in key.pem -outform DER -out key.der +**** To encrypt rsa key already in pem ********** + +a) openssl rsa <server-key.pem.bak -des >server-keyEnc.pem + +note location of des, pass = yassl123 + + +*** To make a public key from a private key ****** + + +openssl rsa -in 1024rsa.priv -pubout -out 1024rsa.pub + diff --git a/extra/yassl/examples/client/client.cpp b/extra/yassl/examples/client/client.cpp index a80a8c2f1a2..d05c31d4d63 100644 --- a/extra/yassl/examples/client/client.cpp +++ b/extra/yassl/examples/client/client.cpp @@ -36,15 +36,20 @@ void ClientError(SSL_CTX* ctx, SSL* ssl, SOCKET_T& sockfd, const char* msg) void NonBlockingSSL_Connect(SSL* ssl, SSL_CTX* ctx, SOCKET_T& sockfd) { int ret = SSL_connect(ssl); - while (ret =! SSL_SUCCESS && SSL_get_error(ssl, 0) == - SSL_ERROR_WANT_READ) { - printf("... client would block\n"); + int err = SSL_get_error(ssl, 0); + while (ret != SSL_SUCCESS && (err == SSL_ERROR_WANT_READ || + err == SSL_ERROR_WANT_WRITE)) { + if (err == SSL_ERROR_WANT_READ) + printf("... client would read block\n"); + else + printf("... client would write block\n"); #ifdef _WIN32 Sleep(1000); #else sleep(1); #endif ret = SSL_connect(ssl); + err = SSL_get_error(ssl, 0); } if (ret != SSL_SUCCESS) ClientError(ctx, ssl, sockfd, "SSL_connect failed"); @@ -81,7 +86,8 @@ void client_test(void* args) #ifdef NON_BLOCKING NonBlockingSSL_Connect(ssl, ctx, sockfd); #else - if (SSL_connect(ssl) != SSL_SUCCESS) + // if you get an error here see note at top of README + if (SSL_connect(ssl) != SSL_SUCCESS) ClientError(ctx, ssl, sockfd, "SSL_connect failed"); #endif showPeer(ssl); @@ -105,7 +111,7 @@ void client_test(void* args) int input = SSL_read(ssl, reply, sizeof(reply)); if (input > 0) { reply[input] = 0; - printf("Server response: %s\n", reply); + printf("Server response: %s\n", reply); } #ifdef TEST_RESUME @@ -121,18 +127,18 @@ void client_test(void* args) tcp_connect(sockfd); SSL_set_fd(sslResume, sockfd); SSL_set_session(sslResume, session); - + if (SSL_connect(sslResume) != SSL_SUCCESS) ClientError(ctx, sslResume, sockfd, "SSL_resume failed"); showPeer(sslResume); - + if (SSL_write(sslResume, msg, sizeof(msg)) != sizeof(msg)) ClientError(ctx, sslResume, sockfd, "SSL_write failed"); input = SSL_read(sslResume, reply, sizeof(reply)); if (input > 0) { reply[input] = 0; - printf("Server response: %s\n", reply); + printf("Server response: %s\n", reply); } SSL_shutdown(sslResume); diff --git a/extra/yassl/examples/echoclient/echoclient.cpp b/extra/yassl/examples/echoclient/echoclient.cpp index 787e554f8bf..c2b8ff66ac9 100644 --- a/extra/yassl/examples/echoclient/echoclient.cpp +++ b/extra/yassl/examples/echoclient/echoclient.cpp @@ -74,10 +74,10 @@ void echoclient_test(void* args) char send[1024]; char reply[1024]; - + while (fgets(send, sizeof(send), fin)) { - int sendSz = strlen(send) + 1; + int sendSz = (int)strlen(send) + 1; if (SSL_write(ssl, send, sendSz) != sendSz) EchoClientError(ctx, ssl, sockfd, "SSL_write failed"); @@ -86,7 +86,7 @@ void echoclient_test(void* args) break; } - if (SSL_read(ssl, reply, sizeof(reply)) > 0) + if (SSL_read(ssl, reply, sizeof(reply)) > 0) fputs(reply, fout); } diff --git a/extra/yassl/examples/echoserver/echoserver.cpp b/extra/yassl/examples/echoserver/echoserver.cpp index a3ba8c12c60..bd044e70e8b 100644 --- a/extra/yassl/examples/echoserver/echoserver.cpp +++ b/extra/yassl/examples/echoserver/echoserver.cpp @@ -93,11 +93,11 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) #endif while (!shutdown) { - sockaddr_in client; + SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); SOCKET_T clientfd = accept(sockfd, (sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); - if (clientfd == -1) { + if (clientfd == (SOCKET_T) -1) { SSL_CTX_free(ctx); tcp_close(sockfd); err_sys("tcp accept failed"); @@ -111,11 +111,11 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) tcp_close(clientfd); continue; } - + char command[1024]; int echoSz(0); while ( (echoSz = SSL_read(ssl, command, sizeof(command))) > 0) { - + if ( strncmp(command, "quit", 4) == 0) { printf("client sent quit command: shutting down!\n"); shutdown = true; @@ -127,7 +127,7 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) char header[] = "<html><body BGCOLOR=\"#ffffff\">\n<pre>\n"; char body[] = "greetings from yaSSL\n"; char footer[] = "</body></html>\r\n\r\n"; - + strncpy(command, type, sizeof(type)); echoSz = sizeof(type) - 1; @@ -140,7 +140,7 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) if (SSL_write(ssl, command, echoSz) != echoSz) EchoError(ctx, ssl, sockfd, clientfd, "SSL_write failed"); - + break; } command[echoSz] = 0; diff --git a/extra/yassl/examples/server/server.cpp b/extra/yassl/examples/server/server.cpp index 8b8066eace5..3fac40e88c4 100644 --- a/extra/yassl/examples/server/server.cpp +++ b/extra/yassl/examples/server/server.cpp @@ -35,15 +35,20 @@ void ServerError(SSL_CTX* ctx, SSL* ssl, SOCKET_T& sockfd, const char* msg) void NonBlockingSSL_Accept(SSL* ssl, SSL_CTX* ctx, SOCKET_T& clientfd) { int ret = SSL_accept(ssl); - while (ret != SSL_SUCCESS && SSL_get_error(ssl, 0) == - SSL_ERROR_WANT_READ) { - printf("... server would block\n"); + int err = SSL_get_error(ssl, 0); + while (ret != SSL_SUCCESS && (err == SSL_ERROR_WANT_READ || + err == SSL_ERROR_WANT_WRITE)) { + if (err == SSL_ERROR_WANT_READ) + printf("... server would read block\n"); + else + printf("... server would write block\n"); #ifdef _WIN32 Sleep(1000); #else sleep(1); #endif ret = SSL_accept(ssl); + err = SSL_get_error(ssl, 0); } if (ret != SSL_SUCCESS) ServerError(ctx, ssl, clientfd, "SSL_accept failed"); @@ -78,14 +83,14 @@ THREAD_RETURN YASSL_API server_test(void* args) SSL* ssl = SSL_new(ctx); SSL_set_fd(ssl, clientfd); - + #ifdef NON_BLOCKING NonBlockingSSL_Accept(ssl, ctx, clientfd); #else if (SSL_accept(ssl) != SSL_SUCCESS) ServerError(ctx, ssl, clientfd, "SSL_accept failed"); #endif - + showPeer(ssl); printf("Using Cipher Suite: %s\n", SSL_get_cipher(ssl)); @@ -93,7 +98,7 @@ THREAD_RETURN YASSL_API server_test(void* args) int input = SSL_read(ssl, command, sizeof(command)); if (input > 0) { command[input] = 0; - printf("First client command: %s\n", command); + printf("First client command: %s\n", command); } char msg[] = "I hear you, fa shizzle!"; diff --git a/extra/yassl/include/buffer.hpp b/extra/yassl/include/buffer.hpp index a51bca9a630..2d7817a7ca2 100644 --- a/extra/yassl/include/buffer.hpp +++ b/extra/yassl/include/buffer.hpp @@ -46,12 +46,6 @@ typedef unsigned int uint; const uint AUTO = 0xFEEDBEEF; -// Checking Policy should implement a check function that tests whether the -// index is within the size limit of the array -struct Check { - void check(uint i, uint limit); -}; - struct NoCheck { void check(uint, uint); @@ -66,7 +60,7 @@ struct NoCheck { * write to the buffer bulk wise and have the correct size */ -class input_buffer : public Check { +class input_buffer : public NoCheck { uint size_; // number of elements in buffer uint current_; // current offset position in buffer byte* buffer_; // storage for buffer @@ -132,7 +126,7 @@ private: * Not using vector because need checked []access and the ability to * write to the buffer bulk wise and retain correct size */ -class output_buffer : public Check { +class output_buffer : public NoCheck { uint current_; // current offset and elements in buffer byte* buffer_; // storage for buffer byte* end_; // end of storage marker diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index ba5fa51f34c..0d99888da88 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2005-2007 MySQL AB, 2008 Sun Microsystems, Inc. + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -30,12 +30,12 @@ #include "prefix_ssl.h" #endif -#include <stdio.h> /* ERR_print fp */ +#include <stdio.h> /* ERR_print fp */ #include "opensslv.h" /* for version number */ #include "rsa.h" -#define YASSL_VERSION "1.7.2" +#define YASSL_VERSION "2.2.0" #if defined(__cplusplus) @@ -43,9 +43,9 @@ extern "C" { #endif void yaSSL_CleanUp(); /* call once at end of application use to - free static singleton memory holders, - not a leak per se, but helpful when - looking for them */ + free static singleton memory holders, + not a leak per se, but helpful when + looking for them */ #if defined(__cplusplus) } // extern @@ -70,11 +70,11 @@ extern "C" { class X509; class X509_NAME; #else - typedef struct SSL SSL; + typedef struct SSL SSL; typedef struct SSL_SESSION SSL_SESSION; - typedef struct SSL_METHOD SSL_METHOD; - typedef struct SSL_CTX SSL_CTX; - typedef struct SSL_CIPHER SSL_CIPHER; + typedef struct SSL_METHOD SSL_METHOD; + typedef struct SSL_CTX SSL_CTX; + typedef struct SSL_CIPHER SSL_CIPHER; typedef struct RSA RSA; @@ -107,6 +107,15 @@ RSA* RSA_generate_key(int, unsigned long, void(*)(int, int, void*), void*); /* X509 stuff, different file? */ +/* because mySQL dereferences to use error and current_cert, even after calling + * get functions for local references */ +typedef struct X509_STORE_CTX { + int error; + int error_depth; + X509* current_cert; +} X509_STORE_CTX; + + typedef struct X509_STORE X509_STORE; typedef struct X509_LOOKUP X509_LOOKUP; typedef struct X509_OBJECT { char c; } X509_OBJECT; @@ -125,16 +134,6 @@ typedef struct BIO BIO; -/* because mySQL dereferences to use error and current_cert, even after calling - * get functions for local references */ -typedef struct X509_STORE_CTX { - int error; - int error_depth; - X509* current_cert; -} X509_STORE_CTX; - - - X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX*); int X509_STORE_CTX_get_error(X509_STORE_CTX*); int X509_STORE_CTX_get_error_depth(X509_STORE_CTX*); @@ -205,7 +204,7 @@ SSL* SSL_new(SSL_CTX*); int SSL_set_fd (SSL*, YASSL_SOCKET_T); YASSL_SOCKET_T SSL_get_fd(const SSL*); int SSL_connect(SSL*); /* if you get an error from connect - see note at top of REAMDE */ + see note at top of README */ int SSL_write(SSL*, const void*, int); int SSL_read(SSL*, void*, int); int SSL_accept(SSL*); @@ -351,11 +350,11 @@ enum { /* ssl Constants */ SSL_ERROR_ZERO_RETURN = 84, SSL_ERROR_SSL = 85, - SSL_SENT_SHUTDOWN = 90, - SSL_RECEIVED_SHUTDOWN = 91, + SSL_ST_CONNECT = 90, + SSL_ST_ACCEPT = 91, SSL_CB_LOOP = 92, - SSL_ST_CONNECT = 93, - SSL_ST_ACCEPT = 94, + SSL_SENT_SHUTDOWN = 93, + SSL_RECEIVED_SHUTDOWN = 94, SSL_CB_ALERT = 95, SSL_CB_READ = 96, SSL_CB_HANDSHAKE_DONE = 97 @@ -366,7 +365,7 @@ enum { /* ssl Constants */ SSL_METHOD *SSLv3_method(void); SSL_METHOD *SSLv3_server_method(void); SSL_METHOD *SSLv3_client_method(void); -SSL_METHOD *TLSv1_server_method(void); +SSL_METHOD *TLSv1_server_method(void); SSL_METHOD *TLSv1_client_method(void); SSL_METHOD *TLSv1_1_server_method(void); SSL_METHOD *TLSv1_1_client_method(void); diff --git a/extra/yassl/include/socket_wrapper.hpp b/extra/yassl/include/socket_wrapper.hpp index 308704c2af0..2372e64e56c 100644 --- a/extra/yassl/include/socket_wrapper.hpp +++ b/extra/yassl/include/socket_wrapper.hpp @@ -26,7 +26,6 @@ #ifndef yaSSL_SOCKET_WRAPPER_HPP #define yaSSL_SOCKET_WRAPPER_HPP -#include <assert.h> #ifdef _WIN32 #include <winsock2.h> @@ -73,7 +72,8 @@ public: uint get_ready() const; socket_t get_fd() const; - uint send(const byte* buf, unsigned int len, int flags = 0) const; + uint send(const byte* buf, unsigned int len, unsigned int& sent, + int flags = 0); uint receive(byte* buf, unsigned int len, int flags = 0); bool wait(); diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp index 433649c545b..e5ee00bc21c 100644 --- a/extra/yassl/include/yassl_int.hpp +++ b/extra/yassl/include/yassl_int.hpp @@ -168,7 +168,7 @@ private: // openSSL X509 names class X509_NAME { - char* name_; + char* name_; size_t sz_; ASN1_STRING entry_; public: @@ -246,11 +246,11 @@ public: SSL_SESSION(const SSL&, RandomPool&); ~SSL_SESSION(); - const opaque* GetID() const; - const opaque* GetSecret() const; - const Cipher* GetSuite() const; - uint GetBornOn() const; - uint GetTimeOut() const; + const opaque* GetID() const; + const opaque* GetSecret() const; + const Cipher* GetSuite() const; + uint GetBornOn() const; + uint GetTimeOut() const; X509* GetPeerX509() const; void SetTimeOut(uint); @@ -417,33 +417,33 @@ class SSL_CTX { public: typedef STL::list<x509*> CertList; private: - SSL_METHOD* method_; - x509* certificate_; - x509* privateKey_; - CertList caList_; - Ciphers ciphers_; - DH_Parms dhParms_; + SSL_METHOD* method_; + x509* certificate_; + x509* privateKey_; + CertList caList_; + Ciphers ciphers_; + DH_Parms dhParms_; pem_password_cb passwordCb_; void* userData_; bool sessionCacheOff_; bool sessionCacheFlushOff_; - Stats stats_; - Mutex mutex_; // for Stats + Stats stats_; + Mutex mutex_; // for Stats VerifyCallback verifyCallback_; public: explicit SSL_CTX(SSL_METHOD* meth); ~SSL_CTX(); - const x509* getCert() const; - const x509* getKey() const; - const SSL_METHOD* getMethod() const; - const Ciphers& GetCiphers() const; - const DH_Parms& GetDH_Parms() const; - const Stats& GetStats() const; - VerifyCallback getVerifyCallback() const; + const x509* getCert() const; + const x509* getKey() const; + const SSL_METHOD* getMethod() const; + const Ciphers& GetCiphers() const; + const DH_Parms& GetDH_Parms() const; + const Stats& GetStats() const; + VerifyCallback getVerifyCallback() const; pem_password_cb GetPasswordCb() const; void* GetUserData() const; - bool GetSessionCacheOff() const; + bool GetSessionCacheOff() const; bool GetSessionCacheFlushOff() const; void setVerifyPeer(); @@ -532,10 +532,13 @@ class Buffers { public: typedef STL::list<input_buffer*> inputList; typedef STL::list<output_buffer*> outputList; + int prevSent; // previous plain text bytes sent when got WANT_WRITE + int plainSz; // plain text bytes in buffer to send when got WANT_WRITE private: - inputList dataList_; // list of users app data / handshake - outputList handShakeList_; // buffered handshake msgs - input_buffer* rawInput_; // buffered raw input yet to process + inputList dataList_; // list of users app data / handshake + outputList handShakeList_; // buffered handshake msgs + input_buffer* rawInput_; // buffered raw input yet to process + output_buffer* output_; // WANT_WRITE buffered output public: Buffers(); ~Buffers(); @@ -546,11 +549,13 @@ public: inputList& useData(); outputList& useHandShake(); - void SetRawInput(input_buffer*); // takes ownership - input_buffer* TakeRawInput(); // takes ownership + void SetRawInput(input_buffer*); // takes ownership + input_buffer* TakeRawInput(); // takes ownership + void SetOutput(output_buffer*); // takes ownership + output_buffer* TakeOutput(); // takes ownership private: Buffers(const Buffers&); // hide copy - Buffers& operator=(const Buffers&); // and assign + Buffers& operator=(const Buffers&); // and assign }; @@ -652,6 +657,7 @@ public: void deriveKeys(); void deriveTLSKeys(); void Send(const byte*, uint); + void SendWriteBuffered(); uint bufferedData(); uint get_SEQIncrement(bool); diff --git a/extra/yassl/include/yassl_types.hpp b/extra/yassl/include/yassl_types.hpp index c73a54a7c15..a9e22833eb1 100644 --- a/extra/yassl/include/yassl_types.hpp +++ b/extra/yassl/include/yassl_types.hpp @@ -26,7 +26,6 @@ #define yaSSL_TYPES_HPP #include <stddef.h> -#include <assert.h> #include "type_traits.hpp" @@ -37,6 +36,13 @@ #endif +#ifdef _MSC_VER + // disable conversion warning + // 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy + #pragma warning(disable:4244 4996) +#endif + + namespace yaSSL { #define YASSL_LIB @@ -63,29 +69,29 @@ namespace yaSSL { template<typename T> void ysDelete(T* ptr) { - if (ptr) ptr->~T(); - ::operator delete(ptr, yaSSL::ys); + if (ptr) ptr->~T(); + ::operator delete(ptr, yaSSL::ys); } template<typename T> void ysArrayDelete(T* ptr) { - // can't do array placement destruction since not tracking size in - // allocation, only allow builtins to use array placement since they - // don't need destructors called - typedef char builtin[TaoCrypt::IsFundamentalType<T>::Yes ? 1 : -1]; - (void)sizeof(builtin); + // can't do array placement destruction since not tracking size in + // allocation, only allow builtins to use array placement since they + // don't need destructors called + typedef char builtin[TaoCrypt::IsFundamentalType<T>::Yes ? 1 : -1]; + (void)sizeof(builtin); - ::operator delete[](ptr, yaSSL::ys); + ::operator delete[](ptr, yaSSL::ys); } #define NEW_YS new (yaSSL::ys) // to resolve compiler generated operator delete on base classes with - // virtual destructors (when on stack), make sure doesn't get called + // virtual destructors (when on stack) class virtual_base { public: - static void operator delete(void*) { assert(0); } + static void operator delete(void*) { } }; @@ -124,7 +130,7 @@ typedef opaque byte; typedef unsigned int uint; - + #ifdef USE_SYS_STL // use system STL #define STL_VECTOR_FILE <vector> diff --git a/extra/yassl/src/buffer.cpp b/extra/yassl/src/buffer.cpp index a5028e7bb53..d885c953207 100644 --- a/extra/yassl/src/buffer.cpp +++ b/extra/yassl/src/buffer.cpp @@ -35,14 +35,6 @@ namespace yaSSL { -// Checking Policy should implement a check function that tests whether the -// index is within the size limit of the array - -void Check::check(uint i, uint limit) -{ - assert(i < limit); -} - void NoCheck::check(uint, uint) { @@ -86,7 +78,6 @@ input_buffer::~input_buffer() // users can pass defualt zero length buffer and then allocate void input_buffer::allocate(uint s) { - assert(!buffer_); // find realloc error buffer_ = NEW_YS byte[s]; end_ = buffer_ + s; } @@ -144,7 +135,6 @@ void input_buffer::set_current(uint i) // user passes in AUTO index for ease of use const byte& input_buffer::operator[](uint i) { - assert (i == AUTO); check(current_, size_); return buffer_[current_++]; } @@ -241,7 +231,6 @@ void output_buffer::set_current(uint c) // users can pass defualt zero length buffer and then allocate void output_buffer::allocate(uint s) { - assert(!buffer_); // find realloc error buffer_ = NEW_YS byte[s]; end_ = buffer_ + s; } @@ -257,7 +246,6 @@ const byte* output_buffer::get_buffer() const // user passes in AUTO as index for ease of use byte& output_buffer::operator[](uint i) { - assert(i == AUTO); check(current_, get_capacity()); return buffer_[current_++]; } diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp index d8660533f2e..7e73464001a 100644 --- a/extra/yassl/src/cert_wrapper.cpp +++ b/extra/yassl/src/cert_wrapper.cpp @@ -250,7 +250,8 @@ int CertManager::Validate() TaoCrypt::Source source((*last)->get_buffer(), (*last)->get_length()); TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_); - if (int err = cert.GetError().What()) + int err = cert.GetError().What(); + if ( err ) return err; const TaoCrypt::PublicKey& key = cert.GetPublicKey(); @@ -266,7 +267,7 @@ int CertManager::Validate() TaoCrypt::CertDecoder cert(source, true, &signers_, verifyNone_); int err = cert.GetError().What(); - if ( err ) + if ( err && err != TaoCrypt::SIG_OTHER_E) return err; uint sz = cert.GetPublicKey().size(); @@ -327,7 +328,6 @@ int CertManager::SetPrivateKey(const x509& key) // Store OpenSSL type peer's cert void CertManager::setPeerX509(X509* x) { - assert(peerX509_ == 0); if (x == 0) return; X509_NAME* issuer = x->GetIssuer(); diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index 08fae4ac17d..c1ee61d043e 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -50,7 +50,7 @@ void buildClientHello(SSL& ssl, ClientHello& hello) hello.suite_len_ = ssl.getSecurity().get_parms().suites_size_; memcpy(hello.cipher_suites_, ssl.getSecurity().get_parms().suites_, hello.suite_len_); - hello.comp_len_ = 1; + hello.comp_len_ = 1; hello.set_length(sizeof(ProtocolVersion) + RAN_LEN + @@ -528,8 +528,9 @@ void ProcessOldClientHello(input_buffer& input, SSL& ssl) input.read(len, sizeof(len)); uint16 randomLen; ato16(len, randomLen); + if (ch.suite_len_ > MAX_SUITE_SZ || sessionLen > ID_LEN || - randomLen > RAN_LEN) { + randomLen > RAN_LEN) { ssl.SetError(bad_input); return; } @@ -707,7 +708,7 @@ int DoProcessReply(SSL& ssl) { // wait for input if blocking if (!ssl.useSocket().wait()) { - ssl.SetError(receive_error); + ssl.SetError(receive_error); return 0; } uint ready = ssl.getSocket().get_ready(); @@ -750,8 +751,8 @@ int DoProcessReply(SSL& ssl) if (static_cast<uint>(RECORD_HEADER) > buffer.get_remaining()) needHdr = true; else { - buffer >> hdr; - ssl.verifyState(hdr); + buffer >> hdr; + ssl.verifyState(hdr); } // make sure we have enough input in buffer to process this record @@ -789,9 +790,8 @@ int DoProcessReply(SSL& ssl) void processReply(SSL& ssl) { if (ssl.GetError()) return; - - if (DoProcessReply(ssl)) - { + + if (DoProcessReply(ssl)) { // didn't complete process if (!ssl.getSocket().IsNonBlocking()) { // keep trying now, blocking ok @@ -857,6 +857,7 @@ void sendServerKeyExchange(SSL& ssl, BufferOutput buffer) if (ssl.GetError()) return; ServerKeyExchange sk(ssl); sk.build(ssl); + if (ssl.GetError()) return; RecordLayerHeader rlHeader; HandShakeHeader hsHeader; @@ -875,8 +876,7 @@ void sendServerKeyExchange(SSL& ssl, BufferOutput buffer) // send change cipher void sendChangeCipher(SSL& ssl, BufferOutput buffer) { - if (ssl.getSecurity().get_parms().entity_ == server_end) - { + if (ssl.getSecurity().get_parms().entity_ == server_end) { if (ssl.getSecurity().get_resuming()) ssl.verifyState(clientKeyExchangeComplete); else @@ -913,7 +913,7 @@ void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer) } else { if (!ssl.getSecurity().GetContext()->GetSessionCacheOff()) - GetSessions().add(ssl); // store session + GetSessions().add(ssl); // store session if (side == client_end) buildFinished(ssl, ssl.useHashes().use_verify(), server); // server } @@ -929,12 +929,22 @@ void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer) // send data int sendData(SSL& ssl, const void* buffer, int sz) { + int sent = 0; + if (ssl.GetError() == YasslError(SSL_ERROR_WANT_READ)) ssl.SetError(no_error); + if (ssl.GetError() == YasslError(SSL_ERROR_WANT_WRITE)) { + ssl.SetError(no_error); + ssl.SendWriteBuffered(); + if (!ssl.GetError()) { + // advance sent to prvevious sent + plain size just sent + sent = ssl.useBuffers().prevSent + ssl.useBuffers().plainSz; + } + } + ssl.verfiyHandShakeComplete(); if (ssl.GetError()) return -1; - int sent = 0; for (;;) { int len = min(sz - sent, MAX_RECORD_SIZE); @@ -943,6 +953,8 @@ int sendData(SSL& ssl, const void* buffer, int sz) Data data; + if (sent == sz) break; + if (ssl.CompressionOn()) { if (Compress(static_cast<const opaque*>(buffer) + sent, len, tmp) == -1) { @@ -957,9 +969,14 @@ int sendData(SSL& ssl, const void* buffer, int sz) buildMessage(ssl, out, data); ssl.Send(out.get_buffer(), out.get_size()); - if (ssl.GetError()) return -1; + if (ssl.GetError()) { + if (ssl.GetError() == YasslError(SSL_ERROR_WANT_WRITE)) { + ssl.useBuffers().plainSz = len; + ssl.useBuffers().prevSent = sent; + } + return -1; + } sent += len; - if (sent == sz) break; } ssl.useLog().ShowData(sent, true); return sent; @@ -992,7 +1009,7 @@ int receiveData(SSL& ssl, Data& data, bool peek) if (peek) ssl.PeekData(data); else - ssl.fillData(data); + ssl.fillData(data); ssl.useLog().ShowData(data.get_length()); if (ssl.GetError()) return -1; diff --git a/extra/yassl/src/make.bat b/extra/yassl/src/make.bat index cccd11dbd17..cccd11dbd17 100644..100755 --- a/extra/yassl/src/make.bat +++ b/extra/yassl/src/make.bat diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp index 3cf6c14c4b3..d88df13c08e 100644 --- a/extra/yassl/src/socket_wrapper.cpp +++ b/extra/yassl/src/socket_wrapper.cpp @@ -109,19 +109,28 @@ uint Socket::get_ready() const } -uint Socket::send(const byte* buf, unsigned int sz, int flags) const +uint Socket::send(const byte* buf, unsigned int sz, unsigned int& written, + int flags) { const byte* pos = buf; const byte* end = pos + sz; + wouldBlock_ = false; + while (pos != end) { int sent = ::send(socket_, reinterpret_cast<const char *>(pos), static_cast<int>(end - pos), flags); - - if (sent == -1) - return 0; - + if (sent == -1) { + if (get_lastError() == SOCKET_EWOULDBLOCK || + get_lastError() == SOCKET_EAGAIN) { + wouldBlock_ = true; // would have blocked this time only + nonBlocking_ = true; // nonblocking, win32 only way to tell + return 0; + } + return static_cast<uint>(-1); + } pos += sent; + written += sent; } return sz; @@ -140,8 +149,8 @@ uint Socket::receive(byte* buf, unsigned int sz, int flags) get_lastError() == SOCKET_EAGAIN) { wouldBlock_ = true; // would have blocked this time only nonBlocking_ = true; // socket nonblocking, win32 only way to tell - return 0; - } + return 0; + } } else if (recvd == 0) return static_cast<uint>(-1); diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index 05c260e80ca..8401798534b 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -252,60 +252,73 @@ int SSL_connect(SSL* ssl) if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ)) ssl->SetError(no_error); + if (ssl->GetError() == YasslError(SSL_ERROR_WANT_WRITE)) { + + ssl->SetError(no_error); + ssl->SendWriteBuffered(); + if (!ssl->GetError()) + ssl->useStates().UseConnect() = + ConnectState(ssl->getStates().GetConnect() + 1); + } + ClientState neededState; switch (ssl->getStates().GetConnect()) { case CONNECT_BEGIN : - sendClientHello(*ssl); + sendClientHello(*ssl); if (!ssl->GetError()) ssl->useStates().UseConnect() = CLIENT_HELLO_SENT; case CLIENT_HELLO_SENT : neededState = ssl->getSecurity().get_resuming() ? - serverFinishedComplete : serverHelloDoneComplete; - while (ssl->getStates().getClient() < neededState) { - if (ssl->GetError()) break; - processReply(*ssl); - } + serverFinishedComplete : serverHelloDoneComplete; + while (ssl->getStates().getClient() < neededState) { + if (ssl->GetError()) break; + processReply(*ssl); + // if resumption failed, reset needed state + if (neededState == serverFinishedComplete) + if (!ssl->getSecurity().get_resuming()) + neededState = serverHelloDoneComplete; + } if (!ssl->GetError()) ssl->useStates().UseConnect() = FIRST_REPLY_DONE; case FIRST_REPLY_DONE : - if(ssl->getCrypto().get_certManager().sendVerify()) - sendCertificate(*ssl); + if(ssl->getCrypto().get_certManager().sendVerify()) + sendCertificate(*ssl); - if (!ssl->getSecurity().get_resuming()) - sendClientKeyExchange(*ssl); + if (!ssl->getSecurity().get_resuming()) + sendClientKeyExchange(*ssl); - if(ssl->getCrypto().get_certManager().sendVerify()) - sendCertificateVerify(*ssl); + if(ssl->getCrypto().get_certManager().sendVerify()) + sendCertificateVerify(*ssl); - sendChangeCipher(*ssl); - sendFinished(*ssl, client_end); - ssl->flushBuffer(); + sendChangeCipher(*ssl); + sendFinished(*ssl, client_end); + ssl->flushBuffer(); if (!ssl->GetError()) ssl->useStates().UseConnect() = FINISHED_DONE; case FINISHED_DONE : - if (!ssl->getSecurity().get_resuming()) - while (ssl->getStates().getClient() < serverFinishedComplete) { - if (ssl->GetError()) break; - processReply(*ssl); - } + if (!ssl->getSecurity().get_resuming()) + while (ssl->getStates().getClient() < serverFinishedComplete) { + if (ssl->GetError()) break; + processReply(*ssl); + } if (!ssl->GetError()) ssl->useStates().UseConnect() = SECOND_REPLY_DONE; case SECOND_REPLY_DONE : - ssl->verifyState(serverFinishedComplete); - ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); + ssl->verifyState(serverFinishedComplete); + ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); if (ssl->GetError()) { GetErrors().Add(ssl->GetError()); - return SSL_FATAL_ERROR; + return SSL_FATAL_ERROR; } - return SSL_SUCCESS; + return SSL_SUCCESS; default : return SSL_FATAL_ERROR; // unkown state @@ -331,27 +344,36 @@ int SSL_accept(SSL* ssl) if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ)) ssl->SetError(no_error); + if (ssl->GetError() == YasslError(SSL_ERROR_WANT_WRITE)) { + + ssl->SetError(no_error); + ssl->SendWriteBuffered(); + if (!ssl->GetError()) + ssl->useStates().UseAccept() = + AcceptState(ssl->getStates().GetAccept() + 1); + } + switch (ssl->getStates().GetAccept()) { case ACCEPT_BEGIN : - processReply(*ssl); + processReply(*ssl); if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_FIRST_REPLY_DONE; case ACCEPT_FIRST_REPLY_DONE : - sendServerHello(*ssl); + sendServerHello(*ssl); - if (!ssl->getSecurity().get_resuming()) { - sendCertificate(*ssl); + if (!ssl->getSecurity().get_resuming()) { + sendCertificate(*ssl); - if (ssl->getSecurity().get_connection().send_server_key_) - sendServerKeyExchange(*ssl); + if (ssl->getSecurity().get_connection().send_server_key_) + sendServerKeyExchange(*ssl); - if(ssl->getCrypto().get_certManager().verifyPeer()) - sendCertificateRequest(*ssl); + if(ssl->getCrypto().get_certManager().verifyPeer()) + sendCertificateRequest(*ssl); - sendServerHelloDone(*ssl); - ssl->flushBuffer(); + sendServerHelloDone(*ssl); + ssl->flushBuffer(); } if (!ssl->GetError()) @@ -359,40 +381,40 @@ int SSL_accept(SSL* ssl) case SERVER_HELLO_DONE : if (!ssl->getSecurity().get_resuming()) { - while (ssl->getStates().getServer() < clientFinishedComplete) { - if (ssl->GetError()) break; - processReply(*ssl); + while (ssl->getStates().getServer() < clientFinishedComplete) { + if (ssl->GetError()) break; + processReply(*ssl); + } } - } if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_SECOND_REPLY_DONE; case ACCEPT_SECOND_REPLY_DONE : - sendChangeCipher(*ssl); - sendFinished(*ssl, server_end); - ssl->flushBuffer(); + sendChangeCipher(*ssl); + sendFinished(*ssl, server_end); + ssl->flushBuffer(); if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_FINISHED_DONE; case ACCEPT_FINISHED_DONE : - if (ssl->getSecurity().get_resuming()) { - while (ssl->getStates().getServer() < clientFinishedComplete) { - if (ssl->GetError()) break; - processReply(*ssl); - } - } + if (ssl->getSecurity().get_resuming()) { + while (ssl->getStates().getServer() < clientFinishedComplete) { + if (ssl->GetError()) break; + processReply(*ssl); + } + } if (!ssl->GetError()) ssl->useStates().UseAccept() = ACCEPT_THIRD_REPLY_DONE; case ACCEPT_THIRD_REPLY_DONE : - ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); + ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); if (ssl->GetError()) { GetErrors().Add(ssl->GetError()); - return SSL_FATAL_ERROR; + return SSL_FATAL_ERROR; } - return SSL_SUCCESS; + return SSL_SUCCESS; default: return SSL_FATAL_ERROR; // unknown state @@ -1097,7 +1119,6 @@ int EVP_BytesToKey(const EVP_CIPHER* type, const EVP_MD* md, const byte* salt, ivLeft -= store; } } - assert(keyOutput == (keyLen + ivLen)); return keyOutput; } diff --git a/extra/yassl/src/yassl.cpp b/extra/yassl/src/yassl.cpp index 815277ce6f3..99a1da5371b 100644 --- a/extra/yassl/src/yassl.cpp +++ b/extra/yassl/src/yassl.cpp @@ -69,13 +69,13 @@ void SetUpBase(Base& base, ConnectionEnd end, SOCKET_T s) if (base.ca_) if (SSL_CTX_load_verify_locations(base.ctx_, - base.ca_, 0) != SSL_SUCCESS) assert(0); + base.ca_, 0) != SSL_SUCCESS) throw(0); if (base.cert_) if (SSL_CTX_use_certificate_file(base.ctx_, - base.cert_, SSL_FILETYPE_PEM) != SSL_SUCCESS) assert(0); + base.cert_, SSL_FILETYPE_PEM) != SSL_SUCCESS) throw(0); if (base.key_) if (SSL_CTX_use_PrivateKey_file(base.ctx_, base.key_, - SSL_FILETYPE_PEM) != SSL_SUCCESS) assert(0); + SSL_FILETYPE_PEM) != SSL_SUCCESS) throw(0); if (end == server_end) SetDH(base); diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp index 2ff30f436f5..e55c10c68c0 100644 --- a/extra/yassl/src/yassl_error.cpp +++ b/extra/yassl/src/yassl_error.cpp @@ -31,6 +31,11 @@ #pragma warning(disable: 4996) #endif +#ifdef _MSC_VER + // 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy + #pragma warning(disable: 4996) +#endif + namespace yaSSL { @@ -59,8 +64,9 @@ void SetErrorString(unsigned long error, char* buffer) { using namespace TaoCrypt; const int max = MAX_ERROR_SZ; // shorthand + int localError = error; // errors from a few enums - switch ((int) error) { + switch (localError) { // yaSSL proper errors case range_error : @@ -121,7 +127,7 @@ void SetErrorString(unsigned long error, char* buffer) case certificate_error : strncpy(buffer, "unable to proccess cerificate", max); - break; + break; case privateKey_error : strncpy(buffer, "unable to proccess private key, bad format", max); @@ -130,7 +136,7 @@ void SetErrorString(unsigned long error, char* buffer) case badVersion_error : strncpy(buffer, "protocol version mismatch", max); break; - + case compress_error : strncpy(buffer, "compression error", max); break; @@ -148,6 +154,10 @@ void SetErrorString(unsigned long error, char* buffer) strncpy(buffer, "the read operation would block", max); break; + case SSL_ERROR_WANT_WRITE : + strncpy(buffer, "the write operation would block", max); + break; + case CERTFICATE_ERROR : strncpy(buffer, "Unable to verify certificate", max); break; diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp index 15d7ec5fb21..c0ef23a4e94 100644 --- a/extra/yassl/src/yassl_imp.cpp +++ b/extra/yassl/src/yassl_imp.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2010, Oracle and/or its affiliates + Copyright (c) 2005, 2012, 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 @@ -117,7 +117,7 @@ void ClientDiffieHellmanPublic::build(SSL& ssl) 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); } @@ -135,8 +135,7 @@ void DH_Server::build(SSL& ssl) mySTL::auto_ptr<Auth> auth; const CertManager& cert = ssl.getCrypto().get_certManager(); - if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) - { + if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) { if (cert.get_keyType() != rsa_sa_algo) { ssl.SetError(privateKey_error); return; @@ -925,8 +924,6 @@ Data::Data(uint16 len, opaque* b) void Data::SetData(uint16 len, const opaque* buffer) { - assert(write_buffer_ == 0); - length_ = len; write_buffer_ = buffer; } @@ -992,6 +989,11 @@ void Data::Process(input_buffer& input, SSL& ssl) int dataSz = msgSz - ivExtra - digestSz - pad - padSz; opaque verify[SHA_LEN]; + if (dataSz < 0) { + ssl.SetError(bad_input); + return; + } + const byte* rawData = input.get_buffer() + input.get_current(); // read data @@ -1006,10 +1008,10 @@ void Data::Process(input_buffer& input, SSL& ssl) tmp.get_buffer(), tmp.get_size())); } else { - input_buffer* data; - ssl.addData(data = NEW_YS input_buffer(dataSz)); - input.read(data->get_buffer(), dataSz); - data->add_size(dataSz); + input_buffer* data; + ssl.addData(data = NEW_YS input_buffer(dataSz)); + input.read(data->get_buffer(), dataSz); + data->add_size(dataSz); } if (ssl.isTLS()) @@ -1085,19 +1087,37 @@ void Certificate::Process(input_buffer& input, SSL& ssl) uint32 list_sz; byte tmp[3]; + if (input.get_remaining() < sizeof(tmp)) { + ssl.SetError(YasslError(bad_input)); + return; + } tmp[0] = input[AUTO]; tmp[1] = input[AUTO]; tmp[2] = input[AUTO]; c24to32(tmp, list_sz); + + if (list_sz > (uint)MAX_RECORD_SIZE) { // sanity check + ssl.SetError(YasslError(bad_input)); + return; + } while (list_sz) { // cert size uint32 cert_sz; + + if (input.get_remaining() < sizeof(tmp)) { + ssl.SetError(YasslError(bad_input)); + return; + } tmp[0] = input[AUTO]; tmp[1] = input[AUTO]; tmp[2] = input[AUTO]; c24to32(tmp, cert_sz); + if (cert_sz > (uint)MAX_RECORD_SIZE || input.get_remaining() < cert_sz){ + ssl.SetError(YasslError(bad_input)); + return; + } x509* myCert; cm.AddPeerCert(myCert = NEW_YS x509(cert_sz)); input.read(myCert->use_buffer(), myCert->get_length()); @@ -1294,7 +1314,7 @@ void ServerHello::Process(input_buffer&, SSL& ssl) ssl.set_pending(cipher_suite_[1]); ssl.set_random(random_, server_end); if (id_len_) - ssl.set_sessionID(session_id_); + ssl.set_sessionID(session_id_); else ssl.useSecurity().use_connection().sessionID_Set_ = false; @@ -1422,7 +1442,7 @@ input_buffer& operator>>(input_buffer& input, ClientHello& hello) if (hello.id_len_) input.read(hello.session_id_, ID_LEN); // Suites - byte tmp[2]; + byte tmp[2]; uint16 len; tmp[0] = input[AUTO]; tmp[1] = input[AUTO]; @@ -1430,8 +1450,8 @@ input_buffer& operator>>(input_buffer& input, ClientHello& hello) hello.suite_len_ = min(len, static_cast<uint16>(MAX_SUITE_SZ)); input.read(hello.cipher_suites_, hello.suite_len_); - if (len > hello.suite_len_) // ignore extra suites - input.set_current(input.get_current() + len - hello.suite_len_); + if (len > hello.suite_len_) // ignore extra suites + input.set_current(input.get_current() + len - hello.suite_len_); // Compression hello.comp_len_ = input[AUTO]; @@ -1495,8 +1515,9 @@ void ClientHello::Process(input_buffer&, SSL& ssl) if (ssl.GetMultiProtocol()) { // SSLv23 support if (ssl.isTLS() && client_version_.minor_ < 1) { // downgrade to SSLv3 - ssl.useSecurity().use_connection().TurnOffTLS(); - ProtocolVersion pv = ssl.getSecurity().get_connection().version_; + ssl.useSecurity().use_connection().TurnOffTLS(); + + ProtocolVersion pv = ssl.getSecurity().get_connection().version_; bool removeDH = ssl.getSecurity().get_parms().removeDH_; bool removeRSA = false; bool removeDSA = false; @@ -1510,7 +1531,7 @@ void ClientHello::Process(input_buffer&, SSL& ssl) // reset w/ SSL suites ssl.useSecurity().use_parms().SetSuites(pv, removeDH, removeRSA, removeDSA); - } + } else if (ssl.isTLSv1_1() && client_version_.minor_ == 1) // downgrade to TLSv1, but use same suites ssl.useSecurity().use_connection().TurnOffTLS1_1(); @@ -1541,6 +1562,7 @@ void ClientHello::Process(input_buffer&, SSL& ssl) ssl.set_session(session); ssl.useSecurity().set_resuming(true); ssl.matchSuite(session->GetSuite(), SUITE_LEN); + if (ssl.GetError()) return; ssl.set_pending(ssl.getSecurity().get_parms().suite_[1]); ssl.set_masterSecret(session->GetSecret()); @@ -2037,7 +2059,7 @@ void Finished::Process(input_buffer& input, SSL& ssl) // verify hashes const Finished& verify = ssl.getHashes().get_verify(); uint finishedSz = ssl.isTLS() ? TLS_FINISHED_SZ : FINISHED_SZ; - + input.read(hashes_.md5_, finishedSz); if (memcmp(&hashes_, &verify.hashes_, finishedSz)) { diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp index 3d553e37337..65e17b01544 100644 --- a/extra/yassl/src/yassl_int.cpp +++ b/extra/yassl/src/yassl_int.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2011, Oracle and/or its affiliates + Copyright (c) 2005, 2012, 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 @@ -308,8 +308,9 @@ SSL::SSL(SSL_CTX* ctx) SetError(YasslError(err)); return; } - else if (serverSide && !(ctx->GetCiphers().setSuites_)) { + else if (serverSide && ctx->GetCiphers().setSuites_ == 0) { // remove RSA or DSA suites depending on cert key type + // but don't override user sets ProtocolVersion pv = secure_.get_connection().version_; bool removeDH = secure_.use_parms().removeDH_; @@ -1128,8 +1129,28 @@ void SSL::flushBuffer() void SSL::Send(const byte* buffer, uint sz) { - if (socket_.send(buffer, sz) != sz) - SetError(send_error); + unsigned int sent = 0; + + if (socket_.send(buffer, sz, sent) != sz) { + if (socket_.WouldBlock()) { + buffers_.SetOutput(NEW_YS output_buffer(sz - sent, buffer + sent, + sz - sent)); + SetError(YasslError(SSL_ERROR_WANT_WRITE)); + } + else + SetError(send_error); + } +} + + +void SSL::SendWriteBuffered() +{ + output_buffer* out = buffers_.TakeOutput(); + + if (out) { + mySTL::auto_ptr<output_buffer> tmp(out); + Send(out->get_buffer(), out->get_size()); + } } @@ -1291,7 +1312,6 @@ void SSL::matchSuite(const opaque* peer, uint length) if (secure_.use_parms().suites_[i] == peer[j]) { secure_.use_parms().suite_[0] = 0x00; secure_.use_parms().suite_[1] = peer[j]; - return; } @@ -1435,7 +1455,6 @@ void SSL::addBuffer(output_buffer* b) void SSL_SESSION::CopyX509(X509* x) { - assert(peerX509_ == 0); if (x == 0) return; X509_NAME* issuer = x->GetIssuer(); @@ -2232,7 +2251,7 @@ Hashes& sslHashes::use_certVerify() } -Buffers::Buffers() : rawInput_(0) +Buffers::Buffers() : prevSent(0), plainSz(0), rawInput_(0), output_(0) {} @@ -2243,12 +2262,18 @@ Buffers::~Buffers() STL::for_each(dataList_.begin(), dataList_.end(), del_ptr_zero()) ; ysDelete(rawInput_); + ysDelete(output_); +} + + +void Buffers::SetOutput(output_buffer* ob) +{ + output_ = ob; } void Buffers::SetRawInput(input_buffer* ib) { - assert(rawInput_ == 0); rawInput_ = ib; } @@ -2262,6 +2287,15 @@ input_buffer* Buffers::TakeRawInput() } +output_buffer* Buffers::TakeOutput() +{ + output_buffer* ret = output_; + output_ = 0; + + return ret; +} + + const Buffers::inputList& Buffers::getData() const { return dataList_; @@ -2536,14 +2570,12 @@ ASN1_STRING* StringHolder::GetString() // these versions should never get called int Compress(const byte* in, int sz, input_buffer& buffer) { - assert(0); return -1; } int DeCompress(input_buffer& in, int sz, input_buffer& out) { - assert(0); return -1; } diff --git a/extra/yassl/taocrypt/CMakeLists.txt b/extra/yassl/taocrypt/CMakeLists.txt index 750731a0449..10ed614445e 100644 --- a/extra/yassl/taocrypt/CMakeLists.txt +++ b/extra/yassl/taocrypt/CMakeLists.txt @@ -20,12 +20,14 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) ADD_DEFINITIONS(${SSL_DEFINES}) SET(TAOCRYPT_SOURCES src/aes.cpp src/aestables.cpp src/algebra.cpp src/arc4.cpp src/asn.cpp src/coding.cpp src/des.cpp src/dh.cpp src/dsa.cpp src/file.cpp src/hash.cpp src/integer.cpp src/md2.cpp - src/md4.cpp src/md5.cpp src/misc.cpp src/random.cpp src/ripemd.cpp src/rsa.cpp src/sha.cpp + src/md4.cpp src/md5.cpp src/misc.cpp src/random.cpp src/ripemd.cpp src/rsa.cpp src/sha.cpp + src/rabbit.cpp src/hc128.cpp include/aes.hpp include/algebra.hpp include/arc4.hpp include/asn.hpp include/block.hpp include/coding.hpp include/des.hpp include/dh.hpp include/dsa.hpp include/dsa.hpp include/error.hpp include/file.hpp include/hash.hpp include/hmac.hpp include/integer.hpp include/md2.hpp include/md5.hpp include/misc.hpp include/modarith.hpp include/modes.hpp - include/random.hpp include/ripemd.hpp include/rsa.hpp include/sha.hpp) + include/random.hpp include/ripemd.hpp include/rsa.hpp include/sha.hpp + include/rabbit.hpp include/hc128.hpp) IF(HAVE_EXPLICIT_TEMPLATE_INSTANTIATION) SET(TAOCRYPT_SOURCES ${TAOCRYPT_SOURCES} src/template_instnt.cpp) diff --git a/extra/yassl/taocrypt/README b/extra/yassl/taocrypt/README index 0a7ff301786..bd786b7ce54 100644 --- a/extra/yassl/taocrypt/README +++ b/extra/yassl/taocrypt/README @@ -21,7 +21,7 @@ Stream Ciphers: ARC4 Public Key Crypto: RSA, DSA, Diffie-Hellman Password based key derivation: PBKDF2 from PKCS #5 Pseudo Random Number Generators -Lare Integer Support +Large Integer Support Base 16/64 encoding/decoding DER encoding/decoding X.509 processing diff --git a/extra/yassl/taocrypt/benchmark/benchmark.cpp b/extra/yassl/taocrypt/benchmark/benchmark.cpp index 1d38b080d0d..6ed7351a56b 100644 --- a/extra/yassl/taocrypt/benchmark/benchmark.cpp +++ b/extra/yassl/taocrypt/benchmark/benchmark.cpp @@ -103,7 +103,7 @@ void bench_des() double persec = 1 / total * megs; - printf("3DES %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total, + printf("3DES %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total, persec); } @@ -123,7 +123,7 @@ void bench_aes(bool show) double persec = 1 / total * megs; if (show) - printf("AES %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total, + printf("AES %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total, persec); } @@ -142,7 +142,7 @@ void bench_twofish() double persec = 1 / total * megs; - printf("Twofish %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total, + printf("Twofish %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total, persec); } @@ -162,7 +162,7 @@ void bench_blowfish() double persec = 1 / total * megs; - printf("Blowfish %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total, + printf("Blowfish %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total, persec); } @@ -181,7 +181,7 @@ void bench_arc4() double persec = 1 / total * megs; - printf("ARC4 %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total, + printf("ARC4 %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total, persec); } @@ -203,7 +203,7 @@ void bench_md5() double persec = 1 / total * megs; - printf("MD5 %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total, + printf("MD5 %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total, persec); } @@ -231,7 +231,7 @@ void bench_sha() double persec = 1 / total * megs; - printf("SHA %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total, + printf("SHA %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total, persec); } @@ -253,7 +253,7 @@ void bench_ripemd() double persec = 1 / total * megs; - printf("RIPEMD %d megs took %5.3f seconds, %5.2f MB/s\n", megs, total, + printf("RIPEMD %d megs took %5.3f seconds, %6.2f MB/s\n", megs, total, persec); } @@ -276,7 +276,7 @@ void bench_rsa() byte message[] = "Everyone gets Friday off."; byte cipher[128]; // for 1024 bit byte plain[128]; // for 1024 bit - const int len = strlen((char*)message); + const int len = (word32)strlen((char*)message); int i; double start = current_time(); diff --git a/extra/yassl/taocrypt/benchmark/benchmark.dsp b/extra/yassl/taocrypt/benchmark/benchmark.dsp index 878dc2b2783..449299a1c8d 100644 --- a/extra/yassl/taocrypt/benchmark/benchmark.dsp +++ b/extra/yassl/taocrypt/benchmark/benchmark.dsp @@ -49,8 +49,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "benchmark - Win32 Debug" @@ -64,7 +64,7 @@ LINK32=link.exe # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\include" /I "..\mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" @@ -72,8 +72,8 @@ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept !ENDIF diff --git a/extra/yassl/taocrypt/benchmark/dh1024.der b/extra/yassl/taocrypt/benchmark/dh1024.der Binary files differindex 1a85d90f3f7..09f81ee14c1 100644 --- a/extra/yassl/taocrypt/benchmark/dh1024.der +++ b/extra/yassl/taocrypt/benchmark/dh1024.der diff --git a/extra/yassl/taocrypt/benchmark/dsa1024.der b/extra/yassl/taocrypt/benchmark/dsa1024.der Binary files differindex 1fcb37fad6a..3a6dfca4b8f 100644 --- a/extra/yassl/taocrypt/benchmark/dsa1024.der +++ b/extra/yassl/taocrypt/benchmark/dsa1024.der diff --git a/extra/yassl/taocrypt/benchmark/make.bat b/extra/yassl/taocrypt/benchmark/make.bat index 1457521bce9..1457521bce9 100644..100755 --- a/extra/yassl/taocrypt/benchmark/make.bat +++ b/extra/yassl/taocrypt/benchmark/make.bat diff --git a/extra/yassl/taocrypt/benchmark/rsa1024.der b/extra/yassl/taocrypt/benchmark/rsa1024.der Binary files differindex 8fc91814472..5ba3fbe6c9c 100644 --- a/extra/yassl/taocrypt/benchmark/rsa1024.der +++ b/extra/yassl/taocrypt/benchmark/rsa1024.der diff --git a/extra/yassl/taocrypt/certs/client-cert.der b/extra/yassl/taocrypt/certs/client-cert.der Binary files differnew file mode 100644 index 00000000000..9c2ef138bf6 --- /dev/null +++ b/extra/yassl/taocrypt/certs/client-cert.der diff --git a/extra/yassl/taocrypt/certs/client-key.der b/extra/yassl/taocrypt/certs/client-key.der Binary files differnew file mode 100644 index 00000000000..649406c4417 --- /dev/null +++ b/extra/yassl/taocrypt/certs/client-key.der diff --git a/extra/yassl/taocrypt/certs/dh1024.dat b/extra/yassl/taocrypt/certs/dh1024.dat new file mode 100644 index 00000000000..86a95518278 --- /dev/null +++ b/extra/yassl/taocrypt/certs/dh1024.dat @@ -0,0 +1 @@ +30818702818100DA9A18547FF03B385CC16508C173A7EF4EB61CB40EF8FEF3B31F145051676166BCDC3FE6B799FC394D08C26385F9413F896E09117E46209D6923602683CEA100924A6EE695281775C619DAA94EA8CB3691B4275B0183F1D39639EBC92995FE645D6C1BC28D409E585549BBD2C5DCDD6C208B04EADD8B7A6D997F72CBAD88390F020102
\ No newline at end of file diff --git a/extra/yassl/taocrypt/certs/dsa512.der b/extra/yassl/taocrypt/certs/dsa512.der Binary files differnew file mode 100644 index 00000000000..027bedeffb1 --- /dev/null +++ b/extra/yassl/taocrypt/certs/dsa512.der diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp index ece7140741a..c20387d86c7 100644 --- a/extra/yassl/taocrypt/include/asn.hpp +++ b/extra/yassl/taocrypt/include/asn.hpp @@ -167,6 +167,7 @@ public: void Decode(RSA_PublicKey&); private: void ReadHeader(); + void ReadHeaderOpenSSL(); }; diff --git a/extra/yassl/taocrypt/include/block.hpp b/extra/yassl/taocrypt/include/block.hpp index 9885c44d2c9..77017e9d5e4 100644 --- a/extra/yassl/taocrypt/include/block.hpp +++ b/extra/yassl/taocrypt/include/block.hpp @@ -61,10 +61,6 @@ public: void destroy(pointer p) {p->~T();} size_type max_size() const {return ~size_type(0)/sizeof(T);} protected: - static void CheckSize(size_t n) - { - assert(n <= ~size_t(0) / sizeof(T)); - } }; @@ -101,7 +97,8 @@ public: pointer allocate(size_type n, const void* = 0) { - this->CheckSize(n); + if (n > this->max_size()) + return 0; if (n == 0) return 0; return NEW_TC T[n]; @@ -144,9 +141,8 @@ public: return *this; } - T& operator[] (word32 i) { assert(i < sz_); return buffer_[i]; } - const T& operator[] (word32 i) const - { assert(i < sz_); return buffer_[i]; } + T& operator[] (word32 i) { return buffer_[i]; } + const T& operator[] (word32 i) const { return buffer_[i]; } T* operator+ (word32 i) { return buffer_ + i; } const T* operator+ (word32 i) const { return buffer_ + i; } diff --git a/extra/yassl/taocrypt/include/blowfish.hpp b/extra/yassl/taocrypt/include/blowfish.hpp index e03ed41aab8..e868872d3cf 100644 --- a/extra/yassl/taocrypt/include/blowfish.hpp +++ b/extra/yassl/taocrypt/include/blowfish.hpp @@ -59,11 +59,11 @@ public: void SetKey(const byte* key, word32 sz, CipherDir fake = ENCRYPTION); void SetIV(const byte* iv) { memcpy(r_, iv, BLOCK_SIZE); } private: - static const word32 p_init_[ROUNDS + 2]; - static const word32 s_init_[4 * 256]; + static const word32 p_init_[ROUNDS + 2]; + static const word32 s_init_[4 * 256]; - word32 pbox_[ROUNDS + 2 + 4 * 256]; - word32* sbox_; + word32 pbox_[ROUNDS + 2 + 4 * 256]; + word32* sbox_; void crypt_block(const word32 in[2], word32 out[2]) const; void AsmProcess(const byte* in, byte* out) const; diff --git a/extra/yassl/taocrypt/include/des.hpp b/extra/yassl/taocrypt/include/des.hpp index f99a289392f..2bc41fc2628 100644 --- a/extra/yassl/taocrypt/include/des.hpp +++ b/extra/yassl/taocrypt/include/des.hpp @@ -84,7 +84,7 @@ private: // DES_EDE3 class DES_EDE3 : public Mode_BASE { public: - DES_EDE3(CipherDir DIR, Mode MODE) + DES_EDE3(CipherDir DIR, Mode MODE) : Mode_BASE(DES_BLOCK_SIZE, DIR, MODE) {} void SetKey(const byte*, word32, CipherDir dir); diff --git a/extra/yassl/taocrypt/include/file.hpp b/extra/yassl/taocrypt/include/file.hpp index e22040f60f0..c340c4fa3ea 100644 --- a/extra/yassl/taocrypt/include/file.hpp +++ b/extra/yassl/taocrypt/include/file.hpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2007 MySQL AB + Copyright (C) 2000, 2012, 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 @@ -39,25 +39,32 @@ public: explicit Source(word32 sz = 0) : buffer_(sz), current_(0) {} Source(const byte* b, word32 sz) : buffer_(b, sz), current_(0) {} + word32 remaining() { if (GetError().What()) return 0; + else return buffer_.size() - current_; } word32 size() const { return buffer_.size(); } void grow(word32 sz) { buffer_.CleanGrow(sz); } + + bool IsLeft(word32 sz) { if (remaining() >= sz) return true; + else { SetError(CONTENT_E); return false; } } const byte* get_buffer() const { return buffer_.get_buffer(); } const byte* get_current() const { return &buffer_[current_]; } word32 get_index() const { return current_; } - void set_index(word32 i) { current_ = i; } + void set_index(word32 i) { if (i < size()) current_ = i; } byte operator[] (word32 i) { current_ = i; return next(); } - byte next() { return buffer_[current_++]; } - byte prev() { return buffer_[--current_]; } + byte next() { if (IsLeft(1)) return buffer_[current_++]; else return 0; } + byte prev() { if (current_) return buffer_[--current_]; else return 0; } void add(const byte* data, word32 len) { - memcpy(buffer_.get_buffer() + current_, data, len); - current_ += len; + if (IsLeft(len)) { + memcpy(buffer_.get_buffer() + current_, data, len); + current_ += len; + } } - void advance(word32 i) { current_ += i; } + void advance(word32 i) { if (IsLeft(i)) current_ += i; } void reset(ByteBlock&); Error GetError() { return error_; } diff --git a/extra/yassl/taocrypt/include/hash.hpp b/extra/yassl/taocrypt/include/hash.hpp index fa5f6c04720..4ebc82e073d 100644 --- a/extra/yassl/taocrypt/include/hash.hpp +++ b/extra/yassl/taocrypt/include/hash.hpp @@ -63,8 +63,8 @@ protected: word32 buffLen_; // in bytes HashLengthType loLen_; // length in bytes HashLengthType hiLen_; // length in bytes - word32 digest_[MaxDigestSz]; - word32 buffer_[MaxBufferSz / sizeof(word32)]; + word32 digest_[MaxDigestSz]; + word32 buffer_[MaxBufferSz / sizeof(word32)]; virtual void Transform() = 0; diff --git a/extra/yassl/taocrypt/include/hc128.hpp b/extra/yassl/taocrypt/include/hc128.hpp new file mode 100644 index 00000000000..d1cf5f075f2 --- /dev/null +++ b/extra/yassl/taocrypt/include/hc128.hpp @@ -0,0 +1,63 @@ +/* + Copyright (c) 2005, 2010, 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; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* hc128.hpp defines HC128 +*/ + + +#ifndef TAO_CRYPT_HC128_HPP +#define TAO_CRYPT_HC128_HPP + +#include "misc.hpp" + +namespace TaoCrypt { + + +// HC128 encryption and decryption +class HC128 { +public: + + typedef HC128 Encryption; + typedef HC128 Decryption; + + + HC128() {} + + void Process(byte*, const byte*, word32); + void SetKey(const byte*, const byte*); +private: + word32 T_[1024]; /* P[i] = T[i]; Q[i] = T[1024 + i ]; */ + word32 X_[16]; + word32 Y_[16]; + word32 counter1024_; /* counter1024 = i mod 1024 at the ith step */ + word32 key_[8]; + word32 iv_[8]; + + void SetIV(const byte*); + void GenerateKeystream(word32*); + void SetupUpdate(); + + HC128(const HC128&); // hide copy + const HC128 operator=(const HC128&); // and assign +}; + +} // namespace + + +#endif // TAO_CRYPT_HC128_HPP + diff --git a/extra/yassl/taocrypt/include/integer.hpp b/extra/yassl/taocrypt/include/integer.hpp index 186d62bb866..256573cf622 100644 --- a/extra/yassl/taocrypt/include/integer.hpp +++ b/extra/yassl/taocrypt/include/integer.hpp @@ -110,13 +110,6 @@ namespace TaoCrypt { #endif -// general MIN -template<typename T> inline -const T& min(const T& a, const T& b) -{ - return a < b ? a : b; -} - // general MAX template<typename T> inline diff --git a/extra/yassl/taocrypt/include/kernelc.hpp b/extra/yassl/taocrypt/include/kernelc.hpp index daa3762d5dd..5bdf1cffa3f 100644 --- a/extra/yassl/taocrypt/include/kernelc.hpp +++ b/extra/yassl/taocrypt/include/kernelc.hpp @@ -30,17 +30,5 @@ extern "C" void* memcpy(void*, const void*, size_t); extern "C" void* memset(void*, int, size_t); extern "C" void printk(char *fmt, ...); -#define KERN_ERR "<3>" /* error conditions */ - -#if defined(NDEBUG) - #define assert(p) ((void)0) -#else - #define assert(expr) \ - if (!(expr)) { \ - printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); } -#endif - - #endif // TAOCRYPT_KERNELC_HPP diff --git a/extra/yassl/taocrypt/include/misc.hpp b/extra/yassl/taocrypt/include/misc.hpp index a375b17eb1e..b6925f916f8 100644 --- a/extra/yassl/taocrypt/include/misc.hpp +++ b/extra/yassl/taocrypt/include/misc.hpp @@ -24,7 +24,6 @@ #if !defined(DO_TAOCRYPT_KERNEL_MODE) #include <stdlib.h> - #include <assert.h> #include <string.h> #else #include "kernelc.hpp" @@ -62,30 +61,30 @@ void CleanUp(); template<typename T> void tcDelete(T* ptr) { - if (ptr) ptr->~T(); - ::operator delete(ptr, TaoCrypt::tc); + if (ptr) ptr->~T(); + ::operator delete(ptr, TaoCrypt::tc); } template<typename T> void tcArrayDelete(T* ptr) { - // can't do array placement destruction since not tracking size in - // allocation, only allow builtins to use array placement since they - // don't need destructors called - typedef char builtin[IsFundamentalType<T>::Yes ? 1 : -1]; - (void)sizeof(builtin); + // can't do array placement destruction since not tracking size in + // allocation, only allow builtins to use array placement since they + // don't need destructors called + typedef char builtin[IsFundamentalType<T>::Yes ? 1 : -1]; + (void)sizeof(builtin); - ::operator delete[](ptr, TaoCrypt::tc); + ::operator delete[](ptr, TaoCrypt::tc); } #define NEW_TC new (TaoCrypt::tc) // to resolve compiler generated operator delete on base classes with - // virtual destructors (when on stack), make sure doesn't get called + // virtual destructors (when on stack) class virtual_base { public: - static void operator delete(void*) { assert(0); } + static void operator delete(void*) { } }; #else // YASSL_PURE_C @@ -366,7 +365,6 @@ inline bool IsPowerOf2(T n) template <class T1, class T2> inline T2 ModPowerOf2(T1 a, T2 b) { - assert(IsPowerOf2(b)); return T2(a) & (b-1); } @@ -409,14 +407,12 @@ inline bool IsAligned(const void* p, T* dummy = 0) // VC60 workaround template <class T> inline T rotlFixed(T x, unsigned int y) { - assert(y < sizeof(T)*8); - return (x<<y) | (x>>(sizeof(T)*8-y)); + return (x<<y) | (x>>(sizeof(T)*8-y)); } template <class T> inline T rotrFixed(T x, unsigned int y) { - assert(y < sizeof(T)*8); - return (x>>y) | (x<<(sizeof(T)*8-y)); + return (x>>y) | (x<<(sizeof(T)*8-y)); } #ifdef INTEL_INTRINSICS @@ -425,13 +421,11 @@ template <class T> inline T rotrFixed(T x, unsigned int y) template<> inline word32 rotlFixed(word32 x, word32 y) { - assert(y < 32); return y ? _lrotl(x, y) : x; } template<> inline word32 rotrFixed(word32 x, word32 y) { - assert(y < 32); return y ? _lrotr(x, y) : x; } @@ -441,7 +435,9 @@ template<> inline word32 rotrFixed(word32 x, word32 y) #undef min #endif -inline word32 min(word32 a, word32 b) + +template <class T> +inline const T& min(const T& a, const T& b) { return a < b ? a : b; } @@ -486,7 +482,6 @@ inline word64 ByteReverse(word64 value) template <typename T> inline void ByteReverse(T* out, const T* in, word32 byteCount) { - assert(byteCount % sizeof(T) == 0); word32 count = byteCount/sizeof(T); for (word32 i=0; i<count; i++) out[i] = ByteReverse(in[i]); @@ -574,7 +569,6 @@ inline void GetUserKey(ByteOrder order, T* out, word32 outlen, const byte* in, word32 inlen) { const unsigned int U = sizeof(T); - assert(inlen <= outlen*U); memcpy(out, in, inlen); memset((byte *)out+inlen, 0, outlen*U-inlen); ByteReverseIf(out, out, RoundUpToMultipleOf(inlen, U), order); @@ -583,7 +577,8 @@ inline void GetUserKey(ByteOrder order, T* out, word32 outlen, const byte* in, #ifdef _MSC_VER // disable conversion warning - #pragma warning(disable:4244) + // 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy + #pragma warning(disable:4244 4996) #endif @@ -678,10 +673,7 @@ template <class T> inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block) { if (assumeAligned) - { - assert(IsAligned<T>(block)); return ByteReverseIf(*reinterpret_cast<const T *>(block), order); - } else return UnalignedGetWord<T>(order, block); } @@ -699,7 +691,6 @@ inline void PutWord(bool assumeAligned, ByteOrder order, byte* block, T value, { if (assumeAligned) { - assert(IsAligned<T>(block)); if (xorBlock) *reinterpret_cast<T *>(block) = ByteReverseIf(value, order) ^ *reinterpret_cast<const T *>(xorBlock); @@ -812,7 +803,6 @@ inline T SafeLeftShift(T value) inline word ShiftWordsLeftByBits(word* r, unsigned int n, unsigned int shiftBits) { - assert (shiftBits<WORD_BITS); word u, carry=0; if (shiftBits) for (unsigned int i=0; i<n; i++) @@ -828,7 +818,6 @@ word ShiftWordsLeftByBits(word* r, unsigned int n, unsigned int shiftBits) inline word ShiftWordsRightByBits(word* r, unsigned int n, unsigned int shiftBits) { - assert (shiftBits<WORD_BITS); word u, carry=0; if (shiftBits) for (int i=n-1; i>=0; i--) diff --git a/extra/yassl/taocrypt/include/modes.hpp b/extra/yassl/taocrypt/include/modes.hpp index 2285bd0e845..5fd36b80d3e 100644 --- a/extra/yassl/taocrypt/include/modes.hpp +++ b/extra/yassl/taocrypt/include/modes.hpp @@ -61,9 +61,7 @@ public: explicit Mode_BASE(int sz, CipherDir dir, Mode mode) : blockSz_(sz), reg_(reinterpret_cast<byte*>(r_)), tmp_(reinterpret_cast<byte*>(t_)), dir_(dir), mode_(mode) - { - assert(sz <= MaxBlockSz); - } + {} virtual ~Mode_BASE() {} virtual void Process(byte*, const byte*, word32); @@ -96,8 +94,7 @@ inline void Mode_BASE::Process(byte* out, const byte* in, word32 sz) { if (mode_ == ECB) ECB_Process(out, in, sz); - else if (mode_ == CBC) - { + else if (mode_ == CBC) { if (dir_ == ENCRYPTION) CBC_Encrypt(out, in, sz); else diff --git a/extra/yassl/taocrypt/include/pwdbased.hpp b/extra/yassl/taocrypt/include/pwdbased.hpp index 5ece1a8f43b..f40a336e2c3 100644 --- a/extra/yassl/taocrypt/include/pwdbased.hpp +++ b/extra/yassl/taocrypt/include/pwdbased.hpp @@ -48,8 +48,9 @@ word32 PBKDF2_HMAC<T>::DeriveKey(byte* derived, word32 dLen, const byte* pwd, word32 pLen, const byte* salt, word32 sLen, word32 iterations) const { - assert(dLen <= MaxDerivedKeyLength()); - assert(iterations > 0); + if (dLen > MaxDerivedKeyLength()) + return 0; + ByteBlock buffer(T::DIGEST_SIZE); HMAC<T> hmac; diff --git a/extra/yassl/taocrypt/include/rabbit.hpp b/extra/yassl/taocrypt/include/rabbit.hpp new file mode 100644 index 00000000000..1e7276dd8ec --- /dev/null +++ b/extra/yassl/taocrypt/include/rabbit.hpp @@ -0,0 +1,65 @@ +/* + Copyright (c) 2005, 2010, 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; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +/* rabbit.hpp defines Rabbit +*/ + + +#ifndef TAO_CRYPT_RABBIT_HPP +#define TAO_CRYPT_RABBIT_HPP + +#include "misc.hpp" + +namespace TaoCrypt { + + +// Rabbit encryption and decryption +class Rabbit { +public: + + typedef Rabbit Encryption; + typedef Rabbit Decryption; + + enum RabbitCtx { Master = 0, Work = 1 }; + + Rabbit() {} + + void Process(byte*, const byte*, word32); + void SetKey(const byte*, const byte*); +private: + struct Ctx { + word32 x[8]; + word32 c[8]; + word32 carry; + }; + + Ctx masterCtx_; + Ctx workCtx_; + + void NextState(RabbitCtx); + void SetIV(const byte*); + + Rabbit(const Rabbit&); // hide copy + const Rabbit operator=(const Rabbit&); // and assign +}; + +} // namespace + + +#endif // TAO_CRYPT_RABBIT_HPP + diff --git a/extra/yassl/taocrypt/include/rsa.hpp b/extra/yassl/taocrypt/include/rsa.hpp index c895ab6fd34..11a4ccfd039 100644 --- a/extra/yassl/taocrypt/include/rsa.hpp +++ b/extra/yassl/taocrypt/include/rsa.hpp @@ -178,7 +178,8 @@ void RSA_Encryptor<Pad>::Encrypt(const byte* plain, word32 sz, byte* cipher, RandomNumberGenerator& rng) { PK_Lengths lengths(key_.GetModulus()); - assert(sz <= lengths.FixedMaxPlaintextLength()); + if (sz > lengths.FixedMaxPlaintextLength()) + return; ByteBlock paddedBlock(lengths.PaddedBlockByteLength()); padding_.Pad(plain, sz, paddedBlock.get_buffer(), @@ -195,7 +196,6 @@ word32 RSA_Decryptor<Pad>::Decrypt(const byte* cipher, word32 sz, byte* plain, RandomNumberGenerator& rng) { PK_Lengths lengths(key_.GetModulus()); - assert(sz == lengths.FixedCiphertextLength()); if (sz != lengths.FixedCiphertextLength()) return 0; diff --git a/extra/yassl/taocrypt/include/runtime.hpp b/extra/yassl/taocrypt/include/runtime.hpp index 3b9d0d9b095..328c8e9e978 100644 --- a/extra/yassl/taocrypt/include/runtime.hpp +++ b/extra/yassl/taocrypt/include/runtime.hpp @@ -31,7 +31,6 @@ #ifdef __sun -#include <assert.h> // Handler for pure virtual functions namespace __Crun { @@ -46,9 +45,7 @@ namespace __Crun { #if __GNUC__ > 2 extern "C" { -#if !defined(DO_TAOCRYPT_KERNEL_MODE) - #include <assert.h> -#else +#if defined(DO_TAOCRYPT_KERNEL_MODE) #include "kernelc.hpp" #endif int __cxa_pure_virtual () __attribute__ ((weak)); diff --git a/extra/yassl/taocrypt/include/types.hpp b/extra/yassl/taocrypt/include/types.hpp index 3efdcdfbccb..5d8bc9f0683 100644 --- a/extra/yassl/taocrypt/include/types.hpp +++ b/extra/yassl/taocrypt/include/types.hpp @@ -62,7 +62,7 @@ typedef unsigned int word32; // compilers we've found 64-bit multiply insructions for #if defined(__GNUC__) || defined(_MSC_VER) || defined(__DECCXX) #if !(defined(__ICC) || defined(__INTEL_COMPILER)) - #define HAVE_64_MULTIPLY + #define HAVE_64_MULTIPLY #endif #endif diff --git a/extra/yassl/taocrypt/mySTL/stdexcept.hpp b/extra/yassl/taocrypt/mySTL/stdexcept.hpp index 9696995248d..15533eebc02 100644 --- a/extra/yassl/taocrypt/mySTL/stdexcept.hpp +++ b/extra/yassl/taocrypt/mySTL/stdexcept.hpp @@ -26,7 +26,6 @@ #include <string.h> // strncpy -#include <assert.h> // assert #include <stdlib.h> // size_t @@ -41,7 +40,7 @@ public: virtual const char* what() const { return ""; } // for compiler generated call, never used - static void operator delete(void*) { assert(0); } + static void operator delete(void*) { } private: // don't allow dynamic creation of exceptions static void* operator new(size_t); diff --git a/extra/yassl/taocrypt/mySTL/vector.hpp b/extra/yassl/taocrypt/mySTL/vector.hpp index 8ba8813ca70..35b92610942 100644 --- a/extra/yassl/taocrypt/mySTL/vector.hpp +++ b/extra/yassl/taocrypt/mySTL/vector.hpp @@ -26,7 +26,6 @@ #include "helpers.hpp" // construct, destory, fill, etc. #include "algorithm.hpp" // swap -#include <assert.h> // assert namespace mySTL { @@ -141,9 +140,9 @@ private: // for growing, n must be bigger than other size vector(size_t n, const vector& other) : vec_(n) { - assert(n > other.size()); - vec_.finish_ = uninit_copy(other.vec_.start_, other.vec_.finish_, - vec_.start_); + if (n > other.size()) + vec_.finish_ = uninit_copy(other.vec_.start_, other.vec_.finish_, + vec_.start_); } }; diff --git a/extra/yassl/taocrypt/src/aes.cpp b/extra/yassl/taocrypt/src/aes.cpp index bf40f414eaa..3b09c5280bf 100644 --- a/extra/yassl/taocrypt/src/aes.cpp +++ b/extra/yassl/taocrypt/src/aes.cpp @@ -79,7 +79,7 @@ void AES::Process(byte* out, const byte* in, word32 sz) out += BLOCK_SIZE; in += BLOCK_SIZE; } - } + } } #endif // DO_AES_ASM @@ -87,8 +87,13 @@ void AES::Process(byte* out, const byte* in, word32 sz) void AES::SetKey(const byte* userKey, word32 keylen, CipherDir /*dummy*/) { - assert( (keylen == 16) || (keylen == 24) || (keylen == 32) ); - + if (keylen <= 16) + keylen = 16; + else if (keylen >= 32) + keylen = 32; + else if (keylen != 24) + keylen = 24; + rounds_ = keylen/4 + 6; word32 temp, *rk = key_; @@ -246,34 +251,34 @@ void AES::encrypt(const byte* inBlock, const byte* xorBlock, for (;;) { t0 = Te0[GETBYTE(s0, 3)] ^ - Te1[GETBYTE(s1, 2)] ^ - Te2[GETBYTE(s2, 1)] ^ - Te3[GETBYTE(s3, 0)] ^ + Te1[GETBYTE(s1, 2)] ^ + Te2[GETBYTE(s2, 1)] ^ + Te3[GETBYTE(s3, 0)] ^ rk[4]; t1 = Te0[GETBYTE(s1, 3)] ^ - Te1[GETBYTE(s2, 2)] ^ - Te2[GETBYTE(s3, 1)] ^ - Te3[GETBYTE(s0, 0)] ^ + Te1[GETBYTE(s2, 2)] ^ + Te2[GETBYTE(s3, 1)] ^ + Te3[GETBYTE(s0, 0)] ^ rk[5]; t2 = Te0[GETBYTE(s2, 3)] ^ - Te1[GETBYTE(s3, 2)] ^ - Te2[GETBYTE(s0, 1)] ^ - Te3[GETBYTE(s1, 0)] ^ + Te1[GETBYTE(s3, 2)] ^ + Te2[GETBYTE(s0, 1)] ^ + Te3[GETBYTE(s1, 0)] ^ rk[6]; t3 = Te0[GETBYTE(s3, 3)] ^ - Te1[GETBYTE(s0, 2)] ^ - Te2[GETBYTE(s1, 1)] ^ - Te3[GETBYTE(s2, 0)] ^ + Te1[GETBYTE(s0, 2)] ^ + Te2[GETBYTE(s1, 1)] ^ + Te3[GETBYTE(s2, 0)] ^ rk[7]; rk += 8; if (--r == 0) { break; } - + s0 = Te0[GETBYTE(t0, 3)] ^ Te1[GETBYTE(t1, 2)] ^ @@ -422,7 +427,7 @@ void AES::decrypt(const byte* inBlock, const byte* xorBlock, (Td4[GETBYTE(t3, 2)] & 0x00ff0000) ^ (Td4[GETBYTE(t2, 1)] & 0x0000ff00) ^ (Td4[GETBYTE(t1, 0)] & 0x000000ff) ^ - rk[0]; + rk[0]; s1 = (Td4[GETBYTE(t1, 3)] & 0xff000000) ^ (Td4[GETBYTE(t0, 2)] & 0x00ff0000) ^ diff --git a/extra/yassl/taocrypt/src/aestables.cpp b/extra/yassl/taocrypt/src/aestables.cpp index e9d6b7a80cb..05c2c3b8e62 100644 --- a/extra/yassl/taocrypt/src/aestables.cpp +++ b/extra/yassl/taocrypt/src/aestables.cpp @@ -33,6 +33,4 @@ const word32 AES::rcon_[] = { }; - - } // namespace diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp index b4afda44535..29754b27b5e 100644 --- a/extra/yassl/taocrypt/src/algebra.cpp +++ b/extra/yassl/taocrypt/src/algebra.cpp @@ -246,7 +246,6 @@ void AbstractGroup::SimultaneousMultiply(Integer *results, const Integer &base, for (i=0; i<expCount; i++) { - assert(expBegin->NotNegative()); exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0)); exponents[i].FindNextWindow(); buckets[i].resize(1<<(exponents[i].windowSize-1), Identity()); @@ -287,7 +286,7 @@ void AbstractGroup::SimultaneousMultiply(Integer *results, const Integer &base, r = buckets[i][buckets[i].size()-1]; if (buckets[i].size() > 1) { - for (int j= (unsigned int) (buckets[i].size()) - 2; j >= 1; j--) + for (size_t j = buckets[i].size()-2; j >= 1; j--) { Accumulate(buckets[i][j], buckets[i][j+1]); Accumulate(r, buckets[i][j]); diff --git a/extra/yassl/taocrypt/src/arc4.cpp b/extra/yassl/taocrypt/src/arc4.cpp index 0944cc31837..4630adcb11a 100644 --- a/extra/yassl/taocrypt/src/arc4.cpp +++ b/extra/yassl/taocrypt/src/arc4.cpp @@ -104,7 +104,7 @@ void ARC4::Process(byte* out, const byte* in, word32 length) #ifdef DO_ARC4_ASM #ifdef _MSC_VER - __declspec(naked) + __declspec(naked) #else __attribute__ ((noinline)) #endif diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp index 1b81db4f0a4..a502666d15b 100644 --- a/extra/yassl/taocrypt/src/asn.cpp +++ b/extra/yassl/taocrypt/src/asn.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2005-2007 MySQL AB, 2009, 2010 Sun Microsystems, Inc. + Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -111,7 +111,8 @@ bool ValidateDate(const byte* date, byte format, CertDecoder::DateType dt) GetTime(certTime.tm_min, date, i); GetTime(certTime.tm_sec, date, i); - assert(date[i] == 'Z'); // only Zulu supported for this profile + if (date[i] != 'Z') // only Zulu supported for this profile + return false; time_t ltime = time(0); tm* localTime = gmtime(<ime); @@ -143,6 +144,8 @@ word32 GetLength(Source& source) if (b >= LONG_LENGTH) { word32 bytes = b & 0x7F; + if (source.IsLeft(bytes) == false) return 0; + while (bytes--) { b = source.next(); length = (length << 8) | b; @@ -214,9 +217,9 @@ void PublicKey::AddToEnd(const byte* data, word32 len) Signer::Signer(const byte* k, word32 kSz, const char* n, const byte* h) : key_(k, kSz) { - size_t sz = strlen(n); - memcpy(name_, n, sz); - name_[sz] = 0; + size_t sz = strlen(n); + memcpy(name_, n, sz); + name_[sz] = 0; memcpy(hash_, h, SHA::DIGEST_SIZE); } @@ -364,12 +367,59 @@ void RSA_Public_Decoder::Decode(RSA_PublicKey& key) ReadHeader(); if (source_.GetError().What()) return; + ReadHeaderOpenSSL(); // may or may not be + if (source_.GetError().What()) return; + // public key key.SetModulus(GetInteger(Integer().Ref())); key.SetPublicExponent(GetInteger(Integer().Ref())); } +// Read OpenSSL format public header +void RSA_Public_Decoder::ReadHeaderOpenSSL() +{ + byte b = source_.next(); // peek + source_.prev(); + + if (b != INTEGER) { // have OpenSSL public format + GetSequence(); + b = source_.next(); + if (b != OBJECT_IDENTIFIER) { + source_.SetError(OBJECT_ID_E); + return; + } + + word32 len = GetLength(source_); + source_.advance(len); + + b = source_.next(); + if (b == TAG_NULL) { // could have NULL tag and 0 terminator, may not + b = source_.next(); + if (b != 0) { + source_.SetError(EXPECT_0_E); + return; + } + } + else + source_.prev(); // put back + + b = source_.next(); + if (b != BIT_STRING) { + source_.SetError(BIT_STR_E); + return; + } + + len = GetLength(source_); + b = source_.next(); + if (b != 0) // could have 0 + source_.prev(); // put back + + GetSequence(); + } +} + + void RSA_Public_Decoder::ReadHeader() { GetSequence(); @@ -420,12 +470,12 @@ CertDecoder::CertDecoder(Source& s, bool decode, SignerList* signers, bool noVerify, CertType ct) : BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0), signature_(0), verify_(!noVerify) -{ +{ issuer_[0] = 0; subject_[0] = 0; if (decode) - Decode(signers, ct); + Decode(signers, ct); } @@ -470,9 +520,9 @@ void CertDecoder::Decode(SignerList* signers, CertType ct) source_.SetError(SIG_OID_E); return; } - + if (ct != CA && verify_ && !ValidateSignature(signers)) - source_.SetError(SIG_OTHER_E); + source_.SetError(SIG_OTHER_E); } @@ -530,8 +580,10 @@ void CertDecoder::StoreKey() read = source_.get_index() - read; length += read; + if (source_.GetError().What()) return; while (read--) source_.prev(); + if (source_.IsLeft(length) == false) return; key_.SetSize(length); key_.SetKey(source_.get_current()); source_.advance(length); @@ -563,6 +615,8 @@ void CertDecoder::AddDSA() word32 length = GetLength(source_); length += source_.get_index() - idx; + if (source_.IsLeft(length) == false) return; + key_.AddToEnd(source_.get_buffer() + idx, length); } @@ -572,6 +626,8 @@ word32 CertDecoder::GetAlgoId() { if (source_.GetError().What()) return 0; word32 length = GetSequence(); + + if (source_.GetError().What()) return 0; byte b = source_.next(); if (b != OBJECT_IDENTIFIER) { @@ -580,26 +636,25 @@ word32 CertDecoder::GetAlgoId() } length = GetLength(source_); + if (source_.IsLeft(length) == false) return 0; + word32 oid = 0; - while(length--) oid += source_.next(); // just sum it up for now - if (oid != SHAwDSA && oid != DSAk) { - b = source_.next(); // should have NULL tag and 0 - - if (b != TAG_NULL) { - source_.SetError(TAG_NULL_E); - return 0; - } - + // could have NULL tag and 0 terminator, but may not + b = source_.next(); + if (b == TAG_NULL) { b = source_.next(); if (b != 0) { source_.SetError(EXPECT_0_E); return 0; } } - + else + // go back, didn't have it + b = source_.prev(); + return oid; } @@ -616,6 +671,10 @@ word32 CertDecoder::GetSignature() } sigLength_ = GetLength(source_); + if (sigLength_ == 0 || source_.IsLeft(sigLength_) == false) { + source_.SetError(CONTENT_E); + return 0; + } b = source_.next(); if (b != 0) { @@ -653,20 +712,22 @@ word32 CertDecoder::GetDigest() } -char *CertDecoder::AddTag(char *ptr, const char *buf_end, - const char *tag_name, word32 tag_name_length, - word32 tag_value_length) +// memory length checked add tag to buffer +char* CertDecoder::AddTag(char* ptr, const char* buf_end, const char* tag_name, + word32 tag_name_length, word32 tag_value_length) { - if (ptr + tag_name_length + tag_value_length > buf_end) - return 0; - - memcpy(ptr, tag_name, tag_name_length); - ptr+= tag_name_length; - - memcpy(ptr, source_.get_current(), tag_value_length); - ptr+= tag_value_length; - - return ptr; + if (ptr + tag_name_length + tag_value_length > buf_end) { + source_.SetError(CONTENT_E); + return 0; + } + + memcpy(ptr, tag_name, tag_name_length); + ptr += tag_name_length; + + memcpy(ptr, source_.get_current(), tag_value_length); + ptr += tag_value_length; + + return ptr; } @@ -679,18 +740,20 @@ void CertDecoder::GetName(NameType nt) word32 length = GetSequence(); // length of all distinguished names if (length >= ASN_NAME_MAX) - goto err; + return; + if (source_.IsLeft(length) == false) return; length += source_.get_index(); - - char *ptr, *buf_end; + + char* ptr; + char* buf_end; if (nt == ISSUER) { - ptr= issuer_; - buf_end= ptr + sizeof(issuer_) - 1; // 1 byte for trailing 0 + ptr = issuer_; + buf_end = ptr + sizeof(issuer_) - 1; // 1 byte for trailing 0 } else { - ptr= subject_; - buf_end= ptr + sizeof(subject_) - 1; // 1 byte for trailing 0 + ptr = subject_; + buf_end = ptr + sizeof(subject_) - 1; // 1 byte for trailing 0 } while (source_.get_index() < length) { @@ -704,7 +767,10 @@ void CertDecoder::GetName(NameType nt) } word32 oidSz = GetLength(source_); + if (source_.IsLeft(oidSz) == false) return; + byte joint[2]; + if (source_.IsLeft(sizeof(joint)) == false) return; memcpy(joint, source_.get_current(), sizeof(joint)); // v1 name types @@ -714,62 +780,68 @@ void CertDecoder::GetName(NameType nt) b = source_.next(); // strType word32 strLen = GetLength(source_); + if (source_.IsLeft(strLen) == false) return; + switch (id) { case COMMON_NAME: - if (!(ptr= AddTag(ptr, buf_end, "/CN=", 4, strLen))) - goto err; + if (!(ptr = AddTag(ptr, buf_end, "/CN=", 4, strLen))) + return; break; case SUR_NAME: - if (!(ptr= AddTag(ptr, buf_end, "/SN=", 4, strLen))) - goto err; + if (!(ptr = AddTag(ptr, buf_end, "/SN=", 4, strLen))) + return; break; case COUNTRY_NAME: - if (!(ptr= AddTag(ptr, buf_end, "/C=", 3, strLen))) - goto err; + if (!(ptr = AddTag(ptr, buf_end, "/C=", 3, strLen))) + return; break; case LOCALITY_NAME: - if (!(ptr= AddTag(ptr, buf_end, "/L=", 3, strLen))) - goto err; + if (!(ptr = AddTag(ptr, buf_end, "/L=", 3, strLen))) + return; break; case STATE_NAME: - if (!(ptr= AddTag(ptr, buf_end, "/ST=", 4, strLen))) - goto err; + if (!(ptr = AddTag(ptr, buf_end, "/ST=", 4, strLen))) + return; break; case ORG_NAME: - if (!(ptr= AddTag(ptr, buf_end, "/O=", 3, strLen))) - goto err; + if (!(ptr = AddTag(ptr, buf_end, "/O=", 3, strLen))) + return; break; case ORGUNIT_NAME: - if (!(ptr= AddTag(ptr, buf_end, "/OU=", 4, strLen))) - goto err; + if (!(ptr = AddTag(ptr, buf_end, "/OU=", 4, strLen))) + return; break; } sha.Update(source_.get_current(), strLen); source_.advance(strLen); } - else { + else { bool email = false; if (joint[0] == 0x2a && joint[1] == 0x86) // email id hdr email = true; source_.advance(oidSz + 1); word32 length = GetLength(source_); + if (source_.IsLeft(length) == false) return; - if (email && !(ptr= AddTag(ptr, buf_end, "/emailAddress=", 14, length))) - goto err; + if (email) { + if (!(ptr = AddTag(ptr, buf_end, "/emailAddress=", 14, length))) { + source_.SetError(CONTENT_E); + return; + } + } source_.advance(length); } } - *ptr= 0; - sha.Final(nt == ISSUER ? issuerHash_ : subjectHash_); - - return; - -err: - source_.SetError(CONTENT_E); + *ptr = 0; + + if (nt == ISSUER) + sha.Final(issuerHash_); + else + sha.Final(subjectHash_); } @@ -785,6 +857,8 @@ void CertDecoder::GetDate(DateType dt) } word32 length = GetLength(source_); + if (source_.IsLeft(length) == false) return; + byte date[MAX_DATE_SZ]; if (length > MAX_DATE_SZ || length < MIN_DATE_SZ) { source_.SetError(DATE_SZ_E); @@ -794,8 +868,7 @@ void CertDecoder::GetDate(DateType dt) memcpy(date, source_.get_current(), length); source_.advance(length); - if (!ValidateDate(date, b, dt) && verify_) - { + if (!ValidateDate(date, b, dt) && verify_) { if (dt == BEFORE) source_.SetError(BEFORE_DATE_E); else @@ -856,7 +929,8 @@ void CertDecoder::GetCompareHash(const byte* plain, word32 sz, byte* digest, // validate signature signed by someone else bool CertDecoder::ValidateSignature(SignerList* signers) { - assert(signers); + if (!signers) + return false; SignerList::iterator first = signers->begin(); SignerList::iterator last = signers->end(); @@ -1077,8 +1151,7 @@ word32 DecodeDSA_Signature(byte* decoded, const byte* encoded, word32 sz) return 0; } word32 rLen = GetLength(source); - if (rLen != 20) - { + if (rLen != 20) { if (rLen == 21) { // zero at front, eat source.next(); --rLen; @@ -1101,8 +1174,7 @@ word32 DecodeDSA_Signature(byte* decoded, const byte* encoded, word32 sz) return 0; } word32 sLen = GetLength(source); - if (sLen != 20) - { + if (sLen != 20) { if (sLen == 21) { source.next(); // zero at front, eat --sLen; @@ -1123,6 +1195,7 @@ word32 DecodeDSA_Signature(byte* decoded, const byte* encoded, word32 sz) } +/* // Get Cert in PEM format from BEGIN to END int GetCert(Source& source) { @@ -1174,12 +1247,10 @@ void PKCS12_Decoder::Decode() // Get MacData optional - /* - mac digestInfo like certdecoder::getdigest? - macsalt octet string - iter integer + // mac digestInfo like certdecoder::getdigest? + // macsalt octet string + // iter integer - */ } @@ -1199,6 +1270,7 @@ int GetPKCS_Cert(const char* password, Source& source) return 0; } +*/ diff --git a/extra/yassl/taocrypt/src/blowfish.cpp b/extra/yassl/taocrypt/src/blowfish.cpp index 2e68f7ffb5c..e1c7c852d19 100644 --- a/extra/yassl/taocrypt/src/blowfish.cpp +++ b/extra/yassl/taocrypt/src/blowfish.cpp @@ -87,7 +87,10 @@ void Blowfish::Process(byte* out, const byte* in, word32 sz) void Blowfish::SetKey(const byte* key_string, word32 keylength, CipherDir dir) { - assert(keylength >= 4 && keylength <= 56); + if (keylength < 4) + keylength = 4; + else if (keylength > 56) + keylength = 56; unsigned i, j=0, k; word32 data, dspace[2] = {0, 0}; @@ -166,16 +169,21 @@ void Blowfish::crypt_block(const word32 in[2], word32 out[2]) const word32 left = in[0]; word32 right = in[1]; + const word32 *const s = sbox_; const word32* p = pbox_; - word32 tmp; left ^= p[0]; - BF_ROUNDS + // roll back up and use s and p index instead of just p + for (unsigned i = 0; i < ROUNDS / 2; i++) { + right ^= (((s[GETBYTE(left,3)] + s[256+GETBYTE(left,2)]) + ^ s[2*256+GETBYTE(left,1)]) + s[3*256+GETBYTE(left,0)]) + ^ p[2*i+1]; -#if ROUNDS == 20 - BF_EXTRA_ROUNDS -#endif + left ^= (((s[GETBYTE(right,3)] + s[256+GETBYTE(right,2)]) + ^ s[2*256+GETBYTE(right,1)]) + s[3*256+GETBYTE(right,0)]) + ^ p[2*i+2]; + } right ^= p[ROUNDS + 1]; @@ -189,17 +197,23 @@ typedef BlockGetAndPut<word32, BigEndian> gpBlock; void Blowfish::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const { - word32 tmp, left, right; + word32 left, right; + const word32 *const s = sbox_; const word32* p = pbox_; gpBlock::Get(in)(left)(right); left ^= p[0]; - BF_ROUNDS + // roll back up and use s and p index instead of just p + for (unsigned i = 0; i < ROUNDS / 2; i++) { + right ^= (((s[GETBYTE(left,3)] + s[256+GETBYTE(left,2)]) + ^ s[2*256+GETBYTE(left,1)]) + s[3*256+GETBYTE(left,0)]) + ^ p[2*i+1]; -#if ROUNDS == 20 - BF_EXTRA_ROUNDS -#endif + left ^= (((s[GETBYTE(right,3)] + s[256+GETBYTE(right,2)]) + ^ s[2*256+GETBYTE(right,1)]) + s[3*256+GETBYTE(right,0)]) + ^ p[2*i+2]; + } right ^= p[ROUNDS + 1]; diff --git a/extra/yassl/taocrypt/src/coding.cpp b/extra/yassl/taocrypt/src/coding.cpp index 75c8f44f636..97c62ea12a7 100644 --- a/extra/yassl/taocrypt/src/coding.cpp +++ b/extra/yassl/taocrypt/src/coding.cpp @@ -95,7 +95,6 @@ void HexEncoder::Encode() void HexDecoder::Decode() { word32 bytes = coded_.size(); - assert((bytes % 2) == 0); decoded_.New(bytes / 2); word32 i(0); @@ -104,15 +103,9 @@ void HexDecoder::Decode() byte b = coded_.next() - 0x30; // 0 starts at 0x30 byte b2 = coded_.next() - 0x30; - // sanity checks - assert( b < sizeof(hexDecode)/sizeof(hexDecode[0]) ); - assert( b2 < sizeof(hexDecode)/sizeof(hexDecode[0]) ); - b = hexDecode[b]; b2 = hexDecode[b2]; - - assert( b != bad && b2 != bad ); - + decoded_[i++] = (b << 4) | b2; bytes -= 2; } @@ -174,9 +167,9 @@ void Base64Encoder::Encode() } encoded_[i++] = '\n'; - assert(i == outSz); - - plain_.reset(encoded_); + + if (i == outSz) + plain_.reset(encoded_); } @@ -197,7 +190,6 @@ void Base64Decoder::Decode() byte e3 = coded_.next(); byte e4 = coded_.next(); - // do asserts first if (e1 == 0) // end file 0's break; diff --git a/extra/yassl/taocrypt/src/dsa.cpp b/extra/yassl/taocrypt/src/dsa.cpp index 79ee91e76f9..a4e9c9503e7 100644 --- a/extra/yassl/taocrypt/src/dsa.cpp +++ b/extra/yassl/taocrypt/src/dsa.cpp @@ -183,7 +183,8 @@ word32 DSA_Signer::Sign(const byte* sha_digest, byte* sig, Integer kInv = k.InverseMod(q); s_ = (kInv * (H + x*r_)) % q; - assert(!!r_ && !!s_); + if (!(!!r_ && !!s_)) + return -1; int rSz = r_.ByteCount(); diff --git a/extra/yassl/taocrypt/src/hash.cpp b/extra/yassl/taocrypt/src/hash.cpp index c51dc42a909..b36a486368c 100644 --- a/extra/yassl/taocrypt/src/hash.cpp +++ b/extra/yassl/taocrypt/src/hash.cpp @@ -21,7 +21,6 @@ #include "runtime.hpp" #include <string.h> -#include <assert.h> #include "hash.hpp" @@ -31,8 +30,6 @@ namespace TaoCrypt { HASHwithTransform::HASHwithTransform(word32 digSz, word32 buffSz) { - assert(digSz <= MaxDigestSz); - assert(buffSz <= MaxBufferSz); } @@ -73,15 +70,15 @@ void HASHwithTransform::Update(const byte* data, word32 len) // Final process, place digest in hash void HASHwithTransform::Final(byte* hash) { - word32 blockSz = getBlockSize(); - word32 digestSz = getDigestSize(); - word32 padSz = getPadSize(); - ByteOrder order = getByteOrder(); + word32 blockSz = getBlockSize(); + word32 digestSz = getDigestSize(); + word32 padSz = getPadSize(); + ByteOrder order = getByteOrder(); AddLength(buffLen_); // before adding pads HashLengthType preLoLen = GetBitCountLo(); HashLengthType preHiLen = GetBitCountHi(); - byte* local = reinterpret_cast<byte*>(buffer_); + byte* local = reinterpret_cast<byte*>(buffer_); local[buffLen_++] = 0x80; // add 1 @@ -95,7 +92,7 @@ void HASHwithTransform::Final(byte* hash) buffLen_ = 0; } memset(&local[buffLen_], 0, padSz - buffLen_); - + ByteReverseIf(local, local, blockSz, order); memcpy(&local[padSz], order ? &preHiLen : &preLoLen, sizeof(preLoLen)); @@ -113,8 +110,6 @@ void HASHwithTransform::Final(byte* hash) HASH64withTransform::HASH64withTransform(word32 digSz, word32 buffSz) { - assert(digSz <= MaxDigestSz); - assert(buffSz <= MaxBufferSz); } diff --git a/extra/yassl/taocrypt/src/hc128.cpp b/extra/yassl/taocrypt/src/hc128.cpp new file mode 100644 index 00000000000..aac92f0abb4 --- /dev/null +++ b/extra/yassl/taocrypt/src/hc128.cpp @@ -0,0 +1,317 @@ +/* + Copyright (c) 2005, 2010, 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; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +#include "runtime.hpp" +#include "hc128.hpp" + + + +namespace TaoCrypt { + + + + +#ifdef BIG_ENDIAN_ORDER + #define LITTLE32(x) ByteReverse((word32)x) +#else + #define LITTLE32(x) (x) +#endif + + +/*h1 function*/ +#define h1(x, y) { \ + byte a,c; \ + a = (byte) (x); \ + c = (byte) ((x) >> 16); \ + y = (T_[512+a])+(T_[512+256+c]); \ +} + +/*h2 function*/ +#define h2(x, y) { \ + byte a,c; \ + a = (byte) (x); \ + c = (byte) ((x) >> 16); \ + y = (T_[a])+(T_[256+c]); \ +} + +/*one step of HC-128, update P and generate 32 bits keystream*/ +#define step_P(u,v,a,b,c,d,n){ \ + word32 tem0,tem1,tem2,tem3; \ + h1((X_[(d)]),tem3); \ + tem0 = rotrFixed((T_[(v)]),23); \ + tem1 = rotrFixed((X_[(c)]),10); \ + tem2 = rotrFixed((X_[(b)]),8); \ + (T_[(u)]) += tem2+(tem0 ^ tem1); \ + (X_[(a)]) = (T_[(u)]); \ + (n) = tem3 ^ (T_[(u)]) ; \ +} + +/*one step of HC-128, update Q and generate 32 bits keystream*/ +#define step_Q(u,v,a,b,c,d,n){ \ + word32 tem0,tem1,tem2,tem3; \ + h2((Y_[(d)]),tem3); \ + tem0 = rotrFixed((T_[(v)]),(32-23)); \ + tem1 = rotrFixed((Y_[(c)]),(32-10)); \ + tem2 = rotrFixed((Y_[(b)]),(32-8)); \ + (T_[(u)]) += tem2 + (tem0 ^ tem1); \ + (Y_[(a)]) = (T_[(u)]); \ + (n) = tem3 ^ (T_[(u)]) ; \ +} + + +/*16 steps of HC-128, generate 512 bits keystream*/ +void HC128::GenerateKeystream(word32* keystream) +{ + word32 cc,dd; + cc = counter1024_ & 0x1ff; + dd = (cc+16)&0x1ff; + + if (counter1024_ < 512) + { + counter1024_ = (counter1024_ + 16) & 0x3ff; + step_P(cc+0, cc+1, 0, 6, 13,4, keystream[0]); + step_P(cc+1, cc+2, 1, 7, 14,5, keystream[1]); + step_P(cc+2, cc+3, 2, 8, 15,6, keystream[2]); + step_P(cc+3, cc+4, 3, 9, 0, 7, keystream[3]); + step_P(cc+4, cc+5, 4, 10,1, 8, keystream[4]); + step_P(cc+5, cc+6, 5, 11,2, 9, keystream[5]); + step_P(cc+6, cc+7, 6, 12,3, 10,keystream[6]); + step_P(cc+7, cc+8, 7, 13,4, 11,keystream[7]); + step_P(cc+8, cc+9, 8, 14,5, 12,keystream[8]); + step_P(cc+9, cc+10,9, 15,6, 13,keystream[9]); + step_P(cc+10,cc+11,10,0, 7, 14,keystream[10]); + step_P(cc+11,cc+12,11,1, 8, 15,keystream[11]); + step_P(cc+12,cc+13,12,2, 9, 0, keystream[12]); + step_P(cc+13,cc+14,13,3, 10,1, keystream[13]); + step_P(cc+14,cc+15,14,4, 11,2, keystream[14]); + step_P(cc+15,dd+0, 15,5, 12,3, keystream[15]); + } + else + { + counter1024_ = (counter1024_ + 16) & 0x3ff; + step_Q(512+cc+0, 512+cc+1, 0, 6, 13,4, keystream[0]); + step_Q(512+cc+1, 512+cc+2, 1, 7, 14,5, keystream[1]); + step_Q(512+cc+2, 512+cc+3, 2, 8, 15,6, keystream[2]); + step_Q(512+cc+3, 512+cc+4, 3, 9, 0, 7, keystream[3]); + step_Q(512+cc+4, 512+cc+5, 4, 10,1, 8, keystream[4]); + step_Q(512+cc+5, 512+cc+6, 5, 11,2, 9, keystream[5]); + step_Q(512+cc+6, 512+cc+7, 6, 12,3, 10,keystream[6]); + step_Q(512+cc+7, 512+cc+8, 7, 13,4, 11,keystream[7]); + step_Q(512+cc+8, 512+cc+9, 8, 14,5, 12,keystream[8]); + step_Q(512+cc+9, 512+cc+10,9, 15,6, 13,keystream[9]); + step_Q(512+cc+10,512+cc+11,10,0, 7, 14,keystream[10]); + step_Q(512+cc+11,512+cc+12,11,1, 8, 15,keystream[11]); + step_Q(512+cc+12,512+cc+13,12,2, 9, 0, keystream[12]); + step_Q(512+cc+13,512+cc+14,13,3, 10,1, keystream[13]); + step_Q(512+cc+14,512+cc+15,14,4, 11,2, keystream[14]); + step_Q(512+cc+15,512+dd+0, 15,5, 12,3, keystream[15]); + } +} + + +/* The following defines the initialization functions */ +#define f1(x) (rotrFixed((x),7) ^ rotrFixed((x),18) ^ ((x) >> 3)) +#define f2(x) (rotrFixed((x),17) ^ rotrFixed((x),19) ^ ((x) >> 10)) + +/*update table P*/ +#define update_P(u,v,a,b,c,d){ \ + word32 tem0,tem1,tem2,tem3; \ + tem0 = rotrFixed((T_[(v)]),23); \ + tem1 = rotrFixed((X_[(c)]),10); \ + tem2 = rotrFixed((X_[(b)]),8); \ + h1((X_[(d)]),tem3); \ + (T_[(u)]) = ((T_[(u)]) + tem2+(tem0^tem1)) ^ tem3; \ + (X_[(a)]) = (T_[(u)]); \ +} + +/*update table Q*/ +#define update_Q(u,v,a,b,c,d){ \ + word32 tem0,tem1,tem2,tem3; \ + tem0 = rotrFixed((T_[(v)]),(32-23)); \ + tem1 = rotrFixed((Y_[(c)]),(32-10)); \ + tem2 = rotrFixed((Y_[(b)]),(32-8)); \ + h2((Y_[(d)]),tem3); \ + (T_[(u)]) = ((T_[(u)]) + tem2+(tem0^tem1)) ^ tem3; \ + (Y_[(a)]) = (T_[(u)]); \ +} + +/*16 steps of HC-128, without generating keystream, */ +/*but use the outputs to update P and Q*/ +void HC128::SetupUpdate() /*each time 16 steps*/ +{ + word32 cc,dd; + cc = counter1024_ & 0x1ff; + dd = (cc+16)&0x1ff; + + if (counter1024_ < 512) + { + counter1024_ = (counter1024_ + 16) & 0x3ff; + update_P(cc+0, cc+1, 0, 6, 13, 4); + update_P(cc+1, cc+2, 1, 7, 14, 5); + update_P(cc+2, cc+3, 2, 8, 15, 6); + update_P(cc+3, cc+4, 3, 9, 0, 7); + update_P(cc+4, cc+5, 4, 10,1, 8); + update_P(cc+5, cc+6, 5, 11,2, 9); + update_P(cc+6, cc+7, 6, 12,3, 10); + update_P(cc+7, cc+8, 7, 13,4, 11); + update_P(cc+8, cc+9, 8, 14,5, 12); + update_P(cc+9, cc+10,9, 15,6, 13); + update_P(cc+10,cc+11,10,0, 7, 14); + update_P(cc+11,cc+12,11,1, 8, 15); + update_P(cc+12,cc+13,12,2, 9, 0); + update_P(cc+13,cc+14,13,3, 10, 1); + update_P(cc+14,cc+15,14,4, 11, 2); + update_P(cc+15,dd+0, 15,5, 12, 3); + } + else + { + counter1024_ = (counter1024_ + 16) & 0x3ff; + update_Q(512+cc+0, 512+cc+1, 0, 6, 13, 4); + update_Q(512+cc+1, 512+cc+2, 1, 7, 14, 5); + update_Q(512+cc+2, 512+cc+3, 2, 8, 15, 6); + update_Q(512+cc+3, 512+cc+4, 3, 9, 0, 7); + update_Q(512+cc+4, 512+cc+5, 4, 10,1, 8); + update_Q(512+cc+5, 512+cc+6, 5, 11,2, 9); + update_Q(512+cc+6, 512+cc+7, 6, 12,3, 10); + update_Q(512+cc+7, 512+cc+8, 7, 13,4, 11); + update_Q(512+cc+8, 512+cc+9, 8, 14,5, 12); + update_Q(512+cc+9, 512+cc+10,9, 15,6, 13); + update_Q(512+cc+10,512+cc+11,10,0, 7, 14); + update_Q(512+cc+11,512+cc+12,11,1, 8, 15); + update_Q(512+cc+12,512+cc+13,12,2, 9, 0); + update_Q(512+cc+13,512+cc+14,13,3, 10, 1); + update_Q(512+cc+14,512+cc+15,14,4, 11, 2); + update_Q(512+cc+15,512+dd+0, 15,5, 12, 3); + } +} + + +/* for the 128-bit key: key[0]...key[15] +* key[0] is the least significant byte of ctx->key[0] (K_0); +* key[3] is the most significant byte of ctx->key[0] (K_0); +* ... +* key[12] is the least significant byte of ctx->key[3] (K_3) +* key[15] is the most significant byte of ctx->key[3] (K_3) +* +* for the 128-bit iv: iv[0]...iv[15] +* iv[0] is the least significant byte of ctx->iv[0] (IV_0); +* iv[3] is the most significant byte of ctx->iv[0] (IV_0); +* ... +* iv[12] is the least significant byte of ctx->iv[3] (IV_3) +* iv[15] is the most significant byte of ctx->iv[3] (IV_3) +*/ + + + +void HC128::SetIV(const byte* iv) +{ + word32 i; + + for (i = 0; i < (128 >> 5); i++) + iv_[i] = LITTLE32(((word32*)iv)[i]); + + for (; i < 8; i++) iv_[i] = iv_[i-4]; + + /* expand the key and IV into the table T */ + /* (expand the key and IV into the table P and Q) */ + + for (i = 0; i < 8; i++) T_[i] = key_[i]; + for (i = 8; i < 16; i++) T_[i] = iv_[i-8]; + + for (i = 16; i < (256+16); i++) + T_[i] = f2(T_[i-2]) + T_[i-7] + f1(T_[i-15]) + T_[i-16]+i; + + for (i = 0; i < 16; i++) T_[i] = T_[256+i]; + + for (i = 16; i < 1024; i++) + T_[i] = f2(T_[i-2]) + T_[i-7] + f1(T_[i-15]) + T_[i-16]+256+i; + + /* initialize counter1024, X and Y */ + counter1024_ = 0; + for (i = 0; i < 16; i++) X_[i] = T_[512-16+i]; + for (i = 0; i < 16; i++) Y_[i] = T_[512+512-16+i]; + + /* run the cipher 1024 steps before generating the output */ + for (i = 0; i < 64; i++) SetupUpdate(); +} + + +void HC128::SetKey(const byte* key, const byte* iv) +{ + word32 i; + + /* Key size in bits 128 */ + for (i = 0; i < (128 >> 5); i++) + key_[i] = LITTLE32(((word32*)key)[i]); + + for ( ; i < 8 ; i++) key_[i] = key_[i-4]; + + SetIV(iv); +} + + +/* The following defines the encryption of data stream */ +void HC128::Process(byte* output, const byte* input, word32 msglen) +{ + word32 i, keystream[16]; + + for ( ; msglen >= 64; msglen -= 64, input += 64, output += 64) + { + GenerateKeystream(keystream); + + /* unroll loop */ + ((word32*)output)[0] = ((word32*)input)[0] ^ LITTLE32(keystream[0]); + ((word32*)output)[1] = ((word32*)input)[1] ^ LITTLE32(keystream[1]); + ((word32*)output)[2] = ((word32*)input)[2] ^ LITTLE32(keystream[2]); + ((word32*)output)[3] = ((word32*)input)[3] ^ LITTLE32(keystream[3]); + ((word32*)output)[4] = ((word32*)input)[4] ^ LITTLE32(keystream[4]); + ((word32*)output)[5] = ((word32*)input)[5] ^ LITTLE32(keystream[5]); + ((word32*)output)[6] = ((word32*)input)[6] ^ LITTLE32(keystream[6]); + ((word32*)output)[7] = ((word32*)input)[7] ^ LITTLE32(keystream[7]); + ((word32*)output)[8] = ((word32*)input)[8] ^ LITTLE32(keystream[8]); + ((word32*)output)[9] = ((word32*)input)[9] ^ LITTLE32(keystream[9]); + ((word32*)output)[10] = ((word32*)input)[10] ^ LITTLE32(keystream[10]); + ((word32*)output)[11] = ((word32*)input)[11] ^ LITTLE32(keystream[11]); + ((word32*)output)[12] = ((word32*)input)[12] ^ LITTLE32(keystream[12]); + ((word32*)output)[13] = ((word32*)input)[13] ^ LITTLE32(keystream[13]); + ((word32*)output)[14] = ((word32*)input)[14] ^ LITTLE32(keystream[14]); + ((word32*)output)[15] = ((word32*)input)[15] ^ LITTLE32(keystream[15]); + } + + if (msglen > 0) + { + GenerateKeystream(keystream); + +#ifdef BIG_ENDIAN_ORDER + { + word32 wordsLeft = msglen / sizeof(word32); + if (msglen % sizeof(word32)) wordsLeft++; + + ByteReverse(keystream, keystream, wordsLeft * sizeof(word32)); + } +#endif + + for (i = 0; i < msglen; i++) + output[i] = input[i] ^ ((byte*)keystream)[i]; + } + +} + + +} // namespace diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index 04c4cefff98..15deb59d4f3 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2010, Oracle and/or its affiliates + Copyright (c) 2005, 2012, 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 @@ -73,7 +73,8 @@ template <class T> CPP_TYPENAME AlignedAllocator<T>::pointer AlignedAllocator<T>::allocate( size_type n, const void *) { - CheckSize(n); + if (n > max_size()) + return 0; if (n == 0) return 0; if (n >= 4) @@ -91,16 +92,13 @@ CPP_TYPENAME AlignedAllocator<T>::pointer AlignedAllocator<T>::allocate( #endif #ifdef TAOCRYPT_NO_ALIGNED_ALLOC - assert(m_pBlock == 0); m_pBlock = p; if (!IsAlignedOn(p, 16)) { - assert(IsAlignedOn(p, 8)); p = (byte *)p + 8; } #endif - assert(IsAlignedOn(p, 16)); return (T*)p; } return NEW_TC T[n]; @@ -116,7 +114,6 @@ void AlignedAllocator<T>::deallocate(void* p, size_type n) #ifdef TAOCRYPT_MM_MALLOC_AVAILABLE _mm_free(p); #elif defined(TAOCRYPT_NO_ALIGNED_ALLOC) - assert(m_pBlock == p || (byte*)m_pBlock+8 == p); free(m_pBlock); m_pBlock = 0; #else @@ -284,14 +281,14 @@ DWord() {} private: struct dword_struct - { - #ifdef LITTLE_ENDIAN_ORDER - word low; - word high; - #else - word high; - word low; - #endif + { + #ifdef LITTLE_ENDIAN_ORDER + word low; + word high; + #else + word high; + word low; + #endif }; union @@ -365,9 +362,6 @@ private: template <class S, class D> S DivideThreeWordsByTwo(S* A, S B0, S B1, D* dummy_VC6_WorkAround = 0) { - // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a S - assert(A[2] < B1 || (A[2]==B1 && A[1] < B0)); - // estimate the quotient: do a 2 S by 1 S divide S Q; if (S(B1+1) == 0) @@ -393,7 +387,6 @@ S DivideThreeWordsByTwo(S* A, S B0, S B1, D* dummy_VC6_WorkAround = 0) A[1] = u.GetLowHalf(); A[2] += u.GetHighHalf(); Q++; - assert(Q); // shouldn't overflow } return Q; @@ -491,7 +484,6 @@ static int Compare(const word *A, const word *B, unsigned int N) static word Increment(word *A, unsigned int N, word B=1) { - assert(N); word t = A[0]; A[0] = t+B; if (A[0] >= t) @@ -504,7 +496,6 @@ static word Increment(word *A, unsigned int N, word B=1) static word Decrement(word *A, unsigned int N, word B=1) { - assert(N); word t = A[0]; A[0] = t-B; if (A[0] <= t) @@ -538,14 +529,11 @@ static word LinearMultiply(word *C, const word *A, word B, unsigned int N) static word AtomicInverseModPower2(word A) { - assert(A%2==1); - word R=A%8; for (unsigned i=3; i<WORD_BITS; i*=2) R = R*(2-R*A); - assert(word(R*A)==1); return R; } @@ -576,14 +564,11 @@ public: static void TAOCRYPT_CDECL Square2(word *R, const word *A); static void TAOCRYPT_CDECL Square4(word *R, const word *A); - static void TAOCRYPT_CDECL Square8(word *R, const word *A) {assert(false);} static unsigned int TAOCRYPT_CDECL SquareRecursionLimit() {return 4;} }; word Portable::Add(word *C, const word *A, const word *B, unsigned int N) { - assert (N%2 == 0); - DWord u(0, 0); for (unsigned int i = 0; i < N; i+=2) { @@ -597,8 +582,6 @@ word Portable::Add(word *C, const word *A, const word *B, unsigned int N) word Portable::Subtract(word *C, const word *A, const word *B, unsigned int N) { - assert (N%2 == 0); - DWord u(0, 0); for (unsigned int i = 0; i < N; i+=2) { @@ -1013,7 +996,7 @@ void Portable::Multiply8Bottom(word *R, const word *A, const word *B) static jmp_buf s_env; static void SigIllHandler(int) { - longjmp(s_env, 1); + longjmp(s_env, 1); } #endif @@ -2130,8 +2113,6 @@ void P4Optimized::Multiply8Bottom(word *C, const word *A, const word *B) void RecursiveMultiply(word *R, word *T, const word *A, const word *B, unsigned int N) { - assert(N>=2 && N%2==0); - if (LowLevel::MultiplyRecursionLimit() >= 8 && N==8) LowLevel::Multiply8(R, A, B); else if (LowLevel::MultiplyRecursionLimit() >= 4 && N==4) @@ -2188,7 +2169,6 @@ void RecursiveMultiply(word *R, word *T, const word *A, const word *B, carry += LowLevel::Add(T0, T0, R2, N); carry += LowLevel::Add(R1, R1, T0, N); - assert (carry >= 0 && carry <= 2); Increment(R3, N2, carry); } } @@ -2196,9 +2176,6 @@ void RecursiveMultiply(word *R, word *T, const word *A, const word *B, void RecursiveSquare(word *R, word *T, const word *A, unsigned int N) { - assert(N && N%2==0); - if (LowLevel::SquareRecursionLimit() >= 8 && N==8) - LowLevel::Square8(R, A); if (LowLevel::SquareRecursionLimit() >= 4 && N==4) LowLevel::Square4(R, A); else if (N==2) @@ -2227,7 +2204,6 @@ void RecursiveSquare(word *R, word *T, const word *A, unsigned int N) void RecursiveMultiplyBottom(word *R, word *T, const word *A, const word *B, unsigned int N) { - assert(N>=2 && N%2==0); if (LowLevel::MultiplyBottomRecursionLimit() >= 8 && N==8) LowLevel::Multiply8Bottom(R, A, B); else if (LowLevel::MultiplyBottomRecursionLimit() >= 4 && N==4) @@ -2250,8 +2226,6 @@ void RecursiveMultiplyBottom(word *R, word *T, const word *A, const word *B, void RecursiveMultiplyTop(word *R, word *T, const word *L, const word *A, const word *B, unsigned int N) { - assert(N>=2 && N%2==0); - if (N==4) { LowLevel::Multiply4(T, A, B); @@ -2315,7 +2289,6 @@ void RecursiveMultiplyTop(word *R, word *T, const word *L, const word *A, carry += Increment(R0, N2, c2+t); carry += LowLevel::Add(R0, R0, T1, N2); carry += LowLevel::Add(R0, R0, T3, N2); - assert (carry >= 0 && carry <= 2); CopyWords(R1, T3, N2); Increment(R1, N2, carry); @@ -2364,9 +2337,6 @@ void AsymmetricMultiply(word *R, word *T, const word *A, unsigned int NA, STL::swap(NA, NB); } - assert(NB % NA == 0); - assert((NB/NA)%2 == 0); // NB is an even multiple of NA - if (NA==2 && !A[1]) { switch (A[0]) @@ -2433,8 +2403,6 @@ static inline unsigned int EvenWordCount(const word *X, unsigned int N) unsigned int AlmostInverse(word *R, word *T, const word *A, unsigned int NA, const word *M, unsigned int N) { - assert(NA<=N && N && N%2==0); - word *b = T; word *c = T+N; word *f = T+2*N; @@ -2460,7 +2428,6 @@ unsigned int AlmostInverse(word *R, word *T, const word *A, unsigned int NA, ShiftWordsRightByWords(f, fgLen, 1); if (c[bcLen-1]) bcLen+=2; - assert(bcLen <= N); ShiftWordsLeftByWords(c, bcLen, 1); k+=WORD_BITS; t=f[0]; @@ -2489,7 +2456,6 @@ unsigned int AlmostInverse(word *R, word *T, const word *A, unsigned int NA, { c[bcLen] = t; bcLen+=2; - assert(bcLen <= N); } if (f[fgLen-2]==0 && g[fgLen-2]==0 && f[fgLen-1]==0 && g[fgLen-1]==0) @@ -2508,7 +2474,6 @@ unsigned int AlmostInverse(word *R, word *T, const word *A, unsigned int NA, { b[bcLen] = 1; bcLen+=2; - assert(bcLen <= N); } } } @@ -2622,11 +2587,14 @@ void Integer::Decode(Source& source) } word32 length = GetLength(source); + if (length == 0 || source.GetError().What()) return; if ( (b = source.next()) == 0x00) length--; else source.prev(); + + if (source.IsLeft(length) == false) return; unsigned int words = (length + WORD_SIZE - 1) / WORD_SIZE; words = RoundupSize(words); @@ -2741,8 +2709,6 @@ void Integer::Randomize(RandomNumberGenerator& rng, unsigned int nbits) void Integer::Randomize(RandomNumberGenerator& rng, const Integer& min, const Integer& max) { - assert(min <= max); - Integer range = max - min; const unsigned int nbits = range.BitCount(); @@ -2881,7 +2847,7 @@ Integer& Integer::operator++() else { word borrow = Decrement(reg_.get_buffer(), reg_.size()); - assert(!borrow); + (void)borrow; // shut up compiler if (WordCount()==0) *this = Zero(); } @@ -2998,7 +2964,6 @@ void PositiveSubtract(Integer &diff, const Integer &a, const Integer& b) b.reg_.get_buffer(), bSize); CopyWords(diff.reg_+bSize, a.reg_+bSize, aSize-bSize); borrow = Decrement(diff.reg_+bSize, aSize-bSize, borrow); - assert(!borrow); diff.sign_ = Integer::POSITIVE; } else @@ -3007,7 +2972,6 @@ void PositiveSubtract(Integer &diff, const Integer &a, const Integer& b) a.reg_.get_buffer(), aSize); CopyWords(diff.reg_+aSize, b.reg_+aSize, bSize-aSize); borrow = Decrement(diff.reg_+aSize, bSize-aSize, borrow); - assert(!borrow); diff.sign_ = Integer::NEGATIVE; } } @@ -3067,7 +3031,6 @@ bool Integer::GetBit(unsigned int n) const unsigned long Integer::GetBits(unsigned int i, unsigned int n) const { - assert(n <= sizeof(unsigned long)*8); unsigned long v = 0; for (unsigned int j=0; j<n; j++) v |= GetBit(i+j) << j; @@ -3127,8 +3090,6 @@ bool Integer::IsConvertableToLong() const signed long Integer::ConvertToLong() const { - assert(IsConvertableToLong()); - unsigned long value = reg_[0]; value += SafeLeftShift<WORD_BITS, unsigned long>(reg_[1]); return sign_ == POSITIVE ? value : -(signed long)value; @@ -3227,11 +3188,9 @@ static inline void AtomicDivide(word *Q, const word *A, const word *B) { // multiply quotient and divisor and add remainder, make sure it // equals dividend - assert(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0]<B[0]))); word P[4]; Portable::Multiply2(P, Q, B); Add(P, P, T, 4); - assert(memcmp(P, A, 4*WORD_SIZE)==0); } #endif } @@ -3241,8 +3200,6 @@ static inline void AtomicDivide(word *Q, const word *A, const word *B) static void CorrectQuotientEstimate(word *R, word *T, word *Q, const word *B, unsigned int N) { - assert(N && N%2==0); - if (Q[1]) { T[N] = T[N+1] = 0; @@ -3260,13 +3217,12 @@ static void CorrectQuotientEstimate(word *R, word *T, word *Q, const word *B, } word borrow = Subtract(R, R, T, N+2); - assert(!borrow && !R[N+1]); + (void)borrow; // shut up compiler while (R[N] || Compare(R, B, N) >= 0) { R[N] -= Subtract(R, R, B, N); Q[1] += (++Q[0]==0); - assert(Q[0] || Q[1]); // no overflow } } @@ -3280,10 +3236,6 @@ static void CorrectQuotientEstimate(word *R, word *T, word *Q, const word *B, void Divide(word* R, word* Q, word* T, const word* A, unsigned int NA, const word* B, unsigned int NB) { - assert(NA && NB && NA%2==0 && NB%2==0); - assert(B[NB-1] || B[NB-2]); - assert(NB <= NA); - // set up temporary work space word *const TA=T; word *const TB=T+NA+2; @@ -3294,7 +3246,6 @@ void Divide(word* R, word* Q, word* T, const word* A, unsigned int NA, TB[0] = TB[NB-1] = 0; CopyWords(TB+shiftWords, B, NB-shiftWords); unsigned shiftBits = WORD_BITS - BitPrecision(TB[NB-1]); - assert(shiftBits < WORD_BITS); ShiftWordsLeftByBits(TB, NB, shiftBits); // copy A into TA and normalize it @@ -3314,7 +3265,6 @@ void Divide(word* R, word* Q, word* T, const word* A, unsigned int NA, else { NA+=2; - assert(Compare(TA+NA-NB, TB, NB) < 0); } word BT[2]; @@ -3340,8 +3290,6 @@ void PositiveDivide(Integer& remainder, Integer& quotient, unsigned aSize = a.WordCount(); unsigned bSize = b.WordCount(); - assert(bSize); - if (a.PositiveCompare(b) == -1) { remainder = a; @@ -3429,8 +3377,6 @@ Integer Integer::Modulo(const Integer &b) const void Integer::Divide(word &remainder, Integer "ient, const Integer ÷nd, word divisor) { - assert(divisor); - if ((divisor & (divisor-1)) == 0) // divisor is a power of 2 { quotient = dividend >> (BitPrecision(divisor)-1); @@ -3470,8 +3416,6 @@ Integer Integer::DividedBy(word b) const word Integer::Modulo(word divisor) const { - assert(divisor); - word remainder; if ((divisor & (divisor-1)) == 0) // divisor is a power of 2 @@ -3517,7 +3461,6 @@ Integer Integer::SquareRoot() const // overestimate square root Integer x, y = Power2((BitCount()+1)/2); - assert(y*y >= *this); do { @@ -3562,8 +3505,6 @@ Integer Integer::Gcd(const Integer &a, const Integer &b) Integer Integer::InverseMod(const Integer &m) const { - assert(m.NotNegative()); - if (IsNegative() || *this>=m) return (*this%m).InverseMod(m); @@ -3806,7 +3747,7 @@ void MontgomeryReduce(word *R, word *T, const word *X, const word *M, word borrow = Subtract(T, X+N, T, N); // defend against timing attack by doing this Add even when not needed word carry = Add(T+N, T, M, N); - assert(carry || !borrow); + (void)carry; // shut up compiler CopyWords(R, T + (borrow ? N : 0), N); } @@ -3862,7 +3803,6 @@ MontgomeryRepresentation::MontgomeryRepresentation(const Integer &m) u((word)0, modulus.reg_.size()), workspace(5*modulus.reg_.size()) { - assert(modulus.IsOdd()); RecursiveInverseModPower2(u.reg_.get_buffer(), workspace.get_buffer(), modulus.reg_.get_buffer(), modulus.reg_.size()); } @@ -3873,7 +3813,6 @@ const Integer& MontgomeryRepresentation::Multiply(const Integer &a, word *const T = workspace.begin(); word *const R = result.reg_.begin(); const unsigned int N = modulus.reg_.size(); - assert(a.reg_.size()<=N && b.reg_.size()<=N); AsymmetricMultiply(T, T+2*N, a.reg_.get_buffer(), a.reg_.size(), b.reg_.get_buffer(), b.reg_.size()); @@ -3888,7 +3827,6 @@ const Integer& MontgomeryRepresentation::Square(const Integer &a) const word *const T = workspace.begin(); word *const R = result.reg_.begin(); const unsigned int N = modulus.reg_.size(); - assert(a.reg_.size()<=N); TaoCrypt::Square(T, T+2*N, a.reg_.get_buffer(), a.reg_.size()); SetWords(T+2*a.reg_.size(), 0, 2*N-2*a.reg_.size()); @@ -3902,7 +3840,6 @@ Integer MontgomeryRepresentation::ConvertOut(const Integer &a) const word *const T = workspace.begin(); word *const R = result.reg_.begin(); const unsigned int N = modulus.reg_.size(); - assert(a.reg_.size()<=N); CopyWords(T, a.reg_.get_buffer(), a.reg_.size()); SetWords(T+a.reg_.size(), 0, 2*N-a.reg_.size()); @@ -3919,7 +3856,6 @@ const Integer& MontgomeryRepresentation::MultiplicativeInverse( word *const T = workspace.begin(); word *const R = result.reg_.begin(); const unsigned int N = modulus.reg_.size(); - assert(a.reg_.size()<=N); CopyWords(T, a.reg_.get_buffer(), a.reg_.size()); SetWords(T+a.reg_.size(), 0, 2*N-a.reg_.size()); diff --git a/extra/yassl/taocrypt/src/make.bat b/extra/yassl/taocrypt/src/make.bat index ecd3023f5ab..ecd3023f5ab 100644..100755 --- a/extra/yassl/taocrypt/src/make.bat +++ b/extra/yassl/taocrypt/src/make.bat diff --git a/extra/yassl/taocrypt/src/md4.cpp b/extra/yassl/taocrypt/src/md4.cpp index cf17c218809..54820f4c944 100644 --- a/extra/yassl/taocrypt/src/md4.cpp +++ b/extra/yassl/taocrypt/src/md4.cpp @@ -27,7 +27,7 @@ #include "algorithm.hpp" #endif - + namespace STL = STL_NAMESPACE; diff --git a/extra/yassl/taocrypt/src/md5.cpp b/extra/yassl/taocrypt/src/md5.cpp index f18e0290c90..4d0a8bd03be 100644 --- a/extra/yassl/taocrypt/src/md5.cpp +++ b/extra/yassl/taocrypt/src/md5.cpp @@ -30,7 +30,7 @@ namespace STL = STL_NAMESPACE; - + namespace TaoCrypt { @@ -108,14 +108,14 @@ void MD5::Update(const byte* data, word32 len) // at once for asm if (buffLen_ == 0) { - word32 times = len / BLOCK_SIZE; - if (times) { - AsmTransform(data, times); - const word32 add = BLOCK_SIZE * times; - AddLength(add); - len -= add; - data += add; - } + word32 times = len / BLOCK_SIZE; + if (times) { + AsmTransform(data, times); + const word32 add = BLOCK_SIZE * times; + AddLength(add); + len -= add; + data += add; + } } // cache any data left diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp index 07ef25ad773..1a4dd4a52d3 100644 --- a/extra/yassl/taocrypt/src/misc.cpp +++ b/extra/yassl/taocrypt/src/misc.cpp @@ -41,28 +41,28 @@ namespace STL = STL_NAMESPACE; void* operator new(size_t sz, TaoCrypt::new_t) { - void* ptr = malloc(sz ? sz : 1); - if (!ptr) abort(); + void* ptr = malloc(sz ? sz : 1); + if (!ptr) abort(); - return ptr; + return ptr; } void operator delete(void* ptr, TaoCrypt::new_t) { - if (ptr) free(ptr); + if (ptr) free(ptr); } void* operator new[](size_t sz, TaoCrypt::new_t nt) { - return ::operator new(sz, nt); + return ::operator new(sz, nt); } void operator delete[](void* ptr, TaoCrypt::new_t nt) { - ::operator delete(ptr, nt); + ::operator delete(ptr, nt); } @@ -89,7 +89,6 @@ namespace STL = STL_NAMESPACE; // Handler for pure virtual functions namespace __Crun { void pure_error() { - assert(!"Aborted: pure virtual method called."); } } @@ -100,7 +99,6 @@ namespace __Crun { extern "C" { int __cxa_pure_virtual() { - assert(!"Aborted: pure virtual method called."); return 0; } @@ -205,8 +203,8 @@ bool HaveCpuId() return true; #else word32 eax, ebx; - __asm__ __volatile - ( + __asm__ __volatile + ( /* Put EFLAGS in eax and ebx */ "pushf;" "pushf;" @@ -223,9 +221,9 @@ bool HaveCpuId() "pop %0;" "popf" : "=r" (eax), "=r" (ebx) - : + : : "cc" - ); + ); if (eax == ebx) return false; diff --git a/extra/yassl/taocrypt/src/rabbit.cpp b/extra/yassl/taocrypt/src/rabbit.cpp new file mode 100644 index 00000000000..0ea4146618a --- /dev/null +++ b/extra/yassl/taocrypt/src/rabbit.cpp @@ -0,0 +1,250 @@ +/* + Copyright (c) 2005, 2010, 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; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + + +#include "runtime.hpp" +#include "rabbit.hpp" + + + +namespace TaoCrypt { + + +#define U32V(x) (word32)(x) + + +#ifdef BIG_ENDIAN_ORDER + #define LITTLE32(x) ByteReverse((word32)x) +#else + #define LITTLE32(x) (x) +#endif + + +// local +namespace { + + +/* Square a 32-bit unsigned integer to obtain the 64-bit result and return */ +/* the upper 32 bits XOR the lower 32 bits */ +word32 RABBIT_g_func(word32 x) +{ + /* Temporary variables */ + word32 a, b, h, l; + + /* Construct high and low argument for squaring */ + a = x&0xFFFF; + b = x>>16; + + /* Calculate high and low result of squaring */ + h = (((U32V(a*a)>>17) + U32V(a*b))>>15) + b*b; + l = x*x; + + /* Return high XOR low */ + return U32V(h^l); +} + + +} // namespace local + + +/* Calculate the next internal state */ +void Rabbit::NextState(RabbitCtx which) +{ + /* Temporary variables */ + word32 g[8], c_old[8], i; + + Ctx* ctx; + + if (which == Master) + ctx = &masterCtx_; + else + ctx = &workCtx_; + + /* Save old counter values */ + for (i=0; i<8; i++) + c_old[i] = ctx->c[i]; + + /* Calculate new counter values */ + ctx->c[0] = U32V(ctx->c[0] + 0x4D34D34D + ctx->carry); + ctx->c[1] = U32V(ctx->c[1] + 0xD34D34D3 + (ctx->c[0] < c_old[0])); + ctx->c[2] = U32V(ctx->c[2] + 0x34D34D34 + (ctx->c[1] < c_old[1])); + ctx->c[3] = U32V(ctx->c[3] + 0x4D34D34D + (ctx->c[2] < c_old[2])); + ctx->c[4] = U32V(ctx->c[4] + 0xD34D34D3 + (ctx->c[3] < c_old[3])); + ctx->c[5] = U32V(ctx->c[5] + 0x34D34D34 + (ctx->c[4] < c_old[4])); + ctx->c[6] = U32V(ctx->c[6] + 0x4D34D34D + (ctx->c[5] < c_old[5])); + ctx->c[7] = U32V(ctx->c[7] + 0xD34D34D3 + (ctx->c[6] < c_old[6])); + ctx->carry = (ctx->c[7] < c_old[7]); + + /* Calculate the g-values */ + for (i=0;i<8;i++) + g[i] = RABBIT_g_func(U32V(ctx->x[i] + ctx->c[i])); + + /* Calculate new state values */ + ctx->x[0] = U32V(g[0] + rotlFixed(g[7],16) + rotlFixed(g[6], 16)); + ctx->x[1] = U32V(g[1] + rotlFixed(g[0], 8) + g[7]); + ctx->x[2] = U32V(g[2] + rotlFixed(g[1],16) + rotlFixed(g[0], 16)); + ctx->x[3] = U32V(g[3] + rotlFixed(g[2], 8) + g[1]); + ctx->x[4] = U32V(g[4] + rotlFixed(g[3],16) + rotlFixed(g[2], 16)); + ctx->x[5] = U32V(g[5] + rotlFixed(g[4], 8) + g[3]); + ctx->x[6] = U32V(g[6] + rotlFixed(g[5],16) + rotlFixed(g[4], 16)); + ctx->x[7] = U32V(g[7] + rotlFixed(g[6], 8) + g[5]); +} + + +/* IV setup */ +void Rabbit::SetIV(const byte* iv) +{ + /* Temporary variables */ + word32 i0, i1, i2, i3, i; + + /* Generate four subvectors */ + i0 = LITTLE32(*(word32*)(iv+0)); + i2 = LITTLE32(*(word32*)(iv+4)); + i1 = (i0>>16) | (i2&0xFFFF0000); + i3 = (i2<<16) | (i0&0x0000FFFF); + + /* Modify counter values */ + workCtx_.c[0] = masterCtx_.c[0] ^ i0; + workCtx_.c[1] = masterCtx_.c[1] ^ i1; + workCtx_.c[2] = masterCtx_.c[2] ^ i2; + workCtx_.c[3] = masterCtx_.c[3] ^ i3; + workCtx_.c[4] = masterCtx_.c[4] ^ i0; + workCtx_.c[5] = masterCtx_.c[5] ^ i1; + workCtx_.c[6] = masterCtx_.c[6] ^ i2; + workCtx_.c[7] = masterCtx_.c[7] ^ i3; + + /* Copy state variables */ + for (i=0; i<8; i++) + workCtx_.x[i] = masterCtx_.x[i]; + workCtx_.carry = masterCtx_.carry; + + /* Iterate the system four times */ + for (i=0; i<4; i++) + NextState(Work); +} + + +/* Key setup */ +void Rabbit::SetKey(const byte* key, const byte* iv) +{ + /* Temporary variables */ + word32 k0, k1, k2, k3, i; + + /* Generate four subkeys */ + k0 = LITTLE32(*(word32*)(key+ 0)); + k1 = LITTLE32(*(word32*)(key+ 4)); + k2 = LITTLE32(*(word32*)(key+ 8)); + k3 = LITTLE32(*(word32*)(key+12)); + + /* Generate initial state variables */ + masterCtx_.x[0] = k0; + masterCtx_.x[2] = k1; + masterCtx_.x[4] = k2; + masterCtx_.x[6] = k3; + masterCtx_.x[1] = U32V(k3<<16) | (k2>>16); + masterCtx_.x[3] = U32V(k0<<16) | (k3>>16); + masterCtx_.x[5] = U32V(k1<<16) | (k0>>16); + masterCtx_.x[7] = U32V(k2<<16) | (k1>>16); + + /* Generate initial counter values */ + masterCtx_.c[0] = rotlFixed(k2, 16); + masterCtx_.c[2] = rotlFixed(k3, 16); + masterCtx_.c[4] = rotlFixed(k0, 16); + masterCtx_.c[6] = rotlFixed(k1, 16); + masterCtx_.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF); + masterCtx_.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF); + masterCtx_.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF); + masterCtx_.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF); + + /* Clear carry bit */ + masterCtx_.carry = 0; + + /* Iterate the system four times */ + for (i=0; i<4; i++) + NextState(Master); + + /* Modify the counters */ + for (i=0; i<8; i++) + masterCtx_.c[i] ^= masterCtx_.x[(i+4)&0x7]; + + /* Copy master instance to work instance */ + for (i=0; i<8; i++) { + workCtx_.x[i] = masterCtx_.x[i]; + workCtx_.c[i] = masterCtx_.c[i]; + } + workCtx_.carry = masterCtx_.carry; + + if (iv) SetIV(iv); +} + + +/* Encrypt/decrypt a message of any size */ +void Rabbit::Process(byte* output, const byte* input, word32 msglen) +{ + /* Temporary variables */ + word32 i; + byte buffer[16]; + + /* Encrypt/decrypt all full blocks */ + while (msglen >= 16) { + /* Iterate the system */ + NextState(Work); + + /* Encrypt/decrypt 16 bytes of data */ + *(word32*)(output+ 0) = *(word32*)(input+ 0) ^ + LITTLE32(workCtx_.x[0] ^ (workCtx_.x[5]>>16) ^ + U32V(workCtx_.x[3]<<16)); + *(word32*)(output+ 4) = *(word32*)(input+ 4) ^ + LITTLE32(workCtx_.x[2] ^ (workCtx_.x[7]>>16) ^ + U32V(workCtx_.x[5]<<16)); + *(word32*)(output+ 8) = *(word32*)(input+ 8) ^ + LITTLE32(workCtx_.x[4] ^ (workCtx_.x[1]>>16) ^ + U32V(workCtx_.x[7]<<16)); + *(word32*)(output+12) = *(word32*)(input+12) ^ + LITTLE32(workCtx_.x[6] ^ (workCtx_.x[3]>>16) ^ + U32V(workCtx_.x[1]<<16)); + + /* Increment pointers and decrement length */ + input += 16; + output += 16; + msglen -= 16; + } + + /* Encrypt/decrypt remaining data */ + if (msglen) { + /* Iterate the system */ + NextState(Work); + + /* Generate 16 bytes of pseudo-random data */ + *(word32*)(buffer+ 0) = LITTLE32(workCtx_.x[0] ^ + (workCtx_.x[5]>>16) ^ U32V(workCtx_.x[3]<<16)); + *(word32*)(buffer+ 4) = LITTLE32(workCtx_.x[2] ^ + (workCtx_.x[7]>>16) ^ U32V(workCtx_.x[5]<<16)); + *(word32*)(buffer+ 8) = LITTLE32(workCtx_.x[4] ^ + (workCtx_.x[1]>>16) ^ U32V(workCtx_.x[7]<<16)); + *(word32*)(buffer+12) = LITTLE32(workCtx_.x[6] ^ + (workCtx_.x[3]>>16) ^ U32V(workCtx_.x[1]<<16)); + + /* Encrypt/decrypt the data */ + for (i=0; i<msglen; i++) + output[i] = input[i] ^ buffer[i]; + } +} + + +} // namespace diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp index 1be0fed612f..aa9be7f1985 100644 --- a/extra/yassl/taocrypt/src/random.cpp +++ b/extra/yassl/taocrypt/src/random.cpp @@ -96,13 +96,13 @@ void OS_Seed::GenerateSeed(byte* output, word32 sz) /* The default OS_Seed implementation */ -OS_Seed::OS_Seed() +OS_Seed::OS_Seed() { fd_ = open("/dev/urandom",O_RDONLY); if (fd_ == -1) { fd_ = open("/dev/random",O_RDONLY); - if (fd_ == -1) - error_.SetError(OPEN_RAN_E); + if (fd_ == -1) + error_.SetError(OPEN_RAN_E); } } diff --git a/extra/yassl/taocrypt/src/ripemd.cpp b/extra/yassl/taocrypt/src/ripemd.cpp index a738c197bf2..e012db43de5 100644 --- a/extra/yassl/taocrypt/src/ripemd.cpp +++ b/extra/yassl/taocrypt/src/ripemd.cpp @@ -110,14 +110,14 @@ void RIPEMD160::Update(const byte* data, word32 len) // all at once for asm if (buffLen_ == 0) { - word32 times = len / BLOCK_SIZE; - if (times) { - AsmTransform(data, times); - const word32 add = BLOCK_SIZE * times; - AddLength(add); - len -= add; - data += add; - } + word32 times = len / BLOCK_SIZE; + if (times) { + AsmTransform(data, times); + const word32 add = BLOCK_SIZE * times; + AddLength(add); + len -= add; + data += add; + } } // cache any data left diff --git a/extra/yassl/taocrypt/src/rsa.cpp b/extra/yassl/taocrypt/src/rsa.cpp index 57d19a59c76..576146377a3 100644 --- a/extra/yassl/taocrypt/src/rsa.cpp +++ b/extra/yassl/taocrypt/src/rsa.cpp @@ -61,7 +61,6 @@ Integer RSA_PrivateKey::CalculateInverse(RandomNumberGenerator& rng, Integer y = ModularRoot(re, dq_, dp_, q_, p_, u_); y = modn.Divide(y, r); // unblind - assert(modn.Exponentiate(y, e_) == x); // check return y; } @@ -124,7 +123,8 @@ word32 RSA_BlockType2::UnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, unsigned i=1; while (i<pkcsBlockLen && pkcsBlock[i++]) { // null body } - assert(i==pkcsBlockLen || pkcsBlock[i-1]==0); + if (!(i==pkcsBlockLen || pkcsBlock[i-1]==0)) + return 0; unsigned int outputLen = pkcsBlockLen - i; invalid = (outputLen > maxOutputLen) || invalid; @@ -179,7 +179,8 @@ word32 RSA_BlockType1::UnPad(const byte* pkcsBlock, word32 pkcsBlockLen, unsigned i=1; while (i<pkcsBlockLen && pkcsBlock[i++]) { // null body } - assert(i==pkcsBlockLen || pkcsBlock[i-1]==0); + if (!(i==pkcsBlockLen || pkcsBlock[i-1]==0)) + return 0; unsigned int outputLen = pkcsBlockLen - i; invalid = (outputLen > maxOutputLen) || invalid; diff --git a/extra/yassl/taocrypt/src/sha.cpp b/extra/yassl/taocrypt/src/sha.cpp index ef165a342ad..1ae42d94e4c 100644 --- a/extra/yassl/taocrypt/src/sha.cpp +++ b/extra/yassl/taocrypt/src/sha.cpp @@ -344,14 +344,14 @@ void SHA::Update(const byte* data, word32 len) // all at once for asm if (buffLen_ == 0) { - word32 times = len / BLOCK_SIZE; - if (times) { - AsmTransform(data, times); - const word32 add = BLOCK_SIZE * times; - AddLength(add); - len -= add; - data += add; - } + word32 times = len / BLOCK_SIZE; + if (times) { + AsmTransform(data, times); + const word32 add = BLOCK_SIZE * times; + AddLength(add); + len -= add; + data += add; + } } // cache any data left diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp index 390da58e191..b472d18236f 100644 --- a/extra/yassl/taocrypt/src/template_instnt.cpp +++ b/extra/yassl/taocrypt/src/template_instnt.cpp @@ -61,7 +61,6 @@ template class PBKDF2_HMAC<SHA>; template class HMAC<MD5>; template class HMAC<SHA>; template class HMAC<RIPEMD160>; - } namespace mySTL { diff --git a/extra/yassl/taocrypt/src/twofish.cpp b/extra/yassl/taocrypt/src/twofish.cpp index 15bb778f444..4ae493624dc 100644 --- a/extra/yassl/taocrypt/src/twofish.cpp +++ b/extra/yassl/taocrypt/src/twofish.cpp @@ -141,8 +141,6 @@ inline word32 Twofish::h(word32 x, const word32* key, unsigned int kLen) void Twofish::SetKey(const byte* userKey, word32 keylen, CipherDir /*dummy*/) { - assert(keylen >= 16 && keylen <= 32); - unsigned int len = (keylen <= 16 ? 2 : (keylen <= 24 ? 3 : 4)); word32 key[8]; GetUserKey(LittleEndianOrder, key, len*2, userKey, keylen); diff --git a/extra/yassl/taocrypt/taocrypt.dsp b/extra/yassl/taocrypt/taocrypt.dsp index 3f1b47990ad..9c8e74da8c8 100644 --- a/extra/yassl/taocrypt/taocrypt.dsp +++ b/extra/yassl/taocrypt/taocrypt.dsp @@ -138,6 +138,10 @@ SOURCE=.\src\hash.cpp # End Source File # Begin Source File +SOURCE=.\src\hc128.cpp +# End Source File +# Begin Source File + SOURCE=.\src\integer.cpp # End Source File # Begin Source File @@ -158,6 +162,10 @@ SOURCE=.\src\misc.cpp # End Source File # Begin Source File +SOURCE=.\src\rabbit.cpp +# End Source File +# Begin Source File + SOURCE=.\src\random.cpp # End Source File # Begin Source File @@ -238,6 +246,10 @@ SOURCE=.\include\hash.hpp # End Source File # Begin Source File +SOURCE=.\include\hc128.hpp +# End Source File +# Begin Source File + SOURCE=.\include\hmac.hpp # End Source File # Begin Source File @@ -274,6 +286,10 @@ SOURCE=.\include\pwdbased.hpp # End Source File # Begin Source File +SOURCE=.\include\rabbit.hpp +# End Source File +# Begin Source File + SOURCE=.\include\random.hpp # End Source File # Begin Source File diff --git a/extra/yassl/taocrypt/test/make.bat b/extra/yassl/taocrypt/test/make.bat index d6d62b984a8..d6d62b984a8 100644..100755 --- a/extra/yassl/taocrypt/test/make.bat +++ b/extra/yassl/taocrypt/test/make.bat diff --git a/extra/yassl/taocrypt/test/memory.cpp b/extra/yassl/taocrypt/test/memory.cpp index bac8f9c2e97..ec398a64c45 100644 --- a/extra/yassl/taocrypt/test/memory.cpp +++ b/extra/yassl/taocrypt/test/memory.cpp @@ -328,3 +328,32 @@ void operator delete[](void* ptr) { ::operator delete(ptr); } + + +extern "C" { + +void* XMALLOC(size_t sz, void* head) +{ + return ::operator new(sz); +} + +void* XREALLOC(void* ptr, size_t sz, void* heap) +{ + void* ret = ::operator new(sz); + + if (ret && ptr) + memcpy(ret, ptr, sz); + + if (ret) + ::operator delete(ptr); + return ret; +} + + +void XFREE(void* ptr, void* heap) +{ + ::operator delete(ptr); +} + +} // extern "C" + diff --git a/extra/yassl/taocrypt/test/test.cpp b/extra/yassl/taocrypt/test/test.cpp index 09836a2ef56..807f91f32ae 100644 --- a/extra/yassl/taocrypt/test/test.cpp +++ b/extra/yassl/taocrypt/test/test.cpp @@ -27,6 +27,8 @@ #include "coding.hpp" #include "random.hpp" #include "pwdbased.hpp" +#include "rabbit.hpp" +#include "hc128.hpp" @@ -86,16 +88,18 @@ using TaoCrypt::PBKDF2_HMAC; using TaoCrypt::tcArrayDelete; using TaoCrypt::GetCert; using TaoCrypt::GetPKCS_Cert; - +using TaoCrypt::Rabbit; +using TaoCrypt::HC128; struct testVector { byte* input_; byte* output_; - size_t inLen_; - size_t outLen_; + word32 inLen_; + word32 outLen_; testVector(const char* in, const char* out) : input_((byte*)in), - output_((byte*)out), inLen_(strlen(in)), outLen_(strlen(out)) {} + output_((byte*)out), inLen_((word32)strlen(in)), + outLen_((word32)strlen(out)) {} }; int sha_test(); @@ -120,13 +124,15 @@ int dsa_test(); int dh_test(); int pwdbased_test(); int pkcs12_test(); +int rabbit_test(); +int hc128_test(); TaoCrypt::RandomNumberGenerator rng; void err_sys(const char* msg, int es) { - printf("%s", msg); + printf("%s\n", msg); exit(es); } @@ -162,7 +168,7 @@ byte* cipher = 0; // block output void taocrypt_test(void* args) { ((func_args*)args)->return_code = -1; // error state - + msg = NEW_TC byte[24]; plain = NEW_TC byte[24]; cipher = NEW_TC byte[24]; @@ -229,6 +235,16 @@ void taocrypt_test(void* args) else printf( "ARC4 test passed!\n"); + if ( (ret = rabbit_test()) ) + err_sys("Rabbit test failed!\n", ret); + else + printf( "Rabbit test passed!\n"); + + if ( (ret = hc128_test()) ) + err_sys("HC128 test failed!\n", ret); + else + printf( "HC128 test passed!\n"); + if ( (ret = des_test()) ) err_sys("DES test failed!\n", ret); else @@ -306,16 +322,16 @@ void taocrypt_test(void* args) void file_test(const char* file, byte* check) { FILE* f; - int i(0); - MD5 md5; - byte buf[1024]; - byte md5sum[MD5::DIGEST_SIZE]; + int i = 0; + MD5 md5; + byte buf[1024]; + byte md5sum[MD5::DIGEST_SIZE]; if( !( f = fopen( file, "rb" ) )) { printf("Can't open %s\n", file); return; } - while( ( i = fread(buf, 1, sizeof(buf), f )) > 0 ) + while( ( i = (int)fread(buf, 1, sizeof(buf), f )) > 0 ) md5.Update(buf, i); md5.Final(md5sum); @@ -704,7 +720,7 @@ int hmac_test() int times( sizeof(test_hmacMD5) / sizeof(testVector) ); for (int i = 0; i < times; ++i) { - hmacMD5.SetKey((byte*)keys[i], strlen(keys[i])); + hmacMD5.SetKey((byte*)keys[i], (word32)strlen(keys[i])); hmacMD5.Update(test_hmacMD5[i].input_, test_hmacMD5[i].inLen_); hmacMD5.Final(hash); @@ -747,8 +763,8 @@ int arc4_test() ARC4::Encryption enc; ARC4::Decryption dec; - enc.SetKey((byte*)keys[i], strlen(keys[i])); - dec.SetKey((byte*)keys[i], strlen(keys[i])); + enc.SetKey((byte*)keys[i], (word32)strlen(keys[i])); + dec.SetKey((byte*)keys[i], (word32)strlen(keys[i])); enc.Process(cipher, test_arc4[i].input_, test_arc4[i].outLen_); dec.Process(plain, cipher, test_arc4[i].outLen_); @@ -764,6 +780,114 @@ int arc4_test() } +int rabbit_test() +{ + byte cipher[16]; + byte plain[16]; + + const char* keys[] = + { + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\xAC\xC3\x51\xDC\xF1\x62\xFC\x3B\xFE\x36\x3D\x2E\x29\x13\x28\x91" + }; + + const char* ivs[] = + { + "\x00\x00\x00\x00\x00\x00\x00\x00", + "\x59\x7E\x26\xC1\x75\xF5\x73\xC3", + 0 + }; + + + testVector test_rabbit[] = + { + testVector("\x00\x00\x00\x00\x00\x00\x00\x00", + "\xED\xB7\x05\x67\x37\x5D\xCD\x7C"), + testVector("\x00\x00\x00\x00\x00\x00\x00\x00", + "\x6D\x7D\x01\x22\x92\xCC\xDC\xE0"), + testVector("\x00\x00\x00\x00\x00\x00\x00\x00", + "\x9C\x51\xE2\x87\x84\xC3\x7F\xE9") + }; + + + int times( sizeof(test_rabbit) / sizeof(testVector) ); + for (int i = 0; i < times; ++i) { + Rabbit::Encryption enc; + Rabbit::Decryption dec; + + enc.SetKey((byte*)keys[i], (byte*)ivs[i]); + dec.SetKey((byte*)keys[i], (byte*)ivs[i]); + + enc.Process(cipher, test_rabbit[i].input_, test_rabbit[i].outLen_); + dec.Process(plain, cipher, test_rabbit[i].outLen_); + + if (memcmp(plain, test_rabbit[i].input_, test_rabbit[i].outLen_)) + return -230 - i; + + if (memcmp(cipher, test_rabbit[i].output_, test_rabbit[i].outLen_)) + return -240 - i; + } + + return 0; +} + + +int hc128_test() +{ + byte cipher[16]; + byte plain[16]; + + const char* keys[] = + { + "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x53\xA6\xF9\x4C\x9F\xF2\x45\x98\xEB\x3E\x91\xE4\x37\x8A\xDD", + "\x0F\x62\xB5\x08\x5B\xAE\x01\x54\xA7\xFA\x4D\xA0\xF3\x46\x99\xEC" + }; + + const char* ivs[] = + { + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x0D\x74\xDB\x42\xA9\x10\x77\xDE\x45\xAC\x13\x7A\xE1\x48\xAF\x16", + "\x28\x8F\xF6\x5D\xC4\x2B\x92\xF9\x60\xC7\x2E\x95\xFC\x63\xCA\x31" + }; + + testVector test_hc128[] = + { + testVector("\x00\x00\x00\x00\x00\x00\x00\x00", + "\x37\x86\x02\xB9\x8F\x32\xA7\x48"), + testVector("\x00\x00\x00\x00\x00\x00\x00\x00", + "\x33\x7F\x86\x11\xC6\xED\x61\x5F"), + testVector("\x00\x00\x00\x00\x00\x00\x00\x00", + "\x2E\x1E\xD1\x2A\x85\x51\xC0\x5A"), + testVector("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x1C\xD8\xAE\xDD\xFE\x52\xE2\x17\xE8\x35\xD0\xB7\xE8\x4E\x29") + }; + + int times( sizeof(test_hc128) / sizeof(testVector) ); + for (int i = 0; i < times; ++i) { + HC128::Encryption enc; + HC128::Decryption dec; + + enc.SetKey((byte*)keys[i], (byte*)ivs[i]); + dec.SetKey((byte*)keys[i], (byte*)ivs[i]); + + enc.Process(cipher, test_hc128[i].input_, test_hc128[i].outLen_); + dec.Process(plain, cipher, test_hc128[i].outLen_); + + if (memcmp(plain, test_hc128[i].input_, test_hc128[i].outLen_)) + return -330 - i; + + if (memcmp(cipher, test_hc128[i].output_, test_hc128[i].outLen_)) + return -340 - i; + } + + return 0; +} + + int des_test() { //ECB mode @@ -1026,7 +1150,7 @@ int rsa_test() RSAES_Encryptor enc(priv); byte message[] = "Everyone gets Friday off."; - const int len(strlen((char*)message)); + const word32 len = (word32)strlen((char*)message); byte cipher[64]; enc.Encrypt(message, len, cipher, rng); @@ -1054,6 +1178,8 @@ int rsa_test() } } CertDecoder cd(source2, true, 0, false, CertDecoder::CA); + if (cd.GetError().What()) + err_sys("cert error", -80); Source source3(cd.GetPublicKey().GetKey(), cd.GetPublicKey().size()); RSA_PublicKey pub(source3); @@ -1174,6 +1300,7 @@ int pwdbased_test() } +/* int pkcs12_test() { Source cert; @@ -1206,4 +1333,5 @@ int pkcs12_test() return 0; } +*/ diff --git a/extra/yassl/testsuite/make.bat b/extra/yassl/testsuite/make.bat index 941e499d7e6..941e499d7e6 100644..100755 --- a/extra/yassl/testsuite/make.bat +++ b/extra/yassl/testsuite/make.bat diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp index a0a9fafc87e..559ebe54f1b 100644 --- a/extra/yassl/testsuite/test.hpp +++ b/extra/yassl/testsuite/test.hpp @@ -23,6 +23,7 @@ #include "runtime.hpp" #include "openssl/ssl.h" /* openssl compatibility test */ +#include "error.hpp" #include <stdio.h> #include <stdlib.h> #include <assert.h> @@ -32,6 +33,10 @@ #ifdef _WIN32 #include <winsock2.h> #include <process.h> + #ifdef TEST_IPV6 // don't require newer SDK for IPV4 + #include <ws2tcpip.h> + #include <wspiapi.h> + #endif #define SOCKET_T unsigned int #else #include <string.h> @@ -42,6 +47,9 @@ #include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> + #ifdef TEST_IPV6 + #include <netdb.h> + #endif #include <pthread.h> #ifdef NON_BLOCKING #include <fcntl.h> @@ -50,6 +58,13 @@ #endif /* _WIN32 */ +#ifdef _MSC_VER + // disable conversion warning + // 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy + #pragma warning(disable:4244 4996) +#endif + + #if !defined(_SOCKLEN_T) && (defined(_WIN32) || defined(__APPLE__)) typedef int socklen_t; #endif @@ -64,6 +79,15 @@ #endif +#ifdef TEST_IPV6 + typedef sockaddr_in6 SOCKADDR_IN_T; + #define AF_INET_V AF_INET6 +#else + typedef sockaddr_in SOCKADDR_IN_T; + #define AF_INET_V AF_INET +#endif + + // Check if _POSIX_THREADS should be forced #if !defined(_POSIX_THREADS) && defined(__hpux) // HPUX does not define _POSIX_THREADS as it's not _fully_ implemented @@ -73,7 +97,7 @@ #ifndef _POSIX_THREADS typedef unsigned int THREAD_RETURN; - typedef unsigned long THREAD_TYPE; + typedef HANDLE THREAD_TYPE; #define YASSL_API __stdcall #else typedef void* THREAD_RETURN; @@ -120,8 +144,8 @@ void start_thread(THREAD_FUNC, func_args*, THREAD_TYPE*); void join_thread(THREAD_TYPE); // yaSSL -const char* const yasslIP = "127.0.0.1"; -const unsigned short yasslPort = 11111; +const char* const yasslIP = "127.0.0.1"; +const unsigned short yasslPort = 11111; // client @@ -180,7 +204,7 @@ extern "C" { static int PasswordCallBack(char* passwd, int sz, int rw, void* userdata) { - strncpy(passwd, "12345678", sz); + strncpy(passwd, "yassl123", sz); return 8; } @@ -300,14 +324,35 @@ inline void tcp_set_nonblocking(SOCKET_T& sockfd) } -inline void tcp_socket(SOCKET_T& sockfd, sockaddr_in& addr) +inline void tcp_socket(SOCKET_T& sockfd, SOCKADDR_IN_T& addr) { - sockfd = socket(AF_INET, SOCK_STREAM, 0); + sockfd = socket(AF_INET_V, SOCK_STREAM, 0); memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; +#ifdef TEST_IPV6 + addr.sin6_family = AF_INET_V; + addr.sin6_port = htons(yasslPort); + addr.sin6_addr = in6addr_loopback; + + /* // for external testing later + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET_V; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + getaddrinfo(yasslIP6, yasslPortStr, &hints, info); + // then use info connect(sockfd, info->ai_addr, info->ai_addrlen) + + if (*info == 0) + err_sys("getaddrinfo failed"); + */ // end external testing later +#else + addr.sin_family = AF_INET_V; addr.sin_port = htons(yasslPort); addr.sin_addr.s_addr = inet_addr(yasslIP); +#endif + } @@ -318,13 +363,13 @@ inline void tcp_close(SOCKET_T& sockfd) #else close(sockfd); #endif - sockfd = -1; + sockfd = (SOCKET_T) -1; } inline void tcp_connect(SOCKET_T& sockfd) { - sockaddr_in addr; + SOCKADDR_IN_T addr; tcp_socket(sockfd, addr); if (connect(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) { @@ -336,9 +381,15 @@ inline void tcp_connect(SOCKET_T& sockfd) inline void tcp_listen(SOCKET_T& sockfd) { - sockaddr_in addr; + SOCKADDR_IN_T addr; tcp_socket(sockfd, addr); +#ifndef _WIN32 + int on = 1; + socklen_t len = sizeof(on); + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len); +#endif + if (bind(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) { tcp_close(sockfd); err_sys("tcp bind failed"); @@ -355,7 +406,7 @@ inline void tcp_accept(SOCKET_T& sockfd, SOCKET_T& clientfd, func_args& args) { tcp_listen(sockfd); - sockaddr_in client; + SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); #if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) @@ -369,7 +420,7 @@ inline void tcp_accept(SOCKET_T& sockfd, SOCKET_T& clientfd, func_args& args) clientfd = accept(sockfd, (sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); - if (clientfd == -1) { + if (clientfd == (SOCKET_T) -1) { tcp_close(sockfd); err_sys("tcp accept failed"); } @@ -387,10 +438,8 @@ inline void showPeer(SSL* ssl) char* issuer = X509_NAME_oneline(X509_get_issuer_name(peer), 0, 0); char* subject = X509_NAME_oneline(X509_get_subject_name(peer), 0, 0); - printf("peer's cert info:\n"); - printf("issuer : %s\n", issuer); - printf("subject: %s\n", subject); - + printf("peer's cert info:\n issuer : %s\n subject: %s\n", issuer, + subject); free(subject); free(issuer); } @@ -436,5 +485,19 @@ inline DH* set_tmpDH(SSL_CTX* ctx) } +inline int verify_callback(int preverify_ok, X509_STORE_CTX* ctx) +{ + X509* err_cert = X509_STORE_CTX_get_current_cert(ctx); + int err = X509_STORE_CTX_get_error(ctx); + int depth = X509_STORE_CTX_get_error_depth(ctx); + + // test allow self signed + if (err_cert && depth == 0 && err == TaoCrypt::SIG_OTHER_E) + return 1; + + return 0; +} + + #endif // yaSSL_TEST_HPP diff --git a/extra/yassl/testsuite/testsuite.cpp b/extra/yassl/testsuite/testsuite.cpp index 5ddb9bb4dab..fa8c997e7c2 100644 --- a/extra/yassl/testsuite/testsuite.cpp +++ b/extra/yassl/testsuite/testsuite.cpp @@ -119,7 +119,7 @@ int main(int argc, char** argv) void start_thread(THREAD_FUNC fun, func_args* args, THREAD_TYPE* thread) { #ifndef _POSIX_THREADS - *thread = _beginthreadex(0, 0, fun, args, 0, 0); + *thread = (HANDLE)_beginthreadex(0, 0, fun, args, 0, 0); #else pthread_create(thread, 0, fun, args); #endif @@ -129,9 +129,9 @@ void start_thread(THREAD_FUNC fun, func_args* args, THREAD_TYPE* thread) void join_thread(THREAD_TYPE thread) { #ifndef _POSIX_THREADS - int res = WaitForSingleObject(reinterpret_cast<HANDLE>(thread), INFINITE); + int res = WaitForSingleObject(thread, INFINITE); assert(res == WAIT_OBJECT_0); - res = CloseHandle(reinterpret_cast<HANDLE>(thread)); + res = CloseHandle(thread); assert(res); #else pthread_join(thread, 0); @@ -158,7 +158,7 @@ int test_openSSL_des() { /* test des encrypt/decrypt */ char data[] = "this is my data "; - int dataSz = strlen(data); + int dataSz = (int)strlen(data); DES_key_schedule key[3]; byte iv[8]; EVP_BytesToKey(EVP_des_ede3_cbc(), EVP_md5(), NULL, (byte*)data, dataSz, 1, diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 052df5d3276..3046c3f7614 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -20,22 +20,14 @@ ${CMAKE_CURRENT_BINARY_DIR}/mysqld_ername.h ${CMAKE_CURRENT_BINARY_DIR}/mysqld_error.h ${CMAKE_CURRENT_BINARY_DIR}/sql_state.h ) -SET(HEADERS_ABI + +SET(HEADERS mysql.h mysql_com.h mysql_time.h my_list.h my_alloc.h typelib.h - mysql/plugin.h - mysql/plugin_audit.h - mysql/plugin_ftparser.h - mysql/plugin_auth.h - mysql/client_plugin.h -) - -SET(HEADERS - ${HEADERS_ABI} my_dbug.h m_string.h my_sys.h @@ -61,4 +53,4 @@ SET(HEADERS ) INSTALL(FILES ${HEADERS} DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT Development) -INSTALL(DIRECTORY mysql/ DESTINATION ${INSTALL_INCLUDEDIR}/mysql COMPONENT Development FILES_MATCHING PATTERN "*.h") +INSTALL(DIRECTORY mysql/ DESTINATION ${INSTALL_INCLUDEDIR} COMPONENT Development FILES_MATCHING PATTERN "*.h") diff --git a/include/m_ctype.h b/include/m_ctype.h index 8e0344356d5..969cb0058ac 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2010, Oracle and/or its affiliates. + Copyright (c) 2000, 2012, 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 @@ -71,7 +71,7 @@ struct unicase_info_st extern MY_UNICASE_INFO *const my_unicase_default[256]; extern MY_UNICASE_INFO *const my_unicase_turkish[256]; -extern MY_UNICASE_INFO *my_unicase_mysql500[256]; +extern MY_UNICASE_INFO *const my_unicase_mysql500[256]; #define MY_UCA_MAX_CONTRACTION 4 #define MY_UCA_MAX_WEIGHT_SIZE 8 @@ -356,6 +356,7 @@ extern struct charset_info_st my_charset_ucs2_bin; extern struct charset_info_st my_charset_ucs2_general_ci; extern struct charset_info_st my_charset_ucs2_general_mysql500_ci; extern struct charset_info_st my_charset_ucs2_unicode_ci; +extern struct charset_info_st my_charset_ucs2_general_mysql500_ci; extern struct charset_info_st my_charset_ujis_bin; extern struct charset_info_st my_charset_ujis_japanese_ci; extern struct charset_info_st my_charset_utf16_bin; diff --git a/include/m_string.h b/include/m_string.h index 7c95c7319dc..9fc6cda4764 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -66,7 +66,9 @@ # define bcmp(A,B,C) memcmp((A),(B),(C)) #endif -#if !defined(bzero) && (!defined(HAVE_BZERO) || !defined(HAVE_DECL_BZERO)) +#if !defined(bzero) && (!defined(HAVE_BZERO) || !HAVE_DECL_BZERO || defined(_AIX)) +/* See autoconf doku: "HAVE_DECL_symbol" will be defined after configure, to 0 or 1 */ +/* AIX has bzero() as a function, but the declaration prototype is strangely hidden */ # define bzero(A,B) memset((A),0,(B)) #endif diff --git a/include/my_global.h b/include/my_global.h index 3ab736ba1fc..8170ce381af 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2001, 2011, Oracle and/or its affiliates. + Copyright (c) 2001, 2012, 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 @@ -446,6 +446,10 @@ extern "C" int madvise(void *addr, size_t len, int behav); #define SIGNAL_HANDLER_RESET_ON_DELIVERY #endif +#ifndef STDERR_FILENO +#define STDERR_FILENO 2 +#endif + /* Deprecated workaround for false-positive uninitialized variables warnings. Those should be silenced using tool-specific heuristics. diff --git a/include/my_stacktrace.h b/include/my_stacktrace.h index ebc30ed8b59..ad05a7df9ab 100644 --- a/include/my_stacktrace.h +++ b/include/my_stacktrace.h @@ -50,11 +50,13 @@ void my_safe_print_str(const char* val, int max_len); void my_write_core(int sig); #if BACKTRACE_DEMANGLE char *my_demangle(const char *mangled_name, int *status); -#endif +#endif /* BACKTRACE_DEMANGLE */ #ifdef __WIN__ void my_set_exception_pointers(EXCEPTION_POINTERS *ep); -#endif -#endif +#endif /* __WIN__ */ +#else +#define my_init_stacktrace() do { } while(0) +#endif /* ! (defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE)) */ #ifndef _WIN32 #define MY_ADDR_RESOLVE_FORK @@ -82,50 +84,6 @@ const char *my_addr_resolve_init(); void my_write_core(int sig); #endif - - -/** - Async-signal-safe utility functions used by signal handler routines. - Declared here in order to unit-test them. - These are not general-purpose, but tailored to the signal handling routines. -*/ -/** - Converts a longlong value to string. - @param base 10 for decimal, 16 for hex values (0..9a..f) - @param val The value to convert - @param buf Assumed to point to the *end* of the buffer. - @returns Pointer to the first character of the converted string. - Negative values: - for base-10 the return string will be prepended with '-' - for base-16 the return string will contain 16 characters - Implemented with simplicity, and async-signal-safety in mind. -*/ -char *my_safe_itoa(int base, longlong val, char *buf); - -/** - Converts a ulonglong value to string. - @param base 10 for decimal, 16 for hex values (0..9a..f) - @param val The value to convert - @param buf Assumed to point to the *end* of the buffer. - @returns Pointer to the first character of the converted string. - Implemented with simplicity, and async-signal-safety in mind. -*/ -char *my_safe_utoa(int base, ulonglong val, char *buf); - -/** - A (very) limited version of snprintf. - @param to Destination buffer. - @param n Size of destination buffer. - @param fmt printf() style format string. - @returns Number of bytes written, including terminating '\0' - Supports 'd' 'i' 'u' 'x' 'p' 's' conversion. - Supports 'l' and 'll' modifiers for integral types. - Does not support any width/precision. - Implemented with simplicity, and async-signal-safety in mind. -*/ -size_t my_safe_snprintf(char* to, size_t n, const char* fmt, ...) - ATTRIBUTE_FORMAT(printf, 3, 4); - /** A (very) limited version of snprintf, which writes the result to STDERR. @sa my_safe_snprintf diff --git a/include/my_sys.h b/include/my_sys.h index 3fcaea95f7b..a02c390fe4b 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -157,16 +157,6 @@ extern char *my_strndup(const char *from, size_t length, myf MyFlags); extern int sf_leaking_memory; /* set to 1 to disable memleak detection */ -#if defined(ENABLED_DEBUG_SYNC) -extern void (*debug_sync_C_callback_ptr)(const char *, size_t); -#define DEBUG_SYNC_C(_sync_point_name_) do { \ - if (debug_sync_C_callback_ptr != NULL) \ - (*debug_sync_C_callback_ptr)(STRING_WITH_LEN(_sync_point_name_)); } \ - while(0) -#else -#define DEBUG_SYNC_C(_sync_point_name_) -#endif /* defined(ENABLED_DEBUG_SYNC) */ - #ifdef HAVE_LARGE_PAGES extern uint my_get_large_page_size(void); extern uchar * my_large_malloc(size_t size, myf my_flags); diff --git a/include/my_valgrind.h b/include/my_valgrind.h index 5af3a14cf10..31651f6c3ed 100644 --- a/include/my_valgrind.h +++ b/include/my_valgrind.h @@ -23,7 +23,7 @@ #define IF_VALGRIND(A,B) B #endif -#if defined(HAVE_VALGRIND) +#if defined(HAVE_VALGRIND) && defined(HAVE_valgrind) # include <valgrind/memcheck.h> # define MEM_UNDEFINED(a,len) VALGRIND_MAKE_MEM_UNDEFINED(a,len) # define MEM_NOACCESS(a,len) VALGRIND_MAKE_MEM_NOACCESS(a,len) diff --git a/include/myisam.h b/include/myisam.h index 3d4eecb7cbe..eaa6b2dbd1f 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2000, 2012, 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 @@ -421,7 +421,7 @@ int flush_pending_blocks(MI_SORT_PARAM *param); int sort_ft_buf_flush(MI_SORT_PARAM *sort_param); int thr_write_keys(MI_SORT_PARAM *sort_param); int sort_write_record(MI_SORT_PARAM *sort_param); -int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ulong); +int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, ulonglong); #ifdef __cplusplus } diff --git a/include/mysql.h.pp b/include/mysql.h.pp index 002b3f2e2ea..ce577146581 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -66,9 +66,7 @@ enum mysql_enum_shutdown_level { SHUTDOWN_WAIT_TRANSACTIONS= (unsigned char)(1 << 1), SHUTDOWN_WAIT_UPDATES= (unsigned char)(1 << 3), SHUTDOWN_WAIT_ALL_BUFFERS= ((unsigned char)(1 << 3) << 1), - SHUTDOWN_WAIT_CRITICAL_BUFFERS= ((unsigned char)(1 << 3) << 1) + 1, - SHUTDOWN_KILL_QUERY= 254, - SHUTDOWN_KILL_CONNECTION= 255 + SHUTDOWN_WAIT_CRITICAL_BUFFERS= ((unsigned char)(1 << 3) << 1) + 1 }; enum enum_cursor_type { diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index 614bb028a0d..b73f2d75193 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -1,5 +1,5 @@ -/* Copyright (c) 2005, 2010, Oracle and/or its affiliates - Copyright (C) 2009-2011 Monty Program Ab +/* Copyright (c) 2005, 2011, Oracle and/or its affiliates + Copyright (C) 2009, 2011, 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 @@ -72,7 +72,7 @@ typedef struct st_mysql_xid MYSQL_XID; #define MYSQL_PLUGIN_INTERFACE_VERSION 0x0103 /* MariaDB plugin interface version */ -#define MARIA_PLUGIN_INTERFACE_VERSION 0x0102 +#define MARIA_PLUGIN_INTERFACE_VERSION 0x0103 /* The allowable types of plugins diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp index dd7dde7973c..b987f690592 100644 --- a/include/mysql/plugin_audit.h.pp +++ b/include/mysql/plugin_audit.h.pp @@ -80,24 +80,8 @@ void thd_progress_next_stage(void* thd); void thd_progress_end(void* thd); const char *set_thd_proc_info(void*, const char * info, const char *func, const char *file, unsigned int line); -#include <mysql/service_logger.h> -typedef struct logger_handle_st LOGGER_HANDLE; -extern struct logger_service_st { - LOGGER_HANDLE* (*open)(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int (*close)(LOGGER_HANDLE *log); - int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); - int (*rotate)(LOGGER_HANDLE *log); -} *logger_service; - LOGGER_HANDLE *logger_open(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int logger_close(LOGGER_HANDLE *log); - int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int logger_rotate(LOGGER_HANDLE *log); - int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); +#include <mysql/service_debug_sync.h> +extern void (*debug_sync_C_callback_ptr)(void*, const char *, size_t); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp index cf3b60d128b..113aaf62d19 100644 --- a/include/mysql/plugin_auth.h.pp +++ b/include/mysql/plugin_auth.h.pp @@ -80,24 +80,8 @@ void thd_progress_next_stage(void* thd); void thd_progress_end(void* thd); const char *set_thd_proc_info(void*, const char * info, const char *func, const char *file, unsigned int line); -#include <mysql/service_logger.h> -typedef struct logger_handle_st LOGGER_HANDLE; -extern struct logger_service_st { - LOGGER_HANDLE* (*open)(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int (*close)(LOGGER_HANDLE *log); - int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); - int (*rotate)(LOGGER_HANDLE *log); -} *logger_service; - LOGGER_HANDLE *logger_open(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int logger_close(LOGGER_HANDLE *log); - int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int logger_rotate(LOGGER_HANDLE *log); - int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); +#include <mysql/service_debug_sync.h> +extern void (*debug_sync_C_callback_ptr)(void*, const char *, size_t); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp index 14129aec85e..6011e7f7519 100644 --- a/include/mysql/plugin_ftparser.h.pp +++ b/include/mysql/plugin_ftparser.h.pp @@ -80,24 +80,8 @@ void thd_progress_next_stage(void* thd); void thd_progress_end(void* thd); const char *set_thd_proc_info(void*, const char * info, const char *func, const char *file, unsigned int line); -#include <mysql/service_logger.h> -typedef struct logger_handle_st LOGGER_HANDLE; -extern struct logger_service_st { - LOGGER_HANDLE* (*open)(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int (*close)(LOGGER_HANDLE *log); - int (*vprintf)(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int (*printf)(LOGGER_HANDLE *log, const char *fmt, ...); - int (*rotate)(LOGGER_HANDLE *log); -} *logger_service; - LOGGER_HANDLE *logger_open(const char *path, - unsigned long long size_limit, - unsigned int rotations); - int logger_close(LOGGER_HANDLE *log); - int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); - int logger_rotate(LOGGER_HANDLE *log); - int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); +#include <mysql/service_debug_sync.h> +extern void (*debug_sync_C_callback_ptr)(void*, const char *, size_t); struct st_mysql_xid { long formatID; long gtrid_length; diff --git a/include/mysql/service_debug_sync.h b/include/mysql/service_debug_sync.h new file mode 100644 index 00000000000..f7bab99ac97 --- /dev/null +++ b/include/mysql/service_debug_sync.h @@ -0,0 +1,354 @@ +#ifndef MYSQL_SERVICE_DEBUG_SYNC_INCLUDED +/* Copyright (c) 2009, 2010, Oracle and/or its affiliates. + Copyright (c) 2012, 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 + == Debug Sync Facility == + + The Debug Sync Facility allows placement of synchronization points in + the server code by using the DEBUG_SYNC macro: + + open_tables(...) + + DEBUG_SYNC(thd, "after_open_tables"); + + lock_tables(...) + + When activated, a sync point can + + - Emit a signal and/or + - Wait for a signal + + Nomenclature: + + - signal: A value of a global variable that persists + until overwritten by a new signal. The global + variable can also be seen as a "signal post" + or "flag mast". Then the signal is what is + attached to the "signal post" or "flag mast". + + - emit a signal: Assign the value (the signal) to the global + variable ("set a flag") and broadcast a + global condition to wake those waiting for + a signal. + + - wait for a signal: Loop over waiting for the global condition until + the global value matches the wait-for signal. + + By default, all sync points are inactive. They do nothing (except to + burn a couple of CPU cycles for checking if they are active). + + A sync point becomes active when an action is requested for it. + To do so, put a line like this in the test case file: + + SET DEBUG_SYNC= 'after_open_tables SIGNAL opened WAIT_FOR flushed'; + + This activates the sync point 'after_open_tables'. It requests it to + emit the signal 'opened' and wait for another thread to emit the signal + 'flushed' when the thread's execution runs through the sync point. + + For every sync point there can be one action per thread only. Every + thread can request multiple actions, but only one per sync point. In + other words, a thread can activate multiple sync points. + + Here is an example how to activate and use the sync points: + + --connection conn1 + SET DEBUG_SYNC= 'after_open_tables SIGNAL opened WAIT_FOR flushed'; + send INSERT INTO t1 VALUES(1); + --connection conn2 + SET DEBUG_SYNC= 'now WAIT_FOR opened'; + SET DEBUG_SYNC= 'after_abort_locks SIGNAL flushed'; + FLUSH TABLE t1; + + When conn1 runs through the INSERT statement, it hits the sync point + 'after_open_tables'. It notices that it is active and executes its + action. It emits the signal 'opened' and waits for another thread to + emit the signal 'flushed'. + + conn2 waits immediately at the special sync point 'now' for another + thread to emit the 'opened' signal. + + A signal remains in effect until it is overwritten. If conn1 signals + 'opened' before conn2 reaches 'now', conn2 will still find the 'opened' + signal. It does not wait in this case. + + When conn2 reaches 'after_abort_locks', it signals 'flushed', which lets + conn1 awake. + + Normally the activation of a sync point is cleared when it has been + executed. Sometimes it is necessary to keep the sync point active for + another execution. You can add an execute count to the action: + + SET DEBUG_SYNC= 'name SIGNAL sig EXECUTE 3'; + + This sets the signal point's activation counter to 3. Each execution + decrements the counter. After the third execution the sync point + becomes inactive. + + One of the primary goals of this facility is to eliminate sleeps from + the test suite. In most cases it should be possible to rewrite test + cases so that they do not need to sleep. (But this facility cannot + synchronize multiple processes.) However, to support test development, + and as a last resort, sync point waiting times out. There is a default + timeout, but it can be overridden: + + SET DEBUG_SYNC= 'name WAIT_FOR sig TIMEOUT 10 EXECUTE 2'; + + TIMEOUT 0 is special: If the signal is not present, the wait times out + immediately. + + When a wait timed out (even on TIMEOUT 0), a warning is generated so + that it shows up in the test result. + + You can throw an error message and kill the query when a synchronization + point is hit a certain number of times: + + SET DEBUG_SYNC= 'name HIT_LIMIT 3'; + + Or combine it with signal and/or wait: + + SET DEBUG_SYNC= 'name SIGNAL sig EXECUTE 2 HIT_LIMIT 3'; + + Here the first two hits emit the signal, the third hit returns the error + message and kills the query. + + For cases where you are not sure that an action is taken and thus + cleared in any case, you can force to clear (deactivate) a sync point: + + SET DEBUG_SYNC= 'name CLEAR'; + + If you want to clear all actions and clear the global signal, use: + + SET DEBUG_SYNC= 'RESET'; + + This is the only way to reset the global signal to an empty string. + + For testing of the facility itself you can execute a sync point just + as if it had been hit: + + SET DEBUG_SYNC= 'name TEST'; + + + === Formal Syntax === + + The string to "assign" to the DEBUG_SYNC variable can contain: + + {RESET | + <sync point name> TEST | + <sync point name> CLEAR | + <sync point name> {{SIGNAL <signal name> | + WAIT_FOR <signal name> [TIMEOUT <seconds>]} + [EXECUTE <count>] &| HIT_LIMIT <count>} + + Here '&|' means 'and/or'. This means that one of the sections + separated by '&|' must be present or both of them. + + + === Activation/Deactivation === + + The facility is an optional part of the MySQL server. + It is enabled in a debug server by default. + + ./configure --enable-debug-sync + + The Debug Sync Facility, when compiled in, is disabled by default. It + can be enabled by a mysqld command line option: + + --debug-sync-timeout[=default_wait_timeout_value_in_seconds] + + 'default_wait_timeout_value_in_seconds' is the default timeout for the + WAIT_FOR action. If set to zero, the facility stays disabled. + + The facility is enabled by default in the test suite, but can be + disabled with: + + mysql-test-run.pl ... --debug-sync-timeout=0 ... + + Likewise the default wait timeout can be set: + + mysql-test-run.pl ... --debug-sync-timeout=10 ... + + The command line option influences the readable value of the system + variable 'debug_sync'. + + * If the facility is not compiled in, the system variable does not exist. + + * If --debug-sync-timeout=0 the value of the variable reads as "OFF". + + * Otherwise the value reads as "ON - current signal: " followed by the + current signal string, which can be empty. + + The readable variable value is the same, regardless if read as global + or session value. + + Setting the 'debug-sync' system variable requires 'SUPER' privilege. + You can never read back the string that you assigned to the variable, + unless you assign the value that the variable does already have. But + that would give a parse error. A syntactically correct string is + parsed into a debug sync action and stored apart from the variable value. + + + === Implementation === + + Pseudo code for a sync point: + + #define DEBUG_SYNC(thd, sync_point_name) + if (unlikely(opt_debug_sync_timeout)) + debug_sync(thd, STRING_WITH_LEN(sync_point_name)) + + The sync point performs a binary search in a sorted array of actions + for this thread. + + The SET DEBUG_SYNC statement adds a requested action to the array or + overwrites an existing action for the same sync point. When it adds a + new action, the array is sorted again. + + + === A typical synchronization pattern === + + There are quite a few places in MySQL, where we use a synchronization + pattern like this: + + mysql_mutex_lock(&mutex); + thd->enter_cond(&condition_variable, &mutex, new_message); + #if defined(ENABLE_DEBUG_SYNC) + if (!thd->killed && !end_of_wait_condition) + DEBUG_SYNC(thd, "sync_point_name"); + #endif + while (!thd->killed && !end_of_wait_condition) + mysql_cond_wait(&condition_variable, &mutex); + thd->exit_cond(old_message); + + Here some explanations: + + thd->enter_cond() is used to register the condition variable and the + mutex in thd->mysys_var. This is done to allow the thread to be + interrupted (killed) from its sleep. Another thread can find the + condition variable to signal and mutex to use for synchronization in + this thread's THD::mysys_var. + + thd->enter_cond() requires the mutex to be acquired in advance. + + thd->exit_cond() unregisters the condition variable and mutex and + releases the mutex. + + If you want to have a Debug Sync point with the wait, please place it + behind enter_cond(). Only then you can safely decide, if the wait will + be taken. Also you will have THD::proc_info correct when the sync + point emits a signal. DEBUG_SYNC sets its own proc_info, but restores + the previous one before releasing its internal mutex. As soon as + another thread sees the signal, it does also see the proc_info from + before entering the sync point. In this case it will be "new_message", + which is associated with the wait that is to be synchronized. + + In the example above, the wait condition is repeated before the sync + point. This is done to skip the sync point, if no wait takes place. + The sync point is before the loop (not inside the loop) to have it hit + once only. It is possible that the condition variable is signaled + multiple times without the wait condition to be true. + + A bit off-topic: At some places, the loop is taken around the whole + synchronization pattern: + + while (!thd->killed && !end_of_wait_condition) + { + mysql_mutex_lock(&mutex); + thd->enter_cond(&condition_variable, &mutex, new_message); + if (!thd->killed [&& !end_of_wait_condition]) + { + [DEBUG_SYNC(thd, "sync_point_name");] + mysql_cond_wait(&condition_variable, &mutex); + } + thd->exit_cond(old_message); + } + + Note that it is important to repeat the test for thd->killed after + enter_cond(). Otherwise the killing thread may kill this thread after + it tested thd->killed in the loop condition and before it registered + the condition variable and mutex in enter_cond(). In this case, the + killing thread does not know that this thread is going to wait on a + condition variable. It would just set THD::killed. But if we would not + test it again, we would go asleep though we are killed. If the killing + thread would kill us when we are after the second test, but still + before sleeping, we hold the mutex, which is registered in mysys_var. + The killing thread would try to acquire the mutex before signaling + the condition variable. Since the mutex is only released implicitly in + mysql_cond_wait(), the signaling happens at the right place. We + have a safe synchronization. + + === Co-work with the DBUG facility === + + When running the MySQL test suite with the --debug-dbug command line + option, the Debug Sync Facility writes trace messages to the DBUG + trace. The following shell commands proved very useful in extracting + relevant information: + + egrep 'query:|debug_sync_exec:' mysql-test/var/log/mysqld.1.trace + + It shows all executed SQL statements and all actions executed by + synchronization points. + + Sometimes it is also useful to see, which synchronization points have + been run through (hit) with or without executing actions. Then add + "|debug_sync_point:" to the egrep pattern. + + === Further reading === + + For a discussion of other methods to synchronize threads see + http://forge.mysql.com/wiki/MySQL_Internals_Test_Synchronization + + For complete syntax tests, functional tests, and examples see the test + case debug_sync.test. + + See also http://forge.mysql.com/worklog/task.php?id=4259 +*/ + +#ifndef MYSQL_ABI_CHECK +#include <stdlib.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef MYSQL_DYNAMIC_PLUGIN +extern void (*debug_sync_service)(MYSQL_THD, const char *, size_t); +#else +#define debug_sync_service debug_sync_C_callback_ptr +extern void (*debug_sync_C_callback_ptr)(MYSQL_THD, const char *, size_t); +#endif + +#ifdef ENABLED_DEBUG_SYNC +#define DEBUG_SYNC(thd, name) \ + do { \ + if (debug_sync_service) \ + debug_sync_service(thd, name, sizeof(name)-1); \ + } while(0) +#else +#define DEBUG_SYNC(thd,name) do { } while(0) +#endif + +/* compatibility macro */ +#define DEBUG_SYNC_C(name) DEBUG_SYNC(NULL, name) + +#ifdef __cplusplus +} +#endif + +#define MYSQL_SERVICE_DEBUG_SYNC_INCLUDED +#endif diff --git a/include/mysql/services.h b/include/mysql/services.h index 258f7b90658..8eb506e1c37 100644 --- a/include/mysql/services.h +++ b/include/mysql/services.h @@ -23,8 +23,7 @@ extern "C" { #include <mysql/service_thd_wait.h> #include <mysql/service_thread_scheduler.h> #include <mysql/service_progress_report.h> -#include <mysql/service_logger.h> - +#include <mysql/service_debug_sync.h> #ifdef __cplusplus } diff --git a/include/mysql_com.h b/include/mysql_com.h index b35e8961bbb..0988d20f97f 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -435,10 +435,7 @@ enum mysql_enum_shutdown_level { /* flush InnoDB buffers and other storage engines' buffers*/ SHUTDOWN_WAIT_ALL_BUFFERS= (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1), /* don't flush InnoDB buffers, flush other storage engines' buffers*/ - SHUTDOWN_WAIT_CRITICAL_BUFFERS= (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1) + 1, - /* Now the 2 levels of the KILL command */ - SHUTDOWN_KILL_QUERY= 254, - SHUTDOWN_KILL_CONNECTION= 255 + SHUTDOWN_WAIT_CRITICAL_BUFFERS= (MYSQL_SHUTDOWN_KILLABLE_UPDATE << 1) + 1 }; /* Compatibility */ diff --git a/include/service_versions.h b/include/service_versions.h index 8a397d71b12..436941643ec 100644 --- a/include/service_versions.h +++ b/include/service_versions.h @@ -24,4 +24,4 @@ #define VERSION_thd_wait 0x0100 #define VERSION_my_thread_scheduler 0x0100 #define VERSION_progress_report 0x0100 -#define VERSION_logger 0x0100 +#define VERSION_debug_sync 0x1000 diff --git a/include/welcome_copyright_notice.h b/include/welcome_copyright_notice.h index 9e40c17efca..739aeb4ede8 100644 --- a/include/welcome_copyright_notice.h +++ b/include/welcome_copyright_notice.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011, Oracle and/or its affiliates. +/* Copyright (c) 2010, 2011, 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 diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt index 754603a2964..182c8748934 100644 --- a/libmysql/CMakeLists.txt +++ b/libmysql/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2006, 2011, Oracle and/or its affiliates. +# Copyright (c) 2006, 2012, 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 diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 6603983e69b..f08159da20a 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. +# Copyright (c) 2006, 2011, 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 @@ -95,7 +95,6 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ../sql/create_options.cc ../sql/rpl_utility.cc ../sql/rpl_reporting.cc ../sql/sql_expression_cache.cc - ../sql/sql_logger.cc ${GEN_SOURCES} ${MYSYS_LIBWRAP_SOURCE} ) diff --git a/libmysqld/examples/CMakeLists.txt b/libmysqld/examples/CMakeLists.txt index e62b2a193e4..e607f3c685a 100644 --- a/libmysqld/examples/CMakeLists.txt +++ b/libmysqld/examples/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2011, 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 diff --git a/libservices/CMakeLists.txt b/libservices/CMakeLists.txt index dd16558ef9c..eb8ff7ffe09 100644 --- a/libservices/CMakeLists.txt +++ b/libservices/CMakeLists.txt @@ -21,7 +21,7 @@ SET(MYSQLSERVICES_SOURCES thd_wait_service.c my_thread_scheduler_service.c progress_report_service.c - logger_service.c) + debug_sync_service.c) ADD_CONVENIENCE_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES}) INSTALL(TARGETS mysqlservices DESTINATION ${INSTALL_LIBDIR} COMPONENT Development) diff --git a/libservices/HOWTO b/libservices/HOWTO index 7edafa89268..7dcfb6d9583 100644 --- a/libservices/HOWTO +++ b/libservices/HOWTO @@ -34,19 +34,19 @@ into a service "foo" you need to #endif extern struct foo_service_st { - int (*foo_func1_type)(...); /* fix the prototype as appropriate */ - void (*foo_func2_type)(...); /* fix the prototype as appropriate */ + int (*foo_func1_ptr)(...); /* fix the prototype as appropriate */ + void (*foo_func2_ptr)(...); /* fix the prototype as appropriate */ } *foo_service; #ifdef MYSQL_DYNAMIC_PLUGIN - #define foo_func1(...) foo_service->foo_func1_type(...) - #define foo_func2(...) foo_service->foo_func2_type(...) + #define foo_func1(...) foo_service->foo_func1_ptr(...) + #define foo_func2(...) foo_service->foo_func2_ptr(...) #else - int foo_func1_type(...); /* fix the prototype as appropriate */ - void foo_func2_type(...); /* fix the prototype as appropriate */ + int foo_func1(...); /* fix the prototype as appropriate */ + void foo_func2(...); /* fix the prototype as appropriate */ #endif @@ -64,27 +64,26 @@ include them in it, e.g. if you use size_t - #include <stdlib.h> it should also declare all the accompanying data structures, as necessary (e.g. thd_alloc_service declares MYSQL_LEX_STRING). -3. add the new file to include/Makefile.am (pkginclude_HEADERS) -4. add the new file to include/mysql/services.h -5. increase the minor plugin ABI version in include/mysql/plugin.h - (MYSQL_PLUGIN_INTERFACE_VERSION = MYSQL_PLUGIN_INTERFACE_VERSION+1) -6. add the version of your service to include/service_versions.h: +3. add the new file to include/mysql/services.h +4. increase the minor plugin ABI version in include/mysql/plugin.h + (MARIA_PLUGIN_INTERFACE_VERSION = MARIA_PLUGIN_INTERFACE_VERSION+1) +5. add the version of your service to include/service_versions.h: ================================================================== #define VERSION_foo 0x0100 ================================================================== -7. create a new file libservices/foo_service.h using the following template: +6. create a new file libservices/foo_service.h using the following template: ================================================================== /* GPL header */ #include <service_versions.h> SERVICE_VERSION *foo_service= (void*)VERSION_foo; ================================================================== -8. add the new file to libservices/CMakeLists.txt (MYSQLSERVICES_SOURCES) -9. add the new file to libservices/Makefile.am (libmysqlservices_a_SOURCES) -10. and finally, register your service for dynamic linking in - sql/sql_plugin_services.h -10.1 fill in the service structure: +7. add the new file to libservices/CMakeLists.txt (MYSQLSERVICES_SOURCES) +8. Add all new files to repository (bzr add) +9. and finally, register your service for dynamic linking in + sql/sql_plugin_services.h as follows: +9.1 fill in the service structure: ================================================================== static struct foo_service_st foo_handler = { foo_func1, @@ -92,7 +91,7 @@ it should also declare all the accompanying data structures, as necessary } ================================================================== -10.2 and add it to the list of services +9.2 and add it to the list of services ================================================================== { "foo_service", VERSION_foo, &foo_handler } diff --git a/libservices/debug_sync_service.c b/libservices/debug_sync_service.c new file mode 100644 index 00000000000..8c7f109e95a --- /dev/null +++ b/libservices/debug_sync_service.c @@ -0,0 +1,18 @@ +/* Copyright (c) 2012, 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 +*/ + +#include <service_versions.h> +SERVICE_VERSION *debug_sync_service= (void*)VERSION_debug_sync; diff --git a/mysql-test/CMakeLists.txt b/mysql-test/CMakeLists.txt index 954e9c44311..d065e8935c2 100644 --- a/mysql-test/CMakeLists.txt +++ b/mysql-test/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2011, 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 @@ -28,6 +28,10 @@ INSTALL( PATTERN ".cvsignore" EXCLUDE PATTERN "*.am" EXCLUDE PATTERN "*.in" EXCLUDE + PATTERN "*.vcxproj" EXCLUDE + PATTERN "*.vcxproj.filters" EXCLUDE + PATTERN "*.vcxproj.user" EXCLUDE + PATTERN "CTest" EXCLUDE ) ENDIF() diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index b3623402065..1f4d29968a5 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -12,7 +12,6 @@ main.signal_demo3 @solaris # Bug#11753919 2010-01-20 alik Several main.sp @solaris # Bug#11753919 2010-01-20 alik Several test cases fail on Solaris with error Thread stack overrun main.wait_timeout @solaris # Bug#11758972 2010-04-26 alik wait_timeout fails on OpenSolaris -rpl.rpl_heartbeat_basic # BUG#12403008 2011-04-27 sven fails sporadically rpl.rpl_innodb_bug28430 # Bug#11754425 rpl.rpl_row_sp011 @solaris # Bug#11753919 2011-07-25 sven Several test cases fail on Solaris with error Thread stack overrun diff --git a/mysql-test/extra/rpl_tests/rpl_insert_id_pk.test b/mysql-test/extra/rpl_tests/rpl_insert_id_pk.test index c3ecd9381c9..f6152180e7a 100644 --- a/mysql-test/extra/rpl_tests/rpl_insert_id_pk.test +++ b/mysql-test/extra/rpl_tests/rpl_insert_id_pk.test @@ -10,6 +10,8 @@ # We also check how the foreign_key_check variable is replicated -- source include/master-slave.inc +call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); + #should work for both SBR and RBR create table t1(a int auto_increment, primary key(a)); @@ -50,6 +52,7 @@ create table t2(b int auto_increment, c int, primary key(b)); insert into t1 values (10); insert into t1 values (null),(null),(null); insert into t2 values (5,0); +--disable_warnings ONCE insert into t2 (c) select * from t1 ORDER BY a; select * from t2 ORDER BY b; sync_slave_with_master; diff --git a/mysql-test/extra/rpl_tests/rpl_multi_update.test b/mysql-test/extra/rpl_tests/rpl_multi_update.test index bf7707f9d6d..cdbdbc191d7 100644 --- a/mysql-test/extra/rpl_tests/rpl_multi_update.test +++ b/mysql-test/extra/rpl_tests/rpl_multi_update.test @@ -1,5 +1,7 @@ source include/master-slave.inc; +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.'); + eval CREATE TABLE t1 ( a int unsigned not null auto_increment primary key, b int unsigned @@ -11,6 +13,7 @@ eval CREATE TABLE t2 ( ) ENGINE=$engine_type; INSERT INTO t1 VALUES (NULL, 0); +--disable_warnings ONCE INSERT INTO t1 SELECT NULL, 0 FROM t1; INSERT INTO t2 VALUES (NULL, 0), (NULL,1); @@ -18,6 +21,7 @@ INSERT INTO t2 VALUES (NULL, 0), (NULL,1); SELECT * FROM t1 ORDER BY a; SELECT * FROM t2 ORDER BY a; +--disable_warnings ONCE UPDATE t1, t2 SET t1.b = t2.b WHERE t1.a = t2.a; sync_slave_with_master; diff --git a/mysql-test/extra/rpl_tests/rpl_multi_update2.test b/mysql-test/extra/rpl_tests/rpl_multi_update2.test index ae4261c0516..b85927a2aed 100644 --- a/mysql-test/extra/rpl_tests/rpl_multi_update2.test +++ b/mysql-test/extra/rpl_tests/rpl_multi_update2.test @@ -17,6 +17,8 @@ eval CREATE TABLE t2 ( ) ENGINE=$engine_type; INSERT INTO t1 VALUES (NULL, 0); + +--disable_warnings ONCE INSERT INTO t1 SELECT NULL, 0 FROM t1; INSERT INTO t2 VALUES (NULL, 0), (NULL,1); @@ -24,6 +26,7 @@ INSERT INTO t2 VALUES (NULL, 0), (NULL,1); SELECT * FROM t1 ORDER BY a; SELECT * FROM t2 ORDER BY a; +--disable_warnings ONCE UPDATE t1, t2 SET t1.b = (t2.b+4) WHERE t1.a = t2.a; SELECT * FROM t1 ORDER BY a; SELECT * FROM t2 ORDER BY a; diff --git a/mysql-test/extra/rpl_tests/rpl_multi_update3.test b/mysql-test/extra/rpl_tests/rpl_multi_update3.test index 6c7a980aecb..f7d4815e9e5 100644 --- a/mysql-test/extra/rpl_tests/rpl_multi_update3.test +++ b/mysql-test/extra/rpl_tests/rpl_multi_update3.test @@ -18,6 +18,8 @@ eval CREATE TABLE t2 ( ) ENGINE=$engine_type; INSERT INTO t1 VALUES (NULL, 0); + +--disable_warnings ONCE INSERT INTO t1 SELECT NULL, 0 FROM t1; INSERT INTO t2 VALUES (NULL, 0), (NULL,1); @@ -25,6 +27,7 @@ INSERT INTO t2 VALUES (NULL, 0), (NULL,1); SELECT * FROM t1 ORDER BY a; SELECT * FROM t2 ORDER BY a; +--disable_warnings ONCE UPDATE t2, (SELECT a FROM t1 ORDER BY a) AS t SET t2.b = t.a+5 ; SELECT * FROM t1 ORDER BY a; SELECT * FROM t2 ORDER BY a; diff --git a/mysql-test/extra/rpl_tests/rpl_start_stop_slave.test b/mysql-test/extra/rpl_tests/rpl_start_stop_slave.test index f828c79bc6a..40bc7746ccf 100644 --- a/mysql-test/extra/rpl_tests/rpl_start_stop_slave.test +++ b/mysql-test/extra/rpl_tests/rpl_start_stop_slave.test @@ -182,7 +182,8 @@ DROP TABLE t1; sync_slave_with_master; # -# bug#3593869-64035 uninitialized event_coordinates instance crashes server +# bug#3593869-64035 attempt to read a member of event_coordinates +# referenced by NULL pointer crashes server. # Testing how out of valid range position value is handled with an error. # diff --git a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf index 18d7e11ee43..66ff188fe55 100644 --- a/mysql-test/include/default_mysqld.cnf +++ b/mysql-test/include/default_mysqld.cnf @@ -60,6 +60,8 @@ loose-performance-schema-max-table-handles=1000 binlog-direct-non-transactional-updates +default-storage-engine=myisam + # here, at the end of [mysqld] group mtr will automatically disable # all optional plugins. diff --git a/mysql-test/include/mtr_check.sql b/mysql-test/include/mtr_check.sql index bcbb9b94136..82c0514b7cd 100644 --- a/mysql-test/include/mtr_check.sql +++ b/mysql-test/include/mtr_check.sql @@ -1,4 +1,4 @@ --- Copyright (c) 2008, 2010, Oracle and/or its affiliates +-- Copyright (c) 2008, 2011, 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 diff --git a/mysql-test/include/not_crashrep.inc b/mysql-test/include/not_crashrep.inc index e126f339a5f..7e0d6c19b85 100644 --- a/mysql-test/include/not_crashrep.inc +++ b/mysql-test/include/not_crashrep.inc @@ -22,3 +22,9 @@ EOF if ($crashrep) { --skip CrashReporter would popup a window } + +# the test will crash mysqld. flush tables now to make sure that +# system tables aren't corrupted by the crash +--disable_query_log ONCE +FLUSH TABLES; + diff --git a/mysql-test/include/query_cache.inc b/mysql-test/include/query_cache.inc index 0cc1ebb21d6..29a82f112c3 100644 --- a/mysql-test/include/query_cache.inc +++ b/mysql-test/include/query_cache.inc @@ -4,6 +4,9 @@ # $engine_type -- storage engine to be tested # $test_foreign_keys -- 0, skip foreign key tests # -- 1, do not skip foreign key tests +# $partitions_a -- partition by column 'a' +# $partitions_id -- partition by column 'id' +# $partitions_s1 -- partition by column 's1' # have to be set before sourcing this script. # # Last update: @@ -19,47 +22,61 @@ eval SET SESSION STORAGE_ENGINE = $engine_type; drop table if exists t1,t2,t3; --enable_warnings +set @save_query_cache_size = @@global.query_cache_size; +set GLOBAL query_cache_size = 1355776; + # # Without auto_commit. # flush status; set autocommit=0; -create table t1 (a int not null); +eval create table t1 (a int not null)$partitions_a; insert into t1 values (1),(2),(3); +--sorted_result select * from t1; show status like "Qcache_queries_in_cache"; drop table t1; commit; set autocommit=1; begin; -create table t1 (a int not null); +eval create table t1 (a int not null)$partitions_a; insert into t1 values (1),(2),(3); +--sorted_result select * from t1; show status like "Qcache_queries_in_cache"; drop table t1; commit; -create table t1 (a int not null); -create table t2 (a int not null); -create table t3 (a int not null); +eval create table t1 (a int not null)$partitions_a; +eval create table t2 (a int not null)$partitions_a; +eval create table t3 (a int not null)$partitions_a; insert into t1 values (1),(2); insert into t2 values (1),(2); insert into t3 values (1),(2); +--sorted_result select * from t1; +--sorted_result select * from t2; +--sorted_result select * from t3; show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; begin; +--sorted_result select * from t1; +--sorted_result select * from t2; +--sorted_result select * from t3; show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; insert into t1 values (3); insert into t2 values (3); insert into t1 values (4); +--sorted_result select * from t1; +--sorted_result select * from t2; +--sorted_result select * from t3; show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; @@ -67,7 +84,7 @@ commit; show status like "Qcache_queries_in_cache"; drop table t3,t2,t1; -CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)); +eval CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id))$partitions_id; select count(*) from t1; insert into t1 (id) values (0); select count(*) from t1; @@ -78,8 +95,6 @@ if ($test_foreign_keys) # # one statement roll back inside transation # -let $save_query_cache_size=`select @@global.query_cache_size`; -set GLOBAL query_cache_size=1355776; CREATE TABLE t1 ( id int(10) NOT NULL auto_increment, a varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY a (a)); CREATE TABLE t2 ( id int(10) NOT NULL auto_increment, b varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY b (b)); CREATE TABLE t3 ( id int(10) NOT NULL auto_increment, t1_id int(10) NOT NULL default '0', t2_id int(10) NOT NULL default '0', state int(11) default NULL, PRIMARY KEY (id), UNIQUE KEY t1_id (t1_id,t2_id), KEY t2_id (t2_id,t1_id), CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`), CONSTRAINT `t3_ibfk_2` FOREIGN KEY (`t2_id`) REFERENCES `t2` (`id`)); @@ -95,9 +110,6 @@ insert into t3 VALUES ( NULL, 1, 1, 2 ); commit; select t1.* from t1, t2, t3 where t3.state & 1 = 0 and t3.t1_id = t1.id and t3.t2_id = t2.id and t1.id = 1 order by t1.a asc; drop table t3,t2,t1; ---disable_query_log -eval set GLOBAL query_cache_size=$save_query_cache_size; ---enable_query_log } # @@ -118,7 +130,7 @@ SET GLOBAL query_cache_size = 204800; flush status; SET @@autocommit=1; eval SET SESSION STORAGE_ENGINE = $engine_type; -CREATE TABLE t2 (s1 int, s2 varchar(1000), key(s1)); +eval CREATE TABLE t2 (s1 int, s2 varchar(1000), key(s1))$partitions_s1; INSERT INTO t2 VALUES (1,repeat('a',10)),(2,repeat('a',10)),(3,repeat('a',10)),(4,repeat('a',10)); COMMIT; START TRANSACTION; @@ -176,8 +188,8 @@ show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; # Final cleanup -eval set GLOBAL query_cache_size=$save_query_cache_size; disconnect connection1; --source include/wait_until_disconnected.inc connection default; +set @@global.query_cache_size = @save_query_cache_size; drop table t2; diff --git a/mysql-test/include/show_slave_hosts.inc b/mysql-test/include/show_slave_hosts.inc new file mode 100644 index 00000000000..e27c1bfb09c --- /dev/null +++ b/mysql-test/include/show_slave_hosts.inc @@ -0,0 +1,3 @@ +--replace_result $SLAVE_MYPORT SLAVE_PORT $DEFAULT_MASTER_PORT DEFAULT_PORT +--replace_regex /[0-9, a-f]{8}-[0-9, a-f]{4}-[0-9, a-f]{4}-[0-9, a-f]{4}-[0-9, a-f]{12}/SLAVE_UUID/ +SHOW SLAVE HOSTS; diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index beb0716d4a7..160fdcd935b 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -25,6 +25,8 @@ use strict; use base qw(Exporter); our @EXPORT= qw(collect_option collect_test_cases); +use Carp; + use mtr_report; use mtr_match; @@ -103,12 +105,12 @@ sub collect_test_cases ($$$$) { # If not reordering, we also shouldn't group by suites, unless # no test cases were named. - # This also effects some logic in the loop following this. + # This also affects some logic in the loop following this. if ($opt_reorder or !@$opt_cases) { foreach my $suite (split(",", $suites)) { - push(@$cases, collect_one_suite($suite, $opt_cases)); + push(@$cases, collect_suite_name($suite, $opt_cases)); } } @@ -136,7 +138,7 @@ sub collect_test_cases ($$$$) { $sname= "main" if !$opt_reorder and !$sname; mtr_error("Could not find '$tname' in '$suites' suite(s)") unless $sname; # If suite was part of name, find it there, may come with combinations - my @this_case = collect_one_suite($sname, [ $test_name_spec ]); + my @this_case = collect_suite_name($sname, [ $test_name_spec ]); if (@this_case) { push (@$cases, @this_case); @@ -310,55 +312,74 @@ sub parse_disabled { } } -sub collect_one_suite +# +# processes one user-specified suite name. +# it could contain wildcards, e.g engines/* +# +sub collect_suite_name { my $suitename= shift; # Test suite name my $opt_cases= shift; my $over; + my %suites; ($suitename, $over) = split '-', $suitename; - mtr_verbose("Collecting: $suitename"); - - my $suitedir= $::glob_mysql_test_dir; # Default - my @overlays = (); if ( $suitename ne "main" ) { # Allow suite to be path to "some dir" if $suitename has at least # one directory part - if ( -d $suitename and splitdir($suitename) > 1 ){ - $suitedir= $suitename; - mtr_report(" - from '$suitedir'"); - + if ( -d $suitename and splitdir($suitename) > 1 ) { + $suites{$suitename} = [ $suitename ]; + mtr_report(" - from '$suitename'"); } else { - @overlays = my_find_dir(dirname($::glob_mysql_test_dir), - ["mysql-test/suite", - "storage/*/mysql-test", - "plugin/*/mysql-test"], - [$suitename]); + my @dirs = my_find_dir(dirname($::glob_mysql_test_dir), + ["mysql-test/suite", + "storage/*/mysql-test", + "plugin/*/mysql-test"], + [$suitename]); # - # XXX at the moment, for simplicity, we will not fully support one plugin - # overlaying a suite of another plugin. Only suites in the main - # mysql-test directory can be safely overlayed. To be fixed, when needed. - # To fix it we'll need a smarter overlay detection (that is, detection of - # what is an overlay and what is the "original" suite) than simply - # "prefer directories with more files". + # if $suitename contained wildcards, we'll have many suites and + # their overlays here. Let's group them appropriately. # - - if ($overlays[0] !~ m@/mysql-test/suite/$suitename$@) { - # prefer directories with more files - @overlays = sort { scalar(<$a/*>) <=> scalar(<$b/*>) } @overlays; + for (@dirs) { + m@^.*/mysql-test/(?:suite/)?(.*)$@ or confess $_; + push @{$suites{$1}}, $_; } - $suitedir = shift @overlays; } } else { - @overlays = my_find_dir(dirname($::glob_mysql_test_dir), - ["storage/*/mysql-test", - "plugin/*/mysql-test"], - ['main'], NOT_REQUIRED); + $suites{$suitename} = [ $::glob_mysql_test_dir, + my_find_dir(dirname($::glob_mysql_test_dir), + ["storage/*/mysql-test", + "plugin/*/mysql-test"], + ['main'], NOT_REQUIRED) ]; + } + + my @cases; + while (my ($name, $dirs) = each %suites) { + # + # XXX at the moment, for simplicity, we will not fully support one + # plugin overlaying a suite of another plugin. Only suites in the main + # mysql-test directory can be safely overlayed. To be fixed, when + # needed. To fix it we'll need a smarter overlay detection (that is, + # detection of what is an overlay and what is the "original" suite) + # than simply "prefer directories with more files". + # + if ($dirs->[0] !~ m@/mysql-test/suite/$name$@) { + # prefer directories with more files + @$dirs = sort { scalar(<$a/*>) <=> scalar(<$b/*>) } @$dirs; + } + push @cases, collect_one_suite($opt_cases, $name, $over, @$dirs); } + return @cases; +} + +sub collect_one_suite { + my ($opt_cases, $suitename, $over, $suitedir, @overlays) = @_; + + mtr_verbose("Collecting: $suitename"); mtr_verbose("suitedir: $suitedir"); mtr_verbose("overlays: @overlays") if @overlays; @@ -380,7 +401,7 @@ sub collect_one_suite local %file_combinations = (); local %file_in_overlay = (); - die unless m@/(?:storage|plugin)/(\w+)/mysql-test/\w+$@; + confess $_ unless m@/(?:storage|plugin)/(\w+)/mysql-test/[\w/]*\w$@; next unless defined $over and ($over eq '' or $over eq $1); push @cases, # don't add cases that take *all* data from the parent suite @@ -396,7 +417,7 @@ sub process_suite { if ($overname) { $parent = $suites{$basename}; - die unless $parent; + confess unless $parent; $suitename = $basename . '-' . $overname; } else { $suitename = $basename; @@ -544,7 +565,7 @@ sub make_combinations($@) if ($combinations[0]->{skip}) { $test->{skip} = 1; $test->{comment} = $combinations[0]->{skip} unless $test->{comment}; - die unless @combinations == 1; + confess unless @combinations == 1; return ($test); } diff --git a/mysql-test/mysql-stress-test.pl b/mysql-test/mysql-stress-test.pl index 860be1c1251..74394e2afbd 100755 --- a/mysql-test/mysql-stress-test.pl +++ b/mysql-test/mysql-stress-test.pl @@ -1,5 +1,21 @@ #!/usr/bin/perl +# Copyright (c) 2005, 2011, 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 Library 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 +# Library 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 + # ====================================================================== # MySQL server stress test system # ====================================================================== diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index bfa7f2bf4e6..fd695d1129f 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1,8 +1,8 @@ #!/usr/bin/perl # -*- cperl -*- -# Copyright (c) 2004, 2011, Oracle and/or its affiliates. -# Copyright (c) 2009-2011 Monty Program Ab +# Copyright (c) 2004, 2012, Oracle and/or its affiliates. +# Copyright (c) 2009, 2012, 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 diff --git a/mysql-test/r/bug13633383.result b/mysql-test/r/bug13633383.result new file mode 100644 index 00000000000..89b522724f9 --- /dev/null +++ b/mysql-test/r/bug13633383.result @@ -0,0 +1,53 @@ +# +# Bug#13633383 63183: SMALL SORT_BUFFER_SIZE CRASH IN MERGE_BUFFERS +# +CREATE TABLE t1 ( +`a` int(11) DEFAULT NULL, +`col432` bit(8) DEFAULT NULL, +`col433` multipoint DEFAULT NULL, +`col434` polygon DEFAULT NULL, +`col435` decimal(50,17) unsigned DEFAULT NULL, +`col436` geometry NOT NULL, +`col437` tinyblob NOT NULL, +`col438` multipolygon DEFAULT NULL, +`col439` mediumblob NOT NULL, +`col440` tinyblob NOT NULL, +`col441` double unsigned DEFAULT NULL +); +CREATE TABLE t2 ( +`a` multipoint DEFAULT NULL, +`col460` date DEFAULT NULL, +`col461` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +`col462` date NOT NULL, +`col463` varbinary(89) NOT NULL, +`col464` year(4) DEFAULT NULL, +`col465` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +`col466` varchar(236) CHARACTER SET utf8 NOT NULL, +`col467` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' +); +CREATE TABLE t3 ( +`FTS_DOC_ID` bigint(20) unsigned NOT NULL, +`col577` datetime DEFAULT NULL, +`col579` bit(38) NOT NULL, +`col580` varchar(93) NOT NULL, +`col581` datetime DEFAULT NULL, +`col583` multipolygon DEFAULT NULL, +`col584` bit(47) NOT NULL +); +set session sort_buffer_size= 32768; +select col435 +from t3 +natural right outer join t1 +natural right outer join t2 a +left outer join t2 b on 1 +group by +repeat('a',10000) desc, +repeat('a',10000) +with rollup +; +col435 +0.00000000000000000 +0.00000000000000000 +0.00000000000000000 +set session sort_buffer_size= default; +DROP TABLE t1, t2, t3; diff --git a/mysql-test/r/cache_innodb.result b/mysql-test/r/cache_innodb.result index 293d7a3f412..85eef0b3418 100644 --- a/mysql-test/r/cache_innodb.result +++ b/mysql-test/r/cache_innodb.result @@ -1,5 +1,7 @@ SET SESSION STORAGE_ENGINE = InnoDB; drop table if exists t1,t2,t3; +set @save_query_cache_size = @@global.query_cache_size; +set GLOBAL query_cache_size = 1355776; flush status; set autocommit=0; create table t1 (a int not null); @@ -100,7 +102,7 @@ show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 2 drop table t3,t2,t1; -CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)); +CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)); select count(*) from t1; count(*) 0 @@ -109,7 +111,6 @@ select count(*) from t1; count(*) 1 drop table t1; -set GLOBAL query_cache_size=1355776; CREATE TABLE t1 ( id int(10) NOT NULL auto_increment, a varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY a (a)); CREATE TABLE t2 ( id int(10) NOT NULL auto_increment, b varchar(25) default NULL, PRIMARY KEY (id), UNIQUE KEY b (b)); CREATE TABLE t3 ( id int(10) NOT NULL auto_increment, t1_id int(10) NOT NULL default '0', t2_id int(10) NOT NULL default '0', state int(11) default NULL, PRIMARY KEY (id), UNIQUE KEY t1_id (t1_id,t2_id), KEY t2_id (t2_id,t1_id), CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`), CONSTRAINT `t3_ibfk_2` FOREIGN KEY (`t2_id`) REFERENCES `t2` (`id`)); @@ -218,7 +219,7 @@ Qcache_queries_in_cache 1 show status like "Qcache_hits"; Variable_name Value Qcache_hits 1 -set GLOBAL query_cache_size=1048576; +set @@global.query_cache_size = @save_query_cache_size; drop table t2; CREATE TABLE t1 (a INT) ENGINE=InnoDB; BEGIN; diff --git a/mysql-test/r/csv.result b/mysql-test/r/csv.result index b4da56cda6f..6b20add1bed 100644 --- a/mysql-test/r/csv.result +++ b/mysql-test/r/csv.result @@ -5415,6 +5415,19 @@ foo DROP TABLE t1; +CREATE TABLE t1 ( b TEXT NOT NULL ) ENGINE=MYISAM; +INSERT INTO t1 VALUES ('x'),('y'); +CREATE TABLE t2 ( a VARCHAR(1) NOT NULL ) ENGINE=CSV; +INSERT INTO t2 VALUES ('r'),('t'); +SELECT * FROM t2 ORDER BY a; +a +r +t +SELECT * FROM t1 LEFT JOIN t2 ON ( b = a ); +b a +x NULL +y NULL +drop table t1,t2; # # Test for the following cases # 1) integers and strings enclosed in quotes diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index b482e3d542c..501b9cb611b 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -4157,5 +4157,16 @@ DROP TABLE t1; SET sql_mode=default; SET NAMES latin1; # +# Bug #13832953 MY_STRNXFRM_UNICODE: ASSERTION `SRC' FAILED +# +CREATE TABLE t1 (c1 SET('','') CHARACTER SET ucs2); +Warnings: +Note 1291 Column 'c1' has duplicated value '' in SET +INSERT INTO t1 VALUES (''); +SELECT COALESCE(c1) FROM t1 ORDER BY 1; +COALESCE(c1) + +DROP TABLE t1; +# # End of 5.5 tests # diff --git a/mysql-test/r/default_storage_engine.result b/mysql-test/r/default_storage_engine.result new file mode 100644 index 00000000000..da3350c6eaf --- /dev/null +++ b/mysql-test/r/default_storage_engine.result @@ -0,0 +1 @@ +"all ok" diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index 5a3d547d6b3..32081c13376 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -2007,5 +2007,44 @@ a b gc SET SESSION optimizer_switch= @save_optimizer_switch; DROP VIEW v; DROP TABLE t1,t2; +# +# LP BUG#968720 crash due to converting to materialized and +# natural join made only once +# +SET @save968720_optimizer_switch=@@optimizer_switch; +SET optimizer_switch = 'derived_merge=on'; +CREATE TABLE t1 (a int, INDEX(a)); +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (a int, INDEX(a)); +INSERT INTO t2 VALUES (1), (2); +INSERT INTO t1 SELECT a FROM (SELECT a FROM test.t1) AS s1 NATURAL JOIN +t2 AS s2; +SELECT * FROM t1; +a +1 +1 +DELETE FROM t1; +INSERT INTO t1 VALUES (1); +PREPARE stmt FROM " +INSERT INTO t1 SELECT a FROM (SELECT a FROM test.t1) AS s1 NATURAL JOIN +t2 AS s2; +"; +EXECUTE stmt; +SELECT * FROM t1; +a +1 +1 +EXECUTE stmt; +SELECT * FROM t1; +a +1 +1 +1 +1 +drop table t1,t2; +set optimizer_switch=@save968720_optimizer_switch; +# +# end of 5.3 tests +# set optimizer_switch=@exit_optimizer_switch; set join_cache_level=@exit_join_cache_level; diff --git a/mysql-test/r/error_simulation.result b/mysql-test/r/error_simulation.result index b3fbc433247..d2f5a24ef1d 100644 --- a/mysql-test/r/error_simulation.result +++ b/mysql-test/r/error_simulation.result @@ -13,7 +13,7 @@ INSERT INTO t1 VALUES ('AAAAAAAAAH','AAAAAAAAAH'), ('AAAAAAAAAI','AAAAAAAAAI'), ('AAAAAAAAAJ','AAAAAAAAAJ'), ('AAAAAAAAAK','AAAAAAAAAK'); set tmp_table_size=1024; -set session debug_dbug="d,raise_error"; +set session debug_dbug="+d,raise_error"; SELECT MAX(a) FROM t1 GROUP BY a,b; ERROR 23000: Can't write; duplicate key in table 'tmp_table' set tmp_table_size=default; diff --git a/mysql-test/r/filesort_debug.result b/mysql-test/r/filesort_debug.result index 6759cf13502..6d6eb817259 100644 --- a/mysql-test/r/filesort_debug.result +++ b/mysql-test/r/filesort_debug.result @@ -4,7 +4,7 @@ SET @old_debug= @@session.debug; # CREATE TABLE t1(f0 int auto_increment primary key, f1 int); INSERT INTO t1(f1) VALUES (0),(1),(2),(3),(4),(5); -SET session debug_dbug= '+d,make_char_array_fail'; +SET session debug_dbug= '+d,make_sort_keys_alloc_fail'; CALL mtr.add_suppression("Out of sort memory"); SELECT * FROM t1 ORDER BY f1 ASC, f0; ERROR HY001: Out of sort memory, consider increasing server sort buffer size @@ -31,3 +31,46 @@ SET DEBUG_SYNC='now SIGNAL filesort_killed'; # connection default SET DEBUG_SYNC= "RESET"; DROP TABLE t1; +# +# Bug#13832772 ASSERTION `THD->IS_ERROR() || KILL_ERRNO' +# FAILED IN FILESORT/MYSQL_DELETE +# +CREATE TABLE t1 ( +c1 BLOB, +c2 TEXT, +c3 TEXT, +c4 TEXT, +c5 TEXT, +c6 TEXT, +c7 TEXT, +c8 BLOB, +c9 TEXT, +c19 TEXT, +pk INT, +c20 TEXT, +c21 BLOB, +c22 TEXT, +c23 TEXT, +c24 TEXT, +c25 TEXT, +c26 BLOB, +c27 TEXT, +c28 TEXT, +primary key (pk) +); +CALL mtr.add_suppression("Out of sort memory"); +DELETE IGNORE FROM t1 ORDER BY c26,c7,c23,c4,c25,c5,c20, +c19,c21,c8,c1,c27,c28,c3,c9,c22,c24,c6,c2,pk LIMIT 2; +ERROR HY001: Out of sort memory, consider increasing server sort buffer size +SHOW WARNINGS; +Level Code Message +Error 1038 Out of sort memory, consider increasing server sort buffer size +Error 1028 Sort aborted: Out of sort memory, consider increasing server sort buffer size +DELETE FROM t1 ORDER BY c26,c7,c23,c4,c25,c5,c20, +c19,c21,c8,c1,c27,c28,c3,c9,c22,c24,c6,c2,pk LIMIT 2; +ERROR HY001: Out of sort memory, consider increasing server sort buffer size +SHOW WARNINGS; +Level Code Message +Error 1038 Out of sort memory, consider increasing server sort buffer size +Error 1028 Sort aborted: Out of sort memory, consider increasing server sort buffer size +DROP TABLE t1; diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index 2c20b77a7c4..0a87f57726d 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -778,4 +778,14 @@ SELECT 1 IN (YEAR(FROM_UNIXTIME(NULL)) ,1); 1 IN (YEAR(FROM_UNIXTIME(NULL)) ,1) 1 # +# +# Bug#13012483: EXPLAIN EXTENDED, PREPARED STATEMENT, CRASH IN CHECK_SIMPLE_EQUALITY +# +CREATE TABLE t1 (a INT); +PREPARE s FROM "SELECT 1 FROM t1 WHERE 1 < ALL (SELECT @:= (1 IN (SELECT 1 FROM t1)) FROM t1)"; +EXECUTE s; +1 +DROP TABLE t1; +# End of test BUG#13012483 +# End of 5.1 tests diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index d4a071d2d63..bfc6b72caa1 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -885,18 +885,12 @@ DROP TABLE t1; select last_day('2005-00-00'); last_day('2005-00-00') NULL -Warnings: -Warning 1292 Incorrect datetime value: '2005-00-00' select last_day('2005-00-01'); last_day('2005-00-01') NULL -Warnings: -Warning 1292 Incorrect datetime value: '2005-00-01' select last_day('2005-01-00'); last_day('2005-01-00') -NULL -Warnings: -Warning 1292 Incorrect datetime value: '2005-01-00' +2005-01-31 select monthname(str_to_date(null, '%m')), monthname(str_to_date(null, '%m')), monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m')); monthname(str_to_date(null, '%m')) monthname(str_to_date(null, '%m')) monthname(str_to_date(1, '%m')) monthname(str_to_date(0, '%m')) @@ -1435,7 +1429,7 @@ NULL # DO WEEK((DATE_ADD((CAST(0 AS DATE)), INTERVAL 1 YEAR_MONTH)), 5); Warnings: -Warning 1292 Truncated incorrect date value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0' # # BUG#13458237 INCONSISTENT HANDLING OF INVALIDE DATES WITH ZERO DAY # SIMILAR TO '2009-10-00' @@ -1469,9 +1463,9 @@ TO_DAYs(DATE'2009-10-00'), TO_DAYs(STR_TO_DATE('200910','%Y%m')); DATE('20091000') 2009-10-00 STR_TO_DATE('200910','%Y%m') 2009-10-00 -LAST_DAY('2009-10-00') NULL -LAST_DAY(DATE('2009-10-00')) NULL -LAST_DAY(DATE'2009-10-00') NULL +LAST_DAY('2009-10-00') 2009-10-31 +LAST_DAY(DATE('2009-10-00')) 2009-10-31 +LAST_DAY(DATE'2009-10-00') 2009-10-31 LAST_DAY(STR_TO_DATE('200910','%Y%m')) 2009-10-31 WEEK('2009-10-00') NULL WEEK(DATE('2009-10-00')) NULL @@ -1499,18 +1493,9 @@ Code 1292 Message Incorrect datetime value: '2009-10-00' Level Warning Code 1292 -Message Truncated incorrect date value: '2009-10-00' -Level Warning -Code 1292 -Message Incorrect datetime value: '2009-10-00' -Level Warning -Code 1292 Message Incorrect datetime value: '2009-10-00' Level Warning Code 1292 -Message Truncated incorrect date value: '2009-10-00' -Level Warning -Code 1292 Message Incorrect datetime value: '2009-10-00' Level Warning Code 1411 @@ -1520,7 +1505,7 @@ Code 1292 Message Incorrect datetime value: '2009-10-00' Level Warning Code 1292 -Message Truncated incorrect date value: '2009-10-00' +Message Incorrect datetime value: '2009-10-00' Level Warning Code 1292 Message Incorrect datetime value: '2009-10-00' @@ -1532,7 +1517,7 @@ Code 1292 Message Incorrect datetime value: '2009-10-00' Level Warning Code 1292 -Message Truncated incorrect date value: '2009-10-00' +Message Incorrect datetime value: '2009-10-00' Level Warning Code 1292 Message Incorrect datetime value: '2009-10-00' @@ -1544,7 +1529,7 @@ Code 1292 Message Incorrect datetime value: '2009-10-00' Level Warning Code 1292 -Message Truncated incorrect date value: '2009-10-00' +Message Incorrect datetime value: '2009-10-00' Level Warning Code 1292 Message Incorrect datetime value: '2009-10-00' @@ -1556,7 +1541,7 @@ Code 1292 Message Incorrect datetime value: '2009-10-00' Level Warning Code 1292 -Message Truncated incorrect date value: '2009-10-00' +Message Incorrect datetime value: '2009-10-00' Level Warning Code 1292 Message Incorrect datetime value: '2009-10-00' @@ -1592,9 +1577,9 @@ TO_DAYs(DATE'0000-01-00'), TO_DAYs(STR_TO_DATE('000001','%Y%m')); DATE('00000100') 0000-01-00 STR_TO_DATE('000001','%Y%m') 0000-01-00 -LAST_DAY('0000-01-00') NULL -LAST_DAY(DATE('0000-01-00')) NULL -LAST_DAY(DATE'0000-01-00') NULL +LAST_DAY('0000-01-00') 0000-01-31 +LAST_DAY(DATE('0000-01-00')) 0000-01-31 +LAST_DAY(DATE'0000-01-00') 0000-01-31 LAST_DAY(STR_TO_DATE('000001','%Y%m')) 0000-01-31 WEEK('0000-01-00') NULL WEEK(DATE('0000-01-00')) NULL @@ -1622,18 +1607,9 @@ Code 1292 Message Incorrect datetime value: '0000-01-00' Level Warning Code 1292 -Message Truncated incorrect date value: '0000-01-00' -Level Warning -Code 1292 -Message Incorrect datetime value: '0000-01-00' -Level Warning -Code 1292 Message Incorrect datetime value: '0000-01-00' Level Warning Code 1292 -Message Truncated incorrect date value: '0000-01-00' -Level Warning -Code 1292 Message Incorrect datetime value: '0000-01-00' Level Warning Code 1411 @@ -1643,7 +1619,7 @@ Code 1292 Message Incorrect datetime value: '0000-01-00' Level Warning Code 1292 -Message Truncated incorrect date value: '0000-01-00' +Message Incorrect datetime value: '0000-01-00' Level Warning Code 1292 Message Incorrect datetime value: '0000-01-00' @@ -1655,7 +1631,7 @@ Code 1292 Message Incorrect datetime value: '0000-01-00' Level Warning Code 1292 -Message Truncated incorrect date value: '0000-01-00' +Message Incorrect datetime value: '0000-01-00' Level Warning Code 1292 Message Incorrect datetime value: '0000-01-00' @@ -1667,7 +1643,7 @@ Code 1292 Message Incorrect datetime value: '0000-01-00' Level Warning Code 1292 -Message Truncated incorrect date value: '0000-01-00' +Message Incorrect datetime value: '0000-01-00' Level Warning Code 1292 Message Incorrect datetime value: '0000-01-00' @@ -1679,7 +1655,7 @@ Code 1292 Message Incorrect datetime value: '0000-01-00' Level Warning Code 1292 -Message Truncated incorrect date value: '0000-01-00' +Message Incorrect datetime value: '0000-01-00' Level Warning Code 1292 Message Incorrect datetime value: '0000-01-00' @@ -1912,7 +1888,7 @@ select timestampadd(week, 1, date("0000-00-00")); timestampadd(week, 1, date("0000-00-00")) NULL Warnings: -Warning 1292 Truncated incorrect date value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' drop table t1; create table t1 (f2 time not null, f3 datetime, f4 int not null, f5 timestamp); insert ignore t1 values ('04:38:11','0000-00-00 00:00:00',0,'0000-00-00 00:00:00'); diff --git a/mysql-test/r/information_schema_all_engines.result b/mysql-test/r/information_schema_all_engines.result index 9304febcc5a..7d47f0404bb 100644 --- a/mysql-test/r/information_schema_all_engines.result +++ b/mysql-test/r/information_schema_all_engines.result @@ -13,9 +13,26 @@ FILES GLOBAL_STATUS GLOBAL_VARIABLES INDEX_STATISTICS +INNODB_BUFFER_POOL_PAGES +INNODB_BUFFER_POOL_PAGES_BLOB +INNODB_BUFFER_POOL_PAGES_INDEX +INNODB_CMP INNODB_CMPMEM +INNODB_CMPMEM_RESET +INNODB_CMP_RESET +INNODB_INDEX_STATS INNODB_LOCKS +INNODB_LOCK_WAITS +INNODB_RSEG +INNODB_SYS_COLUMNS +INNODB_SYS_FIELDS +INNODB_SYS_FOREIGN +INNODB_SYS_FOREIGN_COLS INNODB_SYS_INDEXES +INNODB_SYS_STATS +INNODB_SYS_TABLES +INNODB_SYS_TABLESTATS +INNODB_TABLE_STATS INNODB_TRX KEY_CACHES KEY_COLUMN_USAGE @@ -68,9 +85,26 @@ FILES TABLE_SCHEMA GLOBAL_STATUS VARIABLE_NAME GLOBAL_VARIABLES VARIABLE_NAME INDEX_STATISTICS TABLE_SCHEMA +INNODB_BUFFER_POOL_PAGES page_type +INNODB_BUFFER_POOL_PAGES_BLOB space_id +INNODB_BUFFER_POOL_PAGES_INDEX index_id +INNODB_CMP page_size INNODB_CMPMEM page_size +INNODB_CMPMEM_RESET page_size +INNODB_CMP_RESET page_size +INNODB_INDEX_STATS table_schema INNODB_LOCKS lock_id +INNODB_LOCK_WAITS requesting_trx_id +INNODB_RSEG rseg_id +INNODB_SYS_COLUMNS TABLE_ID +INNODB_SYS_FIELDS INDEX_ID +INNODB_SYS_FOREIGN ID +INNODB_SYS_FOREIGN_COLS ID INNODB_SYS_INDEXES INDEX_ID +INNODB_SYS_STATS INDEX_ID +INNODB_SYS_TABLES SCHEMA +INNODB_SYS_TABLESTATS SCHEMA +INNODB_TABLE_STATS table_schema INNODB_TRX trx_id KEY_CACHES KEY_CACHE_NAME KEY_COLUMN_USAGE CONSTRAINT_SCHEMA @@ -123,9 +157,26 @@ FILES TABLE_SCHEMA GLOBAL_STATUS VARIABLE_NAME GLOBAL_VARIABLES VARIABLE_NAME INDEX_STATISTICS TABLE_SCHEMA +INNODB_BUFFER_POOL_PAGES page_type +INNODB_BUFFER_POOL_PAGES_BLOB space_id +INNODB_BUFFER_POOL_PAGES_INDEX index_id +INNODB_CMP page_size INNODB_CMPMEM page_size +INNODB_CMPMEM_RESET page_size +INNODB_CMP_RESET page_size +INNODB_INDEX_STATS table_schema INNODB_LOCKS lock_id +INNODB_LOCK_WAITS requesting_trx_id +INNODB_RSEG rseg_id +INNODB_SYS_COLUMNS TABLE_ID +INNODB_SYS_FIELDS INDEX_ID +INNODB_SYS_FOREIGN ID +INNODB_SYS_FOREIGN_COLS ID INNODB_SYS_INDEXES INDEX_ID +INNODB_SYS_STATS INDEX_ID +INNODB_SYS_TABLES SCHEMA +INNODB_SYS_TABLESTATS SCHEMA +INNODB_TABLE_STATS table_schema INNODB_TRX trx_id KEY_CACHES KEY_CACHE_NAME KEY_COLUMN_USAGE CONSTRAINT_SCHEMA @@ -184,9 +235,26 @@ FILES information_schema.FILES 1 GLOBAL_STATUS information_schema.GLOBAL_STATUS 1 GLOBAL_VARIABLES information_schema.GLOBAL_VARIABLES 1 INDEX_STATISTICS information_schema.INDEX_STATISTICS 1 +INNODB_BUFFER_POOL_PAGES information_schema.INNODB_BUFFER_POOL_PAGES 1 +INNODB_BUFFER_POOL_PAGES_BLOB information_schema.INNODB_BUFFER_POOL_PAGES_BLOB 1 +INNODB_BUFFER_POOL_PAGES_INDEX information_schema.INNODB_BUFFER_POOL_PAGES_INDEX 1 +INNODB_CMP information_schema.INNODB_CMP 1 INNODB_CMPMEM information_schema.INNODB_CMPMEM 1 +INNODB_CMPMEM_RESET information_schema.INNODB_CMPMEM_RESET 1 +INNODB_CMP_RESET information_schema.INNODB_CMP_RESET 1 +INNODB_INDEX_STATS information_schema.INNODB_INDEX_STATS 1 INNODB_LOCKS information_schema.INNODB_LOCKS 1 +INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1 +INNODB_RSEG information_schema.INNODB_RSEG 1 +INNODB_SYS_COLUMNS information_schema.INNODB_SYS_COLUMNS 1 +INNODB_SYS_FIELDS information_schema.INNODB_SYS_FIELDS 1 +INNODB_SYS_FOREIGN information_schema.INNODB_SYS_FOREIGN 1 +INNODB_SYS_FOREIGN_COLS information_schema.INNODB_SYS_FOREIGN_COLS 1 INNODB_SYS_INDEXES information_schema.INNODB_SYS_INDEXES 1 +INNODB_SYS_STATS information_schema.INNODB_SYS_STATS 1 +INNODB_SYS_TABLES information_schema.INNODB_SYS_TABLES 1 +INNODB_SYS_TABLESTATS information_schema.INNODB_SYS_TABLESTATS 1 +INNODB_TABLE_STATS information_schema.INNODB_TABLE_STATS 1 INNODB_TRX information_schema.INNODB_TRX 1 KEY_CACHES information_schema.KEY_CACHES 1 KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1 @@ -228,9 +296,26 @@ Database: information_schema | GLOBAL_STATUS | | GLOBAL_VARIABLES | | INDEX_STATISTICS | +| INNODB_BUFFER_POOL_PAGES | +| INNODB_BUFFER_POOL_PAGES_BLOB | +| INNODB_BUFFER_POOL_PAGES_INDEX | +| INNODB_CMP | | INNODB_CMPMEM | +| INNODB_CMPMEM_RESET | +| INNODB_CMP_RESET | +| INNODB_INDEX_STATS | | INNODB_LOCKS | +| INNODB_LOCK_WAITS | +| INNODB_RSEG | +| INNODB_SYS_COLUMNS | +| INNODB_SYS_FIELDS | +| INNODB_SYS_FOREIGN | +| INNODB_SYS_FOREIGN_COLS | | INNODB_SYS_INDEXES | +| INNODB_SYS_STATS | +| INNODB_SYS_TABLES | +| INNODB_SYS_TABLESTATS | +| INNODB_TABLE_STATS | | INNODB_TRX | | KEY_CACHES | | KEY_COLUMN_USAGE | @@ -273,9 +358,26 @@ Database: INFORMATION_SCHEMA | GLOBAL_STATUS | | GLOBAL_VARIABLES | | INDEX_STATISTICS | +| INNODB_BUFFER_POOL_PAGES | +| INNODB_BUFFER_POOL_PAGES_BLOB | +| INNODB_BUFFER_POOL_PAGES_INDEX | +| INNODB_CMP | | INNODB_CMPMEM | +| INNODB_CMPMEM_RESET | +| INNODB_CMP_RESET | +| INNODB_INDEX_STATS | | INNODB_LOCKS | +| INNODB_LOCK_WAITS | +| INNODB_RSEG | +| INNODB_SYS_COLUMNS | +| INNODB_SYS_FIELDS | +| INNODB_SYS_FOREIGN | +| INNODB_SYS_FOREIGN_COLS | | INNODB_SYS_INDEXES | +| INNODB_SYS_STATS | +| INNODB_SYS_TABLES | +| INNODB_SYS_TABLESTATS | +| INNODB_TABLE_STATS | | INNODB_TRX | | KEY_CACHES | | KEY_COLUMN_USAGE | @@ -309,5 +411,5 @@ Wildcard: inf_rmation_schema | information_schema | SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA; table_schema count(*) -information_schema 40 +information_schema 57 mysql 23 diff --git a/mysql-test/r/innodb_ext_key.result b/mysql-test/r/innodb_ext_key.result index 0cdfb4f57a7..d2fb29a023c 100644 --- a/mysql-test/r/innodb_ext_key.result +++ b/mysql-test/r/innodb_ext_key.result @@ -681,9 +681,9 @@ SELECT a FROM t1 AS t, t2 WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t index a,b b 7 NULL 10 Using index -1 PRIMARY t1 ref b b 3 test.t.b 2 Using index; FirstMatch(t) +1 PRIMARY t1 ref b b 3 test.t.b 2 Using index +1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t) 1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t.a 1 Using index -1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t2) SELECT a FROM t1 AS t, t2 WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b); a @@ -694,9 +694,9 @@ SELECT a FROM t1 AS t, t2 WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t index a,b b 7 NULL 10 Using index -1 PRIMARY t1 ref b b 3 test.t.b 2 Using index; FirstMatch(t) +1 PRIMARY t1 ref b b 3 test.t.b 2 Using index +1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t) 1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t.a 1 Using index -1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t2) SELECT a FROM t1 AS t, t2 WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b); a diff --git a/mysql-test/r/innodb_icp,innodb_plugin.rdiff b/mysql-test/r/innodb_icp,innodb_plugin.rdiff index 08e16944fba..c74a8473486 100644 --- a/mysql-test/r/innodb_icp,innodb_plugin.rdiff +++ b/mysql-test/r/innodb_icp,innodb_plugin.rdiff @@ -31,18 +31,18 @@ 4 4 show status like "Handler_icp%"; Variable_name Value --Handler_icp_attempts 2 +-Handler_icp_attempts 2 -Handler_icp_match 1 -+Handler_icp_attempts 0 ++Handler_icp_attempts 0 +Handler_icp_match 0 SELECT * FROM t1 WHERE (c2='3' or c2='4') and c2 % 2 = 0 ; c1 c2 4 4 show status like "Handler_icp%"; Variable_name Value --Handler_icp_attempts 2 +-Handler_icp_attempts 2 -Handler_icp_match 1 -+Handler_icp_attempts 0 ++Handler_icp_attempts 0 +Handler_icp_match 0 DROP TABLE t1; # diff --git a/mysql-test/r/innodb_icp.result b/mysql-test/r/innodb_icp.result index 5b4b09df1fe..c1d3fa3445d 100644 --- a/mysql-test/r/innodb_icp.result +++ b/mysql-test/r/innodb_icp.result @@ -818,21 +818,21 @@ INSERT INTO t1 VALUES ('3', '3'),('4','4'),('5','5'); flush status; show status like "Handler_icp%"; Variable_name Value -Handler_icp_attempts 0 +Handler_icp_attempts 0 Handler_icp_match 0 SELECT * FROM t1 FORCE INDEX(c1) WHERE (c1='3' or c1='4') and c1 % 2 = 0 ; c1 c2 4 4 show status like "Handler_icp%"; Variable_name Value -Handler_icp_attempts 2 +Handler_icp_attempts 2 Handler_icp_match 1 SELECT * FROM t1 WHERE (c2='3' or c2='4') and c2 % 2 = 0 ; c1 c2 4 4 show status like "Handler_icp%"; Variable_name Value -Handler_icp_attempts 2 +Handler_icp_attempts 2 Handler_icp_match 1 DROP TABLE t1; # diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index bd661859929..ba16d7dd9de 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -1402,4 +1402,74 @@ select t2.i from t1 left join t2 on t2.i = t1.i where t1.i = '1:1:1'; i 01:01:01 drop table t1,t2; +# +# BUG#954900: unexpected empty set due to an invalid build of key ref +# +CREATE TABLE t1 (dog_id int(10), birthday date, PRIMARY KEY (dog_id,birthday)); +INSERT INTO t1 VALUES (5918,'2004-07-22'); +CREATE TABLE t2 (dog_id int(10) unsigned, t_id char(1), birthday date, a_id int(10), +PRIMARY KEY (dog_id,t_id,birthday,a_id)); +INSERT INTO t2 VALUES +(5918,'N','2004-07-22',5216551), (5918,'N','2004-07-22',5223640), +(5918,'N','2004-07-22',5389491), (5918,'N','2004-07-22',5749434), +(5918,'N','2004-07-22',5992424), (5922,'N','2005-06-30',5076957), +(5924,'N','2000-08-11',20264), (5924,'N','2000-08-11',64251), +(5924,'N','2000-08-11',74748), (5924,'N','2000-08-11',87590), +(5924,'N','2000-08-11',104695), (5924,'N','2000-08-11',133136), +(5924,'N','2000-08-11',5027806), (5924,'N','2000-08-11',5076957), +(5924,'N','2000-08-11',5166821), (5924,'N','2000-08-11',5181896), +(5924,'N','2000-08-11',5217908), (5924,'N','2000-08-11',5220812), +(5924,'N','2000-08-11',5226473), (5924,'N','2000-08-11',5339111), +(5925,'N','2005-02-10',19227), (5925,'N','2005-02-10',74529), +(5925,'N','2005-02-10',74748), (5927,'N','2005-08-18',20264), +(5927,'N','2005-08-18',58364), (5929,'N','2005-01-19',58364), +(5935,'N','2006-03-10',19227), (5935,'N','2006-03-10',64251), +(5935,'N','2006-03-10',5222400), (5935,'N','2006-03-10',5226473), +(5936,'N','2004-10-29',5015032), (5937,'N','2002-04-05',11237), +(5937,'N','2002-04-05',23911), (5937,'N','2002-04-05',112133), +(5937,'N','2002-04-05',169721), (5937,'N','2002-04-05',170650), +(5937,'N','2002-04-05',5014494), (5937,'N','2002-04-05',5166009), +(5937,'N','2002-04-05',5181871), (5937,'N','2002-04-05',5213380), +(5937,'N','2002-04-05',5214875), (5937,'N','2002-04-05',5895062), +(5938,'N','2006-03-24',11237), (5938,'N','2006-03-24',19227), +(5938,'N','2006-03-24',23911), (5938,'N','2006-03-24',58364), +(5938,'N','2006-03-24',64251), (5938,'N','2006-03-24',111716), +(5938,'N','2006-03-24',112702), (5938,'N','2006-03-24',133136), +(5938,'N','2006-03-24',168718), (5938,'N','2006-03-24',5137136), +(5938,'N','2006-03-24',5161519), (5938,'N','2006-03-24',5168120), +(5938,'N','2006-03-24',5219034), (6234,'N','2006-06-02',103058), +(6234,'N','2006-06-02',5146844), (6235,'N','2006-06-01',12900), +(6235,'N','2006-06-01',20264), (6235,'N','2006-06-01',64251), +(6235,'N','2006-06-01',75160), (6235,'N','2006-06-01',5014494), +(6235,'N','2006-06-01',5181638), (6236,'N','2006-06-06',112595), +(6236,'N','2006-06-06',5219601), (6236,'N','2006-06-06',5808374); +CREATE TABLE t3 (dog_id int(10) unsigned); +INSERT INTO t3 VALUES (5918); +CREATE TABLE t4 (dog_id int(10), t_id char(1), birthday date, KEY (t_id)); +INSERT INTO t4 VALUES (5918,'N','2004-07-22'), (5919,'N','2004-07-20'); +CREATE TABLE t5 (dog_id int(10) unsigned, UNIQUE KEY (dog_id)); +INSERT INTO t5 VALUES (5918); +SET @tmp_optimizer_switch=@@optimizer_switch; +SET optimizer_switch='index_condition_pushdown=off'; +EXPLAIN +SELECT * FROM t5 DU, t1 D, t4 DT, t2 DSA, t3 DSAR +WHERE DU.dog_id=D.dog_id AND D.dog_id=DT.dog_id AND D.birthday=DT.birthday AND +DT.t_id=DSA.t_id AND DT.birthday=DSA.birthday AND DSA.dog_id=DSAR.dog_id; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE DU system dog_id NULL NULL NULL 1 +1 SIMPLE D system PRIMARY NULL NULL NULL 1 +1 SIMPLE DSAR system NULL NULL NULL NULL 1 +1 SIMPLE DT range t_id t_id 2 NULL 2 Using where +1 SIMPLE DSA ref PRIMARY PRIMARY 8 const,test.DT.t_id,test.D.birthday 1 Using index +SELECT * FROM t5 DU, t1 D, t4 DT, t2 DSA, t3 DSAR +WHERE DU.dog_id=D.dog_id AND D.dog_id=DT.dog_id AND D.birthday=DT.birthday AND +DT.t_id=DSA.t_id AND DT.birthday=DSA.birthday AND DSA.dog_id=DSAR.dog_id; +dog_id dog_id birthday dog_id t_id birthday dog_id t_id birthday a_id dog_id +5918 5918 2004-07-22 5918 N 2004-07-22 5918 N 2004-07-22 5216551 5918 +5918 5918 2004-07-22 5918 N 2004-07-22 5918 N 2004-07-22 5223640 5918 +5918 5918 2004-07-22 5918 N 2004-07-22 5918 N 2004-07-22 5389491 5918 +5918 5918 2004-07-22 5918 N 2004-07-22 5918 N 2004-07-22 5749434 5918 +5918 5918 2004-07-22 5918 N 2004-07-22 5918 N 2004-07-22 5992424 5918 +SET optimizer_switch=@tmp_optimizer_switch; +DROP TABLE t1,t2,t3,t4,t5; SET optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result index d926ebcfc2b..0892ce7794a 100644 --- a/mysql-test/r/join_cache.result +++ b/mysql-test/r/join_cache.result @@ -3522,7 +3522,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref f1 f1 4 test.t1.f1 3 Using index condition(BKA); Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan show status like "Handler_icp%"; Variable_name Value -Handler_icp_attempts 20 +Handler_icp_attempts 20 Handler_icp_match 4 set join_cache_level=6; select t2.f1, t2.f2, t2.f3 from t1,t2 @@ -3539,7 +3539,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref f1 f1 4 test.t1.f1 3 Using index condition(BKA); Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan show status like "Handler_icp%"; Variable_name Value -Handler_icp_attempts 40 +Handler_icp_attempts 40 Handler_icp_match 8 set join_cache_level=7; select t2.f1, t2.f2, t2.f3 from t1,t2 @@ -3556,7 +3556,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref f1 f1 4 test.t1.f1 3 Using index condition(BKA); Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan show status like "Handler_icp%"; Variable_name Value -Handler_icp_attempts 60 +Handler_icp_attempts 60 Handler_icp_match 12 set join_cache_level=8; select t2.f1, t2.f2, t2.f3 from t1,t2 @@ -3573,7 +3573,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref f1 f1 4 test.t1.f1 3 Using index condition(BKA); Using where; Using join buffer (flat, BKAH join); Key-ordered Rowid-ordered scan show status like "Handler_icp%"; Variable_name Value -Handler_icp_attempts 80 +Handler_icp_attempts 80 Handler_icp_match 16 drop table t1,t2; set join_cache_level=default; @@ -5261,8 +5261,8 @@ SET join_cache_level=0; EXPLAIN SELECT * FROM (SELECT t1.* FROM t1, t2) t WHERE t.a IN (SELECT * FROM t3); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 -1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 Using where +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 +1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 3 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 2 DERIVED t1 ALL NULL NULL NULL NULL 2 2 DERIVED t2 ALL NULL NULL NULL NULL 2 @@ -5480,8 +5480,8 @@ EXPLAIN SELECT * FROM t1 WHERE t1.i IN (SELECT t3.i FROM t3 LEFT JOIN t2 ON t2.i=t3.i); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 -1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 2 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 1 Using where SELECT * FROM t1 WHERE t1.i IN @@ -5494,8 +5494,8 @@ EXPLAIN SELECT * FROM t1 WHERE t1.i IN (SELECT t3.i FROM t3 LEFT JOIN t2 ON t2.i=t3.i); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 -1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 2 MATERIALIZED t3 ALL NULL NULL NULL NULL 2 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (flat, BNL join) SELECT * FROM t1 WHERE t1.i IN diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 163043c2cef..ebe8255fd8b 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -1648,6 +1648,64 @@ NULL NULL NULL DROP TABLE h,m,k; + +# BUG#12567331 - INFINITE LOOP WHEN RESOLVING AN ALIASED COLUMN +# USED IN GROUP BY + +CREATE TABLE t1 ( +col_varchar_1024_latin1_key varchar(1024), +col_varchar_10_latin1 varchar(10), +col_int int(11), +pk int(11) +); +CREATE TABLE t2 ( +col_int_key int(11), +col_int int(11), +pk int(11) +); +PREPARE prep_stmt_9846 FROM ' +SELECT alias1.pk AS field1 FROM +t1 AS alias1 +LEFT JOIN +( + t2 AS alias2 + RIGHT JOIN + ( + t2 AS alias3 + JOIN t1 AS alias4 + ON 1 + ) + ON 1 +) +ON 1 +GROUP BY field1'; +execute prep_stmt_9846; +field1 +execute prep_stmt_9846; +field1 +drop table t1,t2; +# +# Bug #11765810 58813: SERVER THREAD HANGS WHEN JOIN + WHERE + GROUP BY +# IS EXECUTED TWICE FROM P +# +CREATE TABLE t1 ( a INT ) ENGINE = MYISAM; +INSERT INTO t1 VALUES (1); +PREPARE prep_stmt FROM ' + SELECT 1 AS f FROM t1 + LEFT JOIN t1 t2 + RIGHT JOIN t1 t3 + JOIN t1 t4 + ON 1 + ON 1 + ON 1 + GROUP BY f'; +EXECUTE prep_stmt; +f +1 +EXECUTE prep_stmt; +f +1 +DROP TABLE t1; # # Bug#49600: outer join of two single-row tables with joining attributes # evaluated to nulls diff --git a/mysql-test/r/join_outer_jcl6.result b/mysql-test/r/join_outer_jcl6.result index b29c6241f14..3d0e4cbfc79 100644 --- a/mysql-test/r/join_outer_jcl6.result +++ b/mysql-test/r/join_outer_jcl6.result @@ -1659,6 +1659,64 @@ NULL NULL NULL DROP TABLE h,m,k; + +# BUG#12567331 - INFINITE LOOP WHEN RESOLVING AN ALIASED COLUMN +# USED IN GROUP BY + +CREATE TABLE t1 ( +col_varchar_1024_latin1_key varchar(1024), +col_varchar_10_latin1 varchar(10), +col_int int(11), +pk int(11) +); +CREATE TABLE t2 ( +col_int_key int(11), +col_int int(11), +pk int(11) +); +PREPARE prep_stmt_9846 FROM ' +SELECT alias1.pk AS field1 FROM +t1 AS alias1 +LEFT JOIN +( + t2 AS alias2 + RIGHT JOIN + ( + t2 AS alias3 + JOIN t1 AS alias4 + ON 1 + ) + ON 1 +) +ON 1 +GROUP BY field1'; +execute prep_stmt_9846; +field1 +execute prep_stmt_9846; +field1 +drop table t1,t2; +# +# Bug #11765810 58813: SERVER THREAD HANGS WHEN JOIN + WHERE + GROUP BY +# IS EXECUTED TWICE FROM P +# +CREATE TABLE t1 ( a INT ) ENGINE = MYISAM; +INSERT INTO t1 VALUES (1); +PREPARE prep_stmt FROM ' + SELECT 1 AS f FROM t1 + LEFT JOIN t1 t2 + RIGHT JOIN t1 t3 + JOIN t1 t4 + ON 1 + ON 1 + ON 1 + GROUP BY f'; +EXECUTE prep_stmt; +f +1 +EXECUTE prep_stmt; +f +1 +DROP TABLE t1; # # Bug#49600: outer join of two single-row tables with joining attributes # evaluated to nulls diff --git a/mysql-test/r/maria_icp.result b/mysql-test/r/maria_icp.result index 2d0110f2f35..feca63402a4 100644 --- a/mysql-test/r/maria_icp.result +++ b/mysql-test/r/maria_icp.result @@ -824,21 +824,21 @@ INSERT INTO t1 VALUES ('3', '3'),('4','4'),('5','5'); flush status; show status like "Handler_icp%"; Variable_name Value -Handler_icp_attempts 0 +Handler_icp_attempts 0 Handler_icp_match 0 SELECT * FROM t1 FORCE INDEX(c1) WHERE (c1='3' or c1='4') and c1 % 2 = 0 ; c1 c2 4 4 show status like "Handler_icp%"; Variable_name Value -Handler_icp_attempts 2 +Handler_icp_attempts 2 Handler_icp_match 1 SELECT * FROM t1 WHERE (c2='3' or c2='4') and c2 % 2 = 0 ; c1 c2 4 4 show status like "Handler_icp%"; Variable_name Value -Handler_icp_attempts 2 +Handler_icp_attempts 2 Handler_icp_match 1 DROP TABLE t1; set storage_engine= @save_storage_engine; diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index ca72521a819..e991326cdce 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -1,3 +1,4 @@ +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); drop table if exists t1,t2,t3; drop database if exists mysqltest; drop view if exists v1; @@ -605,7 +606,8 @@ a b show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `test`; UPDATE t2,t1 SET t2.a=t1.a+2 +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Update_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT delete from t1; delete from t2; @@ -617,7 +619,8 @@ ERROR 23000: Duplicate entry '4' for key 'PRIMARY' show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `test`; UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a +master-bin.000001 # Table_map # # table_id: # (test.t2) +master-bin.000001 # Update_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT drop table t1, t2; set @@session.binlog_format= @sav_binlog_format; diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 2a2197e7f98..64c61d4ee36 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -2494,6 +2494,19 @@ Table Op Msg_type Msg_text test.t1 check status OK DROP TABLE t1; SET GLOBAL myisam_use_mmap=default; +# +# BUG 11756869 - 48848: MYISAMCHK DOING SORT RECOVER IN CERTAIN +# CASES RESETS DATA POINTER TO SMAL +# +CREATE TABLE t1(a INT, KEY(a)); +ALTER TABLE t1 DISABLE KEYS; +SET @before:= (SELECT MAX_DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test'); +FLUSH TABLES; +SET @after:= (SELECT MAX_DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test'); +SELECT @before=@after; +@before=@after +1 +DROP TABLE t1; End of 5.1 tests # # Bug#51327 MyISAM table is automatically repaired on ALTER diff --git a/mysql-test/r/myisam_icp.result b/mysql-test/r/myisam_icp.result index f1a2af264a3..a8355db55e0 100644 --- a/mysql-test/r/myisam_icp.result +++ b/mysql-test/r/myisam_icp.result @@ -822,21 +822,21 @@ INSERT INTO t1 VALUES ('3', '3'),('4','4'),('5','5'); flush status; show status like "Handler_icp%"; Variable_name Value -Handler_icp_attempts 0 +Handler_icp_attempts 0 Handler_icp_match 0 SELECT * FROM t1 FORCE INDEX(c1) WHERE (c1='3' or c1='4') and c1 % 2 = 0 ; c1 c2 4 4 show status like "Handler_icp%"; Variable_name Value -Handler_icp_attempts 2 +Handler_icp_attempts 2 Handler_icp_match 1 SELECT * FROM t1 WHERE (c2='3' or c2='4') and c2 % 2 = 0 ; c1 c2 4 4 show status like "Handler_icp%"; Variable_name Value -Handler_icp_attempts 2 +Handler_icp_attempts 2 Handler_icp_match 1 DROP TABLE t1; drop table if exists t0, t1, t1i, t1m; diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index f9b64e88f68..fcadee7aced 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1036,7 +1036,7 @@ replicate-events-marked-for-skip replicate replicate-same-server-id FALSE report-host (No default value) report-password (No default value) -report-port 3306 +report-port 0 report-user (No default value) rowid-merge-buff-size 8388608 rpl-recovery-rank 0 diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 7c38fa18faa..1bc1ea31671 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -2354,6 +2354,46 @@ TRUNCATE TABLE t1; INSERT INTO t1 VALUES(0); DROP TABLE t1; SET GLOBAL myisam_use_mmap=default; +# +# Bug#13580775 ASSERTION FAILED: RECORD_LENGTH == M_RECORD_LENGTH, +# FILE FILESORT_UTILS.CC +# +CREATE TABLE t1 ( +a INT PRIMARY KEY, +b INT, +c CHAR(1), +d INT, +KEY (c,d) +) PARTITION BY KEY () PARTITIONS 1; +INSERT INTO t1 VALUES (1,1,'a',1), (2,2,'a',1); +SELECT 1 FROM t1 WHERE 1 IN +(SELECT group_concat(b) +FROM t1 +WHERE c > geomfromtext('point(1 1)') +GROUP BY b +); +1 +1 +1 +DROP TABLE t1; +# +# Bug#13011410 CRASH IN FILESORT CODE WITH GROUP BY/ROLLUP +# +CREATE TABLE t1 ( +a INT, +b MEDIUMINT, +c VARCHAR(300) CHARACTER SET hp8 COLLATE hp8_bin, +PRIMARY KEY (a,c(299))) +ENGINE=myisam +PARTITION BY LINEAR KEY () PARTITIONS 2; +INSERT INTO t1 VALUES (1,2,'test'), (2,3,'hi'), (4,5,'bye'); +SELECT 1 FROM t1 WHERE b < SOME +( SELECT 1 FROM t1 WHERE a >= 1 +GROUP BY b WITH ROLLUP +HAVING b > geomfromtext("") +); +1 +DROP TABLE t1; End of 5.1 tests # # BUG#55385: UPDATE statement throws an error, but still updates diff --git a/mysql-test/r/partition_cache.result b/mysql-test/r/partition_cache.result new file mode 100644 index 00000000000..ac2da9bb78a --- /dev/null +++ b/mysql-test/r/partition_cache.result @@ -0,0 +1,205 @@ +SET SESSION STORAGE_ENGINE = InnoDB; +drop table if exists t1,t2,t3; +set @save_query_cache_size = @@global.query_cache_size; +set GLOBAL query_cache_size = 1355776; +flush status; +set autocommit=0; +create table t1 (a int not null) PARTITION BY KEY (a) PARTITIONS 3; +insert into t1 values (1),(2),(3); +select * from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +drop table t1; +commit; +set autocommit=1; +begin; +create table t1 (a int not null) PARTITION BY KEY (a) PARTITIONS 3; +insert into t1 values (1),(2),(3); +select * from t1; +a +1 +2 +3 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +drop table t1; +commit; +create table t1 (a int not null) PARTITION BY KEY (a) PARTITIONS 3; +create table t2 (a int not null) PARTITION BY KEY (a) PARTITIONS 3; +create table t3 (a int not null) PARTITION BY KEY (a) PARTITIONS 3; +insert into t1 values (1),(2); +insert into t2 values (1),(2); +insert into t3 values (1),(2); +select * from t1; +a +1 +2 +select * from t2; +a +1 +2 +select * from t3; +a +1 +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +begin; +select * from t1; +a +1 +2 +select * from t2; +a +1 +2 +select * from t3; +a +1 +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +insert into t1 values (3); +insert into t2 values (3); +insert into t1 values (4); +select * from t1; +a +1 +2 +3 +4 +select * from t2; +a +1 +2 +3 +select * from t3; +a +1 +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +commit; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +drop table t3,t2,t1; +CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) PARTITION BY HASH (id) PARTITIONS 3; +select count(*) from t1; +count(*) +0 +insert into t1 (id) values (0); +select count(*) from t1; +count(*) +1 +drop table t1; +SET SESSION STORAGE_ENGINE = InnoDB; +SET @@autocommit=1; +connection default +SHOW VARIABLES LIKE 'have_query_cache'; +Variable_name Value +have_query_cache YES +SET GLOBAL query_cache_size = 204800; +flush status; +SET @@autocommit=1; +SET SESSION STORAGE_ENGINE = InnoDB; +CREATE TABLE t2 (s1 int, s2 varchar(1000), key(s1)) PARTITION BY KEY (s1) PARTITIONS 3; +INSERT INTO t2 VALUES (1,repeat('a',10)),(2,repeat('a',10)),(3,repeat('a',10)),(4,repeat('a',10)); +COMMIT; +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +0 +UPDATE t2 SET s2 = 'w' WHERE s1 = 3; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +connection connection1 +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +0 +INSERT INTO t2 VALUES (5,'w'); +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +COMMIT; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +connection default +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +COMMIT; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +connection connection1 +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +INSERT INTO t2 VALUES (6,'w'); +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +3 +connection default +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +START TRANSACTION; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +DELETE from t2 WHERE s1=3; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +1 +COMMIT; +connection connection1 +COMMIT; +SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w'; +count(*) +2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +set @@global.query_cache_size = @save_query_cache_size; +drop table t2; diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 5cba49645b4..851c97c5ec3 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -1,5 +1,31 @@ drop table if exists t1, t2; # +# Bug#13608188 - 64038: CRASH IN HANDLER::HA_THD ON ALTER TABLE AFTER +# REPAIR NON-EXISTING PARTITION +# +CREATE TABLE t1 ( a INT, b INT ); +INSERT INTO t1 VALUES (5,3),(5,6); +ALTER TABLE t1 PARTITION BY KEY(b) PARTITIONS 3 ; +ALTER TABLE t1 REPAIR PARTITION p1, p3; +Table Op Msg_type Msg_text +test.t1 repair error Error in list of partitions to test.t1 +ALTER TABLE t1 ORDER BY b; +DROP TABLE t1; +# +# Bug#13593865 - 64037: CRASH IN HA_PARTITION::CREATE_HANDLERS ON +# ALTER TABLE AFTER DROP PARTITION +# +CREATE TABLE t1 (a INT) +PARTITION BY RANGE (a) +(PARTITION p0 VALUES LESS THAN (0), +PARTITION p1 VALUES LESS THAN MAXVALUE ) ; +ALTER TABLE t1 DROP PARTITION p1; +ALTER TABLE t1 ANALYZE PARTITION p0, p1; +Table Op Msg_type Msg_text +test.t1 analyze error Error in list of partitions to test.t1 +ALTER TABLE t1 COMMENT 'altered'; +DROP TABLE t1; +# # Bug#57924: crash when creating partitioned table with # multiple columns in the partition key # diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index da2f59f375e..dd403f64b5c 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -2,6 +2,35 @@ set global default_storage_engine='innodb'; set session default_storage_engine='innodb'; drop table if exists t1, t2; # +# Bug#13694811: THE OPTIMIZER WRONGLY USES THE FIRST +# INNODB PARTITION STATISTICS +# +CREATE TABLE t1 +(a INT, +b varchar(64), +PRIMARY KEY (a), +KEY (b)) +ENGINE = InnoDB +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (a) SUBPARTITIONS 10 +(PARTITION pNeg VALUES LESS THAN (0), +PARTITION p0 VALUES LESS THAN (1000), +PARTITION pMAX VALUES LESS THAN MAXVALUE); +# Only one row in the first 10 subpartitions +INSERT INTO t1 VALUES (-1, 'Only negative pk value'); +INSERT INTO t1 VALUES (0, 'Mod Zero'), (1, 'One'), (2, 'Two'), (3, 'Three'), +(10, 'Zero'), (11, 'Mod One'), (12, 'Mod Two'), (13, 'Mod Three'), +(20, '0'), (21, '1'), (22, '2'), (23, '3'), +(4, '4'), (5, '5'), (6, '6'), (7, '7'), (8, '8'), (9, '9'); +INSERT INTO t1 SELECT a + 30, b FROM t1 WHERE a >= 0; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +EXPLAIN SELECT b FROM t1 WHERE b between 'L' and 'N' AND a > -100; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range PRIMARY,b b 67 NULL 18 Using where; Using index +DROP TABLE t1; +# # Bug#56287: crash when using Partition datetime in sub in query # CREATE TABLE t1 @@ -148,13 +177,13 @@ insert INTO t1 VALUES (110); ERROR HY000: Table has no partition for value 110 EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 90; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 0 Using where +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 90; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 0 Using where +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 90; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 0 Using where +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 89; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p90 ALL NULL NULL NULL NULL 3 Using where @@ -163,16 +192,16 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p90 ALL NULL NULL NULL NULL 3 Using where EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 89; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 0 Using where +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = 100; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 0 Using where +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= 100; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 0 Using where +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > 100; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 0 Using where +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables DROP TABLE t1; # # Bug#50104: Partitioned table with just 1 partion works with fk diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result index 32c0cd34942..4d48b70d26a 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -18,7 +18,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra # # # # # # # # # 3 # EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 7; id select_type table partitions type possible_keys key key_len ref rows Extra -# # # # # # # # # 9 # +# # # # # # # # # 10 # EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 1; id select_type table partitions type possible_keys key key_len ref rows Extra # # # # # # # # # 3 # @@ -105,7 +105,7 @@ a 6 EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 7; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0,p1,p2,p3,p4,p5,max range PRIMARY PRIMARY 4 NULL 9 Using where; Using index +1 SIMPLE t1 p0,p1,p2,p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index SELECT * FROM t1 WHERE a <= 1; a -1 @@ -168,7 +168,7 @@ a 6 EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 6; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0,p1,p2,p3,p4,p5,max range PRIMARY PRIMARY 4 NULL 9 Using where; Using index +1 SIMPLE t1 p0,p1,p2,p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index SELECT * FROM t1 WHERE a <= 7; a -1 @@ -182,7 +182,7 @@ a 7 EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 7; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0,p1,p2,p3,p4,p5,max range PRIMARY PRIMARY 4 NULL 9 Using where; Using index +1 SIMPLE t1 p0,p1,p2,p3,p4,p5,max index PRIMARY PRIMARY 4 NULL 10 Using where; Using index SELECT * FROM t1 WHERE a = 1; a 1 @@ -424,7 +424,7 @@ a 5 EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < 6; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0,p1,p2,p3,p4,max range PRIMARY PRIMARY 4 NULL 8 Using where; Using index +1 SIMPLE t1 p0,p1,p2,p3,p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index SELECT * FROM t1 WHERE a <= 1; a -1 @@ -474,7 +474,7 @@ a 5 EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 5; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0,p1,p2,p3,p4,max range PRIMARY PRIMARY 4 NULL 8 Using where; Using index +1 SIMPLE t1 p0,p1,p2,p3,p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index SELECT * FROM t1 WHERE a <= 6; a -1 @@ -487,7 +487,7 @@ a 6 EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= 6; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0,p1,p2,p3,p4,max range PRIMARY PRIMARY 4 NULL 8 Using where; Using index +1 SIMPLE t1 p0,p1,p2,p3,p4,max index PRIMARY PRIMARY 4 NULL 9 Using where; Using index SELECT * FROM t1 WHERE a = 1; a 1 @@ -744,13 +744,13 @@ a 1001-01-01 EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-01-01'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 range a a 4 NULL 3 Using where; Using index +1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 index a a 4 NULL 6 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-01-01'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 range a a 4 NULL 3 Using where; Using index +1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 index a a 4 NULL 6 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-01-01'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 range a a 4 NULL 4 Using where; Using index +1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 range a a 4 NULL 3 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-01-01'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL,p2001-01-01 range a a 4 NULL 3 Using where; Using index @@ -759,26 +759,26 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p1001-01-01 system a NULL NULL NULL 1 EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 range a a 4 NULL 3 Using where; Using index +1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 index a a 4 NULL 6 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 range a a 4 NULL 3 Using where; Using index +1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 index a a 4 NULL 6 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 range a a 4 NULL 4 Using where; Using index +1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 range a a 4 NULL 3 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 range a a 4 NULL 4 Using where; Using index +1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 range a a 4 NULL 3 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL ref a a 4 const 1 Using index # Disabling warnings for the invalid date EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 range a a 4 NULL 5 Using where; Using index +1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 range a a 4 NULL 4 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 range a a 4 NULL 5 Using where; Using index +1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 range a a 4 NULL 4 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL,p2001-01-01 index a a 4 NULL 4 Using where; Using index @@ -790,16 +790,16 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL ref a a 4 const 1 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 range a a 4 NULL 5 Using where; Using index +1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 range a a 4 NULL 4 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 range a a 4 NULL 3 Using where; Using index +1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 index a a 4 NULL 6 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 range a a 4 NULL 3 Using where; Using index +1 SIMPLE t1 pNULL,p1001-01-01,p2001-01-01 index a a 4 NULL 5 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 range a a 4 NULL 3 Using where; Using index +1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01 index a a 4 NULL 6 Using where; Using index # test without index ALTER TABLE t1 DROP KEY a; SELECT * FROM t1 WHERE a < '1001-01-01'; @@ -1076,7 +1076,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 range a a 4 NULL 3 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-01-01'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index +1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 3 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-01-01'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 range a a 4 NULL 4 Using where; Using index @@ -1104,10 +1104,10 @@ id select_type table partitions type possible_keys key key_len ref rows Extra # Disabling warnings for the invalid date EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index +1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index +1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p2001-01-01,pNULL index a a 4 NULL 4 Using where; Using index @@ -1119,10 +1119,10 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL ref a a 4 const 1 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index +1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index +1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 3 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL,p1001-01-01 index a a 4 NULL 4 Using where; Using index @@ -1405,7 +1405,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 range a a 4 NULL 3 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-01-01'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index +1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 3 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-01-01'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 range a a 4 NULL 4 Using where; Using index @@ -1433,10 +1433,10 @@ id select_type table partitions type possible_keys key key_len ref rows Extra # Disabling warnings for the invalid date EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index +1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index +1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p2001-01-01,pNULL index a a 4 NULL 4 Using where; Using index @@ -1448,10 +1448,10 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL ref a a 4 const 1 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index +1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index +1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 3 Using where; Using index EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL,p1001-01-01 index a a 4 NULL 4 Using where; Using index @@ -2867,18 +2867,18 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t2 p0,p1,p2 ALL NULL NULL NULL NULL 510 Using where explain partitions select * from t2 where b = 4; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t2 p0,p1,p2,p3,p4 ref b b 5 const 76 +1 SIMPLE t2 p0,p1,p2,p3,p4 ref b b 5 const 96 explain extended select * from t2 where b = 6; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 ref b b 5 const 76 100.00 +1 SIMPLE t2 ref b b 5 const 96 100.00 Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`b` = 6) explain partitions select * from t2 where b = 6; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t2 p0,p1,p2,p3,p4 ref b b 5 const 76 +1 SIMPLE t2 p0,p1,p2,p3,p4 ref b b 5 const 96 explain extended select * from t2 where b in (1,3,5); id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 ALL b NULL NULL NULL 910 40.66 Using where +1 SIMPLE t2 ALL b NULL NULL NULL 910 51.65 Using where Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`b` in (1,3,5)) explain partitions select * from t2 where b in (1,3,5); @@ -2886,7 +2886,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t2 p0,p1,p2,p3,p4 ALL b NULL NULL NULL 910 Using where explain extended select * from t2 where b in (2,4,6); id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 ALL b NULL NULL NULL 910 25.05 Using where +1 SIMPLE t2 ALL b NULL NULL NULL 910 31.65 Using where Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`b` in (2,4,6)) explain partitions select * from t2 where b in (2,4,6); @@ -2894,7 +2894,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t2 p0,p1,p2,p3,p4 ALL b NULL NULL NULL 910 Using where explain extended select * from t2 where b in (7,8,9); id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 ALL b NULL NULL NULL 910 36.70 Using where +1 SIMPLE t2 ALL b NULL NULL NULL 910 19.12 Using where Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`b` in (7,8,9)) explain partitions select * from t2 where b in (7,8,9); @@ -2902,7 +2902,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t2 p0,p1,p2,p3,p4 ALL b NULL NULL NULL 910 Using where explain extended select * from t2 where b > 5; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 ALL b NULL NULL NULL 910 44.84 Using where +1 SIMPLE t2 ALL b NULL NULL NULL 910 29.23 Using where Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`b` > 5) explain partitions select * from t2 where b > 5; @@ -2910,7 +2910,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t2 p0,p1,p2,p3,p4 ALL b NULL NULL NULL 910 Using where explain extended select * from t2 where b > 5 and b < 8; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 ALL b NULL NULL NULL 910 22.09 Using where +1 SIMPLE t2 ALL b NULL NULL NULL 910 28.13 Using where Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where ((`test`.`t2`.`b` > 5) and (`test`.`t2`.`b` < 8)) explain partitions select * from t2 where b > 5 and b < 8; @@ -2918,15 +2918,15 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t2 p0,p1,p2,p3,p4 ALL b NULL NULL NULL 910 Using where explain extended select * from t2 where b > 5 and b < 7; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 range b b 5 NULL 76 100.00 Using where +1 SIMPLE t2 range b b 5 NULL 96 100.00 Using where Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where ((`test`.`t2`.`b` > 5) and (`test`.`t2`.`b` < 7)) explain partitions select * from t2 where b > 5 and b < 7; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t2 p0,p1,p2,p3,p4 range b b 5 NULL 76 Using where +1 SIMPLE t2 p0,p1,p2,p3,p4 range b b 5 NULL 96 Using where explain extended select * from t2 where b > 0 and b < 5; id select_type table type possible_keys key key_len ref rows filtered Extra -1 SIMPLE t2 ALL b NULL NULL NULL 910 41.65 Using where +1 SIMPLE t2 ALL b NULL NULL NULL 910 53.19 Using where Warnings: Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where ((`test`.`t2`.`b` > 0) and (`test`.`t2`.`b` < 5)) explain partitions select * from t2 where b > 0 and b < 5; @@ -2960,10 +2960,10 @@ flush status; delete from t2 where b = 7; show status like 'Handler_read_rnd_next'; Variable_name Value -Handler_read_rnd_next 0 +Handler_read_rnd_next 915 show status like 'Handler_read_key'; Variable_name Value -Handler_read_key 5 +Handler_read_key 0 flush status; delete from t2 where b > 5; show status like 'Handler_read_rnd_next'; diff --git a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result index 2efe7117a26..b5addf16147 100644 --- a/mysql-test/r/plugin.result +++ b/mysql-test/r/plugin.result @@ -15,7 +15,7 @@ PLUGIN_STATUS ACTIVE PLUGIN_TYPE STORAGE ENGINE PLUGIN_TYPE_VERSION # PLUGIN_LIBRARY ha_example.so -PLUGIN_LIBRARY_VERSION 1.2 +PLUGIN_LIBRARY_VERSION 1.3 PLUGIN_AUTHOR Brian Aker, MySQL AB PLUGIN_DESCRIPTION Example storage engine PLUGIN_LICENSE GPL @@ -28,7 +28,7 @@ PLUGIN_STATUS ACTIVE PLUGIN_TYPE DAEMON PLUGIN_TYPE_VERSION # PLUGIN_LIBRARY ha_example.so -PLUGIN_LIBRARY_VERSION 1.2 +PLUGIN_LIBRARY_VERSION 1.3 PLUGIN_AUTHOR Sergei Golubchik PLUGIN_DESCRIPTION Unusable Daemon PLUGIN_LICENSE GPL @@ -57,7 +57,7 @@ PLUGIN_STATUS DELETED PLUGIN_TYPE STORAGE ENGINE PLUGIN_TYPE_VERSION # PLUGIN_LIBRARY ha_example.so -PLUGIN_LIBRARY_VERSION 1.2 +PLUGIN_LIBRARY_VERSION 1.3 PLUGIN_AUTHOR Brian Aker, MySQL AB PLUGIN_DESCRIPTION Example storage engine PLUGIN_LICENSE GPL diff --git a/mysql-test/r/plugin_loaderr.result b/mysql-test/r/plugin_loaderr.result new file mode 100644 index 00000000000..95e5ec794d2 --- /dev/null +++ b/mysql-test/r/plugin_loaderr.result @@ -0,0 +1,10 @@ +call mtr.add_suppression("InnoDB"); +SELECT +PLUGIN_NAME,PLUGIN_STATUS,PLUGIN_TYPE,PLUGIN_LIBRARY,PLUGIN_LIBRARY_VERSION,LOAD_OPTION +FROM INFORMATION_SCHEMA.PLUGINS WHERE plugin_name = 'innodb'; +PLUGIN_NAME InnoDB +PLUGIN_STATUS DISABLED +PLUGIN_TYPE STORAGE ENGINE +PLUGIN_LIBRARY NULL +PLUGIN_LIBRARY_VERSION NULL +LOAD_OPTION ON diff --git a/mysql-test/r/progress_976225.result b/mysql-test/r/progress_976225.result new file mode 100644 index 00000000000..a96b7b411e3 --- /dev/null +++ b/mysql-test/r/progress_976225.result @@ -0,0 +1,11 @@ +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +INSERT INTO t2 VALUES (3),(4); +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 +drop table t1, t2; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index b4a09091aa6..ce0926c6bc1 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1,3 +1,4 @@ +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.'); drop table if exists t1,t2,t3,t4; drop database if exists client_test_db; create table t1 @@ -3754,6 +3755,109 @@ FROM (SELECT 1 UNION SELECT 2) t; 1 1 2 + +# Bug#13805127: Stored program cache produces wrong result in same THD + +PREPARE s1 FROM +" +SELECT c1, t2.c2, count(c3) +FROM + ( + SELECT 3 as c2 FROM dual WHERE @x = 1 + UNION + SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 + ) AS t1, + ( + SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual + UNION + SELECT '2012-03-01 02:00:00', 3, 2 FROM dual + UNION + SELECT '2012-03-01 01:00:00', 2, 1 FROM dual + ) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2 +"; + +SET @x = 1; +SELECT c1, t2.c2, count(c3) +FROM +( +SELECT 3 as c2 FROM dual WHERE @x = 1 +UNION +SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 +) AS t1, +( +SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual +UNION +SELECT '2012-03-01 02:00:00', 3, 2 FROM dual +UNION +SELECT '2012-03-01 01:00:00', 2, 1 FROM dual +) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2; +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 +2012-03-01 01:00:00 3 1 +2012-03-01 02:00:00 3 1 + +EXECUTE s1; +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 +2012-03-01 01:00:00 3 1 +2012-03-01 02:00:00 3 1 + +SET @x = 2; +SELECT c1, t2.c2, count(c3) +FROM +( +SELECT 3 as c2 FROM dual WHERE @x = 1 +UNION +SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 +) AS t1, +( +SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual +UNION +SELECT '2012-03-01 02:00:00', 3, 2 FROM dual +UNION +SELECT '2012-03-01 01:00:00', 2, 1 FROM dual +) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2; +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 + +EXECUTE s1; +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 + +SET @x = 1; +SELECT c1, t2.c2, count(c3) +FROM +( +SELECT 3 as c2 FROM dual WHERE @x = 1 +UNION +SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 +) AS t1, +( +SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual +UNION +SELECT '2012-03-01 02:00:00', 3, 2 FROM dual +UNION +SELECT '2012-03-01 01:00:00', 2, 1 FROM dual +) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2; +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 +2012-03-01 01:00:00 3 1 +2012-03-01 02:00:00 3 1 + +EXECUTE s1; +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 +2012-03-01 01:00:00 3 1 +2012-03-01 02:00:00 3 1 +DEALLOCATE PREPARE s1; # # End of 5.5 tests. prepare stmt from "select date('2010-10-10') between '2010-09-09' and ?"; diff --git a/mysql-test/r/range_vs_index_merge.result b/mysql-test/r/range_vs_index_merge.result index f8738457dd9..faaa6d2429e 100644 --- a/mysql-test/r/range_vs_index_merge.result +++ b/mysql-test/r/range_vs_index_merge.result @@ -1045,6 +1045,182 @@ ID Name Country Population 4030 Sandy USA 101853 4031 Athens-Clarke County USA 101489 4032 Cambridge USA 101355 +set @save_optimizer_switch=@@optimizer_switch; +CREATE INDEX CityName on City(Name); +EXPLAIN SELECT Name, Country, Population FROM City WHERE +(Name='Manila' AND Country='PHL') OR +(Name='Addis Abeba' AND Country='ETH') OR +(Name='Jakarta' AND Country='IDN') OR +(Name='Bangalore' AND Country='IND') OR +(Name='Teheran' AND Country='IRN') OR +(Name='Roma' AND Country='ITA') OR +(Name='Delhi' AND Country='IND') OR +(Name='Venezia' AND Country='ITA') OR +(Name='Tokyo' AND Country='JPN') OR +(Name='Toronto' AND Country='CAN') OR +(Name='Peking' AND Country='CHN') OR +(Name='Lagos' AND Country='NGA') OR +(Name='Tijuana' AND Country='MEX') OR +(Name='Rabat' AND Country='MAR') OR +(Name='Seoul' AND Country='KOR') OR +(Name='Vancouver' AND Country='CAN') OR +(Name='Kaunas' AND Country='LTU') OR +(Name='Paris' AND Country='FRA') OR +(Name='Dakar' AND Country='SEN') OR +(Name='Basel' AND Country='CHE') OR +(Name='Praha' AND Country='CZE') OR +(Name='Ankara' AND Country='TUR') OR +(Name='Dresden' AND Country='DEU') OR +(Name='Lugansk' AND Country='UKR') OR +(Name='Caracas' AND Country='VEN') OR +(Name='Samara' AND Country='RUS') OR +(Name='Seattle' AND Country='USA'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE City index_merge Country,CountryPopulation,CountryName,CityName CountryName,CityName 38,35 NULL 28 Using sort_union(CountryName,CityName); Using where +SELECT Name, Country, Population FROM City WHERE +(Name='Manila' AND Country='PHL') OR +(Name='Addis Abeba' AND Country='ETH') OR +(Name='Jakarta' AND Country='IDN') OR +(Name='Bangalore' AND Country='IND') OR +(Name='Teheran' AND Country='IRN') OR +(Name='Roma' AND Country='ITA') OR +(Name='Delhi' AND Country='IND') OR +(Name='Venezia' AND Country='ITA') OR +(Name='Tokyo' AND Country='JPN') OR +(Name='Toronto' AND Country='CAN') OR +(Name='Peking' AND Country='CHN') OR +(Name='Lagos' AND Country='NGA') OR +(Name='Tijuana' AND Country='MEX') OR +(Name='Rabat' AND Country='MAR') OR +(Name='Seoul' AND Country='KOR') OR +(Name='Vancouver' AND Country='CAN') OR +(Name='Kaunas' AND Country='LTU') OR +(Name='Paris' AND Country='FRA') OR +(Name='Dakar' AND Country='SEN') OR +(Name='Basel' AND Country='CHE') OR +(Name='Praha' AND Country='CZE') OR +(Name='Ankara' AND Country='TUR') OR +(Name='Dresden' AND Country='DEU') OR +(Name='Lugansk' AND Country='UKR') OR +(Name='Caracas' AND Country='VEN') OR +(Name='Samara' AND Country='RUS') OR +(Name='Seattle' AND Country='USA'); +Name Country Population +Addis Abeba ETH 2495000 +Manila PHL 1581082 +Jakarta IDN 9604900 +Delhi IND 7206704 +Bangalore IND 2660088 +Teheran IRN 6758845 +Roma ITA 2643581 +Venezia ITA 277305 +Tokyo JPN 7980230 +Toronto CAN 688275 +Vancouver CAN 514008 +Peking CHN 7472000 +Seoul KOR 9981619 +Kaunas LTU 412639 +Rabat MAR 623457 +Tijuana MEX 1212232 +Lagos NGA 1518000 +Paris FRA 2125246 +Dresden DEU 476668 +Dakar SEN 785071 +Basel CHE 166700 +Praha CZE 1181126 +Ankara TUR 3038159 +Lugansk UKR 469000 +Caracas VEN 1975294 +Samara RUS 1156100 +Seattle USA 563374 +set optimizer_switch='index_merge=off'; +EXPLAIN SELECT Name, Country, Population FROM City WHERE +(Name='Manila' AND Country='PHL') OR +(Name='Addis Abeba' AND Country='ETH') OR +(Name='Jakarta' AND Country='IDN') OR +(Name='Bangalore' AND Country='IND') OR +(Name='Teheran' AND Country='IRN') OR +(Name='Roma' AND Country='ITA') OR +(Name='Delhi' AND Country='IND') OR +(Name='Venezia' AND Country='ITA') OR +(Name='Tokyo' AND Country='JPN') OR +(Name='Toronto' AND Country='CAN') OR +(Name='Peking' AND Country='CHN') OR +(Name='Lagos' AND Country='NGA') OR +(Name='Tijuana' AND Country='MEX') OR +(Name='Rabat' AND Country='MAR') OR +(Name='Seoul' AND Country='KOR') OR +(Name='Vancouver' AND Country='CAN') OR +(Name='Kaunas' AND Country='LTU') OR +(Name='Paris' AND Country='FRA') OR +(Name='Dakar' AND Country='SEN') OR +(Name='Basel' AND Country='CHE') OR +(Name='Praha' AND Country='CZE') OR +(Name='Ankara' AND Country='TUR') OR +(Name='Dresden' AND Country='DEU') OR +(Name='Lugansk' AND Country='UKR') OR +(Name='Caracas' AND Country='VEN') OR +(Name='Samara' AND Country='RUS') OR +(Name='Seattle' AND Country='USA'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE City range Country,CountryPopulation,CountryName,CityName CountryName 38 NULL 29 Using index condition; Using where +SELECT Name, Country, Population FROM City WHERE +(Name='Manila' AND Country='PHL') OR +(Name='Addis Abeba' AND Country='ETH') OR +(Name='Jakarta' AND Country='IDN') OR +(Name='Bangalore' AND Country='IND') OR +(Name='Teheran' AND Country='IRN') OR +(Name='Roma' AND Country='ITA') OR +(Name='Delhi' AND Country='IND') OR +(Name='Venezia' AND Country='ITA') OR +(Name='Tokyo' AND Country='JPN') OR +(Name='Toronto' AND Country='CAN') OR +(Name='Peking' AND Country='CHN') OR +(Name='Lagos' AND Country='NGA') OR +(Name='Tijuana' AND Country='MEX') OR +(Name='Rabat' AND Country='MAR') OR +(Name='Seoul' AND Country='KOR') OR +(Name='Vancouver' AND Country='CAN') OR +(Name='Kaunas' AND Country='LTU') OR +(Name='Paris' AND Country='FRA') OR +(Name='Dakar' AND Country='SEN') OR +(Name='Basel' AND Country='CHE') OR +(Name='Praha' AND Country='CZE') OR +(Name='Ankara' AND Country='TUR') OR +(Name='Dresden' AND Country='DEU') OR +(Name='Lugansk' AND Country='UKR') OR +(Name='Caracas' AND Country='VEN') OR +(Name='Samara' AND Country='RUS') OR +(Name='Seattle' AND Country='USA'); +Name Country Population +Toronto CAN 688275 +Vancouver CAN 514008 +Basel CHE 166700 +Peking CHN 7472000 +Praha CZE 1181126 +Dresden DEU 476668 +Addis Abeba ETH 2495000 +Paris FRA 2125246 +Jakarta IDN 9604900 +Bangalore IND 2660088 +Delhi IND 7206704 +Teheran IRN 6758845 +Roma ITA 2643581 +Venezia ITA 277305 +Tokyo JPN 7980230 +Seoul KOR 9981619 +Kaunas LTU 412639 +Rabat MAR 623457 +Tijuana MEX 1212232 +Lagos NGA 1518000 +Manila PHL 1581082 +Samara RUS 1156100 +Dakar SEN 785071 +Ankara TUR 3038159 +Lugansk UKR 469000 +Seattle USA 563374 +Caracas VEN 1975294 +set optimizer_switch=@save_optimizer_switch; DROP DATABASE world; use test; CREATE TABLE t1 ( diff --git a/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff b/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff index c71cc7c6b45..5913434caae 100644 --- a/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff +++ b/mysql-test/r/range_vs_index_merge_innodb,innodb_plugin.rdiff @@ -1,5 +1,5 @@ ---- r/range_vs_index_merge_innodb.result 2012-02-23 15:57:49.000000000 +0100 -+++ r/range_vs_index_merge_innodb,innodb_plugin.reject 2012-02-23 19:46:02.000000000 +0100 +--- r/range_vs_index_merge_innodb.result 2012-03-24 17:12:02.124422000 +0100 ++++ r/range_vs_index_merge_innodb,innodb_plugin.reject 2012-03-24 18:00:13.647902620 +0100 @@ -50,14 +50,14 @@ WHERE (Population >= 100000 OR Name LIKE 'P%') AND Country='CAN' OR (Population < 100000 OR Name Like 'T%') AND Country='ARG'; @@ -251,3 +251,21 @@ SELECT * FROM City USE INDEX () WHERE ((Population > 101000 AND Population < 11000) OR ID BETWEEN 3500 AND 3800) AND Country='USA' +@@ -1077,7 +1077,7 @@ + (Name='Samara' AND Country='RUS') OR + (Name='Seattle' AND Country='USA'); + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE City range Country,CountryPopulation,CountryName,CityName CountryName 38 NULL 27 Using index condition; Using where ++1 SIMPLE City range Country,CountryPopulation,CountryName,CityName CountryName 38 NULL 27 Using where + SELECT Name, Country, Population FROM City WHERE + (Name='Manila' AND Country='PHL') OR + (Name='Addis Abeba' AND Country='ETH') OR +@@ -1164,7 +1164,7 @@ + (Name='Samara' AND Country='RUS') OR + (Name='Seattle' AND Country='USA'); + id select_type table type possible_keys key key_len ref rows Extra +-1 SIMPLE City range Country,CountryPopulation,CountryName,CityName CountryName 38 NULL 27 Using index condition; Using where ++1 SIMPLE City range Country,CountryPopulation,CountryName,CityName CountryName 38 NULL 27 Using where + SELECT Name, Country, Population FROM City WHERE + (Name='Manila' AND Country='PHL') OR + (Name='Addis Abeba' AND Country='ETH') OR diff --git a/mysql-test/r/range_vs_index_merge_innodb.result b/mysql-test/r/range_vs_index_merge_innodb.result index c42f80f0e85..df3a2af0753 100644 --- a/mysql-test/r/range_vs_index_merge_innodb.result +++ b/mysql-test/r/range_vs_index_merge_innodb.result @@ -1046,6 +1046,182 @@ ID Name Country Population 4030 Sandy USA 101853 4031 Athens-Clarke County USA 101489 4032 Cambridge USA 101355 +set @save_optimizer_switch=@@optimizer_switch; +CREATE INDEX CityName on City(Name); +EXPLAIN SELECT Name, Country, Population FROM City WHERE +(Name='Manila' AND Country='PHL') OR +(Name='Addis Abeba' AND Country='ETH') OR +(Name='Jakarta' AND Country='IDN') OR +(Name='Bangalore' AND Country='IND') OR +(Name='Teheran' AND Country='IRN') OR +(Name='Roma' AND Country='ITA') OR +(Name='Delhi' AND Country='IND') OR +(Name='Venezia' AND Country='ITA') OR +(Name='Tokyo' AND Country='JPN') OR +(Name='Toronto' AND Country='CAN') OR +(Name='Peking' AND Country='CHN') OR +(Name='Lagos' AND Country='NGA') OR +(Name='Tijuana' AND Country='MEX') OR +(Name='Rabat' AND Country='MAR') OR +(Name='Seoul' AND Country='KOR') OR +(Name='Vancouver' AND Country='CAN') OR +(Name='Kaunas' AND Country='LTU') OR +(Name='Paris' AND Country='FRA') OR +(Name='Dakar' AND Country='SEN') OR +(Name='Basel' AND Country='CHE') OR +(Name='Praha' AND Country='CZE') OR +(Name='Ankara' AND Country='TUR') OR +(Name='Dresden' AND Country='DEU') OR +(Name='Lugansk' AND Country='UKR') OR +(Name='Caracas' AND Country='VEN') OR +(Name='Samara' AND Country='RUS') OR +(Name='Seattle' AND Country='USA'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE City range Country,CountryPopulation,CountryName,CityName CountryName 38 NULL 27 Using index condition; Using where +SELECT Name, Country, Population FROM City WHERE +(Name='Manila' AND Country='PHL') OR +(Name='Addis Abeba' AND Country='ETH') OR +(Name='Jakarta' AND Country='IDN') OR +(Name='Bangalore' AND Country='IND') OR +(Name='Teheran' AND Country='IRN') OR +(Name='Roma' AND Country='ITA') OR +(Name='Delhi' AND Country='IND') OR +(Name='Venezia' AND Country='ITA') OR +(Name='Tokyo' AND Country='JPN') OR +(Name='Toronto' AND Country='CAN') OR +(Name='Peking' AND Country='CHN') OR +(Name='Lagos' AND Country='NGA') OR +(Name='Tijuana' AND Country='MEX') OR +(Name='Rabat' AND Country='MAR') OR +(Name='Seoul' AND Country='KOR') OR +(Name='Vancouver' AND Country='CAN') OR +(Name='Kaunas' AND Country='LTU') OR +(Name='Paris' AND Country='FRA') OR +(Name='Dakar' AND Country='SEN') OR +(Name='Basel' AND Country='CHE') OR +(Name='Praha' AND Country='CZE') OR +(Name='Ankara' AND Country='TUR') OR +(Name='Dresden' AND Country='DEU') OR +(Name='Lugansk' AND Country='UKR') OR +(Name='Caracas' AND Country='VEN') OR +(Name='Samara' AND Country='RUS') OR +(Name='Seattle' AND Country='USA'); +Name Country Population +Toronto CAN 688275 +Vancouver CAN 514008 +Basel CHE 166700 +Peking CHN 7472000 +Praha CZE 1181126 +Dresden DEU 476668 +Addis Abeba ETH 2495000 +Paris FRA 2125246 +Jakarta IDN 9604900 +Bangalore IND 2660088 +Delhi IND 7206704 +Teheran IRN 6758845 +Roma ITA 2643581 +Venezia ITA 277305 +Tokyo JPN 7980230 +Seoul KOR 9981619 +Kaunas LTU 412639 +Rabat MAR 623457 +Tijuana MEX 1212232 +Lagos NGA 1518000 +Manila PHL 1581082 +Samara RUS 1156100 +Dakar SEN 785071 +Ankara TUR 3038159 +Lugansk UKR 469000 +Seattle USA 563374 +Caracas VEN 1975294 +set optimizer_switch='index_merge=off'; +EXPLAIN SELECT Name, Country, Population FROM City WHERE +(Name='Manila' AND Country='PHL') OR +(Name='Addis Abeba' AND Country='ETH') OR +(Name='Jakarta' AND Country='IDN') OR +(Name='Bangalore' AND Country='IND') OR +(Name='Teheran' AND Country='IRN') OR +(Name='Roma' AND Country='ITA') OR +(Name='Delhi' AND Country='IND') OR +(Name='Venezia' AND Country='ITA') OR +(Name='Tokyo' AND Country='JPN') OR +(Name='Toronto' AND Country='CAN') OR +(Name='Peking' AND Country='CHN') OR +(Name='Lagos' AND Country='NGA') OR +(Name='Tijuana' AND Country='MEX') OR +(Name='Rabat' AND Country='MAR') OR +(Name='Seoul' AND Country='KOR') OR +(Name='Vancouver' AND Country='CAN') OR +(Name='Kaunas' AND Country='LTU') OR +(Name='Paris' AND Country='FRA') OR +(Name='Dakar' AND Country='SEN') OR +(Name='Basel' AND Country='CHE') OR +(Name='Praha' AND Country='CZE') OR +(Name='Ankara' AND Country='TUR') OR +(Name='Dresden' AND Country='DEU') OR +(Name='Lugansk' AND Country='UKR') OR +(Name='Caracas' AND Country='VEN') OR +(Name='Samara' AND Country='RUS') OR +(Name='Seattle' AND Country='USA'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE City range Country,CountryPopulation,CountryName,CityName CountryName 38 NULL 27 Using index condition; Using where +SELECT Name, Country, Population FROM City WHERE +(Name='Manila' AND Country='PHL') OR +(Name='Addis Abeba' AND Country='ETH') OR +(Name='Jakarta' AND Country='IDN') OR +(Name='Bangalore' AND Country='IND') OR +(Name='Teheran' AND Country='IRN') OR +(Name='Roma' AND Country='ITA') OR +(Name='Delhi' AND Country='IND') OR +(Name='Venezia' AND Country='ITA') OR +(Name='Tokyo' AND Country='JPN') OR +(Name='Toronto' AND Country='CAN') OR +(Name='Peking' AND Country='CHN') OR +(Name='Lagos' AND Country='NGA') OR +(Name='Tijuana' AND Country='MEX') OR +(Name='Rabat' AND Country='MAR') OR +(Name='Seoul' AND Country='KOR') OR +(Name='Vancouver' AND Country='CAN') OR +(Name='Kaunas' AND Country='LTU') OR +(Name='Paris' AND Country='FRA') OR +(Name='Dakar' AND Country='SEN') OR +(Name='Basel' AND Country='CHE') OR +(Name='Praha' AND Country='CZE') OR +(Name='Ankara' AND Country='TUR') OR +(Name='Dresden' AND Country='DEU') OR +(Name='Lugansk' AND Country='UKR') OR +(Name='Caracas' AND Country='VEN') OR +(Name='Samara' AND Country='RUS') OR +(Name='Seattle' AND Country='USA'); +Name Country Population +Toronto CAN 688275 +Vancouver CAN 514008 +Basel CHE 166700 +Peking CHN 7472000 +Praha CZE 1181126 +Dresden DEU 476668 +Addis Abeba ETH 2495000 +Paris FRA 2125246 +Jakarta IDN 9604900 +Bangalore IND 2660088 +Delhi IND 7206704 +Teheran IRN 6758845 +Roma ITA 2643581 +Venezia ITA 277305 +Tokyo JPN 7980230 +Seoul KOR 9981619 +Kaunas LTU 412639 +Rabat MAR 623457 +Tijuana MEX 1212232 +Lagos NGA 1518000 +Manila PHL 1581082 +Samara RUS 1156100 +Dakar SEN 785071 +Ankara TUR 3038159 +Lugansk UKR 469000 +Seattle USA 563374 +Caracas VEN 1975294 +set optimizer_switch=@save_optimizer_switch; DROP DATABASE world; use test; CREATE TABLE t1 ( diff --git a/mysql-test/r/sp-bugs.result b/mysql-test/r/sp-bugs.result index 2425f40d9c2..9d9deaebcc3 100644 --- a/mysql-test/r/sp-bugs.result +++ b/mysql-test/r/sp-bugs.result @@ -111,4 +111,114 @@ DROP FUNCTION db1.f1; DROP TABLE db1.t1; DROP DATABASE db1; DROP DATABASE db2; +USE test; +# +# Bug#13105873:valgrind warning:possible crash in foreign +# key handling on subsequent create table if not exists +# +DROP DATABASE IF EXISTS testdb; +CREATE DATABASE testdb; +USE testdb; +CREATE TABLE t1 (id1 INT PRIMARY KEY); +CREATE PROCEDURE `p1`() +BEGIN +CREATE TABLE IF NOT EXISTS t2(id INT PRIMARY KEY, +CONSTRAINT FK FOREIGN KEY (id) REFERENCES t1( id1 )); +END$ +CALL p1(); +# below stmt should not return valgrind warnings +CALL p1(); +Warnings: +Note 1050 Table 't2' already exists +DROP DATABASE testdb; +USE test; End of 5.1 tests +# +# Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE +# +SET @@SQL_MODE = ''; +CREATE FUNCTION testf_bug11763507() RETURNS INT +BEGIN +RETURN 0; +END +$ +CREATE PROCEDURE testp_bug11763507() +BEGIN +SELECT "PROCEDURE testp_bug11763507"; +END +$ +SELECT testf_bug11763507(); +testf_bug11763507() +0 +SELECT TESTF_bug11763507(); +TESTF_bug11763507() +0 +SHOW FUNCTION STATUS LIKE 'testf_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testf_bug11763507 FUNCTION root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW FUNCTION STATUS WHERE NAME='testf_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testf_bug11763507 FUNCTION root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW FUNCTION STATUS LIKE 'TESTF_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testf_bug11763507 FUNCTION root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW FUNCTION STATUS WHERE NAME='TESTF_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testf_bug11763507 FUNCTION root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE FUNCTION testf_bug11763507; +Function sql_mode Create Function character_set_client collation_connection Database Collation +testf_bug11763507 CREATE DEFINER=`root`@`localhost` FUNCTION `testf_bug11763507`() RETURNS int(11) +BEGIN +RETURN 0; +END latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE FUNCTION TESTF_bug11763507; +Function sql_mode Create Function character_set_client collation_connection Database Collation +testf_bug11763507 CREATE DEFINER=`root`@`localhost` FUNCTION `testf_bug11763507`() RETURNS int(11) +BEGIN +RETURN 0; +END latin1 latin1_swedish_ci latin1_swedish_ci +CALL testp_bug11763507(); +PROCEDURE testp_bug11763507 +PROCEDURE testp_bug11763507 +CALL TESTP_bug11763507(); +PROCEDURE testp_bug11763507 +PROCEDURE testp_bug11763507 +SHOW PROCEDURE STATUS LIKE 'testp_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testp_bug11763507 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW PROCEDURE STATUS WHERE NAME='testp_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testp_bug11763507 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW PROCEDURE STATUS LIKE 'TESTP_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testp_bug11763507 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW PROCEDURE STATUS WHERE NAME='TESTP_bug11763507'; +Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation +test testp_bug11763507 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE PROCEDURE testp_bug11763507; +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +testp_bug11763507 CREATE DEFINER=`root`@`localhost` PROCEDURE `testp_bug11763507`() +BEGIN +SELECT "PROCEDURE testp_bug11763507"; +END latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE PROCEDURE TESTP_bug11763507; +Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation +testp_bug11763507 CREATE DEFINER=`root`@`localhost` PROCEDURE `testp_bug11763507`() +BEGIN +SELECT "PROCEDURE testp_bug11763507"; +END latin1 latin1_swedish_ci latin1_swedish_ci +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name LIKE 'testf_bug11763507'; +specific_name +testf_bug11763507 +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name LIKE 'TESTF_bug11763507'; +specific_name +testf_bug11763507 +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name='testf_bug11763507'; +specific_name +testf_bug11763507 +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name='TESTF_bug11763507'; +specific_name +testf_bug11763507 +DROP PROCEDURE testp_bug11763507; +DROP FUNCTION testf_bug11763507; +#END OF BUG#11763507 test. diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result index fd2e79dff29..67651294498 100644 --- a/mysql-test/r/sp-code.result +++ b/mysql-test/r/sp-code.result @@ -945,3 +945,32 @@ Error 1329 No data - zero rows fetched, selected, or processed SET SESSION debug_dbug="-d,bug23032_emit_warning"; DROP PROCEDURE p1; DROP TABLE t1; +# +# Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE +# +SET @@SQL_MODE = ''; +CREATE FUNCTION testf_bug11763507() RETURNS INT +BEGIN +RETURN 0; +END +$ +CREATE PROCEDURE testp_bug11763507() +BEGIN +SELECT "PROCEDURE testp_bug11763507"; +END +$ +SHOW FUNCTION CODE testf_bug11763507; +Pos Instruction +0 freturn 3 0 +SHOW FUNCTION CODE TESTF_bug11763507; +Pos Instruction +0 freturn 3 0 +SHOW PROCEDURE CODE testp_bug11763507; +Pos Instruction +0 stmt 0 "SELECT "PROCEDURE testp_bug11763507"" +SHOW PROCEDURE CODE TESTP_bug11763507; +Pos Instruction +0 stmt 0 "SELECT "PROCEDURE testp_bug11763507"" +DROP PROCEDURE testp_bug11763507; +DROP FUNCTION testf_bug11763507; +#END OF BUG#11763507 test. diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index c8743ab112d..d52318c6c5b 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -7745,4 +7745,65 @@ CALL p2(); DROP PROCEDURE p1; DROP PROCEDURE p2; DROP TABLE t1; + +# Bug#13805127: Stored program cache produces wrong result in same THD + +CREATE PROCEDURE p1(x INT UNSIGNED) +BEGIN +SELECT c1, t2.c2, count(c3) +FROM +( +SELECT 3 as c2 FROM dual WHERE x = 1 +UNION +SELECT 2 FROM dual WHERE x = 1 OR x = 2 +) AS t1, +( +SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual +UNION +SELECT '2012-03-01 02:00:00', 3, 2 FROM dual +UNION +SELECT '2012-03-01 01:00:00', 2, 1 FROM dual +) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2 +; +END| + +CALL p1(1); +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 +2012-03-01 01:00:00 3 1 +2012-03-01 02:00:00 3 1 +CALL p1(2); +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 +CALL p1(1); +c1 c2 count(c3) +2012-03-01 01:00:00 2 1 +2012-03-01 01:00:00 3 1 +2012-03-01 02:00:00 3 1 +DROP PROCEDURE p1; # End of 5.5 test +# +# Bug#12663165 SP DEAD CODE REMOVAL DOESN'T UNDERSTAND CONTINUE HANDLERS +# +DROP FUNCTION IF EXISTS f1; +CREATE FUNCTION f1() RETURNS INT +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION RETURN f1(); +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION RETURN f1(); +RETURN f1(); +END; +END; +RETURN 1; +END $ +SELECT f1(); +f1() +1 +Warnings: +Error 1424 Recursive stored functions and triggers are not allowed. +Error 1305 FUNCTION test.f1 does not exist +DROP FUNCTION f1; diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result index c4f276774d5..0b4b1726e22 100644 --- a/mysql-test/r/sp_notembedded.result +++ b/mysql-test/r/sp_notembedded.result @@ -258,4 +258,25 @@ SELECT `my.db`.f1(2); 2 # Switching to default connection. DROP DATABASE `my.db`; +USE test; set @@global.concurrent_insert= @old_concurrent_insert; +# +# Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE +# +SET @@SQL_MODE = ''; +CREATE EVENT teste_bug11763507 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO SELECT 1 $ +SHOW EVENTS LIKE 'teste_bug11763507'; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +test teste_bug11763507 root@localhost SYSTEM ONE TIME # # # # NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +SHOW EVENTS LIKE 'TESTE_bug11763507'; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +test teste_bug11763507 root@localhost SYSTEM ONE TIME # # # # NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE EVENT teste_bug11763507; +Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation +teste_bug11763507 SYSTEM # latin1 latin1_swedish_ci latin1_swedish_ci +SHOW CREATE EVENT TESTE_bug11763507; +Event sql_mode time_zone Create Event character_set_client collation_connection Database Collation +teste_bug11763507 SYSTEM # latin1 latin1_swedish_ci latin1_swedish_ci +DROP EVENT teste_bug11763507; +#END OF BUG#11763507 test. diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index e83879274a1..6736ca7f541 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -533,3 +533,207 @@ SELECT * FROM mysql.columns_priv WHERE Host = 'localhost' AND User LIKE 'user_%P Host Db User Table_name Column_name Timestamp Column_priv DROP TABLE t1; DROP TABLE t2; + +# +# Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES +# IGNORED AND BREAKS REPLICATION +# +DROP TABLE IF EXISTS test_table; +DROP FUNCTION IF EXISTS test_function; +CREATE TABLE test_table (c1 CHAR(50)); +SET @org_mode=@@sql_mode; +SET @@sql_mode=''; +PREPARE insert_stmt FROM 'INSERT INTO test_table VALUES (?)'; +PREPARE update_stmt FROM 'UPDATE test_table SET c1= ? WHERE c1= ?'; +CREATE FUNCTION test_function(var CHAR(50)) RETURNS CHAR(50) +BEGIN +DECLARE char_val CHAR(50); +SELECT c1 INTO char_val FROM test_table WHERE c1=var; +RETURN char_val; +END +$ +SET @var1='abcd\'ef'; +SET @var2='abcd\"ef'; +SET @var3='abcd\bef'; +SET @var4='abcd\nef'; +SET @var5='abcd\ref'; +SET @var6='abcd\tef'; +SET @var7='abcd\\ef'; +SET @var8='abcd\%ef'; +SET @var9='abcd\_ef'; +SET @to_var1='wxyz\'ef'; +SET @to_var2='wxyz\"ef'; +SET @to_var3='wxyz\bef'; +SET @to_var4='wxyz\nef'; +SET @to_var5='wxyz\ref'; +SET @to_var6='wxyz\tef'; +SET @to_var7='wxyz\\ef'; +SET @to_var8='wxyz\%ef'; +SET @to_var9='wxyz\_ef'; +# STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT +EXECUTE insert_stmt USING @var1; +EXECUTE insert_stmt USING @var2; +EXECUTE insert_stmt USING @var3; +EXECUTE insert_stmt USING @var4; +EXECUTE insert_stmt USING @var5; +EXECUTE insert_stmt USING @var6; +EXECUTE insert_stmt USING @var7; +EXECUTE insert_stmt USING @var8; +EXECUTE insert_stmt USING @var9; +SELECT * FROM test_table; +c1 +abcd'ef +abcd"ef +abcdef +abcd +ef +abcd
ef +abcd ef +abcd\ef +abcd\%ef +abcd\_ef +EXECUTE update_stmt USING @to_var1, @var1; +EXECUTE update_stmt USING @to_var2, @var2; +EXECUTE update_stmt USING @to_var3, @var3; +EXECUTE update_stmt USING @to_var4, @var4; +EXECUTE update_stmt USING @to_var5, @var5; +EXECUTE update_stmt USING @to_var6, @var6; +EXECUTE update_stmt USING @to_var7, @var7; +EXECUTE update_stmt USING @to_var8, @var8; +EXECUTE update_stmt USING @to_var9, @var9; +SELECT * FROM test_table; +c1 +wxyz'ef +wxyz"ef +wxyzef +wxyz +ef +wxyz
ef +wxyz ef +wxyz\ef +wxyz\%ef +wxyz\_ef + +# END OF CASE - STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT +# STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +select test_function(@to_var1); +test_function(@to_var1) +wxyz'ef +SELECT test_function(@to_var2); +test_function(@to_var2) +wxyz"ef +SELECT test_function(@to_var3); +test_function(@to_var3) +wxyzef +SELECT test_function(@to_var4); +test_function(@to_var4) +wxyz +ef +SELECT test_function(@to_var5); +test_function(@to_var5) +wxyz
ef +SELECT test_function(@to_var6); +test_function(@to_var6) +wxyz ef +SELECT test_function(@to_var7); +test_function(@to_var7) +wxyz\ef +SELECT test_function(@to_var8); +test_function(@to_var8) +wxyz\%ef +SELECT test_function(@to_var9); +test_function(@to_var9) +wxyz\_ef + +# END OF CASE - STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +DELETE FROM test_table; +DROP FUNCTION test_function; +SET @@sql_mode='NO_BACKSLASH_ESCAPES'; +CREATE FUNCTION test_function(var CHAR(50)) RETURNS CHAR(50) +BEGIN +DECLARE char_val CHAR(50); +SELECT c1 INTO char_val FROM test_table WHERE c1=var; +RETURN char_val; +END +$ +# STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT +EXECUTE insert_stmt USING @var1; +EXECUTE insert_stmt USING @var2; +EXECUTE insert_stmt USING @var3; +EXECUTE insert_stmt USING @var4; +EXECUTE insert_stmt USING @var5; +EXECUTE insert_stmt USING @var6; +EXECUTE insert_stmt USING @var7; +EXECUTE insert_stmt USING @var8; +EXECUTE insert_stmt USING @var9; +SELECT * FROM test_table; +c1 +abcd'ef +abcd"ef +abcdef +abcd +ef +abcd
ef +abcd ef +abcd\ef +abcd\%ef +abcd\_ef +EXECUTE update_stmt USING @to_var1, @var1; +EXECUTE update_stmt USING @to_var2, @var2; +EXECUTE update_stmt USING @to_var3, @var3; +EXECUTE update_stmt USING @to_var4, @var4; +EXECUTE update_stmt USING @to_var5, @var5; +EXECUTE update_stmt USING @to_var6, @var6; +EXECUTE update_stmt USING @to_var7, @var7; +EXECUTE update_stmt USING @to_var8, @var8; +EXECUTE update_stmt USING @to_var9, @var9; +SELECT * FROM test_table; +c1 +wxyz'ef +wxyz"ef +wxyzef +wxyz +ef +wxyz
ef +wxyz ef +wxyz\ef +wxyz\%ef +wxyz\_ef + +# END OF CASE - STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT +# STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +select test_function(@to_var1); +test_function(@to_var1) +wxyz'ef +SELECT test_function(@to_var2); +test_function(@to_var2) +wxyz"ef +SELECT test_function(@to_var3); +test_function(@to_var3) +wxyzef +SELECT test_function(@to_var4); +test_function(@to_var4) +wxyz +ef +SELECT test_function(@to_var5); +test_function(@to_var5) +wxyz
ef +SELECT test_function(@to_var6); +test_function(@to_var6) +wxyz ef +SELECT test_function(@to_var7); +test_function(@to_var7) +wxyz\ef +SELECT test_function(@to_var8); +test_function(@to_var8) +wxyz\%ef +SELECT test_function(@to_var9); +test_function(@to_var9) +wxyz\_ef + +# END OF CASE - STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +DROP TABLE test_table; +DROP FUNCTION test_function; +SET @@sql_mode= @org_mode; + +#End of Test for Bug#12601974 diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result index 7e3c2c45116..0da65a5ab51 100644 --- a/mysql-test/r/status.result +++ b/mysql-test/r/status.result @@ -275,7 +275,7 @@ Variable_name Value Handler_commit 0 Handler_delete 0 Handler_discover 0 -Handler_icp_attempts 0 +Handler_icp_attempts 0 Handler_icp_match 0 Handler_mrr_init 0 Handler_mrr_key_refills 0 @@ -316,7 +316,7 @@ Variable_name Value Handler_commit 0 Handler_delete 0 Handler_discover 0 -Handler_icp_attempts 0 +Handler_icp_attempts 0 Handler_icp_match 0 Handler_mrr_init 0 Handler_mrr_key_refills 0 diff --git a/mysql-test/r/status_user.result b/mysql-test/r/status_user.result index 528d005b81b..f43e217b8a5 100644 --- a/mysql-test/r/status_user.result +++ b/mysql-test/r/status_user.result @@ -100,7 +100,7 @@ Variable_name Value Handler_commit 19 Handler_delete 1 Handler_discover 0 -Handler_icp_attempts 0 +Handler_icp_attempts 0 Handler_icp_match 0 Handler_mrr_init 0 Handler_mrr_key_refills 0 diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index b59ec858e98..b1e4cb669ed 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -260,11 +260,11 @@ INSERT INTO t1 (col2) VALUES (CAST('2004-10-15 10:15' AS DATETIME)); INSERT INTO t1 (col3) VALUES (CAST('2004-10-15 10:15' AS DATETIME)); INSERT INTO t1 (col1) VALUES(CAST('0000-10-31' AS DATE)); INSERT INTO t1 (col1) VALUES(CAST('2004-10-0' AS DATE)); -ERROR 22007: Truncated incorrect date value: '2004-10-00' +ERROR 22007: Incorrect datetime value: '2004-10-0' INSERT INTO t1 (col1) VALUES(CAST('2004-0-10' AS DATE)); -ERROR 22007: Truncated incorrect date value: '2004-00-10' +ERROR 22007: Incorrect datetime value: '2004-0-10' INSERT INTO t1 (col1) VALUES(CAST('0000-00-00' AS DATE)); -ERROR 22007: Truncated incorrect date value: '0000-00-00' +ERROR 22007: Incorrect datetime value: '0000-00-00' INSERT INTO t1 (col2) VALUES(CAST('0000-10-31 15:30' AS DATETIME)); INSERT INTO t1 (col2) VALUES(CAST('2004-10-0 15:30' AS DATETIME)); ERROR 22007: Incorrect datetime value: '2004-10-0 15:30' @@ -287,13 +287,13 @@ INSERT INTO t1 (col2) VALUES (CONVERT('2004-10-15 10:15',DATETIME)); INSERT INTO t1 (col3) VALUES (CONVERT('2004-10-15 10:15',DATETIME)); INSERT INTO t1 (col1) VALUES(CONVERT('0000-10-31' , DATE)); INSERT INTO t1 (col1) VALUES(CONVERT('2004-10-0' , DATE)); -ERROR 22007: Truncated incorrect date value: '2004-10-00' +ERROR 22007: Incorrect datetime value: '2004-10-0' INSERT INTO t1 (col1) VALUES(CONVERT('2004-0-10' , DATE)); -ERROR 22007: Truncated incorrect date value: '2004-00-10' +ERROR 22007: Incorrect datetime value: '2004-0-10' INSERT INTO t1 (col1) VALUES('2004-0-10'); ERROR 22007: Incorrect date value: '2004-0-10' for column 'col1' at row 1 INSERT INTO t1 (col1) VALUES(CONVERT('0000-00-00',DATE)); -ERROR 22007: Truncated incorrect date value: '0000-00-00' +ERROR 22007: Incorrect datetime value: '0000-00-00' INSERT INTO t1 (col2) VALUES(CONVERT('0000-10-31 15:30',DATETIME)); INSERT INTO t1 (col2) VALUES(CONVERT('2004-10-0 15:30',DATETIME)); ERROR 22007: Incorrect datetime value: '2004-10-0 15:30' @@ -1137,9 +1137,9 @@ ERROR 22007: Incorrect date value: '0' for column 'col1' at row 1 insert into t1 values (0.0,0.0,0.0); ERROR 22007: Incorrect date value: '0' for column 'col1' at row 1 insert into t1 (col1) values (convert('0000-00-00',date)); -ERROR 22007: Truncated incorrect date value: '0000-00-00' +ERROR 22007: Incorrect datetime value: '0000-00-00' insert into t1 (col1) values (cast('0000-00-00' as date)); -ERROR 22007: Truncated incorrect date value: '0000-00-00' +ERROR 22007: Incorrect datetime value: '0000-00-00' set sql_mode='no_zero_date'; insert into t1 values (0,0,0); Warnings: @@ -1164,7 +1164,7 @@ Warnings: Warning 1264 Out of range value for column 'col1' at row 1 insert ignore into t1 (col1) values (cast('0000-00-00' as date)); Warnings: -Warning 1292 Truncated incorrect date value: '0000-00-00' +Warning 1292 Incorrect datetime value: '0000-00-00' insert into t1 select * from t1; ERROR 22007: Incorrect date value: '0000-00-00' for column 'col1' at row 1 alter table t1 modify col1 datetime; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 0c071f1adfc..29b8c41e515 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4645,6 +4645,55 @@ ERROR 21000: Subquery returns more than 1 row SET SESSION sql_mode=@old_sql_mode; DEALLOCATE PREPARE stmt; DROP TABLE t1; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); +1 +1 +1 +SET SESSION sql_mode=@old_sql_mode; +DROP TABLE t1, t2; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +create table t2(i int); +insert into t2 values(0); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; +CREATE TABLE t1 ( +pk int NOT NULL, +col_varchar_key varchar(1) DEFAULT NULL, +PRIMARY KEY (pk), +KEY col_varchar_key (col_varchar_key) +); +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; +pk +SET SESSION sql_mode=@old_sql_mode; +drop table t2, t1; +drop view v1; End of 5.0 tests. create table t_out (subcase char(3), a1 char(2), b1 char(2), c1 char(2)); @@ -5595,8 +5644,8 @@ WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a FROM it2,it3); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ot1 ALL NULL NULL NULL NULL 2 -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 24 Using where -1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using join buffer (flat, BNL join) +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 2 MATERIALIZED it2 ALL NULL NULL NULL NULL 4 2 MATERIALIZED it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join) DROP TABLE IF EXISTS ot1, ot4, it2, it3; diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result index d5d75b68628..014ff5b5810 100644 --- a/mysql-test/r/subselect3.result +++ b/mysql-test/r/subselect3.result @@ -1144,9 +1144,9 @@ insert into t4 select a from t3; explain select * from t3 where a in (select t1.kp1 from t1,t4 where kp1<20 and t4.pk=t1.c); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using index condition; Using where; LooseScan -1 PRIMARY t4 eq_ref PRIMARY PRIMARY 4 test.t1.c 1 Using index; FirstMatch(t1) -1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where +1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using where +1 PRIMARY t4 eq_ref PRIMARY PRIMARY 4 test.t1.c 1 Using index; FirstMatch(t3) drop table t1, t3, t4; set @@optimizer_switch=@save_optimizer_switch; create table t1 (a int) as select * from t0 where a < 5; @@ -1155,11 +1155,11 @@ set @@optimizer_switch='firstmatch=off,materialization=off'; set @@max_heap_table_size= 16384; explain select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E where a+1 < 10000 + A.a + B.a +C.a+D.a); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY E ALL NULL NULL NULL NULL 5 Start temporary -1 PRIMARY A ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) +1 PRIMARY A ALL NULL NULL NULL NULL 10 1 PRIMARY B ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) -1 PRIMARY C ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join) -1 PRIMARY D ALL NULL NULL NULL NULL 10 Using where; End temporary; Using join buffer (flat, BNL join) +1 PRIMARY E ALL NULL NULL NULL NULL 5 Start temporary; Using join buffer (flat, BNL join) +1 PRIMARY D ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join) +1 PRIMARY C ALL NULL NULL NULL NULL 10 Using where; End temporary; Using join buffer (flat, BNL join) flush status; select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E where a+1 < 10000 + A.a + B.a +C.a+D.a); count(*) diff --git a/mysql-test/r/subselect3_jcl6.result b/mysql-test/r/subselect3_jcl6.result index d794d35cf1a..a62048db506 100644 --- a/mysql-test/r/subselect3_jcl6.result +++ b/mysql-test/r/subselect3_jcl6.result @@ -1154,9 +1154,9 @@ insert into t4 select a from t3; explain select * from t3 where a in (select t1.kp1 from t1,t4 where kp1<20 and t4.pk=t1.c); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using index condition; Using where; LooseScan -1 PRIMARY t4 eq_ref PRIMARY PRIMARY 4 test.t1.c 1 Using index; FirstMatch(t1) -1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where +1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using where +1 PRIMARY t4 eq_ref PRIMARY PRIMARY 4 test.t1.c 1 Using index; FirstMatch(t3) drop table t1, t3, t4; set @@optimizer_switch=@save_optimizer_switch; create table t1 (a int) as select * from t0 where a < 5; @@ -1165,11 +1165,11 @@ set @@optimizer_switch='firstmatch=off,materialization=off'; set @@max_heap_table_size= 16384; explain select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E where a+1 < 10000 + A.a + B.a +C.a+D.a); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY E ALL NULL NULL NULL NULL 5 Using where; Start temporary -1 PRIMARY A ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) -1 PRIMARY B ALL NULL NULL NULL NULL 10 Using join buffer (incremental, BNL join) -1 PRIMARY C ALL NULL NULL NULL NULL 10 Using where; Using join buffer (incremental, BNL join) -1 PRIMARY D hash_ALL NULL #hash#$hj 5 test.E.a 10 Using where; End temporary; Using join buffer (incremental, BNLH join) +1 PRIMARY A ALL NULL NULL NULL NULL 10 +1 PRIMARY B ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) +1 PRIMARY E ALL NULL NULL NULL NULL 5 Using where; Start temporary; Using join buffer (incremental, BNL join) +1 PRIMARY D hash_ALL NULL #hash#$hj 5 test.E.a 10 Using where; Using join buffer (incremental, BNLH join) +1 PRIMARY C ALL NULL NULL NULL NULL 10 Using where; End temporary; Using join buffer (incremental, BNL join) flush status; select count(*) from t0 A, t0 B, t0 C, t0 D where D.a in (select a from t1 E where a+1 < 10000 + A.a + B.a +C.a+D.a); count(*) diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index ecafe57f47a..e8086b53ead 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -4647,6 +4647,55 @@ ERROR 21000: Subquery returns more than 1 row SET SESSION sql_mode=@old_sql_mode; DEALLOCATE PREPARE stmt; DROP TABLE t1; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); +1 +1 +1 +SET SESSION sql_mode=@old_sql_mode; +DROP TABLE t1, t2; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +create table t2(i int); +insert into t2 values(0); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; +CREATE TABLE t1 ( +pk int NOT NULL, +col_varchar_key varchar(1) DEFAULT NULL, +PRIMARY KEY (pk), +KEY col_varchar_key (col_varchar_key) +); +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; +pk +SET SESSION sql_mode=@old_sql_mode; +drop table t2, t1; +drop view v1; End of 5.0 tests. create table t_out (subcase char(3), a1 char(2), b1 char(2), c1 char(2)); @@ -5597,9 +5646,9 @@ WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a FROM it2,it3); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ot1 ALL NULL NULL NULL NULL 2 -1 PRIMARY it2 ALL NULL NULL NULL NULL 4 Using where; Start temporary; Using join buffer (flat, BNL join) -1 PRIMARY it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join) -1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; End temporary; Using join buffer (flat, BNL join) +1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using join buffer (flat, BNL join) +1 PRIMARY it2 ALL NULL NULL NULL NULL 4 Using where +1 PRIMARY it3 ALL NULL NULL NULL NULL 6 Using where; FirstMatch(ot4) DROP TABLE IF EXISTS ot1, ot4, it2, it3; # # Bug#729039: NULL keys used to evaluate subquery diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result index 3079868bbf6..12b1e45c92c 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -4643,6 +4643,55 @@ ERROR 21000: Subquery returns more than 1 row SET SESSION sql_mode=@old_sql_mode; DEALLOCATE PREPARE stmt; DROP TABLE t1; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); +1 +1 +1 +SET SESSION sql_mode=@old_sql_mode; +DROP TABLE t1, t2; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +create table t2(i int); +insert into t2 values(0); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; +CREATE TABLE t1 ( +pk int NOT NULL, +col_varchar_key varchar(1) DEFAULT NULL, +PRIMARY KEY (pk), +KEY col_varchar_key (col_varchar_key) +); +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; +pk +SET SESSION sql_mode=@old_sql_mode; +drop table t2, t1; +drop view v1; End of 5.0 tests. create table t_out (subcase char(3), a1 char(2), b1 char(2), c1 char(2)); diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result index e85f2ccf1e1..b9a4f9b23a9 100644 --- a/mysql-test/r/subselect_no_scache.result +++ b/mysql-test/r/subselect_no_scache.result @@ -4651,6 +4651,55 @@ ERROR 21000: Subquery returns more than 1 row SET SESSION sql_mode=@old_sql_mode; DEALLOCATE PREPARE stmt; DROP TABLE t1; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); +1 +1 +1 +SET SESSION sql_mode=@old_sql_mode; +DROP TABLE t1, t2; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +create table t2(i int); +insert into t2 values(0); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; +CREATE TABLE t1 ( +pk int NOT NULL, +col_varchar_key varchar(1) DEFAULT NULL, +PRIMARY KEY (pk), +KEY col_varchar_key (col_varchar_key) +); +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; +pk +SET SESSION sql_mode=@old_sql_mode; +drop table t2, t1; +drop view v1; End of 5.0 tests. create table t_out (subcase char(3), a1 char(2), b1 char(2), c1 char(2)); @@ -5601,8 +5650,8 @@ WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a FROM it2,it3); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ot1 ALL NULL NULL NULL NULL 2 -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 24 Using where -1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join) +1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using join buffer (flat, BNL join) +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 2 MATERIALIZED it2 ALL NULL NULL NULL NULL 4 2 MATERIALIZED it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join) DROP TABLE IF EXISTS ot1, ot4, it2, it3; diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index 6a84070c2cd..ad6d61e9ec9 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -4643,6 +4643,55 @@ ERROR 21000: Subquery returns more than 1 row SET SESSION sql_mode=@old_sql_mode; DEALLOCATE PREPARE stmt; DROP TABLE t1; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +1 +1 +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +1 +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); +1 +1 +1 +SET SESSION sql_mode=@old_sql_mode; +DROP TABLE t1, t2; +# +# Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +# +create table t2(i int); +insert into t2 values(0); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; +CREATE TABLE t1 ( +pk int NOT NULL, +col_varchar_key varchar(1) DEFAULT NULL, +PRIMARY KEY (pk), +KEY col_varchar_key (col_varchar_key) +); +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; +pk +SET SESSION sql_mode=@old_sql_mode; +drop table t2, t1; +drop view v1; End of 5.0 tests. create table t_out (subcase char(3), a1 char(2), b1 char(2), c1 char(2)); diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index 924d809eb6e..ca834b21df5 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -760,16 +760,16 @@ explain extended select a from t1 where a in (select c from t2 where d >= some(select e from t3 where b=e)); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t2 ALL NULL NULL NULL NULL 6 100.00 Start temporary -1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using where; End temporary; Using join buffer (flat, BNL join) +1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 +1 PRIMARY t2 ALL NULL NULL NULL NULL 6 100.00 Using where; FirstMatch(t1) 3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where Warnings: Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1 -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a` = `test`.`t2`.`c`) and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where ((`test`.`t1`.`b` = `test`.`t3`.`e`) and (<cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where ((`test`.`t1`.`b` = `test`.`t3`.`e`) and (<cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))))) show warnings; Level Code Message Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1 -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a` = `test`.`t2`.`c`) and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where ((`test`.`t1`.`b` = `test`.`t3`.`e`) and (<cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where ((`test`.`t1`.`b` = `test`.`t3`.`e`) and (<cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))))) select a from t1 where a in (select c from t2 where d >= some(select e from t3 where b=e)); a @@ -2168,10 +2168,10 @@ INSERT INTO t5 VALUES (7,0),(9,0); explain SELECT * FROM t3 WHERE t3.a IN (SELECT t5.a FROM t2, t4, t5 WHERE t2.c = t5.a AND t2.b = t5.b); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t5 index a a 10 NULL 2 Using where; Using index; LooseScan +1 PRIMARY t5 index a a 10 NULL 2 Using index; Start temporary 1 PRIMARY t4 ALL NULL NULL NULL NULL 3 -1 PRIMARY t2 ref b b 5 test.t5.b 2 Using where; FirstMatch(t5) -1 PRIMARY t3 ALL NULL NULL NULL NULL 15 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t2 ALL b NULL NULL NULL 10 Using where +1 PRIMARY t3 ALL NULL NULL NULL NULL 15 Using where; End temporary; Using join buffer (flat, BNL join) SELECT * FROM t3 WHERE t3.a IN (SELECT t5.a FROM t2, t4, t5 WHERE t2.c = t5.a AND t2.b = t5.b); a 0 @@ -2250,11 +2250,11 @@ alias1.c IN (SELECT SQ3_alias1.b FROM t2 AS SQ3_alias1 STRAIGHT_JOIN t2 AS SQ3_alias2) LIMIT 100; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <derived2> ALL NULL NULL NULL NULL 20 +1 PRIMARY SQ3_alias1 ALL NULL NULL NULL NULL 20 Start temporary +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join) +1 PRIMARY SQ3_alias2 index NULL PRIMARY 4 NULL 20 Using index; End temporary 1 PRIMARY alias2 ALL NULL NULL NULL NULL 20 Using join buffer (flat, BNL join) 1 PRIMARY t2 ALL NULL NULL NULL NULL 20 Using join buffer (flat, BNL join) -1 PRIMARY SQ3_alias1 ALL NULL NULL NULL NULL 20 Using where; Start temporary -1 PRIMARY SQ3_alias2 index NULL PRIMARY 4 NULL 20 Using index; End temporary 2 DERIVED t2 ALL NULL NULL NULL NULL 20 create table t3 as SELECT @@ -2638,4 +2638,37 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join) drop table t0,t1,t3; set optimizer_switch= @tmp_923246; +# +# BUG#952583: Server crashes in Item_field::fix_after_pullout on INSERT .. SELECT +# +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 ( b INT ); +INSERT INTO t2 VALUES (3),(4); +INSERT INTO t1 +SELECT * FROM ( SELECT * FROM t1 ) AS alias +WHERE a IN ( SELECT b FROM t2 ); +DROP TABLE t1, t2; +# +# BUG#952372: Server crashes on 2nd execution of PS in find_field_in_tables with semijoin+materialization +# +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (2),(3); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 ( b VARCHAR(1) ); +INSERT INTO t2 VALUES ('v'),('v'); +PREPARE pstmt FROM +'SELECT DISTINCT a FROM v1, t2 + WHERE b IN ( SELECT MIN(b) FROM t2 )'; +EXECUTE pstmt; +a +2 +3 +EXECUTE pstmt; +a +2 +3 +DEALLOCATE PREPARE pstmt; +DROP VIEW v1; +DROP TABLE t1, t2; set optimizer_switch=@subselect_sj_tmp; diff --git a/mysql-test/r/subselect_sj2.result b/mysql-test/r/subselect_sj2.result index 0c41fef01ea..97e36cd705c 100644 --- a/mysql-test/r/subselect_sj2.result +++ b/mysql-test/r/subselect_sj2.result @@ -49,9 +49,9 @@ a b 19 14 explain select * from t2 where b in (select a from t1); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 -1 PRIMARY t2 ref b b 5 test.t1.a 2 -2 MATERIALIZED t1 ALL NULL NULL NULL NULL 3 Using where +1 PRIMARY t2 ALL b NULL NULL NULL 20 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED t1 ALL NULL NULL NULL NULL 3 select * from t2 where b in (select a from t1); a b 1 1 @@ -69,9 +69,9 @@ insert into t3 select a,a, a,a,a from t0; insert into t3 select a,a, a+100,a+100,a+100 from t0; explain select * from t3 where b in (select a from t1); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 -1 PRIMARY t3 ref b b 5 test.t1.a 1 -2 MATERIALIZED t1 ALL NULL NULL NULL NULL 3 Using where +1 PRIMARY t3 ALL b NULL NULL NULL 20 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED t1 ALL NULL NULL NULL NULL 3 select * from t3 where b in (select a from t1); a b pk1 pk2 pk3 1 1 1 1 1 @@ -95,13 +95,17 @@ A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a from t0 A, t0 B where B.a <5; explain select * from t3 where b in (select a from t0); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 10 -1 PRIMARY t3 ref b b 5 test.t0.a 1 -2 MATERIALIZED t0 ALL NULL NULL NULL NULL 10 Using where +1 PRIMARY t3 ALL b NULL NULL NULL # +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # +2 MATERIALIZED t0 ALL NULL NULL NULL NULL # select * from t3 where b in (select A.a+B.a from t0 A, t0 B where B.a<5); a b pk1 pk2 0 0 0 0 1 1 1 1 +10 10 10 10 +11 11 11 11 +12 12 12 12 +13 13 13 13 2 2 2 2 3 3 3 3 4 4 4 4 @@ -110,10 +114,6 @@ a b pk1 pk2 7 7 7 7 8 8 8 8 9 9 9 9 -10 10 10 10 -11 11 11 11 -12 12 12 12 -13 13 13 13 set join_buffer_size= @save_join_buffer_size; set max_heap_table_size= @save_max_heap_table_size; explain select * from t1 where a in (select b from t2); @@ -745,8 +745,8 @@ c2 in (select 1 from t3, t2) and c1 in (select convert(c6,char(1)) from t2); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where +1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; FirstMatch(t2) 1 PRIMARY t2 ALL NULL NULL NULL NULL 1 -1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where 1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch(t2) drop table t2, t3; # @@ -900,5 +900,199 @@ a b c 3 1 1 4 1 1 DROP TABLE t1,t2; +# +# BUG#962667: Assertion `0' failed in QUICK_INDEX_SORT_SELECT::need_sorted_output() +# with index_merge+index_merge_sort_union+loosescan+semijoin +# +CREATE TABLE t1 ( +a INT, b VARCHAR(1), c INT, +KEY(a), KEY(b) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(1,'v',9),(2,'v',8),(3,'c',7),(4,'m',6),(5,'x',5), +(6,'i',4),(7,'e',3),(8,'p',2),(9,'s',1),(10,'j',9), +(11,'z',8),(12,'c',7),(13,'a',6),(14,'q',5),(15,'y',4), +(16,'n',3),(17,'r',2),(18,'v',1),(19,'p',0); +CREATE TABLE t2 ( +pk INT, d VARCHAR(1), e INT, +PRIMARY KEY(pk), KEY(d,e) +) ENGINE=InnoDB; +INSERT INTO t2 VALUES +(1,'x',1),(2,'d',2),(3,'r',3),(4,'f',4),(5,'y',5), +(6,'u',6),(7,'m',7),(8,'k',8),(9,'o',9),(10,'w',1), +(11,'m',2),(12,'q',3),(13,'m',4),(14,'d',5), +(15,'g',6),(16,'x',7),(17,'f',8); +explain +SELECT * FROM t1 WHERE b IN ( +SELECT d FROM t2, t1 +WHERE a = d AND ( pk < 2 OR d = 'z' ) +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL b NULL NULL NULL 19 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED t2 index PRIMARY,d d 9 NULL 17 Using where; Using index +2 MATERIALIZED t1 ref a a 5 test.t2.d 1 Using where; Using index +SELECT * FROM t1 WHERE b IN ( +SELECT d FROM t2, t1 +WHERE a = d AND ( pk < 2 OR d = 'z' ) +); +a b c +DROP TABLE t1, t2; +# +# BUG#951937: Wrong result (missing rows) with semijoin+materialization, IN subquery, InnoDB, TEMPTABLE view +# +CREATE TABLE t1 ( +a VARCHAR(1), +b VARCHAR(1) NOT NULL, +KEY(a) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES +('j','j'),('v','v'),('c','c'),('m','m'),('d','d'), +('y','y'),('t','t'),('d','d'),('s','s'),('r','r'), +('m','m'),('b','b'),('x','x'),('g','g'),('p','p'), +('q','q'),('w','w'),('d','d'),('e','e'); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +# This query returned 6 rows instead of 19 +SELECT * FROM v1 +WHERE ( a, a ) IN ( +SELECT alias2.b, alias2.a +FROM t1 AS alias1, t1 AS alias2 +WHERE alias2.b = alias1.a +AND ( alias1.b >= alias1.a OR alias2.b = 'z' ) +); +a b +b b +c c +d d +d d +d d +e e +g g +j j +m m +m m +p p +q q +r r +s s +t t +v v +w w +x x +y y +# Another testcase, without the VIEW: +CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(1) NOT NULL, KEY(a)) ENGINE=InnoDB; +INSERT INTO t2 SELECT * FROM t1; +INSERT INTO t2 SELECT * FROM t1; +EXPLAIN +SELECT * FROM t2 +WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2 +WHERE +alias2.b = alias1.a AND +(alias1.b >= alias1.a OR alias2.b = 'z')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL a NULL NULL NULL 38 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 +2 MATERIALIZED alias1 ALL a NULL NULL NULL 19 Using where +2 MATERIALIZED alias2 ref a a 4 test.alias1.a 1 Using where +SELECT * FROM t2 +WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2 +WHERE +alias2.b = alias1.a AND +(alias1.b >= alias1.a OR alias2.b = 'z')); +a b +b b +b b +c c +c c +d d +d d +d d +d d +d d +d d +e e +e e +g g +g g +j j +j j +m m +m m +m m +m m +p p +p p +q q +q q +r r +r r +s s +s s +t t +t t +v v +v v +w w +w w +x x +x x +y y +y y +DROP VIEW v1; +DROP TABLE t1, t2; +# +# BUG#965872: Server crashes in embedding_sjm on a simple 1-table select with AND and OR +# (this is a regression caused by the fix for BUG#951937) +CREATE TABLE t1 ( a INT, b INT, c INT, d INT ); +INSERT INTO t1 VALUES (4,2,8,9),(4,2,7,8); +SELECT * FROM t1 +WHERE a = d AND ( b = 50 AND b = d OR a = c ); +a b c d +DROP TABLE t1; +# +# BUG#951283: Wrong result (missing rows) with semijoin+firstmatch, IN/ANY subquery +# +set @tmp_951283=@@optimizer_prune_level; +SET optimizer_prune_level=0; +CREATE TABLE t1 ( a INT ) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(10),(11),(12),(13),(14),(15),(16), +(17),(18),(19),(20),(21),(22),(23); +CREATE TABLE t2 ( +b INT PRIMARY KEY, +c VARCHAR(1), +d VARCHAR(1), +KEY(c) +) ENGINE=InnoDB; +INSERT INTO t2 VALUES +(1,'j','j'),(2,'v','v'),(3,'c','c'),(4,'m','m'), +(5,'d','d'),(6,'d','d'),(7,'y','y'),(8,'t','t'), +(9,'d','d'),(10,'s','s'),(11,'r','r'),(12,'m','m'), +(13,'b','b'),(14,'x','x'),(15,'g','g'),(16,'p','p'), +(17,'q','q'),(18,'w','w'),(19,'d','d'); +EXPLAIN +SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3 +WHERE alias3.d IN ( +SELECT alias4.c FROM t2 AS alias4, t2 AS alias5 +WHERE alias5.b = alias4.b +AND ( alias5.b >= alias3.b OR alias5.c != alias3.c ) +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY alias3 ALL PRIMARY NULL NULL NULL 19 Using where +1 PRIMARY alias4 ref PRIMARY,c c 4 test.alias3.d 1 Using index +1 PRIMARY alias5 eq_ref PRIMARY PRIMARY 4 test.alias4.b 1 Using where; FirstMatch(alias3) +1 PRIMARY alias2 ALL NULL NULL NULL NULL 14 Using join buffer (flat, BNL join) +1 PRIMARY alias1 ALL NULL NULL NULL NULL 14 Using join buffer (flat, BNL join) +SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3 +WHERE alias3.d IN ( +SELECT alias4.c FROM t2 AS alias4, t2 AS alias5 +WHERE alias5.b = alias4.b +AND ( alias5.b >= alias3.b OR alias5.c != alias3.c ) +); +COUNT(*) +3724 +set optimizer_prune_level=@tmp_951283; +DROP TABLE t1,t2; # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; diff --git a/mysql-test/r/subselect_sj2_jcl6,innodb_plugin.rdiff b/mysql-test/r/subselect_sj2_jcl6,innodb_plugin.rdiff index 528d3ac08ea..c32f52fe0c2 100644 --- a/mysql-test/r/subselect_sj2_jcl6,innodb_plugin.rdiff +++ b/mysql-test/r/subselect_sj2_jcl6,innodb_plugin.rdiff @@ -1,20 +1,11 @@ ---- r/subselect_sj2_jcl6.result 2012-01-11 18:05:14.000000000 +0100 -+++ r/subselect_sj2_jcl6.reject 2012-02-07 12:52:32.000000000 +0100 -@@ -81,7 +81,7 @@ - explain select * from t3 where b in (select a from t1); - id select_type table type possible_keys key key_len ref rows Extra - 1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 --1 PRIMARY t3 ref b b 5 test.t1.a 1 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan -+1 PRIMARY t3 ref b b 5 test.t1.a 1 - 2 MATERIALIZED t1 ALL NULL NULL NULL NULL 3 Using where - select * from t3 where b in (select a from t1); - a b pk1 pk2 pk3 -@@ -107,7 +107,7 @@ - explain select * from t3 where b in (select a from t0); - id select_type table type possible_keys key key_len ref rows Extra - 1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 10 --1 PRIMARY t3 ref b b 5 test.t0.a 1 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan -+1 PRIMARY t3 ref b b 5 test.t0.a 1 - 2 MATERIALIZED t0 ALL NULL NULL NULL NULL 10 Using where - select * from t3 where b in (select A.a+B.a from t0 A, t0 B where B.a<5); - a b pk1 pk2 +--- r/subselect_sj2_jcl6.result 2012-04-07 12:45:03.000000000 +0200 ++++ r/subselect_sj2_jcl6,innodb_plugin.reject 2012-04-07 13:10:38.000000000 +0200 +@@ -1009,7 +1009,7 @@ + 1 PRIMARY t2 ALL a NULL NULL NULL 38 + 1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 + 2 MATERIALIZED alias1 ALL a NULL NULL NULL 19 Using where +-2 MATERIALIZED alias2 ref a a 4 test.alias1.a 1 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan ++2 MATERIALIZED alias2 ref a a 4 test.alias1.a 1 Using where + SELECT * FROM t2 + WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2 + WHERE diff --git a/mysql-test/r/subselect_sj2_jcl6.result b/mysql-test/r/subselect_sj2_jcl6.result index 073f1619b91..e4030b8138b 100644 --- a/mysql-test/r/subselect_sj2_jcl6.result +++ b/mysql-test/r/subselect_sj2_jcl6.result @@ -60,9 +60,9 @@ a b 19 14 explain select * from t2 where b in (select a from t1); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 -1 PRIMARY t2 ref b b 5 test.t1.a 2 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan -2 MATERIALIZED t1 ALL NULL NULL NULL NULL 3 Using where +1 PRIMARY t2 ALL b NULL NULL NULL 20 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED t1 ALL NULL NULL NULL NULL 3 select * from t2 where b in (select a from t1); a b 1 1 @@ -80,9 +80,9 @@ insert into t3 select a,a, a,a,a from t0; insert into t3 select a,a, a+100,a+100,a+100 from t0; explain select * from t3 where b in (select a from t1); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 -1 PRIMARY t3 ref b b 5 test.t1.a 1 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan -2 MATERIALIZED t1 ALL NULL NULL NULL NULL 3 Using where +1 PRIMARY t3 ALL b NULL NULL NULL 20 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED t1 ALL NULL NULL NULL NULL 3 select * from t3 where b in (select a from t1); a b pk1 pk2 pk3 1 1 1 1 1 @@ -106,13 +106,17 @@ A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a from t0 A, t0 B where B.a <5; explain select * from t3 where b in (select a from t0); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 10 -1 PRIMARY t3 ref b b 5 test.t0.a 1 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan -2 MATERIALIZED t0 ALL NULL NULL NULL NULL 10 Using where +1 PRIMARY t3 ALL b NULL NULL NULL # +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # +2 MATERIALIZED t0 ALL NULL NULL NULL NULL # select * from t3 where b in (select A.a+B.a from t0 A, t0 B where B.a<5); a b pk1 pk2 0 0 0 0 1 1 1 1 +10 10 10 10 +11 11 11 11 +12 12 12 12 +13 13 13 13 2 2 2 2 3 3 3 3 4 4 4 4 @@ -121,10 +125,6 @@ a b pk1 pk2 7 7 7 7 8 8 8 8 9 9 9 9 -10 10 10 10 -11 11 11 11 -12 12 12 12 -13 13 13 13 set join_buffer_size= @save_join_buffer_size; set max_heap_table_size= @save_max_heap_table_size; explain select * from t1 where a in (select b from t2); @@ -759,9 +759,10 @@ c2 in (select 1 from t3, t2) and c1 in (select convert(c6,char(1)) from t2); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where +1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 Using where 1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join) -1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; Using join buffer (incremental, BNL join) -1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch(t2); Using join buffer (incremental, BNL join) +1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch((sj-nest)); Using join buffer (incremental, BNL join) +3 MATERIALIZED t2 ALL NULL NULL NULL NULL 1 drop table t2, t3; # # BUG#761598: InnoDB: Error: row_search_for_mysql() is called without ha_innobase::external_lock() in maria-5.3 @@ -914,6 +915,200 @@ a b c 3 1 1 4 1 1 DROP TABLE t1,t2; +# +# BUG#962667: Assertion `0' failed in QUICK_INDEX_SORT_SELECT::need_sorted_output() +# with index_merge+index_merge_sort_union+loosescan+semijoin +# +CREATE TABLE t1 ( +a INT, b VARCHAR(1), c INT, +KEY(a), KEY(b) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(1,'v',9),(2,'v',8),(3,'c',7),(4,'m',6),(5,'x',5), +(6,'i',4),(7,'e',3),(8,'p',2),(9,'s',1),(10,'j',9), +(11,'z',8),(12,'c',7),(13,'a',6),(14,'q',5),(15,'y',4), +(16,'n',3),(17,'r',2),(18,'v',1),(19,'p',0); +CREATE TABLE t2 ( +pk INT, d VARCHAR(1), e INT, +PRIMARY KEY(pk), KEY(d,e) +) ENGINE=InnoDB; +INSERT INTO t2 VALUES +(1,'x',1),(2,'d',2),(3,'r',3),(4,'f',4),(5,'y',5), +(6,'u',6),(7,'m',7),(8,'k',8),(9,'o',9),(10,'w',1), +(11,'m',2),(12,'q',3),(13,'m',4),(14,'d',5), +(15,'g',6),(16,'x',7),(17,'f',8); +explain +SELECT * FROM t1 WHERE b IN ( +SELECT d FROM t2, t1 +WHERE a = d AND ( pk < 2 OR d = 'z' ) +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL b NULL NULL NULL 19 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED t2 index PRIMARY,d d 9 NULL 17 Using where; Using index +2 MATERIALIZED t1 ref a a 5 test.t2.d 1 Using where; Using index +SELECT * FROM t1 WHERE b IN ( +SELECT d FROM t2, t1 +WHERE a = d AND ( pk < 2 OR d = 'z' ) +); +a b c +DROP TABLE t1, t2; +# +# BUG#951937: Wrong result (missing rows) with semijoin+materialization, IN subquery, InnoDB, TEMPTABLE view +# +CREATE TABLE t1 ( +a VARCHAR(1), +b VARCHAR(1) NOT NULL, +KEY(a) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES +('j','j'),('v','v'),('c','c'),('m','m'),('d','d'), +('y','y'),('t','t'),('d','d'),('s','s'),('r','r'), +('m','m'),('b','b'),('x','x'),('g','g'),('p','p'), +('q','q'),('w','w'),('d','d'),('e','e'); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +# This query returned 6 rows instead of 19 +SELECT * FROM v1 +WHERE ( a, a ) IN ( +SELECT alias2.b, alias2.a +FROM t1 AS alias1, t1 AS alias2 +WHERE alias2.b = alias1.a +AND ( alias1.b >= alias1.a OR alias2.b = 'z' ) +); +a b +b b +c c +d d +d d +d d +e e +g g +j j +m m +m m +p p +q q +r r +s s +t t +v v +w w +x x +y y +# Another testcase, without the VIEW: +CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(1) NOT NULL, KEY(a)) ENGINE=InnoDB; +INSERT INTO t2 SELECT * FROM t1; +INSERT INTO t2 SELECT * FROM t1; +EXPLAIN +SELECT * FROM t2 +WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2 +WHERE +alias2.b = alias1.a AND +(alias1.b >= alias1.a OR alias2.b = 'z')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL a NULL NULL NULL 38 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 +2 MATERIALIZED alias1 ALL a NULL NULL NULL 19 Using where +2 MATERIALIZED alias2 ref a a 4 test.alias1.a 1 Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan +SELECT * FROM t2 +WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2 +WHERE +alias2.b = alias1.a AND +(alias1.b >= alias1.a OR alias2.b = 'z')); +a b +b b +b b +c c +c c +d d +d d +d d +d d +d d +d d +e e +e e +g g +g g +j j +j j +m m +m m +m m +m m +p p +p p +q q +q q +r r +r r +s s +s s +t t +t t +v v +v v +w w +w w +x x +x x +y y +y y +DROP VIEW v1; +DROP TABLE t1, t2; +# +# BUG#965872: Server crashes in embedding_sjm on a simple 1-table select with AND and OR +# (this is a regression caused by the fix for BUG#951937) +CREATE TABLE t1 ( a INT, b INT, c INT, d INT ); +INSERT INTO t1 VALUES (4,2,8,9),(4,2,7,8); +SELECT * FROM t1 +WHERE a = d AND ( b = 50 AND b = d OR a = c ); +a b c d +DROP TABLE t1; +# +# BUG#951283: Wrong result (missing rows) with semijoin+firstmatch, IN/ANY subquery +# +set @tmp_951283=@@optimizer_prune_level; +SET optimizer_prune_level=0; +CREATE TABLE t1 ( a INT ) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(10),(11),(12),(13),(14),(15),(16), +(17),(18),(19),(20),(21),(22),(23); +CREATE TABLE t2 ( +b INT PRIMARY KEY, +c VARCHAR(1), +d VARCHAR(1), +KEY(c) +) ENGINE=InnoDB; +INSERT INTO t2 VALUES +(1,'j','j'),(2,'v','v'),(3,'c','c'),(4,'m','m'), +(5,'d','d'),(6,'d','d'),(7,'y','y'),(8,'t','t'), +(9,'d','d'),(10,'s','s'),(11,'r','r'),(12,'m','m'), +(13,'b','b'),(14,'x','x'),(15,'g','g'),(16,'p','p'), +(17,'q','q'),(18,'w','w'),(19,'d','d'); +EXPLAIN +SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3 +WHERE alias3.d IN ( +SELECT alias4.c FROM t2 AS alias4, t2 AS alias5 +WHERE alias5.b = alias4.b +AND ( alias5.b >= alias3.b OR alias5.c != alias3.c ) +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY alias3 ALL PRIMARY NULL NULL NULL 19 Using where +1 PRIMARY alias4 ref PRIMARY,c c 4 test.alias3.d 1 Using index +1 PRIMARY alias5 eq_ref PRIMARY PRIMARY 4 test.alias4.b 1 Using where; FirstMatch(alias3) +1 PRIMARY alias2 ALL NULL NULL NULL NULL 14 Using join buffer (flat, BNL join) +1 PRIMARY alias1 ALL NULL NULL NULL NULL 14 Using join buffer (incremental, BNL join) +SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3 +WHERE alias3.d IN ( +SELECT alias4.c FROM t2 AS alias4, t2 AS alias5 +WHERE alias5.b = alias4.b +AND ( alias5.b >= alias3.b OR alias5.c != alias3.c ) +); +COUNT(*) +3724 +set optimizer_prune_level=@tmp_951283; +DROP TABLE t1,t2; # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; # @@ -935,9 +1130,9 @@ SELECT t3.* FROM t1 JOIN t3 ON t3.b = t1.b WHERE c IN (SELECT t4.b FROM t4 JOIN t2); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 1 Using where -1 PRIMARY t2 ALL NULL NULL NULL NULL 1 FirstMatch(t3) +1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join) +1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; FirstMatch(t3); Using join buffer (incremental, BNL join) 1 PRIMARY t1 ref b b 4 test.t3.b 1 Using index -1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; FirstMatch(t1) SELECT t3.* FROM t1 JOIN t3 ON t3.b = t1.b WHERE c IN (SELECT t4.b FROM t4 JOIN t2); b c @@ -963,9 +1158,9 @@ EXPLAIN SELECT * FROM t1, t2 WHERE b IN (SELECT a FROM t3, t4 WHERE b = pk); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 1 -1 PRIMARY t4 ALL NULL NULL NULL NULL 1 Using where; FirstMatch(t2) -1 PRIMARY t1 ALL NULL NULL NULL NULL 2 -1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.b 1 Using where; FirstMatch(t1) +1 PRIMARY t4 ALL NULL NULL NULL NULL 1 Using where +1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.b 1 Using where; FirstMatch(t2) +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join) SELECT * FROM t1, t2 WHERE b IN (SELECT a FROM t3, t4 WHERE b = pk); pk a b 1 6 8 diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result index f15492c7322..f69befc8608 100644 --- a/mysql-test/r/subselect_sj2_mat.result +++ b/mysql-test/r/subselect_sj2_mat.result @@ -51,9 +51,9 @@ a b 19 14 explain select * from t2 where b in (select a from t1); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 -1 PRIMARY t2 ref b b 5 test.t1.a 2 -2 MATERIALIZED t1 ALL NULL NULL NULL NULL 3 Using where +1 PRIMARY t2 ALL b NULL NULL NULL 20 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED t1 ALL NULL NULL NULL NULL 3 select * from t2 where b in (select a from t1); a b 1 1 @@ -71,9 +71,9 @@ insert into t3 select a,a, a,a,a from t0; insert into t3 select a,a, a+100,a+100,a+100 from t0; explain select * from t3 where b in (select a from t1); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 -1 PRIMARY t3 ref b b 5 test.t1.a 1 -2 MATERIALIZED t1 ALL NULL NULL NULL NULL 3 Using where +1 PRIMARY t3 ALL b NULL NULL NULL 20 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED t1 ALL NULL NULL NULL NULL 3 select * from t3 where b in (select a from t1); a b pk1 pk2 pk3 1 1 1 1 1 @@ -97,13 +97,17 @@ A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a from t0 A, t0 B where B.a <5; explain select * from t3 where b in (select a from t0); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 10 -1 PRIMARY t3 ref b b 5 test.t0.a 1 -2 MATERIALIZED t0 ALL NULL NULL NULL NULL 10 Using where +1 PRIMARY t3 ALL b NULL NULL NULL # +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func # +2 MATERIALIZED t0 ALL NULL NULL NULL NULL # select * from t3 where b in (select A.a+B.a from t0 A, t0 B where B.a<5); a b pk1 pk2 0 0 0 0 1 1 1 1 +10 10 10 10 +11 11 11 11 +12 12 12 12 +13 13 13 13 2 2 2 2 3 3 3 3 4 4 4 4 @@ -112,10 +116,6 @@ a b pk1 pk2 7 7 7 7 8 8 8 8 9 9 9 9 -10 10 10 10 -11 11 11 11 -12 12 12 12 -13 13 13 13 set join_buffer_size= @save_join_buffer_size; set max_heap_table_size= @save_max_heap_table_size; explain select * from t1 where a in (select b from t2); @@ -747,8 +747,8 @@ c2 in (select 1 from t3, t2) and c1 in (select convert(c6,char(1)) from t2); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where +1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; FirstMatch(t2) 1 PRIMARY t2 ALL NULL NULL NULL NULL 1 -1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where 1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch(t2) drop table t2, t3; # @@ -902,6 +902,200 @@ a b c 3 1 1 4 1 1 DROP TABLE t1,t2; +# +# BUG#962667: Assertion `0' failed in QUICK_INDEX_SORT_SELECT::need_sorted_output() +# with index_merge+index_merge_sort_union+loosescan+semijoin +# +CREATE TABLE t1 ( +a INT, b VARCHAR(1), c INT, +KEY(a), KEY(b) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(1,'v',9),(2,'v',8),(3,'c',7),(4,'m',6),(5,'x',5), +(6,'i',4),(7,'e',3),(8,'p',2),(9,'s',1),(10,'j',9), +(11,'z',8),(12,'c',7),(13,'a',6),(14,'q',5),(15,'y',4), +(16,'n',3),(17,'r',2),(18,'v',1),(19,'p',0); +CREATE TABLE t2 ( +pk INT, d VARCHAR(1), e INT, +PRIMARY KEY(pk), KEY(d,e) +) ENGINE=InnoDB; +INSERT INTO t2 VALUES +(1,'x',1),(2,'d',2),(3,'r',3),(4,'f',4),(5,'y',5), +(6,'u',6),(7,'m',7),(8,'k',8),(9,'o',9),(10,'w',1), +(11,'m',2),(12,'q',3),(13,'m',4),(14,'d',5), +(15,'g',6),(16,'x',7),(17,'f',8); +explain +SELECT * FROM t1 WHERE b IN ( +SELECT d FROM t2, t1 +WHERE a = d AND ( pk < 2 OR d = 'z' ) +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL b NULL NULL NULL 19 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED t2 index PRIMARY,d d 9 NULL 17 Using where; Using index +2 MATERIALIZED t1 ref a a 5 test.t2.d 1 Using where; Using index +SELECT * FROM t1 WHERE b IN ( +SELECT d FROM t2, t1 +WHERE a = d AND ( pk < 2 OR d = 'z' ) +); +a b c +DROP TABLE t1, t2; +# +# BUG#951937: Wrong result (missing rows) with semijoin+materialization, IN subquery, InnoDB, TEMPTABLE view +# +CREATE TABLE t1 ( +a VARCHAR(1), +b VARCHAR(1) NOT NULL, +KEY(a) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES +('j','j'),('v','v'),('c','c'),('m','m'),('d','d'), +('y','y'),('t','t'),('d','d'),('s','s'),('r','r'), +('m','m'),('b','b'),('x','x'),('g','g'),('p','p'), +('q','q'),('w','w'),('d','d'),('e','e'); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +# This query returned 6 rows instead of 19 +SELECT * FROM v1 +WHERE ( a, a ) IN ( +SELECT alias2.b, alias2.a +FROM t1 AS alias1, t1 AS alias2 +WHERE alias2.b = alias1.a +AND ( alias1.b >= alias1.a OR alias2.b = 'z' ) +); +a b +b b +c c +d d +d d +d d +e e +g g +j j +m m +m m +p p +q q +r r +s s +t t +v v +w w +x x +y y +# Another testcase, without the VIEW: +CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(1) NOT NULL, KEY(a)) ENGINE=InnoDB; +INSERT INTO t2 SELECT * FROM t1; +INSERT INTO t2 SELECT * FROM t1; +EXPLAIN +SELECT * FROM t2 +WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2 +WHERE +alias2.b = alias1.a AND +(alias1.b >= alias1.a OR alias2.b = 'z')); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL a NULL NULL NULL 38 +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 +2 MATERIALIZED alias1 ALL a NULL NULL NULL 19 Using where +2 MATERIALIZED alias2 ref a a 4 test.alias1.a 1 Using where +SELECT * FROM t2 +WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2 +WHERE +alias2.b = alias1.a AND +(alias1.b >= alias1.a OR alias2.b = 'z')); +a b +b b +b b +c c +c c +d d +d d +d d +d d +d d +d d +e e +e e +g g +g g +j j +j j +m m +m m +m m +m m +p p +p p +q q +q q +r r +r r +s s +s s +t t +t t +v v +v v +w w +w w +x x +x x +y y +y y +DROP VIEW v1; +DROP TABLE t1, t2; +# +# BUG#965872: Server crashes in embedding_sjm on a simple 1-table select with AND and OR +# (this is a regression caused by the fix for BUG#951937) +CREATE TABLE t1 ( a INT, b INT, c INT, d INT ); +INSERT INTO t1 VALUES (4,2,8,9),(4,2,7,8); +SELECT * FROM t1 +WHERE a = d AND ( b = 50 AND b = d OR a = c ); +a b c d +DROP TABLE t1; +# +# BUG#951283: Wrong result (missing rows) with semijoin+firstmatch, IN/ANY subquery +# +set @tmp_951283=@@optimizer_prune_level; +SET optimizer_prune_level=0; +CREATE TABLE t1 ( a INT ) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(10),(11),(12),(13),(14),(15),(16), +(17),(18),(19),(20),(21),(22),(23); +CREATE TABLE t2 ( +b INT PRIMARY KEY, +c VARCHAR(1), +d VARCHAR(1), +KEY(c) +) ENGINE=InnoDB; +INSERT INTO t2 VALUES +(1,'j','j'),(2,'v','v'),(3,'c','c'),(4,'m','m'), +(5,'d','d'),(6,'d','d'),(7,'y','y'),(8,'t','t'), +(9,'d','d'),(10,'s','s'),(11,'r','r'),(12,'m','m'), +(13,'b','b'),(14,'x','x'),(15,'g','g'),(16,'p','p'), +(17,'q','q'),(18,'w','w'),(19,'d','d'); +EXPLAIN +SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3 +WHERE alias3.d IN ( +SELECT alias4.c FROM t2 AS alias4, t2 AS alias5 +WHERE alias5.b = alias4.b +AND ( alias5.b >= alias3.b OR alias5.c != alias3.c ) +); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY alias3 ALL PRIMARY NULL NULL NULL 19 Using where +1 PRIMARY alias4 ref PRIMARY,c c 4 test.alias3.d 1 Using index +1 PRIMARY alias5 eq_ref PRIMARY PRIMARY 4 test.alias4.b 1 Using where; FirstMatch(alias3) +1 PRIMARY alias2 ALL NULL NULL NULL NULL 14 Using join buffer (flat, BNL join) +1 PRIMARY alias1 ALL NULL NULL NULL NULL 14 Using join buffer (flat, BNL join) +SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3 +WHERE alias3.d IN ( +SELECT alias4.c FROM t2 AS alias4, t2 AS alias5 +WHERE alias5.b = alias4.b +AND ( alias5.b >= alias3.b OR alias5.c != alias3.c ) +); +COUNT(*) +3724 +set optimizer_prune_level=@tmp_951283; +DROP TABLE t1,t2; # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; set optimizer_switch=default; diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result index 6a45a5866f6..19f3baac5f2 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -773,16 +773,16 @@ explain extended select a from t1 where a in (select c from t2 where d >= some(select e from t3 where b=e)); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY t2 ALL NULL NULL NULL NULL 6 100.00 Start temporary -1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using where; End temporary; Using join buffer (flat, BNL join) +1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 +1 PRIMARY t2 ALL NULL NULL NULL NULL 6 100.00 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) 3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 4 100.00 Using where Warnings: Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1 -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a` = `test`.`t2`.`c`) and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where ((`test`.`t1`.`b` = `test`.`t3`.`e`) and (<cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where ((`test`.`t1`.`b` = `test`.`t3`.`e`) and (<cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))))) show warnings; Level Code Message Note 1276 Field or reference 'test.t1.b' of SELECT #3 was resolved in SELECT #1 -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a` = `test`.`t2`.`c`) and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where ((`test`.`t1`.`b` = `test`.`t3`.`e`) and (<cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))))) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`c` = `test`.`t1`.`a`) and <nop>(<expr_cache><`test`.`t2`.`d`,`test`.`t1`.`b`>(<in_optimizer>(`test`.`t2`.`d`,<exists>(select `test`.`t3`.`e` from `test`.`t3` where ((`test`.`t1`.`b` = `test`.`t3`.`e`) and (<cache>(`test`.`t2`.`d`) >= `test`.`t3`.`e`))))))) select a from t1 where a in (select c from t2 where d >= some(select e from t3 where b=e)); a @@ -2182,10 +2182,10 @@ INSERT INTO t5 VALUES (7,0),(9,0); explain SELECT * FROM t3 WHERE t3.a IN (SELECT t5.a FROM t2, t4, t5 WHERE t2.c = t5.a AND t2.b = t5.b); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t5 index a a 10 NULL 2 Using where; Using index; LooseScan -1 PRIMARY t4 ALL NULL NULL NULL NULL 3 -1 PRIMARY t2 ref b b 5 test.t5.b 2 Using where; FirstMatch(t5) -1 PRIMARY t3 ALL NULL NULL NULL NULL 15 Using where; Using join buffer (flat, BNL join) +1 PRIMARY t5 index a a 10 NULL 2 Using index; Start temporary +1 PRIMARY t4 ALL NULL NULL NULL NULL 3 Using join buffer (flat, BNL join) +1 PRIMARY t2 ALL b NULL NULL NULL 10 Using where; Using join buffer (incremental, BNL join) +1 PRIMARY t3 ALL NULL NULL NULL NULL 15 Using where; End temporary; Using join buffer (incremental, BNL join) SELECT * FROM t3 WHERE t3.a IN (SELECT t5.a FROM t2, t4, t5 WHERE t2.c = t5.a AND t2.b = t5.b); a 0 @@ -2264,11 +2264,11 @@ alias1.c IN (SELECT SQ3_alias1.b FROM t2 AS SQ3_alias1 STRAIGHT_JOIN t2 AS SQ3_alias2) LIMIT 100; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <derived2> ALL NULL NULL NULL NULL 20 -1 PRIMARY alias2 ALL NULL NULL NULL NULL 20 Using join buffer (flat, BNL join) -1 PRIMARY t2 ALL NULL NULL NULL NULL 20 Using join buffer (incremental, BNL join) -1 PRIMARY SQ3_alias1 ALL NULL NULL NULL NULL 20 Using where; Start temporary; Using join buffer (incremental, BNL join) +1 PRIMARY SQ3_alias1 ALL NULL NULL NULL NULL 20 Start temporary +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join) 1 PRIMARY SQ3_alias2 index NULL PRIMARY 4 NULL 20 Using index; End temporary; Using join buffer (incremental, BNL join) +1 PRIMARY alias2 ALL NULL NULL NULL NULL 20 Using join buffer (incremental, BNL join) +1 PRIMARY t2 ALL NULL NULL NULL NULL 20 Using join buffer (incremental, BNL join) 2 DERIVED t2 ALL NULL NULL NULL NULL 20 create table t3 as SELECT @@ -2652,6 +2652,39 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join) drop table t0,t1,t3; set optimizer_switch= @tmp_923246; +# +# BUG#952583: Server crashes in Item_field::fix_after_pullout on INSERT .. SELECT +# +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 ( b INT ); +INSERT INTO t2 VALUES (3),(4); +INSERT INTO t1 +SELECT * FROM ( SELECT * FROM t1 ) AS alias +WHERE a IN ( SELECT b FROM t2 ); +DROP TABLE t1, t2; +# +# BUG#952372: Server crashes on 2nd execution of PS in find_field_in_tables with semijoin+materialization +# +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (2),(3); +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 ( b VARCHAR(1) ); +INSERT INTO t2 VALUES ('v'),('v'); +PREPARE pstmt FROM +'SELECT DISTINCT a FROM v1, t2 + WHERE b IN ( SELECT MIN(b) FROM t2 )'; +EXECUTE pstmt; +a +2 +3 +EXECUTE pstmt; +a +2 +3 +DEALLOCATE PREPARE pstmt; +DROP VIEW v1; +DROP TABLE t1, t2; set optimizer_switch=@subselect_sj_tmp; # # BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off @@ -2859,8 +2892,8 @@ EXPLAIN SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a) GROUP BY a HAVING a != 'z'; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 Using temporary; Using filesort -1 PRIMARY t ref idx_a idx_a 4 test.t2.b 2 Using index +1 PRIMARY t index idx_a idx_a 4 NULL 3 Using index; Using temporary; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where 2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a) @@ -2873,8 +2906,8 @@ EXPLAIN SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a) GROUP BY a HAVING a != 'z'; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 Using temporary; Using filesort -1 PRIMARY t ref idx_a idx_a 4 test.t2.b 2 Using index +1 PRIMARY t index idx_a idx_a 4 NULL 3 Using index; Using temporary; Using filesort +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where 2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a) diff --git a/mysql-test/r/subselect_sj_mat.result b/mysql-test/r/subselect_sj_mat.result index 5729e86ce70..dc1d9b407fd 100644 --- a/mysql-test/r/subselect_sj_mat.result +++ b/mysql-test/r/subselect_sj_mat.result @@ -505,15 +505,15 @@ b2 in (select c2 from t3 t3b where c2 LIKE '%03')) and where (c1, c2) in (select b1, b2 from t2i where b2 > '0' or b2 = a2)); id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where -1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join) 1 PRIMARY t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t1.a1,test.t1.a2 2 100.00 Using index; Start temporary 1 PRIMARY t3c ALL NULL NULL NULL NULL 4 100.00 Using where; End temporary; Using join buffer (flat, BNL join) +1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; Start temporary; End temporary; Using join buffer (flat, BNL join) 4 MATERIALIZED t3b ALL NULL NULL NULL NULL 4 100.00 Using where 3 DEPENDENT SUBQUERY t3a ALL NULL NULL NULL NULL 4 100.00 Using where Warnings: Note 1276 Field or reference 'test.t1.a1' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a2' of SELECT #6 was resolved in SELECT #1 -Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3` `t3c`) where ((`test`.`t2`.`b2` = `test`.`t1`.`a2`) and (`test`.`t2i`.`b2` = `test`.`t1`.`a2`) and (`test`.`t3c`.`c2` = `test`.`t1`.`a2`) and (`test`.`t2`.`b1` = `test`.`t1`.`a1`) and (`test`.`t2i`.`b1` = `test`.`t1`.`a1`) and (`test`.`t3c`.`c1` = `test`.`t1`.`a1`) and (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `<subquery4>`.`c2`)))))))) +Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` semi join (`test`.`t2`) semi join (`test`.`t2i` join `test`.`t3` `t3c`) where ((`test`.`t2i`.`b2` = `test`.`t1`.`a2`) and (`test`.`t3c`.`c2` = `test`.`t1`.`a2`) and (`test`.`t2`.`b2` = `test`.`t1`.`a2`) and (`test`.`t2i`.`b1` = `test`.`t1`.`a1`) and (`test`.`t3c`.`c1` = `test`.`t1`.`a1`) and (`test`.`t2`.`b1` = `test`.`t1`.`a1`) and (<expr_cache><`test`.`t2`.`b2`,`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t2`.`b2`,<exists>(select `test`.`t3a`.`c2` from `test`.`t3` `t3a` where ((`test`.`t3a`.`c1` = `test`.`t1`.`a1`) and (<cache>(`test`.`t2`.`b2`) = `test`.`t3a`.`c2`))))) or <expr_cache><`test`.`t2`.`b2`>(<in_optimizer>(`test`.`t2`.`b2`,`test`.`t2`.`b2` in ( <materialize> (select `test`.`t3b`.`c2` from `test`.`t3` `t3b` where (`test`.`t3b`.`c2` like '%03') ), <primary_index_lookup>(`test`.`t2`.`b2` in <temporary table> on distinct_key where ((`test`.`t2`.`b2` = `<subquery4>`.`c2`)))))))) explain extended select * from t1 where (a1, a2) in (select '1 - 01', '2 - 01'); id select_type table type possible_keys key key_len ref rows filtered Extra @@ -1087,11 +1087,11 @@ create index it1a on t1(a); explain extended select a from t1 where a in (select c from t2 where d >= 20); id select_type table type possible_keys key key_len ref rows filtered Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 6 100.00 -1 PRIMARY t1 ref it1a it1a 4 test.t2.c 2 100.00 Using index +1 PRIMARY t1 index it1a it1a 4 NULL 7 100.00 Using index +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 100.00 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a` = `test`.`t2`.`c`) and (`test`.`t2`.`d` >= 20)) +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`d` >= 20)) select a from t1 where a in (select c from t2 where d >= 20); a 2 diff --git a/mysql-test/r/subselect_sj_nonmerged.result b/mysql-test/r/subselect_sj_nonmerged.result index 2a3768c8c50..c7e04225ffe 100644 --- a/mysql-test/r/subselect_sj_nonmerged.result +++ b/mysql-test/r/subselect_sj_nonmerged.result @@ -77,8 +77,8 @@ explain select * from t4 where t4.a in (select max(t2.a) from t1, t2 group by t2.b) and t4.b in (select max(t2.a) from t1, t2 group by t2.b); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 5 -1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 5 Using join buffer (flat, BNL join) +1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 5 +1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 5 Using join buffer (flat, BNL join) 1 PRIMARY t4 ref a a 10 <subquery2>.max(t2.a),<subquery3>.max(t2.a) 12 3 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 Using temporary 3 MATERIALIZED t1 ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 9b6ae60b3b5..ae4c61a1dc7 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -4609,6 +4609,13 @@ UNLOCK TABLES; DROP PROCEDURE p1; DROP TABLE t1; # +# Bug#12626844: WRONG ERROR MESSAGE WHILE CREATING A VIEW ON A +# NON EXISTING DATABASE +# +DROP DATABASE IF EXISTS nodb; +CREATE VIEW nodb.a AS SELECT 1; +ERROR 42000: Unknown database 'nodb' +# # lp:833600 Wrong result with view + outer join + uncorrelated subquery (non-semijoin) # CREATE TABLE t1 ( a int, b int ); @@ -4628,6 +4635,45 @@ NULL NULL 1 0 NULL NULL 1 0 DROP VIEW v2; DROP TABLE t1, t2, t3; +# +# BUG#915222: Valgrind complains or crashes with INSERT SELECT +# within a trigger that uses a view +# +CREATE TABLE t1 (a char(1)); +CREATE TABLE t2 (d int, e char(1)); +INSERT INTO t2 VALUES (13,'z'); +CREATE TRIGGER tr AFTER UPDATE ON t2 +FOR EACH ROW +REPLACE INTO t3 +SELECT f, a AS alias FROM t3, v; +CREATE TABLE t3 (f int, g char(8)); +CREATE VIEW v AS SELECT a, e FROM t2, t1; +UPDATE t2 SET d=7; +UPDATE t2 SET d=7; +UPDATE t2 SET d=7; +UPDATE t2 SET d=7; +DROP TRIGGER tr; +DROP VIEW v; +DROP TABLE t1,t2,t3; +# +# BUG#972943: Assertion failure with INSERT SELECT within a trigger +# that uses derived table and materialized view +# +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (1,0), (2,8); +CREATE ALGORITHM=TEMPTABLE VIEW v1 +AS SELECT * FROM t1; +CREATE TABLE t2 (c int); +CREATE TABLE t3 (d int, e int); +CREATE TRIGGER tr BEFORE INSERT ON t2 FOR EACH ROW +INSERT INTO t3 +SELECT t1.* +FROM (SELECT * FROM t1 WHERE b IN (SELECT b FROM v1)) AS alias1, t1 +WHERE t1.a = 3 OR t1.a > 5; +INSERT INTO t2 VALUES (1); +DROP TRIGGER tr; +DROP VIEW v1; +DROP TABLE t1,t2,t3; # ----------------------------------------------------------------- # -- End of 5.3 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/r/xa.result b/mysql-test/r/xa.result index 3799e9417af..6c242d950ab 100644 --- a/mysql-test/r/xa.result +++ b/mysql-test/r/xa.result @@ -174,7 +174,6 @@ CREATE TABLE t1 (a INT) engine=InnoDB; XA START 'a'; INSERT INTO t1 VALUES (1); SAVEPOINT savep; -ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state XA END 'a'; SELECT * FROM t1; ERROR XAE07: XAER_RMFAIL: The command cannot be executed when global transaction is in the IDLE state diff --git a/mysql-test/suite.pm b/mysql-test/suite.pm index 7c234afffb1..1c2f55660c2 100644 --- a/mysql-test/suite.pm +++ b/mysql-test/suite.pm @@ -26,6 +26,9 @@ sub skip_combinations { $skip{'include/not_windows.inc'} = 'Requires not Windows' if IS_WINDOWS; + $skip{'t/plugin_loaderr.test'} = 'needs compiled-in innodb' + unless $::mysqld_variables{'innodb'} eq "ON"; + # disable tests that use ipv6, if unsupported use Socket; $skip{'include/check_ipv6.inc'} = 'No IPv6' diff --git a/mysql-test/suite/binlog/r/binlog_sql_mode.result b/mysql-test/suite/binlog/r/binlog_sql_mode.result index 4477c94a95e..1aea77c4a4b 100644 --- a/mysql-test/suite/binlog/r/binlog_sql_mode.result +++ b/mysql-test/suite/binlog/r/binlog_sql_mode.result @@ -38,3 +38,114 @@ DROP VIEW testView; DROP TABLE t1; SET @@global.sql_mode= @old_sql_mode; SET @@session.binlog_format=@old_binlog_format; + +# +# Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES +# IGNORED AND BREAKS REPLICATION +# +DROP DATABASE IF EXISTS mysqltest_db; +DROP TABLE IF EXISTS test_table; +CREATE DATABASE mysqltest_db; +USE mysqltest_db; +CREATE TABLE test_table (c1 CHAR(50)); +SET @org_mode=@@sql_mode; +SET @@sql_mode=''; +CREATE PROCEDURE proc_without_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50)) +BEGIN +DECLARE var1 CHAR(50) DEFAULT param1; +DECLARE var2 CHAR(50) DEFAULT param2; +DECLARE var3 CHAR(50) DEFAULT 'abcd\bef'; +DECLARE var4 CHAR(50) DEFAULT 'abcd\nef'; +DECLARE var5 CHAR(50) DEFAULT 'abcd\ref'; +DECLARE var6 CHAR(50) DEFAULT 'abcd\tef'; +DECLARE var7 CHAR(50) DEFAULT 'abcd\\ef'; +DECLARE var8 CHAR(50) DEFAULT 'abcd\%ef'; +DECLARE var9 CHAR(50) DEFAULT 'abcd\_ef'; +INSERT INTO test_table VALUES (var1); +INSERT INTO test_table VALUES (var2); +INSERT INTO test_table VALUES (var3); +INSERT INTO test_table VALUES (var4); +INSERT INTO test_table VALUES (var5); +INSERT INTO test_table VALUES (var6); +INSERT INTO test_table VALUES (var7); +INSERT INTO test_table VALUES (var8); +INSERT INTO test_table VALUES (var9); +END +$ +SET @@sql_mode='NO_BACKSLASH_ESCAPES'$ +CREATE PROCEDURE proc_with_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50)) +BEGIN +DECLARE var1 CHAR(50) DEFAULT param1; +DECLARE var2 CHAR(50) DEFAULT param2; +DECLARE var3 CHAR(50) DEFAULT 'wxyz\bef'; +DECLARE var4 CHAR(50) DEFAULT 'wxyz\nef'; +DECLARE var5 CHAR(50) DEFAULT 'wxyz\ref'; +DECLARE var6 CHAR(50) DEFAULT 'wxyz\tef'; +DECLARE var7 CHAR(50) DEFAULT 'wxyz\\ef'; +DECLARE var8 CHAR(50) DEFAULT 'wxyz\%ef'; +DECLARE var9 CHAR(50) DEFAULT 'wxyz\_ef'; +INSERT INTO test_table VALUES (var1); +INSERT INTO test_table VALUES (var2); +INSERT INTO test_table VALUES (var3); +INSERT INTO test_table VALUES (var4); +INSERT INTO test_table VALUES (var5); +INSERT INTO test_table VALUES (var6); +INSERT INTO test_table VALUES (var7); +INSERT INTO test_table VALUES (var8); +INSERT INTO test_table VALUES (var9); +END +$ +SET @@sql_mode=''; +CALL proc_without_sql_mode('abcd\'ef', 'abcd\"ef'); +CALL proc_with_sql_mode('wxyz\'ef', 'wxyz\"ef'); +SELECT * FROM test_table; +c1 +abcd'ef +abcd"ef +abcdef +abcd +ef +abcd
ef +abcd ef +abcd\ef +abcd\%ef +abcd\_ef +wxyz'ef +wxyz"ef +wxyz\bef +wxyz\nef +wxyz\ref +wxyz\tef +wxyz\\ef +wxyz\%ef +wxyz\_ef +"Dropping table test_table" +DROP TABLE test_table; +#"test_table" content after replaying the binlog +SELECT * FROM test_table; +c1 +abcd'ef +abcd"ef +abcdef +abcd +ef +abcd
ef +abcd ef +abcd\ef +abcd\%ef +abcd\_ef +wxyz'ef +wxyz"ef +wxyz\bef +wxyz\nef +wxyz\ref +wxyz\tef +wxyz\\ef +wxyz\%ef +wxyz\_ef +#Clean up +DROP DATABASE mysqltest_db; +SET @@sql_mode= @org_mode; +use test; + +#End of Test for Bug#12601974 diff --git a/mysql-test/suite/binlog/r/binlog_unsafe.result b/mysql-test/suite/binlog/r/binlog_unsafe.result index 17ad4c6e5b1..2f994e9f5fc 100644 --- a/mysql-test/suite/binlog/r/binlog_unsafe.result +++ b/mysql-test/suite/binlog/r/binlog_unsafe.result @@ -1760,7 +1760,7 @@ SELECT COUNT(*) FROM mysql.general_log; Invoking function func_sidef_1 invoking statement that is unsafe in many ways. CREATE FUNCTION func_sidef_1() RETURNS VARCHAR(100) BEGIN INSERT INTO ta1 VALUES (47); INSERT DELAYED INTO double_autoinc_table SELECT CONCAT(UUID(), @@hostname, myfunc_int(), NULL) FROM mysql.general_log LIMIT 1; RETURN 0; END; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. INSERT INTO t1 SELECT func_sidef_1(); Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1769,12 +1769,13 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. Invoking function func_sidef_2 invoking function func_sidef_1 invoking statement that is unsafe in many ways. CREATE FUNCTION func_sidef_2() RETURNS VARCHAR(100) BEGIN INSERT INTO ta2 VALUES (47); INSERT INTO t1 SELECT func_sidef_1(); RETURN 0; END; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. INSERT INTO t2 SELECT func_sidef_2(); Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1783,13 +1784,14 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP FUNCTION func_sidef_2; Invoking procedure proc_2 invoking function func_sidef_1 invoking statement that is unsafe in many ways. CREATE PROCEDURE proc_2() BEGIN INSERT INTO t1 SELECT func_sidef_1(); INSERT INTO ta2 VALUES (47); END; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. CALL proc_2(); Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1798,13 +1800,14 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP PROCEDURE proc_2; Invoking trigger trig_2 invoking function func_sidef_1 invoking statement that is unsafe in many ways. CREATE TRIGGER trig_2 BEFORE INSERT ON trigger_table_2 FOR EACH ROW BEGIN INSERT INTO ta2 VALUES (47); INSERT INTO t1 SELECT func_sidef_1(); END; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. INSERT INTO trigger_table_2 VALUES (1); Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1813,6 +1816,7 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP TRIGGER trig_2; @@ -1826,7 +1830,8 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. -* binlog_format = STATEMENT: expect 6 warnings. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. +* binlog_format = STATEMENT: expect 7 warnings. INSERT INTO t2 SELECT * FROM view_sidef_2; Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1835,13 +1840,14 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP VIEW view_sidef_2; Invoking prepared statement prep_2 invoking function func_sidef_1 invoking statement that is unsafe in many ways. PREPARE prep_2 FROM "INSERT INTO t1 SELECT func_sidef_1()"; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. EXECUTE prep_2; Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1850,6 +1856,7 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP PREPARE prep_2; @@ -1857,7 +1864,7 @@ DROP FUNCTION func_sidef_1; Invoking procedure proc_1 invoking statement that is unsafe in many ways. CREATE PROCEDURE proc_1() BEGIN INSERT DELAYED INTO double_autoinc_table SELECT CONCAT(UUID(), @@hostname, myfunc_int(), NULL) FROM mysql.general_log LIMIT 1; INSERT INTO ta1 VALUES (47); END; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. CALL proc_1(); Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1866,12 +1873,13 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. Invoking function func_sidef_2 invoking procedure proc_1 invoking statement that is unsafe in many ways. CREATE FUNCTION func_sidef_2() RETURNS VARCHAR(100) BEGIN INSERT INTO ta2 VALUES (47); CALL proc_1(); RETURN 0; END; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. INSERT INTO t2 SELECT func_sidef_2(); Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1880,13 +1888,14 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP FUNCTION func_sidef_2; Invoking procedure proc_2 invoking procedure proc_1 invoking statement that is unsafe in many ways. CREATE PROCEDURE proc_2() BEGIN CALL proc_1(); INSERT INTO ta2 VALUES (47); END; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. CALL proc_2(); Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1895,13 +1904,14 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP PROCEDURE proc_2; Invoking trigger trig_2 invoking procedure proc_1 invoking statement that is unsafe in many ways. CREATE TRIGGER trig_2 BEFORE INSERT ON trigger_table_2 FOR EACH ROW BEGIN INSERT INTO ta2 VALUES (47); CALL proc_1(); END; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. INSERT INTO trigger_table_2 VALUES (1); Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1910,13 +1920,14 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP TRIGGER trig_2; Invoking prepared statement prep_2 invoking procedure proc_1 invoking statement that is unsafe in many ways. PREPARE prep_2 FROM "CALL proc_1()"; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. EXECUTE prep_2; Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1925,6 +1936,7 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP PREPARE prep_2; @@ -1932,7 +1944,7 @@ DROP PROCEDURE proc_1; Invoking trigger trig_1 invoking statement that is unsafe in many ways. CREATE TRIGGER trig_1 BEFORE INSERT ON trigger_table_1 FOR EACH ROW BEGIN INSERT INTO ta1 VALUES (47); INSERT DELAYED INTO double_autoinc_table SELECT CONCAT(UUID(), @@hostname, myfunc_int(), NULL) FROM mysql.general_log LIMIT 1; END; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. INSERT INTO trigger_table_1 VALUES (1); Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1941,12 +1953,13 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. Invoking function func_sidef_2 invoking trigger trig_1 invoking statement that is unsafe in many ways. CREATE FUNCTION func_sidef_2() RETURNS VARCHAR(100) BEGIN INSERT INTO ta2 VALUES (47); INSERT INTO trigger_table_1 VALUES (1); RETURN 0; END; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. INSERT INTO t2 SELECT func_sidef_2(); Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1955,13 +1968,14 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP FUNCTION func_sidef_2; Invoking procedure proc_2 invoking trigger trig_1 invoking statement that is unsafe in many ways. CREATE PROCEDURE proc_2() BEGIN INSERT INTO trigger_table_1 VALUES (1); INSERT INTO ta2 VALUES (47); END; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. CALL proc_2(); Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1970,13 +1984,14 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP PROCEDURE proc_2; Invoking trigger trig_2 invoking trigger trig_1 invoking statement that is unsafe in many ways. CREATE TRIGGER trig_2 BEFORE INSERT ON trigger_table_2 FOR EACH ROW BEGIN INSERT INTO ta2 VALUES (47); INSERT INTO trigger_table_1 VALUES (1); END; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. INSERT INTO trigger_table_2 VALUES (1); Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -1985,13 +2000,14 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP TRIGGER trig_2; Invoking prepared statement prep_2 invoking trigger trig_1 invoking statement that is unsafe in many ways. PREPARE prep_2 FROM "INSERT INTO trigger_table_1 VALUES (1)"; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. EXECUTE prep_2; Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -2000,6 +2016,7 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP PREPARE prep_2; @@ -2007,7 +2024,7 @@ DROP TRIGGER trig_1; Invoking prepared statement prep_1 invoking statement that is unsafe in many ways. PREPARE prep_1 FROM "INSERT DELAYED INTO double_autoinc_table SELECT CONCAT(UUID(), @@hostname, myfunc_int(), NULL) FROM mysql.general_log LIMIT 1"; -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. EXECUTE prep_1; Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -2016,12 +2033,13 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. DROP PREPARE prep_1; Invoking statement that is unsafe in many ways. -* binlog_format = STATEMENT: expect 6 warnings. +* binlog_format = STATEMENT: expect 7 warnings. INSERT DELAYED INTO double_autoinc_table SELECT CONCAT(UUID(), @@hostname, myfunc_int(), NULL) FROM mysql.general_log LIMIT 1; Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. @@ -2030,6 +2048,7 @@ Note 1592 Unsafe statement written to the binary log using statement format sinc Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a UDF which may not return the same value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system variable that may have a different value on the slave. Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. * SQL_LOG_BIN = 0: expect nothing logged and no warning. * binlog_format = MIXED: expect row events in binlog and no warning. diff --git a/mysql-test/suite/binlog/t/binlog_sql_mode.test b/mysql-test/suite/binlog/t/binlog_sql_mode.test index ab4f6450543..167c8f5a96d 100644 --- a/mysql-test/suite/binlog/t/binlog_sql_mode.test +++ b/mysql-test/suite/binlog/t/binlog_sql_mode.test @@ -73,3 +73,99 @@ DROP TABLE t1; SET @@global.sql_mode= @old_sql_mode; SET @@session.binlog_format=@old_binlog_format; + +--echo +--echo # +--echo # Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES +--echo # IGNORED AND BREAKS REPLICATION +--echo # + +--disable_warnings +DROP DATABASE IF EXISTS mysqltest_db; +DROP TABLE IF EXISTS test_table; +--enable_warnings + +CREATE DATABASE mysqltest_db; +USE mysqltest_db; +CREATE TABLE test_table (c1 CHAR(50)); + +SET @org_mode=@@sql_mode; + +SET @@sql_mode=''; +DELIMITER $; +CREATE PROCEDURE proc_without_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50)) +BEGIN + DECLARE var1 CHAR(50) DEFAULT param1; + DECLARE var2 CHAR(50) DEFAULT param2; + DECLARE var3 CHAR(50) DEFAULT 'abcd\bef'; + DECLARE var4 CHAR(50) DEFAULT 'abcd\nef'; + DECLARE var5 CHAR(50) DEFAULT 'abcd\ref'; + DECLARE var6 CHAR(50) DEFAULT 'abcd\tef'; + DECLARE var7 CHAR(50) DEFAULT 'abcd\\ef'; + DECLARE var8 CHAR(50) DEFAULT 'abcd\%ef'; + DECLARE var9 CHAR(50) DEFAULT 'abcd\_ef'; + + INSERT INTO test_table VALUES (var1); + INSERT INTO test_table VALUES (var2); + INSERT INTO test_table VALUES (var3); + INSERT INTO test_table VALUES (var4); + INSERT INTO test_table VALUES (var5); + INSERT INTO test_table VALUES (var6); + INSERT INTO test_table VALUES (var7); + INSERT INTO test_table VALUES (var8); + INSERT INTO test_table VALUES (var9); +END +$ + +SET @@sql_mode='NO_BACKSLASH_ESCAPES'$ +CREATE PROCEDURE proc_with_sql_mode (IN param1 CHAR(50), IN param2 CHAR(50)) +BEGIN + DECLARE var1 CHAR(50) DEFAULT param1; + DECLARE var2 CHAR(50) DEFAULT param2; + DECLARE var3 CHAR(50) DEFAULT 'wxyz\bef'; + DECLARE var4 CHAR(50) DEFAULT 'wxyz\nef'; + DECLARE var5 CHAR(50) DEFAULT 'wxyz\ref'; + DECLARE var6 CHAR(50) DEFAULT 'wxyz\tef'; + DECLARE var7 CHAR(50) DEFAULT 'wxyz\\ef'; + DECLARE var8 CHAR(50) DEFAULT 'wxyz\%ef'; + DECLARE var9 CHAR(50) DEFAULT 'wxyz\_ef'; + + INSERT INTO test_table VALUES (var1); + INSERT INTO test_table VALUES (var2); + INSERT INTO test_table VALUES (var3); + INSERT INTO test_table VALUES (var4); + INSERT INTO test_table VALUES (var5); + INSERT INTO test_table VALUES (var6); + INSERT INTO test_table VALUES (var7); + INSERT INTO test_table VALUES (var8); + INSERT INTO test_table VALUES (var9); +END +$ + +DELIMITER ;$ +SET @@sql_mode=''; +CALL proc_without_sql_mode('abcd\'ef', 'abcd\"ef'); +CALL proc_with_sql_mode('wxyz\'ef', 'wxyz\"ef'); +SELECT * FROM test_table; + +let $MYSQLD_DATADIR= `select @@datadir`; +--exec $MYSQL_BINLOG --force-if-open -d mysqltest_db $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog + +--echo "Dropping table test_table" +DROP TABLE test_table; + +--exec $MYSQL -e "source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog" + +--echo #"test_table" content after replaying the binlog +SELECT * FROM test_table; + +--echo #Clean up +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug12601974.binlog +DROP DATABASE mysqltest_db; +SET @@sql_mode= @org_mode; +use test; + +--echo +--echo #End of Test for Bug#12601974 + + diff --git a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test index 8b48c1723fd..70566da4cfa 100644 --- a/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test +++ b/mysql-test/suite/binlog/t/binlog_stm_unsafe_warning.test @@ -141,7 +141,7 @@ perl; use strict; use Cwd; my $log_error= $ENV{'LOG_ERROR'} or die "LOG_ERROR not set"; - open(FILE, "$log_error") or die("Unable to open '$log_error' from directory " . cwd() . "\n"); + open(FILE, "$log_error") or die("Unable to open '$log_error' from directory " . cwd() . " :$! \n"); my $binlog_counter= $ENV{'BINLOG_COUNTER1'} or die "BINLOG_COUNTER1 not set"; my $count = () = grep(/$binlog_counter/g,<FILE>); # Grep the timestamp value from the error file. diff --git a/mysql-test/suite/binlog/t/binlog_unsafe.test b/mysql-test/suite/binlog/t/binlog_unsafe.test index c64b9197b51..3353855fd0c 100644 --- a/mysql-test/suite/binlog/t/binlog_unsafe.test +++ b/mysql-test/suite/binlog/t/binlog_unsafe.test @@ -233,7 +233,7 @@ while ($unsafe_type < 9) { --let $value_0= --let $sel_sidef_0= --let $sel_retval_0= - --let $CRC_ARG_expected_number_of_warnings= 6 + --let $CRC_ARG_expected_number_of_warnings= 7 } if ($unsafe_type == 8) { diff --git a/mysql-test/suite/engines/funcs/r/db_alter_collate_ascii.result b/mysql-test/suite/engines/funcs/r/db_alter_collate_ascii.result index fdd76f93c10..6a9bfae27db 100644 --- a/mysql-test/suite/engines/funcs/r/db_alter_collate_ascii.result +++ b/mysql-test/suite/engines/funcs/r/db_alter_collate_ascii.result @@ -77,6 +77,7 @@ utf8_persian_ci utf8 208 # # utf8_esperanto_ci utf8 209 # # utf8_hungarian_ci utf8 210 # # utf8_sinhala_ci utf8 211 # # +utf8_general_mysql500_ci utf8 223 # # ucs2_general_ci ucs2 35 Yes # # ucs2_bin ucs2 90 # # ucs2_unicode_ci ucs2 128 # # @@ -99,6 +100,7 @@ ucs2_persian_ci ucs2 144 # # ucs2_esperanto_ci ucs2 145 # # ucs2_hungarian_ci ucs2 146 # # ucs2_sinhala_ci ucs2 147 # # +ucs2_general_mysql500_ci ucs2 159 # # cp866_general_ci cp866 36 Yes # # cp866_bin cp866 68 # # keybcs2_general_ci keybcs2 37 Yes # # diff --git a/mysql-test/suite/engines/funcs/r/db_alter_collate_utf8.result b/mysql-test/suite/engines/funcs/r/db_alter_collate_utf8.result index 4a41ece1fe5..79d1d4cbac2 100644 --- a/mysql-test/suite/engines/funcs/r/db_alter_collate_utf8.result +++ b/mysql-test/suite/engines/funcs/r/db_alter_collate_utf8.result @@ -77,6 +77,7 @@ utf8_persian_ci utf8 208 # # utf8_esperanto_ci utf8 209 # # utf8_hungarian_ci utf8 210 # # utf8_sinhala_ci utf8 211 # # +utf8_general_mysql500_ci utf8 223 # # ucs2_general_ci ucs2 35 Yes # # ucs2_bin ucs2 90 # # ucs2_unicode_ci ucs2 128 # # @@ -99,6 +100,7 @@ ucs2_persian_ci ucs2 144 # # ucs2_esperanto_ci ucs2 145 # # ucs2_hungarian_ci ucs2 146 # # ucs2_sinhala_ci ucs2 147 # # +ucs2_general_mysql500_ci ucs2 159 # # cp866_general_ci cp866 36 Yes # # cp866_bin cp866 68 # # keybcs2_general_ci keybcs2 37 Yes # # diff --git a/mysql-test/suite/innodb/include/innodb-index.inc b/mysql-test/suite/innodb/include/innodb-index.inc deleted file mode 100644 index 37de3162abe..00000000000 --- a/mysql-test/suite/innodb/include/innodb-index.inc +++ /dev/null @@ -1,26 +0,0 @@ ---eval create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a)) engine = innodb default charset=$charset -insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,2,'ad','ad'),(4,4,'afe','afe'); -commit; ---error ER_DUP_ENTRY -alter table t1 add unique index (b); -insert into t1 values(8,9,'fff','fff'); -select * from t1; -show create table t1; -alter table t1 add index (b); -insert into t1 values(10,10,'kkk','iii'); -select * from t1; -select * from t1 force index(b) order by b; -explain select * from t1 force index(b) order by b; -show create table t1; -alter table t1 add unique index (c), add index (d); -insert into t1 values(11,11,'aaa','mmm'); -select * from t1; -select * from t1 force index(b) order by b; -select * from t1 force index(c) order by c; -select * from t1 force index(d) order by d; -explain select * from t1 force index(b) order by b; -explain select * from t1 force index(c) order by c; -explain select * from t1 force index(d) order by d; -show create table t1; -check table t1; -drop table t1; diff --git a/mysql-test/suite/innodb/r/group_commit_crash.result b/mysql-test/suite/innodb/r/group_commit_crash.result index 333e47f38ad..cd47ba62ff2 100644 --- a/mysql-test/suite/innodb/r/group_commit_crash.result +++ b/mysql-test/suite/innodb/r/group_commit_crash.result @@ -2,7 +2,7 @@ CREATE TABLE t1(a CHAR(255), b CHAR(255), c CHAR(255), d CHAR(255), -id INT AUTO_INCREMENT, +id INT, PRIMARY KEY(id)) ENGINE=InnoDB; create table t2 like t1; create procedure setcrash(IN i INT) @@ -17,16 +17,16 @@ ELSE BEGIN END; END CASE; end // FLUSH TABLES; -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 9+1); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 8+1); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 7+1); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 6+1); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 5+1); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 4+1); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 3+1); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 2+1); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 1+1); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 0+1); SET binlog_format= mixed; RESET MASTER; START TRANSACTION; diff --git a/mysql-test/suite/innodb/r/group_commit_crash_no_optimize_thread.result b/mysql-test/suite/innodb/r/group_commit_crash_no_optimize_thread.result index 333e47f38ad..c1ae510d45b 100644 --- a/mysql-test/suite/innodb/r/group_commit_crash_no_optimize_thread.result +++ b/mysql-test/suite/innodb/r/group_commit_crash_no_optimize_thread.result @@ -2,7 +2,7 @@ CREATE TABLE t1(a CHAR(255), b CHAR(255), c CHAR(255), d CHAR(255), -id INT AUTO_INCREMENT, +id INT, PRIMARY KEY(id)) ENGINE=InnoDB; create table t2 like t1; create procedure setcrash(IN i INT) @@ -17,16 +17,16 @@ ELSE BEGIN END; END CASE; end // FLUSH TABLES; -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); -INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 1+9); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 1+8); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 1+7); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 1+6); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 1+5); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 1+4); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 1+3); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 1+2); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 1+1); +INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 1+0); SET binlog_format= mixed; RESET MASTER; START TRANSACTION; diff --git a/mysql-test/suite/innodb/r/innodb-autoinc-61209.result b/mysql-test/suite/innodb/r/innodb-autoinc-61209.result new file mode 100644 index 00000000000..9dd654702e2 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-autoinc-61209.result @@ -0,0 +1,28 @@ +DROP TABLE IF EXISTS bug_61209; +CREATE TABLE bug_61209 (a INT auto_increment, PRIMARY KEY(a)) ENGINE=InnoDB; +INSERT INTO bug_61209 VALUES (), (), (), (); + +# Connect con1 + +# Connect con2 + +# Connection con1 +SET SESSION auto_increment_increment=3; +SET SESSION auto_increment_offset=2; +SELECT GET_LOCK('a', 9); +GET_LOCK('a', 9) +1 + +# Connection con2 +SET SESSION auto_increment_increment=3; +SET SESSION auto_increment_offset=2; +INSERT INTO bug_61209 (a) VALUES (NULL), (NULL), (NULL + GET_LOCK('a', 10)); + +# Connection con1 reap +INSERT INTO bug_61209 (a) VALUES (NULL), (NULL), (NULL); +SELECT RELEASE_LOCK('a'); +RELEASE_LOCK('a') +1 + +# Connection con2 reap +DROP TABLE bug_61209; diff --git a/mysql-test/suite/innodb/r/innodb-autoinc.result b/mysql-test/suite/innodb/r/innodb-autoinc.result index 0c8d16f27fb..9eb89bead74 100644 --- a/mysql-test/suite/innodb/r/innodb-autoinc.result +++ b/mysql-test/suite/innodb/r/innodb-autoinc.result @@ -648,7 +648,7 @@ t2 CREATE TABLE `t2` ( `n` int(10) unsigned NOT NULL, `o` enum('FALSE','TRUE') DEFAULT NULL, PRIMARY KEY (`m`) -) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=latin1 INSERT INTO t1 (b,c) SELECT n,o FROM t2 ; SHOW CREATE TABLE t1; Table Create Table @@ -657,7 +657,7 @@ t1 CREATE TABLE `t1` ( `b` int(10) unsigned NOT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=latin1 INSERT INTO t1 (b,c) SELECT n,o FROM t2 ; SELECT * FROM t1; a b c @@ -671,16 +671,16 @@ a b c 8 4 FALSE 9 5 TRUE 10 5 FALSE -13 1 TRUE -14 1 FALSE -15 2 TRUE -16 2 FALSE -17 3 TRUE -18 3 FALSE -19 4 TRUE -20 4 FALSE -21 5 TRUE -22 5 FALSE +16 1 TRUE +17 1 FALSE +18 2 TRUE +19 2 FALSE +20 3 TRUE +21 3 FALSE +22 4 TRUE +23 4 FALSE +24 5 TRUE +25 5 FALSE SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -688,7 +688,7 @@ t1 CREATE TABLE `t1` ( `b` int(10) unsigned NOT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=latin1 INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false'; SELECT * FROM t1; a b c @@ -702,21 +702,21 @@ a b c 8 4 FALSE 9 5 TRUE 10 5 FALSE -13 1 TRUE -14 1 FALSE -15 2 TRUE -16 2 FALSE -17 3 TRUE -18 3 FALSE -19 4 TRUE -20 4 FALSE -21 5 TRUE -22 5 FALSE -23 1 FALSE -24 2 FALSE -25 3 FALSE -26 4 FALSE -27 5 FALSE +16 1 TRUE +17 1 FALSE +18 2 TRUE +19 2 FALSE +20 3 TRUE +21 3 FALSE +22 4 TRUE +23 4 FALSE +24 5 TRUE +25 5 FALSE +31 1 FALSE +32 2 FALSE +33 3 FALSE +34 4 FALSE +35 5 FALSE SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -724,7 +724,7 @@ t1 CREATE TABLE `t1` ( `b` int(10) unsigned NOT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=latin1 INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false'; SELECT * FROM t1; a b c @@ -738,26 +738,26 @@ a b c 8 4 FALSE 9 5 TRUE 10 5 FALSE -13 1 TRUE -14 1 FALSE -15 2 TRUE -16 2 FALSE -17 3 TRUE -18 3 FALSE -19 4 TRUE -20 4 FALSE -21 5 TRUE -22 5 FALSE -23 1 FALSE -24 2 FALSE -25 3 FALSE -26 4 FALSE -27 5 FALSE -30 1 FALSE -31 2 FALSE -32 3 FALSE -33 4 FALSE -34 5 FALSE +16 1 TRUE +17 1 FALSE +18 2 TRUE +19 2 FALSE +20 3 TRUE +21 3 FALSE +22 4 TRUE +23 4 FALSE +24 5 TRUE +25 5 FALSE +31 1 FALSE +32 2 FALSE +33 3 FALSE +34 4 FALSE +35 5 FALSE +38 1 FALSE +39 2 FALSE +40 3 FALSE +41 4 FALSE +42 5 FALSE SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -765,7 +765,7 @@ t1 CREATE TABLE `t1` ( `b` int(10) unsigned NOT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=45 DEFAULT CHARSET=latin1 INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false'; SHOW CREATE TABLE t1; Table Create Table @@ -774,7 +774,7 @@ t1 CREATE TABLE `t1` ( `b` int(10) unsigned NOT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=52 DEFAULT CHARSET=latin1 INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false'; SHOW CREATE TABLE t1; Table Create Table @@ -783,7 +783,7 @@ t1 CREATE TABLE `t1` ( `b` int(10) unsigned NOT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=latin1 INSERT INTO t1 (b,c) SELECT n,o FROM t2 WHERE o = 'false'; SELECT * FROM t1; a b c @@ -797,41 +797,41 @@ a b c 8 4 FALSE 9 5 TRUE 10 5 FALSE -13 1 TRUE -14 1 FALSE -15 2 TRUE -16 2 FALSE -17 3 TRUE -18 3 FALSE -19 4 TRUE -20 4 FALSE -21 5 TRUE -22 5 FALSE -23 1 FALSE -24 2 FALSE -25 3 FALSE -26 4 FALSE -27 5 FALSE -30 1 FALSE -31 2 FALSE -32 3 FALSE -33 4 FALSE -34 5 FALSE -37 1 FALSE -38 2 FALSE -39 3 FALSE -40 4 FALSE -41 5 FALSE -44 1 FALSE -45 2 FALSE -46 3 FALSE -47 4 FALSE -48 5 FALSE -51 1 FALSE -52 2 FALSE -53 3 FALSE -54 4 FALSE -55 5 FALSE +16 1 TRUE +17 1 FALSE +18 2 TRUE +19 2 FALSE +20 3 TRUE +21 3 FALSE +22 4 TRUE +23 4 FALSE +24 5 TRUE +25 5 FALSE +31 1 FALSE +32 2 FALSE +33 3 FALSE +34 4 FALSE +35 5 FALSE +38 1 FALSE +39 2 FALSE +40 3 FALSE +41 4 FALSE +42 5 FALSE +45 1 FALSE +46 2 FALSE +47 3 FALSE +48 4 FALSE +49 5 FALSE +52 1 FALSE +53 2 FALSE +54 3 FALSE +55 4 FALSE +56 5 FALSE +59 1 FALSE +60 2 FALSE +61 3 FALSE +62 4 FALSE +63 5 FALSE SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( @@ -839,7 +839,7 @@ t1 CREATE TABLE `t1` ( `b` int(10) unsigned NOT NULL, `c` enum('FALSE','TRUE') DEFAULT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB AUTO_INCREMENT=58 DEFAULT CHARSET=latin1 +) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=latin1 DROP TABLE t1; DROP TABLE t2; DROP TABLE IF EXISTS t1; @@ -1251,3 +1251,21 @@ t1 CREATE TABLE `t1` ( PRIMARY KEY (`c1`) ) ENGINE=InnoDB AUTO_INCREMENT=18446744073709551615 DEFAULT CHARSET=latin1 DROP TABLE t1; +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=256; +SHOW VARIABLES LIKE "%auto_inc%"; +Variable_name Value +auto_increment_increment 1 +auto_increment_offset 256 +CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` tinyint(4) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb-blob.result b/mysql-test/suite/innodb/r/innodb-blob.result new file mode 100644 index 00000000000..a90f83945e0 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-blob.result @@ -0,0 +1,119 @@ +CREATE TABLE t1 (a INT PRIMARY KEY, b TEXT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t3 (a INT PRIMARY KEY, b TEXT, c TEXT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,REPEAT('a',30000)),(2,REPEAT('b',40000)); +SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR go1'; +BEGIN; +UPDATE t1 SET a=a+2; +ROLLBACK; +BEGIN; +UPDATE t1 SET b=CONCAT(b,'foo'); +SET DEBUG_SYNC='now WAIT_FOR have_latch'; +SELECT a, RIGHT(b,20) FROM t1; +SET DEBUG_SYNC='now SIGNAL go1'; +a RIGHT(b,20) +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +SET DEBUG_DBUG='+d,row_ins_extern_checkpoint'; +SET DEBUG_SYNC='before_row_ins_extern_latch SIGNAL rec_not_blob WAIT_FOR crash'; +ROLLBACK; +BEGIN; +INSERT INTO t1 VALUES (3,REPEAT('c',50000)); +SET DEBUG_SYNC='now WAIT_FOR rec_not_blob'; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT @@tx_isolation; +@@tx_isolation +READ-UNCOMMITTED +SELECT a, RIGHT(b,20) FROM t1; +a RIGHT(b,20) +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +SELECT a FROM t1; +a +1 +2 +3 +SET DEBUG_DBUG='+d,crash_commit_before'; +INSERT INTO t2 VALUES (42); +ERROR HY000: Lost connection to MySQL server during query +ERROR HY000: Lost connection to MySQL server during query +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +INSERT INTO t3 VALUES +(1,REPEAT('d',7000),REPEAT('e',100)), +(2,REPEAT('g',7000),REPEAT('h',100)); +SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR go'; +UPDATE t3 SET c=REPEAT('f',3000) WHERE a=1; +SET DEBUG_SYNC='now WAIT_FOR have_latch'; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT @@tx_isolation; +@@tx_isolation +READ-UNCOMMITTED +SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3; +SET DEBUG_SYNC='now SIGNAL go'; +a RIGHT(b,20) RIGHT(c,20) +1 dddddddddddddddddddd ffffffffffffffffffff +2 gggggggggggggggggggg hhhhhhhhhhhhhhhhhhhh +CHECK TABLE t1,t2,t3; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t2 check status OK +test.t3 check status OK +BEGIN; +INSERT INTO t2 VALUES (347); +SET DEBUG_DBUG='+d,row_upd_extern_checkpoint'; +SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR crash'; +UPDATE t3 SET c=REPEAT('i',3000) WHERE a=2; +SET DEBUG_SYNC='now WAIT_FOR have_latch'; +SELECT info FROM information_schema.processlist +WHERE state = 'debug sync point: before_row_upd_extern'; +info +UPDATE t3 SET c=REPEAT('i',3000) WHERE a=2 +SET DEBUG_DBUG='+d,crash_commit_before'; +COMMIT; +ERROR HY000: Lost connection to MySQL server during query +ERROR HY000: Lost connection to MySQL server during query +CHECK TABLE t1,t2,t3; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t2 check status OK +test.t3 check status OK +SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3; +a RIGHT(b,20) RIGHT(c,20) +1 dddddddddddddddddddd ffffffffffffffffffff +2 gggggggggggggggggggg hhhhhhhhhhhhhhhhhhhh +SELECT a FROM t3; +a +1 +2 +BEGIN; +INSERT INTO t2 VALUES (33101); +SET DEBUG_DBUG='+d,row_upd_extern_checkpoint'; +SET DEBUG_SYNC='after_row_upd_extern SIGNAL have_latch WAIT_FOR crash'; +UPDATE t3 SET c=REPEAT('j',3000) WHERE a=2; +SET DEBUG_SYNC='now WAIT_FOR have_latch'; +SELECT info FROM information_schema.processlist +WHERE state = 'debug sync point: after_row_upd_extern'; +info +UPDATE t3 SET c=REPEAT('j',3000) WHERE a=2 +SET DEBUG_DBUG='+d,crash_commit_before'; +COMMIT; +ERROR HY000: Lost connection to MySQL server during query +ERROR HY000: Lost connection to MySQL server during query +CHECK TABLE t1,t2,t3; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t2 check status OK +test.t3 check status OK +SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3; +a RIGHT(b,20) RIGHT(c,20) +1 dddddddddddddddddddd ffffffffffffffffffff +2 gggggggggggggggggggg hhhhhhhhhhhhhhhhhhhh +SELECT a FROM t3; +a +1 +2 +SELECT * FROM t2; +a +DROP TABLE t1,t2,t3; diff --git a/mysql-test/suite/innodb/r/innodb-index.result b/mysql-test/suite/innodb/r/innodb-index.result index a33099661aa..48390b14a82 100644 --- a/mysql-test/suite/innodb/r/innodb-index.result +++ b/mysql-test/suite/innodb/r/innodb-index.result @@ -114,6 +114,10 @@ t12963823 CREATE TABLE `t12963823` ( KEY `ndx_o` (`o`(500)), KEY `ndx_p` (`p`(500)) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +create table t1(a varchar(2) primary key) engine=innodb; +insert into t1 values(''); +create index t1a1 on t1(a(1)); +drop table t1; set global innodb_file_per_table=0; set global innodb_file_format=Antelope; create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb; diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index 2ec6c91f7d5..bb4d783ccf4 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -1685,7 +1685,7 @@ count(*) drop table t1; SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_buffer_pool_pages_total'; variable_value -511 +ok SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size'; variable_value 16384 diff --git a/mysql-test/suite/innodb/r/innodb_bug11754376.result b/mysql-test/suite/innodb/r/innodb_bug11754376.result new file mode 100644 index 00000000000..034e4f07403 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug11754376.result @@ -0,0 +1,4 @@ +CREATE TABLE bug11754376 (c INT) ENGINE=INNODB; +SET SESSION DEBUG_DBUG='+d,test_normalize_table_name_low'; +DROP TABLE bug11754376; +SET SESSION DEBUG_DBUG='-d,test_normalize_table_name_low'; diff --git a/mysql-test/suite/innodb/r/innodb_bug11766634.result b/mysql-test/suite/innodb/r/innodb_bug11766634.result new file mode 100644 index 00000000000..7594d512638 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug11766634.result @@ -0,0 +1,5 @@ +create table t1 (f1 char(255)) engine innodb; +drop table t1; +create table t1 (f1 char(255)) engine innodb; +1 +drop table t1; diff --git a/mysql-test/suite/innodb/r/innodb_bug13510739.result b/mysql-test/suite/innodb/r/innodb_bug13510739.result new file mode 100644 index 00000000000..8aa4323eeb0 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug13510739.result @@ -0,0 +1,10 @@ +CREATE TABLE bug13510739 (c INTEGER NOT NULL, PRIMARY KEY (c)) ENGINE=INNODB; +INSERT INTO bug13510739 VALUES (1), (2), (3), (4); +DELETE FROM bug13510739 WHERE c=2; +HANDLER bug13510739 OPEN; +HANDLER bug13510739 READ `primary` = (2); +c +HANDLER bug13510739 READ `primary` NEXT; +c +4 +DROP TABLE bug13510739; diff --git a/mysql-test/suite/innodb/t/group_commit_crash.test b/mysql-test/suite/innodb/t/group_commit_crash.test index 3502ab41180..12c92d19244 100644 --- a/mysql-test/suite/innodb/t/group_commit_crash.test +++ b/mysql-test/suite/innodb/t/group_commit_crash.test @@ -14,7 +14,7 @@ CREATE TABLE t1(a CHAR(255), b CHAR(255), c CHAR(255), d CHAR(255), - id INT AUTO_INCREMENT, + id INT, PRIMARY KEY(id)) ENGINE=InnoDB; create table t2 like t1; delimiter //; @@ -39,7 +39,7 @@ let $numinserts = 10; while ($numinserts) { dec $numinserts; - INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); + eval INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', $numinserts+1); } --enable_reconnect diff --git a/mysql-test/suite/innodb/t/group_commit_crash_no_optimize_thread.test b/mysql-test/suite/innodb/t/group_commit_crash_no_optimize_thread.test index 3502ab41180..2de09d6b0b6 100644 --- a/mysql-test/suite/innodb/t/group_commit_crash_no_optimize_thread.test +++ b/mysql-test/suite/innodb/t/group_commit_crash_no_optimize_thread.test @@ -14,7 +14,7 @@ CREATE TABLE t1(a CHAR(255), b CHAR(255), c CHAR(255), d CHAR(255), - id INT AUTO_INCREMENT, + id INT, PRIMARY KEY(id)) ENGINE=InnoDB; create table t2 like t1; delimiter //; @@ -39,7 +39,7 @@ let $numinserts = 10; while ($numinserts) { dec $numinserts; - INSERT INTO t2(a, b, c, d) VALUES ('a', 'b', 'c', 'd'); + eval INSERT INTO t2(a, b, c, d, id) VALUES ('a', 'b', 'c', 'd', 1+$numinserts); } --enable_reconnect diff --git a/mysql-test/suite/innodb/t/innodb-autoinc-61209.test b/mysql-test/suite/innodb/t/innodb-autoinc-61209.test new file mode 100644 index 00000000000..2a981fe9d44 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-autoinc-61209.test @@ -0,0 +1,55 @@ +# This is the test case for bug #61209 - duplicate key errors +# when using auto_increment_increment > 1 and auto_increment_offset > 1 +# +--source include/have_innodb.inc + +# +# Precautionary clean up. +# +--disable_warnings +DROP TABLE IF EXISTS bug_61209; +--enable_warnings + +# +# Create test data. +# +CREATE TABLE bug_61209 (a INT auto_increment, PRIMARY KEY(a)) ENGINE=InnoDB; + +INSERT INTO bug_61209 VALUES (), (), (), (); + +--echo +--echo # Connect con1 +--connect (con1,localhost,root,,) +--echo +--echo # Connect con2 +--connect (con2,localhost,root,,) + +--echo +--echo # Connection con1 +--connection con1 +SET SESSION auto_increment_increment=3; +SET SESSION auto_increment_offset=2; +SELECT GET_LOCK('a', 9); + +--echo +--echo # Connection con2 +--connection con2 +SET SESSION auto_increment_increment=3; +SET SESSION auto_increment_offset=2; +send INSERT INTO bug_61209 (a) VALUES (NULL), (NULL), (NULL + GET_LOCK('a', 10)); + +--echo +--echo # Connection con1 reap +--connection con1 +INSERT INTO bug_61209 (a) VALUES (NULL), (NULL), (NULL); +SELECT RELEASE_LOCK('a'); + +--echo +--echo # Connection con2 reap +--connection con2 +reap; + +# +# Clean up +# +DROP TABLE bug_61209; diff --git a/mysql-test/suite/innodb/t/innodb-autoinc.test b/mysql-test/suite/innodb/t/innodb-autoinc.test index 4b3c3b2e56d..4f54a8ff957 100644 --- a/mysql-test/suite/innodb/t/innodb-autoinc.test +++ b/mysql-test/suite/innodb/t/innodb-autoinc.test @@ -637,3 +637,14 @@ INSERT INTO t1 VALUES (18446744073709551615); -- source include/restart_mysqld.inc SHOW CREATE TABLE t1; DROP TABLE t1; + + +# Check if we handl offset > column max value properly +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=256; +SHOW VARIABLES LIKE "%auto_inc%"; +# TINYINT +CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb-blob.test b/mysql-test/suite/innodb/t/innodb-blob.test new file mode 100644 index 00000000000..c81d4a8acf1 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-blob.test @@ -0,0 +1,221 @@ +# Bug#13721257 RACE CONDITION IN UPDATES OR INSERTS OF WIDE RECORDS +# Test what happens when a record is inserted or updated so that some +# columns are stored off-page. + +--source include/have_innodb.inc + +if (`select plugin_auth_version <= "1.1.8-24.1" from information_schema.plugins where plugin_name='innodb'`) +{ + --skip Not fixed in XtraDB 1.1.8-24.1 or earlier +} + +# DEBUG_SYNC must be compiled in. +--source include/have_debug_sync.inc + +# Valgrind would complain about memory leaks when we crash on purpose. +--source include/not_valgrind.inc +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc + +CREATE TABLE t1 (a INT PRIMARY KEY, b TEXT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t3 (a INT PRIMARY KEY, b TEXT, c TEXT) ENGINE=InnoDB; + +INSERT INTO t1 VALUES (1,REPEAT('a',30000)),(2,REPEAT('b',40000)); +SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR go1'; +BEGIN; +# This will not block, because it will not store new BLOBs. +UPDATE t1 SET a=a+2; +ROLLBACK; +BEGIN; +--send +UPDATE t1 SET b=CONCAT(b,'foo'); + +connect (con1,localhost,root,,); +SET DEBUG_SYNC='now WAIT_FOR have_latch'; + +# this one should block due to the clustered index tree and leaf page latches +--send +SELECT a, RIGHT(b,20) FROM t1; + +connect (con2,localhost,root,,); + +# Check that the above SELECT is blocked +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = 'Sending data' and + info = 'SELECT a, RIGHT(b,20) FROM t1'; +--source include/wait_condition.inc + +SET DEBUG_SYNC='now SIGNAL go1'; + +connection con1; +reap; +connection default; +reap; +SET DEBUG_DBUG='+d,row_ins_extern_checkpoint'; +SET DEBUG_SYNC='before_row_ins_extern_latch SIGNAL rec_not_blob WAIT_FOR crash'; +ROLLBACK; +BEGIN; +--send +INSERT INTO t1 VALUES (3,REPEAT('c',50000)); + +connection con1; +SET DEBUG_SYNC='now WAIT_FOR rec_not_blob'; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT @@tx_isolation; + +# this one should see (3,NULL_BLOB) +SELECT a, RIGHT(b,20) FROM t1; +SELECT a FROM t1; + +# Request a crash, and restart the server. +SET DEBUG_DBUG='+d,crash_commit_before'; +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--error 2013 +INSERT INTO t2 VALUES (42); + +disconnect con1; +disconnect con2; +connection default; +# This connection should notice the crash as well. +--error 2013 +reap; + +# Write file to make mysql-test-run.pl restart the server +--enable_reconnect +--source include/wait_until_connected_again.inc +--disable_reconnect + +CHECK TABLE t1; + +INSERT INTO t3 VALUES + (1,REPEAT('d',7000),REPEAT('e',100)), + (2,REPEAT('g',7000),REPEAT('h',100)); +SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR go'; +# This should move column b off-page. +--send +UPDATE t3 SET c=REPEAT('f',3000) WHERE a=1; + +connect (con1,localhost,root,,); +SET DEBUG_SYNC='now WAIT_FOR have_latch'; +SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT @@tx_isolation; + +# this one should block +-- send +SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3; + +connect (con2,localhost,root,,); + +# Check that the above SELECT is blocked +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = 'Sending data' and + info = 'SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3'; +--source include/wait_condition.inc + +SET DEBUG_SYNC='now SIGNAL go'; + +connection con1; +reap; +disconnect con1; + +connection default; +reap; + +CHECK TABLE t1,t2,t3; + +connection con2; +BEGIN; +INSERT INTO t2 VALUES (347); +connection default; + +# The row_upd_extern_checkpoint was removed in Bug#13721257, +# because the mini-transaction of the B-tree modification would +# remain open while we are writing the off-page columns and are +# stuck in the DEBUG_SYNC. A checkpoint involves a flush, which +# would wait for the buffer-fix to cease. +SET DEBUG_DBUG='+d,row_upd_extern_checkpoint'; +SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR crash'; +# This should move column b off-page. +--send +UPDATE t3 SET c=REPEAT('i',3000) WHERE a=2; + +connection con2; +SET DEBUG_SYNC='now WAIT_FOR have_latch'; + +# Check that the above UPDATE is blocked +SELECT info FROM information_schema.processlist +WHERE state = 'debug sync point: before_row_upd_extern'; + +# Request a crash, and restart the server. +SET DEBUG_DBUG='+d,crash_commit_before'; +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--error 2013 +COMMIT; + +disconnect con2; +connection default; +# This connection should notice the crash as well. +--error 2013 +reap; + +# Write file to make mysql-test-run.pl restart the server +--enable_reconnect +--source include/wait_until_connected_again.inc +--disable_reconnect + +CHECK TABLE t1,t2,t3; +SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3; +SELECT a FROM t3; + +connect (con2,localhost,root,,); +BEGIN; +INSERT INTO t2 VALUES (33101); +connection default; + +# The row_upd_extern_checkpoint was removed in Bug#13721257, +# because the mini-transaction of the B-tree modification would +# remain open while we are writing the off-page columns and are +# stuck in the DEBUG_SYNC. A checkpoint involves a flush, which +# would wait for the buffer-fix to cease. +SET DEBUG_DBUG='+d,row_upd_extern_checkpoint'; +SET DEBUG_SYNC='after_row_upd_extern SIGNAL have_latch WAIT_FOR crash'; +# This should move column b off-page. +--send +UPDATE t3 SET c=REPEAT('j',3000) WHERE a=2; + +connection con2; +SET DEBUG_SYNC='now WAIT_FOR have_latch'; + +# Check that the above UPDATE is blocked +SELECT info FROM information_schema.processlist +WHERE state = 'debug sync point: after_row_upd_extern'; + +# Request a crash, and restart the server. +SET DEBUG_DBUG='+d,crash_commit_before'; +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +--error 2013 +COMMIT; + +disconnect con2; +connection default; +# This connection should notice the crash as well. +--error 2013 +reap; + +# Write file to make mysql-test-run.pl restart the server +--enable_reconnect +--source include/wait_until_connected_again.inc +--disable_reconnect + +CHECK TABLE t1,t2,t3; +SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3; +SELECT a FROM t3; + +SELECT * FROM t2; + +DROP TABLE t1,t2,t3; diff --git a/mysql-test/suite/innodb/t/innodb-index.test b/mysql-test/suite/innodb/t/innodb-index.test index cb4527d6cb2..cea9055b873 100644 --- a/mysql-test/suite/innodb/t/innodb-index.test +++ b/mysql-test/suite/innodb/t/innodb-index.test @@ -119,6 +119,11 @@ show create table t12963823; # this file complete before dropping the table. By then, the purge thread # will have delt with the updates above. +# Bug#13654923 BOGUS DEBUG ASSERTION IN INDEX CREATION FOR ZERO-LENGTH RECORD +create table t1(a varchar(2) primary key) engine=innodb; +insert into t1 values(''); +create index t1a1 on t1(a(1)); +drop table t1; eval set global innodb_file_per_table=$per_table; eval set global innodb_file_format=$format; diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test index c2309c0fcd6..d57a52a2362 100644 --- a/mysql-test/suite/innodb/t/innodb.test +++ b/mysql-test/suite/innodb/t/innodb.test @@ -1339,7 +1339,7 @@ drop table t1; # Test for testable InnoDB status variables. This test # uses previous ones(pages_created, rows_deleted, ...). ---replace_result 512 511 2047 511 +--replace_result 511 ok 512 ok 2047 ok 513 ok SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_buffer_pool_pages_total'; SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size'; SELECT variable_value - @innodb_rows_deleted_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_deleted'; diff --git a/mysql-test/suite/innodb/t/innodb_bug11754376.test b/mysql-test/suite/innodb/t/innodb_bug11754376.test new file mode 100644 index 00000000000..b740b7e08fe --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug11754376.test @@ -0,0 +1,16 @@ +# +# Bug#11754376 45976: INNODB LOST FILES FOR TEMPORARY TABLES ON GRACEFUL SHUTDOWN +# + +-- source include/have_debug.inc +-- source include/have_innodb.inc + +CREATE TABLE bug11754376 (c INT) ENGINE=INNODB; + +# This will invoke test_normalize_table_name_low() in debug builds + +SET SESSION DEBUG_DBUG='+d,test_normalize_table_name_low'; + +DROP TABLE bug11754376; + +SET SESSION DEBUG_DBUG='-d,test_normalize_table_name_low'; diff --git a/mysql-test/suite/innodb/t/innodb_bug11766634.test b/mysql-test/suite/innodb/t/innodb_bug11766634.test new file mode 100644 index 00000000000..f360c4b1ce1 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug11766634.test @@ -0,0 +1,59 @@ +# Bug 11766634 59783: InnoDB data grows unexpectedly when inserting, +# truncating, inserting the same set of rows. +# +# Scenario: +# create table t1. Insert $recs records. check size of ibdata1. +# drop table t1. create table t1. Insert the same set of $recs +# records. The size of ibdata1 must not increase. +# + +-- source include/not_embedded.inc +-- source include/have_innodb.inc + +create table t1 (f1 char(255)) engine innodb; +let $MYSQLD_DATADIR=`select @@datadir`; +let IBDATA1=$MYSQLD_DATADIR/ibdata1; + +let $recs = 36262; + +--disable_query_log +let $c = $recs; +start transaction; +while ($c) +{ + insert into t1 values ('Hello World'); + dec $c; +} +commit work; +--enable_query_log + +perl; +my $filesize = -s $ENV{'IBDATA1'}; +my $filename = $ENV{MYSQL_TMP_DIR} . '/innodb_bug11766634.txt'; +open F, '>', $filename or die "open(>$filename): $!"; +print F $filesize; +EOF + +drop table t1; +create table t1 (f1 char(255)) engine innodb; + +--disable_query_log +let $c = $recs; +start transaction; +while ($c) +{ + insert into t1 values ('Hello World'); + dec $c; +} +commit work; +--enable_query_log + +perl; +my $filesize = -s $ENV{'IBDATA1'}; +my $filename = $ENV{MYSQL_TMP_DIR} . '/innodb_bug11766634.txt'; +$_=do $filename; +print $_ == $filesize, "\n"; +EOF + +drop table t1; + diff --git a/mysql-test/suite/innodb/t/innodb_bug13510739.test b/mysql-test/suite/innodb/t/innodb_bug13510739.test new file mode 100644 index 00000000000..f10bcd8e272 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug13510739.test @@ -0,0 +1,20 @@ +# +# Bug#13510739 63775: SERVER CRASH ON HANDLER READ NEXT AFTER DELETE RECORD. +# + +-- source include/have_innodb.inc + +CREATE TABLE bug13510739 (c INTEGER NOT NULL, PRIMARY KEY (c)) ENGINE=INNODB; + +INSERT INTO bug13510739 VALUES (1), (2), (3), (4); + +DELETE FROM bug13510739 WHERE c=2; + +HANDLER bug13510739 OPEN; + +HANDLER bug13510739 READ `primary` = (2); + +# this one crashes the server if the bug is present +HANDLER bug13510739 READ `primary` NEXT; + +DROP TABLE bug13510739; diff --git a/mysql-test/suite/innodb/t/innodb_bug34300.test b/mysql-test/suite/innodb/t/innodb_bug34300.test index 3f496741c6a..11682ad7828 100644 --- a/mysql-test/suite/innodb/t/innodb_bug34300.test +++ b/mysql-test/suite/innodb/t/innodb_bug34300.test @@ -7,6 +7,9 @@ -- disable_query_log -- disable_result_log +call mtr.add_suppression("InnoDB: Warning: a long semaphore wait:"); +call mtr.add_suppression("the age of the last checkpoint is"); + # set packet size and reconnect let $max_packet=`select @@global.max_allowed_packet`; SET @@global.max_allowed_packet=16777216; diff --git a/mysql-test/suite/innodb/t/innodb_bug53756.test b/mysql-test/suite/innodb/t/innodb_bug53756.test index 2f778d45f61..c298c945434 100644 --- a/mysql-test/suite/innodb/t/innodb_bug53756.test +++ b/mysql-test/suite/innodb/t/innodb_bug53756.test @@ -137,6 +137,9 @@ INSERT INTO bug_53756 VALUES (666,666); # Request a crash on next execution of commit. SET SESSION debug_dbug="+d,crash_commit_before"; # +# Write file to make mysql-test-run.pl start up the server again +--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +# # Execute the statement that causes the crash. --error 2013 COMMIT; @@ -152,9 +155,6 @@ COMMIT; --echo # --echo # Restart server. # -# Write file to make mysql-test-run.pl start up the server again ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect -# # Turn on reconnect --enable_reconnect # diff --git a/mysql-test/suite/maria/r/maria-autozerofill.result b/mysql-test/suite/maria/r/maria-autozerofill.result index 81df4cbab90..22856fe54b0 100644 --- a/mysql-test/suite/maria/r/maria-autozerofill.result +++ b/mysql-test/suite/maria/r/maria-autozerofill.result @@ -4,17 +4,59 @@ create database mysqltest; use mysqltest; create table t1(a int) engine=aria; insert into t1 values(1); -flush table t1; +create table t2 (a int) engine=aria; +INSERT INTO t2 VALUES (1),(2); +create table t3 (a int) engine=aria; +INSERT INTO t3 VALUES (1),(2); +create table t4 (a int) engine=aria; +INSERT INTO t4 VALUES (1),(2); +create table t5 (a int) engine=aria; +INSERT INTO t5 VALUES (1),(2); +flush tables; create_rename_lsn has non-magic value * shut down mysqld, removed logs, restarted it select * from t1; a 1 Warnings: -Error 1194 t1' is marked as crashed and should be repaired +Note 1194 Zerofilling moved table ./mysqltest/t1 flush table t1; Status: changed,sorted index pages,zerofilled insert into t1 values(2); flush table t1; create_rename_lsn has non-magic value +check table t2; +Table Op Msg_type Msg_text +mysqltest.t2 check error Table is from another system and must be zerofilled or repaired to be usable on this system +mysqltest.t2 check error Corrupt +check table t2; +Table Op Msg_type Msg_text +mysqltest.t2 check error Table is from another system and must be zerofilled or repaired to be usable on this system +mysqltest.t2 check error Corrupt +repair table t2; +Table Op Msg_type Msg_text +mysqltest.t2 repair status OK +check table t2; +Table Op Msg_type Msg_text +mysqltest.t2 check status OK +optimize table t3; +Table Op Msg_type Msg_text +mysqltest.t3 optimize Note Zerofilling moved table ./mysqltest/t3 +mysqltest.t3 optimize status OK +analyze table t4; +Table Op Msg_type Msg_text +mysqltest.t4 analyze Note Zerofilling moved table ./mysqltest/t4 +mysqltest.t4 analyze status OK +repair table t5; +Table Op Msg_type Msg_text +mysqltest.t5 repair status OK +check table t5; +Table Op Msg_type Msg_text +mysqltest.t5 check status OK +repair table t5; +Table Op Msg_type Msg_text +mysqltest.t5 repair status OK +check table t5; +Table Op Msg_type Msg_text +mysqltest.t5 check status OK drop database mysqltest; diff --git a/mysql-test/suite/maria/r/maria-recovery2.result b/mysql-test/suite/maria/r/maria-recovery2.result index 2c92bb8dace..149ce5a01af 100644 --- a/mysql-test/suite/maria/r/maria-recovery2.result +++ b/mysql-test/suite/maria/r/maria-recovery2.result @@ -84,10 +84,11 @@ Table Op Msg_type Msg_text mysqltest.t1 check status OK * testing that checksum after recovery is as expected Checksum-check -ok +failure use mysqltest; select * from t1; a +1 3 drop table t1; * TEST of recovery when crash before bulk-insert-with-repair is committed diff --git a/mysql-test/suite/maria/t/maria-autozerofill.test b/mysql-test/suite/maria/t/maria-autozerofill.test index b42b8e177dc..9bb2782105a 100644 --- a/mysql-test/suite/maria/t/maria-autozerofill.test +++ b/mysql-test/suite/maria/t/maria-autozerofill.test @@ -22,9 +22,19 @@ connection default; use mysqltest; --enable_reconnect +# Create some tables for future tests create table t1(a int) engine=aria; insert into t1 values(1); -flush table t1; +create table t2 (a int) engine=aria; +INSERT INTO t2 VALUES (1),(2); +create table t3 (a int) engine=aria; +INSERT INTO t3 VALUES (1),(2); +create table t4 (a int) engine=aria; +INSERT INTO t4 VALUES (1),(2); +create table t5 (a int) engine=aria; +INSERT INTO t5 VALUES (1),(2); +flush tables; + # Check that table is not zerofilled, not movable let $MYSQLD_DATADIR= `select @@datadir`; --exec $MARIA_CHK -dv $MYSQLD_DATADIR/mysqltest/t1 >$MYSQLTEST_VARDIR/tmp/ariachk.txt @@ -46,6 +56,7 @@ EOF disable_ps_protocol; # see aria-recover.test replace_regex /Table.*t1/t1/ ; +replace_result \\ /; select * from t1; enable_ps_protocol; flush table t1; @@ -80,4 +91,21 @@ perl; close FILE; EOF +# +# BUG#44422 "mysql_upgrade destroys Maria tables?" +# Check repair and optimize of moved table +# +check table t2; +check table t2; +repair table t2; +check table t2; +replace_result \\ /; +optimize table t3; +replace_result \\ /; +analyze table t4; +repair table t5; +check table t5; +repair table t5; +check table t5; + drop database mysqltest; diff --git a/mysql-test/suite/oqgraph/suite.opt b/mysql-test/suite/oqgraph/suite.opt index bc7ccfc1414..c41e40b894d 100644 --- a/mysql-test/suite/oqgraph/suite.opt +++ b/mysql-test/suite/oqgraph/suite.opt @@ -1 +1 @@ ---plugin-load=$HA_OQGRAPH_SO +--plugin-load=$HA_OQGRAPH_SO --enable-oqgraph diff --git a/mysql-test/suite/oqgraph/suite.pm b/mysql-test/suite/oqgraph/suite.pm index 5066d4e9f8a..4e98aa9757c 100644 --- a/mysql-test/suite/oqgraph/suite.pm +++ b/mysql-test/suite/oqgraph/suite.pm @@ -2,7 +2,8 @@ package My::Suite::OQGraph; @ISA = qw(My::Suite); -return "No OQGraph" unless $ENV{HA_OQGRAPH_SO}; +return "No OQGraph" unless $ENV{HA_OQGRAPH_SO} or + $::mysqld_variables{'oqgraph'} eq "ON"; bless { }; diff --git a/mysql-test/suite/plugins/r/feedback_plugin_install.result b/mysql-test/suite/plugins/r/feedback_plugin_install.result index b1b35072a08..37d26b48501 100644 --- a/mysql-test/suite/plugins/r/feedback_plugin_install.result +++ b/mysql-test/suite/plugins/r/feedback_plugin_install.result @@ -5,7 +5,8 @@ ACTIVE select * from information_schema.feedback where variable_name like 'feed%' and variable_name not like '%_uid'; VARIABLE_NAME VARIABLE_VALUE -FEEDBACK 1.1 +FEEDBACK used 1 +FEEDBACK version 1.1 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/feedback_plugin_load.result b/mysql-test/suite/plugins/r/feedback_plugin_load.result index d434d1282c5..443b91bf0cc 100644 --- a/mysql-test/suite/plugins/r/feedback_plugin_load.result +++ b/mysql-test/suite/plugins/r/feedback_plugin_load.result @@ -4,7 +4,8 @@ ACTIVE select * from information_schema.feedback where variable_name like 'feed%' and variable_name not like '%_uid'; VARIABLE_NAME VARIABLE_VALUE -FEEDBACK 1.1 +FEEDBACK used 1 +FEEDBACK version 1.1 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/feedback_plugin_send.result b/mysql-test/suite/plugins/r/feedback_plugin_send.result index db622cb3f97..2852240ca5b 100644 --- a/mysql-test/suite/plugins/r/feedback_plugin_send.result +++ b/mysql-test/suite/plugins/r/feedback_plugin_send.result @@ -4,7 +4,8 @@ ACTIVE select * from information_schema.feedback where variable_name like 'feed%' and variable_name not like '%_uid'; VARIABLE_NAME VARIABLE_VALUE -FEEDBACK 1.1 +FEEDBACK used 2 +FEEDBACK version 1.1 FEEDBACK_SEND_RETRY_WAIT 60 FEEDBACK_SEND_TIMEOUT 60 FEEDBACK_URL http://mariadb.org/feedback_plugin/post diff --git a/mysql-test/suite/rpl/r/rpl_auto_increment_11932.result b/mysql-test/suite/rpl/r/rpl_auto_increment_11932.result index 62ff28e7159..1d378e2d864 100644 --- a/mysql-test/suite/rpl/r/rpl_auto_increment_11932.result +++ b/mysql-test/suite/rpl/r/rpl_auto_increment_11932.result @@ -1,5 +1,6 @@ include/master-slave.inc [connection master] +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.'); drop database if exists test1; create database test1; use test1; diff --git a/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result b/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result index c132f80f58e..cc693bff752 100644 --- a/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result +++ b/mysql-test/suite/rpl/r/rpl_cant_read_event_incident.result @@ -11,7 +11,7 @@ reset slave; start slave; include/wait_for_slave_param.inc [Last_IO_Errno] Last_IO_Errno = '1236' -Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'binlog truncated in the middle of event; consider out of disk space on master; the start event position from '.' at XXX, the last event was read from 'master-bin.000001' at XXX, the last byte read was read from 'master-bin.000001' at XXX.'' +Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'binlog truncated in the middle of event; consider out of disk space on master; the first event '.' at XXX, the last event read from 'master-bin.000001' at XXX, the last byte read from 'master-bin.000001' at XXX.'' reset master; stop slave; reset slave; diff --git a/mysql-test/suite/rpl/r/rpl_checksum.result b/mysql-test/suite/rpl/r/rpl_checksum.result index feabfc19631..ba5cb1b1b2b 100644 --- a/mysql-test/suite/rpl/r/rpl_checksum.result +++ b/mysql-test/suite/rpl/r/rpl_checksum.result @@ -71,7 +71,7 @@ insert into t1 values (1) /* will not be applied on slave due to simulation */; set @@global.debug_dbug='d,simulate_slave_unaware_checksum'; start slave; include/wait_for_slave_io_error.inc [errno=1236] -Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'Slave can not handle replication events with the checksum that master is configured to log; the start event position from 'master-bin.000009' at 245, the last event was read from 'master-bin.000010' at 245, the last byte read was read from 'master-bin.000010' at 245.'' +Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'Slave can not handle replication events with the checksum that master is configured to log; the first event 'master-bin.000009' at 245, the last event read from 'master-bin.000010' at 245, the last byte read from 'master-bin.000010' at 245.'' select count(*) as zero from t1; zero 0 @@ -87,8 +87,7 @@ include/stop_slave.inc create table t2 (a int); set @@global.debug_dbug='d,simulate_checksum_test_failure'; start slave io_thread; -include/wait_for_slave_io_error.inc [errno=1595] -Last_IO_Error = 'Relay log write failure: could not queue event from master' +include/wait_for_slave_io_error.inc [errno=1595,1913] set @@global.debug_dbug=''; start slave io_thread; include/wait_for_slave_param.inc [Read_Master_Log_Pos] diff --git a/mysql-test/suite/rpl/r/rpl_filter_dbs_dynamic.result b/mysql-test/suite/rpl/r/rpl_filter_dbs_dynamic.result new file mode 100644 index 00000000000..321b8d912e6 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_filter_dbs_dynamic.result @@ -0,0 +1,40 @@ +include/master-slave.inc +[connection master] +SET @@GLOBAL.replicate_do_db="db1"; +ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first +SET @@GLOBAL.replicate_ignore_db="db2"; +ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first +include/stop_slave.inc +SET @@GLOBAL.replicate_do_db="db1"; +SET @@GLOBAL.replicate_ignore_db="db2"; +include/start_slave.inc +CREATE DATABASE db1; +CREATE DATABASE db2; +CREATE DATABASE db3; +USE db1; +CREATE TABLE t1 (a INT); +USE db2; +CREATE TABLE t2 (a INT); +USE db3; +CREATE TABLE t3 (a INT); +USE db1; +INSERT INTO t1 VALUES (1); +USE db2; +INSERT INTO t2 VALUES (2); +USE db3; +INSERT INTO t3 VALUES (3); +[on slave] +SHOW DATABASES LIKE 'db%'; +Database (db%) +db1 +SHOW TABLES IN db1 LIKE 't%'; +Tables_in_db1 (t%) +t1 +[on master] +[on master] +DROP DATABASE IF EXISTS db1; +DROP DATABASE IF EXISTS db2; +DROP DATABASE IF EXISTS db3; +include/rpl_end.inc +SET @@GLOBAL.replicate_do_db=""; +SET @@GLOBAL.replicate_ignore_db=""; diff --git a/mysql-test/suite/rpl/r/rpl_filter_tables_dynamic.result b/mysql-test/suite/rpl/r/rpl_filter_tables_dynamic.result new file mode 100644 index 00000000000..9eb803d17ea --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_filter_tables_dynamic.result @@ -0,0 +1,127 @@ +include/master-slave.inc +[connection master] +SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3"; +ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first +SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; +ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first +include/stop_slave.inc +SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3"; +SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; +include/start_slave.inc +CREATE TABLE t1 (id int, a int); +CREATE TABLE t2 (id int, b int); +CREATE TABLE t3 (id int, c int); +CREATE TABLE t4 (id int, d int); +CREATE TABLE t5 (id int, e int); +CREATE TABLE t6 (id int, f int); +CREATE TABLE t7 (id int, g int); +CREATE TABLE t8 (id int, h int); +CREATE TABLE t9 (id int, i int); +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t3 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t4 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t5 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t6 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t7 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t8 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t9 VALUES (1, 1), (2, 2), (3, 3); +[on slave] +SHOW TABLES LIKE 't%'; +Tables_in_test (t%) +t1 +t2 +t3 +[on master] +UPDATE t7 LEFT JOIN t4 ON (t4.id=t7.id) SET d=0, g=0 where t7.id=1; +UPDATE t7 LEFT JOIN (t4, t5, t6) ON (t7.id=t4.id and t7.id=t5.id and t7.id=t6.id) SET d=0, e=0, f=0, g=0 where t7.id=1; +UPDATE t4 LEFT JOIN (t7, t8, t9) ON (t4.id=t7.id and t4.id=t8.id and t4.id=t9.id) SET d=0, g=0, h=0, i=0 where t4.id=1; +UPDATE t7 LEFT JOIN (t8, t9) ON (t7.id=t8.id and t7.id=t9.id) SET g=0, h=0, i=0 where t7.id=1; +UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET d=0 where t1.id=1; +UPDATE t1 LEFT JOIN t7 ON (t1.id=t7.id) SET g=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t4, t5, t6) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t6.id) SET d=0, e=0, f=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t4, t5, t8) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t8.id) SET d=0, e=0, h=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t7, t8, t5) ON (t1.id=t7.id and t1.id=t8.id and t1.id=t5.id) SET g=0, h=0, e=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t2, t3, t5) ON (t1.id=t2.id and t1.id=t3.id and t1.id=t5.id) SET e=0 where t1.id=1; +UPDATE t4 LEFT JOIN t1 ON (t1.id=t4.id) SET a=0, d=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t7) ON (t4.id=t1.id and t7.id=t4.id) SET a = 0, d=0, g=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t2, t3) ON (t1.id=t4.id and t2.id=t4.id and t3.id=t4.id) SET a=0, b=0, c=0, d=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t2, t5) ON (t1.id=t4.id and t2.id=t4.id and t5.id=t4.id) SET a=0, b=0, e=0, d=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t6, t7) ON (t4.id=t1.id and t4.id=t6.id and t4.id=t7.id) SET a=0, d=0, f=0, g=0 where t4.id=1; +UPDATE t7 LEFT JOIN (t4, t1, t2) ON (t7.id=t4.id and t7.id=t1.id and t7.id=t2.id) SET a=0, b=0, d=0, g=0 where t7.id=1; +UPDATE t7 LEFT JOIN (t8, t4, t1) ON (t7.id=t8.id and t7.id=t4.id and t7.id=t1.id) SET a=0, d=0, g=0, h=0 where t7.id=1; +call mtr.add_suppression("Slave SQL.*Error .Table .test.t[47]. doesn.t exist. on query.* Error_code: 1146"); +UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0 where t1.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t4' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0 where t1.id=1'' +UPDATE t1 LEFT JOIN (t4, t7) ON (t1.id=t4.id and t1.id=t7.id) SET a=0 where t1.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t4' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t1 LEFT JOIN (t4, t7) ON (t1.id=t4.id and t1.id=t7.id) SET a=0 where t1.id=1'' +UPDATE t1 LEFT JOIN (t2, t4, t7) ON (t1.id=t2.id and t1.id=t4.id and t1.id=t7.id) SET a=0, b=0 where t1.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t4' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t1 LEFT JOIN (t2, t4, t7) ON (t1.id=t2.id and t1.id=t4.id and t1.id=t7.id) SET a=0, b=0 where t1.id=1'' +UPDATE t1 LEFT JOIN (t2, t3, t7) ON (t1.id=t2.id and t1.id=t3.id and t1.id=t7.id) SET a=0, b=0, c=0 where t1.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t7' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t1 LEFT JOIN (t2, t3, t7) ON (t1.id=t2.id and t1.id=t3.id and t1.id=t7.id) SET a=0, b=0, c=0 where t1.id=1'' +UPDATE t1 LEFT JOIN t7 ON (t1.id=t7.id) SET a=0, g=0 where t1.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t7' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t1 LEFT JOIN t7 ON (t1.id=t7.id) SET a=0, g=0 where t1.id=1'' +UPDATE t7 LEFT JOIN t1 ON (t1.id=t7.id) SET a=0, g=0 where t7.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t7' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t7 LEFT JOIN t1 ON (t1.id=t7.id) SET a=0, g=0 where t7.id=1'' +UPDATE t1 LEFT JOIN (t4, t5, t7) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t7.id) SET a=0, g=0 where t1.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t4' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t1 LEFT JOIN (t4, t5, t7) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t7.id) SET a=0, g=0 where t1.id=1'' +UPDATE t1 LEFT JOIN (t4, t7, t8) ON (t1.id=t4.id and t1.id=t7.id and t1.id=t8.id) SET a=0, g=0 where t1.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t4' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t1 LEFT JOIN (t4, t7, t8) ON (t1.id=t4.id and t1.id=t7.id and t1.id=t8.id) SET a=0, g=0 where t1.id=1'' +UPDATE t1 LEFT JOIN (t7, t8, t9) ON (t1.id=t7.id and t1.id=t8.id and t1.id=t9.id) SET a=0, g=0, h=0, i=0 where t1.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t7' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t1 LEFT JOIN (t7, t8, t9) ON (t1.id=t7.id and t1.id=t8.id and t1.id=t9.id) SET a=0, g=0, h=0, i=0 where t1.id=1'' +UPDATE t7 LEFT JOIN (t1, t2, t3) ON (t7.id=t1.id and t7.id=t2.id and t7.id=t3.id) SET g=0, a=0, b=0, c=0 where t7.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t7' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t7 LEFT JOIN (t1, t2, t3) ON (t7.id=t1.id and t7.id=t2.id and t7.id=t3.id) SET g=0, a=0, b=0, c=0 where t7.id=1'' +UPDATE t7 LEFT JOIN (t4, t5, t3) ON (t7.id=t4.id and t7.id=t5.id and t7.id=t3.id) SET g=0, c=0 where t7.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t7' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t7 LEFT JOIN (t4, t5, t3) ON (t7.id=t4.id and t7.id=t5.id and t7.id=t3.id) SET g=0, c=0 where t7.id=1'' +UPDATE t7 LEFT JOIN (t8, t9, t3) ON (t7.id=t8.id and t7.id=t9.id and t7.id=t3.id) SET g=0, h=0, i=0, c=0 where t7.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t7' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t7 LEFT JOIN (t8, t9, t3) ON (t7.id=t8.id and t7.id=t9.id and t7.id=t3.id) SET g=0, h=0, i=0, c=0 where t7.id=1'' +UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0, d=0 where t1.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t4' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0, d=0 where t1.id=1'' +UPDATE t1 LEFT JOIN (t4, t5, t6) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t6.id) SET a=0, d=0, e=0, f=0 where t1.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t4' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t1 LEFT JOIN (t4, t5, t6) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t6.id) SET a=0, d=0, e=0, f=0 where t1.id=1'' +UPDATE t4 LEFT JOIN (t1, t5, t6) ON (t4.id=t1.id and t4.id=t5.id and t4.id=t6.id) SET a=0, e=0, f=0 where t4.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t4' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t4 LEFT JOIN (t1, t5, t6) ON (t4.id=t1.id and t4.id=t5.id and t4.id=t6.id) SET a=0, e=0, f=0 where t4.id=1'' +UPDATE t7 LEFT JOIN (t1, t4, t2) ON (t7.id=t1.id and t7.id=t4.id and t7.id=t2.id) SET a=0, b=0, d=0, g=0 where t7.id=1; +include/wait_for_slave_sql_error_and_skip.inc [errno=1146] +Last_SQL_Error = 'Error 'Table 'test.t7' doesn't exist' on query. Default database: 'test'. Query: 'UPDATE t7 LEFT JOIN (t1, t4, t2) ON (t7.id=t1.id and t7.id=t4.id and t7.id=t2.id) SET a=0, b=0, d=0, g=0 where t7.id=1'' +[on slave] +show tables like 't%'; +Tables_in_test (t%) +t1 +t2 +t3 +SELECT * FROM t1; +id a +1 1 +2 2 +3 3 +SELECT * FROM t2; +id b +1 1 +2 2 +3 3 +SELECT * FROM t3; +id c +1 1 +2 2 +3 3 +[on master] +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +include/rpl_end.inc +SET @@GLOBAL.replicate_do_table=""; +SET @@GLOBAL.replicate_ignore_table=""; diff --git a/mysql-test/suite/rpl/r/rpl_filter_wild_tables_dynamic.result b/mysql-test/suite/rpl/r/rpl_filter_wild_tables_dynamic.result new file mode 100644 index 00000000000..6858181234e --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_filter_wild_tables_dynamic.result @@ -0,0 +1,26 @@ +include/master-slave.inc +[connection master] +SET @@GLOBAL.replicate_wild_do_table="test.a%"; +ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first +SET @@GLOBAL.replicate_wild_ignore_table="test.b%"; +ERROR HY000: This operation cannot be performed with a running slave; run STOP SLAVE first +include/stop_slave.inc +SET @@GLOBAL.replicate_wild_do_table="test.a%"; +SET @@GLOBAL.replicate_wild_ignore_table="test.b%"; +include/start_slave.inc +CREATE TABLE a1 (a INT); +CREATE TABLE b1 (a INT); +CREATE TABLE c1 (a INT); +INSERT INTO a1 VALUES (1); +INSERT INTO b1 VALUES (2); +INSERT INTO c1 VALUES (3); +[on slave] +SHOW TABLES LIKE '%1'; +Tables_in_test (%1) +a1 +[on master] +[on master] +DROP TABLE IF EXISTS a1,b1,c1; +include/rpl_end.inc +SET @@GLOBAL.replicate_wild_do_table=""; +SET @@GLOBAL.replicate_wild_ignore_table=""; diff --git a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result index d89bce479e5..193172912be 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result @@ -861,7 +861,8 @@ master-bin.000001 # Table_map # # table_id: # (test_rpl.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Xid # # COMMIT /* XID */ master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `test_rpl`; INSERT INTO t2 SELECT * FROM t1 +master-bin.000001 # Table_map # # table_id: # (test_rpl.t2) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Xid # # COMMIT /* XID */ master-bin.000001 # Query # # BEGIN master-bin.000001 # Query # # use `test_rpl`; INSERT INTO t2 VALUES (1, 't1, text 1') ON DUPLICATE KEY UPDATE b = 't2, text 1' diff --git a/mysql-test/suite/rpl/r/rpl_insert_id_pk.result b/mysql-test/suite/rpl/r/rpl_insert_id_pk.result index c2d6d2c9b0c..467b8c1e5cc 100644 --- a/mysql-test/suite/rpl/r/rpl_insert_id_pk.result +++ b/mysql-test/suite/rpl/r/rpl_insert_id_pk.result @@ -1,5 +1,6 @@ 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(a int auto_increment, primary key(a)); create table t2(b int auto_increment, c int, primary key(b)); insert into t1 values (1),(2),(3); diff --git a/mysql-test/suite/rpl/r/rpl_known_bugs_detection.result b/mysql-test/suite/rpl/r/rpl_known_bugs_detection.result index f7aea20a34f..ea738b710fd 100644 --- a/mysql-test/suite/rpl/r/rpl_known_bugs_detection.result +++ b/mysql-test/suite/rpl/r/rpl_known_bugs_detection.result @@ -46,6 +46,7 @@ ON DUPLICATE KEY UPDATE t1.field_3 = t2.field_c; Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... SELECT... ON DUPLICATE KEY UPDATE is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are updated. This order cannot be predicted and may differ on master and the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. INSERT INTO t2 (field_a, field_b, field_c) VALUES (6, 'f', '6f'); INSERT INTO t1 (field_1, field_2, field_3) SELECT t2.field_a, t2.field_b, t2.field_c @@ -54,6 +55,7 @@ ON DUPLICATE KEY UPDATE t1.field_3 = t2.field_c; Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... SELECT... ON DUPLICATE KEY UPDATE is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are updated. This order cannot be predicted and may differ on master and the slave. +Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. 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. SELECT * FROM t1; id field_1 field_2 field_3 1 1 a 1a diff --git a/mysql-test/suite/rpl/r/rpl_log_pos.result b/mysql-test/suite/rpl/r/rpl_log_pos.result index 941dba2f5af..8910f7c8f74 100644 --- a/mysql-test/suite/rpl/r/rpl_log_pos.result +++ b/mysql-test/suite/rpl/r/rpl_log_pos.result @@ -11,7 +11,7 @@ include/stop_slave.inc change master to master_log_pos=MASTER_LOG_POS; start slave; include/wait_for_slave_io_error.inc [errno=1236] -Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master; the start event position from 'master-bin.000001' at XXX, the last event was read from 'master-bin.000001' at XXX, the last byte read was read from 'master-bin.000001' at XXX.'' +Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master; the first event 'master-bin.000001' at XXX, the last event read from 'master-bin.000001' at XXX, the last byte read from 'master-bin.000001' at XXX.'' include/stop_slave_sql.inc show master status; File Position Binlog_Do_DB Binlog_Ignore_DB diff --git a/mysql-test/suite/rpl/r/rpl_manual_change_index_file.result b/mysql-test/suite/rpl/r/rpl_manual_change_index_file.result index efe9bf076f0..d5331d0fc93 100644 --- a/mysql-test/suite/rpl/r/rpl_manual_change_index_file.result +++ b/mysql-test/suite/rpl/r/rpl_manual_change_index_file.result @@ -5,7 +5,7 @@ CREATE TABLE t1(c1 INT); FLUSH LOGS; call mtr.add_suppression('Got fatal error 1236 from master when reading data from binary log: .*could not find next log'); include/wait_for_slave_io_error.inc [errno=1236] -Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'could not find next log; the start event position from 'master-bin.000001' at XXX, the last event was read from 'master-bin.000002' at XXX, the last byte read was read from 'master-bin.000002' at XXX.'' +Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'could not find next log; the first event 'master-bin.000001' at XXX, the last event read from 'master-bin.000002' at XXX, the last byte read from 'master-bin.000002' at XXX.'' CREATE TABLE t2(c1 INT); FLUSH LOGS; CREATE TABLE t3(c1 INT); diff --git a/mysql-test/suite/rpl/r/rpl_multi_update.result b/mysql-test/suite/rpl/r/rpl_multi_update.result index 8634e86afed..74fb7952a2a 100644 --- a/mysql-test/suite/rpl/r/rpl_multi_update.result +++ b/mysql-test/suite/rpl/r/rpl_multi_update.result @@ -1,5 +1,6 @@ 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 ( a int unsigned not null auto_increment primary key, b int unsigned diff --git a/mysql-test/suite/rpl/r/rpl_multi_update2.result b/mysql-test/suite/rpl/r/rpl_multi_update2.result index a3cab693322..03ed5de473d 100644 --- a/mysql-test/suite/rpl/r/rpl_multi_update2.result +++ b/mysql-test/suite/rpl/r/rpl_multi_update2.result @@ -1,5 +1,6 @@ include/master-slave.inc [connection master] +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT'); drop table if exists t1,t2; CREATE TABLE t1 ( a int unsigned not null auto_increment primary key, diff --git a/mysql-test/suite/rpl/r/rpl_multi_update3.result b/mysql-test/suite/rpl/r/rpl_multi_update3.result index 6b9ec5c3947..bf9946f219f 100644 --- a/mysql-test/suite/rpl/r/rpl_multi_update3.result +++ b/mysql-test/suite/rpl/r/rpl_multi_update3.result @@ -1,5 +1,6 @@ include/master-slave.inc [connection master] +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.'); -------- Test for BUG#9361 -------- CREATE TABLE t1 ( diff --git a/mysql-test/suite/rpl/r/rpl_packet.result b/mysql-test/suite/rpl/r/rpl_packet.result index 4b2a525de27..4d5ffae2d63 100644 --- a/mysql-test/suite/rpl/r/rpl_packet.result +++ b/mysql-test/suite/rpl/r/rpl_packet.result @@ -37,7 +37,7 @@ DROP TABLE t1; CREATE TABLE t1 (f1 int PRIMARY KEY, f2 LONGTEXT, f3 LONGTEXT) ENGINE=MyISAM; INSERT INTO t1(f1, f2, f3) VALUES(1, REPEAT('a', @@global.max_allowed_packet), REPEAT('b', @@global.max_allowed_packet)); include/wait_for_slave_io_error.inc [errno=1236] -Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master; the start event position from '.' at XXX, the last event was read from 'master-bin.000001' at XXX, the last byte read was read from 'master-bin.000001' at XXX.'' +Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master; the first event '.' at XXX, the last event read from 'master-bin.000001' at XXX, the last byte read from 'master-bin.000001' at XXX.'' STOP SLAVE; RESET SLAVE; RESET MASTER; diff --git a/mysql-test/suite/rpl/r/rpl_report_port.result b/mysql-test/suite/rpl/r/rpl_report_port.result new file mode 100644 index 00000000000..ebdd3f889f3 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_report_port.result @@ -0,0 +1,8 @@ +include/master-slave.inc +[connection master] +include/assert.inc [The default value shown for the slave's port number is the actual port number of the slave.] +include/rpl_restart_server.inc [server_number=2 parameters: --report-port=9000] +include/start_slave.inc +[Slave restarted with the report-port set to some value] +include/assert.inc [The value shown for the slave's port number is 9000 which is the value set for report-port.] +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_rotate_logs.result b/mysql-test/suite/rpl/r/rpl_rotate_logs.result index 4b830799dd1..f10e30c698d 100644 --- a/mysql-test/suite/rpl/r/rpl_rotate_logs.result +++ b/mysql-test/suite/rpl/r/rpl_rotate_logs.result @@ -1,3 +1,4 @@ +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); start slave; Got one of the listed errors start slave; diff --git a/mysql-test/suite/rpl/r/rpl_show_slave_hosts.result b/mysql-test/suite/rpl/r/rpl_show_slave_hosts.result index 2ada5670e04..16d71e125ab 100644 --- a/mysql-test/suite/rpl/r/rpl_show_slave_hosts.result +++ b/mysql-test/suite/rpl/r/rpl_show_slave_hosts.result @@ -6,7 +6,7 @@ START SLAVE IO_THREAD; include/wait_for_slave_io_to_start.inc SHOW SLAVE HOSTS; Server_id Host Port Master_id -3 slave2 DEFAULT_PORT 1 +3 slave2 SLAVE_PORT 1 2 SLAVE_PORT 1 include/stop_slave_io.inc SHOW SLAVE HOSTS; diff --git a/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result b/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result new file mode 100644 index 00000000000..7820f1ef97f --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_stm_relay_ign_space.result @@ -0,0 +1,5 @@ +include/master-slave.inc +[connection master] +include/assert.inc [Assert that relay log space is close to the limit] +include/diff_tables.inc [master:test.t1,slave:test.t1] +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result b/mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result index 8bf903b0713..2aa2ee3b573 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result +++ b/mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result @@ -75,7 +75,7 @@ CHANGE MASTER TO master_log_pos=MASTER_POS; START SLAVE; include/wait_for_slave_param.inc [Last_IO_Errno] Last_IO_Errno = '1236' -Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'Client requested master to start replication from impossible position; the start event position from 'master-bin.000001' at XXX, the last event was read from 'master-bin.000001' at XXX, the last byte read was read from 'master-bin.000001' at XXX.'' +Last_IO_Error = 'Got fatal error 1236 from master when reading data from binary log: 'Client requested master to start replication from impossible position; the first event 'master-bin.000001' at XXX, the last event read from 'master-bin.000001' at XXX, the last byte read from 'master-bin.000001' at XXX.'' include/stop_slave.inc RESET SLAVE; RESET MASTER; diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment_11932.test b/mysql-test/suite/rpl/t/rpl_auto_increment_11932.test index d1da69533ec..1e5f9e53478 100644 --- a/mysql-test/suite/rpl/t/rpl_auto_increment_11932.test +++ b/mysql-test/suite/rpl/t/rpl_auto_increment_11932.test @@ -8,6 +8,7 @@ # Test supplied by Are Casilla source include/master-slave.inc; +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.'); --disable_warnings connection master; drop database if exists test1; @@ -42,12 +43,16 @@ CREATE PROCEDURE simpleproc3 () $ DELIMITER ;$ +--disable_warnings CALL simpleproc3(); +--enable_warnings select * from t2; TRUNCATE TABLE `t1`; +--disable_warnings CALL simpleproc3(); +--enable_warnings select * from t1; diff --git a/mysql-test/suite/rpl/t/rpl_checksum.test b/mysql-test/suite/rpl/t/rpl_checksum.test index 68f8f41f755..0f0b84aa632 100644 --- a/mysql-test/suite/rpl/t/rpl_checksum.test +++ b/mysql-test/suite/rpl/t/rpl_checksum.test @@ -143,8 +143,12 @@ connection slave; # instruction to io thread set @@global.debug_dbug='d,simulate_checksum_test_failure'; start slave io_thread; ---let $slave_io_errno= 1595 ---let $show_slave_io_error= 1 +# When the checksum error is detected, the slave sets error code 1913 +# (ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE) in queue_event(), then immediately +# sets error 1595 (ER_SLAVE_RELAY_LOG_WRITE_FAILURE) in handle_slave_io(). +# So we usually get 1595, but it is occasionally possible to get 1913. +--let $slave_io_errno= 1595,1913 +--let $show_slave_io_error= 0 source include/wait_for_slave_io_error.inc; set @@global.debug_dbug=''; diff --git a/mysql-test/suite/rpl/t/rpl_filter_dbs_dynamic.test b/mysql-test/suite/rpl/t/rpl_filter_dbs_dynamic.test new file mode 100644 index 00000000000..9439ee32a42 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_filter_dbs_dynamic.test @@ -0,0 +1,65 @@ +# +# Test if dynamic replication database filter rules are properly evaluated. +# + +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +connection slave; +--error ER_SLAVE_MUST_STOP +SET @@GLOBAL.replicate_do_db="db1"; +--error ER_SLAVE_MUST_STOP +SET @@GLOBAL.replicate_ignore_db="db2"; + +connection slave; +source include/stop_slave.inc; +SET @@GLOBAL.replicate_do_db="db1"; +SET @@GLOBAL.replicate_ignore_db="db2"; +source include/start_slave.inc; +connection master; + +CREATE DATABASE db1; +CREATE DATABASE db2; +CREATE DATABASE db3; + +# db is mentioned in do-db rules +USE db1; +CREATE TABLE t1 (a INT); + +# db is mentioned in ignore-db rules +USE db2; +CREATE TABLE t2 (a INT); + +# db is not mentioned in do-db or ignore-db rules +USE db3; +CREATE TABLE t3 (a INT); + +USE db1; +INSERT INTO t1 VALUES (1); + +USE db2; +INSERT INTO t2 VALUES (2); + +USE db3; +INSERT INTO t3 VALUES (3); + +# Only db1 should be replicated to slave +sync_slave_with_master; +echo [on slave]; +SHOW DATABASES LIKE 'db%'; +SHOW TABLES IN db1 LIKE 't%'; + +connection master; +echo [on master]; + +# Clean up +connection master; +echo [on master]; +DROP DATABASE IF EXISTS db1; +DROP DATABASE IF EXISTS db2; +DROP DATABASE IF EXISTS db3; +--source include/rpl_end.inc + +connection slave; +SET @@GLOBAL.replicate_do_db=""; +SET @@GLOBAL.replicate_ignore_db=""; diff --git a/mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test b/mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test new file mode 100644 index 00000000000..5cc9e8e0789 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_filter_tables_dynamic.test @@ -0,0 +1,218 @@ +# Test evaluation of replication table filter rules +# +# ==== Purpose ==== +# +# Test if dynamic replication table filter rules are properly evaluated +# when some of the tables referenced by the multiple-table update do not +# exist on slave. +# +# ==== Method ==== +# +# Master creates tables t1, t2, t3, t4, t5, t6, t7, t8, t9 and the +# slave is started with the following replication table filter rules: +# +# SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3"; +# +# and +# +# SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; +# +# So the slave only replicate changes to tables t1, t2 and t3 and only +# these tables exist on slave. +# +# From now on, tables t1, t2, and t3 are referenced as do tables, +# tables t4, t5, t6 are referenced as ignore tables, and tables t7, +# t8, t9 are referenced as other tables. +# +# All multi-table update tests reference tables that are not do +# tables, which do not exist on slave. And the following situations +# of multi-table update will be tested: +# +# 1. Do tables are not referenced at all +# 2. Do tables are not referenced for update +# 3. Ignore tables are referenced for update before do tables +# 4. Only do tables are referenced for update +# 5. Do tables and other tables are referenced for update +# 6. Do tables are referenced for update before ignore tables +# +# For 1, 2 and 3, the statement should be ignored by slave, for 4, 5 +# and 6 the statement should be accepted by slave and cause an error +# because of non-exist tables. +# + +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +connection slave; +--error ER_SLAVE_MUST_STOP +SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3"; +--error ER_SLAVE_MUST_STOP +SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; + +connection slave; +source include/stop_slave.inc; +SET @@GLOBAL.replicate_do_table="test.t1,test.t2,test.t3"; +SET @@GLOBAL.replicate_ignore_table="test.t4,test.t5,test.t6"; +source include/start_slave.inc; +connection master; + +# These tables are mentioned in do-table rules +CREATE TABLE t1 (id int, a int); +CREATE TABLE t2 (id int, b int); +CREATE TABLE t3 (id int, c int); + +# These tables are mentioned in ignore-table rules +CREATE TABLE t4 (id int, d int); +CREATE TABLE t5 (id int, e int); +CREATE TABLE t6 (id int, f int); + +# These tables are not mentioned in do-table or ignore-table rules +CREATE TABLE t7 (id int, g int); +CREATE TABLE t8 (id int, h int); +CREATE TABLE t9 (id int, i int); + +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t3 VALUES (1, 1), (2, 2), (3, 3); + +INSERT INTO t4 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t5 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t6 VALUES (1, 1), (2, 2), (3, 3); + +INSERT INTO t7 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t8 VALUES (1, 1), (2, 2), (3, 3); +INSERT INTO t9 VALUES (1, 1), (2, 2), (3, 3); + +# Only t1, t2, t3 should be replicated to slave +sync_slave_with_master; +echo [on slave]; +SHOW TABLES LIKE 't%'; + +connection master; +echo [on master]; + +# +# Do tables are not referenced, these statements should be ignored by +# slave. +# +UPDATE t7 LEFT JOIN t4 ON (t4.id=t7.id) SET d=0, g=0 where t7.id=1; +UPDATE t7 LEFT JOIN (t4, t5, t6) ON (t7.id=t4.id and t7.id=t5.id and t7.id=t6.id) SET d=0, e=0, f=0, g=0 where t7.id=1; +UPDATE t4 LEFT JOIN (t7, t8, t9) ON (t4.id=t7.id and t4.id=t8.id and t4.id=t9.id) SET d=0, g=0, h=0, i=0 where t4.id=1; +UPDATE t7 LEFT JOIN (t8, t9) ON (t7.id=t8.id and t7.id=t9.id) SET g=0, h=0, i=0 where t7.id=1; + +# +# Do tables are not referenced for update, these statements should be +# ignored by slave. +# +UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET d=0 where t1.id=1; +UPDATE t1 LEFT JOIN t7 ON (t1.id=t7.id) SET g=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t4, t5, t6) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t6.id) SET d=0, e=0, f=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t4, t5, t8) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t8.id) SET d=0, e=0, h=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t7, t8, t5) ON (t1.id=t7.id and t1.id=t8.id and t1.id=t5.id) SET g=0, h=0, e=0 where t1.id=1; +UPDATE t1 LEFT JOIN (t2, t3, t5) ON (t1.id=t2.id and t1.id=t3.id and t1.id=t5.id) SET e=0 where t1.id=1; + +# +# Ignore tables are referenced for update before do tables, these +# statements should be ignore by slave. +# +UPDATE t4 LEFT JOIN t1 ON (t1.id=t4.id) SET a=0, d=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t7) ON (t4.id=t1.id and t7.id=t4.id) SET a = 0, d=0, g=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t2, t3) ON (t1.id=t4.id and t2.id=t4.id and t3.id=t4.id) SET a=0, b=0, c=0, d=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t2, t5) ON (t1.id=t4.id and t2.id=t4.id and t5.id=t4.id) SET a=0, b=0, e=0, d=0 where t4.id=1; +UPDATE t4 LEFT JOIN (t1, t6, t7) ON (t4.id=t1.id and t4.id=t6.id and t4.id=t7.id) SET a=0, d=0, f=0, g=0 where t4.id=1; +UPDATE t7 LEFT JOIN (t4, t1, t2) ON (t7.id=t4.id and t7.id=t1.id and t7.id=t2.id) SET a=0, b=0, d=0, g=0 where t7.id=1; +UPDATE t7 LEFT JOIN (t8, t4, t1) ON (t7.id=t8.id and t7.id=t4.id and t7.id=t1.id) SET a=0, d=0, g=0, h=0 where t7.id=1; + +# Sync slave to make sure all above statements are correctly ignored, +# if any of the above statement are not ignored, it would cause error +# and stop slave sql thread. +sync_slave_with_master; +connection slave; +call mtr.add_suppression("Slave SQL.*Error .Table .test.t[47]. doesn.t exist. on query.* Error_code: 1146"); +connection master; + +# Parameters for include/wait_for_slave_sql_error_and_skip.inc: +# Ask it to show SQL error message. +let $show_slave_sql_error= 1; +# The expected error will always be 1146 (ER_NO_SUCH_TABLE). +let $slave_sql_errno= 1146; + +# +# Only do tables are referenced for update, these statements should +# cause error on slave +# +UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t4, t7) ON (t1.id=t4.id and t1.id=t7.id) SET a=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t2, t4, t7) ON (t1.id=t2.id and t1.id=t4.id and t1.id=t7.id) SET a=0, b=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t2, t3, t7) ON (t1.id=t2.id and t1.id=t3.id and t1.id=t7.id) SET a=0, b=0, c=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +# +# Do tables and other tables are referenced for update, these +# statements should cause error on slave +# +UPDATE t1 LEFT JOIN t7 ON (t1.id=t7.id) SET a=0, g=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN t1 ON (t1.id=t7.id) SET a=0, g=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t4, t5, t7) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t7.id) SET a=0, g=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t4, t7, t8) ON (t1.id=t4.id and t1.id=t7.id and t1.id=t8.id) SET a=0, g=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t7, t8, t9) ON (t1.id=t7.id and t1.id=t8.id and t1.id=t9.id) SET a=0, g=0, h=0, i=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN (t1, t2, t3) ON (t7.id=t1.id and t7.id=t2.id and t7.id=t3.id) SET g=0, a=0, b=0, c=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN (t4, t5, t3) ON (t7.id=t4.id and t7.id=t5.id and t7.id=t3.id) SET g=0, c=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN (t8, t9, t3) ON (t7.id=t8.id and t7.id=t9.id and t7.id=t3.id) SET g=0, h=0, i=0, c=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +# +# Do tables are referenced for update before ignore tables +# +UPDATE t1 LEFT JOIN t4 ON (t1.id=t4.id) SET a=0, d=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t1 LEFT JOIN (t4, t5, t6) ON (t1.id=t4.id and t1.id=t5.id and t1.id=t6.id) SET a=0, d=0, e=0, f=0 where t1.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t4 LEFT JOIN (t1, t5, t6) ON (t4.id=t1.id and t4.id=t5.id and t4.id=t6.id) SET a=0, e=0, f=0 where t4.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +UPDATE t7 LEFT JOIN (t1, t4, t2) ON (t7.id=t1.id and t7.id=t4.id and t7.id=t2.id) SET a=0, b=0, d=0, g=0 where t7.id=1; +source include/wait_for_slave_sql_error_and_skip.inc; + +sync_slave_with_master; +echo [on slave]; + +# We should only have tables t1, t2, t3 on slave +show tables like 't%'; + +# The rows in these tables should remain untouched +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +# Clean up +connection master; +echo [on master]; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +--source include/rpl_end.inc + +connection slave; +SET @@GLOBAL.replicate_do_table=""; +SET @@GLOBAL.replicate_ignore_table=""; diff --git a/mysql-test/suite/rpl/t/rpl_filter_wild_tables_dynamic.test b/mysql-test/suite/rpl/t/rpl_filter_wild_tables_dynamic.test new file mode 100644 index 00000000000..c822c81f270 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_filter_wild_tables_dynamic.test @@ -0,0 +1,50 @@ +# +# Test if dynamic replication wild table filter rules are properly evaluated. +# + +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +connection slave; +--error ER_SLAVE_MUST_STOP +SET @@GLOBAL.replicate_wild_do_table="test.a%"; +--error ER_SLAVE_MUST_STOP +SET @@GLOBAL.replicate_wild_ignore_table="test.b%"; + +connection slave; +source include/stop_slave.inc; +SET @@GLOBAL.replicate_wild_do_table="test.a%"; +SET @@GLOBAL.replicate_wild_ignore_table="test.b%"; +source include/start_slave.inc; +connection master; + +# Table is mentioned in wild-do-table rules +CREATE TABLE a1 (a INT); + +# Table is mentioned in wild-ignore-table rules +CREATE TABLE b1 (a INT); + +# Table is not mentioned in wild-do-table or wild-ignore-table rules +CREATE TABLE c1 (a INT); + +INSERT INTO a1 VALUES (1); +INSERT INTO b1 VALUES (2); +INSERT INTO c1 VALUES (3); + +# Only a1 should be replicated to slave +sync_slave_with_master; +echo [on slave]; +SHOW TABLES LIKE '%1'; + +connection master; +echo [on master]; + +# Clean up +connection master; +echo [on master]; +DROP TABLE IF EXISTS a1,b1,c1; +--source include/rpl_end.inc + +connection slave; +SET @@GLOBAL.replicate_wild_do_table=""; +SET @@GLOBAL.replicate_wild_ignore_table=""; diff --git a/mysql-test/suite/rpl/t/rpl_multi_update2.test b/mysql-test/suite/rpl/t/rpl_multi_update2.test index 497568f2738..138c1455952 100644 --- a/mysql-test/suite/rpl/t/rpl_multi_update2.test +++ b/mysql-test/suite/rpl/t/rpl_multi_update2.test @@ -6,6 +6,7 @@ ####################################################### --source include/not_ndb_default.inc --source include/master-slave.inc +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT'); let $engine_type=MyISAM; --source extra/rpl_tests/rpl_multi_update2.test --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_multi_update3.test b/mysql-test/suite/rpl/t/rpl_multi_update3.test index f6e70f14b30..dc12d528c24 100644 --- a/mysql-test/suite/rpl/t/rpl_multi_update3.test +++ b/mysql-test/suite/rpl/t/rpl_multi_update3.test @@ -6,6 +6,7 @@ ####################################################### --source include/not_ndb_default.inc --source include/master-slave.inc +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.'); let $engine_type=MyISAM; -- source extra/rpl_tests/rpl_multi_update3.test --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_optimize.test b/mysql-test/suite/rpl/t/rpl_optimize.test index b48ef579b6b..47063539ffc 100644 --- a/mysql-test/suite/rpl/t/rpl_optimize.test +++ b/mysql-test/suite/rpl/t/rpl_optimize.test @@ -25,6 +25,7 @@ enable_query_log; create table t1 (a int not null auto_increment primary key, b int, key(b)); INSERT INTO t1 (a) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); +--disable_warnings INSERT INTO t1 (a) SELECT null FROM t1; INSERT INTO t1 (a) SELECT null FROM t1; INSERT INTO t1 (a) SELECT null FROM t1; @@ -38,6 +39,7 @@ INSERT INTO t1 (a) SELECT null FROM t1; INSERT INTO t1 (a) SELECT null FROM t1; INSERT INTO t1 (a) SELECT null FROM t1; INSERT INTO t1 (a) SELECT null FROM t1; +--enable_warnings save_master_pos; # a few updates to force OPTIMIZE to do something --disable_warnings diff --git a/mysql-test/suite/rpl/t/rpl_report_port-slave.opt b/mysql-test/suite/rpl/t/rpl_report_port-slave.opt new file mode 100644 index 00000000000..ffe2b2e7016 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_report_port-slave.opt @@ -0,0 +1 @@ +--report-port= diff --git a/mysql-test/suite/rpl/t/rpl_report_port.test b/mysql-test/suite/rpl/t/rpl_report_port.test new file mode 100644 index 00000000000..b1b71a2982c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_report_port.test @@ -0,0 +1,49 @@ +# +#BUG#13333431 : INCORRECT DEFAULT PORT IN 'SHOW SLAVE HOSTS' OUTPUT +# +# ==== Purpose ==== +# +# The test show the default value printed for the slave's port number if the +# --report-port= <some value> is not set on the slave. This is different from +# the present scenario which show 3306 as the default value if the report-port +# is not set on the slave. +# +#====Method==== +# +# Start replication with report port not set.This will give the actual port +# number of the slave (ie. SLAVE_PORT) for the on doing SHOW SLAVE HOSTS on +# the master. +# Restart the slave server with report port set to 9000 and start the slave. +# In this case on doing SHOW SLAVE HOSTS on the master, we get the port number +# of the slave to be 9000. + +source include/master-slave.inc; + +connection master; + +--let $report_port= query_get_value(SHOW SLAVE HOSTS, Port, 1) +--let assert_text= The default value shown for the slave's port number is the actual port number of the slave. +--let assert_cond= $report_port = "$SLAVE_MYPORT" +--source include/assert.inc + +# Start the server with some value being passed to the report_port= <option> +# this will be used incase we have to mask the value of the slave's port +# number in certain situations. + +--let $rpl_server_number= 2 +--let $rpl_server_parameters= --report-port=9000 +--source include/rpl_restart_server.inc + +connection slave; +--source include/start_slave.inc + +--echo [Slave restarted with the report-port set to some value] +connection master; + +# 9000 is the value of the port we should get. +--let $report_port= query_get_value(SHOW SLAVE HOSTS, Port, 1) +--let assert_text= The value shown for the slave's port number is 9000 which is the value set for report-port. +--let assert_cond= $report_port = "9000" +--source include/assert.inc + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_rotate_logs.test b/mysql-test/suite/rpl/t/rpl_rotate_logs.test index 77ce540ff36..393623888ec 100644 --- a/mysql-test/suite/rpl/t/rpl_rotate_logs.test +++ b/mysql-test/suite/rpl/t/rpl_rotate_logs.test @@ -27,6 +27,7 @@ EOF chmod 0000 $MYSQLD_SLAVE_DATADIR/master.info; connection slave; +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); # START SLAVE will fail because it can't read the file (mode 000) # (system error 13) --replace_result $MYSQL_TEST_DIR TESTDIR diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event.test b/mysql-test/suite/rpl/t/rpl_semi_sync_event.test index c84f597c1ee..b4a9a9e6e59 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_event.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event.test @@ -52,9 +52,10 @@ SET GLOBAL event_scheduler = ON; replace_result $engine_type ENGINE_TYPE; eval CREATE TABLE t1 (i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, f varchar(8)) ENGINE=$engine_type; INSERT INTO t1 (f) VALUES ('a'),('a'),('a'),('a'),('a'); +--disable_warnings INSERT INTO t1 SELECT i+5, f FROM t1; INSERT INTO t1 SELECT i+10, f FROM t1; - +--enable_warnings CREATE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO t1 VALUES (SLEEP(5),CONCAT('ev1_',CONNECTION_ID())); CREATE EVENT ev2 ON SCHEDULE EVERY 1 SECOND diff --git a/mysql-test/suite/rpl/t/rpl_show_slave_hosts.test b/mysql-test/suite/rpl/t/rpl_show_slave_hosts.test index 105f1873659..7ba5e90b96d 100644 --- a/mysql-test/suite/rpl/t/rpl_show_slave_hosts.test +++ b/mysql-test/suite/rpl/t/rpl_show_slave_hosts.test @@ -25,6 +25,7 @@ let $field= Server_id; # 3 is server_id of slave2. let $condition= ='3'; source include/wait_show_condition.inc; +--replace_column 3 'SLAVE_PORT' --replace_result $SLAVE_MYPORT SLAVE_PORT $DEFAULT_MASTER_PORT DEFAULT_PORT SHOW SLAVE HOSTS; diff --git a/mysql-test/suite/rpl/t/rpl_start_stop_slave.test b/mysql-test/suite/rpl/t/rpl_start_stop_slave.test index ffe346d9731..c9c8f043668 100644 --- a/mysql-test/suite/rpl/t/rpl_start_stop_slave.test +++ b/mysql-test/suite/rpl/t/rpl_start_stop_slave.test @@ -28,7 +28,8 @@ set @time_before_kill := (select CURRENT_TIMESTAMP); --replace_regex /kill [0-9]*/kill <connection_id>/ --eval kill $connection_id - +let $wait_condition= SELECT COUNT(*) = 0 FROM information_schema.processlist where id=$connection_id; +--source include/wait_condition.inc set @time_after_kill := (select CURRENT_TIMESTAMP); --echo [Time after the query] @@ -38,10 +39,9 @@ if(`select TIMESTAMPDIFF(SECOND,@time_after_kill, @time_before_kill) > 60`) --echo # assert : The difference between the timestamps 'time_after_kill' and 'time_before_kill' should be less than 60sec. --die } - --echo [Killing of the slave IO thread was successful] ---disable_warnings + START SLAVE IO_THREAD; ---enable_warnings + # End of test --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt new file mode 100644 index 00000000000..f780540aba8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space-slave.opt @@ -0,0 +1 @@ +--relay-log-space-limit=8192 --relay-log-purge --max-relay-log-size=4096 diff --git a/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test new file mode 100644 index 00000000000..db6e6bd14bf --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_relay_ign_space.test @@ -0,0 +1,101 @@ +# +# BUG#12400313 / BUG#64503 test case +# +# +# Description +# ----------- +# +# This test case starts the slave server with: +# --relay-log-space-limit=8192 --relay-log-purge --max-relay-log-size=4096 +# +# Then it issues some queries that will cause the slave to reach +# relay-log-space-limit. We lock the table so that the SQL thread is +# not able to purge the log and then we issue some more statements. +# +# The purpose is to show that the IO thread will honor the limits +# while the SQL thread is not able to purge the relay logs, which did +# not happen before this patch. In addition we assert that while +# ignoring the limit (SQL thread needs to rotate before purging), the +# IO thread does not do it in an uncontrolled manner. + +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc +--source include/have_innodb.inc + +--disable_query_log +CREATE TABLE t1 (c1 TEXT) engine=InnoDB; + +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); + +--sync_slave_with_master + +# wait for the SQL thread to sleep +--let $show_statement= SHOW PROCESSLIST +--let $field= State +--let $condition= = 'Slave has read all relay log; waiting for the slave I/O thread to update it' +--source include/wait_show_condition.inc + +# now the io thread has set rli->ignore_space_limit +# lets lock the table so that once the SQL thread awakes +# it blocks there and does not set rli->ignore_space_limit +# back to zero +LOCK TABLE t1 WRITE; + +# now issue more statements that will overflow the +# rli->log_space_limit (in this case ~10K) +--connection master + +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); +INSERT INTO t1 VALUES ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); + +--connection slave + +# ASSERT that the IO thread waits for the SQL thread to release some +# space before continuing +--let $show_statement= SHOW PROCESSLIST +--let $field= State +--let $condition= LIKE 'Waiting for %' +# before the patch (IO would have transfered everything) +#--let $condition= = 'Waiting for master to send event' +# after the patch (now it waits for space to be freed) +#--let $condition= = 'Waiting for the slave SQL thread to free enough relay log space' +--source include/wait_show_condition.inc + +# without the patch we can uncomment the following two lines and +# watch the IO thread synchronize with the master, thus writing +# relay logs way over the space limit +#--connection master +#--source include/sync_slave_io_with_master.inc + +## ASSERT that the IO thread has honored the limit+few bytes required to be able to purge +--let $relay_log_space_while_sql_is_executing = query_get_value(SHOW SLAVE STATUS, Relay_Log_Space, 1) +--let $relay_log_space_limit = query_get_value(SHOW VARIABLES LIKE "relay_log_space_limit", Value, 1) +--let $assert_text= Assert that relay log space is close to the limit +--let $assert_cond= $relay_log_space_while_sql_is_executing <= $relay_log_space_limit * 1.15 +--source include/assert.inc + +# unlock the table and let SQL thread continue applying events +UNLOCK TABLES; + +--connection master +--sync_slave_with_master +--let $diff_tables=master:test.t1,slave:test.t1 +--source include/diff_tables.inc + +--connection master +DROP TABLE t1; +--enable_query_log +--sync_slave_with_master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_timezone.test b/mysql-test/suite/rpl/t/rpl_timezone.test index 7355106b6b4..1f0220421ab 100644 --- a/mysql-test/suite/rpl/t/rpl_timezone.test +++ b/mysql-test/suite/rpl/t/rpl_timezone.test @@ -13,14 +13,14 @@ # timezone used in CONVERT_TZ is not binlogged. To debug (by Guilhem # and possibly Konstantin). +source include/master-slave.inc; + --disable_query_log CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); --enable_query_log --disable_ps_protocol -source include/master-slave.inc; - # Save original timezone set @my_time_zone= @@global.time_zone; @@ -90,6 +90,7 @@ insert into t1 values ('20040101000000',NULL), ('20040611093902',NULL); # from originally inserted) # set time_zone='MET'; +--disable_warnings ONCE insert into t2 (select * from t1); SELECT * FROM t1 ORDER BY n; sync_slave_with_master; diff --git a/mysql-test/suite/sys_vars/r/debug_dbug_func.result b/mysql-test/suite/sys_vars/r/debug_dbug_func.result index 064769a562b..a622a4d024c 100644 --- a/mysql-test/suite/sys_vars/r/debug_dbug_func.result +++ b/mysql-test/suite/sys_vars/r/debug_dbug_func.result @@ -51,13 +51,13 @@ End of 5.1 tests SET @old_globaldebug = @@global.debug; SET @old_sessiondebug= @@session.debug; # Test 1 - Bug test case, single connection -SET GLOBAL debug_dbug= '+O,../../log/bug46165.1.trace'; +SET GLOBAL debug_dbug= '+O,MYSQL_TMP_DIR/bug46165.1.trace'; SET SESSION debug_dbug= '-d:-t:-i'; SET GLOBAL debug_dbug= ''; SET SESSION debug_dbug= ''; # Test 2 - Bug test case, two connections # Connection default -SET GLOBAL debug_dbug= '+O,../../log/bug46165.2.trace'; +SET GLOBAL debug_dbug= '+O,MYSQL_TMP_DIR/bug46165.2.trace'; SET SESSION debug_dbug= '-d:-t:-i'; # Connection con1 SET GLOBAL debug_dbug= ''; @@ -68,12 +68,21 @@ SET SESSION debug_dbug= ''; SET GLOBAL debug_dbug= ''; # Test 3 - Active session trace file on disconnect # Connection con1 -SET GLOBAL debug_dbug= '+O,../../log/bug46165.3.trace'; -SET SESSION debug_dbug= '-d:-t:-i'; +SET GLOBAL debug_dbug= '+O,MYSQL_TMP_DIR/bug46165.3.trace'; +SELECT @@global.debug_dbug, @@session.debug_dbug; +@@global.debug_dbug @@session.debug_dbug +O,MYSQL_TMP_DIR/bug46165.3.trace O,MYSQL_TMP_DIR/bug46165.3.trace +SET SESSION debug_dbug= '+T'; +SELECT @@global.debug_dbug, @@session.debug_dbug; +@@global.debug_dbug @@session.debug_dbug +O,MYSQL_TMP_DIR/bug46165.3.trace O,MYSQL_TMP_DIR/bug46165.3.trace:T SET GLOBAL debug_dbug= ''; +SELECT @@global.debug_dbug, @@session.debug_dbug; +@@global.debug_dbug @@session.debug_dbug + O,MYSQL_TMP_DIR/bug46165.3.trace:T # Test 4 - Active session trace file on two connections # Connection default -SET GLOBAL debug_dbug= '+O,../../log/bug46165.4.trace'; +SET GLOBAL debug_dbug= '+O,MYSQL_TMP_DIR/bug46165.4.trace'; SET SESSION debug_dbug= '-d:-t:-i'; # Connection con1 SET SESSION debug_dbug= '-d:-t:-i'; @@ -84,8 +93,8 @@ SET SESSION debug_dbug= ''; # Connection con1 # Connection default # Test 5 - Different trace files -SET SESSION debug_dbug= '+O,../../log/bug46165.5.trace'; -SET SESSION debug_dbug= '+O,../../log/bug46165.6.trace'; +SET SESSION debug_dbug= '+O,MYSQL_TMP_DIR/bug46165.5.trace'; +SET SESSION debug_dbug= '+O,MYSQL_TMP_DIR/bug46165.6.trace'; SET SESSION debug_dbug= '-O'; SET GLOBAL debug_dbug= @old_globaldebug; SET SESSION debug_dbug= @old_sessiondebug; diff --git a/mysql-test/suite/sys_vars/r/innodb_adaptive_flushing_basic.result b/mysql-test/suite/sys_vars/r/innodb_adaptive_flushing_basic.result index 418a693d319..5ca47804794 100644 --- a/mysql-test/suite/sys_vars/r/innodb_adaptive_flushing_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_adaptive_flushing_basic.result @@ -73,8 +73,8 @@ set global innodb_adaptive_flushing=1e1; ERROR 42000: Incorrect argument type to variable 'innodb_adaptive_flushing' set global innodb_adaptive_flushing=2; ERROR 42000: Variable 'innodb_adaptive_flushing' can't be set to the value of '2' -NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643) set global innodb_adaptive_flushing=-3; +ERROR 42000: Variable 'innodb_adaptive_flushing' can't be set to the value of '-3' select @@global.innodb_adaptive_flushing; @@global.innodb_adaptive_flushing 1 diff --git a/mysql-test/suite/sys_vars/r/innodb_adaptive_hash_index_basic.result b/mysql-test/suite/sys_vars/r/innodb_adaptive_hash_index_basic.result index bc908090627..1dbd625b52b 100644 --- a/mysql-test/suite/sys_vars/r/innodb_adaptive_hash_index_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_adaptive_hash_index_basic.result @@ -73,8 +73,8 @@ set global innodb_adaptive_hash_index=1e1; ERROR 42000: Incorrect argument type to variable 'innodb_adaptive_hash_index' set global innodb_adaptive_hash_index=2; ERROR 42000: Variable 'innodb_adaptive_hash_index' can't be set to the value of '2' -NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643) set global innodb_adaptive_hash_index=-3; +ERROR 42000: Variable 'innodb_adaptive_hash_index' can't be set to the value of '-3' select @@global.innodb_adaptive_hash_index; @@global.innodb_adaptive_hash_index 1 diff --git a/mysql-test/suite/sys_vars/r/innodb_large_prefix_basic.result b/mysql-test/suite/sys_vars/r/innodb_large_prefix_basic.result index adb56b347cd..3877988bbee 100644 --- a/mysql-test/suite/sys_vars/r/innodb_large_prefix_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_large_prefix_basic.result @@ -73,8 +73,8 @@ set global innodb_large_prefix=1e1; ERROR 42000: Incorrect argument type to variable 'innodb_large_prefix' set global innodb_large_prefix=2; ERROR 42000: Variable 'innodb_large_prefix' can't be set to the value of '2' -NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643) set global innodb_large_prefix=-3; +ERROR 42000: Variable 'innodb_large_prefix' can't be set to the value of '-3' select @@global.innodb_large_prefix; @@global.innodb_large_prefix 1 diff --git a/mysql-test/suite/sys_vars/r/innodb_random_read_ahead_basic.result b/mysql-test/suite/sys_vars/r/innodb_random_read_ahead_basic.result index d627aa92ba7..80075be6374 100644 --- a/mysql-test/suite/sys_vars/r/innodb_random_read_ahead_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_random_read_ahead_basic.result @@ -73,17 +73,17 @@ set global innodb_random_read_ahead=1e1; ERROR 42000: Incorrect argument type to variable 'innodb_random_read_ahead' set global innodb_random_read_ahead=2; ERROR 42000: Variable 'innodb_random_read_ahead' can't be set to the value of '2' -NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643) set global innodb_random_read_ahead=-3; +ERROR 42000: Variable 'innodb_random_read_ahead' can't be set to the value of '-3' select @@global.innodb_random_read_ahead; @@global.innodb_random_read_ahead -1 +0 select * from information_schema.global_variables where variable_name='innodb_random_read_ahead'; VARIABLE_NAME VARIABLE_VALUE -INNODB_RANDOM_READ_AHEAD ON +INNODB_RANDOM_READ_AHEAD OFF select * from information_schema.session_variables where variable_name='innodb_random_read_ahead'; VARIABLE_NAME VARIABLE_VALUE -INNODB_RANDOM_READ_AHEAD ON +INNODB_RANDOM_READ_AHEAD OFF set global innodb_random_read_ahead='AUTO'; ERROR 42000: Variable 'innodb_random_read_ahead' can't be set to the value of 'AUTO' SET @@global.innodb_random_read_ahead = @start_global_value; diff --git a/mysql-test/suite/sys_vars/r/innodb_stats_on_metadata_basic.result b/mysql-test/suite/sys_vars/r/innodb_stats_on_metadata_basic.result index d3410d7b9c1..852ef8a353d 100644 --- a/mysql-test/suite/sys_vars/r/innodb_stats_on_metadata_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_stats_on_metadata_basic.result @@ -73,8 +73,8 @@ set global innodb_stats_on_metadata=1e1; ERROR 42000: Incorrect argument type to variable 'innodb_stats_on_metadata' set global innodb_stats_on_metadata=2; ERROR 42000: Variable 'innodb_stats_on_metadata' can't be set to the value of '2' -NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643) set global innodb_stats_on_metadata=-3; +ERROR 42000: Variable 'innodb_stats_on_metadata' can't be set to the value of '-3' select @@global.innodb_stats_on_metadata; @@global.innodb_stats_on_metadata 1 diff --git a/mysql-test/suite/sys_vars/r/innodb_strict_mode_basic.result b/mysql-test/suite/sys_vars/r/innodb_strict_mode_basic.result index 200f9166215..9c5e62d2684 100644 --- a/mysql-test/suite/sys_vars/r/innodb_strict_mode_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_strict_mode_basic.result @@ -99,9 +99,10 @@ set global innodb_strict_mode='AUTO'; ERROR 42000: Variable 'innodb_strict_mode' can't be set to the value of 'AUTO' set session innodb_strict_mode='AUTO'; ERROR 42000: Variable 'innodb_strict_mode' can't be set to the value of 'AUTO' -NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643) set global innodb_strict_mode=-3; +ERROR 42000: Variable 'innodb_strict_mode' can't be set to the value of '-3' set session innodb_strict_mode=-7; +ERROR 42000: Variable 'innodb_strict_mode' can't be set to the value of '-7' select @@global.innodb_strict_mode; @@global.innodb_strict_mode 1 diff --git a/mysql-test/suite/sys_vars/r/innodb_support_xa_basic.result b/mysql-test/suite/sys_vars/r/innodb_support_xa_basic.result index 537fd3e5db1..754b09310bf 100644 --- a/mysql-test/suite/sys_vars/r/innodb_support_xa_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_support_xa_basic.result @@ -73,6 +73,7 @@ SELECT @@session.innodb_support_xa; SET @@session.innodb_support_xa = ÓFF; ERROR 42000: Variable 'innodb_support_xa' can't be set to the value of 'ÓFF' SET @@global.innodb_support_xa = -1; +ERROR 42000: Variable 'innodb_support_xa' can't be set to the value of '-1' SELECT @@global.innodb_support_xa; @@global.innodb_support_xa 1 diff --git a/mysql-test/suite/sys_vars/r/innodb_table_locks_basic.result b/mysql-test/suite/sys_vars/r/innodb_table_locks_basic.result index e77424df871..08dc5d7aaca 100644 --- a/mysql-test/suite/sys_vars/r/innodb_table_locks_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_table_locks_basic.result @@ -55,6 +55,7 @@ SELECT @@global.innodb_table_locks; 1 '#--------------------FN_DYNVARS_046_04-------------------------#' SET @@session.innodb_table_locks = -6; +ERROR 42000: Variable 'innodb_table_locks' can't be set to the value of '-6' SET @@session.innodb_table_locks = 1.6; ERROR 42000: Incorrect argument type to variable 'innodb_table_locks' SET @@session.innodb_table_locks = "T"; @@ -72,6 +73,7 @@ SELECT @@session.innodb_table_locks; SET @@session.innodb_table_locks = ÓFF; ERROR 42000: Variable 'innodb_table_locks' can't be set to the value of 'ÓFF' SET @@global.innodb_table_locks = -1; +ERROR 42000: Variable 'innodb_table_locks' can't be set to the value of '-1' SET @@global.innodb_table_locks = 2; ERROR 42000: Variable 'innodb_table_locks' can't be set to the value of '2' SET @@global.innodb_table_locks = "T"; diff --git a/mysql-test/suite/sys_vars/r/replicate_do_db_basic.result b/mysql-test/suite/sys_vars/r/replicate_do_db_basic.result new file mode 100644 index 00000000000..b964d3d14a1 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/replicate_do_db_basic.result @@ -0,0 +1,37 @@ +# +# Basic testing of replicate_do_db. +# +SET @save_replicate_do_db = @@GLOBAL.replicate_do_db; +SELECT @save_replicate_do_db; +@save_replicate_do_db + +# Scope. +SET @@SESSION.replicate_do_db = ""; +ERROR HY000: Variable 'replicate_do_db' is a GLOBAL variable and should be set with SET GLOBAL +SELECT @@SESSION.replicate_do_db; +ERROR HY000: Variable 'replicate_do_db' is a GLOBAL variable +# Incorrect type. +SET @@GLOBAL.replicate_do_db=1; +ERROR 42000: Incorrect argument type to variable 'replicate_do_db' +SET @@GLOBAL.replicate_do_db=1.1; +ERROR 42000: Incorrect argument type to variable 'replicate_do_db' +SET @@GLOBAL.replicate_do_db=1e1; +ERROR 42000: Incorrect argument type to variable 'replicate_do_db' +# Argument syntax. +SET @@GLOBAL.replicate_do_db="db1,,,,,db3"; +SELECT @@GLOBAL.replicate_do_db; +@@GLOBAL.replicate_do_db +db1,db3 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate_do_db'; +VARIABLE_NAME VARIABLE_VALUE +REPLICATE_DO_DB db1,db3 +SET @@GLOBAL.replicate_do_db="db1,,,db2,,,db3"; +SELECT @@GLOBAL.replicate_do_db; +@@GLOBAL.replicate_do_db +db1,db2,db3 +SET @@GLOBAL.replicate_do_db=""; +SELECT @@GLOBAL.replicate_do_db; +@@GLOBAL.replicate_do_db + +# Cleanup. +SET @@GLOBAL.replicate_do_db = @save_replicate_do_db; diff --git a/mysql-test/suite/sys_vars/r/replicate_do_table_basic.result b/mysql-test/suite/sys_vars/r/replicate_do_table_basic.result new file mode 100644 index 00000000000..fac237228ac --- /dev/null +++ b/mysql-test/suite/sys_vars/r/replicate_do_table_basic.result @@ -0,0 +1,44 @@ +# +# Basic testing of replicate_do_table. +# +SET @save_replicate_do_table = @@GLOBAL.replicate_do_table; +SELECT @save_replicate_do_table; +@save_replicate_do_table + +# Scope. +SET @@SESSION.replicate_do_table = ""; +ERROR HY000: Variable 'replicate_do_table' is a GLOBAL variable and should be set with SET GLOBAL +SELECT @@SESSION.replicate_do_table; +ERROR HY000: Variable 'replicate_do_table' is a GLOBAL variable +# Incorrect type. +SET @@GLOBAL.replicate_do_table=1; +ERROR 42000: Incorrect argument type to variable 'replicate_do_table' +SET @@GLOBAL.replicate_do_table=1.1; +ERROR 42000: Incorrect argument type to variable 'replicate_do_table' +SET @@GLOBAL.replicate_do_table=1e1; +ERROR 42000: Incorrect argument type to variable 'replicate_do_table' +# Incorrect arguments. +SET @@GLOBAL.replicate_do_table="t1"; +ERROR HY000: Incorrect arguments to SET +SET @@GLOBAL.replicate_do_table="test.t1, t2"; +ERROR HY000: Incorrect arguments to SET +SET @@GLOBAL.replicate_do_table="test.,t1"; +ERROR HY000: Incorrect arguments to SET +# Argument syntax. +SET @@GLOBAL.replicate_do_table="test.t1,,,,,test.t3"; +SELECT @@GLOBAL.replicate_do_table; +@@GLOBAL.replicate_do_table +test.t3,test.t1 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate_do_table'; +VARIABLE_NAME VARIABLE_VALUE +REPLICATE_DO_TABLE test.t3,test.t1 +SET @@GLOBAL.replicate_do_table="test.t1,,,test2.t2,,,test.t3"; +SELECT @@GLOBAL.replicate_do_table; +@@GLOBAL.replicate_do_table +test.t3,test.t1,test2.t2 +SET @@GLOBAL.replicate_do_table=""; +SELECT @@GLOBAL.replicate_do_table; +@@GLOBAL.replicate_do_table + +# Cleanup. +SET @@GLOBAL.replicate_do_table = @save_replicate_do_table; diff --git a/mysql-test/suite/sys_vars/r/replicate_ignore_db_basic.result b/mysql-test/suite/sys_vars/r/replicate_ignore_db_basic.result new file mode 100644 index 00000000000..c4d7a37321e --- /dev/null +++ b/mysql-test/suite/sys_vars/r/replicate_ignore_db_basic.result @@ -0,0 +1,37 @@ +# +# Basic testing of replicate_ignore_db. +# +SET @save_replicate_ignore_db = @@GLOBAL.replicate_ignore_db; +SELECT @save_replicate_ignore_db; +@save_replicate_ignore_db + +# Scope. +SET @@SESSION.replicate_ignore_db = ""; +ERROR HY000: Variable 'replicate_ignore_db' is a GLOBAL variable and should be set with SET GLOBAL +SELECT @@SESSION.replicate_ignore_db; +ERROR HY000: Variable 'replicate_ignore_db' is a GLOBAL variable +# Incorrect type. +SET @@GLOBAL.replicate_ignore_db=1; +ERROR 42000: Incorrect argument type to variable 'replicate_ignore_db' +SET @@GLOBAL.replicate_ignore_db=1.1; +ERROR 42000: Incorrect argument type to variable 'replicate_ignore_db' +SET @@GLOBAL.replicate_ignore_db=1e1; +ERROR 42000: Incorrect argument type to variable 'replicate_ignore_db' +# Argument syntax. +SET @@GLOBAL.replicate_ignore_db="db1,,,,,db3"; +SELECT @@GLOBAL.replicate_ignore_db; +@@GLOBAL.replicate_ignore_db +db1,db3 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate_ignore_db'; +VARIABLE_NAME VARIABLE_VALUE +REPLICATE_IGNORE_DB db1,db3 +SET @@GLOBAL.replicate_ignore_db="db1,,,db2,,,db3"; +SELECT @@GLOBAL.replicate_ignore_db; +@@GLOBAL.replicate_ignore_db +db1,db2,db3 +SET @@GLOBAL.replicate_ignore_db=""; +SELECT @@GLOBAL.replicate_ignore_db; +@@GLOBAL.replicate_ignore_db + +# Cleanup. +SET @@GLOBAL.replicate_ignore_db = @save_replicate_ignore_db; diff --git a/mysql-test/suite/sys_vars/r/replicate_ignore_table_basic.result b/mysql-test/suite/sys_vars/r/replicate_ignore_table_basic.result new file mode 100644 index 00000000000..bc463d07319 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/replicate_ignore_table_basic.result @@ -0,0 +1,44 @@ +# +# Basic testing of replicate_ignore_table. +# +SET @save_replicate_ignore_table = @@GLOBAL.replicate_ignore_table; +SELECT @save_replicate_ignore_table; +@save_replicate_ignore_table + +# Scope. +SET @@SESSION.replicate_ignore_table = ""; +ERROR HY000: Variable 'replicate_ignore_table' is a GLOBAL variable and should be set with SET GLOBAL +SELECT @@SESSION.replicate_ignore_table; +ERROR HY000: Variable 'replicate_ignore_table' is a GLOBAL variable +# Incorrect type. +SET @@GLOBAL.replicate_ignore_table=1; +ERROR 42000: Incorrect argument type to variable 'replicate_ignore_table' +SET @@GLOBAL.replicate_ignore_table=1.1; +ERROR 42000: Incorrect argument type to variable 'replicate_ignore_table' +SET @@GLOBAL.replicate_ignore_table=1e1; +ERROR 42000: Incorrect argument type to variable 'replicate_ignore_table' +# Incorrect arguments. +SET @@GLOBAL.replicate_ignore_table="t1"; +ERROR HY000: Incorrect arguments to SET +SET @@GLOBAL.replicate_ignore_table="test.t1, t2"; +ERROR HY000: Incorrect arguments to SET +SET @@GLOBAL.replicate_ignore_table="test.,t1"; +ERROR HY000: Incorrect arguments to SET +# Argument syntax. +SET @@GLOBAL.replicate_ignore_table="test.t1,,,,,test.t3"; +SELECT @@GLOBAL.replicate_ignore_table; +@@GLOBAL.replicate_ignore_table +test.t3,test.t1 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate_ignore_table'; +VARIABLE_NAME VARIABLE_VALUE +REPLICATE_IGNORE_TABLE test.t3,test.t1 +SET @@GLOBAL.replicate_ignore_table="test.t1,,,test2.t2,,,test.t3"; +SELECT @@GLOBAL.replicate_ignore_table; +@@GLOBAL.replicate_ignore_table +test.t3,test.t1,test2.t2 +SET @@GLOBAL.replicate_ignore_table=""; +SELECT @@GLOBAL.replicate_ignore_table; +@@GLOBAL.replicate_ignore_table + +# Cleanup. +SET @@GLOBAL.replicate_ignore_table = @save_replicate_ignore_table; diff --git a/mysql-test/suite/sys_vars/r/replicate_wild_do_table_basic.result b/mysql-test/suite/sys_vars/r/replicate_wild_do_table_basic.result new file mode 100644 index 00000000000..5647cc964fb --- /dev/null +++ b/mysql-test/suite/sys_vars/r/replicate_wild_do_table_basic.result @@ -0,0 +1,44 @@ +# +# Basic testing of replicate_wild_do_table. +# +SET @save_replicate_wild_do_table = @@GLOBAL.replicate_wild_do_table; +SELECT @save_replicate_wild_do_table; +@save_replicate_wild_do_table + +# Scope. +SET @@SESSION.replicate_wild_do_table = ""; +ERROR HY000: Variable 'replicate_wild_do_table' is a GLOBAL variable and should be set with SET GLOBAL +SELECT @@SESSION.replicate_wild_do_table; +ERROR HY000: Variable 'replicate_wild_do_table' is a GLOBAL variable +# Incorrect type. +SET @@GLOBAL.replicate_wild_do_table=1; +ERROR 42000: Incorrect argument type to variable 'replicate_wild_do_table' +SET @@GLOBAL.replicate_wild_do_table=1.1; +ERROR 42000: Incorrect argument type to variable 'replicate_wild_do_table' +SET @@GLOBAL.replicate_wild_do_table=1e1; +ERROR 42000: Incorrect argument type to variable 'replicate_wild_do_table' +# Incorrect arguments. +SET @@GLOBAL.replicate_wild_do_table="t1"; +ERROR HY000: Incorrect arguments to SET +SET @@GLOBAL.replicate_wild_do_table="test.t, t2"; +ERROR HY000: Incorrect arguments to SET +SET @@GLOBAL.replicate_wild_do_table="test.,t1"; +ERROR HY000: Incorrect arguments to SET +# Argument syntax. +SET @@GLOBAL.replicate_wild_do_table="test.%,,,,,test.t3"; +SELECT @@GLOBAL.replicate_wild_do_table; +@@GLOBAL.replicate_wild_do_table +test.%,test.t3 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate_wild_do_table'; +VARIABLE_NAME VARIABLE_VALUE +REPLICATE_WILD_DO_TABLE test.%,test.t3 +SET @@GLOBAL.replicate_wild_do_table="test.t1,,,test2.%,,,test.t3"; +SELECT @@GLOBAL.replicate_wild_do_table; +@@GLOBAL.replicate_wild_do_table +test.t1,test2.%,test.t3 +SET @@GLOBAL.replicate_wild_do_table=""; +SELECT @@GLOBAL.replicate_wild_do_table; +@@GLOBAL.replicate_wild_do_table + +# Cleanup. +SET @@GLOBAL.replicate_wild_do_table = @save_replicate_wild_do_table; diff --git a/mysql-test/suite/sys_vars/r/replicate_wild_ignore_table_basic.result b/mysql-test/suite/sys_vars/r/replicate_wild_ignore_table_basic.result new file mode 100644 index 00000000000..c6829b792a4 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/replicate_wild_ignore_table_basic.result @@ -0,0 +1,44 @@ +# +# Basic testing of replicate_wild_ignore_table. +# +SET @save_replicate_wild_ignore_table = @@GLOBAL.replicate_wild_ignore_table; +SELECT @save_replicate_wild_ignore_table; +@save_replicate_wild_ignore_table + +# Scope. +SET @@SESSION.replicate_wild_ignore_table = ""; +ERROR HY000: Variable 'replicate_wild_ignore_table' is a GLOBAL variable and should be set with SET GLOBAL +SELECT @@SESSION.replicate_wild_ignore_table; +ERROR HY000: Variable 'replicate_wild_ignore_table' is a GLOBAL variable +# Incorrect type. +SET @@GLOBAL.replicate_wild_ignore_table=1; +ERROR 42000: Incorrect argument type to variable 'replicate_wild_ignore_table' +SET @@GLOBAL.replicate_wild_ignore_table=1.1; +ERROR 42000: Incorrect argument type to variable 'replicate_wild_ignore_table' +SET @@GLOBAL.replicate_wild_ignore_table=1e1; +ERROR 42000: Incorrect argument type to variable 'replicate_wild_ignore_table' +# Incorrect arguments. +SET @@GLOBAL.replicate_wild_ignore_table="t1"; +ERROR HY000: Incorrect arguments to SET +SET @@GLOBAL.replicate_wild_ignore_table="test.t, t2"; +ERROR HY000: Incorrect arguments to SET +SET @@GLOBAL.replicate_wild_ignore_table="test.,t1"; +ERROR HY000: Incorrect arguments to SET +# Argument syntax. +SET @@GLOBAL.replicate_wild_ignore_table="test.%,,,,,test.t3"; +SELECT @@GLOBAL.replicate_wild_ignore_table; +@@GLOBAL.replicate_wild_ignore_table +test.%,test.t3 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate_wild_ignore_table'; +VARIABLE_NAME VARIABLE_VALUE +REPLICATE_WILD_IGNORE_TABLE test.%,test.t3 +SET @@GLOBAL.replicate_wild_ignore_table="test.t1,,,test2.%,,,test.t3"; +SELECT @@GLOBAL.replicate_wild_ignore_table; +@@GLOBAL.replicate_wild_ignore_table +test.t1,test2.%,test.t3 +SET @@GLOBAL.replicate_wild_ignore_table=""; +SELECT @@GLOBAL.replicate_wild_ignore_table; +@@GLOBAL.replicate_wild_ignore_table + +# Cleanup. +SET @@GLOBAL.replicate_wild_ignore_table = @save_replicate_wild_ignore_table; diff --git a/mysql-test/suite/sys_vars/r/rpl_semi_sync_master_enabled_basic.result b/mysql-test/suite/sys_vars/r/rpl_semi_sync_master_enabled_basic.result index ad3ca0de0fa..3e444519441 100644 --- a/mysql-test/suite/sys_vars/r/rpl_semi_sync_master_enabled_basic.result +++ b/mysql-test/suite/sys_vars/r/rpl_semi_sync_master_enabled_basic.result @@ -45,7 +45,7 @@ set session rpl_semi_sync_master_enabled=1; ERROR HY000: Variable 'rpl_semi_sync_master_enabled' is a GLOBAL variable and should be set with SET GLOBAL select @@global.rpl_semi_sync_master_enabled; @@global.rpl_semi_sync_master_enabled --1 +1 select @@session.rpl_semi_sync_master_enabled; ERROR HY000: Variable 'rpl_semi_sync_master_enabled' is a GLOBAL variable show global variables like 'rpl_semi_sync_master_enabled'; diff --git a/mysql-test/suite/sys_vars/r/rpl_semi_sync_slave_enabled_basic.result b/mysql-test/suite/sys_vars/r/rpl_semi_sync_slave_enabled_basic.result index 25688f55ecd..a23b160e6f2 100644 --- a/mysql-test/suite/sys_vars/r/rpl_semi_sync_slave_enabled_basic.result +++ b/mysql-test/suite/sys_vars/r/rpl_semi_sync_slave_enabled_basic.result @@ -45,7 +45,7 @@ set session rpl_semi_sync_slave_enabled=1; ERROR HY000: Variable 'rpl_semi_sync_slave_enabled' is a GLOBAL variable and should be set with SET GLOBAL select @@global.rpl_semi_sync_slave_enabled; @@global.rpl_semi_sync_slave_enabled --1 +1 select @@session.rpl_semi_sync_slave_enabled; ERROR HY000: Variable 'rpl_semi_sync_slave_enabled' is a GLOBAL variable show global variables like 'rpl_semi_sync_slave_enabled'; diff --git a/mysql-test/suite/sys_vars/t/debug_dbug_func.test b/mysql-test/suite/sys_vars/t/debug_dbug_func.test index b57ff812ef5..209c62281fb 100644 --- a/mysql-test/suite/sys_vars/t/debug_dbug_func.test +++ b/mysql-test/suite/sys_vars/t/debug_dbug_func.test @@ -59,7 +59,8 @@ SET @old_globaldebug = @@global.debug; SET @old_sessiondebug= @@session.debug; --echo # Test 1 - Bug test case, single connection -SET GLOBAL debug_dbug= '+O,../../log/bug46165.1.trace'; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +eval SET GLOBAL debug_dbug= '+O,$MYSQL_TMP_DIR/bug46165.1.trace'; SET SESSION debug_dbug= '-d:-t:-i'; SET GLOBAL debug_dbug= ''; @@ -68,7 +69,8 @@ SET SESSION debug_dbug= ''; --echo # Test 2 - Bug test case, two connections --echo # Connection default connection default; -SET GLOBAL debug_dbug= '+O,../../log/bug46165.2.trace'; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +eval SET GLOBAL debug_dbug= '+O,$MYSQL_TMP_DIR/bug46165.2.trace'; SET SESSION debug_dbug= '-d:-t:-i'; --echo # Connection con1 @@ -89,16 +91,24 @@ SET GLOBAL debug_dbug= ''; --echo # Test 3 - Active session trace file on disconnect --echo # Connection con1 connect (con1, localhost, root); -SET GLOBAL debug_dbug= '+O,../../log/bug46165.3.trace'; -SET SESSION debug_dbug= '-d:-t:-i'; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +eval SET GLOBAL debug_dbug= '+O,$MYSQL_TMP_DIR/bug46165.3.trace'; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +SELECT @@global.debug_dbug, @@session.debug_dbug; +SET SESSION debug_dbug= '+T'; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +SELECT @@global.debug_dbug, @@session.debug_dbug; SET GLOBAL debug_dbug= ''; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +SELECT @@global.debug_dbug, @@session.debug_dbug; disconnect con1; --source include/wait_until_disconnected.inc --echo # Test 4 - Active session trace file on two connections --echo # Connection default connection default; -SET GLOBAL debug_dbug= '+O,../../log/bug46165.4.trace'; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +eval SET GLOBAL debug_dbug= '+O,$MYSQL_TMP_DIR/bug46165.4.trace'; SET SESSION debug_dbug= '-d:-t:-i'; --echo # Connection con1 @@ -118,8 +128,10 @@ disconnect con1; connection default; --echo # Test 5 - Different trace files -SET SESSION debug_dbug= '+O,../../log/bug46165.5.trace'; -SET SESSION debug_dbug= '+O,../../log/bug46165.6.trace'; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +eval SET SESSION debug_dbug= '+O,$MYSQL_TMP_DIR/bug46165.5.trace'; +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +eval SET SESSION debug_dbug= '+O,$MYSQL_TMP_DIR/bug46165.6.trace'; SET SESSION debug_dbug= '-O'; SET GLOBAL debug_dbug= @old_globaldebug; diff --git a/mysql-test/suite/sys_vars/t/innodb_adaptive_flushing_basic.test b/mysql-test/suite/sys_vars/t/innodb_adaptive_flushing_basic.test index 236b652f9c6..051d863b13f 100644 --- a/mysql-test/suite/sys_vars/t/innodb_adaptive_flushing_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_adaptive_flushing_basic.test @@ -54,7 +54,7 @@ set global innodb_adaptive_flushing=1.1; set global innodb_adaptive_flushing=1e1; --error ER_WRONG_VALUE_FOR_VAR set global innodb_adaptive_flushing=2; ---echo NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643) +--error ER_WRONG_VALUE_FOR_VAR set global innodb_adaptive_flushing=-3; select @@global.innodb_adaptive_flushing; select * from information_schema.global_variables where variable_name='innodb_adaptive_flushing'; diff --git a/mysql-test/suite/sys_vars/t/innodb_adaptive_hash_index_basic.test b/mysql-test/suite/sys_vars/t/innodb_adaptive_hash_index_basic.test index d6d48ab460c..5171c0e1621 100644 --- a/mysql-test/suite/sys_vars/t/innodb_adaptive_hash_index_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_adaptive_hash_index_basic.test @@ -54,7 +54,7 @@ set global innodb_adaptive_hash_index=1.1; set global innodb_adaptive_hash_index=1e1; --error ER_WRONG_VALUE_FOR_VAR set global innodb_adaptive_hash_index=2; ---echo NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643) +--error ER_WRONG_VALUE_FOR_VAR set global innodb_adaptive_hash_index=-3; select @@global.innodb_adaptive_hash_index; select * from information_schema.global_variables where variable_name='innodb_adaptive_hash_index'; diff --git a/mysql-test/suite/sys_vars/t/innodb_large_prefix_basic.test b/mysql-test/suite/sys_vars/t/innodb_large_prefix_basic.test index 582e9ffbee8..8d3f3afa0a9 100644 --- a/mysql-test/suite/sys_vars/t/innodb_large_prefix_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_large_prefix_basic.test @@ -54,7 +54,7 @@ set global innodb_large_prefix=1.1; set global innodb_large_prefix=1e1; --error ER_WRONG_VALUE_FOR_VAR set global innodb_large_prefix=2; ---echo NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643) +--error ER_WRONG_VALUE_FOR_VAR set global innodb_large_prefix=-3; select @@global.innodb_large_prefix; select * from information_schema.global_variables where variable_name='innodb_large_prefix'; diff --git a/mysql-test/suite/sys_vars/t/innodb_random_read_ahead_basic.test b/mysql-test/suite/sys_vars/t/innodb_random_read_ahead_basic.test index f78223bad02..b7ba6f36b15 100644 --- a/mysql-test/suite/sys_vars/t/innodb_random_read_ahead_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_random_read_ahead_basic.test @@ -54,7 +54,7 @@ set global innodb_random_read_ahead=1.1; set global innodb_random_read_ahead=1e1; --error ER_WRONG_VALUE_FOR_VAR set global innodb_random_read_ahead=2; ---echo NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643) +--error ER_WRONG_VALUE_FOR_VAR set global innodb_random_read_ahead=-3; select @@global.innodb_random_read_ahead; select * from information_schema.global_variables where variable_name='innodb_random_read_ahead'; diff --git a/mysql-test/suite/sys_vars/t/innodb_stats_on_metadata_basic.test b/mysql-test/suite/sys_vars/t/innodb_stats_on_metadata_basic.test index e6d59997ac6..9028ee7f687 100644 --- a/mysql-test/suite/sys_vars/t/innodb_stats_on_metadata_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_stats_on_metadata_basic.test @@ -54,7 +54,7 @@ set global innodb_stats_on_metadata=1.1; set global innodb_stats_on_metadata=1e1; --error ER_WRONG_VALUE_FOR_VAR set global innodb_stats_on_metadata=2; ---echo NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643) +--error ER_WRONG_VALUE_FOR_VAR set global innodb_stats_on_metadata=-3; select @@global.innodb_stats_on_metadata; select * from information_schema.global_variables where variable_name='innodb_stats_on_metadata'; diff --git a/mysql-test/suite/sys_vars/t/innodb_strict_mode_basic.test b/mysql-test/suite/sys_vars/t/innodb_strict_mode_basic.test index 53fbdca2d32..10f8d1ce4e7 100644 --- a/mysql-test/suite/sys_vars/t/innodb_strict_mode_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_strict_mode_basic.test @@ -68,8 +68,9 @@ set session innodb_strict_mode=2; set global innodb_strict_mode='AUTO'; --error ER_WRONG_VALUE_FOR_VAR set session innodb_strict_mode='AUTO'; ---echo NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643) +--error ER_WRONG_VALUE_FOR_VAR set global innodb_strict_mode=-3; +--error ER_WRONG_VALUE_FOR_VAR set session innodb_strict_mode=-7; select @@global.innodb_strict_mode; select @@session.innodb_strict_mode; diff --git a/mysql-test/suite/sys_vars/t/innodb_support_xa_basic.test b/mysql-test/suite/sys_vars/t/innodb_support_xa_basic.test index 65681c4a544..988b8f01b93 100644 --- a/mysql-test/suite/sys_vars/t/innodb_support_xa_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_support_xa_basic.test @@ -127,6 +127,7 @@ SET @@session.innodb_support_xa = ÓFF; # for global +--error ER_WRONG_VALUE_FOR_VAR SET @@global.innodb_support_xa = -1; SELECT @@global.innodb_support_xa; diff --git a/mysql-test/suite/sys_vars/t/innodb_table_locks_basic.test b/mysql-test/suite/sys_vars/t/innodb_table_locks_basic.test index 7af8f700f39..e7503bd334d 100644 --- a/mysql-test/suite/sys_vars/t/innodb_table_locks_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_table_locks_basic.test @@ -106,6 +106,7 @@ SELECT @@global.innodb_table_locks; # for session +--error ER_WRONG_VALUE_FOR_VAR SET @@session.innodb_table_locks = -6; --Error ER_WRONG_TYPE_FOR_VAR SET @@session.innodb_table_locks = 1.6; @@ -127,6 +128,7 @@ SET @@session.innodb_table_locks = ÓFF; # for global +--error ER_WRONG_VALUE_FOR_VAR SET @@global.innodb_table_locks = -1; --Error ER_WRONG_VALUE_FOR_VAR SET @@global.innodb_table_locks = 2; diff --git a/mysql-test/suite/sys_vars/t/replicate_do_db_basic.test b/mysql-test/suite/sys_vars/t/replicate_do_db_basic.test new file mode 100644 index 00000000000..ccf50b1d6ab --- /dev/null +++ b/mysql-test/suite/sys_vars/t/replicate_do_db_basic.test @@ -0,0 +1,39 @@ +--source include/not_embedded.inc + +--echo # +--echo # Basic testing of replicate_do_db. +--echo # + +SET @save_replicate_do_db = @@GLOBAL.replicate_do_db; +SELECT @save_replicate_do_db; + +--echo # Scope. + +--error ER_GLOBAL_VARIABLE +SET @@SESSION.replicate_do_db = ""; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@SESSION.replicate_do_db; + +--echo # Incorrect type. + +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_do_db=1; +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_do_db=1.1; +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_do_db=1e1; + +--echo # Argument syntax. + +SET @@GLOBAL.replicate_do_db="db1,,,,,db3"; +SELECT @@GLOBAL.replicate_do_db; +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate_do_db'; + +SET @@GLOBAL.replicate_do_db="db1,,,db2,,,db3"; +SELECT @@GLOBAL.replicate_do_db; + +SET @@GLOBAL.replicate_do_db=""; +SELECT @@GLOBAL.replicate_do_db; + +--echo # Cleanup. +SET @@GLOBAL.replicate_do_db = @save_replicate_do_db; diff --git a/mysql-test/suite/sys_vars/t/replicate_do_table_basic.test b/mysql-test/suite/sys_vars/t/replicate_do_table_basic.test new file mode 100644 index 00000000000..f3b1585613e --- /dev/null +++ b/mysql-test/suite/sys_vars/t/replicate_do_table_basic.test @@ -0,0 +1,48 @@ +--source include/not_embedded.inc + +--echo # +--echo # Basic testing of replicate_do_table. +--echo # + +SET @save_replicate_do_table = @@GLOBAL.replicate_do_table; +SELECT @save_replicate_do_table; + +--echo # Scope. + +--error ER_GLOBAL_VARIABLE +SET @@SESSION.replicate_do_table = ""; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@SESSION.replicate_do_table; + +--echo # Incorrect type. + +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_do_table=1; +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_do_table=1.1; +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_do_table=1e1; + +--echo # Incorrect arguments. + +--error ER_WRONG_ARGUMENTS +SET @@GLOBAL.replicate_do_table="t1"; +--error ER_WRONG_ARGUMENTS +SET @@GLOBAL.replicate_do_table="test.t1, t2"; +--error ER_WRONG_ARGUMENTS +SET @@GLOBAL.replicate_do_table="test.,t1"; + +--echo # Argument syntax. + +SET @@GLOBAL.replicate_do_table="test.t1,,,,,test.t3"; +SELECT @@GLOBAL.replicate_do_table; +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate_do_table'; + +SET @@GLOBAL.replicate_do_table="test.t1,,,test2.t2,,,test.t3"; +SELECT @@GLOBAL.replicate_do_table; + +SET @@GLOBAL.replicate_do_table=""; +SELECT @@GLOBAL.replicate_do_table; + +--echo # Cleanup. +SET @@GLOBAL.replicate_do_table = @save_replicate_do_table; diff --git a/mysql-test/suite/sys_vars/t/replicate_ignore_db_basic.test b/mysql-test/suite/sys_vars/t/replicate_ignore_db_basic.test new file mode 100644 index 00000000000..3a0bc88109a --- /dev/null +++ b/mysql-test/suite/sys_vars/t/replicate_ignore_db_basic.test @@ -0,0 +1,39 @@ +--source include/not_embedded.inc + +--echo # +--echo # Basic testing of replicate_ignore_db. +--echo # + +SET @save_replicate_ignore_db = @@GLOBAL.replicate_ignore_db; +SELECT @save_replicate_ignore_db; + +--echo # Scope. + +--error ER_GLOBAL_VARIABLE +SET @@SESSION.replicate_ignore_db = ""; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@SESSION.replicate_ignore_db; + +--echo # Incorrect type. + +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_ignore_db=1; +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_ignore_db=1.1; +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_ignore_db=1e1; + +--echo # Argument syntax. + +SET @@GLOBAL.replicate_ignore_db="db1,,,,,db3"; +SELECT @@GLOBAL.replicate_ignore_db; +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate_ignore_db'; + +SET @@GLOBAL.replicate_ignore_db="db1,,,db2,,,db3"; +SELECT @@GLOBAL.replicate_ignore_db; + +SET @@GLOBAL.replicate_ignore_db=""; +SELECT @@GLOBAL.replicate_ignore_db; + +--echo # Cleanup. +SET @@GLOBAL.replicate_ignore_db = @save_replicate_ignore_db; diff --git a/mysql-test/suite/sys_vars/t/replicate_ignore_table_basic.test b/mysql-test/suite/sys_vars/t/replicate_ignore_table_basic.test new file mode 100644 index 00000000000..aebe90732d2 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/replicate_ignore_table_basic.test @@ -0,0 +1,48 @@ +--source include/not_embedded.inc + +--echo # +--echo # Basic testing of replicate_ignore_table. +--echo # + +SET @save_replicate_ignore_table = @@GLOBAL.replicate_ignore_table; +SELECT @save_replicate_ignore_table; + +--echo # Scope. + +--error ER_GLOBAL_VARIABLE +SET @@SESSION.replicate_ignore_table = ""; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@SESSION.replicate_ignore_table; + +--echo # Incorrect type. + +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_ignore_table=1; +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_ignore_table=1.1; +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_ignore_table=1e1; + +--echo # Incorrect arguments. + +--error ER_WRONG_ARGUMENTS +SET @@GLOBAL.replicate_ignore_table="t1"; +--error ER_WRONG_ARGUMENTS +SET @@GLOBAL.replicate_ignore_table="test.t1, t2"; +--error ER_WRONG_ARGUMENTS +SET @@GLOBAL.replicate_ignore_table="test.,t1"; + +--echo # Argument syntax. + +SET @@GLOBAL.replicate_ignore_table="test.t1,,,,,test.t3"; +SELECT @@GLOBAL.replicate_ignore_table; +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate_ignore_table'; + +SET @@GLOBAL.replicate_ignore_table="test.t1,,,test2.t2,,,test.t3"; +SELECT @@GLOBAL.replicate_ignore_table; + +SET @@GLOBAL.replicate_ignore_table=""; +SELECT @@GLOBAL.replicate_ignore_table; + +--echo # Cleanup. +SET @@GLOBAL.replicate_ignore_table = @save_replicate_ignore_table; diff --git a/mysql-test/suite/sys_vars/t/replicate_wild_do_table_basic.test b/mysql-test/suite/sys_vars/t/replicate_wild_do_table_basic.test new file mode 100644 index 00000000000..b96a62f8dd1 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/replicate_wild_do_table_basic.test @@ -0,0 +1,48 @@ +--source include/not_embedded.inc + +--echo # +--echo # Basic testing of replicate_wild_do_table. +--echo # + +SET @save_replicate_wild_do_table = @@GLOBAL.replicate_wild_do_table; +SELECT @save_replicate_wild_do_table; + +--echo # Scope. + +--error ER_GLOBAL_VARIABLE +SET @@SESSION.replicate_wild_do_table = ""; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@SESSION.replicate_wild_do_table; + +--echo # Incorrect type. + +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_wild_do_table=1; +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_wild_do_table=1.1; +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_wild_do_table=1e1; + +--echo # Incorrect arguments. + +--error ER_WRONG_ARGUMENTS +SET @@GLOBAL.replicate_wild_do_table="t1"; +--error ER_WRONG_ARGUMENTS +SET @@GLOBAL.replicate_wild_do_table="test.t, t2"; +--error ER_WRONG_ARGUMENTS +SET @@GLOBAL.replicate_wild_do_table="test.,t1"; + +--echo # Argument syntax. + +SET @@GLOBAL.replicate_wild_do_table="test.%,,,,,test.t3"; +SELECT @@GLOBAL.replicate_wild_do_table; +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate_wild_do_table'; + +SET @@GLOBAL.replicate_wild_do_table="test.t1,,,test2.%,,,test.t3"; +SELECT @@GLOBAL.replicate_wild_do_table; + +SET @@GLOBAL.replicate_wild_do_table=""; +SELECT @@GLOBAL.replicate_wild_do_table; + +--echo # Cleanup. +SET @@GLOBAL.replicate_wild_do_table = @save_replicate_wild_do_table; diff --git a/mysql-test/suite/sys_vars/t/replicate_wild_ignore_table_basic.test b/mysql-test/suite/sys_vars/t/replicate_wild_ignore_table_basic.test new file mode 100644 index 00000000000..2900deab4d1 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/replicate_wild_ignore_table_basic.test @@ -0,0 +1,48 @@ +--source include/not_embedded.inc + +--echo # +--echo # Basic testing of replicate_wild_ignore_table. +--echo # + +SET @save_replicate_wild_ignore_table = @@GLOBAL.replicate_wild_ignore_table; +SELECT @save_replicate_wild_ignore_table; + +--echo # Scope. + +--error ER_GLOBAL_VARIABLE +SET @@SESSION.replicate_wild_ignore_table = ""; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@SESSION.replicate_wild_ignore_table; + +--echo # Incorrect type. + +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_wild_ignore_table=1; +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_wild_ignore_table=1.1; +--error ER_WRONG_TYPE_FOR_VAR +SET @@GLOBAL.replicate_wild_ignore_table=1e1; + +--echo # Incorrect arguments. + +--error ER_WRONG_ARGUMENTS +SET @@GLOBAL.replicate_wild_ignore_table="t1"; +--error ER_WRONG_ARGUMENTS +SET @@GLOBAL.replicate_wild_ignore_table="test.t, t2"; +--error ER_WRONG_ARGUMENTS +SET @@GLOBAL.replicate_wild_ignore_table="test.,t1"; + +--echo # Argument syntax. + +SET @@GLOBAL.replicate_wild_ignore_table="test.%,,,,,test.t3"; +SELECT @@GLOBAL.replicate_wild_ignore_table; +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='replicate_wild_ignore_table'; + +SET @@GLOBAL.replicate_wild_ignore_table="test.t1,,,test2.%,,,test.t3"; +SELECT @@GLOBAL.replicate_wild_ignore_table; + +SET @@GLOBAL.replicate_wild_ignore_table=""; +SELECT @@GLOBAL.replicate_wild_ignore_table; + +--echo # Cleanup. +SET @@GLOBAL.replicate_wild_ignore_table = @save_replicate_wild_ignore_table; diff --git a/mysql-test/suite/sys_vars/t/report_port_basic.test b/mysql-test/suite/sys_vars/t/report_port_basic.test index 122c92c5446..903289230bd 100644 --- a/mysql-test/suite/sys_vars/t/report_port_basic.test +++ b/mysql-test/suite/sys_vars/t/report_port_basic.test @@ -2,18 +2,19 @@ # # only global # ---replace_result $DEFAULT_MASTER_PORT DEFAULT_MASTER_PORT +--replace_regex s/[0-9]+/DEFAULT_MASTER_PORT/ select @@global.report_port; --error ER_INCORRECT_GLOBAL_LOCAL_VAR select @@session.report_port; ---replace_result $DEFAULT_MASTER_PORT DEFAULT_MASTER_PORT +--replace_column 2 'DEFAULT_MASTER_PORT' show global variables like 'report_port'; ---replace_result $DEFAULT_MASTER_PORT DEFAULT_MASTER_PORT +--replace_column 2 'DEFAULT_MASTER_PORT' show session variables like 'report_port'; ---replace_result $DEFAULT_MASTER_PORT DEFAULT_MASTER_PORT +--replace_column 2 'DEFAULT_MASTER_PORT' select * from information_schema.global_variables where variable_name='report_port'; ---replace_result $DEFAULT_MASTER_PORT DEFAULT_MASTER_PORT +--replace_column 2 'DEFAULT_MASTER_PORT' select * from information_schema.session_variables where variable_name='report_port'; +--replace_column 2 'DEFAULT_MASTER_PORT' # # show that it's read-only diff --git a/mysql-test/t/bug13633383.test b/mysql-test/t/bug13633383.test new file mode 100644 index 00000000000..72eb2f81c98 --- /dev/null +++ b/mysql-test/t/bug13633383.test @@ -0,0 +1,82 @@ +--echo # +--echo # Bug#13633383 63183: SMALL SORT_BUFFER_SIZE CRASH IN MERGE_BUFFERS +--echo # + +CREATE TABLE t1 ( + `a` int(11) DEFAULT NULL, + `col432` bit(8) DEFAULT NULL, + `col433` multipoint DEFAULT NULL, + `col434` polygon DEFAULT NULL, + `col435` decimal(50,17) unsigned DEFAULT NULL, + `col436` geometry NOT NULL, + `col437` tinyblob NOT NULL, + `col438` multipolygon DEFAULT NULL, + `col439` mediumblob NOT NULL, + `col440` tinyblob NOT NULL, + `col441` double unsigned DEFAULT NULL +); + +CREATE TABLE t2 ( + `a` multipoint DEFAULT NULL, + `col460` date DEFAULT NULL, + `col461` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `col462` date NOT NULL, + `col463` varbinary(89) NOT NULL, + `col464` year(4) DEFAULT NULL, + `col465` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `col466` varchar(236) CHARACTER SET utf8 NOT NULL, + `col467` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' +); + +CREATE TABLE t3 ( + `FTS_DOC_ID` bigint(20) unsigned NOT NULL, + `col577` datetime DEFAULT NULL, + `col579` bit(38) NOT NULL, + `col580` varchar(93) NOT NULL, + `col581` datetime DEFAULT NULL, + `col583` multipolygon DEFAULT NULL, + `col584` bit(47) NOT NULL +); + +--disable_query_log + +INSERT INTO t1 VALUES (0,0xFF,'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 JæÀ',NULL,0.00000000000000000,'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0àÃ\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0àC\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0àC\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',0xB623A952C5,'\0\0\0\0\0\0\0\0\0\0\0ðiøÀ\0\0\0\0jøÀ',0x22,0xD81F72A9,56403); +INSERT INTO t1 VALUES (-32768,0x00,'\0\0\0\0\0\0\0\0\0\0\0Àrç@\0\0\0\0jøÀ','\0\0\0\0\0\0\0\0\0\0\0\0ÛâÀ\0\0\0\0jøÀ',NULL,'\0\0\0\0\0\0\0\0\0\0\0À6Ò@\0\0\0\0\0jøÀ',0xC80876AF04,'\0\0\0\0\0\0\0\0\0\0\0€[áÀ\0\0\0\0ðiøÀ',0x016C576E34,0x1B,0); +INSERT INTO t1 VALUES (-2147483648,0x17,'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0]ÇÀ',NULL,0.00000000000000000,'\0\0\0\0\0\0\0\0\0\0\0ðiøÀìÊFQƒìCµ',0x68D352,'\0\0\0\0\0\0\0\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0àÃ\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0àC\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0àÃ\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0àC\0\0\0\0\0àÃ\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0','','',0); +INSERT INTO t1 VALUES (1,0xFF,'\0\0\0\0\0\0\0\0\0\0\0Ð÷À\0\0\0\0Àü×À','\0\0\0\0\0\0\0\0\0\0\0`6ë@\0\0\0\0à²î@',32767.00000000000000000,'\0\0\0\0\0\0\0\0\0\0\0ðiø@†ö¯{âÌ',0x1406B0C524,'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0àÃ\0\0\0\0\0àC\0\0\0\0\0àC',0xC04B75CCFD,0xC4CD,1); +INSERT INTO t1 VALUES (0,0xFF,NULL,'\0\0\0\0\0\0\0\0\0\0\0\0jø@\0\0\0\0\0(¦À',0.06140000000000000,'\0\0\0\0\0\0\0\0\0\0\0ðiø@$7”H#ÀÐ1',0x3F,'\0\0\0\0\0\0\0\0\0\0\0jøÀCHK¶µ$·',0x1E87C5DA,0xCC870E,NULL); + + +INSERT INTO t2 VALUES ('\0\0\0\0\0\0\0\0\0\0\0\0k¿À\0\0\0\0\0jø@','2011-02-19','2011-08-10 14:21:44','2012-09-25',0xCCC3,0000,'2012-07-28 16:25:23','idpapxbfjrigkfqnhnfmhvtewlvxfmjhfqizhhsowbetimmkhukpzeixbfyzmsalaafssdovflpvxldldmuamfoulanivuxigbjwkzbapcxmmprpyasaozdqwqjuixajzmiepkcvnvtewdvyodupziffgzbcmsfhikbuehyhzfnxlsdzulbsrqmtszzzupcmxlvcpxahuiotgadwhpcuqmyzgrbkxzxwriqkymdaqnzz','2012-01-20 09:01:25'); +INSERT INTO t2 VALUES (NULL,'2011-05-14','2012-10-17 04:33:30','2012-01-20','',0000,'2012-05-08 11:06:53','otbywkbfwwtgpfgurtqwgfcwmmntsdxkounuzueoclrpnadghfzmbrh','2012-03-24 21:01:09'); +INSERT INTO t2 VALUES ('\0\0\0\0\0\0\06ý¹PVh,;bºö$î°','2012-07-21','2011-11-21 04:23:27','2011-06-18',0x21,0000,'2011-09-10 14:01:05','goybgohrexhfqwerpknkbyiqowvcdpyxvbklkbeeuvfbjtkmontmkmgcjutkjphewnvvobzilamtjqjbtvqgczozqcmvbbzvoxkycsvplfykmzpwljdcromsilspjuoyhxwduymxkymvmijehtutftqmpfpbesonppacogyogjqhyonizbsgzwubzgeoehryqswzkftgzhzssnlstuszpwauxmdhgjcawabnjcynzrrh','2012-11-19 18:30:51'); +INSERT INTO t2 VALUES ('\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0À®ÛÀ','2012-09-01','2012-01-20 09:01:34','2011-02-12',0x1FDF59DC65,0000,'2011-07-07 19:48:34','xohwzrslzxbpxdvqfsumavjwwmsdcgczlmxrtxavsqtnpggxesvekbcelnnrxkvvlwqwbydlhwzltwaurkfltafeijstmzueiqddjdxzddymhsungndmojndbspkezvdfhqxijxxrwiolqgnsedenszkiljgropmcbxsjntjmnonnltyiysuejsznuurmonebslawybppziavystrylwunselezpbslmkzggpziffrud','2012-01-19 22:00:00'); +INSERT INTO t2 VALUES ('\0\0\0\0\0\0\0\0\0\0\0\0jø@\0\0\0\0\0\0\0\0','0000-00-00','2012-05-21 09:59:10','2011-04-17',0x02307EDF,0000,'2012-01-20 09:01:34','vjcwlxxeydntegsdqhxgriarmbvzwzwdexcalvacxhilaejpmxdpkuvblukchagzoellbdndelfednqktzobyhjqweqaugqnfikdalmaytyunjqvxcsirhaqnvqsstgrgfscnsemseebdemfditoswccsxthnddzslgjkyujxoqsvzrssymoovqmibcmbboruyxlvopengdqqgqwekrflhvjcpondxivnshvhrnqvfls','2012-09-23 23:54:02'); + + +INSERT INTO t3 VALUES (11787,'2012-07-24 15:22:50',0x00000000FF,'qbdydwxepydtonqnghurnuntughjwfygzttqwtmfzfbtifjcearpatksofbrfgnaccvapahywhsstdplphrxbcubhktov','2011-08-27 19:28:03',NULL,0x00000000001C); + +INSERT INTO t3 VALUES (11788,'2012-05-17 08:38:13',0x3FFFFFFFFF,'jkvkjxaikruljqalyvnbfjptxgbpsgnxlzthhcrswwdcfrhilwwgqmxynxjnehwmyfzdyywjzfyasuvjbrevkxtnyodiu','2012-05-09 11:09:52',NULL,0x0000000000B8); + +INSERT INTO t3 VALUES (1,'2011-02-17 19:55:19',0x000098FAF3,'rnzhemtrqjdrappwbmxnzkfatcgtvqklrpfpdqiwjnjbeaxpcbhqqunbzmtmitdszxyrdvkeedqwpbiefqnwvhiznwfyq','2012-11-10 18:00:25','\0\0\0\0\0\0\0\0\0\0\0\0jøÀ\0\0\0\0€1á@',0x7FFFFFFFFFFF); + +INSERT INTO t3 VALUES (11789,'2011-12-26 01:30:56',0x0000000001,'dhryqjghgixymqywclxpovwnlgnltuzdvggmlaxtzrsbpxkahkiahpkrddpoeftqqwejbjxrdzfgvkzvhcalopgumspgg','2011-03-21 06:25:44',NULL,0x00000000293A); + +INSERT INTO t3 VALUES (4294967296,'2011-04-12 21:05:37',0x0000CE3238,'xwcplgaxcpgfsmcjftxffxgmjwabpmrcycbxmwjvqtlvtlwuipuwgbuygnxomjplqohyuqyzsoiggroigcnchzpiilyhe','2012-03-20 05:35:39',NULL,0x00000000006E); + +--enable_query_log + +set session sort_buffer_size= 32768; +select col435 +from t3 +natural right outer join t1 +natural right outer join t2 a +left outer join t2 b on 1 +group by + repeat('a',10000) desc, + repeat('a',10000) +with rollup +; +set session sort_buffer_size= default; + +DROP TABLE t1, t2, t3; diff --git a/mysql-test/t/cache_innodb-master.opt b/mysql-test/t/cache_innodb-master.opt deleted file mode 100644 index 6672b4ddce1..00000000000 --- a/mysql-test/t/cache_innodb-master.opt +++ /dev/null @@ -1 +0,0 @@ ---query_cache_size=1M diff --git a/mysql-test/t/csv.test b/mysql-test/t/csv.test index 148964d8d96..768a21912a2 100644 --- a/mysql-test/t/csv.test +++ b/mysql-test/t/csv.test @@ -1820,6 +1820,21 @@ INSERT INTO t1 VALUES(-1); SELECT * FROM t1; DROP TABLE t1; +# +# Bug#970528 +# Server crashes in my_strnncollsp_simple on LEFT JOIN with CSV table, +# TEXT field +# + +CREATE TABLE t1 ( b TEXT NOT NULL ) ENGINE=MYISAM; +INSERT INTO t1 VALUES ('x'),('y'); + +CREATE TABLE t2 ( a VARCHAR(1) NOT NULL ) ENGINE=CSV; +INSERT INTO t2 VALUES ('r'),('t'); + +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t1 LEFT JOIN t2 ON ( b = a ); +drop table t1,t2; # # Bug #40814 CSV engine does not parse \X characters when they occur in unquoted fields diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index e93a2ab0fbf..f3557e36a58 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -796,5 +796,14 @@ SET collation_connection=ucs2_general_ci; SET NAMES latin1; --echo # +--echo # Bug #13832953 MY_STRNXFRM_UNICODE: ASSERTION `SRC' FAILED +--echo # +CREATE TABLE t1 (c1 SET('','') CHARACTER SET ucs2); +INSERT INTO t1 VALUES (''); +SELECT COALESCE(c1) FROM t1 ORDER BY 1; +DROP TABLE t1; + + +--echo # --echo # End of 5.5 tests --echo # diff --git a/mysql-test/t/default_storage_engine.test b/mysql-test/t/default_storage_engine.test new file mode 100644 index 00000000000..4ecfc3b8d44 --- /dev/null +++ b/mysql-test/t/default_storage_engine.test @@ -0,0 +1,16 @@ +if (`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'innodb' AND PLUGIN_LIBRARY IS NULL`) +{ + --skip Requires built-in InnoDB. +} + +let $cmd=`select replace("$MYSQLD_BOOTSTRAP_CMD", " --default-storage-engine=myisam", "")`; + +# +# Now it *must* fail, because if InnoDB is compiled in, it is used as a default +# storage engine. but $MYSQLD_BOOTSTRAP_CMD includes --skip-innodb +# +error 1; +exec $cmd; + +echo "all ok"; # to not have zero-length result file + diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test index d1ed2ff5ba6..03d308b6c45 100644 --- a/mysql-test/t/derived_view.test +++ b/mysql-test/t/derived_view.test @@ -1380,6 +1380,43 @@ SET SESSION optimizer_switch= @save_optimizer_switch; DROP VIEW v; DROP TABLE t1,t2; +--echo # +--echo # LP BUG#968720 crash due to converting to materialized and +--echo # natural join made only once +--echo # + +SET @save968720_optimizer_switch=@@optimizer_switch; +SET optimizer_switch = 'derived_merge=on'; + +CREATE TABLE t1 (a int, INDEX(a)); +INSERT INTO t1 VALUES (1); + +CREATE TABLE t2 (a int, INDEX(a)); +INSERT INTO t2 VALUES (1), (2); + +INSERT INTO t1 SELECT a FROM (SELECT a FROM test.t1) AS s1 NATURAL JOIN +t2 AS s2; +SELECT * FROM t1; + +DELETE FROM t1; +INSERT INTO t1 VALUES (1); + +PREPARE stmt FROM " +INSERT INTO t1 SELECT a FROM (SELECT a FROM test.t1) AS s1 NATURAL JOIN +t2 AS s2; +"; +EXECUTE stmt; +SELECT * FROM t1; +EXECUTE stmt; +SELECT * FROM t1; + +drop table t1,t2; +set optimizer_switch=@save968720_optimizer_switch; + +--echo # +--echo # end of 5.3 tests +--echo # + # The following command must be the last one the file set optimizer_switch=@exit_optimizer_switch; set join_cache_level=@exit_join_cache_level; diff --git a/mysql-test/t/error_simulation.test b/mysql-test/t/error_simulation.test index c9f445c0cb0..ea7dd12fb9e 100644 --- a/mysql-test/t/error_simulation.test +++ b/mysql-test/t/error_simulation.test @@ -23,7 +23,7 @@ set tmp_table_size=1024; # Set debug flag so an error is returned when # tmp table in query is converted from heap to myisam -set session debug_dbug="d,raise_error"; +set session debug_dbug="+d,raise_error"; --replace_regex /in table '[^']+'/in table 'tmp_table'/ --error ER_DUP_KEY diff --git a/mysql-test/t/events_restart.test b/mysql-test/t/events_restart.test index facf2912087..83d28c0812d 100644 --- a/mysql-test/t/events_restart.test +++ b/mysql-test/t/events_restart.test @@ -106,3 +106,4 @@ let $wait_condition= select count(*) = 0 from information_schema.processlist where db='events_test' and command = 'Connect' and user=current_user(); --source include/wait_condition.inc + diff --git a/mysql-test/t/filesort_debug.test b/mysql-test/t/filesort_debug.test index 88d957e47c3..f89d46a7bd0 100644 --- a/mysql-test/t/filesort_debug.test +++ b/mysql-test/t/filesort_debug.test @@ -11,7 +11,7 @@ SET @old_debug= @@session.debug; CREATE TABLE t1(f0 int auto_increment primary key, f1 int); INSERT INTO t1(f1) VALUES (0),(1),(2),(3),(4),(5); -SET session debug_dbug= '+d,make_char_array_fail'; +SET session debug_dbug= '+d,make_sort_keys_alloc_fail'; CALL mtr.add_suppression("Out of sort memory"); --error ER_OUT_OF_SORTMEMORY SELECT * FROM t1 ORDER BY f1 ASC, f0; @@ -57,3 +57,46 @@ disconnect con2; --source include/wait_until_count_sessions.inc SET DEBUG_SYNC= "RESET"; DROP TABLE t1; + +--echo # +--echo # Bug#13832772 ASSERTION `THD->IS_ERROR() || KILL_ERRNO' +--echo # FAILED IN FILESORT/MYSQL_DELETE +--echo # + +CREATE TABLE t1 ( + c1 BLOB, + c2 TEXT, + c3 TEXT, + c4 TEXT, + c5 TEXT, + c6 TEXT, + c7 TEXT, + c8 BLOB, + c9 TEXT, + c19 TEXT, + pk INT, + c20 TEXT, + c21 BLOB, + c22 TEXT, + c23 TEXT, + c24 TEXT, + c25 TEXT, + c26 BLOB, + c27 TEXT, + c28 TEXT, + primary key (pk) +); + +CALL mtr.add_suppression("Out of sort memory"); + +--error ER_OUT_OF_SORTMEMORY +DELETE IGNORE FROM t1 ORDER BY c26,c7,c23,c4,c25,c5,c20, +c19,c21,c8,c1,c27,c28,c3,c9,c22,c24,c6,c2,pk LIMIT 2; +SHOW WARNINGS; + +--error ER_OUT_OF_SORTMEMORY +DELETE FROM t1 ORDER BY c26,c7,c23,c4,c25,c5,c20, +c19,c21,c8,c1,c27,c28,c3,c9,c22,c24,c6,c2,pk LIMIT 2; +SHOW WARNINGS; + +DROP TABLE t1; diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index 9e6628a1972..97bd628e2f9 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -562,5 +562,18 @@ SELECT 1 IN (YEAR(FROM_UNIXTIME(NULL)) ,1); --echo # +--echo # +--echo # Bug#13012483: EXPLAIN EXTENDED, PREPARED STATEMENT, CRASH IN CHECK_SIMPLE_EQUALITY +--echo # + +CREATE TABLE t1 (a INT); +PREPARE s FROM "SELECT 1 FROM t1 WHERE 1 < ALL (SELECT @:= (1 IN (SELECT 1 FROM t1)) FROM t1)"; +EXECUTE s; + +DROP TABLE t1; + +--echo # End of test BUG#13012483 + +--echo # --echo End of 5.1 tests diff --git a/mysql-test/t/information_schema_all_engines-master.opt b/mysql-test/t/information_schema_all_engines-master.opt index 9104e73e554..085c81d34bb 100644 --- a/mysql-test/t/information_schema_all_engines-master.opt +++ b/mysql-test/t/information_schema_all_engines-master.opt @@ -1 +1,18 @@ --loose-skip-safemalloc --loose-mutex-deadlock-detector=0 +--loose-innodb-buffer-pool-pages +--loose-innodb-buffer-pool-pages-blob +--loose-innodb-buffer-pool-pages-index +--loose-innodb-cmp +--loose-innodb-cmpmem-reset +--loose-innodb-cmp-reset +--loose-innodb-index-stats +--loose-innodb-lock-waits +--loose-innodb-rseg +--loose-innodb-sys-columns +--loose-innodb-sys-fields +--loose-innodb-sys-foreign +--loose-innodb-sys-foreign-cols +--loose-innodb-sys-stats +--loose-innodb-sys-tables +--loose-innodb-sys-tablestats +--loose-innodb-table-stats diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 51bb72e1239..907d39e95fe 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -1067,4 +1067,72 @@ insert into t2 values ('1:1:1'); select t2.i from t1 left join t2 on t2.i = t1.i where t1.i = '1:1:1'; drop table t1,t2; +--echo # +--echo # BUG#954900: unexpected empty set due to an invalid build of key ref +--echo # + +CREATE TABLE t1 (dog_id int(10), birthday date, PRIMARY KEY (dog_id,birthday)); +INSERT INTO t1 VALUES (5918,'2004-07-22'); + +CREATE TABLE t2 (dog_id int(10) unsigned, t_id char(1), birthday date, a_id int(10), +PRIMARY KEY (dog_id,t_id,birthday,a_id)); +INSERT INTO t2 VALUES +(5918,'N','2004-07-22',5216551), (5918,'N','2004-07-22',5223640), +(5918,'N','2004-07-22',5389491), (5918,'N','2004-07-22',5749434), +(5918,'N','2004-07-22',5992424), (5922,'N','2005-06-30',5076957), +(5924,'N','2000-08-11',20264), (5924,'N','2000-08-11',64251), +(5924,'N','2000-08-11',74748), (5924,'N','2000-08-11',87590), +(5924,'N','2000-08-11',104695), (5924,'N','2000-08-11',133136), +(5924,'N','2000-08-11',5027806), (5924,'N','2000-08-11',5076957), +(5924,'N','2000-08-11',5166821), (5924,'N','2000-08-11',5181896), +(5924,'N','2000-08-11',5217908), (5924,'N','2000-08-11',5220812), +(5924,'N','2000-08-11',5226473), (5924,'N','2000-08-11',5339111), +(5925,'N','2005-02-10',19227), (5925,'N','2005-02-10',74529), +(5925,'N','2005-02-10',74748), (5927,'N','2005-08-18',20264), +(5927,'N','2005-08-18',58364), (5929,'N','2005-01-19',58364), +(5935,'N','2006-03-10',19227), (5935,'N','2006-03-10',64251), +(5935,'N','2006-03-10',5222400), (5935,'N','2006-03-10',5226473), +(5936,'N','2004-10-29',5015032), (5937,'N','2002-04-05',11237), +(5937,'N','2002-04-05',23911), (5937,'N','2002-04-05',112133), +(5937,'N','2002-04-05',169721), (5937,'N','2002-04-05',170650), +(5937,'N','2002-04-05',5014494), (5937,'N','2002-04-05',5166009), +(5937,'N','2002-04-05',5181871), (5937,'N','2002-04-05',5213380), +(5937,'N','2002-04-05',5214875), (5937,'N','2002-04-05',5895062), +(5938,'N','2006-03-24',11237), (5938,'N','2006-03-24',19227), +(5938,'N','2006-03-24',23911), (5938,'N','2006-03-24',58364), +(5938,'N','2006-03-24',64251), (5938,'N','2006-03-24',111716), +(5938,'N','2006-03-24',112702), (5938,'N','2006-03-24',133136), +(5938,'N','2006-03-24',168718), (5938,'N','2006-03-24',5137136), +(5938,'N','2006-03-24',5161519), (5938,'N','2006-03-24',5168120), +(5938,'N','2006-03-24',5219034), (6234,'N','2006-06-02',103058), +(6234,'N','2006-06-02',5146844), (6235,'N','2006-06-01',12900), +(6235,'N','2006-06-01',20264), (6235,'N','2006-06-01',64251), +(6235,'N','2006-06-01',75160), (6235,'N','2006-06-01',5014494), +(6235,'N','2006-06-01',5181638), (6236,'N','2006-06-06',112595), +(6236,'N','2006-06-06',5219601), (6236,'N','2006-06-06',5808374); + +CREATE TABLE t3 (dog_id int(10) unsigned); +INSERT INTO t3 VALUES (5918); + +CREATE TABLE t4 (dog_id int(10), t_id char(1), birthday date, KEY (t_id)); +INSERT INTO t4 VALUES (5918,'N','2004-07-22'), (5919,'N','2004-07-20'); + +CREATE TABLE t5 (dog_id int(10) unsigned, UNIQUE KEY (dog_id)); +INSERT INTO t5 VALUES (5918); + +SET @tmp_optimizer_switch=@@optimizer_switch; +SET optimizer_switch='index_condition_pushdown=off'; + +EXPLAIN +SELECT * FROM t5 DU, t1 D, t4 DT, t2 DSA, t3 DSAR +WHERE DU.dog_id=D.dog_id AND D.dog_id=DT.dog_id AND D.birthday=DT.birthday AND + DT.t_id=DSA.t_id AND DT.birthday=DSA.birthday AND DSA.dog_id=DSAR.dog_id; +SELECT * FROM t5 DU, t1 D, t4 DT, t2 DSA, t3 DSAR +WHERE DU.dog_id=D.dog_id AND D.dog_id=DT.dog_id AND D.birthday=DT.birthday AND + DT.t_id=DSA.t_id AND DT.birthday=DSA.birthday AND DSA.dog_id=DSAR.dog_id; + +SET optimizer_switch=@tmp_optimizer_switch; + +DROP TABLE t1,t2,t3,t4,t5; + SET optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index d5c6d995b4c..a4469728c0f 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -1260,6 +1260,62 @@ WHERE TABLE1.pk IS NULL; DROP TABLE h,m,k; +--echo +--echo # BUG#12567331 - INFINITE LOOP WHEN RESOLVING AN ALIASED COLUMN +--echo # USED IN GROUP BY +--echo +CREATE TABLE t1 ( + col_varchar_1024_latin1_key varchar(1024), + col_varchar_10_latin1 varchar(10), + col_int int(11), + pk int(11) +); +CREATE TABLE t2 ( + col_int_key int(11), + col_int int(11), + pk int(11) +); + +PREPARE prep_stmt_9846 FROM ' +SELECT alias1.pk AS field1 FROM +t1 AS alias1 +LEFT JOIN +( + t2 AS alias2 + RIGHT JOIN + ( + t2 AS alias3 + JOIN t1 AS alias4 + ON 1 + ) + ON 1 +) +ON 1 +GROUP BY field1'; +execute prep_stmt_9846; +execute prep_stmt_9846; +drop table t1,t2; + +--echo # +--echo # Bug #11765810 58813: SERVER THREAD HANGS WHEN JOIN + WHERE + GROUP BY +--echo # IS EXECUTED TWICE FROM P +--echo # +CREATE TABLE t1 ( a INT ) ENGINE = MYISAM; +INSERT INTO t1 VALUES (1); +PREPARE prep_stmt FROM ' + SELECT 1 AS f FROM t1 + LEFT JOIN t1 t2 + RIGHT JOIN t1 t3 + JOIN t1 t4 + ON 1 + ON 1 + ON 1 + GROUP BY f'; +EXECUTE prep_stmt; +EXECUTE prep_stmt; + +DROP TABLE t1; + --echo # --echo # Bug#49600: outer join of two single-row tables with joining attributes --echo # evaluated to nulls diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index 51bb64bd31d..48735304aad 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -6,6 +6,8 @@ source include/not_embedded.inc; source include/have_log_bin.inc; +CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT."); + --disable_warnings drop table if exists t1,t2,t3; drop database if exists mysqltest; @@ -142,6 +144,7 @@ INSERT INTO t2(ParId) VALUES(1), (2), (3); select * from t2; +--disable_warnings ONCE UPDATE t2, t1 SET t2.tst = t1.tst, t2.tst1 = t1.tst1 WHERE t2.ParId = t1.Id; select * from t2; @@ -299,6 +302,7 @@ drop table t1,t2; create table t1 (a int not null auto_increment primary key, b int not null); insert into t1 (b) values (1),(2),(3),(4); +--disable_warnings ONCE update t1, t1 as t2 set t1.b=t2.b+1 where t1.a=t2.a; select * from t1; drop table t1; @@ -356,6 +360,7 @@ create table `t2` (`c2_id` int(10) unsigned NULL auto_increment, `c2_p_id` int(1 insert into t1 values (0,'A01-Comp',1); insert into t1 values (0,'B01-Comp',1); insert into t2 values (0,1,'A Note',1); +--disable_warnings ONCE update t1 left join t2 on p_id = c2_p_id set c2_note = 'asdf-1' where p_id = 2; select * from t1; select * from t2; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 9bdd6faa422..4199d98073c 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1718,6 +1718,20 @@ CHECK TABLE t1; DROP TABLE t1; SET GLOBAL myisam_use_mmap=default; +--echo # +--echo # BUG 11756869 - 48848: MYISAMCHK DOING SORT RECOVER IN CERTAIN +--echo # CASES RESETS DATA POINTER TO SMAL +--echo # +CREATE TABLE t1(a INT, KEY(a)); +ALTER TABLE t1 DISABLE KEYS; +let $MYSQLD_DATADIR= `select @@datadir`; +SET @before:= (SELECT MAX_DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test'); +FLUSH TABLES; +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--exec $MYISAMCHK -sn $MYSQLD_DATADIR/test/t1 +SET @after:= (SELECT MAX_DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test'); +SELECT @before=@after; +DROP TABLE t1; --echo End of 5.1 tests --echo # diff --git a/mysql-test/t/mysqldump-no-binlog.test b/mysql-test/t/mysqldump-no-binlog.test index 434b2931792..5f934bc440f 100644 --- a/mysql-test/t/mysqldump-no-binlog.test +++ b/mysql-test/t/mysqldump-no-binlog.test @@ -2,5 +2,6 @@ --source include/not_embedded.inc --replace_regex /MASTER_LOG_POS=[0-9]+/XX/ +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --compact --master-data=2 test 2>&1 diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 1d18ef06db4..920dbe76d1b 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -601,48 +601,62 @@ create table t3(a varchar(30) primary key, b int not null); --disable_query_log select '------ Testing with illegal table names ------' as test_sequence ; --enable_query_log +--replace_result mysqldump.exe mysqldump --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\d-2-1.sql" 2>&1 +--replace_result mysqldump.exe mysqldump --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\t1" 2>&1 +--replace_result mysqldump.exe mysqldump --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\t1" 2>&1 +--replace_result mysqldump.exe mysqldump --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\\\t1" 2>&1 +--replace_result mysqldump.exe mysqldump --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\1" 2>&1 +--replace_result mysqldump.exe mysqldump --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t\\1" 2>&1 +--replace_result mysqldump.exe mysqldump --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "t/1" 2>&1 +--replace_result mysqldump.exe mysqldump --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "T_1" 2>&1 +--replace_result mysqldump.exe mysqldump --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "T%1" 2>&1 +--replace_result mysqldump.exe mysqldump --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "T'1" 2>&1 +--replace_result mysqldump.exe mysqldump --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "T_1" 2>&1 +--replace_result mysqldump.exe mysqldump --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "T_" 2>&1 --disable_query_log select '------ Testing with illegal database names ------' as test_sequence ; --enable_query_log +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_d 2>&1 +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --compact --skip-comments "mysqld\ump_test_db" 2>&1 @@ -728,6 +742,7 @@ drop table `t1`; create table t1(a int); create table t2(a int); create table t3(a int); +--replace_result mysqldump.exe mysqldump --error 6 --exec $MYSQL_DUMP --skip-comments --force --no-data test t3 t1 non_existing t2 drop table t1, t2, t3; @@ -738,6 +753,7 @@ drop table t1, t2, t3; --echo # create table t1 (a int); +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --skip-comments --force test t1 --where="xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 2>&1 drop table t1; @@ -1279,6 +1295,7 @@ create view v1 as select * from t1; drop table t1; # mysqldump gets 1356 from server, but gives us 2 --echo mysqldump { +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --force -N --compact --skip-comments test --echo } mysqldump @@ -1376,11 +1393,13 @@ create table t1(a int, b varchar(34)); reset master; # Execute mysqldump, will fail on FLUSH TABLES +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --compact --master-data -u mysqltest_1 test 2>&1 # Execute mysqldump, will fail on FLUSH TABLES # use --force, should no affect behaviour +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --compact --force --master-data -u mysqltest_1 test 2>&1 @@ -1388,11 +1407,13 @@ reset master; grant RELOAD on *.* to mysqltest_1@localhost; # Execute mysqldump, will fail on SHOW MASTER STATUS +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --compact --master-data -u mysqltest_1 test 2>&1 # Execute mysqldump, will fail on SHOW MASTER STATUS. # use --force, should not alter behaviour +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --compact --force --master-data -u mysqltest_1 test 2>&1 @@ -1507,14 +1528,18 @@ CREATE TABLE t1(a int); INSERT INTO t1 VALUES (1), (2); # too long a file path causes an error +--replace_result mysqldump.exe mysqldump --error 1 --exec $MYSQL_DUMP --tab=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa test 2>&1 --exec $MYSQL_DUMP --tab=$MYSQLTEST_VARDIR/tmp/ --fields-terminated-by=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa test +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --tab=$MYSQLTEST_VARDIR/tmp/ --fields-enclosed-by=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa test +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --tab=$MYSQLTEST_VARDIR/tmp/ --fields-optionally-enclosed-by=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa test +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --tab=$MYSQLTEST_VARDIR/tmp/ --fields-escaped-by=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa test --exec $MYSQL_DUMP --tab=$MYSQLTEST_VARDIR/tmp/ --lines-terminated-by=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa test @@ -1588,6 +1613,7 @@ connection user27293; create procedure mysqldump_test_db.sp1() select 'hello'; +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP -f --compact --user=user2 --password= -h 127.0.0.1 -P $MASTER_MYPORT --routines mysqldump_test_db @@ -1693,6 +1719,7 @@ DROP TABLE `straße`; CREATE TABLE `כדשגכחךלדגכחשךדגחכךלדגכ` ( f1 INT ); --exec $MYSQL_DUMP --character-sets-dir=$MYSQL_SHAREDIR/charsets --skip-comments --default-character-set=utf8 --compatible=mysql323 test +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --character-sets-dir=$MYSQL_SHAREDIR/charsets --skip-comments --default-character-set=latin1 --compatible=mysql323 test DROP TABLE `כדשגכחךלדגכחשךדגחכךלדגכ`; @@ -1748,6 +1775,7 @@ select * from words2; # Drop table "words" and run with threads, should fail drop table words; --replace_regex /.*mysqlimport(\.exe)*/mysqlimport/ +--replace_result mysqldump.exe mysqldump --error 1 --exec $MYSQL_IMPORT --silent --use-threads=2 test $MYSQLTEST_VARDIR/tmp/t1.txt $MYSQLTEST_VARDIR/tmp/t2.txt $MYSQLTEST_VARDIR/std_data/words.dat $MYSQLTEST_VARDIR/std_data/words2.dat 2>&1 @@ -2086,10 +2114,12 @@ INSERT INTO t1 VALUES (1, 'ABC-ÐБВ', 'DEF-ÂÃÄ'), (2, NULL, NULL); --echo # error on multi-character ENCLOSED/ESCAPED BY +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --tab=$MYSQLTEST_VARDIR/tmp/ --fields-enclosed-by='12345' test t1 --remove_file $file +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --tab=$MYSQLTEST_VARDIR/tmp/ --fields-escaped-by='12345' test t1 --remove_file $file @@ -2302,6 +2332,7 @@ connection conn_1; --echo # Running 'replace_regex on timestamp' --replace_regex /[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/--TIME--/ +--replace_result mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --user=user1 -R -E --triggers -X BUG52792 diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test index 8b2d4455435..f9abb75b7e9 100644 --- a/mysql-test/t/openssl_1.test +++ b/mysql-test/t/openssl_1.test @@ -197,7 +197,7 @@ INSERT INTO t1 VALUES (1), (2); --exec $MYSQL_DUMP --skip-create --skip-comments --ssl --ssl-ca=$MYSQL_TEST_DIR/std_data/cacert.pem --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test # With wrong parameters ---replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR mysqldump.exe mysqldump --error 2 --exec $MYSQL_DUMP --skip-create --skip-comments --ssl --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test 2>&1 diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 3224f4d4081..d6d49c59255 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -2350,6 +2350,51 @@ INSERT INTO t1 VALUES(0); DROP TABLE t1; SET GLOBAL myisam_use_mmap=default; +--echo # +--echo # Bug#13580775 ASSERTION FAILED: RECORD_LENGTH == M_RECORD_LENGTH, +--echo # FILE FILESORT_UTILS.CC +--echo # + +CREATE TABLE t1 ( + a INT PRIMARY KEY, + b INT, + c CHAR(1), + d INT, + KEY (c,d) +) PARTITION BY KEY () PARTITIONS 1; + +INSERT INTO t1 VALUES (1,1,'a',1), (2,2,'a',1); + +SELECT 1 FROM t1 WHERE 1 IN +(SELECT group_concat(b) + FROM t1 + WHERE c > geomfromtext('point(1 1)') + GROUP BY b +); + +DROP TABLE t1; + +--echo # +--echo # Bug#13011410 CRASH IN FILESORT CODE WITH GROUP BY/ROLLUP +--echo # + +CREATE TABLE t1 ( + a INT, + b MEDIUMINT, + c VARCHAR(300) CHARACTER SET hp8 COLLATE hp8_bin, + PRIMARY KEY (a,c(299))) +ENGINE=myisam +PARTITION BY LINEAR KEY () PARTITIONS 2; + +INSERT INTO t1 VALUES (1,2,'test'), (2,3,'hi'), (4,5,'bye'); +SELECT 1 FROM t1 WHERE b < SOME +( SELECT 1 FROM t1 WHERE a >= 1 + GROUP BY b WITH ROLLUP + HAVING b > geomfromtext("") +); + +DROP TABLE t1; + --echo End of 5.1 tests --echo # diff --git a/mysql-test/t/partition_cache.test b/mysql-test/t/partition_cache.test new file mode 100644 index 00000000000..b5d19796b7c --- /dev/null +++ b/mysql-test/t/partition_cache.test @@ -0,0 +1,21 @@ +# t/cache_innodb.test +# +# Last update: +# 2006-07-26 ML test refactored (MySQL 5.1) +# main code t/innodb_cache.test --> include/query_cache.inc +# new wrapper t/cache_innodb.test +# + +--source include/have_query_cache.inc + +--source include/have_innodb.inc +--source include/have_partition.inc +let $engine_type= InnoDB; +# Using SELECT to get a space as first character. +let $partitions_a= `SELECT ' PARTITION BY KEY (a) PARTITIONS 3'`; +let $partitions_id= `SELECT ' PARTITION BY HASH (id) PARTITIONS 3'`; +let $partitions_s1= `SELECT ' PARTITION BY KEY (s1) PARTITIONS 3'`; +# partitioning does not support FOREIGN KEYs +let $test_foreign_keys= 0; + +--source include/query_cache.inc diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index 39dd6773ce8..f8f09e4b5e7 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -11,6 +11,34 @@ drop table if exists t1, t2; let $MYSQLD_DATADIR= `SELECT @@datadir`; --echo # +--echo # Bug#13608188 - 64038: CRASH IN HANDLER::HA_THD ON ALTER TABLE AFTER +--echo # REPAIR NON-EXISTING PARTITION +--echo # +CREATE TABLE t1 ( a INT, b INT ); +INSERT INTO t1 VALUES (5,3),(5,6); +ALTER TABLE t1 PARTITION BY KEY(b) PARTITIONS 3 ; +ALTER TABLE t1 REPAIR PARTITION p1, p3; +ALTER TABLE t1 ORDER BY b; +DROP TABLE t1; + +--echo # +--echo # Bug#13593865 - 64037: CRASH IN HA_PARTITION::CREATE_HANDLERS ON +--echo # ALTER TABLE AFTER DROP PARTITION +--echo # + +CREATE TABLE t1 (a INT) +PARTITION BY RANGE (a) +(PARTITION p0 VALUES LESS THAN (0), + PARTITION p1 VALUES LESS THAN MAXVALUE ) ; + +ALTER TABLE t1 DROP PARTITION p1; +ALTER TABLE t1 ANALYZE PARTITION p0, p1; + +ALTER TABLE t1 COMMENT 'altered'; + +DROP TABLE t1; + +--echo # --echo # Bug#57924: crash when creating partitioned table with --echo # multiple columns in the partition key --echo # diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test index 28a9c6e2e64..2756f7d1ebb 100644 --- a/mysql-test/t/partition_innodb.test +++ b/mysql-test/t/partition_innodb.test @@ -12,6 +12,35 @@ drop table if exists t1, t2; let $MYSQLD_DATADIR= `SELECT @@datadir`; --echo # +--echo # Bug#13694811: THE OPTIMIZER WRONGLY USES THE FIRST +--echo # INNODB PARTITION STATISTICS +--echo # + +CREATE TABLE t1 +(a INT, + b varchar(64), + PRIMARY KEY (a), + KEY (b)) +ENGINE = InnoDB +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (a) SUBPARTITIONS 10 +(PARTITION pNeg VALUES LESS THAN (0), + PARTITION p0 VALUES LESS THAN (1000), + PARTITION pMAX VALUES LESS THAN MAXVALUE); + +--echo # Only one row in the first 10 subpartitions +INSERT INTO t1 VALUES (-1, 'Only negative pk value'); + +INSERT INTO t1 VALUES (0, 'Mod Zero'), (1, 'One'), (2, 'Two'), (3, 'Three'), +(10, 'Zero'), (11, 'Mod One'), (12, 'Mod Two'), (13, 'Mod Three'), +(20, '0'), (21, '1'), (22, '2'), (23, '3'), +(4, '4'), (5, '5'), (6, '6'), (7, '7'), (8, '8'), (9, '9'); +INSERT INTO t1 SELECT a + 30, b FROM t1 WHERE a >= 0; +ANALYZE TABLE t1; +EXPLAIN SELECT b FROM t1 WHERE b between 'L' and 'N' AND a > -100; +DROP TABLE t1; + +--echo # --echo # Bug#56287: crash when using Partition datetime in sub in query --echo # diff --git a/mysql-test/t/plugin_loaderr.opt b/mysql-test/t/plugin_loaderr.opt new file mode 100644 index 00000000000..38cb906723d --- /dev/null +++ b/mysql-test/t/plugin_loaderr.opt @@ -0,0 +1 @@ +--innodb --innodb-page-size=6000 diff --git a/mysql-test/t/plugin_loaderr.test b/mysql-test/t/plugin_loaderr.test new file mode 100644 index 00000000000..e319e2fb54d --- /dev/null +++ b/mysql-test/t/plugin_loaderr.test @@ -0,0 +1,10 @@ + +# We used an invalid command-line option and InnoDB failed to start. +# Ignore all related warnings +call mtr.add_suppression("InnoDB"); + +--vertical_results +SELECT +PLUGIN_NAME,PLUGIN_STATUS,PLUGIN_TYPE,PLUGIN_LIBRARY,PLUGIN_LIBRARY_VERSION,LOAD_OPTION +FROM INFORMATION_SCHEMA.PLUGINS WHERE plugin_name = 'innodb'; + diff --git a/mysql-test/t/progress_976225.test b/mysql-test/t/progress_976225.test new file mode 100644 index 00000000000..32ded8b0ee0 --- /dev/null +++ b/mysql-test/t/progress_976225.test @@ -0,0 +1,8 @@ +--source include/have_xtradb.inc + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (b INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2); +INSERT INTO t2 VALUES (3),(4); +OPTIMIZE TABLE t1, t2; +drop table t1, t2; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 58e85c7a3a1..b2f64b8172b 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1,5 +1,6 @@ -- source include/not_embedded.inc -- source include/have_log_bin.inc +call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.'); # # SQL Syntax for Prepared Statements test # @@ -249,8 +250,10 @@ prepare stmt1 from "select 1 into @var"; execute stmt1; execute stmt1; prepare stmt1 from "create table t1 select 1 as i"; +--disable_warnings ONCE execute stmt1; drop table t1; +--disable_warnings ONCE execute stmt1; prepare stmt1 from "insert into t1 select i from t1"; execute stmt1; @@ -443,6 +446,7 @@ deallocate prepare stmt; create table t1 (a int); insert into t1 values (1),(2),(3); create table t2 select * from t1; +--disable_warnings prepare stmt FROM 'create table t2 select * from t1'; drop table t2; execute stmt; @@ -452,6 +456,7 @@ execute stmt; execute stmt; drop table t2; execute stmt; +--enable_warnings drop table t1,t2; deallocate prepare stmt; @@ -1187,6 +1192,7 @@ create database mysqltest character set utf8; prepare stmt1 from "create table mysqltest.t1 (c char(10))"; prepare stmt2 from "create table mysqltest.t2 select 'test'"; execute stmt1; +--disable_warnings ONCE execute stmt2; show create table mysqltest.t1; show create table mysqltest.t2; @@ -1194,6 +1200,7 @@ drop table mysqltest.t1; drop table mysqltest.t2; alter database mysqltest character set latin1; execute stmt1; +--disable_warnings ONCE execute stmt2; show create table mysqltest.t1; show create table mysqltest.t2; @@ -3370,6 +3377,94 @@ disconnect con1; SELECT * FROM (SELECT 1 UNION SELECT 2) t; +--echo +--echo # Bug#13805127: Stored program cache produces wrong result in same THD +--echo + +PREPARE s1 FROM +" +SELECT c1, t2.c2, count(c3) +FROM + ( + SELECT 3 as c2 FROM dual WHERE @x = 1 + UNION + SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 + ) AS t1, + ( + SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual + UNION + SELECT '2012-03-01 02:00:00', 3, 2 FROM dual + UNION + SELECT '2012-03-01 01:00:00', 2, 1 FROM dual + ) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2 +"; + +--echo +SET @x = 1; +SELECT c1, t2.c2, count(c3) +FROM + ( + SELECT 3 as c2 FROM dual WHERE @x = 1 + UNION + SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 + ) AS t1, + ( + SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual + UNION + SELECT '2012-03-01 02:00:00', 3, 2 FROM dual + UNION + SELECT '2012-03-01 01:00:00', 2, 1 FROM dual + ) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2; +--echo +EXECUTE s1; + +--echo +SET @x = 2; +SELECT c1, t2.c2, count(c3) +FROM + ( + SELECT 3 as c2 FROM dual WHERE @x = 1 + UNION + SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 + ) AS t1, + ( + SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual + UNION + SELECT '2012-03-01 02:00:00', 3, 2 FROM dual + UNION + SELECT '2012-03-01 01:00:00', 2, 1 FROM dual + ) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2; +--echo +EXECUTE s1; + +--echo +SET @x = 1; +SELECT c1, t2.c2, count(c3) +FROM + ( + SELECT 3 as c2 FROM dual WHERE @x = 1 + UNION + SELECT 2 FROM dual WHERE @x = 1 OR @x = 2 + ) AS t1, + ( + SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual + UNION + SELECT '2012-03-01 02:00:00', 3, 2 FROM dual + UNION + SELECT '2012-03-01 01:00:00', 2, 1 FROM dual + ) AS t2 +WHERE t2.c2 = t1.c2 +GROUP BY c1, c2; +--echo +EXECUTE s1; + +DEALLOCATE PREPARE s1; --echo # --echo # End of 5.5 tests. diff --git a/mysql-test/t/range_vs_index_merge.test b/mysql-test/t/range_vs_index_merge.test index de7e6a0838c..613a7cf5760 100755 --- a/mysql-test/t/range_vs_index_merge.test +++ b/mysql-test/t/range_vs_index_merge.test @@ -621,6 +621,62 @@ SELECT * FROM City (Population BETWEEN 101000 AND 102000 OR Name LIKE 'Pa%'); +# +# LP bug #954262: index merge oover long disjunction in WHERE +# + +set @save_optimizer_switch=@@optimizer_switch; + +CREATE INDEX CityName on City(Name); + +let $cond = +(Name='Manila' AND Country='PHL') OR +(Name='Addis Abeba' AND Country='ETH') OR +(Name='Jakarta' AND Country='IDN') OR +(Name='Bangalore' AND Country='IND') OR +(Name='Teheran' AND Country='IRN') OR +(Name='Roma' AND Country='ITA') OR +(Name='Delhi' AND Country='IND') OR +(Name='Venezia' AND Country='ITA') OR +(Name='Tokyo' AND Country='JPN') OR +(Name='Toronto' AND Country='CAN') OR +(Name='Peking' AND Country='CHN') OR +(Name='Lagos' AND Country='NGA') OR +(Name='Tijuana' AND Country='MEX') OR +(Name='Rabat' AND Country='MAR') OR +(Name='Seoul' AND Country='KOR') OR +(Name='Vancouver' AND Country='CAN') OR +(Name='Kaunas' AND Country='LTU') OR +(Name='Paris' AND Country='FRA') OR +(Name='Dakar' AND Country='SEN') OR +(Name='Basel' AND Country='CHE') OR +(Name='Praha' AND Country='CZE') OR +(Name='Ankara' AND Country='TUR') OR +(Name='Dresden' AND Country='DEU') OR +(Name='Lugansk' AND Country='UKR') OR +(Name='Caracas' AND Country='VEN') OR +(Name='Samara' AND Country='RUS') OR +(Name='Seattle' AND Country='USA'); + +eval +EXPLAIN SELECT Name, Country, Population FROM City WHERE +$cond; +eval +SELECT Name, Country, Population FROM City WHERE +$cond; + +set optimizer_switch='index_merge=off'; + +eval +EXPLAIN SELECT Name, Country, Population FROM City WHERE +$cond; +eval +SELECT Name, Country, Population FROM City WHERE +$cond; + +set optimizer_switch=@save_optimizer_switch; + + DROP DATABASE world; use test; diff --git a/mysql-test/t/sp-bugs.test b/mysql-test/t/sp-bugs.test index fe52632c784..3ab1689e8b2 100644 --- a/mysql-test/t/sp-bugs.test +++ b/mysql-test/t/sp-bugs.test @@ -138,4 +138,93 @@ DROP FUNCTION db1.f1; DROP TABLE db1.t1; DROP DATABASE db1; DROP DATABASE db2; +USE test; + +--echo # +--echo # Bug#13105873:valgrind warning:possible crash in foreign +--echo # key handling on subsequent create table if not exists +--echo # + +--disable_warnings +DROP DATABASE IF EXISTS testdb; +--enable_warnings +CREATE DATABASE testdb; +USE testdb; +CREATE TABLE t1 (id1 INT PRIMARY KEY); +DELIMITER $; +CREATE PROCEDURE `p1`() +BEGIN + CREATE TABLE IF NOT EXISTS t2(id INT PRIMARY KEY, + CONSTRAINT FK FOREIGN KEY (id) REFERENCES t1( id1 )); +END$ +DELIMITER ;$ +CALL p1(); +--echo # below stmt should not return valgrind warnings +CALL p1(); +DROP DATABASE testdb; +USE test; + --echo End of 5.1 tests + +--echo # +--echo # Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE +--echo # +SET @@SQL_MODE = ''; +DELIMITER $; +CREATE FUNCTION testf_bug11763507() RETURNS INT +BEGIN + RETURN 0; +END +$ + +CREATE PROCEDURE testp_bug11763507() +BEGIN + SELECT "PROCEDURE testp_bug11763507"; +END +$ + +DELIMITER ;$ + +# STORED FUNCTIONS +SELECT testf_bug11763507(); +SELECT TESTF_bug11763507(); + +--replace_column 5 # 6 # +SHOW FUNCTION STATUS LIKE 'testf_bug11763507'; +--replace_column 5 # 6 # +SHOW FUNCTION STATUS WHERE NAME='testf_bug11763507'; +--replace_column 5 # 6 # +SHOW FUNCTION STATUS LIKE 'TESTF_bug11763507'; +--replace_column 5 # 6 # +SHOW FUNCTION STATUS WHERE NAME='TESTF_bug11763507'; + +SHOW CREATE FUNCTION testf_bug11763507; +SHOW CREATE FUNCTION TESTF_bug11763507; + +# STORED PROCEDURE +CALL testp_bug11763507(); +CALL TESTP_bug11763507(); + +--replace_column 5 # 6 # +SHOW PROCEDURE STATUS LIKE 'testp_bug11763507'; +--replace_column 5 # 6 # +SHOW PROCEDURE STATUS WHERE NAME='testp_bug11763507'; +--replace_column 5 # 6 # +SHOW PROCEDURE STATUS LIKE 'TESTP_bug11763507'; +--replace_column 5 # 6 # +SHOW PROCEDURE STATUS WHERE NAME='TESTP_bug11763507'; + +SHOW CREATE PROCEDURE testp_bug11763507; +SHOW CREATE PROCEDURE TESTP_bug11763507; + +# INFORMATION SCHEMA +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name LIKE 'testf_bug11763507'; +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name LIKE 'TESTF_bug11763507'; + +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name='testf_bug11763507'; +SELECT specific_name FROM INFORMATION_SCHEMA.ROUTINES WHERE specific_name='TESTF_bug11763507'; + +DROP PROCEDURE testp_bug11763507; +DROP FUNCTION testf_bug11763507; + +--echo #END OF BUG#11763507 test. diff --git a/mysql-test/t/sp-code.test b/mysql-test/t/sp-code.test index 4c1b287769d..d4b63a73920 100644 --- a/mysql-test/t/sp-code.test +++ b/mysql-test/t/sp-code.test @@ -702,3 +702,35 @@ SET SESSION debug_dbug="-d,bug23032_emit_warning"; DROP PROCEDURE p1; DROP TABLE t1; + +--echo # +--echo # Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE +--echo # +SET @@SQL_MODE = ''; +DELIMITER $; +CREATE FUNCTION testf_bug11763507() RETURNS INT +BEGIN + RETURN 0; +END +$ + +CREATE PROCEDURE testp_bug11763507() +BEGIN + SELECT "PROCEDURE testp_bug11763507"; +END +$ + +DELIMITER ;$ + +# STORED FUNCTIONS +SHOW FUNCTION CODE testf_bug11763507; +SHOW FUNCTION CODE TESTF_bug11763507; + +# STORED PROCEDURE +SHOW PROCEDURE CODE testp_bug11763507; +SHOW PROCEDURE CODE TESTP_bug11763507; + +DROP PROCEDURE testp_bug11763507; +DROP FUNCTION testf_bug11763507; + +--echo #END OF BUG#11763507 test. diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index cafa7f0a551..ef99a8a521a 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -9039,4 +9039,69 @@ DROP PROCEDURE p1; DROP PROCEDURE p2; DROP TABLE t1; +--echo +--echo # Bug#13805127: Stored program cache produces wrong result in same THD +--echo + +delimiter |; + +CREATE PROCEDURE p1(x INT UNSIGNED) +BEGIN + SELECT c1, t2.c2, count(c3) + FROM + ( + SELECT 3 as c2 FROM dual WHERE x = 1 + UNION + SELECT 2 FROM dual WHERE x = 1 OR x = 2 + ) AS t1, + ( + SELECT '2012-03-01 01:00:00' AS c1, 3 as c2, 1 as c3 FROM dual + UNION + SELECT '2012-03-01 02:00:00', 3, 2 FROM dual + UNION + SELECT '2012-03-01 01:00:00', 2, 1 FROM dual + ) AS t2 + WHERE t2.c2 = t1.c2 + GROUP BY c1, c2 + ; +END| + +delimiter ;| + +--echo +CALL p1(1); +CALL p1(2); +CALL p1(1); + +DROP PROCEDURE p1; + --echo # End of 5.5 test + + +--echo # +--echo # Bug#12663165 SP DEAD CODE REMOVAL DOESN'T UNDERSTAND CONTINUE HANDLERS +--echo # + +--disable_warnings +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +delimiter $; +CREATE FUNCTION f1() RETURNS INT +BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; + BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION RETURN f1(); + BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION RETURN f1(); + RETURN f1(); + END; + END; +RETURN 1; +END $ +delimiter ;$ + +# This used to cause an assertion. +SELECT f1(); + +DROP FUNCTION f1; diff --git a/mysql-test/t/sp_notembedded.test b/mysql-test/t/sp_notembedded.test index 87de5063d00..39e7102079c 100644 --- a/mysql-test/t/sp_notembedded.test +++ b/mysql-test/t/sp_notembedded.test @@ -427,6 +427,7 @@ SELECT `my.db`.f1(2); connection default; disconnect addcon; DROP DATABASE `my.db`; +USE test; # # Restore global concurrent_insert value. Keep in the end of the test file. @@ -437,3 +438,26 @@ set @@global.concurrent_insert= @old_concurrent_insert; # Wait till all disconnects are completed --source include/wait_until_count_sessions.inc +--echo # +--echo # Bug#11763507 - 56224: FUNCTION NAME IS CASE-SENSITIVE +--echo # +SET @@SQL_MODE = ''; +DELIMITER $; + +CREATE EVENT teste_bug11763507 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO SELECT 1 $ + +DELIMITER ;$ +# EVENTS +--replace_column 6 # 7 # 8 # 9 # +SHOW EVENTS LIKE 'teste_bug11763507'; +--replace_column 6 # 7 # 8 # 9 # +SHOW EVENTS LIKE 'TESTE_bug11763507'; + +--replace_column 4 # +SHOW CREATE EVENT teste_bug11763507; +--replace_column 4 # +SHOW CREATE EVENT TESTE_bug11763507; + +DROP EVENT teste_bug11763507; +--echo #END OF BUG#11763507 test. diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test index 27956bc8877..b46da77554a 100644 --- a/mysql-test/t/sql_mode.test +++ b/mysql-test/t/sql_mode.test @@ -359,3 +359,157 @@ SELECT * FROM mysql.columns_priv WHERE Host = 'localhost' AND User LIKE 'user_%P # Cleanup DROP TABLE t1; DROP TABLE t2; + + +--echo +--echo # +--echo # Test for Bug#12601974 - STORED PROCEDURE SQL_MODE=NO_BACKSLASH_ESCAPES +--echo # IGNORED AND BREAKS REPLICATION +--echo # + +--disable_warnings +DROP TABLE IF EXISTS test_table; +DROP FUNCTION IF EXISTS test_function; +--enable_warnings + +CREATE TABLE test_table (c1 CHAR(50)); + +SET @org_mode=@@sql_mode; + +SET @@sql_mode=''; + +PREPARE insert_stmt FROM 'INSERT INTO test_table VALUES (?)'; +PREPARE update_stmt FROM 'UPDATE test_table SET c1= ? WHERE c1= ?'; +DELIMITER $; +CREATE FUNCTION test_function(var CHAR(50)) RETURNS CHAR(50) +BEGIN + DECLARE char_val CHAR(50); + SELECT c1 INTO char_val FROM test_table WHERE c1=var; + RETURN char_val; +END +$ +DELIMITER ;$ + +SET @var1='abcd\'ef'; +SET @var2='abcd\"ef'; +SET @var3='abcd\bef'; +SET @var4='abcd\nef'; +SET @var5='abcd\ref'; +SET @var6='abcd\tef'; +SET @var7='abcd\\ef'; +SET @var8='abcd\%ef'; +SET @var9='abcd\_ef'; + +SET @to_var1='wxyz\'ef'; +SET @to_var2='wxyz\"ef'; +SET @to_var3='wxyz\bef'; +SET @to_var4='wxyz\nef'; +SET @to_var5='wxyz\ref'; +SET @to_var6='wxyz\tef'; +SET @to_var7='wxyz\\ef'; +SET @to_var8='wxyz\%ef'; +SET @to_var9='wxyz\_ef'; + +--echo # STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT +EXECUTE insert_stmt USING @var1; +EXECUTE insert_stmt USING @var2; +EXECUTE insert_stmt USING @var3; +EXECUTE insert_stmt USING @var4; +EXECUTE insert_stmt USING @var5; +EXECUTE insert_stmt USING @var6; +EXECUTE insert_stmt USING @var7; +EXECUTE insert_stmt USING @var8; +EXECUTE insert_stmt USING @var9; + +SELECT * FROM test_table; + +EXECUTE update_stmt USING @to_var1, @var1; +EXECUTE update_stmt USING @to_var2, @var2; +EXECUTE update_stmt USING @to_var3, @var3; +EXECUTE update_stmt USING @to_var4, @var4; +EXECUTE update_stmt USING @to_var5, @var5; +EXECUTE update_stmt USING @to_var6, @var6; +EXECUTE update_stmt USING @to_var7, @var7; +EXECUTE update_stmt USING @to_var8, @var8; +EXECUTE update_stmt USING @to_var9, @var9; + +SELECT * FROM test_table; + +--echo +--echo # END OF CASE - STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT + +--echo # STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +select test_function(@to_var1); +SELECT test_function(@to_var2); +SELECT test_function(@to_var3); +SELECT test_function(@to_var4); +SELECT test_function(@to_var5); +SELECT test_function(@to_var6); +SELECT test_function(@to_var7); +SELECT test_function(@to_var8); +SELECT test_function(@to_var9); + +--echo +--echo # END OF CASE - STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +DELETE FROM test_table; +DROP FUNCTION test_function; + +SET @@sql_mode='NO_BACKSLASH_ESCAPES'; +DELIMITER $; +CREATE FUNCTION test_function(var CHAR(50)) RETURNS CHAR(50) +BEGIN + DECLARE char_val CHAR(50); + SELECT c1 INTO char_val FROM test_table WHERE c1=var; + RETURN char_val; +END +$ +DELIMITER ;$ + +--echo # STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT +EXECUTE insert_stmt USING @var1; +EXECUTE insert_stmt USING @var2; +EXECUTE insert_stmt USING @var3; +EXECUTE insert_stmt USING @var4; +EXECUTE insert_stmt USING @var5; +EXECUTE insert_stmt USING @var6; +EXECUTE insert_stmt USING @var7; +EXECUTE insert_stmt USING @var8; +EXECUTE insert_stmt USING @var9; + +SELECT * FROM test_table; + +EXECUTE update_stmt USING @to_var1, @var1; +EXECUTE update_stmt USING @to_var2, @var2; +EXECUTE update_stmt USING @to_var3, @var3; +EXECUTE update_stmt USING @to_var4, @var4; +EXECUTE update_stmt USING @to_var5, @var5; +EXECUTE update_stmt USING @to_var6, @var6; +EXECUTE update_stmt USING @to_var7, @var7; +EXECUTE update_stmt USING @to_var8, @var8; +EXECUTE update_stmt USING @to_var9, @var9; + +SELECT * FROM test_table; + +--echo +--echo # END OF CASE - STRING LILTERAL WITH BACKSLASH IN PREPARE STATEMENT + +--echo # STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING +select test_function(@to_var1); +SELECT test_function(@to_var2); +SELECT test_function(@to_var3); +SELECT test_function(@to_var4); +SELECT test_function(@to_var5); +SELECT test_function(@to_var6); +SELECT test_function(@to_var7); +SELECT test_function(@to_var8); +SELECT test_function(@to_var9); + +--echo +--echo # END OF CASE - STRING LILTERAL WITH BACKSLASH IN FUNCTION RETURNING STRING + +DROP TABLE test_table; +DROP FUNCTION test_function; +SET @@sql_mode= @org_mode; + +--echo +--echo #End of Test for Bug#12601974 diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 458aa88f071..f369f10a5e4 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3542,6 +3542,61 @@ SET SESSION sql_mode=@old_sql_mode; DEALLOCATE PREPARE stmt; DROP TABLE t1; +--echo # +--echo # Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +--echo # + +CREATE TABLE t1(a1 int); +INSERT INTO t1 VALUES (1),(2); + +CREATE TABLE t2(a1 int); +INSERT INTO t2 VALUES (3); + +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; + +## All these are subject to the transformation +## '1 < some (...)' => '1 < max(...)' +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2 FROM t2); +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 2.0 FROM t2); +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT 'a' FROM t2); +SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t2); + +SET SESSION sql_mode=@old_sql_mode; + +DROP TABLE t1, t2; + +--echo # +--echo # Bug#12763207 - ASSERT IN SUBSELECT::SINGLE_VALUE_TRANSFORMER +--echo # + +create table t2(i int); +insert into t2 values(0); + +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; + +CREATE VIEW v1 AS +SELECT 'f' FROM t2 UNION SELECT 'x' FROM t2 +; + +CREATE TABLE t1 ( + pk int NOT NULL, + col_varchar_key varchar(1) DEFAULT NULL, + PRIMARY KEY (pk), + KEY col_varchar_key (col_varchar_key) +); + +SELECT t1.pk +FROM t1 +WHERE t1.col_varchar_key < ALL ( SELECT * FROM v1 ) +; + +SET SESSION sql_mode=@old_sql_mode; + +drop table t2, t1; +drop view v1; + --echo End of 5.0 tests. # diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test index 6b8a757b9e8..2fb6f6b53b8 100644 --- a/mysql-test/t/subselect_sj.test +++ b/mysql-test/t/subselect_sj.test @@ -2331,5 +2331,40 @@ explain select * from t3 where a in (select kp1 from t1 where kp1<20); drop table t0,t1,t3; set optimizer_switch= @tmp_923246; +--echo # +--echo # BUG#952583: Server crashes in Item_field::fix_after_pullout on INSERT .. SELECT +--echo # +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 ( b INT ); +INSERT INTO t2 VALUES (3),(4); + +INSERT INTO t1 +SELECT * FROM ( SELECT * FROM t1 ) AS alias +WHERE a IN ( SELECT b FROM t2 ); + +DROP TABLE t1, t2; + +--echo # +--echo # BUG#952372: Server crashes on 2nd execution of PS in find_field_in_tables with semijoin+materialization +--echo # +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (2),(3); +CREATE VIEW v1 AS SELECT * FROM t1; + +CREATE TABLE t2 ( b VARCHAR(1) ); +INSERT INTO t2 VALUES ('v'),('v'); + +PREPARE pstmt FROM + 'SELECT DISTINCT a FROM v1, t2 + WHERE b IN ( SELECT MIN(b) FROM t2 )'; + +EXECUTE pstmt; +EXECUTE pstmt; + +DEALLOCATE PREPARE pstmt; +DROP VIEW v1; +DROP TABLE t1, t2; + # The following command must be the last one the file set optimizer_switch=@subselect_sj_tmp; diff --git a/mysql-test/t/subselect_sj2.test b/mysql-test/t/subselect_sj2.test index ede631f32be..92fc500cf55 100644 --- a/mysql-test/t/subselect_sj2.test +++ b/mysql-test/t/subselect_sj2.test @@ -78,13 +78,7 @@ insert into t3 select A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a from t0 A, t0 B where B.a <5; -# -# InnoDB does not use join buffer here, XtraDB does -# (despite the comment above which says "no join buffering", -# because it does not hold when this file is included -# into subselect_sj2_jcl6.test) -# -#--replace_regex /Using join buffer// +--replace_column 9 # explain select * from t3 where b in (select a from t0); select * from t3 where b in (select A.a+B.a from t0 A, t0 B where B.a<5); @@ -1093,5 +1087,143 @@ SELECT * FROM t1, t2 WHERE c IN (SELECT c FROM t1, t2 WHERE a = b); DROP TABLE t1,t2; +--echo # +--echo # BUG#962667: Assertion `0' failed in QUICK_INDEX_SORT_SELECT::need_sorted_output() +--echo # with index_merge+index_merge_sort_union+loosescan+semijoin +--echo # +CREATE TABLE t1 ( + a INT, b VARCHAR(1), c INT, + KEY(a), KEY(b) +) ENGINE=InnoDB; + +INSERT INTO t1 VALUES +(1,'v',9),(2,'v',8),(3,'c',7),(4,'m',6),(5,'x',5), +(6,'i',4),(7,'e',3),(8,'p',2),(9,'s',1),(10,'j',9), +(11,'z',8),(12,'c',7),(13,'a',6),(14,'q',5),(15,'y',4), +(16,'n',3),(17,'r',2),(18,'v',1),(19,'p',0); + +CREATE TABLE t2 ( + pk INT, d VARCHAR(1), e INT, + PRIMARY KEY(pk), KEY(d,e) +) ENGINE=InnoDB; + +INSERT INTO t2 VALUES +(1,'x',1),(2,'d',2),(3,'r',3),(4,'f',4),(5,'y',5), +(6,'u',6),(7,'m',7),(8,'k',8),(9,'o',9),(10,'w',1), +(11,'m',2),(12,'q',3),(13,'m',4),(14,'d',5), +(15,'g',6),(16,'x',7),(17,'f',8); + +explain +SELECT * FROM t1 WHERE b IN ( + SELECT d FROM t2, t1 + WHERE a = d AND ( pk < 2 OR d = 'z' ) +); +SELECT * FROM t1 WHERE b IN ( + SELECT d FROM t2, t1 + WHERE a = d AND ( pk < 2 OR d = 'z' ) +); + +DROP TABLE t1, t2; + +--echo # +--echo # BUG#951937: Wrong result (missing rows) with semijoin+materialization, IN subquery, InnoDB, TEMPTABLE view +--echo # +CREATE TABLE t1 ( + a VARCHAR(1), + b VARCHAR(1) NOT NULL, + KEY(a) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES +('j','j'),('v','v'),('c','c'),('m','m'),('d','d'), +('y','y'),('t','t'),('d','d'),('s','s'),('r','r'), +('m','m'),('b','b'),('x','x'),('g','g'),('p','p'), +('q','q'),('w','w'),('d','d'),('e','e'); + +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; + +--echo # This query returned 6 rows instead of 19 +--sorted_result +SELECT * FROM v1 +WHERE ( a, a ) IN ( + SELECT alias2.b, alias2.a + FROM t1 AS alias1, t1 AS alias2 + WHERE alias2.b = alias1.a + AND ( alias1.b >= alias1.a OR alias2.b = 'z' ) +); + +--echo # Another testcase, without the VIEW: +CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(1) NOT NULL, KEY(a)) ENGINE=InnoDB; +INSERT INTO t2 SELECT * FROM t1; +INSERT INTO t2 SELECT * FROM t1; +EXPLAIN +SELECT * FROM t2 + WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2 + WHERE + alias2.b = alias1.a AND + (alias1.b >= alias1.a OR alias2.b = 'z')); + +--sorted_result +SELECT * FROM t2 + WHERE (a, a) IN (SELECT alias2.b, alias2.a FROM t1 AS alias1, t1 AS alias2 + WHERE + alias2.b = alias1.a AND + (alias1.b >= alias1.a OR alias2.b = 'z')); + +DROP VIEW v1; +DROP TABLE t1, t2; + +--echo # +--echo # BUG#965872: Server crashes in embedding_sjm on a simple 1-table select with AND and OR +--echo # (this is a regression caused by the fix for BUG#951937) +CREATE TABLE t1 ( a INT, b INT, c INT, d INT ); +INSERT INTO t1 VALUES (4,2,8,9),(4,2,7,8); + +SELECT * FROM t1 +WHERE a = d AND ( b = 50 AND b = d OR a = c ); +DROP TABLE t1; + +--echo # +--echo # BUG#951283: Wrong result (missing rows) with semijoin+firstmatch, IN/ANY subquery +--echo # +set @tmp_951283=@@optimizer_prune_level; +SET optimizer_prune_level=0; + +CREATE TABLE t1 ( a INT ) ENGINE=InnoDB; +INSERT INTO t1 VALUES + (10),(11),(12),(13),(14),(15),(16), + (17),(18),(19),(20),(21),(22),(23); + +CREATE TABLE t2 ( + b INT PRIMARY KEY, + c VARCHAR(1), + d VARCHAR(1), + KEY(c) +) ENGINE=InnoDB; + +INSERT INTO t2 VALUES + (1,'j','j'),(2,'v','v'),(3,'c','c'),(4,'m','m'), + (5,'d','d'),(6,'d','d'),(7,'y','y'),(8,'t','t'), + (9,'d','d'),(10,'s','s'),(11,'r','r'),(12,'m','m'), + (13,'b','b'),(14,'x','x'),(15,'g','g'),(16,'p','p'), + (17,'q','q'),(18,'w','w'),(19,'d','d'); + +EXPLAIN +SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3 +WHERE alias3.d IN ( + SELECT alias4.c FROM t2 AS alias4, t2 AS alias5 + WHERE alias5.b = alias4.b + AND ( alias5.b >= alias3.b OR alias5.c != alias3.c ) +); + +SELECT COUNT(*) FROM t1 AS alias1, t1 AS alias2, t2 AS alias3 +WHERE alias3.d IN ( + SELECT alias4.c FROM t2 AS alias4, t2 AS alias5 + WHERE alias5.b = alias4.b + AND ( alias5.b >= alias3.b OR alias5.c != alias3.c ) +); + +set optimizer_prune_level=@tmp_951283; +DROP TABLE t1,t2; + --echo # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 79c733ed791..0585073a6f5 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -4521,6 +4521,18 @@ DROP TABLE t1; disconnect con2; disconnect con3; + +--echo # +--echo # Bug#12626844: WRONG ERROR MESSAGE WHILE CREATING A VIEW ON A +--echo # NON EXISTING DATABASE +--echo # + +--disable_warnings +DROP DATABASE IF EXISTS nodb; +--enable_warnings +--error ER_BAD_DB_ERROR +CREATE VIEW nodb.a AS SELECT 1; + # Check that all connections opened by test cases in this file are really # gone so execution of other tests won't be affected by their presence. --source include/wait_until_count_sessions.inc @@ -4546,6 +4558,61 @@ SELECT * FROM t1 RIGHT JOIN v2 ON ( v2.a = t1.a ) WHERE v2.b IN ( SELECT b FROM DROP VIEW v2; DROP TABLE t1, t2, t3; +--echo # +--echo # BUG#915222: Valgrind complains or crashes with INSERT SELECT +--echo # within a trigger that uses a view +--echo # + +CREATE TABLE t1 (a char(1)); + +CREATE TABLE t2 (d int, e char(1)); + +INSERT INTO t2 VALUES (13,'z'); + +CREATE TRIGGER tr AFTER UPDATE ON t2 + FOR EACH ROW + REPLACE INTO t3 + SELECT f, a AS alias FROM t3, v; + +CREATE TABLE t3 (f int, g char(8)); + +CREATE VIEW v AS SELECT a, e FROM t2, t1; + +UPDATE t2 SET d=7; +UPDATE t2 SET d=7; +UPDATE t2 SET d=7; +UPDATE t2 SET d=7; + +DROP TRIGGER tr; +DROP VIEW v; +DROP TABLE t1,t2,t3; + +--echo # +--echo # BUG#972943: Assertion failure with INSERT SELECT within a trigger +--echo # that uses derived table and materialized view +--echo # + +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (1,0), (2,8); + +CREATE ALGORITHM=TEMPTABLE VIEW v1 + AS SELECT * FROM t1; + +CREATE TABLE t2 (c int); +CREATE TABLE t3 (d int, e int); + +CREATE TRIGGER tr BEFORE INSERT ON t2 FOR EACH ROW + INSERT INTO t3 + SELECT t1.* + FROM (SELECT * FROM t1 WHERE b IN (SELECT b FROM v1)) AS alias1, t1 + WHERE t1.a = 3 OR t1.a > 5; + +INSERT INTO t2 VALUES (1); + +DROP TRIGGER tr; +DROP VIEW v1; +DROP TABLE t1,t2,t3; + --echo # ----------------------------------------------------------------- --echo # -- End of 5.3 tests. --echo # ----------------------------------------------------------------- diff --git a/mysql-test/t/xa.test b/mysql-test/t/xa.test index ab589ae6727..1709886eb0c 100644 --- a/mysql-test/t/xa.test +++ b/mysql-test/t/xa.test @@ -298,7 +298,6 @@ CREATE TABLE t1 (a INT) engine=InnoDB; XA START 'a'; INSERT INTO t1 VALUES (1); ---error ER_XAER_RMFAIL SAVEPOINT savep; XA END 'a'; diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 54f8c9b45f9..800a5a90b39 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -1061,7 +1061,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_S6_ + fun:_Z*13find_all_keysP13st_sort_paramP10SQL_SELECTPPhP11st_io_cacheS6_ fun:_Z8filesortP3THDP5TABLEP13st_sort_fieldjP10SQL_SELECTybPy } diff --git a/mysys/charset-def.c b/mysys/charset-def.c index 65defb5d33b..4183b1fcd99 100644 --- a/mysys/charset-def.c +++ b/mysys/charset-def.c @@ -1,5 +1,4 @@ -/* Copyright (c) 2000, 2003-2007 MySQL AB, 2009, 2010 Sun Microsystems, Inc. - Use is subject to license terms. +/* Copyright (c) 2000, 2012, 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 diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index 5eda20c3236..d23ef129aa2 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -211,13 +211,16 @@ void _lf_pinbox_put_pins(LF_PINS *pins) LF_PINBOX *pinbox= pins->pinbox; uint32 top_ver, nr; nr= pins->link; -#ifdef MY_LF_EXTRA_DEBUG + +#ifndef DBUG_OFF { + /* This thread should not hold any pin. */ int i; for (i= 0; i < LF_PINBOX_PINS; i++) DBUG_ASSERT(pins->pin[i] == 0); } -#endif +#endif /* DBUG_OFF */ + /* XXX this will deadlock if other threads will wait for the caller to do something after _lf_pinbox_put_pins(), diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c index 14f482d2c9c..e5a3a5fe13b 100644 --- a/mysys/my_addr_resolve.c +++ b/mysys/my_addr_resolve.c @@ -134,13 +134,13 @@ err: #include <ctype.h> static int in[2], out[2]; static int initialized= 0; +static char output[1024]; int my_addr_resolve(void *ptr, my_addr_loc *loc) { char input[32], *s; - char output[1024]; size_t len; - len= my_safe_snprintf(input, sizeof(input), "0x%p\n", ptr); + len= my_snprintf(input, sizeof(input), "%p\n", ptr); if (write(in[1], input, len) <= 0) return 1; if (read(out[0], output, sizeof(output)) <= 0) diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c index f1caea6d21a..2a23a699f69 100644 --- a/mysys/my_getsystime.c +++ b/mysys/my_getsystime.c @@ -119,7 +119,6 @@ void my_time_init() ulonglong my_getcputime() { #ifdef CLOCK_THREAD_CPUTIME_ID -#ifdef HAVE_CLOCK_GETTIME struct timespec tp; if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)) return 0; @@ -129,8 +128,6 @@ ulonglong my_getcputime() if (syscall(__NR_clock_gettime, CLOCK_THREAD_CPUTIME_ID, &tp)) return 0; return (ulonglong)tp.tv_sec*10000000+(ulonglong)tp.tv_nsec/100; -#endif /* HAVE_CLOCK_GETTIME */ -#else /* HAVE_THREAD_CPUTIME_ID */ +#endif /* CLOCK_THREAD_CPUTIME_ID */ return 0; -#endif } diff --git a/mysys/my_init.c b/mysys/my_init.c index bb72d0e0426..193c8281577 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates + Copyright (c) 2000, 2012, Oracle and/or its affiliates Copyright (c) 2009, 2011, Monty Program Ab This program is free software; you can redistribute it and/or modify @@ -35,6 +35,8 @@ static my_bool win32_init_tcp_ip(); #define my_win_init() #endif +extern pthread_key(struct st_my_thread_var*, THR_KEY_mysys); + #define SCALE_SEC 100 #define SCALE_USEC 10000 @@ -201,11 +203,12 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", #endif } + my_thread_end(); + my_thread_global_end(); + if (!(infoflag & MY_DONT_FREE_DBUG)) DBUG_END(); /* Must be done as late as possible */ - my_thread_end(); - my_thread_global_end(); my_mutex_end(); #if defined(SAFE_MUTEX) /* @@ -220,7 +223,9 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", if (have_tcpip) WSACleanup(); #endif /* __WIN__ */ - + + /* At very last, delete mysys key, it is used everywhere including DBUG */ + pthread_key_delete(THR_KEY_mysys); my_init_done=0; } /* my_end */ diff --git a/mysys/my_new.cc b/mysys/my_new.cc index 03b3d0f5870..4266452da43 100644 --- a/mysys/my_new.cc +++ b/mysys/my_new.cc @@ -23,6 +23,7 @@ */ #include "mysys_priv.h" +#include <new> #ifdef USE_MYSYS_NEW @@ -36,6 +37,16 @@ void *operator new[] (size_t sz) return (void *) my_malloc (sz ? sz : 1, MYF(0)); } +void* operator new(std::size_t sz, const std::nothrow_t&) throw() +{ + return (void *) my_malloc (sz ? sz : 1, MYF(0)); +} + +void* operator new[](std::size_t sz, const std::nothrow_t&) throw() +{ + return (void *) my_malloc (sz ? sz : 1, MYF(0)); +} + void operator delete (void *ptr) { my_free(ptr); @@ -46,6 +57,16 @@ void operator delete[] (void *ptr) throw () my_free(ptr); } +void operator delete(void* ptr, const std::nothrow_t&) throw() +{ + my_free(ptr); +} + +void operator delete[](void* ptr, const std::nothrow_t&) throw() +{ + my_free(ptr); +} + C_MODE_START int __cxa_pure_virtual() diff --git a/mysys/my_static.c b/mysys/my_static.c index 73af96d87d2..bc2d8beac83 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -90,13 +90,7 @@ static const char *proc_info_dummy(void *a __attribute__((unused)), /* this is to be able to call set_thd_proc_info from the C code */ const char *(*proc_info_hook)(void *, const char *, const char *, const char *, const unsigned int)= proc_info_dummy; -#if defined(ENABLED_DEBUG_SYNC) -/** - Global pointer to be set if callback function is defined - (e.g. in mysqld). See sql/debug_sync.cc. -*/ -void (*debug_sync_C_callback_ptr)(const char *, size_t); -#endif /* defined(ENABLED_DEBUG_SYNC) */ +void (*debug_sync_C_callback_ptr)(MYSQL_THD, const char *, size_t)= 0; /* How to disable options */ my_bool my_disable_locking=0; diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c index 67b9e7d961f..b0e910f7ba0 100644 --- a/mysys/my_symlink.c +++ b/mysys/my_symlink.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2001, 2010, Oracle and/or its affiliates + Copyright (c) 2001, 2011, 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 diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 03041342787..ac16189f3a7 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -274,7 +274,6 @@ void my_thread_global_end(void) */ if (all_threads_killed) { - pthread_key_delete(THR_KEY_mysys); my_thread_destroy_internal_mutex(); } my_thread_global_init_done= 0; diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c index 6f9ab13c82b..a481b4d961c 100644 --- a/mysys/ptr_cmp.c +++ b/mysys/ptr_cmp.c @@ -21,17 +21,23 @@ #include "mysys_priv.h" #include <myisampack.h> - -#ifdef __sun /* - * On Solaris, memcmp() is normally faster than the unrolled ptr_compare_N + * On some platforms, memcmp() is faster than the unrolled ptr_compare_N * functions, as memcmp() is usually a platform-specific implementation - * written in assembler, provided in /usr/lib/libc/libc_hwcap*.so.1. - * This implementation is also usually faster than the built-in memcmp - * supplied by GCC, so it is recommended to build with "-fno-builtin-memcmp" - * in CFLAGS if building with GCC on Solaris. + * written in assembler. for example one in /usr/lib/libc/libc_hwcap*.so.1. + * on Solaris, or on Windows inside C runtime linrary. + * + * On Solaris, native implementation is also usually faster than the + * built-in memcmp supplied by GCC, so it is recommended to build + * with "-fno-builtin-memcmp"in CFLAGS if building with GCC on Solaris. */ +#if defined (__sun) || defined (_WIN32) +#define USE_NATIVE_MEMCMP 1 +#endif + +#ifdef USE_NATIVE_MEMCMP + #include <string.h> static int native_compare(size_t *length, unsigned char **a, unsigned char **b) @@ -39,7 +45,7 @@ static int native_compare(size_t *length, unsigned char **a, unsigned char **b) return memcmp(*a, *b, *length); } -#else /* __sun */ +#else /* USE_NATIVE_MEMCMP */ static int ptr_compare(size_t *compare_length, uchar **a, uchar **b); static int ptr_compare_0(size_t *compare_length, uchar **a, uchar **b); @@ -50,7 +56,7 @@ static int ptr_compare_3(size_t *compare_length, uchar **a, uchar **b); /* Get a pointer to a optimal byte-compare function for a given size */ -#ifdef __sun +#ifdef USE_NATIVE_MEMCMP qsort2_cmp get_ptr_compare (size_t size __attribute__((unused))) { return (qsort2_cmp) native_compare; @@ -68,7 +74,7 @@ qsort2_cmp get_ptr_compare (size_t size) } return 0; /* Impossible */ } -#endif /* __sun */ +#endif /* USE_NATIVE_MEMCMP */ /* @@ -78,7 +84,7 @@ qsort2_cmp get_ptr_compare (size_t size) #define cmp(N) if (first[N] != last[N]) return (int) first[N] - (int) last[N] -#ifndef __sun +#ifndef USE_NATIVE_MEMCMP static int ptr_compare(size_t *compare_length, uchar **a, uchar **b) { diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index cfcfd51dac7..31f0333725f 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -246,6 +246,7 @@ static void warn(const char *format,...) { void *frame[SF_REMEMBER_FRAMES + SF_FRAMES_SKIP]; int frames= backtrace(frame, array_elements(frame)); + fprintf(stderr, " "); if (frames < SF_REMEMBER_FRAMES + SF_FRAMES_SKIP) frame[frames]= 0; print_stack(frame + SF_FRAMES_SKIP); diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c index c4c863404b4..846a90cc127 100644 --- a/mysys/stacktrace.c +++ b/mysys/stacktrace.c @@ -661,9 +661,10 @@ void my_print_stacktrace(uchar* unused1, ulong unused2) my_safe_printf_stderr("%s!", base_image_name); } if(have_symbol) - fprintf(stderr, "%s()", package.sym.Name); + my_safe_printf_stderr("%s()", package.sym.Name); + else if(have_module) - fprintf(stderr,"%s", "???"); + my_safe_printf_stderr("%s", "???"); if(have_source) { @@ -671,7 +672,7 @@ void my_print_stacktrace(uchar* unused1, ulong unused2) my_safe_printf_stderr("[%s:%u]", base_file_name, line.LineNumber); } - fprintf(stderr,"%s", "\n"); + my_safe_printf_stderr("%s", "\n"); } } @@ -742,189 +743,10 @@ void my_safe_print_str(const char *val, int len) #endif /*__WIN__*/ -#ifdef __WIN__ -size_t my_write_stderr(const void *buf, size_t count) -{ - return fwrite(buf, 1, count, stderr); -} -#else size_t my_write_stderr(const void *buf, size_t count) { return (size_t) write(STDERR_FILENO, buf, count); } -#endif - - -static const char digits[]= "0123456789abcdef"; - -char *my_safe_utoa(int base, ulonglong val, char *buf) -{ - *buf--= 0; - do { - *buf--= digits[val % base]; - } while ((val /= base) != 0); - return buf + 1; -} - - -char *my_safe_itoa(int base, longlong val, char *buf) -{ - char *orig_buf= buf; - const my_bool is_neg= (val < 0); - *buf--= 0; - - if (is_neg) - val= -val; - if (is_neg && base == 16) - { - int ix; - val-= 1; - for (ix= 0; ix < 16; ++ix) - buf[-ix]= '0'; - } - - do { - *buf--= digits[val % base]; - } while ((val /= base) != 0); - - if (is_neg && base == 10) - *buf--= '-'; - - if (is_neg && base == 16) - { - int ix; - buf= orig_buf - 1; - for (ix= 0; ix < 16; ++ix, --buf) - { - switch (*buf) - { - case '0': *buf= 'f'; break; - case '1': *buf= 'e'; break; - case '2': *buf= 'd'; break; - case '3': *buf= 'c'; break; - case '4': *buf= 'b'; break; - case '5': *buf= 'a'; break; - case '6': *buf= '9'; break; - case '7': *buf= '8'; break; - case '8': *buf= '7'; break; - case '9': *buf= '6'; break; - case 'a': *buf= '5'; break; - case 'b': *buf= '4'; break; - case 'c': *buf= '3'; break; - case 'd': *buf= '2'; break; - case 'e': *buf= '1'; break; - case 'f': *buf= '0'; break; - } - } - } - return buf+1; -} - - -static const char *check_longlong(const char *fmt, my_bool *have_longlong) -{ - *have_longlong= FALSE; - if (*fmt == 'l') - { - fmt++; - if (*fmt != 'l') - *have_longlong= (sizeof(long) == sizeof(longlong)); - else - { - fmt++; - *have_longlong= TRUE; - } - } - return fmt; -} - -static size_t my_safe_vsnprintf(char *to, size_t size, - const char* format, va_list ap) -{ - char *start= to; - char *end= start + size - 1; - for (; *format; ++format) - { - my_bool have_longlong = FALSE; - if (*format != '%') - { - if (to == end) /* end of buffer */ - break; - *to++= *format; /* copy ordinary char */ - continue; - } - ++format; /* skip '%' */ - - format= check_longlong(format, &have_longlong); - - switch (*format) - { - case 'd': - case 'i': - case 'u': - case 'x': - case 'p': - { - longlong ival= 0; - ulonglong uval = 0; - if (*format == 'p') - have_longlong= (sizeof(void *) == sizeof(longlong)); - if (have_longlong) - { - if (*format == 'u') - uval= va_arg(ap, ulonglong); - else - ival= va_arg(ap, longlong); - } - else - { - if (*format == 'u') - uval= va_arg(ap, unsigned int); - else - ival= va_arg(ap, int); - } - - { - char buff[22]; - const int base= (*format == 'x' || *format == 'p') ? 16 : 10; - char *val_as_str= (*format == 'u') ? - my_safe_utoa(base, uval, &buff[sizeof(buff)-1]) : - my_safe_itoa(base, ival, &buff[sizeof(buff)-1]); - - /* Strip off "ffffffff" if we have 'x' format without 'll' */ - if (*format == 'x' && !have_longlong && ival < 0) - val_as_str+= 8; - - while (*val_as_str && to < end) - *to++= *val_as_str++; - continue; - } - } - case 's': - { - const char *val= va_arg(ap, char*); - if (!val) - val= "(null)"; - while (*val && to < end) - *to++= *val++; - continue; - } - } - } - *to= 0; - return to - start; -} - - -size_t my_safe_snprintf(char* to, size_t n, const char* fmt, ...) -{ - size_t result; - va_list args; - va_start(args,fmt); - result= my_safe_vsnprintf(to, n, fmt, args); - va_end(args); - return result; -} size_t my_safe_printf_stderr(const char* fmt, ...) @@ -933,7 +755,7 @@ size_t my_safe_printf_stderr(const char* fmt, ...) size_t result; va_list args; va_start(args,fmt); - result= my_safe_vsnprintf(to, sizeof(to), fmt, args); + result= my_vsnprintf(to, sizeof(to), fmt, args); va_end(args); my_write_stderr(to, result); return result; diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 2979244962d..7c10b0abe8c 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -1287,6 +1287,9 @@ thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner, if (result != THR_LOCK_SUCCESS) { /* Aborted */ thr_multi_unlock(data,(uint) (pos-data), 0); + /* Mark all requested locks as TL_UNLOCK (to simplify lock checking) */ + for ( ; pos < end ; pos++) + (*pos)->type= TL_UNLOCK; DBUG_RETURN(result); } DEBUG_SYNC_C("thr_multi_lock_after_thr_lock"); diff --git a/mysys/waiting_threads.c b/mysys/waiting_threads.c index ddc06a3ae5e..f7e74e012d2 100644 --- a/mysys/waiting_threads.c +++ b/mysys/waiting_threads.c @@ -423,6 +423,8 @@ static void wt_resource_destroy(uchar *arg) DBUG_VOID_RETURN; } +static int wt_init_done; + void wt_init() { DBUG_ENTER("wt_init"); @@ -456,18 +458,22 @@ void wt_init() my_atomic_rwlock_init(&cycle_stats_lock); my_atomic_rwlock_init(&success_stats_lock); my_atomic_rwlock_init(&wait_stats_lock); + wt_init_done= 1; DBUG_VOID_RETURN; } void wt_end() { DBUG_ENTER("wt_end"); + if (!wt_init_done) + DBUG_VOID_RETURN; DBUG_ASSERT(reshash.count == 0); lf_hash_destroy(&reshash); my_atomic_rwlock_destroy(&cycle_stats_lock); my_atomic_rwlock_destroy(&success_stats_lock); my_atomic_rwlock_destroy(&wait_stats_lock); + wt_init_done= 0; DBUG_VOID_RETURN; } diff --git a/packaging/WiX/custom_ui.wxs b/packaging/WiX/custom_ui.wxs index a77612c4e50..568053f4cf5 100644 --- a/packaging/WiX/custom_ui.wxs +++ b/packaging/WiX/custom_ui.wxs @@ -2,7 +2,7 @@ xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<!--
- Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2012, 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
@@ -30,7 +30,7 @@ <Control Id="Back" Type="PushButton" X="156" Y="243" Width="56" Height="17" Text="!(loc.WixUIBack)" Disabled="yes" />
<Control Id="Description" Type="Text" X="135" Y="80" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.WelcomeDlgDescription)" />
<Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.WelcomeDlgTitle)" />
- <Control Id="CopyrightText" Type="Text" X="135" Y="200" Width="220" Height="40" Transparent="yes" Text="Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved." />
+ <Control Id="CopyrightText" Type="Text" X="135" Y="200" Width="220" Height="40" Transparent="yes" Text="Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved." />
<Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="!(loc.WelcomeDlgBitmap)" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
</Dialog>
diff --git a/plugin/auth_examples/dialog_examples.c b/plugin/auth_examples/dialog_examples.c index 9c4728b7886..067244d6f7d 100644 --- a/plugin/auth_examples/dialog_examples.c +++ b/plugin/auth_examples/dialog_examples.c @@ -1,5 +1,5 @@ /* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab - Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2010, 2011, 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 diff --git a/plugin/auth_examples/qa_auth_interface.c b/plugin/auth_examples/qa_auth_interface.c index 303978f7b1f..ddf51a3dd19 100644 --- a/plugin/auth_examples/qa_auth_interface.c +++ b/plugin/auth_examples/qa_auth_interface.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2011, 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 diff --git a/plugin/auth_examples/qa_auth_server.c b/plugin/auth_examples/qa_auth_server.c index a6a06cfa289..59b926b63dc 100644 --- a/plugin/auth_examples/qa_auth_server.c +++ b/plugin/auth_examples/qa_auth_server.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 2011, 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 diff --git a/plugin/daemon_example/CMakeLists.txt b/plugin/daemon_example/CMakeLists.txt index 06c39af4bdd..3d674c4ef3e 100644 --- a/plugin/daemon_example/CMakeLists.txt +++ b/plugin/daemon_example/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2011, 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 diff --git a/plugin/daemon_example/daemon_example.cc b/plugin/daemon_example/daemon_example.cc index ab374a4fb3f..ec2979de3c3 100644 --- a/plugin/daemon_example/daemon_example.cc +++ b/plugin/daemon_example/daemon_example.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2011, 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 diff --git a/plugin/feedback/utils.cc b/plugin/feedback/utils.cc index 48bbd72d530..f81fde2ab8f 100644 --- a/plugin/feedback/utils.cc +++ b/plugin/feedback/utils.cc @@ -152,26 +152,36 @@ namespace feedback { static const bool UNSIGNED= true; ///< used below when inserting integers /** - callback for fill_plugin_version() - insert a plugin name and its version + callback for fill_plugins() */ static my_bool show_plugins(THD *thd, plugin_ref plugin, void *arg) { TABLE *table= (TABLE*) arg; + char name[NAME_LEN*2]; + size_t name_len; char version[20]; size_t version_len; + name_len= my_snprintf(name, sizeof(name), "%s version", + plugin_name(plugin)->str); + version_len= my_snprintf(version, sizeof(version), "%d.%d", (plugin_decl(plugin)->version) >> 8, (plugin_decl(plugin)->version) & 0xff); - INSERT2(plugin_name(plugin)->str, plugin_name(plugin)->length, + INSERT2(name, name_len, (version, version_len, system_charset_info)); + name_len= my_snprintf(name, sizeof(name), "%s used", + plugin_name(plugin)->str); + + INSERT2(name, name_len, (plugin_ref_to_int(plugin)->locks_total, UNSIGNED)); + return 0; } /** - inserts all plugins and their versions into I_S.FEEDBACK + inserts all plugins, their versions, and usage counters */ int fill_plugin_version(THD *thd, TABLE_LIST *tables) { diff --git a/plugin/handler_socket/handlersocket/hstcpsvr_worker.cpp b/plugin/handler_socket/handlersocket/hstcpsvr_worker.cpp index 85887d1d55c..c254d17dff5 100644 --- a/plugin/handler_socket/handlersocket/hstcpsvr_worker.cpp +++ b/plugin/handler_socket/handlersocket/hstcpsvr_worker.cpp @@ -7,6 +7,7 @@ */ #include <my_config.h> +#include <sys/types.h> #include <netinet/in.h> #include <errno.h> #include <poll.h> diff --git a/plugin/handler_socket/libhsclient/fatal.cpp b/plugin/handler_socket/libhsclient/fatal.cpp index 8f8751da382..5cdd8879ab1 100644 --- a/plugin/handler_socket/libhsclient/fatal.cpp +++ b/plugin/handler_socket/libhsclient/fatal.cpp @@ -9,6 +9,7 @@ #include <stdlib.h> #include <stdio.h> #include <syslog.h> +#include <unistd.h> #include "fatal.hpp" diff --git a/plugin/semisync/semisync_master.cc b/plugin/semisync/semisync_master.cc index 7504697a21f..9e857f83d39 100644 --- a/plugin/semisync/semisync_master.cc +++ b/plugin/semisync/semisync_master.cc @@ -626,7 +626,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, (int)is_on()); } - while (is_on()) + while (is_on() && !thd_killed(NULL)) { if (reply_file_name_inited_) { @@ -743,7 +743,8 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, At this point, the binlog file and position of this transaction must have been removed from ActiveTranx. */ - assert(!active_tranxs_->is_tranx_end_pos(trx_wait_binlog_name, + assert(thd_killed(NULL) || + !active_tranxs_->is_tranx_end_pos(trx_wait_binlog_name, trx_wait_binlog_pos)); /* Update the status counter. */ diff --git a/plugin/sql_errlog/CMakeLists.txt b/plugin/sql_errlog/CMakeLists.txt index 18fb9f5421d..50c4b7d806d 100644 --- a/plugin/sql_errlog/CMakeLists.txt +++ b/plugin/sql_errlog/CMakeLists.txt @@ -13,4 +13,4 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -MYSQL_ADD_PLUGIN(sql_errlog sql_errlog.c MODULE_ONLY) +MYSQL_ADD_PLUGIN(sql_errlog sql_errlog.c sql_logger.cc service_logger.h MODULE_ONLY) diff --git a/libservices/logger_service.c b/plugin/sql_errlog/logger_service.c index 896b0714293..c45e978413c 100644 --- a/libservices/logger_service.c +++ b/plugin/sql_errlog/logger_service.c @@ -16,5 +16,6 @@ #include <service_versions.h> +/* file reserved for the future use */ SERVICE_VERSION *logger_service= (void *) VERSION_logger; diff --git a/include/mysql/service_logger.h b/plugin/sql_errlog/service_logger.h index 47a478ef5b4..2aa4d94f010 100644 --- a/include/mysql/service_logger.h +++ b/plugin/sql_errlog/service_logger.h @@ -69,7 +69,7 @@ extern struct logger_service_st { int (*rotate)(LOGGER_HANDLE *log); } *logger_service; -#ifdef MYSQL_DYNAMIC_PLUGIN +#if 0 /*MYSQL_DYNAMIC_PLUGIN*/ #define logger_open(path, size_limit, rotations) \ (logger_service->open(path, size_limit, rotations)) @@ -87,6 +87,8 @@ extern struct logger_service_st { int logger_vprintf(LOGGER_HANDLE *log, const char *fmt, va_list argptr); int logger_rotate(LOGGER_HANDLE *log); int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...); + + void init_logger_mutexes(); #endif diff --git a/plugin/sql_errlog/sql_errlog.c b/plugin/sql_errlog/sql_errlog.c index ee2765a7143..ce383916621 100644 --- a/plugin/sql_errlog/sql_errlog.c +++ b/plugin/sql_errlog/sql_errlog.c @@ -16,6 +16,7 @@ #include <mysql/plugin_audit.h> #include <stdio.h> #include <time.h> +#include "service_logger.h" /* Disable __attribute__() on non-gcc compilers. @@ -32,6 +33,7 @@ rate 0 means the logging was disabled. */ + static char *filename; static unsigned int rate; static unsigned long long size_limit; @@ -50,7 +52,7 @@ static MYSQL_SYSVAR_UINT(rate, rate, PLUGIN_VAR_RQCMDARG, static MYSQL_SYSVAR_ULONGLONG(size_limit, size_limit, PLUGIN_VAR_READONLY, "Log file size limit", NULL, NULL, - 1000000, 100, 0, 1); + 1000000, 100, ((long long) 0x7FFFFFFFFFFFFFFFLL), 1); static MYSQL_SYSVAR_UINT(rotations, rotations, PLUGIN_VAR_READONLY, "Number of rotations before log is removed.", @@ -104,6 +106,8 @@ static void log_sql_errors(MYSQL_THD thd __attribute__((unused)), static int sql_error_log_init(void *p __attribute__((unused))) { + init_logger_mutexes(); + logfile= logger_open(filename, size_limit, rotations); if (logfile == NULL) { fprintf(stderr, "Could not create file '%s'\n", @@ -117,7 +121,8 @@ static int sql_error_log_init(void *p __attribute__((unused))) static int sql_error_log_deinit(void *p __attribute__((unused))) { - logger_close(logfile); + if (logfile) + logger_close(logfile); return 0; } @@ -139,6 +144,24 @@ static struct st_mysql_audit descriptor = { MYSQL_AUDIT_GENERAL_CLASSMASK } }; +mysql_declare_plugin(sql_errlog) +{ + MYSQL_AUDIT_PLUGIN, + &descriptor, + "SQL_ERROR_LOG", + "Alexey Botchkov", + "Log SQL level errors to a file with rotation", + PLUGIN_LICENSE_GPL, + sql_error_log_init, + sql_error_log_deinit, + 0x0100, + NULL, + vars, + NULL, + 0 +} +mysql_declare_plugin_end; + maria_declare_plugin(sql_errlog) { MYSQL_AUDIT_PLUGIN, diff --git a/sql/sql_logger.cc b/plugin/sql_errlog/sql_logger.cc index fe3c9a87d20..8bf757f2fd7 100644 --- a/sql/sql_logger.cc +++ b/plugin/sql_errlog/sql_logger.cc @@ -16,10 +16,15 @@ #include "my_global.h" #include <my_sys.h> -#include <mysql/service_logger.h> +#include "service_logger.h" +#include <my_pthread.h> -extern char *mysql_data_home; -extern PSI_mutex_key key_LOCK_logger_service; +extern MYSQL_PLUGIN_IMPORT char *mysql_data_home; + +/* These belong to the service initialization */ +static PSI_mutex_key key_LOCK_logger_service; +static PSI_mutex_info mutex_list[]= +{{ &key_LOCK_logger_service, "logger_service_file_st::lock", PSI_FLAG_GLOBAL}}; typedef struct logger_handle_st { File file; @@ -181,3 +186,9 @@ int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...) return result; } +void init_logger_mutexes() +{ + if (PSI_server) + PSI_server->register_mutex("sql_logger", mutex_list, 1); +} + diff --git a/scripts/mysql_install_db.pl.in b/scripts/mysql_install_db.pl.in index 83756d686d2..3fdecc968e1 100644 --- a/scripts/mysql_install_db.pl.in +++ b/scripts/mysql_install_db.pl.in @@ -1,7 +1,7 @@ #!/usr/bin/perl # -*- cperl -*- # -# Copyright (C) 2007 MySQL AB +# Copyright (c) 2007, 2011, 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 diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index f0b09cc3e77..1dd6b787c43 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -1,7 +1,6 @@ #!/bin/sh -# Copyright (c) 2000-2008 MySQL AB, 2009, 2010 Sun Microsystems, Inc. -# Copyright (c) 2009-2011 Monty Program Ab -# Use is subject to license terms. +# Copyright (c) 2000, 2011, Oracle and/or its affiliates. +# Copyright (c) 2009, 2011, 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 diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 20e5e115687..aaf1936afe1 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -15,6 +15,7 @@ KILL_MYSQLD=1; MYSQLD= niceness=0 +nowatch=0 mysqld_ld_preload= mysqld_ld_library_path= @@ -44,16 +45,18 @@ usage () { cat <<EOF Usage: $0 [OPTIONS] --no-defaults Don't read the system defaults file + --core-file-size=LIMIT Limit core files to the specified size --defaults-file=FILE Use the specified defaults file --defaults-extra-file=FILE Also use defaults from the specified file --ledir=DIRECTORY Look for mysqld in the specified directory --open-files-limit=LIMIT Limit the number of open files - --core-file-size=LIMIT Limit core files to the specified size --timezone=TZ Set the system timezone --malloc-lib=LIB Preload shared library LIB if available --mysqld=FILE Use the specified file as mysqld --mysqld-version=VERSION Use "mysqld-VERSION" as mysqld --nice=NICE Set the scheduling priority of mysqld + --no-auto-restart Exit after starting mysqld + --nowatch Exit after starting mysqld --plugin-dir=DIR Plugins are under DIR or DIR/VERSION, if VERSION is given --skip-kill-mysqld Don't try to kill stray mysqld processes @@ -140,8 +143,16 @@ eval_log_error () { ;; esac - #echo "Running mysqld: [$cmd]" - eval "$cmd" + if test $nowatch -eq 1 + then + # We'd prefer to exec $cmd here, but SELinux needs to be fixed first + #/usr/bin/logger "Running mysqld: $cmd" + eval "$cmd &" + exit 0 + else + #echo "Running mysqld: [$cmd]" + eval "$cmd" + fi } shell_quote_string() { @@ -202,6 +213,7 @@ parse_arguments() { fi ;; --nice=*) niceness="$val" ;; + --nowatch|--no-watch|--no-auto-restart) nowatch=1 ;; --open-files-limit=*) open_files="$val" ;; --open_files_limit=*) open_files="$val" ;; --skip-kill-mysqld*) KILL_MYSQLD=0 ;; diff --git a/scripts/mytop.sh b/scripts/mytop.sh index 7cec85e2136..a36fddf7368 100755 --- a/scripts/mytop.sh +++ b/scripts/mytop.sh @@ -18,8 +18,10 @@ use DBI; use Getopt::Long; use Socket; use List::Util qw(min max); +use File::Basename; $main::VERSION = "1.9a"; +my $path_for_script= dirname($0); $|=1; $0 = 'mytop'; @@ -95,7 +97,8 @@ my %config = ( slow => 10, # slow query time socket => '', sort => 0, # default or reverse sort ("s") - user => 'root' + user => 'root', + fullqueries => 0 ); my %qcache = (); ## The query cache--used for full query info support. @@ -112,6 +115,17 @@ my $CLEAR = $WIN ? '': `clear`; my $RM_RESET = 0; my $RM_NOBLKRD = 3; ## using 4 traps Ctrl-C :-( +# Add options from .my.cnf first + +my $my_print_defaults; +if (!defined($my_print_defaults=my_which("my_print_defaults"))) +{ + print "Warning: Can't find my_print_defaults. Please add it to your PATH!\n"; + exit(1); +} + +unshift @ARGV, split "\n", `$my_print_defaults client mytop`; + ## Read the user's config file, if it exists. my $config = "$ENV{HOME}/.mytop"; @@ -160,7 +174,8 @@ GetOptions( "long_nums!" => \$config{long_nums}, "mode|m=s" => \$config{mode}, "slow=i" => \$config{slow}, - "sort=s" => \$config{sort} + "sort=s" => \$config{sort}, + "fullqueries|L!" => \$config{fullqueries} ); ## User may have put the port with the host. @@ -744,6 +759,25 @@ while (1) { $config{mode} = 'status'; } + + ## L - full queries toggle + + if ($key eq 'L') + { + if ($config{fullqueries}) + { + $config{fullqueries} = 0; + print RED(), "-- full queries OFF --", RESET(); + sleep 1; + } + else + { + $config{fullqueries} = 1; + print RED(), "-- full queries ON --", RESET(); + sleep 1; + } + } + } ReadMode($RM_RESET) unless $config{batchmode}; @@ -1115,7 +1149,13 @@ sub GetData() my $state= $width <= 80 ? 6 : int(min(6+($width-80)/3, 15)); my $free = $width - $used - ($state - 6); my $format= "%9s %8s %15s %9s %6s %5s %6s %${state}s %-.${free}s\n"; - my $format2= "%9d %8.8s %15.15s %9.9s %6d %5.1f %6.6s %${state}.${state}s %-${free}.${free}s\n"; + my $format2; + if ($config{fullqueries}) + { + $format2 = "%9d %8.8s %15.15s %9.9s %6d %5.1f %6.6s %${state}.${state}s %-${free}s\n"; + } else { + $format2 = "%9d %8.8s %15.15s %9.9s %6d %5.1f %6.6s %${state}.${state}s %-${free}.${free}s\n"; + } print BOLD() if ($HAS_COLOR); printf $format, @@ -1244,7 +1284,12 @@ sub GetData() if ($thread->{Info}) { - $smInfo = substr $thread->{Info}, 0, $free; + if ($config{fullqueries}) + { + $smInfo = $thread->{Info}; + } else { + $smInfo = substr $thread->{Info}, 0, $free; + } } # if ($thread->{State}) # { @@ -1690,6 +1735,7 @@ Origional work by Jeremy D. Zawodny <${YELLOW}Jeremy\@Zawodny.com${RESET}> u - show only a specific user V - show variablesi : - enter a command (not yet implemented) + L - show full queries (do not strip to terminal width) Base version from ${GREEN}http://www.mysqlfanboy.com/mytop${RESET} This version comes as part of the ${GREEN}MariaDB${RESET} distribution. @@ -1789,6 +1835,35 @@ sub FindProg($) return $found; } +#### +#### my_which is used, because we can't assume that every system has the +#### which -command. my_which can take only one argument at a time. +#### Return values: requested system command with the first found path, +#### or undefined, if not found. +#### + +sub my_which +{ + my ($command) = @_; + my (@paths, $path); + + return $command if (-f $command && -x $command); + + # Check first if this is a source distribution, then if this binary + # distribution and last in the path + + push @paths, "./extra"; + push @paths, $path_for_script; + push @paths, split(':', $ENV{'PATH'}); + + foreach $path (@paths) + { + $path .= "/$command"; + return $path if (-f $path && -x $path); + } + return undef(); +} + =pod =head1 SYNOPSIS @@ -2056,11 +2131,15 @@ command-line arguments are applied. =head2 Config File Instead of always using bulky command-line parameters, you can also -use a config file in your home directory (C<~/.mytop>). If present, -B<mytop> will read it automatically. It is read I<before> any of your +use a config files for the default value of your options. + +mytop will first read the [client] and [mytop] sections from your +my.cnf files. After that it will read the (C<~/.mytop>) file from your +home directory (if present). These are read I<before> any of your command-line arguments are processed, so your command-line arguments will override directives in the config file. + Here is a sample config file C<~/.mytop> which implements the defaults described above. @@ -2275,6 +2354,10 @@ Many thanks go to these fine folks: =over +=Item Jean Weisbuch + +Added --fullqueries and reading of .my.cnf + =item Sami Ahlroos (sami@avis-net.de) Suggested the idle/noidle stuff. diff --git a/sql-common/client.c b/sql-common/client.c index f6084d061b8..349d844ebd3 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -2969,10 +2969,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, const char *scramble_plugin; ulong pkt_length; NET *net= &mysql->net; -#ifdef MYSQL_SERVER - thr_alarm_t alarmed; - ALARM alarm_buff; -#endif #ifdef __WIN__ HANDLE hPipe=INVALID_HANDLE_VALUE; #endif @@ -3181,17 +3177,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, my_snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host); DBUG_PRINT("info",("Server name: '%s'. TCP sock: %d", host, port)); -#ifdef MYSQL_SERVER - thr_alarm_init(&alarmed); - thr_alarm(&alarmed, mysql->options.connect_timeout, &alarm_buff); -#endif - DBUG_PRINT("info",("IP '%s'", "client")); -#ifdef MYSQL_SERVER - thr_end_alarm(&alarmed); -#endif - memset(&hints, 0, sizeof(hints)); hints.ai_socktype= SOCK_STREAM; hints.ai_protocol= IPPROTO_TCP; diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 4574f1af6d6..6affd5c0ecf 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2004, 2011, Oracle and/or its affiliates. + Copyright (c) 2004, 2012, 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 diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index f74931388bb..7149c54478a 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -102,7 +102,6 @@ SET (SQL_SOURCE gcalc_slicescan.cc gcalc_tools.cc threadpool_common.cc ../sql-common/mysql_async.c - sql_logger.cc ${WSREP_SOURCES} ${GEN_SOURCES} ${MYSYS_LIBWRAP_SOURCE} @@ -290,7 +289,7 @@ IF(INSTALL_LAYOUT STREQUAL "STANDALONE") # We need to create empty directories (data/test) the installation. # This does not work with current CPack due to http://www.cmake.org/Bug/view.php?id=8767 # Avoid completely empty directories and install dummy file instead. -SET(DUMMY_FILE ${CMAKE_CURRENT_BINARY_DIR}/.empty ) +SET(DUMMY_FILE ${CMAKE_CURRENT_BINARY_DIR}/db.opt ) FILE(WRITE ${DUMMY_FILE} "") INSTALL(FILES ${DUMMY_FILE} DESTINATION data/test COMPONENT DataFiles) @@ -322,7 +321,11 @@ IF(WIN32 AND MYSQLD_EXECUTABLE) DEPENDS initdb.dep ) INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data DESTINATION . - COMPONENT DataFiles PATTERN "initdb.dep" EXCLUDE PATTERN "bootstrap.sql" EXCLUDE) + COMPONENT DataFiles + PATTERN "initdb.dep" EXCLUDE + PATTERN "bootstrap.sql" EXCLUDE + PATTERN "aria*" EXCLUDE + ) ELSE() # Not windows or cross compiling, just install an empty directory INSTALL(FILES ${DUMMY_FILE} DESTINATION data/mysql COMPONENT DataFiles) diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index a789763dd25..4097d7fe6e1 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -13,307 +13,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/** - == Debug Sync Facility == - - The Debug Sync Facility allows placement of synchronization points in - the server code by using the DEBUG_SYNC macro: - - open_tables(...) - - DEBUG_SYNC(thd, "after_open_tables"); - - lock_tables(...) - - When activated, a sync point can - - - Emit a signal and/or - - Wait for a signal - - Nomenclature: - - - signal: A value of a global variable that persists - until overwritten by a new signal. The global - variable can also be seen as a "signal post" - or "flag mast". Then the signal is what is - attached to the "signal post" or "flag mast". - - - emit a signal: Assign the value (the signal) to the global - variable ("set a flag") and broadcast a - global condition to wake those waiting for - a signal. - - - wait for a signal: Loop over waiting for the global condition until - the global value matches the wait-for signal. - - By default, all sync points are inactive. They do nothing (except to - burn a couple of CPU cycles for checking if they are active). - - A sync point becomes active when an action is requested for it. - To do so, put a line like this in the test case file: - - SET DEBUG_SYNC= 'after_open_tables SIGNAL opened WAIT_FOR flushed'; - - This activates the sync point 'after_open_tables'. It requests it to - emit the signal 'opened' and wait for another thread to emit the signal - 'flushed' when the thread's execution runs through the sync point. - - For every sync point there can be one action per thread only. Every - thread can request multiple actions, but only one per sync point. In - other words, a thread can activate multiple sync points. - - Here is an example how to activate and use the sync points: - - --connection conn1 - SET DEBUG_SYNC= 'after_open_tables SIGNAL opened WAIT_FOR flushed'; - send INSERT INTO t1 VALUES(1); - --connection conn2 - SET DEBUG_SYNC= 'now WAIT_FOR opened'; - SET DEBUG_SYNC= 'after_abort_locks SIGNAL flushed'; - FLUSH TABLE t1; - - When conn1 runs through the INSERT statement, it hits the sync point - 'after_open_tables'. It notices that it is active and executes its - action. It emits the signal 'opened' and waits for another thread to - emit the signal 'flushed'. - - conn2 waits immediately at the special sync point 'now' for another - thread to emit the 'opened' signal. - - A signal remains in effect until it is overwritten. If conn1 signals - 'opened' before conn2 reaches 'now', conn2 will still find the 'opened' - signal. It does not wait in this case. - - When conn2 reaches 'after_abort_locks', it signals 'flushed', which lets - conn1 awake. - - Normally the activation of a sync point is cleared when it has been - executed. Sometimes it is necessary to keep the sync point active for - another execution. You can add an execute count to the action: - - SET DEBUG_SYNC= 'name SIGNAL sig EXECUTE 3'; - - This sets the signal point's activation counter to 3. Each execution - decrements the counter. After the third execution the sync point - becomes inactive. - - One of the primary goals of this facility is to eliminate sleeps from - the test suite. In most cases it should be possible to rewrite test - cases so that they do not need to sleep. (But this facility cannot - synchronize multiple processes.) However, to support test development, - and as a last resort, sync point waiting times out. There is a default - timeout, but it can be overridden: - - SET DEBUG_SYNC= 'name WAIT_FOR sig TIMEOUT 10 EXECUTE 2'; - - TIMEOUT 0 is special: If the signal is not present, the wait times out - immediately. - - When a wait timed out (even on TIMEOUT 0), a warning is generated so - that it shows up in the test result. - - You can throw an error message and kill the query when a synchronization - point is hit a certain number of times: - - SET DEBUG_SYNC= 'name HIT_LIMIT 3'; - - Or combine it with signal and/or wait: - - SET DEBUG_SYNC= 'name SIGNAL sig EXECUTE 2 HIT_LIMIT 3'; - - Here the first two hits emit the signal, the third hit returns the error - message and kills the query. - - For cases where you are not sure that an action is taken and thus - cleared in any case, you can force to clear (deactivate) a sync point: - - SET DEBUG_SYNC= 'name CLEAR'; - - If you want to clear all actions and clear the global signal, use: - - SET DEBUG_SYNC= 'RESET'; - - This is the only way to reset the global signal to an empty string. - - For testing of the facility itself you can execute a sync point just - as if it had been hit: - - SET DEBUG_SYNC= 'name TEST'; - - - === Formal Syntax === - - The string to "assign" to the DEBUG_SYNC variable can contain: - - {RESET | - <sync point name> TEST | - <sync point name> CLEAR | - <sync point name> {{SIGNAL <signal name> | - WAIT_FOR <signal name> [TIMEOUT <seconds>]} - [EXECUTE <count>] &| HIT_LIMIT <count>} - - Here '&|' means 'and/or'. This means that one of the sections - separated by '&|' must be present or both of them. - - - === Activation/Deactivation === - - The facility is an optional part of the MySQL server. - It is enabled in a debug server by default. - - ./configure --enable-debug-sync - - The Debug Sync Facility, when compiled in, is disabled by default. It - can be enabled by a mysqld command line option: - - --debug-sync-timeout[=default_wait_timeout_value_in_seconds] - - 'default_wait_timeout_value_in_seconds' is the default timeout for the - WAIT_FOR action. If set to zero, the facility stays disabled. - - The facility is enabled by default in the test suite, but can be - disabled with: - - mysql-test-run.pl ... --debug-sync-timeout=0 ... - - Likewise the default wait timeout can be set: - - mysql-test-run.pl ... --debug-sync-timeout=10 ... - - The command line option influences the readable value of the system - variable 'debug_sync'. - - * If the facility is not compiled in, the system variable does not exist. - - * If --debug-sync-timeout=0 the value of the variable reads as "OFF". - - * Otherwise the value reads as "ON - current signal: " followed by the - current signal string, which can be empty. - - The readable variable value is the same, regardless if read as global - or session value. - - Setting the 'debug-sync' system variable requires 'SUPER' privilege. - You can never read back the string that you assigned to the variable, - unless you assign the value that the variable does already have. But - that would give a parse error. A syntactically correct string is - parsed into a debug sync action and stored apart from the variable value. - - - === Implementation === - - Pseudo code for a sync point: - - #define DEBUG_SYNC(thd, sync_point_name) - if (unlikely(opt_debug_sync_timeout)) - debug_sync(thd, STRING_WITH_LEN(sync_point_name)) - - The sync point performs a binary search in a sorted array of actions - for this thread. - - The SET DEBUG_SYNC statement adds a requested action to the array or - overwrites an existing action for the same sync point. When it adds a - new action, the array is sorted again. - - - === A typical synchronization pattern === - - There are quite a few places in MySQL, where we use a synchronization - pattern like this: - - mysql_mutex_lock(&mutex); - thd->enter_cond(&condition_variable, &mutex, new_message); - #if defined(ENABLE_DEBUG_SYNC) - if (!thd->killed && !end_of_wait_condition) - DEBUG_SYNC(thd, "sync_point_name"); - #endif - while (!thd->killed && !end_of_wait_condition) - mysql_cond_wait(&condition_variable, &mutex); - thd->exit_cond(old_message); - - Here some explanations: - - thd->enter_cond() is used to register the condition variable and the - mutex in thd->mysys_var. This is done to allow the thread to be - interrupted (killed) from its sleep. Another thread can find the - condition variable to signal and mutex to use for synchronization in - this thread's THD::mysys_var. - - thd->enter_cond() requires the mutex to be acquired in advance. - - thd->exit_cond() unregisters the condition variable and mutex and - releases the mutex. - - If you want to have a Debug Sync point with the wait, please place it - behind enter_cond(). Only then you can safely decide, if the wait will - be taken. Also you will have THD::proc_info correct when the sync - point emits a signal. DEBUG_SYNC sets its own proc_info, but restores - the previous one before releasing its internal mutex. As soon as - another thread sees the signal, it does also see the proc_info from - before entering the sync point. In this case it will be "new_message", - which is associated with the wait that is to be synchronized. - - In the example above, the wait condition is repeated before the sync - point. This is done to skip the sync point, if no wait takes place. - The sync point is before the loop (not inside the loop) to have it hit - once only. It is possible that the condition variable is signaled - multiple times without the wait condition to be true. - - A bit off-topic: At some places, the loop is taken around the whole - synchronization pattern: - - while (!thd->killed && !end_of_wait_condition) - { - mysql_mutex_lock(&mutex); - thd->enter_cond(&condition_variable, &mutex, new_message); - if (!thd->killed [&& !end_of_wait_condition]) - { - [DEBUG_SYNC(thd, "sync_point_name");] - mysql_cond_wait(&condition_variable, &mutex); - } - thd->exit_cond(old_message); - } - - Note that it is important to repeat the test for thd->killed after - enter_cond(). Otherwise the killing thread may kill this thread after - it tested thd->killed in the loop condition and before it registered - the condition variable and mutex in enter_cond(). In this case, the - killing thread does not know that this thread is going to wait on a - condition variable. It would just set THD::killed. But if we would not - test it again, we would go asleep though we are killed. If the killing - thread would kill us when we are after the second test, but still - before sleeping, we hold the mutex, which is registered in mysys_var. - The killing thread would try to acquire the mutex before signaling - the condition variable. Since the mutex is only released implicitly in - mysql_cond_wait(), the signaling happens at the right place. We - have a safe synchronization. - - === Co-work with the DBUG facility === - - When running the MySQL test suite with the --debug-dbug command line - option, the Debug Sync Facility writes trace messages to the DBUG - trace. The following shell commands proved very useful in extracting - relevant information: - - egrep 'query:|debug_sync_exec:' mysql-test/var/log/mysqld.1.trace - - It shows all executed SQL statements and all actions executed by - synchronization points. - - Sometimes it is also useful to see, which synchronization points have - been run through (hit) with or without executing actions. Then add - "|debug_sync_point:" to the egrep pattern. - - === Further reading === - - For a discussion of other methods to synchronize threads see - http://forge.mysql.com/wiki/MySQL_Internals_Test_Synchronization - - For complete syntax tests, functional tests, and examples see the test - case debug_sync.test. - - See also worklog entry WL#4259 - Test Synchronization Facility -*/ +/* see include/mysql/service_debug_sync.h for debug sync documentation */ #include "debug_sync.h" @@ -382,57 +82,16 @@ struct st_debug_sync_globals }; static st_debug_sync_globals debug_sync_global; /* All globals in one object */ -/** - Callback pointer for C files. -*/ -extern "C" void (*debug_sync_C_callback_ptr)(const char *, size_t); +extern uint opt_debug_sync_timeout; /** Callbacks from C files. */ C_MODE_START -static void debug_sync_C_callback(const char *, size_t); +static void debug_sync(THD *thd, const char *sync_point_name, size_t name_len); static int debug_sync_qsort_cmp(const void *, const void *); C_MODE_END -/** - Callback for debug sync, to be used by C files. See thr_lock.c for example. - - @description - - We cannot place a sync point directly in C files (like those in mysys or - certain storage engines written mostly in C like MyISAM or Maria). Because - they are C code and do not include sql_priv.h. So they do not know the - macro DEBUG_SYNC(thd, sync_point_name). The macro needs a 'thd' argument. - Hence it cannot be used in files outside of the sql/ directory. - - The workaround is to call back simple functions like this one from - non-sql/ files. - - We want to allow modules like thr_lock to be used without sql/ and - especially without Debug Sync. So we cannot just do a simple call - of the callback function. Instead we provide a global pointer in - the other file, which is to be set to the callback by Debug Sync. - If the pointer is not set, no call back will be done. If Debug - Sync sets the pointer to a callback function like this one, it will - be called. That way thr_lock.c does not have an undefined reference - to Debug Sync and can be used without it. Debug Sync, in contrast, - has an undefined reference to that pointer and thus requires - thr_lock to be linked too. But this is not a problem as it is part - of the MySQL server anyway. - - @note - The callback pointer in C files is set only if debug sync is - initialized. And this is done only if opt_debug_sync_timeout is set. -*/ - -static void debug_sync_C_callback(const char *sync_point_name, - size_t name_len) -{ - if (unlikely(opt_debug_sync_timeout)) - debug_sync(current_thd, sync_point_name, name_len); -} - #ifdef HAVE_PSI_INTERFACE static PSI_mutex_key key_debug_sync_globals_ds_mutex; @@ -495,7 +154,7 @@ int debug_sync_init(void) DBUG_RETURN(rc); /* purecov: inspected */ /* Set the call back pointer in C files. */ - debug_sync_C_callback_ptr= debug_sync_C_callback; + debug_sync_C_callback_ptr= debug_sync; } DBUG_RETURN(0); @@ -1857,12 +1516,14 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) @param[in] name_len length of sync point name */ -void debug_sync(THD *thd, const char *sync_point_name, size_t name_len) +static void debug_sync(THD *thd, const char *sync_point_name, size_t name_len) { + if (!thd) + thd= current_thd; + st_debug_sync_control *ds_control= thd->debug_sync_control; st_debug_sync_action *action; DBUG_ENTER("debug_sync"); - DBUG_ASSERT(thd); DBUG_ASSERT(sync_point_name); DBUG_ASSERT(name_len); DBUG_ASSERT(ds_control); diff --git a/sql/debug_sync.h b/sql/debug_sync.h index 50881f491fe..4d29d6e7508 100644 --- a/sql/debug_sync.h +++ b/sql/debug_sync.h @@ -32,15 +32,6 @@ class THD; #if defined(ENABLED_DEBUG_SYNC) -/* Macro to be put in the code at synchronization points. */ -#define DEBUG_SYNC(_thd_, _sync_point_name_) \ - do { if (unlikely(opt_debug_sync_timeout)) \ - debug_sync(_thd_, STRING_WITH_LEN(_sync_point_name_)); \ - } while (0) - -/* Command line option --debug-sync-timeout. See mysqld.cc. */ -extern MYSQL_PLUGIN_IMPORT uint opt_debug_sync_timeout; - /* Default WAIT_FOR timeout if command line option is given without argument. */ #define DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT 300 @@ -49,13 +40,8 @@ extern int debug_sync_init(void); extern void debug_sync_end(void); extern void debug_sync_init_thread(THD *thd); extern void debug_sync_end_thread(THD *thd); -extern void debug_sync(THD *thd, const char *sync_point_name, size_t name_len); extern bool debug_sync_set_action(THD *thd, const char *action_str, size_t len); -#else /* defined(ENABLED_DEBUG_SYNC) */ - -#define DEBUG_SYNC(_thd_, _sync_point_name_) /* disabled DEBUG_SYNC */ - #endif /* defined(ENABLED_DEBUG_SYNC) */ #endif /* DEBUG_SYNC_INCLUDED */ diff --git a/sql/field.cc b/sql/field.cc index f5b43c69f63..d913e395b1a 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7860,8 +7860,7 @@ String *Field_set::val_str(String *val_buffer, ulonglong tmp=(ulonglong) Field_enum::val_int(); uint bitnr=0; - val_buffer->length(0); - val_buffer->set_charset(field_charset); + val_buffer->set("", 0, field_charset); while (tmp && bitnr < (uint) typelib->count) { if (tmp & 1) diff --git a/sql/filesort.cc b/sql/filesort.cc index 2ef9a48e6a2..03379f2738a 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2000, 2011, 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 @@ -44,13 +44,11 @@ if (my_b_write((file),(uchar*) (from),param->ref_length)) \ /* functions defined in this file */ -static char **make_char_array(char **old_pos, register uint fields, - uint length, myf my_flag); static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count, uchar *buf); static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select, - uchar * *sort_keys, IO_CACHE *buffer_file, - IO_CACHE *tempfile,IO_CACHE *indexfile); + uchar * *sort_keys, uchar *sort_keys_buf, + IO_CACHE *buffer_file, IO_CACHE *tempfile); static int write_keys(SORTPARAM *param,uchar * *sort_keys, uint count, IO_CACHE *buffer_file, IO_CACHE *tempfile); static void make_sortkey(SORTPARAM *param,uchar *to, uchar *ref_pos); @@ -86,8 +84,6 @@ static void unpack_addon_fields(struct st_sort_addon_field *addon_field, (Needed by UPDATE/INSERT or ALTER TABLE) @param examined_rows Store number of examined rows here - @todo - check why we do this (param.keys--) @note If we sort by position (like if sort_positions is 1) filesort() will call table->prepare_for_position(). @@ -105,12 +101,13 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, bool sort_positions, ha_rows *examined_rows) { int error; - ulong memavl, min_sort_memory; + ulong memory_available= thd->variables.sortbuff_size; + ulong min_sort_memory; uint maxbuffer; BUFFPEK *buffpek; - ha_rows records= HA_POS_ERROR; + ha_rows num_rows= HA_POS_ERROR; uchar **sort_keys= 0; - IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile; + IO_CACHE tempfile, buffpek_pointers, *outfile; SORTPARAM param; bool multi_byte_charset; DBUG_ENTER("filesort"); @@ -183,75 +180,67 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, param.max_rows= max_rows; if (select && select->quick) - { status_var_increment(thd->status_var.filesort_range_count); - } else - { status_var_increment(thd->status_var.filesort_scan_count); - } thd->query_plan_flags|= QPLAN_FILESORT; -#ifdef CAN_TRUST_RANGE - if (select && select->quick && select->quick->records > 0L) - { - records=min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2), - table->file->stats.records)+EXTRA_RECORDS; - selected_records_file=0; - } - else -#endif - { - records= table->file->estimate_rows_upper_bound(); - /* - If number of records is not known, use as much of sort buffer - as possible. - */ - if (records == HA_POS_ERROR) - records--; // we use 'records+1' below. - selected_records_file= 0; - } + + // 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)))) goto err; - memavl= thd->variables.sortbuff_size; - min_sort_memory= max(MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2); - while (memavl >= min_sort_memory) + min_sort_memory= max(MIN_SORT_MEMORY, param.sort_length * MERGEBUFF2); + if (!table_sort.sort_keys) { - ulong old_memavl; - ulong keys= memavl/(param.rec_length+sizeof(char*)); - param.keys=(uint) min(records+1, keys); - if ((table_sort.sort_keys= - (uchar **) make_char_array((char **) table_sort.sort_keys, - param.keys, param.rec_length, MYF(0)))) - break; - old_memavl=memavl; - if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory) - memavl= min_sort_memory; + while (memory_available >= min_sort_memory) + { + ulong keys= memory_available / (param.rec_length + sizeof(char*)); + table_sort.keys= (uint) min(num_rows, keys); + + DBUG_EXECUTE_IF("make_sort_keys_alloc_fail", + DBUG_SET("+d,simulate_out_of_memory");); + + if ((table_sort.sort_keys= + (uchar**) my_malloc(table_sort.keys*(param.rec_length+sizeof(char*)), + MYF(0)))) + break; + ulong old_memory_available= memory_available; + memory_available= memory_available/4*3; + if (memory_available < min_sort_memory && + old_memory_available > min_sort_memory) + memory_available= min_sort_memory; + } } + sort_keys= table_sort.sort_keys; - if (memavl < min_sort_memory) + param.keys= table_sort.keys; + if (memory_available < min_sort_memory) { - my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG)); + my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR + ME_FATALERROR)); goto err; } if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(ME_ERROR | MY_WME))) goto err; - param.keys--; /* TODO: check why we do this */ param.sort_form= table; param.end=(param.local_sortorder=sortorder)+s_length; - if ((records=find_all_keys(¶m,select,sort_keys, &buffpek_pointers, - &tempfile, selected_records_file)) == - HA_POS_ERROR) + num_rows= find_all_keys(¶m, + select, + sort_keys, + (uchar *)(sort_keys+param.keys), + &buffpek_pointers, + &tempfile); + if (num_rows == HA_POS_ERROR) goto err; maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek)); if (maxbuffer == 0) // The whole set is in memory { - if (save_index(¶m,sort_keys,(uint) records, &table_sort)) + if (save_index(¶m,sort_keys,(uint) num_rows, &table_sort)) goto err; } else @@ -285,8 +274,9 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, Use also the space previously used by string pointers in sort_buffer for temporary key storage. */ - param.keys=((param.keys*(param.rec_length+sizeof(char*))) / - param.rec_length-1); + param.keys=((param.keys * + (param.rec_length+sizeof(char*))) / + param.rec_length - 1); maxbuffer--; // Offset from 0 if (merge_many_buff(¶m,(uchar*) sort_keys,buffpek,&maxbuffer, &tempfile)) @@ -294,13 +284,21 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, if (flush_io_cache(&tempfile) || reinit_io_cache(&tempfile,READ_CACHE,0L,0,0)) goto err; - if (merge_index(¶m,(uchar*) sort_keys,buffpek,maxbuffer,&tempfile, + if (merge_index(¶m, + (uchar*) sort_keys, + buffpek, + maxbuffer, + &tempfile, outfile)) goto err; } - if (records > param.max_rows) - records=param.max_rows; - error =0; + + if (num_rows > param.max_rows) + { + // If find_all_keys() produced more results than the query LIMIT. + num_rows= param.max_rows; + } + error= 0; err: my_free(param.tmp_buffer); @@ -349,15 +347,15 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, } else statistic_add(thd->status_var.filesort_rows, - (ulong) records, &LOCK_status); + (ulong) num_rows, &LOCK_status); *examined_rows= param.examined_rows; #ifdef SKIP_DBUG_IN_FILESORT DBUG_POP(); /* Ok to DBUG */ #endif memcpy(&table->sort, &table_sort, sizeof(FILESORT_INFO)); - DBUG_PRINT("exit",("records: %ld", (long) records)); - MYSQL_FILESORT_DONE(error, records); - DBUG_RETURN(error ? HA_POS_ERROR : records); + DBUG_PRINT("exit",("num_rows: %ld", (long) num_rows)); + MYSQL_FILESORT_DONE(error, num_rows); + DBUG_RETURN(error ? HA_POS_ERROR : num_rows); } /* filesort */ @@ -381,29 +379,6 @@ void filesort_free_buffers(TABLE *table, bool full) table->sort.addon_field= NULL; } -/** Make a array of string pointers. */ - -static char **make_char_array(char **old_pos, register uint fields, - uint length, myf my_flag) -{ - register char **pos; - char *char_pos; - DBUG_ENTER("make_char_array"); - - DBUG_EXECUTE_IF("make_char_array_fail", - DBUG_SET("+d,simulate_out_of_memory");); - - if (old_pos || - (old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)), - my_flag))) - { - pos=old_pos; char_pos=((char*) (pos+fields)) -length; - while (fields--) *(pos++) = (char_pos+= length); - } - - DBUG_RETURN(old_pos); -} /* make_char_array */ - /** Read 'count' number of buffer pointers into memory. */ @@ -490,7 +465,6 @@ static void dbug_print_record(TABLE *table, bool print_rowid) @param buffpek_pointers File to write BUFFPEKs describing sorted segments in tempfile. @param tempfile File to write sorted sequences of sortkeys to. - @param indexfile If !NULL, use it for source data (contains rowids) @note Basic idea: @@ -518,9 +492,9 @@ static void dbug_print_record(TABLE *table, bool print_rowid) */ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, - uchar **sort_keys, + uchar **sort_keys, uchar *sort_keys_buf, IO_CACHE *buffpek_pointers, - IO_CACHE *tempfile, IO_CACHE *indexfile) + IO_CACHE *tempfile) { int error,flag,quick_select; uint idx,indexpos,ref_length; @@ -531,6 +505,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, volatile killed_state *killed= &thd->killed; handler *file; MY_BITMAP *save_read_set, *save_write_set, *save_vcol_set; + uchar *next_sort_key= sort_keys_buf; DBUG_ENTER("find_all_keys"); DBUG_PRINT("info",("using: %s", (select ? select->quick ? "ranges" : "where": @@ -544,12 +519,11 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, ref_pos= ref_buff; quick_select=select && select->quick; record=0; - flag= ((!indexfile && (file->ha_table_flags() & HA_REC_NOT_IN_SEQ)) - || quick_select); - if (indexfile || flag) + flag= ((file->ha_table_flags() & HA_REC_NOT_IN_SEQ) || quick_select); + if (flag) ref_pos= &file->ref[0]; next_pos=ref_pos; - if (! indexfile && ! quick_select) + if (!quick_select) { next_pos=(uchar*) 0; /* Find records in sequence */ if (file->ha_rnd_init_with_error(1)) @@ -589,26 +563,16 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, { if ((error= select->quick->get_next())) break; - if (!error) + if (!error && sort_form->vfield) update_virtual_fields(thd, sort_form); file->position(sort_form->record[0]); DBUG_EXECUTE_IF("debug_filesort", dbug_print_record(sort_form, TRUE);); } else /* Not quick-select */ { - if (indexfile) { - if (my_b_read(indexfile,(uchar*) ref_pos,ref_length)) /* purecov: deadcode */ - { - error= my_errno ? my_errno : -1; /* Abort */ - break; - } - error=file->ha_rnd_pos(sort_form->record[0],next_pos); - } - else - { - error=file->ha_rnd_next(sort_form->record[0]); - if (!error) + error= file->ha_rnd_next(sort_form->record[0]); + if (!error && sort_form->vfield) update_virtual_fields(thd, sort_form); if (!flag) { @@ -625,7 +589,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, if (*killed) { DBUG_PRINT("info",("Sort killed by user")); - if (!indexfile && !quick_select) + if (!quick_select) { (void) file->extra(HA_EXTRA_NO_CACHE); file->ha_rnd_end(); @@ -669,12 +633,16 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, { if (idx == param->keys) { - if (write_keys(param,sort_keys,idx,buffpek_pointers,tempfile)) + if (write_keys(param, sort_keys, + idx, buffpek_pointers, tempfile)) DBUG_RETURN(HA_POS_ERROR); - idx=0; + idx= 0; + next_sort_key= sort_keys_buf; indexpos++; } - make_sortkey(param,sort_keys[idx++],ref_pos); + sort_keys[idx++]= next_sort_key; + make_sortkey(param, next_sort_key, ref_pos); + next_sort_key+= param->rec_length; } else file->unlock_row(); @@ -699,15 +667,17 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos)); if (error != HA_ERR_END_OF_FILE) { - file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */ + file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); // purecov: inspected DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ } if (indexpos && idx && - write_keys(param,sort_keys,idx,buffpek_pointers,tempfile)) + write_keys(param, sort_keys, + idx, buffpek_pointers, tempfile)) DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */ - DBUG_RETURN(my_b_inited(tempfile) ? - (ha_rows) (my_b_tell(tempfile)/param->rec_length) : - idx); + const ha_rows retval= + my_b_inited(tempfile) ? + (ha_rows) (my_b_tell(tempfile)/param->rec_length) : idx; + DBUG_RETURN(retval); } /* find_all_keys */ @@ -1310,8 +1280,9 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, { buffpek->base= strpos; buffpek->max_keys= maxcount; - strpos+= (uint) (error= (int) read_to_buffer(from_file, buffpek, - rec_length)); + strpos+= + (uint) (error= (int) read_to_buffer(from_file, buffpek, rec_length)); + if (error == -1) goto err; /* purecov: inspected */ buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index f3c9553f524..70e1e9dc7cf 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -1,8 +1,7 @@ #ifndef HA_NDBCLUSTER_INCLUDED #define HA_NDBCLUSTER_INCLUDED -/* Copyright (c) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc. - Use is subject to license terms. +/* Copyright (c) 2000, 2010, 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 diff --git a/sql/ha_ndbcluster_binlog.h b/sql/ha_ndbcluster_binlog.h index 1cc20c954cb..a02f687d76f 100644 --- a/sql/ha_ndbcluster_binlog.h +++ b/sql/ha_ndbcluster_binlog.h @@ -1,8 +1,7 @@ #ifndef HA_NDBCLUSTER_BINLOG_INCLUDED #define HA_NDBCLUSTER_BINLOG_INCLUDED -/* Copyright (c) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc. - Use is subject to license terms. +/* Copyright (c) 2000, 2010, 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 diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 36d5da94b11..b4181fc6d7f 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2011, Oracle and/or its affiliates. + Copyright (c) 2005, 2012, 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 @@ -289,6 +289,7 @@ void ha_partition::init_handler_variables() m_is_sub_partitioned= 0; m_is_clone_of= NULL; m_clone_mem_root= NULL; + m_part_ids_sorted_by_num_of_records= NULL; #ifdef DONT_HAVE_TO_BE_INITALIZED m_start_key.flag= 0; @@ -325,6 +326,7 @@ ha_partition::~ha_partition() } my_free(m_ordered_rec_buffer); m_ordered_rec_buffer= NULL; + my_free(m_part_ids_sorted_by_num_of_records); clear_handler_file(); @@ -1259,7 +1261,7 @@ bool ha_partition::check_and_repair(THD *thd) @retval FALSE Cannot be auto repaired */ -bool ha_partition::auto_repair() const +bool ha_partition::auto_repair(int error) const { DBUG_ENTER("ha_partition::auto_repair"); @@ -1267,7 +1269,7 @@ bool ha_partition::auto_repair() const As long as we only support one storage engine per table, we can use the first partition for this function. */ - DBUG_RETURN(m_file[0]->auto_repair()); + DBUG_RETURN(m_file[0]->auto_repair(error)); } @@ -2741,6 +2743,16 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) m_start_key.key= (const uchar*)ptr; } } + if (!m_part_ids_sorted_by_num_of_records) + { + if (!(m_part_ids_sorted_by_num_of_records= + (uint32*) my_malloc(m_tot_parts * sizeof(uint32), MYF(MY_WME)))) + DBUG_RETURN(error); + uint32 i; + /* Initialize it with all partition ids. */ + for (i= 0; i < m_tot_parts; i++) + m_part_ids_sorted_by_num_of_records[i]= i; + } /* Initialize the bitmap we use to minimize ha_start_bulk_insert calls */ if (bitmap_init(&m_bulk_insert_started, NULL, m_tot_parts + 1, FALSE)) @@ -3670,14 +3682,14 @@ int ha_partition::truncate_partition(Alter_info *alter_info, bool *binlog_stmt) uint num_parts= m_part_info->num_parts; uint num_subparts= m_part_info->num_subparts; uint i= 0; - uint num_parts_set= alter_info->partition_names.elements; - uint num_parts_found= set_part_state(alter_info, m_part_info, - PART_ADMIN); DBUG_ENTER("ha_partition::truncate_partition"); /* Only binlog when it starts any call to the partitions handlers */ *binlog_stmt= false; + if (set_part_state(alter_info, m_part_info, PART_ADMIN)) + DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); + /* TRUNCATE also means resetting auto_increment. Hence, reset it so that it will be initialized again at the next use. @@ -3687,10 +3699,6 @@ int ha_partition::truncate_partition(Alter_info *alter_info, bool *binlog_stmt) table_share->ha_part_data->auto_inc_initialized= FALSE; unlock_auto_increment(); - if (num_parts_set != num_parts_found && - (!(alter_info->flags & ALTER_ALL_PARTITION))) - DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); - *binlog_stmt= true; do @@ -5318,6 +5326,24 @@ int ha_partition::handle_ordered_prev(uchar *buf) and read_time calls */ +/** + Helper function for sorting according to number of rows in descending order. +*/ + +int ha_partition::compare_number_of_records(ha_partition *me, + const uint32 *a, + const uint32 *b) +{ + handler **file= me->m_file; + /* Note: sorting in descending order! */ + if (file[*a]->stats.records > file[*b]->stats.records) + return -1; + if (file[*a]->stats.records < file[*b]->stats.records) + return 1; + return 0; +} + + /* General method to gather info from handler @@ -5562,6 +5588,15 @@ int ha_partition::info(uint flag) } i++; } while (*(++file_array)); + /* + Sort the array of part_ids by number of records in + in descending order. + */ + my_qsort2((void*) m_part_ids_sorted_by_num_of_records, + m_tot_parts, + sizeof(uint32), + (qsort2_cmp) compare_number_of_records, + this); file= m_file[handler_instance]; file->info(HA_STATUS_CONST | no_lock_flag); @@ -6099,7 +6134,7 @@ int ha_partition::extra(enum ha_extra_function operation) 0 Success DESCRIPTION - Called at end of each statement to reste buffers + Called at end of each statement to reset buffers */ int ha_partition::reset(void) @@ -6317,21 +6352,73 @@ const key_map *ha_partition::keys_to_use_for_scanning() DBUG_RETURN(m_file[0]->keys_to_use_for_scanning()); } -#define MAX_PARTS_FOR_OPTIMIZER_CALLS 10 -/* - Prepare start variables for estimating optimizer costs. - @param[out] num_used_parts Number of partitions after pruning. - @param[out] check_min_num Number of partitions to call. - @param[out] first first used partition. +/** + Minimum number of rows to base optimizer estimate on. */ -void ha_partition::partitions_optimizer_call_preparations(uint *first, - uint *num_used_parts, - uint *check_min_num) + +ha_rows ha_partition::min_rows_for_estimate() { - *first= bitmap_get_first_set(&(m_part_info->used_partitions)); - *num_used_parts= bitmap_bits_set(&(m_part_info->used_partitions)); - *check_min_num= min(MAX_PARTS_FOR_OPTIMIZER_CALLS, *num_used_parts); + uint i, max_used_partitions, tot_used_partitions; + DBUG_ENTER("ha_partition::min_rows_for_estimate"); + + tot_used_partitions= bitmap_bits_set(&m_part_info->used_partitions); + DBUG_ASSERT(tot_used_partitions); + + /* + Allow O(log2(tot_partitions)) increase in number of used partitions. + This gives O(tot_rows/log2(tot_partitions)) rows to base the estimate on. + I.e when the total number of partitions doubles, allow one more + partition to be checked. + */ + i= 2; + max_used_partitions= 1; + while (i < m_tot_parts) + { + max_used_partitions++; + i= i << 1; + } + if (max_used_partitions > tot_used_partitions) + max_used_partitions= tot_used_partitions; + + /* stats.records is already updated by the info(HA_STATUS_VARIABLE) call. */ + DBUG_PRINT("info", ("max_used_partitions: %u tot_rows: %lu", + max_used_partitions, + (ulong) stats.records)); + DBUG_PRINT("info", ("tot_used_partitions: %u min_rows_to_check: %lu", + tot_used_partitions, + (ulong) stats.records * max_used_partitions + / tot_used_partitions)); + DBUG_RETURN(stats.records * max_used_partitions / tot_used_partitions); +} + + +/** + Get the biggest used partition. + + Starting at the N:th biggest partition and skips all non used + partitions, returning the biggest used partition found + + @param[in,out] part_index Skip the *part_index biggest partitions + + @return The biggest used partition with index not lower than *part_index. + @retval NO_CURRENT_PART_ID No more partition used. + @retval != NO_CURRENT_PART_ID partition id of biggest used partition with + index >= *part_index supplied. Note that + *part_index will be updated to the next + partition index to use. +*/ + +uint ha_partition::get_biggest_used_partition(uint *part_index) +{ + uint part_id; + while ((*part_index) < m_tot_parts) + { + part_id= m_part_ids_sorted_by_num_of_records[(*part_index)++]; + if (bitmap_is_set(&m_part_info->used_partitions, part_id)) + return part_id; + } + return NO_CURRENT_PART_ID; } @@ -6347,115 +6434,107 @@ void ha_partition::partitions_optimizer_call_preparations(uint *first, double ha_partition::scan_time() { - double scan_time= 0.0; - uint first, part_id, num_used_parts, check_min_num, partitions_called= 0; + double scan_time= 0; + handler **file; DBUG_ENTER("ha_partition::scan_time"); - partitions_optimizer_call_preparations(&first, &num_used_parts, &check_min_num); - for (part_id= first; partitions_called < num_used_parts ; part_id++) - { - if (!bitmap_is_set(&(m_part_info->used_partitions), part_id)) - continue; - scan_time+= m_file[part_id]->scan_time(); - partitions_called++; - if (partitions_called >= check_min_num && scan_time != 0.0) - { - DBUG_RETURN(scan_time * - (double) num_used_parts / (double) partitions_called); - } - } + for (file= m_file; *file; file++) + if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file))) + scan_time+= (*file)->scan_time(); DBUG_RETURN(scan_time); } -/* - Estimate rows for records_in_range or estimate_rows_upper_bound. +/** + Find number of records in a range. + @param inx Index number + @param min_key Start of range + @param max_key End of range - @param is_records_in_range call records_in_range instead of - estimate_rows_upper_bound. - @param inx (only for records_in_range) index to use. - @param min_key (only for records_in_range) start of range. - @param max_key (only for records_in_range) end of range. + @return Number of rows in range. - @return Number of rows or HA_POS_ERROR. + Given a starting key, and an ending key estimate the number of rows that + will exist between the two. max_key may be empty which in case determine + if start_key matches any rows. */ -ha_rows ha_partition::estimate_rows(bool is_records_in_range, uint inx, - key_range *min_key, key_range *max_key) + +ha_rows ha_partition::records_in_range(uint inx, key_range *min_key, + key_range *max_key) { - ha_rows rows, estimated_rows= 0; - uint first, part_id, num_used_parts, check_min_num, partitions_called= 0; + ha_rows min_rows_to_check, rows, estimated_rows=0, checked_rows= 0; + uint partition_index= 0, part_id; DBUG_ENTER("ha_partition::records_in_range"); - partitions_optimizer_call_preparations(&first, &num_used_parts, &check_min_num); - for (part_id= first; partitions_called < num_used_parts ; part_id++) + min_rows_to_check= min_rows_for_estimate(); + + while ((part_id= get_biggest_used_partition(&partition_index)) + != NO_CURRENT_PART_ID) { - if (!bitmap_is_set(&(m_part_info->used_partitions), part_id)) - continue; - if (is_records_in_range) - rows= m_file[part_id]->records_in_range(inx, min_key, max_key); - else - rows= m_file[part_id]->estimate_rows_upper_bound(); + rows= m_file[part_id]->records_in_range(inx, min_key, max_key); + + DBUG_PRINT("info", ("part %u match %lu rows of %lu", part_id, (ulong) rows, + (ulong) m_file[part_id]->stats.records)); + if (rows == HA_POS_ERROR) DBUG_RETURN(HA_POS_ERROR); estimated_rows+= rows; - partitions_called++; - if (partitions_called >= check_min_num && estimated_rows) + checked_rows+= m_file[part_id]->stats.records; + /* + Returning 0 means no rows can be found, so we must continue + this loop as long as we have estimated_rows == 0. + Also many engines return 1 to indicate that there may exist + a matching row, we do not normalize this by dividing by number of + used partitions, but leave it to be returned as a sum, which will + reflect that we will need to scan each partition's index. + + Note that this statistics may not always be correct, so we must + continue even if the current partition has 0 rows, since we might have + deleted rows from the current partition, or inserted to the next + partition. + */ + if (estimated_rows && checked_rows && + checked_rows >= min_rows_to_check) { - DBUG_RETURN(estimated_rows * num_used_parts / partitions_called); + DBUG_PRINT("info", + ("records_in_range(inx %u): %lu (%lu * %lu / %lu)", + inx, + (ulong) (estimated_rows * stats.records / checked_rows), + (ulong) estimated_rows, + (ulong) stats.records, + (ulong) checked_rows)); + DBUG_RETURN(estimated_rows * stats.records / checked_rows); } } + DBUG_PRINT("info", ("records_in_range(inx %u): %lu", + inx, + (ulong) estimated_rows)); DBUG_RETURN(estimated_rows); } -/* - Find number of records in a range - - SYNOPSIS - records_in_range() - inx Index number - min_key Start of range - max_key End of range - - RETURN VALUE - Number of rows in range - - DESCRIPTION - Given a starting key, and an ending key estimate the number of rows that - will exist between the two. end_key may be empty which in case determine - if start_key matches any rows. - - Called from opt_range.cc by check_quick_keys(). - - monty: MUST be called for each range and added. - Note that MySQL will assume that if this returns 0 there is no - matching rows for the range! -*/ - -ha_rows ha_partition::records_in_range(uint inx, key_range *min_key, - key_range *max_key) -{ - DBUG_ENTER("ha_partition::records_in_range"); - - DBUG_RETURN(estimate_rows(TRUE, inx, min_key, max_key)); -} - - -/* - Estimate upper bound of number of rows - - SYNOPSIS - estimate_rows_upper_bound() +/** + Estimate upper bound of number of rows. - RETURN VALUE - Number of rows + @return Number of rows. */ ha_rows ha_partition::estimate_rows_upper_bound() { + ha_rows rows, tot_rows= 0; + handler **file= m_file; DBUG_ENTER("ha_partition::estimate_rows_upper_bound"); - DBUG_RETURN(estimate_rows(FALSE, 0, NULL, NULL)); + do + { + if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file))) + { + rows= (*file)->estimate_rows_upper_bound(); + if (rows == HA_POS_ERROR) + DBUG_RETURN(HA_POS_ERROR); + tot_rows+= rows; + } + } while (*(++file)); + DBUG_RETURN(tot_rows); } diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 8723682904a..aa9179f9f69 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -2,7 +2,7 @@ #define HA_PARTITION_INCLUDED /* - Copyright (c) 2005, 2011, Oracle and/or its affiliates. + Copyright (c) 2005, 2012, 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 @@ -176,6 +176,12 @@ private: ha_rows m_bulk_inserted_rows; /** used for prediction of start_bulk_insert rows */ enum_monotonicity_info m_part_func_monotonicity_info; + /** Sorted array of partition ids in descending order of number of rows. */ + uint32 *m_part_ids_sorted_by_num_of_records; + /* Compare function for my_qsort2, for reversed order. */ + static int compare_number_of_records(ha_partition *me, + const uint32 *a, + const uint32 *b); public: handler *clone(const char *name, MEM_ROOT *mem_root); virtual void set_part_info(partition_info *part_info) @@ -196,9 +202,9 @@ public: */ ha_partition(handlerton *hton, TABLE_SHARE * table); ha_partition(handlerton *hton, partition_info * part_info); - ha_partition(handlerton *hton, TABLE_SHARE *share,
- partition_info *part_info_arg,
- ha_partition *clone_arg,
+ ha_partition(handlerton *hton, TABLE_SHARE *share, + partition_info *part_info_arg, + ha_partition *clone_arg, MEM_ROOT *clone_mem_root_arg); ~ha_partition(); /* @@ -538,6 +544,20 @@ public: virtual int extra(enum ha_extra_function operation); virtual int extra_opt(enum ha_extra_function operation, ulong cachesize); virtual int reset(void); + /* + Do not allow caching of partitioned tables, since we cannot return + a callback or engine_data that would work for a generic engine. + */ + virtual my_bool register_query_cache_table(THD *thd, char *table_key, + uint key_length, + qc_engine_callback + *engine_callback, + ulonglong *engine_data) + { + *engine_callback= NULL; + *engine_data= 0; + return FALSE; + } private: static const uint NO_CURRENT_PART_ID; @@ -567,15 +587,9 @@ public: */ private: - /* - Helper function to get the minimum number of partitions to use for - the optimizer hints/cost calls. - */ - void partitions_optimizer_call_preparations(uint *num_used_parts, - uint *check_min_num, - uint *first); - ha_rows estimate_rows(bool is_records_in_range, uint inx, - key_range *min_key, key_range *max_key); + /* Helper functions for optimizer hints. */ + ha_rows min_rows_for_estimate(); + uint get_biggest_used_partition(uint *part_index); public: /* @@ -1085,7 +1099,7 @@ public: virtual int check(THD* thd, HA_CHECK_OPT *check_opt); virtual int repair(THD* thd, HA_CHECK_OPT *check_opt); virtual bool check_and_repair(THD *thd); - virtual bool auto_repair() const; + virtual bool auto_repair(int error) const; virtual bool is_crashed() const; private: diff --git a/sql/handler.cc b/sql/handler.cc index c04759b196f..861a63ec88a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1188,7 +1188,7 @@ int ha_commit_trans(THD *thd, bool all) } #ifdef WITH_ARIA_STORAGE_ENGINE - ha_maria::implicit_commit(thd, FALSE); + ha_maria::implicit_commit(thd, TRUE); #endif if (!ha_info) diff --git a/sql/handler.h b/sql/handler.h index 4ac7202587e..e41d325a68f 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2451,7 +2451,7 @@ public: virtual uint checksum() const { return 0; } virtual bool is_crashed() const { return 0; } - virtual bool auto_repair() const { return 0; } + virtual bool auto_repair(int error) const { return 0; } void update_global_table_stats(); void update_global_index_stats(); diff --git a/sql/item.cc b/sql/item.cc index c4bb1a399ab..f9032c79c12 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2000, 2012, Oracle and/or its affiliates. Copyright (c) 2010, 2012, Monty Program Ab This program is free software; you can redistribute it and/or modify @@ -1001,6 +1001,21 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs) } +void Item::set_name_for_rollback(THD *thd, const char *str, uint length, + CHARSET_INFO *cs) +{ + char *old_name, *new_name; + old_name= name; + set_name(str, length, cs); + new_name= name; + if (old_name != new_name) + { + name= old_name; + thd->change_item_tree((Item **) &name, (Item *) new_name); + } +} + + /** @details This function is called when: @@ -2606,17 +2621,20 @@ void Item_field::fix_after_pullout(st_select_lex *new_parent, Item **ref) { if (new_parent == get_depended_from()) depended_from= NULL; - Name_resolution_context *ctx= new Name_resolution_context(); - ctx->outer_context= NULL; // We don't build a complete name resolver - ctx->table_list= NULL; // We rely on first_name_resolution_table instead - ctx->select_lex= new_parent; - ctx->first_name_resolution_table= context->first_name_resolution_table; - ctx->last_name_resolution_table= context->last_name_resolution_table; - ctx->error_processor= context->error_processor; - ctx->error_processor_data= context->error_processor_data; - ctx->resolve_in_select_list= context->resolve_in_select_list; - ctx->security_ctx= context->security_ctx; - this->context=ctx; + if (context) + { + Name_resolution_context *ctx= new Name_resolution_context(); + ctx->outer_context= NULL; // We don't build a complete name resolver + ctx->table_list= NULL; // We rely on first_name_resolution_table instead + ctx->select_lex= new_parent; + ctx->first_name_resolution_table= context->first_name_resolution_table; + ctx->last_name_resolution_table= context->last_name_resolution_table; + ctx->error_processor= context->error_processor; + ctx->error_processor_data= context->error_processor_data; + ctx->resolve_in_select_list= context->resolve_in_select_list; + ctx->security_ctx= context->security_ctx; + this->context=ctx; + } } @@ -3557,7 +3575,7 @@ String *Item_param::val_str(String* str) that binary log contains wrong statement */ -const String *Item_param::query_val_str(String* str) const +const String *Item_param::query_val_str(THD *thd, String* str) const { switch (state) { case INT_VALUE: @@ -3595,7 +3613,8 @@ const String *Item_param::query_val_str(String* str) const case LONG_DATA_VALUE: { str->length(0); - append_query_string(value.cs_info.character_set_client, &str_value, str); + append_query_string(thd, value.cs_info.character_set_client, &str_value, + str); break; } case NULL_VALUE: @@ -3728,7 +3747,7 @@ void Item_param::print(String *str, enum_query_type query_type) char buffer[STRING_BUFFER_USUAL_SIZE]; String tmp(buffer, sizeof(buffer), &my_charset_bin); const String *res; - res= query_val_str(&tmp); + res= query_val_str(current_thd, &tmp); str->append(*res); } } diff --git a/sql/item.h b/sql/item.h index cf13f501c69..b3801e6c488 100644 --- a/sql/item.h +++ b/sql/item.h @@ -656,6 +656,8 @@ public: #endif } /*lint -e1509 */ void set_name(const char *str, uint length, CHARSET_INFO *cs); + void set_name_for_rollback(THD *thd, const char *str, uint length, + CHARSET_INFO *cs); void rename(char *new_name); void init_make_field(Send_field *tmp_field,enum enum_field_types type); virtual void cleanup(); @@ -2258,7 +2260,7 @@ public: */ void (*set_param_func)(Item_param *param, uchar **pos, ulong len); - const String *query_val_str(String *str) const; + const String *query_val_str(THD *thd, String *str) const; bool convert_str_value(THD *thd); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f5dc74c389c..d3251bc1fb3 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5463,7 +5463,7 @@ Item *Item_bool_rowready_func2::negated_item() */ Item_equal::Item_equal(Item *f1, Item *f2, bool with_const_item) - : Item_bool_func(), eval_item(0), cond_false(0) + : Item_bool_func(), eval_item(0), cond_false(0), context_field(NULL) { const_item_cache= 0; with_const= with_const_item; @@ -5486,7 +5486,7 @@ Item_equal::Item_equal(Item *f1, Item *f2, bool with_const_item) */ Item_equal::Item_equal(Item_equal *item_equal) - : Item_bool_func(), eval_item(0), cond_false(0) + : Item_bool_func(), eval_item(0), cond_false(0), context_field(NULL) { const_item_cache= 0; List_iterator_fast<Item> li(item_equal->equal_items); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 384c91d5d2e..5558b77d67d 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, 2010, Oracle and/or its affiliates. - Copyright (c) 2009-2011, Monty Program Ab +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2009, 2011, 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 @@ -249,7 +249,7 @@ public: Item_in_optimizer(Item *a, Item_in_subselect *b): Item_bool_func(a, reinterpret_cast<Item *>(b)), cache(0), expr_cache(0), save_cache(0), result_for_null_param(UNKNOWN) - {} + { with_subselect= true; } bool fix_fields(THD *, Item **); bool fix_left(THD *thd, Item **ref); bool is_null(); @@ -1693,9 +1693,16 @@ class Item_equal: public Item_bool_func as datetimes. The comparator is used only if compare_as_dates=TRUE */ Arg_comparator cmp; + + /* + For Item_equal objects inside an OR clause: one of the fields that were + used in the original equality. + */ + Item_field *context_field; public: inline Item_equal() - : Item_bool_func(), with_const(FALSE), eval_item(0), cond_false(0) + : Item_bool_func(), with_const(FALSE), eval_item(0), cond_false(0), + context_field(NULL) { const_item_cache=0 ;} Item_equal(Item *f1, Item *f2, bool with_const_item); Item_equal(Item_equal *item_equal); @@ -1722,6 +1729,8 @@ public: Item *transform(Item_transformer transformer, uchar *arg); virtual void print(String *str, enum_query_type query_type); CHARSET_INFO *compare_collation(); + + void set_context_field(Item_field *ctx_field) { context_field= ctx_field; } friend class Item_equal_fields_iterator; friend Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, Item_equal *item_equal); diff --git a/sql/item_func.cc b/sql/item_func.cc index c56909d4335..b9bab372500 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -6745,7 +6745,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref) if (res) DBUG_RETURN(res); - if (thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW) + if (thd->lex->is_view_context_analysis()) { /* Here we check privileges of the stored routine only during view diff --git a/sql/item_func.h b/sql/item_func.h index f5c43360ee8..3b1a38cf447 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -150,7 +150,7 @@ public: void count_only_length(); void count_real_length(); void count_decimal_length(); - inline bool get_arg0_date(MYSQL_TIME *ltime, uint fuzzy_date) + inline bool get_arg0_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) { return (null_value=args[0]->get_date(ltime, fuzzy_date)); } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index d5f85e7ff5d..b1829c1892a 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -2508,7 +2508,7 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref) } } - if ((thd_arg->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW) && + if (thd_arg->lex->is_view_context_analysis() && left_expr && !left_expr->fixed && left_expr->fix_fields(thd_arg, &left_expr)) return TRUE; @@ -2531,7 +2531,8 @@ void Item_in_subselect::update_used_tables() { Item_subselect::update_used_tables(); left_expr->update_used_tables(); - used_tables_cache |= left_expr->used_tables(); + //used_tables_cache |= left_expr->used_tables(); + used_tables_cache= Item_subselect::used_tables() | left_expr->used_tables(); } diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 80914f499fe..857d9bc2080 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2009-2011, Monty Program Ab + Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2009, 2011, 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 @@ -2435,7 +2435,7 @@ bool Item_time_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) bool Item_date_typecast::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) { - if (get_arg0_date(ltime, TIME_FUZZY_DATE)) + if (get_arg0_date(ltime, fuzzy_date & ~TIME_TIME_ONLY)) return 1; ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0; @@ -3145,7 +3145,7 @@ bool Item_func_str_to_date::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) bool Item_func_last_day::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) { - if (get_arg0_date(ltime, fuzzy_date & ~TIME_FUZZY_DATE) || + if (get_arg0_date(ltime, fuzzy_date) || (ltime->month == 0)) return (null_value=1); uint month_idx= ltime->month-1; diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 150c2c212d7..0fa2d39aea9 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -1,5 +1,4 @@ -/* - Copyright (c) 2005, 2010, Oracle and/or its affiliates. +/* Copyright (c) 2005, 2011, 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 diff --git a/sql/lock.cc b/sql/lock.cc index bbaa51dbbae..7ae3b23ff24 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -413,7 +413,7 @@ void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count) { MYSQL_LOCK *sql_lock; if ((sql_lock= get_lock_data(thd, table, count, GET_LOCK_UNLOCK))) - mysql_unlock_tables(thd, sql_lock); + mysql_unlock_tables(thd, sql_lock, 1); } diff --git a/sql/log.cc b/sql/log.cc index ee7d548d81a..2ef6463aa81 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3873,8 +3873,6 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included) mysql_mutex_lock(&rli->log_space_lock); rli->relay_log.purge_logs(to_purge_if_included, included, 0, 0, &rli->log_space_total); - // Tell the I/O thread to take the relay_log_space_limit into account - rli->ignore_log_space_limit= 0; mysql_mutex_unlock(&rli->log_space_lock); /* diff --git a/sql/log_event.cc b/sql/log_event.cc index 05340fff03a..e02cfc6d20c 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -632,7 +632,7 @@ char *str_to_hex(char *to, const char *from, uint len) */ int -append_query_string(CHARSET_INFO *csinfo, +append_query_string(THD *thd, CHARSET_INFO *csinfo, String const *from, String *to) { char *beg, *ptr; @@ -647,9 +647,26 @@ append_query_string(CHARSET_INFO *csinfo, else { *ptr++= '\''; - ptr+= escape_string_for_mysql(csinfo, ptr, 0, - from->ptr(), from->length()); - *ptr++='\''; + if (!(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)) + { + ptr+= escape_string_for_mysql(csinfo, ptr, 0, + from->ptr(), from->length()); + } + else + { + const char *frm_str= from->ptr(); + + for (; frm_str < (from->ptr() + from->length()); frm_str++) + { + /* Using '' way to represent "'" */ + if (*frm_str == '\'') + *ptr++= *frm_str; + + *ptr++= *frm_str; + } + } + + *ptr++= '\''; } to->length(orig_len + ptr - beg); return 0; diff --git a/sql/log_event.h b/sql/log_event.h index de9cd65514c..78dccb3cac1 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1,5 +1,4 @@ -/* - Copyright (c) 2000, 2010, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2012, 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 @@ -4261,7 +4260,7 @@ private: }; #endif -int append_query_string(CHARSET_INFO *csinfo, +int append_query_string(THD *thd, CHARSET_INFO *csinfo, String const *from, String *to); bool rpl_get_position_info(const char **log_file_name, ulonglong *log_pos, diff --git a/sql/mem_root_array.h b/sql/mem_root_array.h new file mode 100644 index 00000000000..5ce4dcb584d --- /dev/null +++ b/sql/mem_root_array.h @@ -0,0 +1,175 @@ +/* Copyright (c) 2011, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#ifndef MEM_ROOT_ARRAY_INCLUDED +#define MEM_ROOT_ARRAY_INCLUDED + +#include <my_alloc.h> + +/** + A typesafe replacement for DYNAMIC_ARRAY. + We use MEM_ROOT for allocating storage, rather than the C++ heap. + The interface is chosen to be similar to std::vector. + + @remark + Unlike DYNAMIC_ARRAY, elements are properly copied + (rather than memcpy()d) if the underlying array needs to be expanded. + + @remark + Depending on has_trivial_destructor, we destroy objects which are + removed from the array (including when the array object itself is destroyed). + + @remark + Note that MEM_ROOT has no facility for reusing free space, + so don't use this if multiple re-expansions are likely to happen. + + @param Element_type The type of the elements of the container. + Elements must be copyable. + @param has_trivial_destructor If true, we don't destroy elements. + We could have used type traits to determine this. + __has_trivial_destructor is supported by some (but not all) + compilers we use. +*/ +template<typename Element_type, bool has_trivial_destructor> +class Mem_root_array +{ +public: + Mem_root_array(MEM_ROOT *root) + : m_root(root), m_array(NULL), m_size(0), m_capacity(0) + { + DBUG_ASSERT(m_root != NULL); + } + + ~Mem_root_array() + { + clear(); + } + + Element_type &at(size_t n) + { + DBUG_ASSERT(n < size()); + return m_array[n]; + } + + const Element_type &at(size_t n) const + { + DBUG_ASSERT(n < size()); + return m_array[n]; + } + + // Returns a pointer to the first element in the array. + Element_type *begin() { return &m_array[0]; } + + // Returns a pointer to the past-the-end element in the array. + Element_type *end() { return &m_array[size()]; } + + // Erases all of the elements. + void clear() + { + if (!empty()) + chop(0); + } + + /* + Chops the tail off the array, erasing all tail elements. + @param pos Index of first element to erase. + */ + void chop(const size_t pos) + { + DBUG_ASSERT(pos < m_size); + if (!has_trivial_destructor) + { + for (size_t ix= pos; ix < m_size; ++ix) + { + Element_type *p= &m_array[ix]; + p->~Element_type(); // Destroy discarded element. + } + } + m_size= pos; + } + + /* + Reserves space for array elements. + Copies over existing elements, in case we are re-expanding the array. + + @param n number of elements. + @retval true if out-of-memory, false otherwise. + */ + bool reserve(size_t n) + { + if (n <= m_capacity) + return false; + + void *mem= alloc_root(m_root, n * element_size()); + if (!mem) + return true; + Element_type *array= static_cast<Element_type*>(mem); + + // Copy all the existing elements into the new array. + for (size_t ix= 0; ix < m_size; ++ix) + { + Element_type *new_p= &array[ix]; + Element_type *old_p= &m_array[ix]; + new (new_p) Element_type(*old_p); // Copy into new location. + if (!has_trivial_destructor) + old_p->~Element_type(); // Destroy the old element. + } + + // Forget the old array. + m_array= array; + m_capacity= n; + return false; + } + + /* + Adds a new element at the end of the array, after its current last + element. The content of this new element is initialized to a copy of + the input argument. + + @param element Object to copy. + @retval true if out-of-memory, false otherwise. + */ + bool push_back(const Element_type &element) + { + const size_t min_capacity= 20; + const size_t expansion_factor= 2; + if (0 == m_capacity && reserve(min_capacity)) + return true; + if (m_size == m_capacity && reserve(m_capacity * expansion_factor)) + return true; + Element_type *p= &m_array[m_size++]; + new (p) Element_type(element); + return false; + } + + size_t capacity() const { return m_capacity; } + size_t element_size() const { return sizeof(Element_type); } + bool empty() const { return size() == 0; } + size_t size() const { return m_size; } + +private: + MEM_ROOT *const m_root; + Element_type *m_array; + size_t m_size; + size_t m_capacity; + + // Not (yet) implemented. + Mem_root_array(const Mem_root_array&); + Mem_root_array &operator=(const Mem_root_array&); +}; + + +#endif // MEM_ROOT_ARRAY_INCLUDED diff --git a/sql/mysql_install_db.cc b/sql/mysql_install_db.cc index 086dc292dec..364dca9120a 100644 --- a/sql/mysql_install_db.cc +++ b/sql/mysql_install_db.cc @@ -316,9 +316,9 @@ static int create_myini() static const char update_root_passwd_part1[]= - "UPDATE mysql.user SET Password = PASSWORD('"; + "UPDATE mysql.user SET Password = PASSWORD("; static const char update_root_passwd_part2[]= - "') where User='root';\n"; + ") where User='root';\n"; static const char remove_default_user_cmd[]= "DELETE FROM mysql.user where User='';\n"; static const char allow_remote_root_access_cmd[]= @@ -589,11 +589,19 @@ static int create_db_instance() } /* Change root password if requested. */ - if (opt_password) + if (opt_password && opt_password[0]) { - verbose("Changing root password",remove_default_user_cmd); + verbose("Setting root password",remove_default_user_cmd); fputs(update_root_passwd_part1, in); - fputs(opt_password, in); + + /* Use hex encoding for password, to avoid escaping problems.*/ + fputc('0', in); + fputc('x', in); + for(int i= 0; opt_password[i]; i++) + { + fprintf(in,"%02x",opt_password[i]); + } + fputs(update_root_passwd_part2, in); fflush(in); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 2251663c94a..ec6219b978f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2008-2012 Monty Program Ab +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2008, 2012, 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 @@ -702,7 +702,7 @@ int mysqld_server_started= 0; File_parser_dummy_hook file_parser_dummy_hook; /* replication parameters, if master_host is not NULL, we are a slave */ -uint report_port= MYSQL_PORT; +uint report_port= 0; ulong master_retry_count=0; char *master_info_file; char *relay_log_info_file, *report_user, *report_password, *report_host; @@ -711,9 +711,8 @@ char *opt_logname, *opt_slow_logname, *opt_bin_logname; /* Static variables */ -my_bool opt_stack_trace; static volatile sig_atomic_t kill_in_progress; - +my_bool opt_stack_trace; my_bool opt_expect_abort= 0; static my_bool opt_bootstrap, opt_myisam_log; static int cleanup_done; @@ -779,7 +778,6 @@ PSI_mutex_key key_LOCK_stats, key_LOCK_wakeup_ready; PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered; -PSI_mutex_key key_LOCK_logger_service; static PSI_mutex_info all_server_mutexes[]= { @@ -839,8 +837,6 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_commit_ordered, "LOCK_commit_ordered", PSI_FLAG_GLOBAL}, { &key_LOG_INFO_lock, "LOG_INFO::lock", 0}, { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL}, - { &key_LOCK_logger_service, "logger_service_file_st::lock", - PSI_FLAG_GLOBAL}, #ifdef WITH_WSREP { &key_LOCK_wsrep_ready, "LOCK_wsrep_ready", PSI_FLAG_GLOBAL}, { &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL}, @@ -2344,8 +2340,8 @@ static void network_init(void) { #ifdef HAVE_SYS_UN_H struct sockaddr_un UNIXaddr; -#endif int arg; +#endif DBUG_ENTER("network_init"); if (MYSQL_CALLBACK_ELSE(thread_scheduler, init, (), 0)) @@ -2353,6 +2349,11 @@ static void network_init(void) set_ports(); + if (report_port == 0) + { + report_port= mysqld_port; + } + DBUG_ASSERT(report_port != 0); if (!opt_disable_networking && !opt_bootstrap) { if (mysqld_port) @@ -2457,10 +2458,6 @@ static void network_init(void) } -#endif /*!EMBEDDED_LIBRARY*/ - - -#ifndef EMBEDDED_LIBRARY /** Close a connection. @@ -2878,10 +2875,6 @@ static void check_data_home(const char *path) #endif /* __WIN__ */ -#ifdef HAVE_LINUXTHREADS -#define UNSAFE_DEFAULT_LINUX_THREADS 200 -#endif - #if BACKTRACE_DEMANGLE #include <cxxabi.h> @@ -2891,13 +2884,84 @@ extern "C" char *my_demangle(const char *mangled_name, int *status) } #endif + +/* + pthread_attr_setstacksize() without so much platform-dependency + + Return: The actual stack size if possible. +*/ + +#ifndef EMBEDDED_LIBRARY +static size_t my_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ + size_t guard_size __attribute__((unused))= 0; + +#if defined(__ia64__) || defined(__ia64) + /* + On IA64, half of the requested stack size is used for "normal stack" + and half for "register stack". The space measured by check_stack_overrun + is the "normal stack", so double the request to make sure we have the + caller-expected amount of normal stack. + + NOTE: there is no guarantee that the register stack can't grow faster + than normal stack, so it's very unclear that we won't dump core due to + stack overrun despite check_stack_overrun's efforts. Experimentation + shows that in the execution_constants test, the register stack grows + less than half as fast as normal stack, but perhaps other scenarios are + less forgiving. If it turns out that more space is needed for the + register stack, that could be forced (rather inefficiently) by using a + multiplier higher than 2 here. + */ + stacksize *= 2; +#endif + + /* + On many machines, the "guard space" is subtracted from the requested + stack size, and that space is quite large on some platforms. So add + it to our request, if we can find out what it is. + */ +#ifdef HAVE_PTHREAD_ATTR_GETGUARDSIZE + if (pthread_attr_getguardsize(attr, &guard_size)) + guard_size = 0; /* if can't find it out, treat as 0 */ +#endif + + pthread_attr_setstacksize(attr, stacksize + guard_size); + + /* Retrieve actual stack size if possible */ +#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE + { + size_t real_stack_size= 0; + /* We must ignore real_stack_size = 0 as Solaris 2.9 can return 0 here */ + if (pthread_attr_getstacksize(attr, &real_stack_size) == 0 && + real_stack_size > guard_size) + { + real_stack_size -= guard_size; + if (real_stack_size < stacksize) + { + if (global_system_variables.log_warnings) + sql_print_warning("Asked for %zu thread stack, but got %zu", + stacksize, real_stack_size); + stacksize= real_stack_size; + } + } + } +#endif /* !EMBEDDED_LIBRARY */ + +#if defined(__ia64__) || defined(__ia64) + stacksize /= 2; +#endif + return stacksize; +} +#endif + + #if !defined(__WIN__) #ifndef SA_RESETHAND #define SA_RESETHAND 0 -#endif +#endif /* SA_RESETHAND */ #ifndef SA_NODEFER #define SA_NODEFER 0 -#endif +#endif /* SA_NODEFER */ #ifndef EMBEDDED_LIBRARY @@ -2915,9 +2979,7 @@ static void init_signals(void) sigemptyset(&sa.sa_mask); sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL); -#ifdef HAVE_STACKTRACE my_init_stacktrace(); -#endif #if defined(__amiga__) sa.sa_handler=(void(*)())handle_fatal_signal; #else @@ -2989,15 +3051,7 @@ static void start_signal_handler(void) #if !defined(HAVE_DEC_3_2_THREADS) pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM); (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); -#if defined(__ia64__) || defined(__ia64) - /* - Peculiar things with ia64 platforms - it seems we only have half the - stack size in reality, so we have to double it here - */ - pthread_attr_setstacksize(&thr_attr,my_thread_stack_size*2); -#else - pthread_attr_setstacksize(&thr_attr,my_thread_stack_size); -#endif + (void) my_setstacksize(&thr_attr,my_thread_stack_size); #endif mysql_mutex_lock(&LOCK_thread_count); @@ -3561,10 +3615,10 @@ static int init_common_variables() (except in the embedded server, where the default continues to be MyISAM) */ -#ifndef WITH_INNOBASE_STORAGE_ENGINE - default_storage_engine= const_cast<char *>("MyISAM"); -#else +#if defined(WITH_INNOBASE_STORAGE_ENGINE) || defined(WITH_XTRADB_STORAGE_ENGINE) default_storage_engine= const_cast<char *>("InnoDB"); +#else + default_storage_engine= const_cast<char *>("MyISAM"); #endif /* @@ -5280,37 +5334,9 @@ int mysqld_main(int argc, char **argv) unireg_abort(1); // Will do exit init_signals(); -#if defined(__ia64__) || defined(__ia64) - /* - Peculiar things with ia64 platforms - it seems we only have half the - stack size in reality, so we have to double it here - */ - pthread_attr_setstacksize(&connection_attrib,my_thread_stack_size*2); -#else - pthread_attr_setstacksize(&connection_attrib,my_thread_stack_size); -#endif -#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE - { - /* Retrieve used stack size; Needed for checking stack overflows */ - size_t stack_size= 0; - pthread_attr_getstacksize(&connection_attrib, &stack_size); -#if defined(__ia64__) || defined(__ia64) - stack_size/= 2; -#endif - /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */ - if (stack_size && stack_size < my_thread_stack_size) - { - if (global_system_variables.log_warnings) - sql_print_warning("Asked for %llu thread stack, but got %zu", - my_thread_stack_size, stack_size); -#if defined(__ia64__) || defined(__ia64) - my_thread_stack_size= stack_size*2; -#else - my_thread_stack_size= stack_size; -#endif - } - } -#endif + + my_thread_stack_size= my_setstacksize(&connection_attrib, + my_thread_stack_size); (void) thr_setconcurrency(concurrency); // 10 by default @@ -6048,8 +6074,10 @@ void handle_connections_sockets() uint error_count=0; THD *thd; struct sockaddr_storage cAddr; - int ip_flags=0,socket_flags=0,flags=0,retval; - int extra_ip_flags=0; + 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; #ifdef HAVE_POLL int socket_count= 0; @@ -6646,17 +6674,6 @@ struct my_option my_long_options[]= {"help", '?', "Display this help and exit.", &opt_help, &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef DBUG_OFF - {"debug", '#', "Built in DBUG debugger. Disabled in this build.", - ¤t_dbug_option, ¤t_dbug_option, 0, GET_STR, OPT_ARG, - 0, 0, 0, 0, 0, 0}, -#endif -#ifdef HAVE_REPLICATION - {"debug-abort-slave-event-count", 0, - "Option used by mysql-test for debugging and testing of replication.", - &abort_slave_event_count, &abort_slave_event_count, - 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif /* HAVE_REPLICATION */ {"allow-suspicious-udfs", 0, "Allows use of UDFs consisting of only one symbol xxx() " "without corresponding xxx_init() or xxx_deinit(). That also means " @@ -6725,30 +6742,86 @@ struct my_option my_long_options[]= /* 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. */ +#ifdef DBUG_OFF + {"debug", '#', "Built in DBUG debugger. Disabled in this build.", + ¤t_dbug_option, ¤t_dbug_option, 0, GET_STR, OPT_ARG, + 0, 0, 0, 0, 0, 0}, +#endif +#ifdef HAVE_REPLICATION + {"debug-abort-slave-event-count", 0, + "Option used by mysql-test for debugging and testing of replication.", + &abort_slave_event_count, &abort_slave_event_count, + 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#endif /* HAVE_REPLICATION */ +#ifndef DBUG_OFF + {"debug-assert-on-error", 0, + "Do an assert in various functions if we get a fatal error", + &my_assert_on_error, &my_assert_on_error, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"debug-assert-if-crashed-table", 0, + "Do an assert in handler::print_error() if we get a crashed table", + &debug_assert_if_crashed_table, &debug_assert_if_crashed_table, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, +#endif +#ifdef HAVE_REPLICATION + {"debug-disconnect-slave-event-count", 0, + "Option used by mysql-test for debugging and testing of replication.", + &disconnect_slave_event_count, &disconnect_slave_event_count, + 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#endif /* HAVE_REPLICATION */ + {"debug-exit-info", 'T', "Used for debugging. Use at your own risk.", + 0, 0, 0, GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug-gdb", 0, + "Set up signals usable for debugging.", + &opt_debugging, &opt_debugging, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef HAVE_REPLICATION + {"debug-max-binlog-dump-events", 0, + "Option used by mysql-test for debugging and testing of replication.", + &max_binlog_dump_events, &max_binlog_dump_events, 0, + GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#endif /* HAVE_REPLICATION */ +#ifdef SAFE_MUTEX + {"debug-mutex-deadlock-detector", 0, + "Enable checking of wrong mutex usage.", + &safe_mutex_deadlock_detector, + &safe_mutex_deadlock_detector, + 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, +#endif + {"debug-no-sync", 0, + "Disables system sync calls. Only for running tests or debugging!", + &my_disable_sync, &my_disable_sync, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, +#ifdef HAVE_REPLICATION + {"debug-sporadic-binlog-dump-fail", 0, + "Option used by mysql-test for debugging and testing of replication.", + &opt_sporadic_binlog_dump_fail, + &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, + 0}, +#endif /* HAVE_REPLICATION */ {"default-storage-engine", 0, "The default storage engine for new tables", &default_storage_engine, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"default-time-zone", 0, "Set the default time zone.", &default_tz_name, &default_tz_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, +#if defined(ENABLED_DEBUG_SYNC) + {"debug-sync-timeout", OPT_DEBUG_SYNC_TIMEOUT, + "Enable the debug sync facility " + "and optionally specify a default wait timeout in seconds. " + "A zero value keeps the facility disabled.", + &opt_debug_sync_timeout, 0, + 0, GET_UINT, OPT_ARG, 0, 0, UINT_MAX, 0, 0, 0}, +#endif /* defined(ENABLED_DEBUG_SYNC) */ #ifdef HAVE_OPENSSL {"des-key-file", 0, "Load keys for des_encrypt() and des_encrypt from given file.", &des_key_file, &des_key_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_OPENSSL */ -#ifdef HAVE_REPLICATION - {"debug-disconnect-slave-event-count", 0, - "Option used by mysql-test for debugging and testing of replication.", - &disconnect_slave_event_count, &disconnect_slave_event_count, - 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif /* HAVE_REPLICATION */ #ifdef HAVE_STACKTRACE {"stack-trace", 0 , "Print a symbolic stack trace on failure", &opt_stack_trace, &opt_stack_trace, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, #endif /* HAVE_STACKTRACE */ - {"debug-exit-info", 'T', "Used for debugging. Use at your own risk.", 0, 0, 0, - GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"external-locking", 0, "Use system (external) locking (disabled by " "default). With this option enabled you can run myisamchk to test " "(not repair) tables while the MySQL server is running. Disable with " @@ -6760,10 +6833,6 @@ struct my_option my_long_options[]= "Set up signals usable for debugging. Deprecated, use --debug-gdb instead.", &opt_debugging, &opt_debugging, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"debug-gdb", 0, - "Set up signals usable for debugging.", - &opt_debugging, &opt_debugging, - 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_LARGE_PAGE_OPTION {"super-large-pages", 0, "Enable support for super large pages.", &opt_super_large_pages, &opt_super_large_pages, 0, @@ -6854,10 +6923,6 @@ struct my_option my_long_options[]= {"init-rpl-role", 0, "Set the replication role.", &rpl_status, &rpl_status, &rpl_role_typelib, GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"debug-max-binlog-dump-events", 0, - "Option used by mysql-test for debugging and testing of replication.", - &max_binlog_dump_events, &max_binlog_dump_events, 0, - GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ {"memlock", 0, "Lock mysqld in memory.", &locked_in_memory, &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -6963,13 +7028,6 @@ struct my_option my_long_options[]= "(Default: 15000).", &slow_start_timeout, &slow_start_timeout, 0, GET_ULONG, REQUIRED_ARG, 15000, 0, 0, 0, 0, 0}, #endif -#ifdef HAVE_REPLICATION - {"debug-sporadic-binlog-dump-fail", 0, - "Option used by mysql-test for debugging and testing of replication.", - &opt_sporadic_binlog_dump_fail, - &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, - 0}, -#endif /* HAVE_REPLICATION */ #ifdef HAVE_OPENSSL {"ssl", 0, "Enable SSL for connection (automatically enabled with other flags).", @@ -6991,9 +7049,6 @@ struct my_option my_long_options[]= files. */ IF_VALGRIND(0,IF_WIN(0,1)), 0, 0, 0, 0, 0}, - {"debug-no-sync", 0, - "Disables system sync calls. Only for running tests or debugging!", - &my_disable_sync, &my_disable_sync, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"sysdate-is-now", 0, "Non-default option to alias SYSDATE() to NOW() to make it safe-replicable. " "Since 5.0, SYSDATE() returns a `dynamic' value different for different " @@ -7004,14 +7059,6 @@ struct my_option my_long_options[]= "Decision to use in heuristic recover process. Possible values are COMMIT " "or ROLLBACK.", &tc_heuristic_recover, &tc_heuristic_recover, &tc_heuristic_recover_typelib, GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#if defined(ENABLED_DEBUG_SYNC) - {"debug-sync-timeout", OPT_DEBUG_SYNC_TIMEOUT, - "Enable the debug sync facility " - "and optionally specify a default wait timeout in seconds. " - "A zero value keeps the facility disabled.", - &opt_debug_sync_timeout, 0, - 0, GET_UINT, OPT_ARG, 0, 0, UINT_MAX, 0, 0, 0}, -#endif /* defined(ENABLED_DEBUG_SYNC) */ {"temp-pool", 0, #if (ENABLE_TEMP_POOL) "Using this option will cause most temporary files created to use a small " @@ -7041,16 +7088,6 @@ struct my_option my_long_options[]= {"table_cache", 0, "Deprecated; use --table-open-cache instead.", &table_cache_size, &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0}, -#ifndef DBUG_OFF - {"debug-assert-on-error", 0, - "Do an assert in various functions if we get a fatal error", - &my_assert_on_error, &my_assert_on_error, - 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"debug-assert-if-crashed-table", 0, - "Do an assert in handler::print_error() if we get a crashed table", - &debug_assert_if_crashed_table, &debug_assert_if_crashed_table, - 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, -#endif {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -7530,7 +7567,7 @@ SHOW_VAR status_vars[]= { {"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS}, {"Handler_discover", (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONG_STATUS}, - {"Handler_icp_attempts ", (char*) offsetof(STATUS_VAR, ha_icp_attempts), SHOW_LONG_STATUS}, + {"Handler_icp_attempts", (char*) offsetof(STATUS_VAR, ha_icp_attempts), SHOW_LONG_STATUS}, {"Handler_icp_match", (char*) offsetof(STATUS_VAR, ha_icp_match), SHOW_LONG_STATUS}, {"Handler_mrr_init", (char*) offsetof(STATUS_VAR, ha_mrr_init_count), SHOW_LONG_STATUS}, @@ -8567,6 +8604,14 @@ static int get_options(int *argc_ptr, char ***argv_ptr) one_thread_scheduler(thread_scheduler); one_thread_scheduler(extra_thread_scheduler); #else + +#ifdef _WIN32 + /* workaround: disable thread pool on XP */ + if (GetProcAddress(GetModuleHandle("kernel32"),"CreateThreadpool") == 0 && + thread_handling > SCHEDULER_NO_THREADS) + thread_handling = SCHEDULER_ONE_THREAD_PER_CONNECTION; +#endif + if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION) one_thread_per_connection_scheduler(thread_scheduler, &max_connections, &connection_count); diff --git a/sql/mysqld.h b/sql/mysqld.h index 99093e1e83b..9ce53555e45 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2012, 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 diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 2e8b00982fc..c6ee117213d 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1396,7 +1396,7 @@ SEL_IMERGE::SEL_IMERGE(SEL_IMERGE *arg, uint cnt, for (SEL_TREE **tree = trees, **arg_tree= arg->trees; tree < trees_next; tree++, arg_tree++) { - if (!(*tree= new SEL_TREE(*arg_tree, FALSE, param))) + if (!(*tree= new SEL_TREE(*arg_tree, TRUE, param))) goto mem_err; } diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index dcb5181acc3..56b76f5982e 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -188,6 +188,252 @@ */ +/* +EqualityPropagationAndSjmNests +****************************** + +Equalities are used for: +P1. Equality propagation +P2. Equality substitution [for a certain join order] + +The equality propagation is not affected by SJM nests. In fact, it is done +before we determine the execution plan, i.e. before we even know we will use +SJM-nests for execution. + +The equality substitution is affected. + +Substitution without SJMs +========================= +When one doesn't have SJM nests, tables have a strict join order: + + ---------------------------------> + t1 -- t2 -- t3 -- t4 --- t5 + + + ? ^ + \ + --(part-of-WHERE) + + +parts WHERE/ON and ref. expressions are attached at some point along the axis. +Expression is allowed to refer to a table column if the table is to the left of +the attachment point. For any given expression, we have a goal: + + "Move leftmost allowed attachment point as much as possible to the left" + +Substitution with SJMs - task setting +===================================== + +When SJM nests are present, there is no global strict table ordering anymore: + + + ---------------------------------> + + ot1 -- ot2 --- sjm -- ot4 --- ot5 + | + | Main execution + - - - - - - - - - - - - - - - - - - - - - - - - + | Materialization + it1 -- it2 --/ + + +Besides that, we must take into account that + - values for outer table columns, otN.col, are inaccessible at + materialization step (SJM-RULE) + - values for inner table columns, itN.col, are inaccessible at Main execution + step, except for SJ-Materialization-Scan and columns that are in the + subquery's select list. (SJM-RULE) + +Substitution with SJMs - solution +================================= + +First, we introduce global strict table ordering like this: + + ot1 - ot2 --\ /--- ot3 -- ot5 + \--- it1 --- it2 --/ + +Now, let's see how to meet (SJM-RULE). + +SJ-Materialization is only applicable for uncorrelated subqueries. From this, it +follows that any multiple equality will either +1. include only columns of outer tables, or +2. include only columns of inner tables, or +3. include columns of inner and outer tables, joined together through one + of IN-equalities. + +Cases #1 and #2 can be handled in the same way as with regular inner joins. + +Case #3 requires special handling, so that we don't construct violations of +(SJM-RULE). Let's consider possible ways to build violations. + +Equality propagation starts with the clause in this form + + top_query_where AND subquery_where AND in_equalities + +First, it builds multi-equalities. It can also build a mixed multi-equality + + multiple-equal(ot1.col, ot2.col, ... it1.col, itN.col) + +Multi-equalities are pushed down the OR-clauses in top_query_where and in +subquery_where, so it's possible that clauses like this one are built: + + subquery_cond OR (multiple-equal(it1.col, ot1.col,...) AND ...) + ^^^^^^^^^^^^^ \ + | this must be evaluated + \- can only be evaluated at the main phase. + at the materialization phase + +Finally, equality substitution is started. It does two operations: + + +1. Field reference substitution +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +(In the code, this is Item_field::replace_equal_field) + +This is a process of replacing each reference to "tblX.col" +with the first element of the multi-equality. (REF-SUBST-ORIG) + +This behaviour can cause problems with Semi-join nests. Suppose, we have a +condition: + + func(it1.col, it2.col) + +and a multi-equality(ot1.col, it1.col). Then, reference to "it1.col" will be +replaced with "ot1.col", constructing a condition + + func(ot1.col, it2.col) + +which will be a violation of (SJM-RULE). + +In order to avoid this, (REF-SUBST-ORIG) is amended as follows: + +- references to tables "itX.col" that are inner wrt some SJM nest, are + replaced with references to the first inner table from the same SJM nest. + +- references to top-level tables "otX.col" are replaced with references to + the first element of the multi-equality, no matter if that first element is + a column of a top-level table or of table from some SJM nest. + (REF-SUBST-SJM) + + The case where the first element is a table from an SJM nest $SJM is ok, + because it can be proven that $SJM uses SJ-Materialization-Scan, and + "unpacks" correct column values to the first element during the main + execution phase. + +2. Item_equal elimination +~~~~~~~~~~~~~~~~~~~~~~~~~ +(In the code: eliminate_item_equal) This is a process of taking + + multiple-equal(a,b,c,d,e) + +and replacing it with an equivalent expression which is an AND of pair-wise +equalities: + + a=b AND a=c AND ... + +The equalities are picked such that for any given join prefix (t1,t2...) the +subset of equalities that can be evaluated gives the most restrictive +filtering. + +Without SJM nests, it is sufficient to compare every multi-equality member +with the first one: + + elem1=elem2 AND elem1=elem3 AND elem1=elem4 ... + +When SJM nests are present, we should take care not to construct equalities +that violate the (SJM-RULE). This is achieved by generating separate sets of +equalites for top-level tables and for inner tables. That is, for the join +order + + ot1 - ot2 --\ /--- ot3 -- ot5 + \--- it1 --- it2 --/ + +we will generate + ot1.col=ot2.col + ot1.col=ot3.col + ot1.col=ot5.col + it2.col=it1.col + + +2.1 The problem with Item_equals and ORs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +As has been mentioned above, multiple equalities are pushed down into OR +clauses, possibly building clauses like this: + + func(it.col2) OR multiple-equal(it1.col1, it1.col2, ot1.col) (1) + +where the first part of the clause has references to inner tables, while the +second has references to the top-level tables, which is a violation of +(SJM-RULE). + +AND-clauses of this kind do not create problems, because make_cond_for_table() +will take them apart. OR-clauses will not be split. It is possible to +split-out the part that's dependent on the inner table: + + func(it.col2) OR it1.col1=it1.col2 + +but this is a less-restrictive condition than condition (1). Current execution +scheme will still try to generate the "remainder" condition: + + func(it.col2) OR it1.col1=ot1.col + +which is a violation of (SJM-RULE). + +QQ: "ot1.col=it1.col" is checked at the upper level. Why was it not removed +here? +AA: because has a proper subset of conditions that are found on this level. + consider a join order of ot, sjm(it) + and a condition + ot.col=it.col AND ( ot.col=it.col='foo' OR it.col2='bar') + + we will produce: + table ot: nothing + table it: ot.col=it.col AND (ot.col='foo' OR it.col2='bar') + ^^^^ ^^^^^^^^^^^^^^^^ + | \ the problem is that + | this part condition didnt + | receive a substitution + | + +--- it was correct to subst, 'ot' is + the left-most. + + +Does it make sense to push "inner=outer" down into ORs? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Yes. Consider the query: + + select * from ot + where ot.col in (select it.col from it where (it.col='foo' OR it.col='bar')) + +here, it may be useful to infer that + + (ot.col='foo' OR ot.col='bar') (CASE-FOR-SUBST) + +and attach that condition to the table 'ot'. + +Possible solutions for Item_equals and ORs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Solution #1 +~~~~~~~~~~~ +Let make_cond_for_table() chop analyze the OR clauses it has produced and +discard them if they violate (SJM-RULE). This solution would allow to handle +cases like (CASE-FOR-SUBST) at the expense of making semantics of +make_cond_for_table() complicated. + +Solution #2 +~~~~~~~~~~~ +Before the equality propagation phase, none of the OR clauses violate the +(SJM-RULE). This way, if we remember which tables the original equality +referred to, we can only generate equalities that refer to the outer (or inner) +tables. Note that this will disallow handling of cases like (CASE-FOR-SUBST). + +Currently, solution #2 is implemented. + +*/ + static bool subquery_types_allow_materialization(Item_in_subselect *in_subs); @@ -346,8 +592,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join) TODO: for PS, make the whole block execute only on the first execution */ Item_subselect *subselect; - if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW) && // (1) - (subselect= parent_unit->item)) // (2) + if (!thd->lex->is_view_context_analysis() && // (1) + (subselect= parent_unit->item)) // (2) { Item_in_subselect *in_subs= NULL; Item_allany_subselect *allany_subs= NULL; @@ -1229,6 +1475,8 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) sj_nest->embedding= emb_tbl_nest; sj_nest->alias= (char*) "(sj-nest)"; sj_nest->sj_subq_pred= subq_pred; + sj_nest->original_subq_pred_used_tables= subq_pred->used_tables() | + subq_pred->left_expr->used_tables(); /* Nests do not participate in those 'chains', so: */ /* sj_nest->next_leaf= sj_nest->next_local= sj_nest->next_global == NULL*/ emb_join_list->push_back(sj_nest); @@ -1267,7 +1515,10 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) (a theory: a next_local chain always starts with ::leaf_tables because view's tables are inserted after the view) */ - for (tl= parent_lex->leaf_tables.head(); tl->next_local; tl= tl->next_local) ; + + for (tl= (TABLE_LIST*)(parent_lex->table_list.first); tl->next_local; tl= tl->next_local) + {} + tl->next_local= subq_lex->leaf_tables.head(); /* A theory: no need to re-connect the next_global chain */ @@ -1480,7 +1731,7 @@ static bool convert_subq_to_jtbm(JOIN *parent_join, (a theory: a next_local chain always starts with ::leaf_tables because view's tables are inserted after the view) */ - for (tl= parent_lex->leaf_tables.head(); tl->next_local; tl= tl->next_local) + for (tl= (TABLE_LIST*)(parent_lex->table_list.first); tl->next_local; tl= tl->next_local) {} tl->next_local= jtbm; @@ -2670,6 +2921,8 @@ bool Firstmatch_picker::check_qep(JOIN *join, } } } + else + invalidate_firstmatch_prefix(); return FALSE; } @@ -3097,7 +3350,22 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join) record_count, join->best_positions + idx, &loose_scan_pos); if (idx==first) + { join->best_positions[idx]= loose_scan_pos; + /* + If LooseScan is based on ref access (including the "degenerate" + one with 0 key parts), we should use full index scan. + + Unfortunately, lots of code assumes that if tab->type==JT_ALL && + tab->quick!=NULL, then quick select should be used. The only + simple way to fix this is to remove the quick select: + */ + if (join->best_positions[idx].key) + { + delete join->best_positions[idx].table->quick; + join->best_positions[idx].table->quick= NULL; + } + } } rem_tables &= ~join->best_positions[idx].table->table->map; record_count *= join->best_positions[idx].records_read; @@ -4950,7 +5218,6 @@ bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, bool JOIN::choose_subquery_plan(table_map join_tables) { - Join_plan_state save_qep; /* The original QEP of the subquery. */ enum_reopt_result reopt_result= REOPT_NONE; Item_in_subselect *in_subs; @@ -4969,12 +5236,16 @@ bool JOIN::choose_subquery_plan(table_map join_tables) } else return false; + /* A strategy must be chosen earlier. */ DBUG_ASSERT(in_subs->has_strategy()); DBUG_ASSERT(in_to_exists_where || in_to_exists_having); DBUG_ASSERT(!in_to_exists_where || in_to_exists_where->fixed); DBUG_ASSERT(!in_to_exists_having || in_to_exists_having->fixed); + /* The original QEP of the subquery. */ + Join_plan_state save_qep(table_count); + /* Compute and compare the costs of materialization and in-exists if both strategies are possible and allowed by the user (checked during the prepare diff --git a/sql/password.c b/sql/password.c index f4ff3156bec..1a12a81f7c6 100644 --- a/sql/password.c +++ b/sql/password.c @@ -503,7 +503,7 @@ check_scramble(const uchar *scramble_arg, const char *message, mysql_sha1_reset(&sha1_context); mysql_sha1_input(&sha1_context, buf, SHA1_HASH_SIZE); mysql_sha1_result(&sha1_context, hash_stage2_reassured); - return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE); + return test(memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE)); } diff --git a/sql/protocol.cc b/sql/protocol.cc index 4a7ea88c402..4026b327ddb 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. - Copyright (c) 2008-2011 Monty Program Ab +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. + Copyright (c) 2008, 2011, 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 diff --git a/sql/records.cc b/sql/records.cc index 77fdc427b86..d52481c36f5 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -344,7 +344,8 @@ static int rr_quick(READ_RECORD *info) break; } } - update_virtual_fields(info->thd, info->table); + if (info->table->vfield) + update_virtual_fields(info->thd, info->table); return tmp; } @@ -460,7 +461,7 @@ int rr_sequential(READ_RECORD *info) break; } } - if (!tmp) + if (!tmp && info->table->vfield) update_virtual_fields(info->thd, info->table); return tmp; } diff --git a/sql/rpl_filter.cc b/sql/rpl_filter.cc index 5f5473e09ab..0380bc323a3 100644 --- a/sql/rpl_filter.cc +++ b/sql/rpl_filter.cc @@ -42,8 +42,8 @@ Rpl_filter::~Rpl_filter() free_string_array(&wild_do_table); if (wild_ignore_table_inited) free_string_array(&wild_ignore_table); - free_list(&do_db); - free_list(&ignore_db); + free_string_list(&do_db); + free_string_list(&ignore_db); free_list(&rewrite_db); } @@ -263,6 +263,57 @@ Rpl_filter::is_on() } +/** + Parse and add the given comma-separated sequence of filter rules. + + @param spec Comma-separated sequence of filter rules. + @param add Callback member function to add a filter rule. + + @return true if error, false otherwise. +*/ + +int +Rpl_filter::parse_filter_rule(const char* spec, Add_filter add) +{ + int status= 0; + char *arg, *ptr, *pstr; + + if (! (ptr= my_strdup(spec, MYF(MY_WME)))) + return true; + + pstr= ptr; + + while (pstr) + { + arg= pstr; + + /* Parse token string. */ + pstr= strpbrk(arg, ","); + + /* NUL terminate the token string. */ + if (pstr) + *pstr++= '\0'; + + /* Skip an empty token string. */ + if (arg[0] == '\0') + continue; + + /* Skip leading spaces. */ + while (my_isspace(system_charset_info, *arg)) + arg++; + + status= (this->*add)(arg); + + if (status) + break; + } + + my_free(ptr); + + return status; +} + + int Rpl_filter::add_do_table(const char* table_spec) { @@ -285,6 +336,46 @@ Rpl_filter::add_ignore_table(const char* table_spec) } +int +Rpl_filter::set_do_table(const char* table_spec) +{ + int status; + + if (do_table_inited) + my_hash_reset(&do_table); + + status= parse_filter_rule(table_spec, &Rpl_filter::add_do_table); + + if (!do_table.records) + { + my_hash_free(&do_table); + do_table_inited= 0; + } + + return status; +} + + +int +Rpl_filter::set_ignore_table(const char* table_spec) +{ + int status; + + if (ignore_table_inited) + my_hash_reset(&ignore_table); + + status= parse_filter_rule(table_spec, &Rpl_filter::add_ignore_table); + + if (!ignore_table.records) + { + my_hash_free(&ignore_table); + ignore_table_inited= 0; + } + + return status; +} + + int Rpl_filter::add_wild_do_table(const char* table_spec) { @@ -307,6 +398,46 @@ Rpl_filter::add_wild_ignore_table(const char* table_spec) } +int +Rpl_filter::set_wild_do_table(const char* table_spec) +{ + int status; + + if (wild_do_table_inited) + free_string_array(&wild_do_table); + + status= parse_filter_rule(table_spec, &Rpl_filter::add_wild_do_table); + + if (!wild_do_table.elements) + { + delete_dynamic(&wild_do_table); + wild_do_table_inited= 0; + } + + return status; +} + + +int +Rpl_filter::set_wild_ignore_table(const char* table_spec) +{ + int status; + + if (wild_ignore_table_inited) + free_string_array(&wild_ignore_table); + + status= parse_filter_rule(table_spec, &Rpl_filter::add_wild_ignore_table); + + if (!wild_ignore_table.elements) + { + delete_dynamic(&wild_ignore_table); + wild_ignore_table_inited= 0; + } + + return status; +} + + void Rpl_filter::add_db_rewrite(const char* from_db, const char* to_db) { @@ -355,25 +486,59 @@ Rpl_filter::add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec) } -void +int +Rpl_filter::add_string_list(I_List<i_string> *list, const char* spec) +{ + char *str; + i_string *node; + + if (! (str= my_strdup(spec, MYF(MY_WME)))) + return true; + + if (! (node= new i_string(str))) + { + my_free(str); + return true; + } + + list->push_back(node); + + return false; +} + + +int Rpl_filter::add_do_db(const char* table_spec) { DBUG_ENTER("Rpl_filter::add_do_db"); - i_string *db = new i_string(table_spec); - do_db.push_back(db); - DBUG_VOID_RETURN; + DBUG_RETURN(add_string_list(&do_db, table_spec)); } -void +int Rpl_filter::add_ignore_db(const char* table_spec) { DBUG_ENTER("Rpl_filter::add_ignore_db"); - i_string *db = new i_string(table_spec); - ignore_db.push_back(db); - DBUG_VOID_RETURN; + DBUG_RETURN(add_string_list(&ignore_db, table_spec)); } + +int +Rpl_filter::set_do_db(const char* db_spec) +{ + free_string_list(&do_db); + return parse_filter_rule(db_spec, &Rpl_filter::add_do_db); +} + + +int +Rpl_filter::set_ignore_db(const char* db_spec) +{ + free_string_list(&ignore_db); + return parse_filter_rule(db_spec, &Rpl_filter::add_ignore_db); +} + + extern "C" uchar *get_table_key(const uchar *, size_t *, my_bool); extern "C" void free_table_ent(void* a); @@ -448,6 +613,23 @@ Rpl_filter::free_string_array(DYNAMIC_ARRAY *a) } +void +Rpl_filter::free_string_list(I_List<i_string> *l) +{ + void *ptr; + i_string *tmp; + + while ((tmp= l->get())) + { + ptr= (void *) tmp->ptr; + my_free(ptr); + delete tmp; + } + + l->empty(); +} + + /* Builds a String from a HASH of TABLE_RULE_ENT. Cannot be used for any other hash, as it assumes that the hash entries are TABLE_RULE_ENT. @@ -564,3 +746,37 @@ Rpl_filter::get_ignore_db() { return &ignore_db; } + + +void +Rpl_filter::db_rule_ent_list_to_str(String* str, I_List<i_string>* list) +{ + I_List_iterator<i_string> it(*list); + i_string* s; + + str->length(0); + + while ((s= it++)) + { + str->append(s->ptr); + str->append(','); + } + + // Remove last ',' + if (!str->is_empty()) + str->chop(); +} + + +void +Rpl_filter::get_do_db(String* str) +{ + db_rule_ent_list_to_str(str, get_do_db()); +} + + +void +Rpl_filter::get_ignore_db(String* str) +{ + db_rule_ent_list_to_str(str, get_ignore_db()); +} diff --git a/sql/rpl_filter.h b/sql/rpl_filter.h index d32fb36d6fb..2eb0340b714 100644 --- a/sql/rpl_filter.h +++ b/sql/rpl_filter.h @@ -61,11 +61,20 @@ public: int add_do_table(const char* table_spec); int add_ignore_table(const char* table_spec); + int set_do_table(const char* table_spec); + int set_ignore_table(const char* table_spec); + int add_wild_do_table(const char* table_spec); int add_wild_ignore_table(const char* table_spec); - void add_do_db(const char* db_spec); - void add_ignore_db(const char* db_spec); + int set_wild_do_table(const char* table_spec); + int set_wild_ignore_table(const char* table_spec); + + int add_do_db(const char* db_spec); + int add_ignore_db(const char* db_spec); + + int set_do_db(const char* db_spec); + int set_ignore_db(const char* db_spec); void add_db_rewrite(const char* from_db, const char* to_db); @@ -83,6 +92,9 @@ public: I_List<i_string>* get_do_db(); I_List<i_string>* get_ignore_db(); + void get_do_db(String* str); + void get_ignore_db(String* str); + private: bool table_rules_on; @@ -92,13 +104,21 @@ private: int add_table_rule(HASH* h, const char* table_spec); int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec); + typedef int (Rpl_filter::*Add_filter)(char const*); + + int parse_filter_rule(const char* spec, Add_filter func); + void free_string_array(DYNAMIC_ARRAY *a); + void free_string_list(I_List<i_string> *l); void table_rule_ent_hash_to_str(String* s, HASH* h, bool inited); void table_rule_ent_dynamic_array_to_str(String* s, DYNAMIC_ARRAY* a, bool inited); + void db_rule_ent_list_to_str(String* s, I_List<i_string>* l); TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len); + int add_string_list(I_List<i_string> *list, const char* spec); + /* Those 4 structures below are uninitialized memory unless the corresponding *_inited variables are "true". diff --git a/sql/rpl_handler.h b/sql/rpl_handler.h index 4d1bce45c54..4743fffb9a0 100644 --- a/sql/rpl_handler.h +++ b/sql/rpl_handler.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2011, 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 diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc index c015ce62a99..ec1a96e8a2b 100644 --- a/sql/rpl_injector.cc +++ b/sql/rpl_injector.cc @@ -1,5 +1,4 @@ -/* - Copyright (c) 2006, 2010, Oracle and/or its affiliates. +/* Copyright (c) 2006, 2011, 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 diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index ae2a4bbec01..3c5a99121fa 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. +/* Copyright (c) 2006, 2012, Oracle and/or its affiliates. Copyright (c) 2010, 2011, Monty Program Ab This program is free software; you can redistribute it and/or modify diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index c98f7253b18..a885576ef1c 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -1,5 +1,4 @@ -/* - Copyright (c) 2006, 2010, Oracle and/or its affiliates. +/* Copyright (c) 2006, 2012, 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 diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index da1fc98c3e1..e1efbc7ee4c 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1,5 +1,4 @@ -/* - Copyright (c) 2006, 2011, Oracle and/or its affiliates. +/* Copyright (c) 2006, 2012, 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 diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index fef910de65d..958002561bc 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -1,5 +1,4 @@ -/* - Copyright (c) 2005, 2010, Oracle and/or its affiliates. +/* Copyright (c) 2005, 2012, 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 @@ -204,6 +203,13 @@ public: bool ignore_log_space_limit; /* + Used by the SQL thread to instructs the IO thread to rotate + the logs when the SQL thread needs to purge to release some + disk space. + */ + bool sql_force_rotate_relay; + + /* When it commits, InnoDB internally stores the master log position it has processed so far; the position to store is the one of the end of the committing event (the COMMIT query event, or the event if in autocommit diff --git a/sql/set_var.h b/sql/set_var.h index 85faaaadd73..006498773b8 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -1,6 +1,6 @@ #ifndef SET_VAR_INCLUDED #define SET_VAR_INCLUDED -/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. +/* Copyright (c) 2002, 2011, 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 diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 73357b6c4a2..8510eb1f1ac 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -4701,14 +4701,14 @@ ER_NOT_SUPPORTED_YET 42000 spa "Esta versión de MariaDB no soporta todavia '%s'" swe "Denna version av MariaDB kan ännu inte utföra '%s'" ER_MASTER_FATAL_ERROR_READING_BINLOG - nla "Kreeg fatale fout %d: '%-.512s' van master tijdens lezen van data uit binaire log" - eng "Got fatal error %d from master when reading data from binary log: '%-.512s'" - ger "Schwerer Fehler %d: '%-.512s vom Master beim Lesen des binären Logs" - ita "Errore fatale %d: '%-.512s' dal master leggendo i dati dal log binario" - por "Obteve fatal erro %d: '%-.512s' do master quando lendo dados do binary log" - rus "Получена неиÑÐ¿Ñ€Ð°Ð²Ð¸Ð¼Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° %d: '%-.512s' от головного Ñервера в процеÑÑе выборки данных из двоичного журнала" - spa "Recibió fatal error %d: '%-.512s' del master cuando leyendo datos del binary log" - swe "Fick fatalt fel %d: '%-.512s' frÃ¥n master vid läsning av binärloggen" + nla "Kreeg fatale fout %d: '%-.320s' van master tijdens lezen van data uit binaire log" + eng "Got fatal error %d from master when reading data from binary log: '%-.320s'" + ger "Schwerer Fehler %d: '%-.320s vom Master beim Lesen des binären Logs" + ita "Errore fatale %d: '%-.320s' dal master leggendo i dati dal log binario" + por "Obteve fatal erro %d: '%-.320s' do master quando lendo dados do binary log" + rus "Получена неиÑÐ¿Ñ€Ð°Ð²Ð¸Ð¼Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° %d: '%-.320s' от головного Ñервера в процеÑÑе выборки данных из двоичного журнала" + spa "Recibió fatal error %d: '%-.320s' del master cuando leyendo datos del binary log" + swe "Fick fatalt fel %d: '%-.320s' frÃ¥n master vid läsning av binärloggen" ER_SLAVE_IGNORED_TABLE eng "Slave SQL thread ignored the query because of replicate-*-table rules" ger "Slave-SQL-Thread hat die Abfrage aufgrund von replicate-*-table-Regeln ignoriert" @@ -6486,6 +6486,16 @@ ER_PLUGIN_NO_UNINSTALL ER_PLUGIN_NO_INSTALL eng "Plugin '%s' is marked as not dynamically installable. You have to stop the server to install it." +ER_BINLOG_UNSAFE_WRITE_AUTOINC_SELECT + eng "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." + +ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC + eng "CREATE TABLE... SELECT... on a table with an auto-increment column is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are inserted. This order cannot be predicted and may differ on master and the slave." + +# +# End of 5.5 error messages. +# + # # MariaDB error messages section starts here # diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index 0b5fce7758f..37f28844a7c 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -77,7 +77,7 @@ extern "C" sig_handler handle_fatal_signal(int sig) curr_time= my_time(0); localtime_r(&curr_time, &tm); - fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d ", + my_safe_printf_stderr("%02d%02d%02d %2d:%02d:%02d ", tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); if (opt_expect_abort @@ -139,6 +139,7 @@ extern "C" sig_handler handle_fatal_signal(int sig) "Hope that's ok; if not, decrease some variables in the equation.\n\n"); #if defined(HAVE_LINUXTHREADS) +#define UNSAFE_DEFAULT_LINUX_THREADS 200 if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS) { my_safe_printf_stderr( @@ -166,7 +167,7 @@ extern "C" sig_handler handle_fatal_signal(int sig) "where mysqld died. If you see no messages after this, something went\n" "terribly wrong...\n"); my_print_stacktrace(thd ? (uchar*) thd->thread_stack : NULL, - my_thread_stack_size); + (ulong)my_thread_stack_size); } if (thd) { diff --git a/sql/slave.cc b/sql/slave.cc index 833820203b0..ee48b2008dc 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2008-2011 Monty Program Ab +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2008, 2011, 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 @@ -1342,7 +1342,7 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi) const char act[]= "now " "wait_for signal.get_unix_timestamp"; - DBUG_ASSERT(opt_debug_sync_timeout > 0); + DBUG_ASSERT(debug_sync_service); DBUG_ASSERT(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act))); };); @@ -1392,7 +1392,7 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi) const char act[]= "now " "wait_for signal.get_server_id"; - DBUG_ASSERT(opt_debug_sync_timeout > 0); + DBUG_ASSERT(debug_sync_service); DBUG_ASSERT(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act))); };); @@ -1791,6 +1791,54 @@ Waiting for the slave SQL thread to free enough relay log space"); !(slave_killed=io_slave_killed(thd,mi)) && !rli->ignore_log_space_limit) mysql_cond_wait(&rli->log_space_cond, &rli->log_space_lock); + + /* + Makes the IO thread read only one event at a time + until the SQL thread is able to purge the relay + logs, freeing some space. + + Therefore, once the SQL thread processes this next + event, it goes to sleep (no more events in the queue), + sets ignore_log_space_limit=true and wakes the IO thread. + However, this event may have been enough already for + the SQL thread to purge some log files, freeing + rli->log_space_total . + + This guarantees that the SQL and IO thread move + forward only one event at a time (to avoid deadlocks), + when the relay space limit is reached. It also + guarantees that when the SQL thread is prepared to + rotate (to be able to purge some logs), the IO thread + will know about it and will rotate. + + NOTE: The ignore_log_space_limit is only set when the SQL + thread sleeps waiting for events. + + */ + if (rli->ignore_log_space_limit) + { +#ifndef DBUG_OFF + { + char llbuf1[22], llbuf2[22]; + DBUG_PRINT("info", ("log_space_limit=%s " + "log_space_total=%s " + "ignore_log_space_limit=%d " + "sql_force_rotate_relay=%d", + llstr(rli->log_space_limit,llbuf1), + llstr(rli->log_space_total,llbuf2), + (int) rli->ignore_log_space_limit, + (int) rli->sql_force_rotate_relay)); + } +#endif + if (rli->sql_force_rotate_relay) + { + rotate_relay_log(rli->mi); + rli->sql_force_rotate_relay= false; + } + + rli->ignore_log_space_limit= false; + } + thd->exit_cond(save_proc_info); DBUG_RETURN(slave_killed); } @@ -3037,7 +3085,7 @@ connected: const char act[]= "now " "wait_for signal.io_thread_let_running"; - DBUG_ASSERT(opt_debug_sync_timeout > 0); + DBUG_ASSERT(debug_sync_service); DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); };); @@ -4115,8 +4163,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) { int error= 0; String error_msg; - ulong inc_pos; - ulong event_pos; + ulonglong inc_pos; + ulonglong event_pos; Relay_log_info *rli= &mi->rli; mysql_mutex_t *log_lock= rli->relay_log.get_log_lock(); ulong s_id; @@ -5066,19 +5114,45 @@ static Log_event* next_event(Relay_log_info* rli) constraint, because we do not want the I/O thread to block because of space (it's ok if it blocks for any other reason (e.g. because the master does not send anything). Then the I/O thread stops waiting - and reads more events. - The SQL thread decides when the I/O thread should take log_space_limit - into account again : ignore_log_space_limit is reset to 0 - in purge_first_log (when the SQL thread purges the just-read relay - log), and also when the SQL thread starts. We should also reset - ignore_log_space_limit to 0 when the user does RESET SLAVE, but in - fact, no need as RESET SLAVE requires that the slave + and reads one more event and starts honoring log_space_limit again. + + If the SQL thread needs more events to be able to rotate the log (it + might need to finish the current group first), then it can ask for one + more at a time. Thus we don't outgrow the relay log indefinitely, + but rather in a controlled manner, until the next rotate. + + When the SQL thread starts it sets ignore_log_space_limit to false. + We should also reset ignore_log_space_limit to 0 when the user does + RESET SLAVE, but in fact, no need as RESET SLAVE requires that the slave be stopped, and the SQL thread sets ignore_log_space_limit to 0 when it stops. */ mysql_mutex_lock(&rli->log_space_lock); - // prevent the I/O thread from blocking next times - rli->ignore_log_space_limit= 1; + + /* + If we have reached the limit of the relay space and we + are going to sleep, waiting for more events: + + 1. If outside a group, SQL thread asks the IO thread + to force a rotation so that the SQL thread purges + logs next time it processes an event (thus space is + freed). + + 2. If in a group, SQL thread asks the IO thread to + ignore the limit and queues yet one more event + so that the SQL thread finishes the group and + is are able to rotate and purge sometime soon. + */ + if (rli->log_space_limit && + rli->log_space_limit < rli->log_space_total) + { + /* force rotation if not in an unfinished group */ + rli->sql_force_rotate_relay= !rli->is_in_group(); + + /* ask for one more event */ + rli->ignore_log_space_limit= true; + } + /* If the I/O thread is blocked, unblock it. Ok to broadcast after unlock, because the mutex is only destroyed in diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index f88aed7ab3d..14f49ecc077 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2002, 2012, 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 diff --git a/sql/sp_cache.h b/sql/sp_cache.h index ba70bf32400..b21d4c4bf25 100644 --- a/sql/sp_cache.h +++ b/sql/sp_cache.h @@ -1,5 +1,5 @@ /* -*- C++ -*- */ -/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2002, 2012, 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 diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 355b6f1788c..9a356cb3321 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -158,7 +158,7 @@ sp_get_item_value(THD *thd, Item *item, String *str) buf.append(result->charset()->csname); if (cs->escape_with_backslash_is_dangerous) buf.append(' '); - append_query_string(cs, result, &buf); + append_query_string(thd, cs, result, &buf); buf.append(" COLLATE '"); buf.append(item->collation.collation->name); buf.append('\''); @@ -3557,6 +3557,23 @@ sp_instr_hpush_jump::opt_mark(sp_head *sp, List<sp_instr> *leads) m_optdest= sp->get_instr(m_dest); } sp->add_mark_lead(m_dest, leads); + + /* + For continue handlers, all instructions in the scope of the handler + are possible leads. For example, the instruction after freturn might + be executed if the freturn triggers the condition handled by the + continue handler. + + m_dest marks the start of the handler scope. It's added as a lead + above, so we start on m_dest+1 here. + m_opt_hpop is the hpop marking the end of the handler scope. + */ + if (m_type == SP_HANDLER_CONTINUE) + { + for (uint scope_ip= m_dest+1; scope_ip <= m_opt_hpop; scope_ip++) + sp->add_mark_lead(scope_ip, leads); + } + return m_ip+1; } diff --git a/sql/sp_head.h b/sql/sp_head.h index c79b5dfbd0b..409db33ef02 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -1017,7 +1017,7 @@ class sp_instr_hpush_jump : public sp_instr_jump public: sp_instr_hpush_jump(uint ip, sp_pcontext *ctx, int htype, uint fp) - : sp_instr_jump(ip, ctx), m_type(htype), m_frame(fp) + : sp_instr_jump(ip, ctx), m_type(htype), m_frame(fp), m_opt_hpop(0) { m_cond.empty(); } @@ -1039,6 +1039,15 @@ public: return m_ip; } + virtual void backpatch(uint dest, sp_pcontext *dst_ctx) + { + DBUG_ASSERT(!m_dest || !m_opt_hpop); + if (!m_dest) + m_dest= dest; + else + m_opt_hpop= dest; + } + inline void add_condition(struct sp_cond_type *cond) { m_cond.push_front(cond); @@ -1048,6 +1057,7 @@ private: int m_type; ///< Handler type uint m_frame; + uint m_opt_hpop; // hpop marking end of handler scope. List<struct sp_cond_type> m_cond; }; // class sp_instr_hpush_jump : public sp_instr_jump diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 5897d74582a..f8c602e6482 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -442,12 +442,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0)); DBUG_RETURN(TRUE); } - uint num_parts_found; - uint num_parts_opt= alter_info->partition_names.elements; - num_parts_found= set_part_state(alter_info, table->table->part_info, - PART_ADMIN); - if (num_parts_found != num_parts_opt && - (!(alter_info->flags & ALTER_ALL_PARTITION))) + if (set_part_state(alter_info, table->table->part_info, PART_ADMIN)) { char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE]; size_t length; @@ -896,6 +891,9 @@ send_result_message: DBUG_RETURN(FALSE); err: + /* Make sure this table instance is not reused after the failure. */ + if (table && table->table) + table->table->m_needs_reopen= true; trans_rollback_stmt(thd); trans_rollback(thd); close_thread_tables(thd); // Shouldn't be needed diff --git a/sql/sql_base.cc b/sql/sql_base.cc index d0404693405..d4aeedeb852 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. Copyright (c) 2010, 2011 Monty Program Ab This program is free software; you can redistribute it and/or modify @@ -220,7 +220,8 @@ static bool auto_repair_table(THD *thd, TABLE_LIST *table_list); static void free_cache_entry(TABLE *entry); static bool has_write_table_with_auto_increment(TABLE_LIST *tables); - +static bool +has_write_table_with_auto_increment_and_select(TABLE_LIST *tables); uint cached_open_tables(void) { @@ -523,7 +524,7 @@ static void table_def_use_table(THD *thd, TABLE *table) static void table_def_unuse_table(TABLE *table) { - THD *thd= table->in_use; + THD *thd __attribute__((unused))= table->in_use; DBUG_ASSERT(table->in_use); /* We shouldn't put the table to 'unused' list if the share is old. */ @@ -5746,9 +5747,20 @@ 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); + /* 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. @@ -6167,15 +6179,22 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list, */ if (*ref && !(*ref)->is_autogenerated_name) { - if (register_tree_change && - thd->stmt_arena->is_stmt_prepare_or_first_stmt_execute()) - arena= thd->activate_stmt_arena_if_needed(&backup); - item->set_name((*ref)->name, (*ref)->name_length, - system_charset_info); - item->real_item()->set_name((*ref)->name, (*ref)->name_length, - system_charset_info); - if (arena) - thd->restore_active_arena(arena, &backup); + if (register_tree_change) + { + item->set_name_for_rollback(thd, (*ref)->name, + (*ref)->name_length, + system_charset_info); + item->real_item()->set_name_for_rollback(thd, (*ref)->name, + (*ref)->name_length, + system_charset_info); + } + else + { + item->set_name((*ref)->name, (*ref)->name_length, + system_charset_info); + item->real_item()->set_name((*ref)->name, (*ref)->name_length, + system_charset_info); + } } if (register_tree_change) thd->change_item_tree(ref, item); @@ -7457,6 +7476,14 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, */ result= FALSE; + /* + Save the lists made during natural join matching (because + the matching done only once but we need the list in case + of prepared statements). + */ + table_ref_1->persistent_used_items= table_ref_1->used_items; + table_ref_2->persistent_used_items= table_ref_2->used_items; + err: if (arena) thd->restore_active_arena(arena, &backup); @@ -8820,14 +8847,9 @@ fill_record(THD * thd, List<Item> &fields, List<Item> &values, } /* Update virtual fields*/ thd->abort_on_warning= FALSE; - if (vcol_table) - { - if (vcol_table->vfield) - { - if (update_virtual_fields(thd, vcol_table, TRUE)) - goto err; - } - } + if (vcol_table && vcol_table->vfield && + update_virtual_fields(thd, vcol_table, TRUE)) + goto err; thd->abort_on_warning= save_abort_on_warning; thd->no_errors= save_no_errors; DBUG_RETURN(thd->is_error()); @@ -9440,6 +9462,41 @@ has_write_table_with_auto_increment(TABLE_LIST *tables) 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); +} + + /* Open and lock system tables for read. diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 9c86b2838c4..210d259f364 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1,5 +1,4 @@ -/* - Copyright (c) 2000, 2010, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2011, 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 diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 5b63201a910..283327abe61 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -145,9 +145,9 @@ Key::Key(const Key &rhs, MEM_ROOT *mem_root) */ Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root) - :Key(rhs), + :Key(rhs,mem_root), ref_table(rhs.ref_table), - ref_columns(rhs.ref_columns), + ref_columns(rhs.ref_columns,mem_root), delete_opt(rhs.delete_opt), update_opt(rhs.update_opt), match_opt(rhs.match_opt) @@ -3930,6 +3930,9 @@ void THD::restore_backup_open_tables_state(Open_tables_backup *backup) extern "C" int thd_killed(const MYSQL_THD thd) { + if (!thd) + thd= current_thd; + if (!(thd->killed & KILL_HARD_BIT)) return 0; return thd->killed; diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index e96068484eb..04e46bfa1e6 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2007, 2011, Oracle and/or its affiliates. - Copyright (c) 2008-2012 Monty Program Ab + Copyright (c) 2007, 2012, Oracle and/or its affiliates. + Copyright (c) 2008, 2012, 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 diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 7fc623daf88..bde7a082f42 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -327,7 +327,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, while (!(error=info.read_record(&info)) && !thd->killed && ! thd->is_error()) { - update_virtual_fields(thd, table); + if (table->vfield) + update_virtual_fields(thd, table); thd->examined_row_count++; // thd->is_error() is tested to disallow delete row on error if (!select || select->skip_record(thd) > 0) diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index c67618f0680..d03b38171fc 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -922,7 +922,8 @@ retry: goto ok; } /* Generate values for virtual fields */ - update_virtual_fields(thd, table); + if (table->vfield) + update_virtual_fields(thd, table); if (cond && !cond->val_int()) { if (thd->is_error()) diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index e0e1b175116..f953cf4df57 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -3345,23 +3345,26 @@ int JOIN_TAB_SCAN::next() int skip_rc; READ_RECORD *info= &join_tab->read_record; SQL_SELECT *select= join_tab->cache_select; + TABLE *table= join_tab->table; + THD *thd= join->thd; + if (is_first_record) is_first_record= FALSE; else err= info->read_record(info); - if (!err) - update_virtual_fields(join->thd, join_tab->table); - while (!err && select && (skip_rc= select->skip_record(join->thd)) <= 0) + if (!err && table->vfield) + update_virtual_fields(thd, table); + while (!err && select && (skip_rc= select->skip_record(thd)) <= 0) { - if (join->thd->killed || skip_rc < 0) + if (thd->killed || skip_rc < 0) return 1; /* Move to the next record if the last retrieved record does not meet the condition pushed to the table join_tab. */ err= info->read_record(info); - if (!err) - update_virtual_fields(join->thd, join_tab->table); + if (!err && table->vfield) + update_virtual_fields(thd, table); } return err; } @@ -3875,7 +3878,8 @@ int JOIN_TAB_SCAN_MRR::next() */ DBUG_ASSERT(cache->buff <= (uchar *) (*ptr) && (uchar *) (*ptr) <= cache->end_pos); - update_virtual_fields(join->thd, join_tab->table); + if (join_tab->table->vfield) + update_virtual_fields(join->thd, join_tab->table); } return rc; } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 070bcdfcfd4..f7887b2e8b9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1,5 +1,4 @@ -/* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2012, 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 @@ -63,9 +62,11 @@ Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] = ER_BINLOG_UNSAFE_MIXED_STATEMENT, ER_BINLOG_UNSAFE_INSERT_IGNORE_SELECT, ER_BINLOG_UNSAFE_INSERT_SELECT_UPDATE, + ER_BINLOG_UNSAFE_WRITE_AUTOINC_SELECT, ER_BINLOG_UNSAFE_REPLACE_SELECT, ER_BINLOG_UNSAFE_CREATE_IGNORE_SELECT, ER_BINLOG_UNSAFE_CREATE_REPLACE_SELECT, + ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC, ER_BINLOG_UNSAFE_UPDATE_IGNORE }; @@ -470,6 +471,8 @@ void lex_start(THD *thd) lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED; lex->select_lex.init_order(); lex->select_lex.group_list.empty(); + if (lex->select_lex.group_list_ptrs) + lex->select_lex.group_list_ptrs->clear(); lex->describe= 0; lex->subqueries= FALSE; lex->context_analysis_only= 0; @@ -1891,6 +1894,8 @@ void st_select_lex::init_select() sj_nests.empty(); sj_subselects.empty(); group_list.empty(); + if (group_list_ptrs) + group_list_ptrs->clear(); type= db= 0; having= 0; table_join_options= 0; @@ -3298,6 +3303,8 @@ static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl) The passed WHERE and HAVING are to be saved for the future executions. This function saves it, and returns a copy which can be thrashed during this execution of the statement. By saving/thrashing here we mean only + We also save the chain of ORDER::next in group_list, in case + the list is modified by remove_const(). AND/OR trees. The function also calls fix_prepare_info_in_table_list that saves all ON expressions. @@ -3309,6 +3316,19 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds, if (!thd->stmt_arena->is_conventional() && first_execution) { first_execution= 0; + if (group_list.first) + { + if (!group_list_ptrs) + { + void *mem= thd->stmt_arena->alloc(sizeof(Group_list_ptrs)); + group_list_ptrs= new (mem) Group_list_ptrs(thd->stmt_arena->mem_root); + } + group_list_ptrs->reserve(group_list.elements); + for (ORDER *order= group_list.first; order; order= order->next) + { + group_list_ptrs->push_back(order); + } + } if (*conds) { thd->check_and_register_item_tree(&prep_where, conds); @@ -4197,3 +4217,7 @@ void binlog_unsafe_map_init() BINLOG_DIRECT_OFF & TRX_CACHE_NOT_EMPTY); } #endif + +#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION +template class Mem_root_array<ORDER*, true>; +#endif diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 718c9c7e6a2..f1ee6cf22ec 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1,5 +1,4 @@ -/* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2012, 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 @@ -25,6 +24,7 @@ #include "sql_trigger.h" #include "item.h" /* From item_subselect.h: subselect_union_engine */ #include "thr_lock.h" /* thr_lock_type, TL_UNLOCK */ +#include "mem_root_array.h" /* YACC and LEX Definitions */ @@ -262,6 +262,7 @@ enum enum_drop_mode #define TL_OPTION_ALIAS 8 typedef List<Item> List_item; +typedef Mem_root_array<ORDER*, true> Group_list_ptrs; /* SERVERS CACHE CHANGES */ typedef struct st_lex_server_options @@ -736,7 +737,16 @@ public: enum olap_type olap; /* FROM clause - points to the beginning of the TABLE_LIST::next_local list. */ SQL_I_List<TABLE_LIST> table_list; - SQL_I_List<ORDER> group_list; /* GROUP BY clause. */ + + /* + GROUP BY clause. + This list may be mutated during optimization (by remove_const()), + so for prepared statements, we keep a copy of the ORDER.next pointers in + group_list_ptrs, and re-establish the original list before each execution. + */ + SQL_I_List<ORDER> group_list; + Group_list_ptrs *group_list_ptrs; + List<Item> item_list; /* list of fields & expressions */ List<String> interval_list; bool is_item_list_lookup; @@ -942,7 +952,8 @@ public: bool test_limit(); friend void lex_start(THD *thd); - st_select_lex() : n_sum_items(0), n_child_sum_items(0) {} + st_select_lex() : group_list_ptrs(NULL), n_sum_items(0), n_child_sum_items(0) + {} void make_empty_select() { init_query(); @@ -1374,6 +1385,13 @@ public: BINLOG_STMT_UNSAFE_INSERT_SELECT_UPDATE, /** + Query that writes to a table with auto_inc column after selecting from + other tables are unsafe as the order in which the rows are retrieved by + select may differ on master and slave. + */ + BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT, + + /** INSERT...REPLACE SELECT is unsafe because which rows are replaced depends on the order that rows are retrieved by SELECT. This order cannot be predicted and may differ on master and the slave. @@ -1395,6 +1413,14 @@ public: BINLOG_STMT_UNSAFE_CREATE_REPLACE_SELECT, /** + CREATE TABLE...SELECT on a table with auto-increment column is unsafe + because which rows are replaced depends on the order that rows are + retrieved from SELECT. This order cannot be predicted and may differ on + master and the slave + */ + BINLOG_STMT_UNSAFE_CREATE_SELECT_AUTOINC, + + /** UPDATE...IGNORE is unsafe because which rows are ignored depends on the order that rows are updated. This order cannot be predicted and may differ on master and the slave. diff --git a/sql/sql_list.h b/sql/sql_list.h index 6cc05ff1f62..e3a04c36071 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -260,6 +260,7 @@ public: last= &first; return tmp->info; } + /* Remove from this list elements that are contained in the passed list. We assume that the passed list is a tail of this list (that is, the whole diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a955b434319..51d81616c24 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,6 +1,5 @@ -/* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2008-2012 Monty Program Ab +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2008, 2012, 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 @@ -3379,7 +3378,7 @@ end_with_restore_list: const char act2[]= "now " "signal signal.continued"; - DBUG_ASSERT(opt_debug_sync_timeout > 0); + DBUG_ASSERT(debug_sync_service); DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act1))); DBUG_ASSERT(!debug_sync_set_action(thd, diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 070b48f7a7b..9ba0569f1e0 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -4398,11 +4398,20 @@ error: } -/* - Sets which partitions to be used in the command +/** + Sets which partitions to be used in the command. + + @param alter_info Alter_info pointer holding partition names and flags. + @param tab_part_info partition_info holding all partitions. + @param part_state Which state to set for the named partitions. + + @return Operation status + @retval false Success + @retval true Failure */ -uint set_part_state(Alter_info *alter_info, partition_info *tab_part_info, - enum partition_state part_state) + +bool set_part_state(Alter_info *alter_info, partition_info *tab_part_info, + enum partition_state part_state) { uint part_count= 0; uint num_parts_found= 0; @@ -4428,7 +4437,21 @@ uint set_part_state(Alter_info *alter_info, partition_info *tab_part_info, else part_elem->part_state= PART_NORMAL; } while (++part_count < tab_part_info->num_parts); - return num_parts_found; + + if (num_parts_found != alter_info->partition_names.elements && + !(alter_info->flags & ALTER_ALL_PARTITION)) + { + /* Not all given partitions found, revert and return failure */ + part_it.rewind(); + part_count= 0; + do + { + partition_element *part_elem= part_it++; + part_elem->part_state= PART_NORMAL; + } while (++part_count < tab_part_info->num_parts); + return true; + } + return false; } @@ -4947,11 +4970,7 @@ that are reorganised. } else if (alter_info->flags & ALTER_REBUILD_PARTITION) { - uint num_parts_found; - uint num_parts_opt= alter_info->partition_names.elements; - num_parts_found= set_part_state(alter_info, tab_part_info, PART_CHANGED); - if (num_parts_found != num_parts_opt && - (!(alter_info->flags & ALTER_ALL_PARTITION))) + if (set_part_state(alter_info, tab_part_info, PART_CHANGED)) { my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0), "REBUILD"); goto err; diff --git a/sql/sql_partition.h b/sql/sql_partition.h index cc11d859903..2fd9b4c3d75 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -254,7 +254,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, char *db, const char *table_name, TABLE *fast_alter_table); -uint set_part_state(Alter_info *alter_info, partition_info *tab_part_info, +bool set_part_state(Alter_info *alter_info, partition_info *tab_part_info, enum partition_state part_state); uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, HA_CREATE_INFO *create_info, diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 6a1a9221064..4e80549fe9d 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2005, 2011, Oracle and/or its affiliates. + Copyright (c) 2005, 2012, Oracle and/or its affiliates. Copyright (c) 2010, 2011, Monty Program Ab This program is free software; you can redistribute it and/or modify @@ -980,9 +980,13 @@ plugin_ref plugin_lock(THD *thd, plugin_ref ptr) without a mutex. */ if (! plugin_dlib(ptr)) + { + plugin_ref_to_int(ptr)->locks_total++; DBUG_RETURN(ptr); + } #endif mysql_mutex_lock(&LOCK_plugin); + plugin_ref_to_int(ptr)->locks_total++; rc= my_intern_plugin_lock_ci(lex, ptr); mysql_mutex_unlock(&LOCK_plugin); DBUG_RETURN(rc); @@ -1179,6 +1183,10 @@ static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check) } plugin->state= PLUGIN_IS_UNINITIALIZED; + /* maintain the obsolete @@have_innodb variable */ + if (!my_strcasecmp(&my_charset_latin1, plugin->name.str, "InnoDB")) + have_innodb= SHOW_OPTION_DISABLED; + /* We do the check here because NDB has a worker THD which doesn't exit until NDB is shut down. @@ -1520,6 +1528,10 @@ int plugin_init(int *argc, char **argv, int flags) goto err; } + /* prepare debug_sync service */ + DBUG_ASSERT(strcmp(list_of_services[5].name, "debug_sync_service") == 0); + list_of_services[5].service= *(void**)&debug_sync_C_callback_ptr; + mysql_mutex_lock(&LOCK_plugin); initialized= 1; @@ -1583,7 +1595,11 @@ int plugin_init(int *argc, char **argv, int flags) { if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED && plugin_initialize(plugin_ptr)) - goto err_unlock; + { + if (mandatory) + goto err_unlock; + plugin_ptr->state= PLUGIN_IS_DISABLED; + } } /* @@ -2381,11 +2397,11 @@ static int check_func_bool(THD *thd, struct st_mysql_sys_var *var, { if (value->val_int(value, &tmp) < 0) goto err; - if (tmp > 1) + if (tmp != 0 && tmp != 1) goto err; result= (int) tmp; } - *(my_bool *) save= -result; + *(my_bool *) save= result ? 1 : 0; return 0; err: return 1; @@ -2575,7 +2591,7 @@ err: static void update_func_bool(THD *thd, struct st_mysql_sys_var *var, void *tgt, const void *save) { - *(my_bool *) tgt= *(my_bool *) save ? TRUE : FALSE; + *(my_bool *) tgt= *(my_bool *) save ? 1 : 0; } @@ -3553,19 +3569,6 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, opt->name, plugin_name); } } - /* - PLUGIN_VAR_STR command-line options without PLUGIN_VAR_MEMALLOC, point - directly to values in the argv[] array. For plugins started at the - server startup, argv[] array is allocated with load_defaults(), and - freed when the server is shut down. But for plugins loaded with - INSTALL PLUGIN, the memory allocated with load_defaults() is freed with - freed() at the end of mysql_install_plugin(). Which means we cannot - allow any pointers into that area. - Thus, for all plugins loaded after the server was started, - we force all command-line options to be PLUGIN_VAR_MEMALLOC - */ - if (mysqld_server_started && !(opt->flags & PLUGIN_VAR_NOCMDOPT)) - opt->flags|= PLUGIN_VAR_MEMALLOC; break; case PLUGIN_VAR_ENUM: if (!opt->check) @@ -3793,8 +3796,29 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, error= 1; for (opt= tmp->plugin->system_vars; opt && *opt; opt++) { - st_mysql_sys_var *o; - if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR)) + st_mysql_sys_var *o= *opt; + + /* + PLUGIN_VAR_STR command-line options without PLUGIN_VAR_MEMALLOC, point + directly to values in the argv[] array. For plugins started at the + server startup, argv[] array is allocated with load_defaults(), and + freed when the server is shut down. But for plugins loaded with + INSTALL PLUGIN, the memory allocated with load_defaults() is freed with + freed() at the end of mysql_install_plugin(). Which means we cannot + allow any pointers into that area. + Thus, for all plugins loaded after the server was started, + we copy string values to a plugin's memroot. + */ + if (mysqld_server_started && + ((o->flags & (PLUGIN_VAR_STR | PLUGIN_VAR_NOCMDOPT | + PLUGIN_VAR_MEMALLOC)) == PLUGIN_VAR_STR)) + { + sysvar_str_t* str= (sysvar_str_t *)o; + if (*str->value) + *str->value= strdup_root(mem_root, *str->value); + } + + if (o->flags & PLUGIN_VAR_NOSYSVAR) continue; if ((var= find_bookmark(plugin_name.str, o->name, o->flags))) v= new (mem_root) sys_var_pluginvar(&chain, var->key + 1, o); diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index fc059142e24..eaa368f3515 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -99,6 +99,7 @@ struct st_plugin_int struct st_plugin_dl *plugin_dl; uint state; uint ref_count; /* number of threads using the plugin */ + uint locks_total; /* how many times the plugin was locked */ void *data; /* plugin type specific, e.g. handlerton */ MEM_ROOT mem_root; /* memory for dynamic plugin structures */ sys_var *system_vars; /* server variables for this plugin */ diff --git a/sql/sql_plugin_services.h b/sql/sql_plugin_services.h index bd6d136585a..c779547059d 100644 --- a/sql/sql_plugin_services.h +++ b/sql/sql_plugin_services.h @@ -54,14 +54,6 @@ static struct progress_report_service_st progress_report_handler= { set_thd_proc_info }; -static struct logger_service_st logger_handler= { - logger_open, - logger_close, - logger_vprintf, - logger_printf, - logger_rotate -}; - static struct st_service_ref list_of_services[]= { { "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler }, @@ -69,6 +61,6 @@ static struct st_service_ref list_of_services[]= { "thd_wait_service", VERSION_thd_wait, &thd_wait_handler }, { "my_thread_scheduler_service", VERSION_my_thread_scheduler, &my_thread_scheduler_handler }, { "progress_report_service", VERSION_progress_report, &progress_report_handler }, - { "logger_service", VERSION_logger, &logger_handler }, + { "debug_sync_service", VERSION_debug_sync, 0 } // updated in plugin_init() }; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index e25751a4b88..ed437c498e6 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2002, 2011, Oracle and/or its affiliates. - Copyright (c) 2008-2011 Monty Program Ab +/* Copyright (c) 2002, 2012, Oracle and/or its affiliates. + Copyright (c) 2008, 2011, 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 @@ -888,7 +888,7 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, */ else if (! is_param_long_data_type(param)) DBUG_RETURN(1); - res= param->query_val_str(&str); + res= param->query_val_str(thd, &str); if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ @@ -1062,7 +1062,7 @@ static bool emb_insert_params_with_log(Prepared_statement *stmt, DBUG_RETURN(1); } } - res= param->query_val_str(&str); + res= param->query_val_str(thd, &str); if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ @@ -1208,7 +1208,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt, setup_one_conversion_function(thd, param, param->param_type); if (param->set_from_user_var(thd, entry)) DBUG_RETURN(1); - val= param->query_val_str(&buf); + val= param->query_val_str(thd, &buf); if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ @@ -2512,6 +2512,14 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) DBUG_ASSERT(sl->join == 0); ORDER *order; /* Fix GROUP list */ + if (sl->group_list_ptrs && sl->group_list_ptrs->size() > 0) + { + for (uint ix= 0; ix < sl->group_list_ptrs->size() - 1; ++ix) + { + order= sl->group_list_ptrs->at(ix); + order->next= sl->group_list_ptrs->at(ix+1); + } + } for (order= sl->group_list.first; order; order= order->next) order->item= &order->item_ptr; /* Fix ORDER list */ diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index e743e474747..b3348698a35 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -1,6 +1,5 @@ -/* - Copyright (c) 2007, 2010, Oracle and/or its affiliates. - Copyright (c) 2008-2011 Monty Program Ab +/* Copyright (c) 2007, 2011, Oracle and/or its affiliates. + Copyright (c) 2008, 2011, 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 diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index ecb47324552..816ae57c828 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1,6 +1,5 @@ -/* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2008-2011 Monty Program Ab +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2008, 2011, 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 @@ -625,7 +624,6 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, String* const packet = &thd->packet; int error; const char *errmsg = "Unknown error", *tmp_msg; - char llbuff0[22], llbuff1[22], llbuff2[22]; char error_text[MAX_SLAVE_ERRMSG]; // to be send to slave via my_message() NET* net = &thd->net; mysql_mutex_t *log_lock; @@ -906,7 +904,7 @@ impossible position"; const char act[]= "now " "wait_for signal.continue"; - DBUG_ASSERT(opt_debug_sync_timeout > 0); + DBUG_ASSERT(debug_sync_service); DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act))); const char act2[]= @@ -1181,12 +1179,14 @@ err: detailing the fatal error message with coordinates of the last position read. */ - const char *fmt= "%s; the start event position from '%s' at %s, the last event was read from '%s' at %s, the last byte read was read from '%s' at %s."; - my_snprintf(error_text, sizeof(error_text), fmt, errmsg, - my_basename(p_start_coord->file_name), - (llstr(p_start_coord->pos, llbuff0), llbuff0), - my_basename(p_coord->file_name), (llstr(p_coord->pos, llbuff1), llbuff1), - my_basename(log_file_name), (llstr(my_b_tell(&log), llbuff2), llbuff2)); + my_snprintf(error_text, sizeof(error_text), + "%s; the first event '%s' at %lld, " + "the last event read from '%s' at %lld, " + "the last byte read from '%s' at %lld.", + errmsg, + my_basename(p_start_coord->file_name), p_start_coord->pos, + my_basename(p_coord->file_name), p_coord->pos, + my_basename(log_file_name), my_b_tell(&log)); } else strcpy(error_text, errmsg); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 35c45a9033c..8f8ecd1725d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -643,7 +643,7 @@ JOIN::prepare(Item ***rref_pointer_array, */ if (select_lex->master_unit()->item && // 1) select_lex->first_cond_optimization && // 2) - !(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW)) // 3) + !thd->lex->is_view_context_analysis()) // 3) { remove_redundant_subquery_clauses(select_lex); } @@ -3085,12 +3085,11 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, key_map const_ref, eq_part; bool has_expensive_keyparts; TABLE **table_vector; - JOIN_TAB *stat,*stat_end,*s,**stat_ref; + JOIN_TAB *stat,*stat_end,*s,**stat_ref, **stat_vector; KEYUSE *keyuse,*start_keyuse; table_map outer_join=0; table_map no_rows_const_tables= 0; SARGABLE_PARAM *sargables= 0; - JOIN_TAB *stat_vector[MAX_TABLES+1]; List_iterator<TABLE_LIST> ti(tables_list); TABLE_LIST *tables; DBUG_ENTER("make_join_statistics"); @@ -3099,9 +3098,19 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, table_count=join->table_count; stat=(JOIN_TAB*) join->thd->calloc(sizeof(JOIN_TAB)*(table_count)); - stat_ref=(JOIN_TAB**) join->thd->alloc(sizeof(JOIN_TAB*)*MAX_TABLES); + stat_ref=(JOIN_TAB**) join->thd->alloc(sizeof(JOIN_TAB*)* + (MAX_TABLES + table_count + 1)); + stat_vector= stat_ref + MAX_TABLES; table_vector=(TABLE**) join->thd->alloc(sizeof(TABLE*)*(table_count*2)); - if (!stat || !stat_ref || !table_vector) + join->positions= new (join->thd->mem_root) POSITION[(table_count+1)]; + /* + best_positions is ok to allocate with alloc() as we copy things to it with + memcpy() + */ + join->best_positions= (POSITION*) join->thd->alloc(sizeof(POSITION)* + (table_count +1)); + + if (join->thd->is_fatal_error) DBUG_RETURN(1); // Eom /* purecov: inspected */ join->best_ref=stat_vector; @@ -3122,6 +3131,12 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, table->pos_in_table_list= tables; error= tables->fetch_number_of_rows(); +#ifdef WITH_PARTITION_STORAGE_ENGINE + const bool no_partitions_used= table->no_partitions_used; +#else + const bool no_partitions_used= FALSE; +#endif + DBUG_EXECUTE_IF("bug11747970_raise_error", { if (!error) @@ -3153,13 +3168,10 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, if (*s->on_expr_ref) { /* s is the only inner table of an outer join */ -#ifdef WITH_PARTITION_STORAGE_ENGINE if (!table->is_filled_at_execution() && - (!table->file->stats.records || table->no_partitions_used) && !embedding) -#else - if (!table->is_filled_at_execution() && - !table->file->stats.records && !embedding) -#endif + ((!table->file->stats.records && + (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT)) || + no_partitions_used) && !embedding) { // Empty table s->dependent= 0; // Ignore LEFT JOIN depend. no_rows_const_tables |= table->map; @@ -3199,16 +3211,12 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, if (inside_an_outer_join) continue; } -#ifdef WITH_PARTITION_STORAGE_ENGINE - const bool no_partitions_used= table->no_partitions_used; -#else - const bool no_partitions_used= FALSE; -#endif - if (!table->is_filled_at_execution() && - (table->s->system || table->file->stats.records <= 1 || + if (!table->is_filled_at_execution() && + (table->s->system || + (table->file->stats.records <= 1 && + (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT)) || no_partitions_used) && !s->dependent && - (table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) && !table->fulltext_searched && !join->no_const_tables) { set_position(join,const_count++,s,(KEYUSE*) 0); @@ -5757,6 +5765,114 @@ best_access_path(JOIN *join, } +/* + Find JOIN_TAB's embedding (i.e, parent) subquery. + - For merged semi-joins, tables inside the semi-join nest have their + semi-join nest as parent. We intentionally ignore results of table + pullout action here. + - For non-merged semi-joins (JTBM tabs), the embedding subquery is the + JTBM join tab itself. +*/ + +static TABLE_LIST* get_emb_subq(JOIN_TAB *tab) +{ + TABLE_LIST *tlist= tab->table->pos_in_table_list; + if (tlist->jtbm_subselect) + return tlist; + TABLE_LIST *embedding= tlist->embedding; + if (!embedding || !embedding->sj_subq_pred) + return NULL; + return embedding; +} + + +/* + Choose initial table order that "helps" semi-join optimizations. + + The idea is that we should start with the order that is the same as the one + we would have had if we had semijoin=off: + - Top-level tables go first + - subquery tables are grouped together by the subquery they are in, + - subquery tables are attached where the subquery predicate would have been + attached if we had semi-join off. + + This function relies on join_tab_cmp()/join_tab_cmp_straight() to produce + certain pre-liminary ordering, see compare_embedding_subqueries() for its + description. +*/ + +static void choose_initial_table_order(JOIN *join) +{ + TABLE_LIST *emb_subq; + JOIN_TAB **tab= join->best_ref + join->const_tables; + JOIN_TAB **tabs_end= tab + join->table_count - join->const_tables; + /* Find where the top-level JOIN_TABs end and subquery JOIN_TABs start */ + for (; tab != tabs_end; tab++) + { + if ((emb_subq= get_emb_subq(*tab))) + break; + } + uint n_subquery_tabs= tabs_end - tab; + + if (!n_subquery_tabs) + return; + + /* Copy the subquery JOIN_TABs to a separate array */ + JOIN_TAB *subquery_tabs[MAX_TABLES]; + memcpy(subquery_tabs, tab, sizeof(JOIN_TAB*) * n_subquery_tabs); + + JOIN_TAB **last_top_level_tab= tab; + JOIN_TAB **subq_tab= subquery_tabs; + JOIN_TAB **subq_tabs_end= subquery_tabs + n_subquery_tabs; + TABLE_LIST *cur_subq_nest= NULL; + for (; subq_tab < subq_tabs_end; subq_tab++) + { + if (get_emb_subq(*subq_tab)!= cur_subq_nest) + { + /* + Reached the part of subquery_tabs that covers tables in some subquery. + */ + cur_subq_nest= get_emb_subq(*subq_tab); + + /* Determine how many tables the subquery has */ + JOIN_TAB **last_tab_for_subq; + for (last_tab_for_subq= subq_tab; + last_tab_for_subq < subq_tabs_end && + get_emb_subq(*last_tab_for_subq) == cur_subq_nest; + last_tab_for_subq++) {} + uint n_subquery_tables= last_tab_for_subq - subq_tab; + + /* + Walk the original array and find where this subquery would have been + attached to + */ + table_map need_tables= cur_subq_nest->original_subq_pred_used_tables; + need_tables &= ~(join->const_table_map | PSEUDO_TABLE_BITS); + for (JOIN_TAB **top_level_tab= join->best_ref + join->const_tables; + top_level_tab < last_top_level_tab; + //top_level_tab < join->best_ref + join->table_count; + top_level_tab++) + { + need_tables &= ~(*top_level_tab)->table->map; + /* Check if this is the place where subquery should be attached */ + if (!need_tables) + { + /* Move away the top-level tables that are after top_level_tab */ + uint top_tail_len= last_top_level_tab - top_level_tab - 1; + memmove(top_level_tab + 1 + n_subquery_tables, top_level_tab + 1, + sizeof(JOIN_TAB*)*top_tail_len); + last_top_level_tab += n_subquery_tables; + memcpy(top_level_tab + 1, subq_tab, sizeof(JOIN_TAB*)*n_subquery_tables); + break; + } + } + DBUG_ASSERT(!need_tables); + subq_tab += n_subquery_tables - 1; + } + } +} + + /** Selects and invokes a search strategy for an optimal query plan. @@ -5812,9 +5928,21 @@ choose_plan(JOIN *join, table_map join_tables) */ jtab_sort_func= straight_join ? join_tab_cmp_straight : join_tab_cmp; } + + /* + psergey-todo: if we're not optimizing an SJM nest, + - sort that outer tables are first, and each sjm nest follows + - then, put each [sjm_table1, ... sjm_tableN] sub-array right where + WHERE clause pushdown would have put it. + */ my_qsort2(join->best_ref + join->const_tables, join->table_count - join->const_tables, sizeof(JOIN_TAB*), jtab_sort_func, (void*)join->emb_sjm_nest); + + if (!join->emb_sjm_nest) + { + choose_initial_table_order(join); + } join->cur_sj_inner_tables= 0; if (straight_join) @@ -5854,6 +5982,64 @@ choose_plan(JOIN *join, table_map join_tables) } +/* + Compare two join tabs based on the subqueries they are from. + - top-level join tabs go first + - then subqueries are ordered by their select_id (we're using this + criteria because we need a cross-platform, deterministic ordering) + + @return + 0 - equal + -1 - jt1 < jt2 + 1 - jt1 > jt2 +*/ + +static int compare_embedding_subqueries(JOIN_TAB *jt1, JOIN_TAB *jt2) +{ + /* Determine if the first table is originally from a subquery */ + TABLE_LIST *tbl1= jt1->table->pos_in_table_list; + uint tbl1_select_no; + if (tbl1->jtbm_subselect) + { + tbl1_select_no= + tbl1->jtbm_subselect->unit->first_select()->select_number; + } + else if (tbl1->embedding && tbl1->embedding->sj_subq_pred) + { + tbl1_select_no= + tbl1->embedding->sj_subq_pred->unit->first_select()->select_number; + } + else + tbl1_select_no= 1; /* Top-level */ + + /* Same for the second table */ + TABLE_LIST *tbl2= jt2->table->pos_in_table_list; + uint tbl2_select_no; + if (tbl2->jtbm_subselect) + { + tbl2_select_no= + tbl2->jtbm_subselect->unit->first_select()->select_number; + } + else if (tbl2->embedding && tbl2->embedding->sj_subq_pred) + { + tbl2_select_no= + tbl2->embedding->sj_subq_pred->unit->first_select()->select_number; + } + else + tbl2_select_no= 1; /* Top-level */ + + /* + Put top-level tables in front. Tables from within subqueries must follow, + grouped by their owner subquery. We don't care about the order that + subquery groups are in, because choose_initial_table_order() will re-order + the groups. + */ + if (tbl1_select_no != tbl2_select_no) + return tbl1_select_no > tbl2_select_no ? 1 : -1; + return 0; +} + + /** Compare two JOIN_TAB objects based on the number of accessed records. @@ -5870,6 +6056,9 @@ choose_plan(JOIN *join, table_map join_tables) a: dependent = 0x0 table->map = 0x1 found_records = 3 ptr = 0x907e6b0 b: dependent = 0x0 table->map = 0x2 found_records = 3 ptr = 0x907e838 c: dependent = 0x6 table->map = 0x10 found_records = 2 ptr = 0x907ecd0 + + As for subuqueries, this function must produce order that can be fed to + choose_initial_table_order(). @retval 1 if first is bigger @@ -5884,7 +6073,15 @@ join_tab_cmp(const void *dummy, const void* ptr1, const void* ptr2) { JOIN_TAB *jt1= *(JOIN_TAB**) ptr1; JOIN_TAB *jt2= *(JOIN_TAB**) ptr2; + int cmp; + if ((cmp= compare_embedding_subqueries(jt1, jt2)) != 0) + return cmp; + /* + After that, + take care about ordering imposed by LEFT JOIN constraints, + possible [eq]ref accesses, and numbers of matching records in the table. + */ if (jt1->dependent & jt2->table->map) return 1; if (jt2->dependent & jt1->table->map) @@ -5915,6 +6112,10 @@ join_tab_cmp_straight(const void *dummy, const void* ptr1, const void* ptr2) DBUG_ASSERT(!jt1->emb_sj_nest); DBUG_ASSERT(!jt2->emb_sj_nest); + int cmp; + if ((cmp= compare_embedding_subqueries(jt1, jt2)) != 0) + return cmp; + if (jt1->dependent & jt2->table->map) return 1; if (jt2->dependent & jt1->table->map) @@ -7634,7 +7835,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, if (keyuse->null_rejecting) j->ref.null_rejecting |= 1 << i; keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables; - if (!keyuse->used_tables && !thd->lex->describe) + if (!keyuse->val->used_tables() && !thd->lex->describe) { // Compare against constant store_key_item tmp(thd, keyinfo->key_part[i].field, @@ -10850,6 +11051,9 @@ finish: acceptable, as this happens rarely. The implementation without copying would be much more complicated. + For description of how equality propagation works with SJM nests, grep + for EqualityPropagationAndSjmNests. + @param left_item left term of the quality to be checked @param right_item right term of the equality to be checked @param item equality item if the equality originates from a condition @@ -10923,12 +11127,14 @@ static bool check_simple_equality(Item *left_item, Item *right_item, { /* left_item_equal of an upper level contains left_item */ left_item_equal= new Item_equal(left_item_equal); + left_item_equal->set_context_field(((Item_field*) left_item)); cond_equal->current_level.push_back(left_item_equal); } if (right_copyfl) { /* right_item_equal of an upper level contains right_item */ right_item_equal= new Item_equal(right_item_equal); + right_item_equal->set_context_field(((Item_field*) right_item)); cond_equal->current_level.push_back(right_item_equal); } @@ -10958,6 +11164,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item, Item_equal *item_equal= new Item_equal(orig_left_item, orig_right_item, FALSE); + item_equal->set_context_field((Item_field*)left_item); cond_equal->current_level.push_back(item_equal); } } @@ -11014,6 +11221,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item, { item_equal= new Item_equal(item_equal); cond_equal->current_level.push_back(item_equal); + item_equal->set_context_field(field_item); } if (item_equal) { @@ -11027,6 +11235,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item, else { item_equal= new Item_equal(const_item, orig_field_item, TRUE); + item_equal->set_context_field(field_item); cond_equal->current_level.push_back(item_equal); } return TRUE; @@ -11663,6 +11872,8 @@ static TABLE_LIST* embedding_sjm(Item *item) Item_equal::get_first() also takes similar measures for dealing with equality substitution in presense of SJM nests. + Grep for EqualityPropagationAndSjmNests for a more verbose description. + @return - The condition with generated simple equalities or a pointer to the simple generated equality, if success. @@ -11726,9 +11937,13 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, on upper AND-levels. */ if (upper) - { + { + TABLE_LIST *native_sjm= embedding_sjm(item_equal->context_field); if (item_const && upper->get_const()) + { + /* Upper item also has "field_item=const". Don't produce equality here */ item= 0; + } else { Item_equal_fields_iterator li(*item_equal); @@ -11739,6 +11954,8 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, break; } } + if (embedding_sjm(field_item) != native_sjm) + item= NULL; /* Don't produce equality */ } bool produce_equality= test(item == field_item); @@ -12434,11 +12651,9 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top, Flatten nested joins that can be flattened. no ON expression and not a semi-join => can be flattened. */ - TABLE_LIST *right_neighbor= NULL; li.rewind(); while ((table= li++)) { - bool fix_name_res= FALSE; nested_join= table->nested_join; if (table->sj_on_expr && !in_sj) { @@ -12475,15 +12690,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top, tbl->dep_tables|= table->dep_tables; } li.replace(repl_list); - /* Need to update the name resolution table chain when flattening joins */ - fix_name_res= TRUE; - table= *li.ref(); } - if (fix_name_res) - table->next_name_resolution_table= right_neighbor ? - right_neighbor->first_leaf_for_name_resolution() : - NULL; - right_neighbor= table; } DBUG_RETURN(conds); } @@ -15828,7 +16035,8 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, DBUG_RETURN(NESTED_LOOP_KILLED); /* purecov: inspected */ } - update_virtual_fields(join->thd, join_tab->table); + if (join_tab->table->vfield) + update_virtual_fields(join->thd, join_tab->table); if (select_cond) { @@ -16256,7 +16464,8 @@ join_read_system(JOIN_TAB *tab) empty_record(table); // Make empty record return -1; } - update_virtual_fields(tab->join->thd, table); + if (table->vfield) + update_virtual_fields(tab->join->thd, table); store_record(table,record[1]); } else if (!table->status) // Only happens with left join @@ -16305,7 +16514,8 @@ join_read_const(JOIN_TAB *tab) return report_error(table, error); return -1; } - update_virtual_fields(tab->join->thd, table); + if (table->vfield) + update_virtual_fields(tab->join->thd, table); store_record(table,record[1]); } else if (!(table->status & ~STATUS_NULL_ROW)) // Only happens with left join diff --git a/sql/sql_select.h b/sql/sql_select.h index 2f7d31de404..53f2356853e 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -742,7 +742,7 @@ public: Information about a position of table within a join order. Used in join optimization. */ -typedef struct st_position +typedef struct st_position :public Sql_alloc { /* The table that's put into join order */ JOIN_TAB *table; @@ -844,23 +844,36 @@ protected: */ class Join_plan_state { public: - DYNAMIC_ARRAY keyuse; /* Copy of the JOIN::keyuse array. */ - POSITION best_positions[MAX_TABLES+1]; /* Copy of JOIN::best_positions */ + DYNAMIC_ARRAY keyuse; /* Copy of the JOIN::keyuse array. */ + POSITION *best_positions; /* Copy of JOIN::best_positions */ /* Copies of the JOIN_TAB::keyuse pointers for each JOIN_TAB. */ - KEYUSE *join_tab_keyuse[MAX_TABLES]; + KEYUSE **join_tab_keyuse; /* Copies of JOIN_TAB::checked_keys for each JOIN_TAB. */ - key_map join_tab_checked_keys[MAX_TABLES]; - SJ_MATERIALIZATION_INFO *sj_mat_info[MAX_TABLES]; + key_map *join_tab_checked_keys; + SJ_MATERIALIZATION_INFO **sj_mat_info; + my_bool error; public: - Join_plan_state() + Join_plan_state(uint tables) : error(0) { keyuse.elements= 0; keyuse.buffer= NULL; + best_positions= 0; /* To detect errors */ + error= my_multi_malloc(MYF(MY_WME), + &best_positions, + sizeof(*best_positions) * (tables + 1), + &join_tab_keyuse, + sizeof(*join_tab_keyuse) * tables, + &join_tab_checked_keys, + sizeof(*join_tab_checked_keys) * tables, + &sj_mat_info, + sizeof(sj_mat_info) * tables, + NullS) == 0; } Join_plan_state(JOIN *join); ~Join_plan_state() { delete_dynamic(&keyuse); + my_free(best_positions); } }; @@ -958,7 +971,7 @@ public: */ ha_rows fetch_limit; /* Finally picked QEP. This is result of join optimization */ - POSITION best_positions[MAX_TABLES+1]; + POSITION *best_positions; /******* Join optimization state members start *******/ /* @@ -968,7 +981,7 @@ public: TABLE_LIST *emb_sjm_nest; /* Current join optimization state */ - POSITION positions[MAX_TABLES+1]; + POSITION *positions; /* Bitmap of nested joins embedding the position at the end of the current @@ -1238,6 +1251,7 @@ public: exec_const_cond= 0; group_optimized_away= 0; no_rows_in_result_called= 0; + positions= best_positions= 0; all_fields= fields_arg; if (&fields_list != &fields_arg) /* Avoid valgrind-warning */ diff --git a/sql/sql_show.cc b/sql/sql_show.cc index da48c7cdc63..82647df6756 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - 2009-2011 Monty Program Ab +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2009, 2011, 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 @@ -1236,7 +1236,9 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, handler *file= table->file; TABLE_SHARE *share= table->s; HA_CREATE_INFO create_info; - bool show_table_options __attribute__ ((unused))= FALSE; +#ifdef WITH_PARTITION_STORAGE_ENGINE + bool show_table_options= FALSE; +#endif /* WITH_PARTITION_STORAGE_ENGINE */ bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL | MODE_ORACLE | MODE_MSSQL | @@ -1470,7 +1472,9 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN("\n)")); if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode) { +#ifdef WITH_PARTITION_STORAGE_ENGINE show_table_options= TRUE; +#endif /* WITH_PARTITION_STORAGE_ENGINE */ /* IF check_create_info @@ -3631,16 +3635,17 @@ end: @retval 1 error */ -static int fill_schema_table_names(THD *thd, TABLE *table, +static int fill_schema_table_names(THD *thd, TABLE_LIST *tables, LEX_STRING *db_name, LEX_STRING *table_name, bool with_i_schema) { + TABLE *table= tables->table; if (with_i_schema) { table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), system_charset_info); } - else + else if (tables->table_open_method != SKIP_OPEN_TABLE) { enum legacy_db_type not_used; char path[FN_REFLEN + 1]; @@ -4202,7 +4207,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) /* SHOW TABLE NAMES command */ if (schema_table_idx == SCH_TABLE_NAMES) { - if (fill_schema_table_names(thd, tables->table, db_name, + if (fill_schema_table_names(thd, tables, db_name, table_name, with_i_schema)) continue; } @@ -5252,7 +5257,8 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0) { restore_record(table, s->default_values); - if (!wild || !wild[0] || !wild_compare(sp_name.c_ptr_safe(), wild, 0)) + if (!wild || !wild[0] || !wild_case_compare(system_charset_info, + sp_name.c_ptr_safe(), wild)) { int enum_idx= (int) proc_table->field[MYSQL_PROC_FIELD_ACCESS]->val_int(); table->field[3]->store(sp_name.ptr(), sp_name.length(), cs); @@ -6412,7 +6418,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) DBUG_RETURN(1); } - if (!(!wild || !wild[0] || !wild_compare(et.name.str, wild, 0))) + if (!(!wild || !wild[0] || !wild_case_compare(scs, et.name.str, wild))) DBUG_RETURN(0); /* @@ -6835,6 +6841,7 @@ static my_bool find_schema_table_in_plugin(THD *thd, plugin_ref plugin, if (!my_strcasecmp(system_charset_info, schema_table->table_name, table_name)) { + my_plugin_lock(thd, plugin); p_schema_table->schema_table= schema_table; DBUG_RETURN(1); } @@ -7501,6 +7508,8 @@ bool get_schema_tables_result(JOIN *join, join->error= 1; tab->read_record.table->file= table_list->table->file; table_list->schema_table_state= executed_place; + if (!thd->is_error()) + my_error(ER_UNKNOWN_ERROR, MYF(0)); break; } tab->read_record.table->file= table_list->table->file; @@ -8389,7 +8398,7 @@ ST_SCHEMA_TABLE schema_tables[]= get_all_tables, 0, get_schema_constraints_record, 3, 4, 0, OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY}, {"TABLE_NAMES", table_names_fields_info, create_schema_table, - get_all_tables, make_table_names_old_format, 0, 1, 2, 1, 0}, + get_all_tables, make_table_names_old_format, 0, 1, 2, 1, OPTIMIZE_I_S_TABLE}, {"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table, fill_schema_table_privileges, 0, 0, -1, -1, 0, 0}, {"TABLE_STATISTICS", table_stats_fields_info, create_schema_table, diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 1fdd81de089..5687a2220fe 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2010, 2011 Monty Program Ab + Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2010, 2011, 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 @@ -379,7 +379,7 @@ uint filename_to_tablename(const char *from, char *to, uint to_length DBUG_ENTER("filename_to_tablename"); DBUG_PRINT("enter", ("from '%s'", from)); - if (!memcmp(from, tmp_file_prefix, tmp_file_prefix_length)) + if (!strncmp(from, tmp_file_prefix, tmp_file_prefix_length)) { /* Temporary table name. */ res= (strnmov(to, from, to_length) - to); @@ -3144,6 +3144,15 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, DBUG_RETURN(TRUE); } + /* + CREATE TABLE[with auto_increment column] SELECT is unsafe as the rows + inserted in the created table depends on the order of the rows fetched + from the select tables. This order may differ on master and slave. We + therefore mark it as unsafe. + */ + if (select_field_count > 0 && auto_increment) + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_CREATE_SELECT_AUTOINC); + /* Create keys */ List_iterator<Key> key_iterator(alter_info->key_list); @@ -7283,7 +7292,8 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to, error= 1; break; } - update_virtual_fields(thd, from); + if (from->vfield) + update_virtual_fields(thd, from); if (++thd->progress.counter >= time_to_report_progress) { time_to_report_progress+= MY_HOW_OFTEN_TO_WRITE/10; @@ -7310,7 +7320,8 @@ copy_data_between_tables(THD *thd, TABLE *from,TABLE *to, copy_ptr->do_copy(copy_ptr); } prev_insert_id= to->file->next_insert_id; - update_virtual_fields(thd, to, TRUE); + if (to->vfield) + update_virtual_fields(thd, to, TRUE); if (thd->is_error()) { error= 1; @@ -7379,6 +7390,7 @@ err: error=1; if (error < 0 && to->file->extra(HA_EXTRA_PREPARE_FOR_RENAME)) error= 1; + thd_progress_end(thd); DBUG_RETURN(error > 0 ? -1 : 0); } diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 46f27f184fa..25ab84fe4db 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -618,8 +618,8 @@ Open streams: %10lu\n", (ulong) my_file_opened, (ulong) my_stream_opened); - ALARM_INFO alarm_info; #ifndef DONT_USE_THR_ALARM + ALARM_INFO alarm_info; thr_alarm_info(&alarm_info); printf("\nAlarm status:\n\ Active alarms: %u\n\ diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 50c57b62067..169e0d9e418 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -1,5 +1,4 @@ -/* - Copyright (c) 2000, 2010, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2012, 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 diff --git a/sql/sql_update.cc b/sql/sql_update.cc index ddb95f09ce2..cb536b79413 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -559,7 +559,8 @@ int mysql_update(THD *thd, while (!(error=info.read_record(&info)) && !thd->killed) { - update_virtual_fields(thd, table); + if (table->vfield) + update_virtual_fields(thd, table); thd->examined_row_count++; if (!select || (error= select->skip_record(thd)) > 0) { @@ -674,7 +675,8 @@ int mysql_update(THD *thd, while (!(error=info.read_record(&info)) && !thd->killed) { - update_virtual_fields(thd, table); + if (table->vfield) + update_virtual_fields(thd, table); thd->examined_row_count++; if (!select || select->skip_record(thd) > 0) { diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 0db69af094f..b6a7cf010ed 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -445,6 +445,13 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, view= lex->unlink_first_table(&link_to_local); + if (check_db_dir_existence(view->db)) + { + my_error(ER_BAD_DB_ERROR, MYF(0), view->db); + res= TRUE; + goto err; + } + if (mode == VIEW_ALTER && fill_defined_view_parts(thd, view)) { res= TRUE; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 5f9066afd39..34e015e1f9b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2772,9 +2772,15 @@ sp_decl: sp_instr_hpush_jump *i= new sp_instr_hpush_jump(sp->instructions(), ctx, $2, ctx->current_var_count()); - if (i == NULL || - sp->add_instr(i) || - sp->push_backpatch(i, ctx->push_label((char *)"", 0))) + if (i == NULL || sp->add_instr(i)) + MYSQL_YYABORT; + + /* For continue handlers, mark end of handler scope. */ + if ($2 == SP_HANDLER_CONTINUE && + sp->push_backpatch(i, ctx->last_label())) + MYSQL_YYABORT; + + if (sp->push_backpatch(i, ctx->push_label(empty_c_string, 0))) MYSQL_YYABORT; } sp_hcond_list sp_proc_stmt diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index dd11f51b212..8edfa8f2a6e 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2002, 2012, Oracle and/or its affiliates. Copyright (c) 2012, Monty Program Ab This program is free software; you can redistribute it and/or modify @@ -2954,7 +2954,7 @@ static Sys_var_uint Sys_repl_report_port( "port or if you have a special tunnel from the master or other clients " "to the slave. If not sure, leave this option unset", READ_ONLY GLOBAL_VAR(report_port), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(0, UINT_MAX), DEFAULT(MYSQL_PORT), BLOCK_SIZE(1)); + VALID_RANGE(0, UINT_MAX), DEFAULT(0), BLOCK_SIZE(1)); #endif static Sys_var_mybool Sys_keep_files_on_create( @@ -3255,6 +3255,150 @@ static Sys_var_mybool Sys_relay_log_recovery( "processed", GLOBAL_VAR(relay_log_recovery), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); +bool Sys_var_rpl_filter::do_check(THD *thd, set_var *var) +{ + bool status; + + mysql_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&active_mi->rli.run_lock); + + status= active_mi->rli.slave_running; + + mysql_mutex_unlock(&active_mi->rli.run_lock); + mysql_mutex_unlock(&LOCK_active_mi); + + if (status) + my_error(ER_SLAVE_MUST_STOP, MYF(0)); + else + status= Sys_var_charptr::do_string_check(thd, var, charset(thd)); + + return status; +} + +bool Sys_var_rpl_filter::global_update(THD *thd, set_var *var) +{ + bool slave_running, status= false; + + mysql_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&active_mi->rli.run_lock); + + if (! (slave_running= active_mi->rli.slave_running)) + status= set_filter_value(var->save_result.string_value.str); + + mysql_mutex_unlock(&active_mi->rli.run_lock); + mysql_mutex_unlock(&LOCK_active_mi); + + if (slave_running) + my_error(ER_SLAVE_MUST_STOP, MYF(0)); + + return slave_running || status; +} + +bool Sys_var_rpl_filter::set_filter_value(const char *value) +{ + bool status= true; + + switch (opt_id) { + case OPT_REPLICATE_DO_DB: + status= rpl_filter->set_do_db(value); + break; + case OPT_REPLICATE_DO_TABLE: + status= rpl_filter->set_do_table(value); + break; + case OPT_REPLICATE_IGNORE_DB: + status= rpl_filter->set_ignore_db(value); + break; + case OPT_REPLICATE_IGNORE_TABLE: + status= rpl_filter->set_ignore_table(value); + break; + case OPT_REPLICATE_WILD_DO_TABLE: + status= rpl_filter->set_wild_do_table(value); + break; + case OPT_REPLICATE_WILD_IGNORE_TABLE: + status= rpl_filter->set_wild_ignore_table(value); + break; + } + + return status; +} + +uchar *Sys_var_rpl_filter::global_value_ptr(THD *thd, LEX_STRING *base) +{ + char buf[256]; + String tmp(buf, sizeof(buf), &my_charset_bin); + + tmp.length(0); + + mysql_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&active_mi->rli.run_lock); + + switch (opt_id) { + case OPT_REPLICATE_DO_DB: + rpl_filter->get_do_db(&tmp); + break; + case OPT_REPLICATE_DO_TABLE: + rpl_filter->get_do_table(&tmp); + break; + case OPT_REPLICATE_IGNORE_DB: + rpl_filter->get_ignore_db(&tmp); + break; + case OPT_REPLICATE_IGNORE_TABLE: + rpl_filter->get_ignore_table(&tmp); + break; + case OPT_REPLICATE_WILD_DO_TABLE: + rpl_filter->get_wild_do_table(&tmp); + break; + case OPT_REPLICATE_WILD_IGNORE_TABLE: + rpl_filter->get_wild_ignore_table(&tmp); + break; + } + + mysql_mutex_unlock(&active_mi->rli.run_lock); + mysql_mutex_unlock(&LOCK_active_mi); + + return (uchar *) thd->strmake(tmp.ptr(), tmp.length()); +} + +static Sys_var_rpl_filter Sys_replicate_do_db( + "replicate_do_db", OPT_REPLICATE_DO_DB, + "Tell the slave to restrict replication to updates of tables " + "whose names appear in the comma-separated list. For " + "statement-based replication, only the default database (that " + "is, the one selected by USE) is considered, not any explicitly " + "mentioned tables in the query. For row-based replication, the " + "actual names of table(s) being updated are checked."); + +static Sys_var_rpl_filter Sys_replicate_do_table( + "replicate_do_table", OPT_REPLICATE_DO_TABLE, + "Tells the slave to restrict replication to tables in the " + "comma-separated list."); + +static Sys_var_rpl_filter Sys_replicate_ignore_db( + "replicate_ignore_db", OPT_REPLICATE_IGNORE_DB, + "Tell the slave to restrict replication to updates of tables " + "whose names do not appear in the comma-separated list. For " + "statement-based replication, only the default database (that " + "is, the one selected by USE) is considered, not any explicitly " + "mentioned tables in the query. For row-based replication, the " + "actual names of table(s) being updated are checked."); + +static Sys_var_rpl_filter Sys_replicate_ignore_table( + "replicate_ignore_table", OPT_REPLICATE_IGNORE_TABLE, + "Tells the slave thread not to replicate any statement that " + "updates the specified table, even if any other tables might be " + "updated by the same statement."); + +static Sys_var_rpl_filter Sys_replicate_wild_do_table( + "replicate_wild_do_table", OPT_REPLICATE_WILD_DO_TABLE, + "Tells the slave thread to restrict replication to statements " + "where any of the updated tables match the specified database " + "and table name patterns."); + +static Sys_var_rpl_filter Sys_replicate_wild_ignore_table( + "replicate_wild_ignore_table", OPT_REPLICATE_WILD_IGNORE_TABLE, + "Tells the slave thread to not replicate to the tables that " + "match the given wildcard pattern."); + static Sys_var_charptr Sys_slave_load_tmpdir( "slave_load_tmpdir", "The location where the slave should put " "its temporary files when replicating a LOAD DATA INFILE command", diff --git a/sql/sys_vars.h b/sql/sys_vars.h index f2a2966e6a2..4ea6b1f036e 100644 --- a/sql/sys_vars.h +++ b/sql/sys_vars.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2002, 2011, 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 @@ -430,11 +430,11 @@ public: my_free(global_var(char*)); flags&= ~ALLOCATED; } - bool do_check(THD *thd, set_var *var) + static bool do_string_check(THD *thd, set_var *var, CHARSET_INFO *charset) { char buff[STRING_BUFFER_USUAL_SIZE], buff2[STRING_BUFFER_USUAL_SIZE]; - String str(buff, sizeof(buff), charset(thd)); - String str2(buff2, sizeof(buff2), charset(thd)), *res; + String str(buff, sizeof(buff), charset); + String str2(buff2, sizeof(buff2), charset), *res; if (!(res=var->value->val_str(&str))) var->save_result.string_value.str= 0; @@ -442,10 +442,10 @@ public: { uint32 unused; if (String::needs_conversion(res->length(), res->charset(), - charset(thd), &unused)) + charset, &unused)) { uint errors; - str2.copy(res->ptr(), res->length(), res->charset(), charset(thd), + str2.copy(res->ptr(), res->length(), res->charset(), charset, &errors); res=&str2; @@ -456,6 +456,8 @@ public: return false; } + bool do_check(THD *thd, set_var *var) + { return do_string_check(thd, var, charset(thd)); } bool session_update(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); @@ -550,6 +552,44 @@ protected: } }; +class Sys_var_rpl_filter: public sys_var +{ +private: + int opt_id; + +public: + Sys_var_rpl_filter(const char *name, int getopt_id, const char *comment) + : sys_var(&all_sys_vars, name, comment, sys_var::GLOBAL, 0, -1, + NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, + NULL, NULL, 0, NULL), opt_id(getopt_id) + { + option.var_type= GET_STR; + } + + bool check_update_type(Item_result type) + { return type != STRING_RESULT; } + + bool do_check(THD *thd, set_var *var); + + void session_save_default(THD *thd, set_var *var) + { DBUG_ASSERT(FALSE); } + + void global_save_default(THD *thd, set_var *var) + { DBUG_ASSERT(FALSE); } + + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + + bool global_update(THD *thd, set_var *var); + +protected: + uchar *global_value_ptr(THD *thd, LEX_STRING *base); + bool set_filter_value(const char *value); +}; + /** The class for string variables. Useful for strings that aren't necessarily \0-terminated. Otherwise the same as Sys_var_charptr. diff --git a/sql/table.cc b/sql/table.cc index f8430b9575a..dc8ab3c6b42 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2466,30 +2466,35 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, /* Process virtual columns, if any. */ - if (!(vfield_ptr = (Field **) alloc_root(&outparam->mem_root, - (uint) ((share->vfields+1)* - sizeof(Field*))))) - goto err; - - outparam->vfield= vfield_ptr; - - for (field_ptr= outparam->field; *field_ptr; field_ptr++) + if (!share->vfields) + outparam->vfield= NULL; + else { - if ((*field_ptr)->vcol_info) + if (!(vfield_ptr = (Field **) alloc_root(&outparam->mem_root, + (uint) ((share->vfields+1)* + sizeof(Field*))))) + goto err; + + outparam->vfield= vfield_ptr; + + for (field_ptr= outparam->field; *field_ptr; field_ptr++) { - if (unpack_vcol_info_from_frm(thd, - outparam, - *field_ptr, - &(*field_ptr)->vcol_info->expr_str, - &error_reported)) + if ((*field_ptr)->vcol_info) { - error= 4; // in case no error is reported - goto err; + if (unpack_vcol_info_from_frm(thd, + outparam, + *field_ptr, + &(*field_ptr)->vcol_info->expr_str, + &error_reported)) + { + error= 4; // in case no error is reported + goto err; + } + *(vfield_ptr++)= *field_ptr; } - *(vfield_ptr++)= *field_ptr; } + *vfield_ptr= 0; // End marker } - *vfield_ptr= 0; // End marker #ifdef WITH_PARTITION_STORAGE_ENGINE if (share->partition_info_str_len && outparam->file) @@ -2602,8 +2607,7 @@ partititon_err: HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags)))) { /* Set a flag if the table is crashed and it can be auto. repaired */ - share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) && - outparam->file->auto_repair() && + share->crashed= (outparam->file->auto_repair(ha_err) && !(ha_open_flags & HA_OPEN_FOR_REPAIR)); switch (ha_err) @@ -4039,7 +4043,21 @@ bool TABLE_LIST::create_field_translation(THD *thd) Query_arena *arena= thd->stmt_arena, backup; bool res= FALSE; - used_items.empty(); + if (thd->stmt_arena->is_conventional() || + thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) + { + /* initialize lists */ + used_items.empty(); + persistent_used_items.empty(); + } + else + { + /* + Copy the list created by natural join procedure because the procedure + will not be repeated. + */ + used_items= persistent_used_items; + } if (field_translation) { @@ -5103,7 +5121,7 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref, if (view->table && view->table->maybe_null) item->maybe_null= TRUE; /* Save item in case we will need to fall back to materialization. */ - view->used_items.push_back(item); + view->used_items.push_front(item); DBUG_RETURN(item); } @@ -6362,8 +6380,7 @@ int update_virtual_fields(THD *thd, TABLE *table, bool for_write) DBUG_ENTER("update_virtual_fields"); Field **vfield_ptr, *vfield; int error __attribute__ ((unused))= 0; - if (!table || !table->vfield) - DBUG_RETURN(0); + DBUG_ASSERT(table && table->vfield); thd->reset_arena_for_cached_items(table->expr_arena); /* Iterate over virtual fields in the table */ @@ -6675,7 +6692,11 @@ bool TABLE_LIST::change_refs_to_fields() if (!materialized_items[idx]) return TRUE; } - ref->ref= materialized_items + idx; + /* + We need to restore the pointers after the execution of the + prepared statement. + */ + thd->change_item_tree((Item **)&ref->ref, (Item*)materialized_items + idx); } return FALSE; diff --git a/sql/table.h b/sql/table.h index d2337022724..7b50caae536 100644 --- a/sql/table.h +++ b/sql/table.h @@ -303,6 +303,7 @@ typedef struct st_filesort_info { IO_CACHE *io_cache; /* If sorted through filesort */ uchar **sort_keys; /* Buffer for sorting keys */ + uint keys; /* Number of key pointers in buffer */ 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 */ @@ -1573,6 +1574,8 @@ struct TABLE_LIST /* If this is a non-jtbm semi-join nest: corresponding subselect predicate */ Item_in_subselect *sj_subq_pred; + table_map original_subq_pred_used_tables; + /* If this is a jtbm semi-join object: corresponding subselect predicate */ Item_in_subselect *jtbm_subselect; /* TODO: check if this can be joined with tablenr_exec */ @@ -1852,7 +1855,13 @@ struct TABLE_LIST /* TRUE <=> don't prepare this derived table/view as it should be merged.*/ bool skip_prepare_derived; + /* + Items created by create_view_field and collected to change them in case + of materialization of the view/derived table + */ List<Item> used_items; + /* Sublist (tail) of persistent used_items */ + List<Item> persistent_used_items; Item **materialized_items; /* View creation context. */ diff --git a/sql/threadpool_unix.cc b/sql/threadpool_unix.cc index 407905fd5f6..f5ea771883d 100644 --- a/sql/threadpool_unix.cc +++ b/sql/threadpool_unix.cc @@ -295,7 +295,7 @@ int io_poll_create() int io_poll_start_read(int pollfd, int fd, void *data) { struct kevent ke; - EV_SET(&ke, fd, EVFILT_READ, EV_ADD|EV_ENABLE|EV_CLEAR, + EV_SET(&ke, fd, EVFILT_READ, EV_ADD|EV_ONESHOT, 0, 0, data); return kevent(pollfd, &ke, 1, 0, 0, 0); } @@ -303,6 +303,9 @@ int io_poll_start_read(int pollfd, int fd, void *data) int io_poll_associate_fd(int pollfd, int fd, void *data) { + struct kevent ke; + EV_SET(&ke, fd, EVFILT_READ, EV_ADD|EV_ONESHOT, + 0, 0, data); return io_poll_start_read(pollfd,fd, data); } @@ -330,17 +333,6 @@ int io_poll_wait(int pollfd, struct kevent *events, int maxevents, int timeout_m (timeout_ms >= 0)?&ts:NULL); } while (ret == -1 && errno == EINTR); - if (ret > 0) - { - /* Disable monitoring for the events we that we dequeued */ - for (int i=0; i < ret; i++) - { - struct kevent *ke = &events[i]; - EV_SET(ke, ke->ident, EVFILT_READ, EV_ADD|EV_DISABLE, - 0, 0, ke->udata); - } - kevent(pollfd, events, ret, 0, 0, 0); - } return ret; } diff --git a/sql/threadpool_win.cc b/sql/threadpool_win.cc index bf1d4740a13..c8cc38e612a 100644 --- a/sql/threadpool_win.cc +++ b/sql/threadpool_win.cc @@ -144,6 +144,9 @@ WEAK_SYMBOL(VOID, SubmitThreadpoolWork,PTP_WORK pwk); WEAK_SYMBOL(VOID, CloseThreadpoolWork, PTP_WORK pwk); #define CloseThreadpoolWork my_CloseThreadpoolWork +WEAK_SYMBOL(BOOL, CallbackMayRunLong, PTP_CALLBACK_INSTANCE pci); +#define CallbackMayRunLong my_CallbackMayRunLong + #if _MSC_VER >= 1600 /* Stack size manipulation available only on Win7+ /declarations in VS10 */ WEAK_SYMBOL(BOOL, SetThreadpoolStackInformation, PTP_POOL, @@ -419,8 +422,10 @@ void set_wait_timeout(connection_t *connection, ulonglong old_timeout) /* Connection destructor */ -void destroy_connection(connection_t *connection) +void destroy_connection(connection_t *connection, PTP_CALLBACK_INSTANCE instance) { + if (instance) + DisassociateCurrentThreadFromCallback(instance); if (connection->io) { WaitForThreadpoolIoCallbacks(connection->io, TRUE); @@ -583,10 +588,8 @@ static VOID CALLBACK io_completion_callback(PTP_CALLBACK_INSTANCE instance, error: /* Some error has occured. */ - if (instance) - DisassociateCurrentThreadFromCallback(instance); - destroy_connection(connection); + destroy_connection(connection, instance); free(connection); } @@ -603,7 +606,7 @@ static void CALLBACK login_callback(PTP_CALLBACK_INSTANCE instance, connection_t *connection =(connection_t *)context; if (login(connection, instance) != 0) { - destroy_connection(connection); + destroy_connection(connection, instance); free(connection); } } diff --git a/sql/transaction.cc b/sql/transaction.cc index 2b23b5e19f1..d5f9436ae53 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -426,7 +426,7 @@ bool trans_savepoint(THD *thd, LEX_STRING name) DBUG_RETURN(FALSE); enum xa_states xa_state= thd->transaction.xid_state.xa_state; - if (xa_state != XA_NOTR) + if (xa_state != XA_NOTR && xa_state != XA_ACTIVE) { my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]); DBUG_RETURN(TRUE); diff --git a/sql/unireg.h b/sql/unireg.h index 50aaa103b34..f8317a89c8c 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -2,7 +2,7 @@ #define UNIREG_INCLUDED /* - Copyright (c) 2000, 2010, Oracle and/or its affiliates. + Copyright (c) 2000, 2011, 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 diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index 25812a7ad48..6b29c6d9d53 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2004, 2011, Oracle and/or its affiliates + Copyright (c) 2004, 2012, 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 @@ -1399,6 +1399,8 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) char writer_filename[FN_REFLEN]; DBUG_ENTER("ha_archive::optimize"); + mysql_mutex_lock(&share->mutex); + if (init_archive_reader()) DBUG_RETURN(errno); @@ -1414,7 +1416,10 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) MY_REPLACE_EXT | MY_UNPACK_FILENAME); if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR|O_BINARY))) + { + mysql_mutex_unlock(&share->mutex); DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); + } /* Transfer the embedded FRM so that the file can be discoverable. @@ -1500,10 +1505,12 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt) rc= my_rename(writer_filename, share->data_file_name, MYF(0)); + mysql_mutex_unlock(&share->mutex); DBUG_RETURN(rc); error: DBUG_PRINT("ha_archive", ("Failed to recover, error was %d", rc)); azclose(&writer); + mysql_mutex_unlock(&share->mutex); DBUG_RETURN(rc); } diff --git a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h index 7ae6bf57a32..165c7443070 100644 --- a/storage/archive/ha_archive.h +++ b/storage/archive/ha_archive.h @@ -126,7 +126,9 @@ public: int free_share(); int init_archive_writer(); int init_archive_reader(); - bool auto_repair() const { return 1; } // For the moment we just do this + // Always try auto_repair in case of HA_ERR_CRASHED_ON_USAGE + bool auto_repair(int error) const + { return error == HA_ERR_CRASHED_ON_USAGE; } int read_data_header(azio_stream *file_to_read); void position(const uchar *record); int info(uint); diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc index 7bdbb4349cd..036dd374cb0 100644 --- a/storage/blackhole/ha_blackhole.cc +++ b/storage/blackhole/ha_blackhole.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2005, 2011, 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 diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index 64fd7102e93..d31e5ee8d89 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -1,5 +1,4 @@ -/* - Copyright (c) 2004, 2010, Oracle and/or its affiliates +/* Copyright (c) 2004, 2011, 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 @@ -962,6 +961,7 @@ int ha_tina::open(const char *name, int mode, uint open_options) */ thr_lock_data_init(&share->lock, &lock, (void*) this); ref_length= sizeof(my_off_t); + init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0); share->lock.get_status= tina_get_status; share->lock.update_status= tina_update_status; @@ -979,6 +979,7 @@ int ha_tina::close(void) { int rc= 0; DBUG_ENTER("ha_tina::close"); + free_root(&blobroot, MYF(0)); rc= mysql_file_close(data_file, MYF(0)); DBUG_RETURN(free_share(share) || rc); } @@ -1197,7 +1198,7 @@ int ha_tina::rnd_init(bool scan) current_position= next_position= 0; stats.records= 0; - records_is_known= 0; + records_is_known= found_end_of_file= 0; chain_ptr= chain; DBUG_RETURN(0); @@ -1247,6 +1248,7 @@ int ha_tina::rnd_next(uchar *buf) stats.records++; rc= 0; end: + found_end_of_file= (rc == HA_ERR_END_OF_FILE); MYSQL_READ_ROW_DONE(rc); DBUG_RETURN(rc); } @@ -1346,8 +1348,7 @@ int ha_tina::rnd_end() my_off_t file_buffer_start= 0; DBUG_ENTER("ha_tina::rnd_end"); - free_root(&blobroot, MYF(0)); - records_is_known= 1; + records_is_known= found_end_of_file; if ((chain_ptr - chain) > 0) { @@ -1760,6 +1761,13 @@ int ha_tina::check(THD* thd, HA_CHECK_OPT* check_opt) } +int ha_tina::reset(void) +{ + free_root(&blobroot, MYF(0)); + return 0; +} + + bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes) { diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h index 837da613171..88af2c9652c 100644 --- a/storage/csv/ha_tina.h +++ b/storage/csv/ha_tina.h @@ -81,7 +81,7 @@ class ha_tina: public handler uchar chain_alloced; uint32 chain_size; uint local_data_file_version; /* Saved version of the data file used */ - bool records_is_known; + bool records_is_known, found_end_of_file; MEM_ROOT blobroot; private: @@ -150,9 +150,12 @@ public: int rnd_end(); int repair(THD* thd, HA_CHECK_OPT* check_opt); /* This is required for SQL layer to know that we support autorepair */ + bool auto_repair(int error) const + { return error == HA_ERR_CRASHED_ON_USAGE; } bool auto_repair() const { return 1; } void position(const uchar *record); int info(uint); + int reset(); int extra(enum ha_extra_function operation); int delete_all_rows(void); int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info); diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc index dcbfb176c6a..17ac1e962aa 100644 --- a/storage/example/ha_example.cc +++ b/storage/example/ha_example.cc @@ -1,5 +1,4 @@ -/* - Copyright (c) 2004, 2010, Oracle and/or its affiliates +/* Copyright (c) 2004, 2011, 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 diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 4294f4b094f..549001ab08b 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2004, 2010, Oracle and/or its affiliates +/* Copyright (c) 2004, 2011, 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 diff --git a/storage/heap/_check.c b/storage/heap/_check.c index 08b6da62ae1..6cd01012d84 100644 --- a/storage/heap/_check.c +++ b/storage/heap/_check.c @@ -110,8 +110,13 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records, for (i=found=max_links=seek=0 ; i < records ; i++) { hash_info=hp_find_hash(&keydef->block,i); - if (hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec), - blength,records) == i) + if (hash_info->hash_of_key != hp_rec_hashnr(keydef, hash_info->ptr_to_rec)) + { + DBUG_PRINT("error", + ("Found row with wrong hash_of_key at position %lu", i)); + error= 1; + } + if (hp_mask(hash_info->hash_of_key, blength, records) == i) { found++; seek++; @@ -119,9 +124,7 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records, while ((hash_info=hash_info->next_key) && found < records + 1) { seek+= ++links; - if ((rec_link = hp_mask(hp_rec_hashnr(keydef, hash_info->ptr_to_rec), - blength, records)) - != i) + if ((rec_link= hp_mask(hash_info->hash_of_key, blength, records)) != i) { DBUG_PRINT("error", ("Record in wrong link: Link %lu Record: 0x%lx Record-link %lu", @@ -147,14 +150,14 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records, error=1; } DBUG_PRINT("info", - ("records: %ld seeks: %lu max links: %lu hitrate: %.2f " - "buckets: %lu", - records,seek,max_links, + ("key: %u records: %ld seeks: %lu max links: %lu " + "hitrate: %.2f buckets: %lu", + keynr, records,seek,max_links, (float) seek / (float) (records ? records : 1), hash_buckets_found)); if (print_status) - printf("Key: %d records: %ld seeks: %lu max links: %lu " - "hitrate: %.2f buckets: %lu\n", + printf("Key: %u records: %ld seeks: %lu max links: %lu " + "hitrate: %.2f buckets: %lu\n", keynr, records, seek, max_links, (float) seek / (float) (records ? records : 1), hash_buckets_found); diff --git a/storage/heap/heapdef.h b/storage/heap/heapdef.h index e844f90d321..db00ea87a01 100644 --- a/storage/heap/heapdef.h +++ b/storage/heap/heapdef.h @@ -48,6 +48,7 @@ typedef struct st_hp_hash_info { struct st_hp_hash_info *next_key; uchar *ptr_to_rec; + ulong hash_of_key; } HASH_INFO; typedef struct { diff --git a/storage/heap/hp_create.c b/storage/heap/hp_create.c index 5ec38955664..22ab9b54a85 100644 --- a/storage/heap/hp_create.c +++ b/storage/heap/hp_create.c @@ -250,12 +250,20 @@ static void init_block(HP_BLOCK *block, uint reclength, ulong min_records, max_records= 1000; /* As good as quess as anything */ recbuffer= (uint) (reclength + sizeof(uchar**) - 1) & ~(sizeof(uchar**) - 1); records_in_block= max_records / 10; - if (records_in_block < 10 && max_records) + + /* + We don't want too few records_in_block as otherwise the overhead of + of the HP_PTRS block will be too notable + */ + records_in_block= min(1000, max_records); + if (records_in_block < 10) records_in_block= 10; - if (!records_in_block || records_in_block*recbuffer > + + /* The + 1 is there to ensure that we get at least 1 row per level */ + if (records_in_block*recbuffer > (my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS)) records_in_block= (my_default_record_cache_size - sizeof(HP_PTRS) * - HP_MAX_LEVELS) / recbuffer + 1; + HP_MAX_LEVELS) / recbuffer + 1; block->records_in_block= records_in_block; block->recbuffer= recbuffer; block->last_allocated= 0L; diff --git a/storage/heap/hp_delete.c b/storage/heap/hp_delete.c index db2c0df6128..d00ac94a918 100644 --- a/storage/heap/hp_delete.c +++ b/storage/heap/hp_delete.c @@ -149,8 +149,9 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, else if (pos->next_key) { empty=pos->next_key; - pos->ptr_to_rec=empty->ptr_to_rec; - pos->next_key=empty->next_key; + pos->ptr_to_rec= empty->ptr_to_rec; + pos->next_key= empty->next_key; + pos->hash_of_key= empty->hash_of_key; } else keyinfo->hash_buckets--; @@ -159,7 +160,7 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, DBUG_RETURN (0); /* Move the last key (lastpos) */ - lastpos_hashnr = hp_rec_hashnr(keyinfo, lastpos->ptr_to_rec); + lastpos_hashnr= lastpos->hash_of_key; /* pos is where lastpos should be */ pos=hp_find_hash(&keyinfo->block, hp_mask(lastpos_hashnr, share->blength, share->records)); @@ -168,7 +169,7 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, empty[0]=lastpos[0]; DBUG_RETURN(0); } - pos_hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec); + pos_hashnr= pos->hash_of_key; /* pos3 is where the pos should be */ pos3= hp_find_hash(&keyinfo->block, hp_mask(pos_hashnr, share->blength, share->records)); diff --git a/storage/heap/hp_hash.c b/storage/heap/hp_hash.c index e916224c4d5..d44726ba762 100644 --- a/storage/heap/hp_hash.c +++ b/storage/heap/hp_hash.c @@ -148,8 +148,8 @@ uchar *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *key, { flag=0; /* Reset flag */ if (hp_find_hash(&keyinfo->block, - hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec), - share->blength, share->records)) != pos) + hp_mask(pos->hash_of_key, + share->blength, share->records)) != pos) break; /* Wrong link */ } } @@ -299,7 +299,9 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const uchar *key) } } } +#ifdef ONLY_FOR_HASH_DEBUGGING DBUG_PRINT("exit", ("hash: 0x%lx", nr)); +#endif return((ulong) nr); } @@ -366,7 +368,9 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const uchar *rec) } } } +#ifdef ONLY_FOR_HASH_DEBUGGING DBUG_PRINT("exit", ("hash: 0x%lx", nr)); +#endif return(nr); } @@ -437,7 +441,9 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const uchar *key) } } } +#ifdef ONLY_FOR_HASH_DEBUGGING DBUG_PRINT("exit", ("hash: 0x%lx", nr)); +#endif return(nr); } @@ -490,7 +496,9 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const uchar *rec) } } } +#ifdef ONLY_FOR_HASH_DEBUGGING DBUG_PRINT("exit", ("hash: 0x%lx", nr)); +#endif return(nr); } diff --git a/storage/heap/hp_info.c b/storage/heap/hp_info.c index c72dbaf2065..17f8c3fe97a 100644 --- a/storage/heap/hp_info.c +++ b/storage/heap/hp_info.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2004 MySQL AB +/* Copyright (c) 2000, 2011, 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 diff --git a/storage/heap/hp_test2.c b/storage/heap/hp_test2.c index caf7ff4daa9..058a2904697 100644 --- a/storage/heap/hp_test2.c +++ b/storage/heap/hp_test2.c @@ -65,7 +65,7 @@ int main(int argc, char *argv[]) get_options(argc,argv); bzero(&hp_create_info, sizeof(hp_create_info)); - hp_create_info.max_table_size= 1024L*1024L; + hp_create_info.max_table_size= 2*1024L*1024L; hp_create_info.keys= keys; hp_create_info.keydef= keyinfo; hp_create_info.reclength= reclength; @@ -636,7 +636,7 @@ static int get_options(int argc,char *argv[]) case 'V': case 'I': case '?': - printf("%s Ver 1.1 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE); + printf("%s Ver 1.2 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE); puts("TCX Datakonsult AB, by Monty, for your professional use\n"); printf("Usage: %s [-?ABIKLsWv] [-m#] [-t#]\n",progname); exit(0); diff --git a/storage/heap/hp_write.c b/storage/heap/hp_write.c index fc6c31e324b..8bfecc7747c 100644 --- a/storage/heap/hp_write.c +++ b/storage/heap/hp_write.c @@ -105,7 +105,7 @@ int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *record, uchar *recpos) { heap_rb_param custom_arg; - uint old_allocated; + size_t old_allocated; custom_arg.keyseg= keyinfo->seg; custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos); @@ -152,6 +152,13 @@ static uchar *next_free_record_pos(HP_SHARE *info) if ((info->records > info->max_records && info->max_records) || (info->data_length + info->index_length >= info->max_table_size)) { + DBUG_PRINT("error", + ("record file full. records: %u max_records: %lu " + "data_length: %llu index_length: %llu " + "max_table_size: %llu", + info->records, info->max_records, + info->data_length, info->index_length, + info->max_table_size)); my_errno=HA_ERR_RECORD_FILE_FULL; DBUG_RETURN(NULL); } @@ -198,6 +205,7 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, HP_SHARE *share = info->s; int flag; ulong halfbuff,hashnr,first_index; + ulong UNINIT_VAR(hash_of_key), UNINIT_VAR(hash_of_key2); uchar *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2); HASH_INFO *empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos; DBUG_ENTER("hp_write_key"); @@ -228,7 +236,7 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, { do { - hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec); + hashnr = pos->hash_of_key; if (flag == 0) { /* @@ -260,7 +268,6 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, flag=LOWFIND | HIGHFIND; /* key shall be moved to the current empty position */ gpos=empty; - ptr_to_rec=pos->ptr_to_rec; empty=pos; /* This place is now free */ } else @@ -271,7 +278,6 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, */ flag=LOWFIND | LOWUSED; gpos=pos; - ptr_to_rec=pos->ptr_to_rec; } } else @@ -280,13 +286,15 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, if (!(flag & LOWUSED)) { /* Change link of previous lower-list key */ - gpos->ptr_to_rec=ptr_to_rec; - gpos->next_key=pos; + gpos->ptr_to_rec= ptr_to_rec; + gpos->next_key= pos; + gpos->hash_of_key= hash_of_key; flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED); } gpos=pos; - ptr_to_rec=pos->ptr_to_rec; } + ptr_to_rec= pos->ptr_to_rec; + hash_of_key= pos->hash_of_key; } else { @@ -297,20 +305,21 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, /* key shall be moved to the last (empty) position */ gpos2= empty; empty= pos; - ptr_to_rec2=pos->ptr_to_rec; } else { if (!(flag & HIGHUSED)) { /* Change link of previous upper-list key and save */ - gpos2->ptr_to_rec=ptr_to_rec2; - gpos2->next_key=pos; + gpos2->ptr_to_rec= ptr_to_rec2; + gpos2->next_key= pos; + gpos2->hash_of_key= hash_of_key2; flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED); } gpos2=pos; - ptr_to_rec2=pos->ptr_to_rec; } + ptr_to_rec2= pos->ptr_to_rec; + hash_of_key2= pos->hash_of_key; } } while ((pos=pos->next_key)); @@ -326,23 +335,27 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, if ((flag & (LOWFIND | LOWUSED)) == LOWFIND) { - gpos->ptr_to_rec=ptr_to_rec; - gpos->next_key=0; + gpos->ptr_to_rec= ptr_to_rec; + gpos->hash_of_key= hash_of_key; + gpos->next_key= 0; } if ((flag & (HIGHFIND | HIGHUSED)) == HIGHFIND) { - gpos2->ptr_to_rec=ptr_to_rec2; - gpos2->next_key=0; + gpos2->ptr_to_rec= ptr_to_rec2; + gpos2->hash_of_key= hash_of_key2; + gpos2->next_key= 0; } } /* Check if we are at the empty position */ - pos=hp_find_hash(&keyinfo->block, hp_mask(hp_rec_hashnr(keyinfo, record), - share->blength, share->records + 1)); + hash_of_key= hp_rec_hashnr(keyinfo, record); + pos=hp_find_hash(&keyinfo->block, + hp_mask(hash_of_key, share->blength, share->records + 1)); if (pos == empty) { - pos->ptr_to_rec=recpos; - pos->next_key=0; + pos->ptr_to_rec= recpos; + pos->hash_of_key= hash_of_key; + pos->next_key= 0; keyinfo->hash_buckets++; } else @@ -350,18 +363,17 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, /* Check if more records in same hash-nr family */ empty[0]=pos[0]; gpos=hp_find_hash(&keyinfo->block, - hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec), + hp_mask(pos->hash_of_key, share->blength, share->records + 1)); + + pos->ptr_to_rec= recpos; + pos->hash_of_key= hash_of_key; if (pos == gpos) - { - pos->ptr_to_rec=recpos; pos->next_key=empty; - } else { keyinfo->hash_buckets++; - pos->ptr_to_rec=recpos; - pos->next_key=0; + pos->next_key= 0; hp_movelink(pos, gpos, empty); } diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 04b5fd8d19d..e4455630bc8 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -214,6 +214,15 @@ IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8) PROPERTIES COMPILE_FLAGS -Od) ENDIF() +IF(MSVC) + # Avoid "unreferenced label" warning in generated file + GET_FILENAME_COMPONENT(_SRC_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) + SET_SOURCE_FILES_PROPERTIES(${_SRC_DIR}/pars/pars0grm.c + PROPERTIES COMPILE_FLAGS "/wd4102") + SET_SOURCE_FILES_PROPERTIES(${_SRC_DIR}/pars/lexyy.c + PROPERTIES COMPILE_FLAGS "/wd4003") +ENDIF() + SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c buf/buf0buddy.c buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c data/data0data.c data/data0type.c diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c index 88371208230..fc3cdaf3cf1 100644 --- a/storage/innobase/btr/btr0btr.c +++ b/storage/innobase/btr/btr0btr.c @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -56,11 +56,12 @@ btr_corruption_report( (unsigned) buf_block_get_space(block), (unsigned) buf_block_get_page_no(block), index->name, index->table_name); - buf_page_print(buf_block_get_frame(block), 0); if (block->page.zip.data) { buf_page_print(block->page.zip.data, - buf_block_get_zip_size(block)); + buf_block_get_zip_size(block), + BUF_PAGE_PRINT_NO_CRASH); } + buf_page_print(buf_block_get_frame(block), 0, 0); } #ifdef UNIV_BLOB_DEBUG @@ -926,28 +927,31 @@ btr_page_alloc_for_ibuf( /**************************************************************//** Allocates a new file page to be used in an index tree. NOTE: we assume that the caller has made the reservation for free extents! -@return new allocated block, x-latched; NULL if out of space */ -UNIV_INTERN +@retval NULL if no page could be allocated +@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded +(init_mtr == mtr, or the page was not previously freed in mtr) +@retval block (not allocated or initialized) otherwise */ +static __attribute__((nonnull, warn_unused_result)) buf_block_t* -btr_page_alloc( -/*===========*/ +btr_page_alloc_low( +/*===============*/ dict_index_t* index, /*!< in: index */ ulint hint_page_no, /*!< in: hint of a good page */ byte file_direction, /*!< in: direction where a possible page split is made */ ulint level, /*!< in: level where the page is placed in the tree */ - mtr_t* mtr) /*!< in: mtr */ + mtr_t* mtr, /*!< in/out: mini-transaction + for the allocation */ + mtr_t* init_mtr) /*!< in/out: mtr or another + mini-transaction in which the + page should be initialized. + If init_mtr!=mtr, but the page + is already X-latched in mtr, do + not initialize the page. */ { fseg_header_t* seg_header; page_t* root; - buf_block_t* new_block; - ulint new_page_no; - - if (dict_index_is_ibuf(index)) { - - return(btr_page_alloc_for_ibuf(index, mtr)); - } root = btr_root_get(index, mtr); @@ -961,62 +965,96 @@ btr_page_alloc( reservation for free extents, and thus we know that a page can be allocated: */ - new_page_no = fseg_alloc_free_page_general(seg_header, hint_page_no, - file_direction, TRUE, mtr); - if (new_page_no == FIL_NULL) { + return(fseg_alloc_free_page_general( + seg_header, hint_page_no, file_direction, + TRUE, mtr, init_mtr)); +} - return(NULL); +/**************************************************************//** +Allocates a new file page to be used in an index tree. NOTE: we assume +that the caller has made the reservation for free extents! +@retval NULL if no page could be allocated +@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded +(init_mtr == mtr, or the page was not previously freed in mtr) +@retval block (not allocated or initialized) otherwise */ +UNIV_INTERN +buf_block_t* +btr_page_alloc( +/*===========*/ + dict_index_t* index, /*!< in: index */ + ulint hint_page_no, /*!< in: hint of a good page */ + byte file_direction, /*!< in: direction where a possible + page split is made */ + ulint level, /*!< in: level where the page is placed + in the tree */ + mtr_t* mtr, /*!< in/out: mini-transaction + for the allocation */ + mtr_t* init_mtr) /*!< in/out: mini-transaction + for x-latching and initializing + the page */ +{ + buf_block_t* new_block; + + if (dict_index_is_ibuf(index)) { + + return(btr_page_alloc_for_ibuf(index, mtr)); } - new_block = buf_page_get(dict_index_get_space(index), - dict_table_zip_size(index->table), - new_page_no, RW_X_LATCH, mtr); - buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW); + new_block = btr_page_alloc_low( + index, hint_page_no, file_direction, level, mtr, init_mtr); + + if (new_block) { + buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW); + } return(new_block); } /**************************************************************//** Gets the number of pages in a B-tree. -@return number of pages */ +@return number of pages, or ULINT_UNDEFINED if the index is unavailable */ UNIV_INTERN ulint btr_get_size( /*=========*/ dict_index_t* index, /*!< in: index */ - ulint flag) /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */ + ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */ + mtr_t* mtr) /*!< in/out: mini-transaction where index + is s-latched */ { fseg_header_t* seg_header; page_t* root; ulint n; ulint dummy; - mtr_t mtr; - mtr_start(&mtr); + ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index), + MTR_MEMO_S_LOCK)); - mtr_s_lock(dict_index_get_lock(index), &mtr); + if (index->page == FIL_NULL + || index->to_be_dropped + || *index->name == TEMP_INDEX_PREFIX) { + return(ULINT_UNDEFINED); + } - root = btr_root_get(index, &mtr); + root = btr_root_get(index, mtr); if (flag == BTR_N_LEAF_PAGES) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; - fseg_n_reserved_pages(seg_header, &n, &mtr); + fseg_n_reserved_pages(seg_header, &n, mtr); } else if (flag == BTR_TOTAL_SIZE) { seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP; - n = fseg_n_reserved_pages(seg_header, &dummy, &mtr); + n = fseg_n_reserved_pages(seg_header, &dummy, mtr); seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF; - n += fseg_n_reserved_pages(seg_header, &dummy, &mtr); + n += fseg_n_reserved_pages(seg_header, &dummy, mtr); } else { ut_error; } - mtr_commit(&mtr); - return(n); } @@ -1098,10 +1136,10 @@ btr_page_free( buf_block_t* block, /*!< in: block to be freed, x-latched */ mtr_t* mtr) /*!< in: mtr */ { - ulint level; - - level = btr_page_get_level(buf_block_get_frame(block), mtr); + const page_t* page = buf_block_get_frame(block); + ulint level = btr_page_get_level(page, mtr); + ut_ad(fil_page_get_type(block->frame) == FIL_PAGE_INDEX); btr_page_free_low(index, block, level, mtr); } @@ -1215,9 +1253,11 @@ btr_page_get_father_node_ptr_func( != page_no)) { rec_t* print_rec; fputs("InnoDB: Dump of the child page:\n", stderr); - buf_page_print(page_align(user_rec), 0); + buf_page_print(page_align(user_rec), 0, + BUF_PAGE_PRINT_NO_CRASH); fputs("InnoDB: Dump of the parent page:\n", stderr); - buf_page_print(page_align(node_ptr), 0); + buf_page_print(page_align(node_ptr), 0, + BUF_PAGE_PRINT_NO_CRASH); fputs("InnoDB: Corruption of an index tree: table ", stderr); ut_print_name(stderr, NULL, TRUE, index->table_name); @@ -1341,16 +1381,12 @@ btr_create( /* Allocate then the next page to the segment: it will be the tree root page */ - page_no = fseg_alloc_free_page(buf_block_get_frame( - ibuf_hdr_block) - + IBUF_HEADER - + IBUF_TREE_SEG_HEADER, - IBUF_TREE_ROOT_PAGE_NO, - FSP_UP, mtr); - ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO); - - block = buf_page_get(space, zip_size, page_no, - RW_X_LATCH, mtr); + block = fseg_alloc_free_page( + buf_block_get_frame(ibuf_hdr_block) + + IBUF_HEADER + IBUF_TREE_SEG_HEADER, + IBUF_TREE_ROOT_PAGE_NO, + FSP_UP, mtr); + ut_ad(buf_block_get_page_no(block) == IBUF_TREE_ROOT_PAGE_NO); } else { #ifdef UNIV_BLOB_DEBUG if ((type & DICT_CLUSTERED) && !index->blobs) { @@ -1654,8 +1690,8 @@ btr_page_reorganize_low( if (UNIV_UNLIKELY(data_size1 != data_size2) || UNIV_UNLIKELY(max_ins_size1 != max_ins_size2)) { - buf_page_print(page, 0); - buf_page_print(temp_page, 0); + buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH); + buf_page_print(temp_page, 0, BUF_PAGE_PRINT_NO_CRASH); fprintf(stderr, "InnoDB: Error: page old data size %lu" " new data size %lu\n" @@ -1666,6 +1702,7 @@ btr_page_reorganize_low( (unsigned long) data_size1, (unsigned long) data_size2, (unsigned long) max_ins_size1, (unsigned long) max_ins_size2); + ut_ad(0); } else { success = TRUE; } @@ -1829,7 +1866,7 @@ btr_root_raise_and_insert( level = btr_page_get_level(root, mtr); - new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr); + new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr); 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); @@ -2565,7 +2602,7 @@ func_start: /* 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); + btr_page_get_level(page, mtr), mtr, mtr); 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, @@ -3015,15 +3052,16 @@ btr_node_ptr_delete( ut_a(err == DB_SUCCESS); if (!compressed) { - btr_cur_compress_if_useful(&cursor, mtr); + btr_cur_compress_if_useful(&cursor, FALSE, mtr); } } /*************************************************************//** If page is the only on its level, this function moves its records to the -father page, thus reducing the tree height. */ +father page, thus reducing the tree height. +@return father block */ static -void +buf_block_t* btr_lift_page_up( /*=============*/ dict_index_t* index, /*!< in: index tree */ @@ -3140,6 +3178,8 @@ btr_lift_page_up( } ut_ad(page_validate(father_page, index)); ut_ad(btr_check_node_ptr(index, father_block, mtr)); + + return(father_block); } /*************************************************************//** @@ -3156,11 +3196,13 @@ UNIV_INTERN ibool btr_compress( /*=========*/ - btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift; - the page must not be empty: in record delete - use btr_discard_page if the page would become - empty */ - mtr_t* mtr) /*!< in: mtr */ + btr_cur_t* cursor, /*!< in/out: cursor on the page to merge + or lift; the page must not be empty: + when deleting records, use btr_discard_page() + if the page would become empty */ + ibool adjust, /*!< in: TRUE if should adjust the + cursor position even if compression occurs */ + mtr_t* mtr) /*!< in/out: mini-transaction */ { dict_index_t* index; ulint space; @@ -3178,6 +3220,7 @@ btr_compress( ulint* offsets; ulint data_size; ulint n_recs; + ulint nth_rec = 0; /* remove bogus warning */ ulint max_ins_size; ulint max_ins_size_reorg; @@ -3205,6 +3248,10 @@ btr_compress( offsets = btr_page_get_father_block(NULL, heap, index, block, mtr, &father_cursor); + if (adjust) { + nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor)); + } + /* Decide the page to which we try to merge and which will inherit the locks */ @@ -3231,9 +3278,9 @@ btr_compress( } else { /* The page is the only one on the level, lift the records to the father */ - btr_lift_page_up(index, block, mtr); - mem_heap_free(heap); - return(TRUE); + + merge_block = btr_lift_page_up(index, block, mtr); + goto func_exit; } n_recs = page_get_n_recs(page); @@ -3315,6 +3362,10 @@ err_exit: btr_node_ptr_delete(index, block, mtr); lock_update_merge_left(merge_block, orig_pred, block); + + if (adjust) { + nth_rec += page_rec_get_n_recs_before(orig_pred); + } } else { rec_t* orig_succ; #ifdef UNIV_BTR_DEBUG @@ -3379,7 +3430,6 @@ err_exit: } btr_blob_dbg_remove(page, index, "btr_compress"); - mem_heap_free(heap); if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) { /* Update the free bits of the B-tree page in the @@ -3431,6 +3481,16 @@ err_exit: btr_page_free(index, block, mtr); ut_ad(btr_check_node_ptr(index, merge_block, mtr)); +func_exit: + mem_heap_free(heap); + + if (adjust) { + btr_cur_position( + index, + page_rec_get_nth(merge_block->frame, nth_rec), + merge_block, cursor); + } + return(TRUE); } @@ -3867,7 +3927,7 @@ btr_index_rec_validate( (ulong) rec_get_n_fields_old(rec), (ulong) n); if (dump_on_error) { - buf_page_print(page, 0); + buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH); fputs("InnoDB: corrupt record ", stderr); rec_print_old(stderr, rec); @@ -3905,7 +3965,8 @@ btr_index_rec_validate( (ulong) i, (ulong) len, (ulong) fixed_size); if (dump_on_error) { - buf_page_print(page, 0); + buf_page_print(page, 0, + BUF_PAGE_PRINT_NO_CRASH); fputs("InnoDB: corrupt record ", stderr); rec_print_new(stderr, rec, offsets); @@ -4115,8 +4176,8 @@ loop: btr_validate_report2(index, level, block, right_block); fputs("InnoDB: broken FIL_PAGE_NEXT" " or FIL_PAGE_PREV links\n", stderr); - buf_page_print(page, 0); - buf_page_print(right_page, 0); + buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH); + buf_page_print(right_page, 0, BUF_PAGE_PRINT_NO_CRASH); ret = FALSE; } @@ -4125,8 +4186,8 @@ loop: != page_is_comp(page))) { btr_validate_report2(index, level, block, right_block); fputs("InnoDB: 'compact' flag mismatch\n", stderr); - buf_page_print(page, 0); - buf_page_print(right_page, 0); + buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH); + buf_page_print(right_page, 0, BUF_PAGE_PRINT_NO_CRASH); ret = FALSE; @@ -4149,8 +4210,8 @@ loop: fputs("InnoDB: records in wrong order" " on adjacent pages\n", stderr); - buf_page_print(page, 0); - buf_page_print(right_page, 0); + buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH); + buf_page_print(right_page, 0, BUF_PAGE_PRINT_NO_CRASH); fputs("InnoDB: record ", stderr); rec = page_rec_get_prev(page_get_supremum_rec(page)); @@ -4199,8 +4260,8 @@ loop: fputs("InnoDB: node pointer to the page is wrong\n", stderr); - buf_page_print(father_page, 0); - buf_page_print(page, 0); + buf_page_print(father_page, 0, BUF_PAGE_PRINT_NO_CRASH); + buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH); fputs("InnoDB: node ptr ", stderr); rec_print(stderr, node_ptr, index); @@ -4232,8 +4293,10 @@ loop: btr_validate_report1(index, level, block); - buf_page_print(father_page, 0); - buf_page_print(page, 0); + buf_page_print(father_page, 0, + BUF_PAGE_PRINT_NO_CRASH); + buf_page_print(page, 0, + BUF_PAGE_PRINT_NO_CRASH); fputs("InnoDB: Error: node ptrs differ" " on levels > 0\n" @@ -4278,9 +4341,15 @@ loop: btr_validate_report1(index, level, block); - buf_page_print(father_page, 0); - buf_page_print(page, 0); - buf_page_print(right_page, 0); + buf_page_print( + father_page, 0, + BUF_PAGE_PRINT_NO_CRASH); + buf_page_print( + page, 0, + BUF_PAGE_PRINT_NO_CRASH); + buf_page_print( + right_page, 0, + BUF_PAGE_PRINT_NO_CRASH); } } else { page_t* right_father_page @@ -4298,10 +4367,18 @@ loop: btr_validate_report1(index, level, block); - buf_page_print(father_page, 0); - buf_page_print(right_father_page, 0); - buf_page_print(page, 0); - buf_page_print(right_page, 0); + buf_page_print( + father_page, 0, + BUF_PAGE_PRINT_NO_CRASH); + buf_page_print( + right_father_page, 0, + BUF_PAGE_PRINT_NO_CRASH); + buf_page_print( + page, 0, + BUF_PAGE_PRINT_NO_CRASH); + buf_page_print( + right_page, 0, + BUF_PAGE_PRINT_NO_CRASH); } if (page_get_page_no(right_father_page) @@ -4315,10 +4392,18 @@ loop: btr_validate_report1(index, level, block); - buf_page_print(father_page, 0); - buf_page_print(right_father_page, 0); - buf_page_print(page, 0); - buf_page_print(right_page, 0); + buf_page_print( + father_page, 0, + BUF_PAGE_PRINT_NO_CRASH); + buf_page_print( + right_father_page, 0, + BUF_PAGE_PRINT_NO_CRASH); + buf_page_print( + page, 0, + BUF_PAGE_PRINT_NO_CRASH); + buf_page_print( + right_page, 0, + BUF_PAGE_PRINT_NO_CRASH); } } } diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c index 1551aee5426..e227e47b52f 100644 --- a/storage/innobase/btr/btr0cur.c +++ b/storage/innobase/btr/btr0cur.c @@ -18,8 +18,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -1860,7 +1860,7 @@ btr_cur_update_in_place( page_zip = buf_block_get_page_zip(block); /* Check that enough space is available on the compressed page. */ - if (UNIV_LIKELY_NULL(page_zip) + if (page_zip && !btr_cur_update_alloc_zip(page_zip, block, index, rec_offs_size(offsets), FALSE, mtr)) { return(DB_ZIP_OVERFLOW); @@ -2051,7 +2051,7 @@ any_extern: ut_a(!page_zip || page_zip_validate(page_zip, page)); #endif /* UNIV_ZIP_DEBUG */ - if (UNIV_LIKELY_NULL(page_zip) + if (page_zip && !btr_cur_update_alloc_zip(page_zip, block, index, new_rec_size, TRUE, mtr)) { err = DB_ZIP_OVERFLOW; @@ -2209,7 +2209,9 @@ btr_cur_pessimistic_update( /*=======================*/ ulint flags, /*!< in: undo logging, locking, and rollback flags */ - btr_cur_t* cursor, /*!< in: cursor on the record to update */ + btr_cur_t* cursor, /*!< in/out: cursor on the record to update; + cursor may become invalid if *big_rec == NULL + || !(flags & BTR_KEEP_POS_FLAG) */ mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to be stored externally by the caller, or NULL */ @@ -2348,10 +2350,10 @@ btr_cur_pessimistic_update( record to be inserted: we have to remember which fields were such */ ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec)); - offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, heap); + ut_ad(rec_offs_validate(rec, index, offsets)); n_ext += btr_push_update_extern_fields(new_entry, update, *heap); - if (UNIV_LIKELY_NULL(page_zip)) { + if (page_zip) { ut_ad(page_is_comp(page)); if (page_zip_rec_needs_ext( rec_get_converted_size(index, new_entry, n_ext), @@ -2371,6 +2373,10 @@ make_external: err = DB_TOO_BIG_RECORD; goto return_after_reservations; } + + ut_ad(page_is_leaf(page)); + ut_ad(dict_index_is_clust(index)); + ut_ad(flags & BTR_KEEP_POS_FLAG); } /* Store state of explicit locks on rec on the page infimum record, @@ -2398,6 +2404,8 @@ make_external: rec = btr_cur_insert_if_possible(cursor, new_entry, n_ext, mtr); if (rec) { + page_cursor->rec = rec; + lock_rec_restore_from_page_infimum(btr_cur_get_block(cursor), rec, block); @@ -2411,7 +2419,10 @@ make_external: rec, index, offsets, mtr); } - btr_cur_compress_if_useful(cursor, mtr); + btr_cur_compress_if_useful( + cursor, + big_rec_vec != NULL && (flags & BTR_KEEP_POS_FLAG), + mtr); if (page_zip && !dict_index_is_clust(index) && page_is_leaf(page)) { @@ -2431,6 +2442,21 @@ make_external: } } + if (big_rec_vec) { + ut_ad(page_is_leaf(page)); + ut_ad(dict_index_is_clust(index)); + ut_ad(flags & BTR_KEEP_POS_FLAG); + + /* btr_page_split_and_insert() in + btr_cur_pessimistic_insert() invokes + mtr_memo_release(mtr, index->lock, MTR_MEMO_X_LOCK). + We must keep the index->lock when we created a + big_rec, so that row_upd_clust_rec() can store the + big_rec in the same mini-transaction. */ + + mtr_x_lock(dict_index_get_lock(index), mtr); + } + /* Was the record to be updated positioned as the first user record on its page? */ was_first = page_cur_is_before_first(page_cursor); @@ -2446,6 +2472,7 @@ make_external: ut_a(rec); ut_a(err == DB_SUCCESS); ut_a(dummy_big_rec == NULL); + page_cursor->rec = rec; if (dict_index_is_sec_or_ibuf(index)) { /* Update PAGE_MAX_TRX_ID in the index page header. @@ -2880,10 +2907,12 @@ UNIV_INTERN ibool btr_cur_compress_if_useful( /*=======================*/ - btr_cur_t* cursor, /*!< in: cursor on the page to compress; - cursor does not stay valid if compression - occurs */ - mtr_t* mtr) /*!< in: mtr */ + btr_cur_t* cursor, /*!< in/out: cursor on the page to compress; + cursor does not stay valid if !adjust and + compression occurs */ + ibool adjust, /*!< in: TRUE if should adjust the + cursor position even if compression occurs */ + mtr_t* mtr) /*!< in/out: mini-transaction */ { ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(btr_cur_get_index(cursor)), @@ -2892,7 +2921,7 @@ btr_cur_compress_if_useful( MTR_MEMO_PAGE_X_FIX)); return(btr_cur_compress_recommendation(cursor, mtr) - && btr_compress(cursor, mtr)); + && btr_compress(cursor, adjust, mtr)); } /*******************************************************//** @@ -3134,7 +3163,7 @@ return_after_reservations: mem_heap_free(heap); if (ret == FALSE) { - ret = btr_cur_compress_if_useful(cursor, mtr); + ret = btr_cur_compress_if_useful(cursor, FALSE, mtr); } if (n_extents > 0) { @@ -3870,10 +3899,10 @@ btr_cur_set_ownership_of_extern_field( byte_val = byte_val | BTR_EXTERN_OWNER_FLAG; } - if (UNIV_LIKELY_NULL(page_zip)) { + if (page_zip) { mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val); page_zip_write_blob_ptr(page_zip, rec, index, offsets, i, mtr); - } else if (UNIV_LIKELY(mtr != NULL)) { + } else if (mtr != NULL) { mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, byte_val, MLOG_1BYTE, mtr); @@ -4106,9 +4135,9 @@ The fields are stored on pages allocated from leaf node file segment of the index tree. @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ UNIV_INTERN -ulint -btr_store_big_rec_extern_fields_func( -/*=================================*/ +enum db_err +btr_store_big_rec_extern_fields( +/*============================*/ dict_index_t* index, /*!< in: index of rec; the index tree MUST be X-latched */ buf_block_t* rec_block, /*!< in/out: block containing rec */ @@ -4117,38 +4146,37 @@ btr_store_big_rec_extern_fields_func( the "external storage" flags in offsets will not correspond to rec when this function returns */ -#ifdef UNIV_DEBUG - mtr_t* local_mtr, /*!< in: mtr containing the - latch to rec and to the tree */ -#endif /* UNIV_DEBUG */ -#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG - ibool update_in_place,/*! in: TRUE if the record is updated - in place (not delete+insert) */ -#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ - const big_rec_t*big_rec_vec) /*!< in: vector containing fields + const big_rec_t*big_rec_vec, /*!< in: vector containing fields to be stored externally */ - + mtr_t* btr_mtr, /*!< in: mtr containing the + latches to the clustered index */ + enum blob_op op) /*! in: operation code */ { - ulint rec_page_no; - byte* field_ref; - ulint extern_len; - ulint store_len; - ulint page_no; - ulint space_id; - ulint zip_size; - ulint prev_page_no; - ulint hint_page_no; - ulint i; - mtr_t mtr; - mem_heap_t* heap = NULL; + ulint rec_page_no; + byte* field_ref; + ulint extern_len; + ulint store_len; + ulint page_no; + ulint space_id; + ulint zip_size; + ulint prev_page_no; + ulint hint_page_no; + ulint i; + mtr_t mtr; + mtr_t* alloc_mtr; + mem_heap_t* heap = NULL; page_zip_des_t* page_zip; - z_stream c_stream; + z_stream c_stream; + buf_block_t** freed_pages = NULL; + ulint n_freed_pages = 0; + enum db_err error = DB_SUCCESS; ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_any_extern(offsets)); - ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index), + ut_ad(btr_mtr); + ut_ad(mtr_memo_contains(btr_mtr, dict_index_get_lock(index), MTR_MEMO_X_LOCK)); - ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr_memo_contains(btr_mtr, rec_block, MTR_MEMO_PAGE_X_FIX)); ut_ad(buf_block_get_frame(rec_block) == page_align(rec)); ut_a(dict_index_is_clust(index)); @@ -4161,7 +4189,7 @@ btr_store_big_rec_extern_fields_func( rec_page_no = buf_block_get_page_no(rec_block); ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX); - if (UNIV_LIKELY_NULL(page_zip)) { + if (page_zip) { int err; /* Zlib deflate needs 128 kilobytes for the default @@ -4177,6 +4205,42 @@ btr_store_big_rec_extern_fields_func( ut_a(err == Z_OK); } + if (btr_blob_op_is_update(op)) { + /* Avoid reusing pages that have been previously freed + in btr_mtr. */ + if (btr_mtr->n_freed_pages) { + if (heap == NULL) { + heap = mem_heap_create( + btr_mtr->n_freed_pages + * sizeof *freed_pages); + } + + freed_pages = mem_heap_alloc( + heap, + btr_mtr->n_freed_pages + * sizeof *freed_pages); + n_freed_pages = 0; + } + + /* Because btr_mtr will be committed after mtr, it is + possible that the tablespace has been extended when + the B-tree record was updated or inserted, or it will + be extended while allocating pages for big_rec. + + TODO: In mtr (not btr_mtr), write a redo log record + about extending the tablespace to its current size, + and remember the current size. Whenever the tablespace + grows as pages are allocated, write further redo log + records to mtr. (Currently tablespace extension is not + covered by the redo log. If it were, the record would + only be written to btr_mtr, which is committed after + mtr.) */ + alloc_mtr = btr_mtr; + } else { + /* Use the local mtr for allocations. */ + alloc_mtr = &mtr; + } + #if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG /* All pointers to externally stored columns in the record must either be zero or they must be pointers to inherited @@ -4191,7 +4255,7 @@ btr_store_big_rec_extern_fields_func( /* Either this must be an update in place, or the BLOB must be inherited, or the BLOB pointer must be zero (will be written in this function). */ - ut_a(update_in_place + ut_a(op == BTR_STORE_UPDATE || (field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG) || !memcmp(field_ref, field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE)); @@ -4216,7 +4280,7 @@ btr_store_big_rec_extern_fields_func( prev_page_no = FIL_NULL; - if (UNIV_LIKELY_NULL(page_zip)) { + if (page_zip) { int err = deflateReset(&c_stream); ut_a(err == Z_OK); @@ -4236,18 +4300,24 @@ btr_store_big_rec_extern_fields_func( hint_page_no = prev_page_no + 1; } +alloc_another: block = btr_page_alloc(index, hint_page_no, - FSP_NO_DIR, 0, &mtr); + FSP_NO_DIR, 0, alloc_mtr, &mtr); if (UNIV_UNLIKELY(block == NULL)) { - mtr_commit(&mtr); + error = DB_OUT_OF_FILE_SPACE; + goto func_exit; + } - if (UNIV_LIKELY_NULL(page_zip)) { - deflateEnd(&c_stream); - mem_heap_free(heap); - } - - return(DB_OUT_OF_FILE_SPACE); + if (rw_lock_get_x_lock_count(&block->lock) > 1) { + /* This page must have been freed in + btr_mtr previously. Put it aside, and + allocate another page for the BLOB data. */ + ut_ad(alloc_mtr == btr_mtr); + ut_ad(btr_blob_op_is_update(op)); + ut_ad(n_freed_pages < btr_mtr->n_freed_pages); + freed_pages[n_freed_pages++] = block; + goto alloc_another; } page_no = buf_block_get_page_no(block); @@ -4264,7 +4334,7 @@ btr_store_big_rec_extern_fields_func( SYNC_EXTERN_STORAGE); prev_page = buf_block_get_frame(prev_block); - if (UNIV_LIKELY_NULL(page_zip)) { + if (page_zip) { mlog_write_ulint( prev_page + FIL_PAGE_NEXT, page_no, MLOG_4BYTES, &mtr); @@ -4281,7 +4351,7 @@ btr_store_big_rec_extern_fields_func( } - if (UNIV_LIKELY_NULL(page_zip)) { + if (page_zip) { int err; page_zip_des_t* blob_page_zip; @@ -4364,11 +4434,15 @@ btr_store_big_rec_extern_fields_func( goto next_zip_page; } - rec_block = buf_page_get(space_id, zip_size, - rec_page_no, - RW_X_LATCH, &mtr); - buf_block_dbg_add_level(rec_block, - SYNC_NO_ORDER_CHECK); + if (alloc_mtr == &mtr) { + rec_block = buf_page_get( + space_id, zip_size, + rec_page_no, + RW_X_LATCH, &mtr); + buf_block_dbg_add_level( + rec_block, + SYNC_NO_ORDER_CHECK); + } if (err == Z_STREAM_END) { mach_write_to_4(field_ref @@ -4402,7 +4476,8 @@ btr_store_big_rec_extern_fields_func( page_zip_write_blob_ptr( page_zip, rec, index, offsets, - big_rec_vec->fields[i].field_no, &mtr); + big_rec_vec->fields[i].field_no, + alloc_mtr); next_zip_page: prev_page_no = page_no; @@ -4447,19 +4522,23 @@ next_zip_page: extern_len -= store_len; - rec_block = buf_page_get(space_id, zip_size, - rec_page_no, - RW_X_LATCH, &mtr); - buf_block_dbg_add_level(rec_block, - SYNC_NO_ORDER_CHECK); + if (alloc_mtr == &mtr) { + rec_block = buf_page_get( + space_id, zip_size, + rec_page_no, + RW_X_LATCH, &mtr); + buf_block_dbg_add_level( + rec_block, + SYNC_NO_ORDER_CHECK); + } mlog_write_ulint(field_ref + BTR_EXTERN_LEN, 0, - MLOG_4BYTES, &mtr); + MLOG_4BYTES, alloc_mtr); mlog_write_ulint(field_ref + BTR_EXTERN_LEN + 4, big_rec_vec->fields[i].len - extern_len, - MLOG_4BYTES, &mtr); + MLOG_4BYTES, alloc_mtr); if (prev_page_no == FIL_NULL) { btr_blob_dbg_add_blob( @@ -4469,18 +4548,19 @@ next_zip_page: mlog_write_ulint(field_ref + BTR_EXTERN_SPACE_ID, - space_id, - MLOG_4BYTES, &mtr); + space_id, MLOG_4BYTES, + alloc_mtr); mlog_write_ulint(field_ref + BTR_EXTERN_PAGE_NO, - page_no, - MLOG_4BYTES, &mtr); + page_no, MLOG_4BYTES, + alloc_mtr); mlog_write_ulint(field_ref + BTR_EXTERN_OFFSET, FIL_PAGE_DATA, - MLOG_4BYTES, &mtr); + MLOG_4BYTES, + alloc_mtr); } prev_page_no = page_no; @@ -4494,8 +4574,23 @@ next_zip_page: } } - if (UNIV_LIKELY_NULL(page_zip)) { +func_exit: + if (page_zip) { deflateEnd(&c_stream); + } + + if (n_freed_pages) { + ulint i; + + ut_ad(alloc_mtr == btr_mtr); + ut_ad(btr_blob_op_is_update(op)); + + for (i = 0; i < n_freed_pages; i++) { + btr_page_free_low(index, freed_pages[i], 0, alloc_mtr); + } + } + + if (heap != NULL) { mem_heap_free(heap); } @@ -4516,7 +4611,7 @@ next_zip_page: ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG)); } #endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ - return(DB_SUCCESS); + return(error); } /*******************************************************************//** @@ -4719,7 +4814,7 @@ btr_free_externally_stored_field( btr_page_free_low(index, ext_block, 0, &mtr); - if (UNIV_LIKELY(page_zip != NULL)) { + if (page_zip) { mach_write_to_4(field_ref + BTR_EXTERN_PAGE_NO, next_page_no); mach_write_to_4(field_ref + BTR_EXTERN_LEN + 4, diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c index fb153556b2f..7ac96c1a1b1 100644 --- a/storage/innobase/btr/btr0pcur.c +++ b/storage/innobase/btr/btr0pcur.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2012, 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 @@ -133,6 +133,8 @@ btr_pcur_store_position( ut_a(btr_page_get_next(page, mtr) == FIL_NULL); ut_a(btr_page_get_prev(page, mtr) == FIL_NULL); + ut_ad(page_is_leaf(page)); + ut_ad(page_get_page_no(page) == index->page); cursor->old_stored = BTR_PCUR_OLD_STORED; @@ -325,13 +327,19 @@ btr_pcur_restore_position_func( /* Save the old search mode of the cursor */ old_mode = cursor->search_mode; - if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) { + switch (cursor->rel_pos) { + case BTR_PCUR_ON: mode = PAGE_CUR_LE; - } else if (cursor->rel_pos == BTR_PCUR_AFTER) { + break; + case BTR_PCUR_AFTER: mode = PAGE_CUR_G; - } else { - ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE); + break; + case BTR_PCUR_BEFORE: mode = PAGE_CUR_L; + break; + default: + ut_error; + mode = 0; } btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode, @@ -340,25 +348,44 @@ btr_pcur_restore_position_func( /* Restore the old search mode */ cursor->search_mode = old_mode; - if (cursor->rel_pos == BTR_PCUR_ON - && btr_pcur_is_on_user_rec(cursor) - && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor), - rec_get_offsets( - btr_pcur_get_rec(cursor), index, - NULL, ULINT_UNDEFINED, &heap))) { - - /* We have to store the NEW value for the modify clock, since - the cursor can now be on a different page! But we can retain - the value of old_rec */ + if (btr_pcur_is_on_user_rec(cursor)) { + switch (cursor->rel_pos) { + case BTR_PCUR_ON: + if (!cmp_dtuple_rec( + tuple, btr_pcur_get_rec(cursor), + rec_get_offsets(btr_pcur_get_rec(cursor), + index, NULL, + ULINT_UNDEFINED, &heap))) { + + /* We have to store the NEW value for + the modify clock, since the cursor can + now be on a different page! But we can + retain the value of old_rec */ + + cursor->block_when_stored = + btr_pcur_get_block(cursor); + cursor->modify_clock = + buf_block_get_modify_clock( + cursor->block_when_stored); + cursor->old_stored = BTR_PCUR_OLD_STORED; - cursor->block_when_stored = btr_pcur_get_block(cursor); - cursor->modify_clock = buf_block_get_modify_clock( - cursor->block_when_stored); - cursor->old_stored = BTR_PCUR_OLD_STORED; + mem_heap_free(heap); - mem_heap_free(heap); + return(TRUE); + } - return(TRUE); + break; + case BTR_PCUR_BEFORE: + page_cur_move_to_next(btr_pcur_get_page_cur(cursor)); + break; + case BTR_PCUR_AFTER: + page_cur_move_to_prev(btr_pcur_get_page_cur(cursor)); + break; +#ifdef UNIV_DEBUG + default: + ut_error; +#endif /* UNIV_DEBUG */ + } } mem_heap_free(heap); diff --git a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c index 1825544a265..53a0c0eb5d9 100644 --- a/storage/innobase/btr/btr0sea.c +++ b/storage/innobase/btr/btr0sea.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -1176,7 +1176,7 @@ cleanup: index->name, (ulong) block->n_pointers); rw_lock_x_unlock(&btr_search_latch); - btr_search_validate(); + ut_ad(btr_search_validate()); } else { rw_lock_x_unlock(&btr_search_latch); } @@ -1908,7 +1908,9 @@ btr_search_validate(void) (ulong) block->curr_left_side); if (n_page_dumps < 20) { - buf_page_print(page, 0); + buf_page_print( + page, 0, + BUF_PAGE_PRINT_NO_CRASH); n_page_dumps++; } } diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index 0721929abd3..1672057d552 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -605,8 +605,12 @@ void buf_page_print( /*===========*/ const byte* read_buf, /*!< in: a database page */ - ulint zip_size) /*!< in: compressed page size, or - 0 for uncompressed pages */ + ulint zip_size, /*!< in: compressed page size, or + 0 for uncompressed pages */ + ulint flags) /*!< in: 0 or + BUF_PAGE_PRINT_NO_CRASH or + BUF_PAGE_PRINT_NO_FULL */ + { #ifndef UNIV_HOTBACKUP dict_index_t* index; @@ -615,17 +619,18 @@ buf_page_print( ulint old_checksum; ulint size = zip_size; - ut_ad(0); - if (!size) { size = UNIV_PAGE_SIZE; } - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Page dump in ascii and hex (%lu bytes):\n", - (ulong) size); - ut_print_buf(stderr, read_buf, size); - fputs("\nInnoDB: End of page dump\n", stderr); + if (!(flags & BUF_PAGE_PRINT_NO_FULL)) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Page dump in ascii and hex (%lu bytes):\n", + (ulong) size); + ut_print_buf(stderr, read_buf, size); + fputs("\nInnoDB: End of page dump\n", stderr); + } if (zip_size) { /* Print compressed page. */ @@ -797,6 +802,8 @@ buf_page_print( stderr); break; } + + ut_ad(flags & BUF_PAGE_PRINT_NO_CRASH); } #ifndef UNIV_HOTBACKUP @@ -2454,7 +2461,7 @@ wait_until_unfixed: block->page.buf_fix_count = 1; buf_block_set_io_fix(block, BUF_IO_READ); - rw_lock_x_lock_func(&block->lock, 0, file, line); + rw_lock_x_lock_inline(&block->lock, 0, file, line); UNIV_MEM_INVALID(bpage, sizeof *bpage); @@ -2594,14 +2601,14 @@ wait_until_unfixed: break; case RW_S_LATCH: - rw_lock_s_lock_func(&(block->lock), 0, file, line); + rw_lock_s_lock_inline(&(block->lock), 0, file, line); fix_type = MTR_MEMO_PAGE_S_FIX; break; default: ut_ad(rw_latch == RW_X_LATCH); - rw_lock_x_lock_func(&(block->lock), 0, file, line); + rw_lock_x_lock_inline(&(block->lock), 0, file, line); fix_type = MTR_MEMO_PAGE_X_FIX; break; @@ -2681,8 +2688,8 @@ buf_page_optimistic_get( file, line); fix_type = MTR_MEMO_PAGE_S_FIX; } else { - success = rw_lock_x_lock_func_nowait(&(block->lock), - file, line); + success = rw_lock_x_lock_func_nowait_inline(&(block->lock), + file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } @@ -2811,8 +2818,8 @@ buf_page_get_known_nowait( file, line); fix_type = MTR_MEMO_PAGE_S_FIX; } else { - success = rw_lock_x_lock_func_nowait(&(block->lock), - file, line); + success = rw_lock_x_lock_func_nowait_inline(&(block->lock), + file, line); fix_type = MTR_MEMO_PAGE_X_FIX; } @@ -2899,8 +2906,8 @@ buf_page_try_get_func( S-latch. */ fix_type = MTR_MEMO_PAGE_X_FIX; - success = rw_lock_x_lock_func_nowait(&block->lock, - file, line); + success = rw_lock_x_lock_func_nowait_inline(&block->lock, + file, line); } if (!success) { @@ -3557,7 +3564,8 @@ corrupt: "InnoDB: You may have to recover" " from a backup.\n", (ulong) bpage->offset); - buf_page_print(frame, buf_page_get_zip_size(bpage)); + buf_page_print(frame, buf_page_get_zip_size(bpage), + BUF_PAGE_PRINT_NO_CRASH); fprintf(stderr, "InnoDB: Database page corruption on disk" " or a failed\n" @@ -4742,34 +4750,32 @@ buf_all_freed(void) /*********************************************************************//** Checks that there currently are no pending i/o-operations for the buffer pool. -@return TRUE if there is no pending i/o */ +@return number of pending i/o */ UNIV_INTERN -ibool -buf_pool_check_no_pending_io(void) -/*==============================*/ +ulint +buf_pool_check_num_pending_io(void) +/*===============================*/ { ulint i; - ibool ret = TRUE; + ulint pending_io = 0; buf_pool_mutex_enter_all(); - for (i = 0; i < srv_buf_pool_instances && ret; i++) { + for (i = 0; i < srv_buf_pool_instances; i++) { const buf_pool_t* buf_pool; buf_pool = buf_pool_from_array(i); - if (buf_pool->n_pend_reads - + buf_pool->n_flush[BUF_FLUSH_LRU] - + buf_pool->n_flush[BUF_FLUSH_LIST] - + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) { + pending_io += buf_pool->n_pend_reads + + buf_pool->n_flush[BUF_FLUSH_LRU] + + buf_pool->n_flush[BUF_FLUSH_LIST] + + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]; - ret = FALSE; - } } buf_pool_mutex_exit_all(); - return(ret); + return(pending_io); } #if 0 diff --git a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c index 06b3ec393c1..6e8e8fdda5a 100644 --- a/storage/innobase/buf/buf0flu.c +++ b/storage/innobase/buf/buf0flu.c @@ -757,7 +757,8 @@ buf_flush_buffered_writes(void) if (UNIV_UNLIKELY (!page_simple_validate_new(block->frame))) { corrupted_page: - buf_page_print(block->frame, 0); + buf_page_print(block->frame, 0, + BUF_PAGE_PRINT_NO_CRASH); ut_print_timestamp(stderr); fprintf(stderr, diff --git a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c index 15b0ad40aaa..8e787fdba17 100644 --- a/storage/innobase/buf/buf0lru.c +++ b/storage/innobase/buf/buf0lru.c @@ -335,39 +335,275 @@ next_page: } /******************************************************************//** +While flushing (or removing dirty) pages from a tablespace we don't +want to hog the CPU and resources. Release the buffer pool and block +mutex and try to force a context switch. Then reacquire the same mutexes. +The current page is "fixed" before the release of the mutexes and then +"unfixed" again once we have reacquired the mutexes. */ +static +void +buf_flush_yield( +/*============*/ + buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ + buf_page_t* bpage) /*!< in/out: current page */ +{ + mutex_t* block_mutex; + + ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(buf_page_in_file(bpage)); + + block_mutex = buf_page_get_mutex(bpage); + + mutex_enter(block_mutex); + /* "Fix" the block so that the position cannot be + changed after we release the buffer pool and + block mutexes. */ + buf_page_set_sticky(bpage); + + /* Now it is safe to release the buf_pool->mutex. */ + buf_pool_mutex_exit(buf_pool); + + mutex_exit(block_mutex); + /* Try and force a context switch. */ + os_thread_yield(); + + buf_pool_mutex_enter(buf_pool); + + mutex_enter(block_mutex); + /* "Unfix" the block now that we have both the + buffer pool and block mutex again. */ + buf_page_unset_sticky(bpage); + mutex_exit(block_mutex); +} + +/******************************************************************//** +If we have hogged the resources for too long then release the buffer +pool and flush list mutex and do a thread yield. Set the current page +to "sticky" so that it is not relocated during the yield. +@return TRUE if yielded */ +static +ibool +buf_flush_try_yield( +/*================*/ + buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ + buf_page_t* bpage, /*!< in/out: bpage to remove */ + ulint processed) /*!< in: number of pages processed */ +{ + /* Every BUF_LRU_DROP_SEARCH_SIZE iterations in the + loop we release buf_pool->mutex to let other threads + do their job but only if the block is not IO fixed. This + ensures that the block stays in its position in the + flush_list. */ + + if (bpage != NULL + && processed >= BUF_LRU_DROP_SEARCH_SIZE + && buf_page_get_io_fix(bpage) == BUF_IO_NONE) { + + buf_flush_list_mutex_exit(buf_pool); + + /* Release the buffer pool and block mutex + to give the other threads a go. */ + + buf_flush_yield(buf_pool, bpage); + + buf_flush_list_mutex_enter(buf_pool); + + /* Should not have been removed from the flush + list during the yield. However, this check is + not sufficient to catch a remove -> add. */ + + ut_ad(bpage->in_flush_list); + + return(TRUE); + } + + return(FALSE); +} + +/******************************************************************//** +Removes a single page from a given tablespace inside a specific +buffer pool instance. +@return TRUE if page was removed. */ +static +ibool +buf_flush_or_remove_page( +/*=====================*/ + buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ + buf_page_t* bpage) /*!< in/out: bpage to remove */ +{ + mutex_t* block_mutex; + ibool processed = FALSE; + + ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(buf_flush_list_mutex_own(buf_pool)); + + block_mutex = buf_page_get_mutex(bpage); + + /* bpage->space and bpage->io_fix are protected by + buf_pool->mutex and block_mutex. It is safe to check + them while holding buf_pool->mutex only. */ + + if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) { + + /* We cannot remove this page during this scan + yet; maybe the system is currently reading it + in, or flushing the modifications to the file */ + + } else { + + /* We have to release the flush_list_mutex to obey the + latching order. We are however guaranteed that the page + will stay in the flush_list because buf_flush_remove() + needs buf_pool->mutex as well (for the non-flush case). */ + + buf_flush_list_mutex_exit(buf_pool); + + mutex_enter(block_mutex); + + ut_ad(bpage->oldest_modification != 0); + + if (bpage->buf_fix_count == 0) { + + buf_flush_remove(bpage); + + processed = TRUE; + } + + mutex_exit(block_mutex); + + buf_flush_list_mutex_enter(buf_pool); + } + + ut_ad(!mutex_own(block_mutex)); + + return(processed); +} + +/******************************************************************//** Remove all dirty pages belonging to a given tablespace inside a specific buffer pool instance when we are deleting the data file(s) of that tablespace. The pages still remain a part of LRU and are evicted from -the list as they age towards the tail of the LRU. */ +the list as they age towards the tail of the LRU. +@return TRUE if all freed. */ +static +ibool +buf_flush_or_remove_pages( +/*======================*/ + buf_pool_t* buf_pool, /*!< buffer pool instance */ + ulint id) /*!< in: target space id for which + to remove or flush pages */ +{ + buf_page_t* prev; + buf_page_t* bpage; + ulint processed = 0; + ibool all_freed = TRUE; + + buf_flush_list_mutex_enter(buf_pool); + + for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list); + bpage != NULL; + bpage = prev) { + + ut_a(buf_page_in_file(bpage)); + ut_ad(bpage->in_flush_list); + + /* Save the previous link because once we free the + page we can't rely on the links. */ + + prev = UT_LIST_GET_PREV(list, bpage); + + if (buf_page_get_space(bpage) != id) { + + /* Skip this block, as it does not belong to + the target space. */ + + } else if (!buf_flush_or_remove_page(buf_pool, bpage)) { + + /* Remove was unsuccessful, we have to try again + by scanning the entire list from the end. */ + + all_freed = FALSE; + } + + ++processed; + + /* Yield if we have hogged the CPU and mutexes for too long. */ + if (buf_flush_try_yield(buf_pool, prev, processed)) { + + /* Reset the batch size counter if we had to yield. */ + + processed = 0; + } + + } + + buf_flush_list_mutex_exit(buf_pool); + + return(all_freed); +} + +/******************************************************************//** +Remove or flush all the dirty pages that belong to a given tablespace +inside a specific buffer pool instance. The pages will remain in the LRU +list and will be evicted from the LRU list as they age and move towards +the tail of the LRU list. */ static void -buf_LRU_remove_dirty_pages_for_tablespace( -/*======================================*/ +buf_flush_dirty_pages( +/*==================*/ + buf_pool_t* buf_pool, /*!< buffer pool instance */ + ulint id) /*!< in: space id */ +{ + ibool all_freed; + + do { + buf_pool_mutex_enter(buf_pool); + + all_freed = buf_flush_or_remove_pages(buf_pool, id); + + buf_pool_mutex_exit(buf_pool); + + ut_ad(buf_flush_validate(buf_pool)); + + if (!all_freed) { + os_thread_sleep(20000); + } + + } while (!all_freed); +} + +/******************************************************************//** +Remove all pages that belong to a given tablespace inside a specific +buffer pool instance when we are DISCARDing the tablespace. */ +static +void +buf_LRU_remove_all_pages( +/*=====================*/ buf_pool_t* buf_pool, /*!< buffer pool instance */ ulint id) /*!< in: space id */ { buf_page_t* bpage; ibool all_freed; - ulint i; scan_again: buf_pool_mutex_enter(buf_pool); - buf_flush_list_mutex_enter(buf_pool); all_freed = TRUE; - for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list), i = 0; - bpage != NULL; ++i) { + for (bpage = UT_LIST_GET_LAST(buf_pool->LRU); + bpage != NULL; + /* No op */) { buf_page_t* prev_bpage; mutex_t* block_mutex = NULL; ut_a(buf_page_in_file(bpage)); + ut_ad(bpage->in_LRU_list); - prev_bpage = UT_LIST_GET_PREV(list, bpage); + prev_bpage = UT_LIST_GET_PREV(LRU, bpage); /* bpage->space and bpage->io_fix are protected by - buf_pool->mutex and block_mutex. It is safe to check + buf_pool->mutex and the block_mutex. It is safe to check them while holding buf_pool->mutex only. */ if (buf_page_get_space(bpage) != id) { @@ -381,83 +617,87 @@ scan_again: all_freed = FALSE; goto next_page; - } + } else { - /* We have to release the flush_list_mutex to obey the - latching order. We are however guaranteed that the page - will stay in the flush_list because buf_flush_remove() - needs buf_pool->mutex as well. */ - buf_flush_list_mutex_exit(buf_pool); - block_mutex = buf_page_get_mutex(bpage); - mutex_enter(block_mutex); + block_mutex = buf_page_get_mutex(bpage); + mutex_enter(block_mutex); - if (bpage->buf_fix_count > 0) { - mutex_exit(block_mutex); - buf_flush_list_mutex_enter(buf_pool); + if (bpage->buf_fix_count > 0) { - /* We cannot remove this page during - this scan yet; maybe the system is - currently reading it in, or flushing - the modifications to the file */ + mutex_exit(block_mutex); - all_freed = FALSE; - goto next_page; - } + /* We cannot remove this page during + this scan yet; maybe the system is + currently reading it in, or flushing + the modifications to the file */ - ut_ad(bpage->oldest_modification != 0); + all_freed = FALSE; - buf_flush_remove(bpage); + goto next_page; + } + } - mutex_exit(block_mutex); - buf_flush_list_mutex_enter(buf_pool); -next_page: - bpage = prev_bpage; + ut_ad(mutex_own(block_mutex)); - if (!bpage) { - break; +#ifdef UNIV_DEBUG + if (buf_debug_prints) { + fprintf(stderr, + "Dropping space %lu page %lu\n", + (ulong) buf_page_get_space(bpage), + (ulong) buf_page_get_page_no(bpage)); } +#endif + if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) { + /* Do nothing, because the adaptive hash index + covers uncompressed pages only. */ + } else if (((buf_block_t*) bpage)->index) { + ulint page_no; + ulint zip_size; - /* Every BUF_LRU_DROP_SEARCH_SIZE iterations in the - loop we release buf_pool->mutex to let other threads - do their job. */ - if (i < BUF_LRU_DROP_SEARCH_SIZE) { - continue; + buf_pool_mutex_exit(buf_pool); + + zip_size = buf_page_get_zip_size(bpage); + page_no = buf_page_get_page_no(bpage); + + mutex_exit(block_mutex); + + /* Note that the following call will acquire + and release block->lock X-latch. */ + + btr_search_drop_page_hash_when_freed( + id, zip_size, page_no); + + goto scan_again; } - /* We IO-fix the block to make sure that the block - stays in its position in the flush_list. */ - if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) { - /* Block is already IO-fixed. We don't - want to change the value. Lets leave - this block alone. */ - continue; + if (bpage->oldest_modification != 0) { + buf_flush_remove(bpage); } - buf_flush_list_mutex_exit(buf_pool); - block_mutex = buf_page_get_mutex(bpage); - mutex_enter(block_mutex); - buf_page_set_sticky(bpage); - mutex_exit(block_mutex); + ut_ad(!bpage->in_flush_list); - /* Now it is safe to release the buf_pool->mutex. */ - buf_pool_mutex_exit(buf_pool); - os_thread_yield(); - buf_pool_mutex_enter(buf_pool); + /* Remove from the LRU list. */ - mutex_enter(block_mutex); - buf_page_unset_sticky(bpage); - mutex_exit(block_mutex); + if (buf_LRU_block_remove_hashed_page(bpage, TRUE) + != BUF_BLOCK_ZIP_FREE) { - buf_flush_list_mutex_enter(buf_pool); - ut_ad(bpage->in_flush_list); + buf_LRU_block_free_hashed_page((buf_block_t*) bpage); + mutex_exit(block_mutex); + + } else { + /* The block_mutex should have been released + by buf_LRU_block_remove_hashed_page() when it + returns BUF_BLOCK_ZIP_FREE. */ + ut_ad(block_mutex == &buf_pool->zip_mutex); + } - i = 0; + ut_ad(!mutex_own(block_mutex)); + +next_page: + bpage = prev_bpage; } buf_pool_mutex_exit(buf_pool); - buf_flush_list_mutex_exit(buf_pool); - - ut_ad(buf_flush_validate(buf_pool)); if (!all_freed) { os_thread_sleep(20000); @@ -467,28 +707,46 @@ next_page: } /******************************************************************//** -Invalidates all pages belonging to a given tablespace when we are deleting -the data file(s) of that tablespace. */ +Removes all pages belonging to a given tablespace. */ UNIV_INTERN void -buf_LRU_invalidate_tablespace( +buf_LRU_flush_or_remove_pages( /*==========================*/ - ulint id) /*!< in: space id */ + ulint id, /*!< in: space id */ + enum buf_remove_t buf_remove)/*!< in: remove or flush + strategy */ { - ulint i; + ulint i; - /* Before we attempt to drop pages one by one we first - attempt to drop page hash index entries in batches to make - it more efficient. The batching attempt is a best effort - attempt and does not guarantee that all pages hash entries - will be dropped. We get rid of remaining page hash entries - one by one below. */ for (i = 0; i < srv_buf_pool_instances; i++) { buf_pool_t* buf_pool; buf_pool = buf_pool_from_array(i); - buf_LRU_drop_page_hash_for_tablespace(buf_pool, id); - buf_LRU_remove_dirty_pages_for_tablespace(buf_pool, id); + + switch (buf_remove) { + case BUF_REMOVE_ALL_NO_WRITE: + /* A DISCARD tablespace case. Remove AHI entries + and evict all pages from LRU. */ + + /* Before we attempt to drop pages hash entries + one by one we first attempt to drop page hash + index entries in batches to make it more + efficient. The batching attempt is a best effort + attempt and does not guarantee that all pages + hash entries will be dropped. We get rid of + remaining page hash entries one by one below. */ + buf_LRU_drop_page_hash_for_tablespace(buf_pool, id); + buf_LRU_remove_all_pages(buf_pool, id); + break; + + case BUF_REMOVE_FLUSH_NO_WRITE: + /* A DROP table case. AHI entries are already + removed. No need to evict all pages from LRU + list. Just evict pages from flush list without + writing. */ + buf_flush_dirty_pages(buf_pool, id); + break; + } } } diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index 9dc3cef229e..ce4988c1bfd 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -4337,16 +4337,27 @@ dict_update_statistics( (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE || (srv_force_recovery < SRV_FORCE_NO_LOG_REDO && dict_index_is_clust(index)))) { + mtr_t mtr; ulint size; - size = btr_get_size(index, BTR_TOTAL_SIZE); - index->stat_index_size = size; + mtr_start(&mtr); + mtr_s_lock(dict_index_get_lock(index), &mtr); - sum_of_index_sizes += size; + size = btr_get_size(index, BTR_TOTAL_SIZE, &mtr); - size = btr_get_size(index, BTR_N_LEAF_PAGES); + if (size != ULINT_UNDEFINED) { + sum_of_index_sizes += size; + index->stat_index_size = size; + size = btr_get_size( + index, BTR_N_LEAF_PAGES, &mtr); + } + + mtr_commit(&mtr); - if (size == 0) { + switch (size) { + case ULINT_UNDEFINED: + goto fake_statistics; + case 0: /* The root node of the tree is a leaf */ size = 1; } @@ -4363,6 +4374,7 @@ dict_update_statistics( various means, also via secondary indexes. */ ulint i; +fake_statistics: sum_of_index_sizes++; index->stat_index_size = index->stat_n_leaf_pages = 1; diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c index 2e4c6aeeb60..2390333b393 100644 --- a/storage/innobase/fil/fil0fil.c +++ b/storage/innobase/fil/fil0fil.c @@ -185,7 +185,7 @@ struct fil_space_struct { .ibd file of tablespace and want to stop temporarily posting of new i/o requests on the file */ - ibool stop_ibuf_merges; + ibool stop_new_ops; /*!< we set this TRUE when we start deleting a single-table tablespace */ ibool is_being_deleted; @@ -210,12 +210,13 @@ struct fil_space_struct { ulint n_pending_flushes; /*!< this is positive when flushing the tablespace to disk; dropping of the tablespace is forbidden if this is positive */ - ulint n_pending_ibuf_merges;/*!< this is positive - when merging insert buffer entries to - a page so that we may need to access - the ibuf bitmap page in the - tablespade: dropping of the tablespace - is forbidden if this is positive */ + ulint n_pending_ops;/*!< this is positive when we + have pending operations against this + tablespace. The pending operations can + be ibuf merges or lock validation code + trying to read a block. + Dropping of the tablespace is forbidden + if this is positive */ hash_node_t hash; /*!< hash chain node */ hash_node_t name_hash;/*!< hash chain the name_hash table */ #ifndef UNIV_HOTBACKUP @@ -964,11 +965,6 @@ retry: return; } - if (fil_system->n_open < fil_system->max_n_open) { - - return; - } - space = fil_space_get_by_id(space_id); if (space != NULL && space->stop_ios) { @@ -985,6 +981,25 @@ retry: mutex_exit(&fil_system->mutex); +#ifndef UNIV_HOTBACKUP + + /* Wake the i/o-handler threads to make sure pending + i/o's are performed */ + os_aio_simulated_wake_handler_threads(); + + /* The sleep here is just to give IO helper threads a + bit of time to do some work. It is not required that + all IO related to the tablespace being renamed must + be flushed here as we do fil_flush() in + fil_rename_tablespace() as well. */ + os_thread_sleep(20000); + +#endif /* UNIV_HOTBACKUP */ + + /* Flush tablespaces so that we can close modified + files in the LRU list */ + fil_flush_file_spaces(FIL_TABLESPACE); + os_thread_sleep(20000); count2++; @@ -992,6 +1007,11 @@ retry: goto retry; } + if (fil_system->n_open < fil_system->max_n_open) { + + return; + } + /* If the file is already open, no need to do anything; if the space does not exist, we handle the situation in the function which called this function */ @@ -1263,7 +1283,7 @@ try_again: } space->stop_ios = FALSE; - space->stop_ibuf_merges = FALSE; + space->stop_new_ops = FALSE; space->is_being_deleted = FALSE; space->purpose = purpose; space->size = 0; @@ -1272,7 +1292,7 @@ try_again: space->n_reserved_extents = 0; space->n_pending_flushes = 0; - space->n_pending_ibuf_merges = 0; + space->n_pending_ops = 0; UT_LIST_INIT(space->chain); space->magic_n = FIL_SPACE_MAGIC_N; @@ -1872,13 +1892,12 @@ fil_read_first_page( #ifndef UNIV_HOTBACKUP /*******************************************************************//** -Increments the count of pending insert buffer page merges, if space is not -being deleted. -@return TRUE if being deleted, and ibuf merges should be skipped */ +Increments the count of pending operation, if space is not being deleted. +@return TRUE if being deleted, and operation should be skipped */ UNIV_INTERN ibool -fil_inc_pending_ibuf_merges( -/*========================*/ +fil_inc_pending_ops( +/*================*/ ulint id) /*!< in: space id */ { fil_space_t* space; @@ -1894,13 +1913,13 @@ fil_inc_pending_ibuf_merges( (ulong) id); } - if (space == NULL || space->stop_ibuf_merges) { + if (space == NULL || space->stop_new_ops) { mutex_exit(&fil_system->mutex); return(TRUE); } - space->n_pending_ibuf_merges++; + space->n_pending_ops++; mutex_exit(&fil_system->mutex); @@ -1908,11 +1927,11 @@ fil_inc_pending_ibuf_merges( } /*******************************************************************//** -Decrements the count of pending insert buffer page merges. */ +Decrements the count of pending operations. */ UNIV_INTERN void -fil_decr_pending_ibuf_merges( -/*=========================*/ +fil_decr_pending_ops( +/*=================*/ ulint id) /*!< in: space id */ { fil_space_t* space; @@ -1923,13 +1942,13 @@ fil_decr_pending_ibuf_merges( if (space == NULL) { fprintf(stderr, - "InnoDB: Error: decrementing ibuf merge of a" - " dropped tablespace %lu\n", + "InnoDB: Error: decrementing pending operation" + " of a dropped tablespace %lu\n", (ulong) id); } if (space != NULL) { - space->n_pending_ibuf_merges--; + space->n_pending_ops--; } mutex_exit(&fil_system->mutex); @@ -2140,7 +2159,7 @@ fil_op_log_parse_or_replay( switch (type) { case MLOG_FILE_DELETE: if (fil_tablespace_exists_in_mem(space_id)) { - ut_a(fil_delete_tablespace(space_id)); + ut_a(fil_delete_tablespace(space_id, TRUE)); } break; @@ -2210,7 +2229,9 @@ UNIV_INTERN ibool fil_delete_tablespace( /*==================*/ - ulint id) /*!< in: space id */ + ulint id, /*!< in: space id */ + ibool evict_all) /*!< in: TRUE if we want all pages + evicted from LRU. */ { ibool success; fil_space_t* space; @@ -2219,15 +2240,15 @@ fil_delete_tablespace( char* path; ut_a(id != 0); -stop_ibuf_merges: +stop_new_ops: mutex_enter(&fil_system->mutex); space = fil_space_get_by_id(id); if (space != NULL) { - space->stop_ibuf_merges = TRUE; + space->stop_new_ops = TRUE; - if (space->n_pending_ibuf_merges == 0) { + if (space->n_pending_ops == 0) { mutex_exit(&fil_system->mutex); count = 0; @@ -2241,9 +2262,10 @@ stop_ibuf_merges: ut_print_filename(stderr, space->name); fprintf(stderr, ",\n" "InnoDB: but there are %lu pending" - " ibuf merges on it.\n" + " operations (most likely ibuf merges)" + " on it.\n" "InnoDB: Loop %lu.\n", - (ulong) space->n_pending_ibuf_merges, + (ulong) space->n_pending_ops, (ulong) count); } @@ -2252,7 +2274,7 @@ stop_ibuf_merges: os_thread_sleep(20000); count++; - goto stop_ibuf_merges; + goto stop_new_ops; } } @@ -2278,7 +2300,7 @@ try_again: } ut_a(space); - ut_a(space->n_pending_ibuf_merges == 0); + ut_a(space->n_pending_ops == 0); space->is_being_deleted = TRUE; @@ -2331,7 +2353,10 @@ try_again: completely and permanently. The flag is_being_deleted also prevents fil_flush() from being applied to this tablespace. */ - buf_LRU_invalidate_tablespace(id); + buf_LRU_flush_or_remove_pages( + id, evict_all + ? BUF_REMOVE_ALL_NO_WRITE + : BUF_REMOVE_FLUSH_NO_WRITE); #endif /* printf("Deleting tablespace %s id %lu\n", space->name, id); */ @@ -2419,7 +2444,7 @@ fil_discard_tablespace( { ibool success; - success = fil_delete_tablespace(id); + success = fil_delete_tablespace(id, TRUE); if (!success) { fprintf(stderr, @@ -2551,7 +2576,7 @@ fil_rename_tablespace( retry: count++; - if (count > 1000) { + if (!(count % 1000)) { ut_print_timestamp(stderr); fputs(" InnoDB: Warning: problems renaming ", stderr); ut_print_filename(stderr, old_name); diff --git a/storage/innobase/fsp/fsp0fsp.c b/storage/innobase/fsp/fsp0fsp.c index 2d626405c5c..6d00a1f1d4a 100644 --- a/storage/innobase/fsp/fsp0fsp.c +++ b/storage/innobase/fsp/fsp0fsp.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2012, 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 @@ -211,15 +211,13 @@ fseg_n_reserved_pages_low( /********************************************************************//** Marks a page used. The page must reside within the extents of the given segment. */ -static +static __attribute__((nonnull)) void fseg_mark_page_used( /*================*/ fseg_inode_t* seg_inode,/*!< in: segment inode */ - ulint space, /*!< in: space id */ - ulint zip_size,/*!< in: compressed page size in bytes - or 0 for uncompressed pages */ ulint page, /*!< in: page offset */ + xdes_t* descr, /* extent descriptor */ mtr_t* mtr); /*!< in: mtr */ /**********************************************************************//** Returns the first extent descriptor for a segment. We think of the extent @@ -250,28 +248,38 @@ fsp_fill_free_list( descriptor page and ibuf bitmap page; then we do not allocate more extents */ ulint space, /*!< in: space */ - fsp_header_t* header, /*!< in: space header */ - mtr_t* mtr); /*!< in: mtr */ + fsp_header_t* header, /*!< in/out: space header */ + mtr_t* mtr) /*!< in/out: mini-transaction */ + __attribute__((nonnull)); /**********************************************************************//** Allocates a single free page from a segment. This function implements the intelligent allocation strategy which tries to minimize file space fragmentation. -@return the allocated page number, FIL_NULL if no page could be allocated */ +@retval NULL if no page could be allocated +@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded +(init_mtr == mtr, or the page was not previously freed in mtr) +@retval block (not allocated or initialized) otherwise */ static -ulint +buf_block_t* fseg_alloc_free_page_low( /*=====================*/ ulint space, /*!< in: space */ ulint zip_size,/*!< in: compressed page size in bytes or 0 for uncompressed pages */ - fseg_inode_t* seg_inode, /*!< in: segment inode */ - ulint hint, /*!< in: hint of which page would be desirable */ + fseg_inode_t* seg_inode, /*!< in/out: segment inode */ + ulint hint, /*!< in: hint of which page would be + desirable */ byte direction, /*!< in: if the new page is needed because of an index page split, and records are inserted there in order, into which direction they go alphabetically: FSP_DOWN, FSP_UP, FSP_NO_DIR */ - mtr_t* mtr); /*!< in: mtr handle */ + mtr_t* mtr, /*!< in/out: mini-transaction */ + mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction + in which the page should be initialized. + If init_mtr!=mtr, but the page is already + latched in mtr, do not initialize the page. */ + __attribute__((warn_unused_result, nonnull)); #endif /* !UNIV_HOTBACKUP */ /**********************************************************************//** @@ -633,23 +641,22 @@ xdes_calc_descriptor_index( /********************************************************************//** Gets pointer to a the extent descriptor of a page. The page where the extent -descriptor resides is x-locked. If the page offset is equal to the free limit -of the space, adds new extents from above the free limit to the space free -list, if not free limit == space size. This adding is necessary to make the -descriptor defined, as they are uninitialized above the free limit. +descriptor resides is x-locked. This function no longer extends the data +file. @return pointer to the extent descriptor, NULL if the page does not -exist in the space or if the offset exceeds the free limit */ -UNIV_INLINE +exist in the space or if the offset is >= the free limit */ +UNIV_INLINE __attribute__((nonnull, warn_unused_result)) xdes_t* xdes_get_descriptor_with_space_hdr( /*===============================*/ - fsp_header_t* sp_header,/*!< in/out: space header, x-latched */ - ulint space, /*!< in: space id */ - ulint offset, /*!< in: page offset; - if equal to the free limit, - we try to add new extents to - the space free list */ - mtr_t* mtr) /*!< in: mtr handle */ + fsp_header_t* sp_header, /*!< in/out: space header, x-latched + in mtr */ + ulint space, /*!< in: space id */ + ulint offset, /*!< in: page offset; if equal + to the free limit, we try to + add new extents to the space + free list */ + mtr_t* mtr) /*!< in/out: mini-transaction */ { ulint limit; ulint size; @@ -657,11 +664,9 @@ xdes_get_descriptor_with_space_hdr( ulint descr_page_no; page_t* descr_page; - ut_ad(mtr); ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL), MTR_MEMO_X_LOCK)); - ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_S_FIX) - || mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX)); ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET); /* Read free limit and space size */ limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT); @@ -669,19 +674,10 @@ xdes_get_descriptor_with_space_hdr( zip_size = dict_table_flags_to_zip_size( mach_read_from_4(sp_header + FSP_SPACE_FLAGS)); - /* If offset is >= size or > limit, return NULL */ - - if ((offset >= size) || (offset > limit)) { - + if ((offset >= size) || (offset >= limit)) { return(NULL); } - /* If offset is == limit, fill free list of the space. */ - - if (offset == limit) { - fsp_fill_free_list(FALSE, space, sp_header, mtr); - } - descr_page_no = xdes_calc_descriptor_page(zip_size, offset); if (descr_page_no == 0) { @@ -711,7 +707,7 @@ is necessary to make the descriptor defined, as they are uninitialized above the free limit. @return pointer to the extent descriptor, NULL if the page does not exist in the space or if the offset exceeds the free limit */ -static +static __attribute__((nonnull, warn_unused_result)) xdes_t* xdes_get_descriptor( /*================*/ @@ -720,7 +716,7 @@ xdes_get_descriptor( or 0 for uncompressed pages */ ulint offset, /*!< in: page offset; if equal to the free limit, we try to add new extents to the space free list */ - mtr_t* mtr) /*!< in: mtr handle */ + mtr_t* mtr) /*!< in/out: mini-transaction */ { buf_block_t* block; fsp_header_t* sp_header; @@ -1098,14 +1094,14 @@ fsp_header_get_tablespace_size(void) Tries to extend a single-table tablespace so that a page would fit in the data file. @return TRUE if success */ -static +static __attribute__((nonnull, warn_unused_result)) ibool fsp_try_extend_data_file_with_pages( /*================================*/ ulint space, /*!< in: space */ ulint page_no, /*!< in: page number */ - fsp_header_t* header, /*!< in: space header */ - mtr_t* mtr) /*!< in: mtr */ + fsp_header_t* header, /*!< in/out: space header */ + mtr_t* mtr) /*!< in/out: mini-transaction */ { ibool success; ulint actual_size; @@ -1130,7 +1126,7 @@ fsp_try_extend_data_file_with_pages( /***********************************************************************//** Tries to extend the last data file of a tablespace if it is auto-extending. @return FALSE if not auto-extending */ -static +static __attribute__((nonnull)) ibool fsp_try_extend_data_file( /*=====================*/ @@ -1140,8 +1136,8 @@ fsp_try_extend_data_file( the actual file size rounded down to megabyte */ ulint space, /*!< in: space */ - fsp_header_t* header, /*!< in: space header */ - mtr_t* mtr) /*!< in: mtr */ + fsp_header_t* header, /*!< in/out: space header */ + mtr_t* mtr) /*!< in/out: mini-transaction */ { ulint size; ulint zip_size; @@ -1277,7 +1273,7 @@ fsp_fill_free_list( then we do not allocate more extents */ ulint space, /*!< in: space */ fsp_header_t* header, /*!< in/out: space header */ - mtr_t* mtr) /*!< in: mtr */ + mtr_t* mtr) /*!< in/out: mini-transaction */ { ulint limit; ulint size; @@ -1476,29 +1472,120 @@ fsp_alloc_free_extent( } /**********************************************************************//** -Allocates a single free page from a space. The page is marked as used. -@return the page offset, FIL_NULL if no page could be allocated */ +Allocates a single free page from a space. */ +static __attribute__((nonnull)) +void +fsp_alloc_from_free_frag( +/*=====================*/ + fsp_header_t* header, /*!< in/out: tablespace header */ + xdes_t* descr, /*!< in/out: extent descriptor */ + ulint bit, /*!< in: slot to allocate in the extent */ + mtr_t* mtr) /*!< in/out: mini-transaction */ +{ + ulint frag_n_used; + + ut_ad(xdes_get_state(descr, mtr) == XDES_FREE_FRAG); + ut_a(xdes_get_bit(descr, XDES_FREE_BIT, bit, mtr)); + xdes_set_bit(descr, XDES_FREE_BIT, bit, FALSE, mtr); + + /* Update the FRAG_N_USED field */ + frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES, + mtr); + frag_n_used++; + mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES, + mtr); + if (xdes_is_full(descr, mtr)) { + /* The fragment is full: move it to another list */ + flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE, + mtr); + xdes_set_state(descr, XDES_FULL_FRAG, mtr); + + flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE, + mtr); + mlog_write_ulint(header + FSP_FRAG_N_USED, + frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES, + mtr); + } +} + +/**********************************************************************//** +Gets a buffer block for an allocated page. + +NOTE: If init_mtr != mtr, the block will only be initialized if it was +not previously x-latched. It is assumed that the block has been +x-latched only by mtr, and freed in mtr in that case. + +@return block, initialized if init_mtr==mtr +or rw_lock_x_lock_count(&block->lock) == 1 */ static -ulint +buf_block_t* +fsp_page_create( +/*============*/ + ulint space, /*!< in: space id of the allocated page */ + ulint zip_size, /*!< in: compressed page size in bytes + or 0 for uncompressed pages */ + ulint page_no, /*!< in: page number of the allocated page */ + mtr_t* mtr, /*!< in: mini-transaction of the allocation */ + mtr_t* init_mtr) /*!< in: mini-transaction for initializing + the page */ +{ + buf_block_t* block + = buf_page_create(space, page_no, zip_size, init_mtr); +#ifdef UNIV_SYNC_DEBUG + ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX) + == rw_lock_own(&block->lock, RW_LOCK_EX)); +#endif /* UNIV_SYNC_DEBUG */ + + /* Mimic buf_page_get(), but avoid the buf_pool->page_hash lookup. */ + rw_lock_x_lock(&block->lock); + mutex_enter(&block->mutex); + buf_block_buf_fix_inc(block, __FILE__, __LINE__); + mutex_exit(&block->mutex); + mtr_memo_push(init_mtr, block, MTR_MEMO_PAGE_X_FIX); + + if (init_mtr == mtr + || rw_lock_get_x_lock_count(&block->lock) == 1) { + + /* Initialize the page, unless it was already + X-latched in mtr. (In this case, we would want to + allocate another page that has not been freed in mtr.) */ + ut_ad(init_mtr == mtr + || !mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + + fsp_init_file_page(block, init_mtr); + } + + return(block); +} + +/**********************************************************************//** +Allocates a single free page from a space. The page is marked as used. +@retval NULL if no page could be allocated +@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded +(init_mtr == mtr, or the page was not previously freed in mtr) +@retval block (not allocated or initialized) otherwise */ +static __attribute__((nonnull, warn_unused_result)) +buf_block_t* fsp_alloc_free_page( /*================*/ ulint space, /*!< in: space id */ ulint zip_size,/*!< in: compressed page size in bytes or 0 for uncompressed pages */ ulint hint, /*!< in: hint of which page would be desirable */ - mtr_t* mtr) /*!< in: mtr handle */ + mtr_t* mtr, /*!< in/out: mini-transaction */ + mtr_t* init_mtr)/*!< in/out: mini-transaction in which the + page should be initialized + (may be the same as mtr) */ { fsp_header_t* header; fil_addr_t first; xdes_t* descr; - buf_block_t* block; ulint free; - ulint frag_n_used; ulint page_no; ulint space_size; - ibool success; ut_ad(mtr); + ut_ad(init_mtr); header = fsp_get_space_header(space, zip_size, mtr); @@ -1525,7 +1612,7 @@ fsp_alloc_free_page( if (descr == NULL) { /* No free space left */ - return(FIL_NULL); + return(NULL); } xdes_set_state(descr, XDES_FREE_FRAG, mtr); @@ -1570,50 +1657,18 @@ fsp_alloc_free_page( " space size %lu. Page no %lu.\n", (ulong) space, (ulong) space_size, (ulong) page_no); - return(FIL_NULL); + return(NULL); } - success = fsp_try_extend_data_file_with_pages(space, page_no, - header, mtr); - if (!success) { + if (!fsp_try_extend_data_file_with_pages(space, page_no, + header, mtr)) { /* No disk space left */ - return(FIL_NULL); + return(NULL); } } - xdes_set_bit(descr, XDES_FREE_BIT, free, FALSE, mtr); + fsp_alloc_from_free_frag(header, descr, free, mtr); - /* Update the FRAG_N_USED field */ - frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES, - mtr); - frag_n_used++; - mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES, - mtr); - if (xdes_is_full(descr, mtr)) { - /* The fragment is full: move it to another list */ - flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE, - mtr); - xdes_set_state(descr, XDES_FULL_FRAG, mtr); - - flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE, - mtr); - mlog_write_ulint(header + FSP_FRAG_N_USED, - frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES, - mtr); - } - - /* Initialize the allocated page to the buffer pool, so that it can - be obtained immediately with buf_page_get without need for a disk - read. */ - - buf_page_create(space, page_no, zip_size, mtr); - - block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr); - buf_block_dbg_add_level(block, SYNC_FSP_PAGE); - - /* Prior contents of the page should be ignored */ - fsp_init_file_page(block, mtr); - - return(page_no); + return(fsp_page_create(space, zip_size, page_no, mtr, init_mtr)); } /**********************************************************************//** @@ -1652,6 +1707,9 @@ fsp_free_page( fputs("InnoDB: Dump of descriptor: ", stderr); ut_print_buf(stderr, ((byte*)descr) - 50, 200); putc('\n', stderr); + /* Crash in debug version, so that we get a core dump + of this corruption. */ + ut_ad(0); if (state == XDES_FREE) { /* We put here some fault tolerance: if the page @@ -1670,6 +1728,9 @@ fsp_free_page( "InnoDB: Dump of descriptor: ", (ulong) page); ut_print_buf(stderr, ((byte*)descr) - 50, 200); putc('\n', stderr); + /* Crash in debug version, so that we get a core dump + of this corruption. */ + ut_ad(0); /* We put here some fault tolerance: if the page is already free, return without doing anything! */ @@ -1704,6 +1765,8 @@ fsp_free_page( mtr); fsp_free_extent(space, zip_size, page, mtr); } + + mtr->n_freed_pages++; } /**********************************************************************//** @@ -1836,7 +1899,6 @@ fsp_alloc_seg_inode_page( fseg_inode_t* inode; buf_block_t* block; page_t* page; - ulint page_no; ulint space; ulint zip_size; ulint i; @@ -1847,15 +1909,15 @@ fsp_alloc_seg_inode_page( zip_size = dict_table_flags_to_zip_size( mach_read_from_4(FSP_SPACE_FLAGS + space_header)); - page_no = fsp_alloc_free_page(space, zip_size, 0, mtr); + block = fsp_alloc_free_page(space, zip_size, 0, mtr, mtr); - if (page_no == FIL_NULL) { + if (block == NULL) { return(FALSE); } - block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); + ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1); block->check_index_page_at_flush = FALSE; @@ -2258,19 +2320,20 @@ fseg_create_general( } if (page == 0) { - page = fseg_alloc_free_page_low(space, zip_size, - inode, 0, FSP_UP, mtr); + block = fseg_alloc_free_page_low(space, zip_size, + inode, 0, FSP_UP, mtr, mtr); - if (page == FIL_NULL) { + if (block == NULL) { fsp_free_seg_inode(space, zip_size, inode, mtr); goto funct_exit; } - block = buf_page_get(space, zip_size, page, RW_X_LATCH, mtr); + ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1); + header = byte_offset + buf_block_get_frame(block); - mlog_write_ulint(header - byte_offset + FIL_PAGE_TYPE, + mlog_write_ulint(buf_block_get_frame(block) + FIL_PAGE_TYPE, FIL_PAGE_TYPE_SYS, MLOG_2BYTES, mtr); } @@ -2447,8 +2510,10 @@ fseg_fill_free_list( Allocates a free extent for the segment: looks first in the free list of the segment, then tries to allocate from the space free list. NOTE that the extent returned still resides in the segment free list, it is not yet taken off it! -@return allocated extent, still placed in the segment free list, NULL -if could not be allocated */ +@retval NULL if no page could be allocated +@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded +(init_mtr == mtr, or the page was not previously freed in mtr) +@retval block (not allocated or initialized) otherwise */ static xdes_t* fseg_alloc_free_extent( @@ -2500,22 +2565,30 @@ fseg_alloc_free_extent( Allocates a single free page from a segment. This function implements the intelligent allocation strategy which tries to minimize file space fragmentation. -@return the allocated page number, FIL_NULL if no page could be allocated */ +@retval NULL if no page could be allocated +@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded +(init_mtr == mtr, or the page was not previously freed in mtr) +@retval block (not allocated or initialized) otherwise */ static -ulint +buf_block_t* fseg_alloc_free_page_low( /*=====================*/ ulint space, /*!< in: space */ ulint zip_size,/*!< in: compressed page size in bytes or 0 for uncompressed pages */ - fseg_inode_t* seg_inode, /*!< in: segment inode */ - ulint hint, /*!< in: hint of which page would be desirable */ + fseg_inode_t* seg_inode, /*!< in/out: segment inode */ + ulint hint, /*!< in: hint of which page would be + desirable */ byte direction, /*!< in: if the new page is needed because of an index page split, and records are inserted there in order, into which direction they go alphabetically: FSP_DOWN, FSP_UP, FSP_NO_DIR */ - mtr_t* mtr) /*!< in: mtr handle */ + mtr_t* mtr, /*!< in/out: mini-transaction */ + mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction + in which the page should be initialized. + If init_mtr!=mtr, but the page is already + latched in mtr, do not initialize the page. */ { fsp_header_t* space_header; ulint space_size; @@ -2526,7 +2599,6 @@ fseg_alloc_free_page_low( ulint ret_page; /*!< the allocated page offset, FIL_NULL if could not be allocated */ xdes_t* ret_descr; /*!< the extent of the allocated page */ - ibool frag_page_allocated = FALSE; ibool success; ulint n; @@ -2548,6 +2620,7 @@ fseg_alloc_free_page_low( if (descr == NULL) { /* Hint outside space or too high above free limit: reset hint */ + /* The file space header page is always allocated. */ hint = 0; descr = xdes_get_descriptor(space, zip_size, hint, mtr); } @@ -2558,15 +2631,19 @@ fseg_alloc_free_page_low( && mach_read_from_8(descr + XDES_ID) == seg_id && (xdes_get_bit(descr, XDES_FREE_BIT, hint % FSP_EXTENT_SIZE, mtr) == TRUE)) { - +take_hinted_page: /* 1. We can take the hinted page =================================*/ ret_descr = descr; ret_page = hint; + /* Skip the check for extending the tablespace. If the + page hint were not within the size of the tablespace, + we would have got (descr == NULL) above and reset the hint. */ + goto got_hinted_page; /*-----------------------------------------------------------*/ - } else if ((xdes_get_state(descr, mtr) == XDES_FREE) - && ((reserved - used) < reserved / FSEG_FILLFACTOR) - && (used >= FSEG_FRAG_LIMIT)) { + } else if (xdes_get_state(descr, mtr) == XDES_FREE + && reserved - used < reserved / FSEG_FILLFACTOR + && used >= FSEG_FRAG_LIMIT) { /* 2. We allocate the free extent from space and can take ========================================================= @@ -2584,7 +2661,7 @@ fseg_alloc_free_page_low( /* Try to fill the segment free list */ fseg_fill_free_list(seg_inode, space, zip_size, hint + FSP_EXTENT_SIZE, mtr); - ret_page = hint; + goto take_hinted_page; /*-----------------------------------------------------------*/ } else if ((direction != FSP_NO_DIR) && ((reserved - used) < reserved / FSEG_FILLFACTOR) @@ -2632,7 +2709,7 @@ fseg_alloc_free_page_low( first = flst_get_first(seg_inode + FSEG_FREE, mtr); } else { ut_error; - return(FIL_NULL); + return(NULL); } ret_descr = xdes_lst_get_descriptor(space, zip_size, @@ -2644,20 +2721,23 @@ fseg_alloc_free_page_low( } else if (used < FSEG_FRAG_LIMIT) { /* 6. We allocate an individual page from the space ===================================================*/ - ret_page = fsp_alloc_free_page(space, zip_size, hint, mtr); - ret_descr = NULL; - - frag_page_allocated = TRUE; + buf_block_t* block = fsp_alloc_free_page( + space, zip_size, hint, mtr, init_mtr); - if (ret_page != FIL_NULL) { + if (block != NULL) { /* Put the page in the fragment page array of the segment */ n = fseg_find_free_frag_page_slot(seg_inode, mtr); - ut_a(n != FIL_NULL); + ut_a(n != ULINT_UNDEFINED); - fseg_set_nth_frag_page_no(seg_inode, n, ret_page, - mtr); + fseg_set_nth_frag_page_no( + seg_inode, n, buf_block_get_page_no(block), + mtr); } + + /* fsp_alloc_free_page() invoked fsp_init_file_page() + already. */ + return(block); /*-----------------------------------------------------------*/ } else { /* 7. We allocate a new extent and take its first page @@ -2675,7 +2755,7 @@ fseg_alloc_free_page_low( if (ret_page == FIL_NULL) { /* Page could not be allocated */ - return(FIL_NULL); + return(NULL); } if (space != 0) { @@ -2693,38 +2773,22 @@ fseg_alloc_free_page_low( " the space size %lu. Page no %lu.\n", (ulong) space, (ulong) space_size, (ulong) ret_page); - return(FIL_NULL); + return(NULL); } success = fsp_try_extend_data_file_with_pages( space, ret_page, space_header, mtr); if (!success) { /* No disk space left */ - return(FIL_NULL); + return(NULL); } } } - if (!frag_page_allocated) { - /* Initialize the allocated page to buffer pool, so that it - can be obtained immediately with buf_page_get without need - for a disk read */ - buf_block_t* block; - ulint zip_size = dict_table_flags_to_zip_size( - mach_read_from_4(FSP_SPACE_FLAGS + space_header)); - - block = buf_page_create(space, ret_page, zip_size, mtr); - buf_block_dbg_add_level(block, SYNC_FSP_PAGE); - - if (UNIV_UNLIKELY(block != buf_page_get(space, zip_size, - ret_page, RW_X_LATCH, - mtr))) { - ut_error; - } - - /* The prior contents of the page should be ignored */ - fsp_init_file_page(block, mtr); - +got_hinted_page: + /* ret_descr == NULL if the block was allocated from free_frag + (XDES_FREE_FRAG) */ + if (ret_descr != NULL) { /* At this point we know the extent and the page offset. The extent is still in the appropriate list (FSEG_NOT_FULL or FSEG_FREE), and the page is not yet marked as used. */ @@ -2734,25 +2798,31 @@ fseg_alloc_free_page_low( ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT, ret_page % FSP_EXTENT_SIZE, mtr) == TRUE); - fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr); + fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr); } - buf_reset_check_index_page_at_flush(space, ret_page); - - return(ret_page); + return(fsp_page_create( + space, dict_table_flags_to_zip_size( + mach_read_from_4(FSP_SPACE_FLAGS + + space_header)), + ret_page, mtr, init_mtr)); } /**********************************************************************//** Allocates a single free page from a segment. This function implements the intelligent allocation strategy which tries to minimize file space fragmentation. -@return allocated page offset, FIL_NULL if no page could be allocated */ +@retval NULL if no page could be allocated +@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded +(init_mtr == mtr, or the page was not previously freed in mtr) +@retval block (not allocated or initialized) otherwise */ UNIV_INTERN -ulint +buf_block_t* fseg_alloc_free_page_general( /*=========================*/ - fseg_header_t* seg_header,/*!< in: segment header */ - ulint hint, /*!< in: hint of which page would be desirable */ + fseg_header_t* seg_header,/*!< in/out: segment header */ + ulint hint, /*!< in: hint of which page would be + desirable */ byte direction,/*!< in: if the new page is needed because of an index page split, and records are inserted there in order, into which @@ -2763,15 +2833,18 @@ fseg_alloc_free_page_general( with fsp_reserve_free_extents, then there is no need to do the check for this individual page */ - mtr_t* mtr) /*!< in: mtr handle */ + mtr_t* mtr, /*!< in/out: mini-transaction handle */ + mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction + in which the page should be initialized. + If init_mtr!=mtr, but the page is already + latched in mtr, do not initialize the page. */ { fseg_inode_t* inode; ulint space; ulint flags; ulint zip_size; rw_lock_t* latch; - ibool success; - ulint page_no; + buf_block_t* block; ulint n_reserved; space = page_get_space_id(page_align(seg_header)); @@ -2796,43 +2869,20 @@ fseg_alloc_free_page_general( inode = fseg_inode_get(seg_header, space, zip_size, mtr); - if (!has_done_reservation) { - success = fsp_reserve_free_extents(&n_reserved, space, 2, - FSP_NORMAL, mtr); - if (!success) { - return(FIL_NULL); - } + if (!has_done_reservation + && !fsp_reserve_free_extents(&n_reserved, space, 2, + FSP_NORMAL, mtr)) { + return(NULL); } - page_no = fseg_alloc_free_page_low(space, zip_size, - inode, hint, direction, mtr); + block = fseg_alloc_free_page_low(space, zip_size, + inode, hint, direction, + mtr, init_mtr); if (!has_done_reservation) { fil_space_release_free_extents(space, n_reserved); } - return(page_no); -} - -/**********************************************************************//** -Allocates a single free page from a segment. This function implements -the intelligent allocation strategy which tries to minimize file space -fragmentation. -@return allocated page offset, FIL_NULL if no page could be allocated */ -UNIV_INTERN -ulint -fseg_alloc_free_page( -/*=================*/ - fseg_header_t* seg_header,/*!< in: segment header */ - ulint hint, /*!< in: hint of which page would be desirable */ - byte direction,/*!< in: if the new page is needed because - of an index page split, and records are - inserted there in order, into which - direction they go alphabetically: FSP_DOWN, - FSP_UP, FSP_NO_DIR */ - mtr_t* mtr) /*!< in: mtr handle */ -{ - return(fseg_alloc_free_page_general(seg_header, hint, direction, - FALSE, mtr)); + return(block); } /**********************************************************************//** @@ -3154,27 +3204,21 @@ fsp_get_available_space_in_free_extents( /********************************************************************//** Marks a page used. The page must reside within the extents of the given segment. */ -static +static __attribute__((nonnull)) void fseg_mark_page_used( /*================*/ fseg_inode_t* seg_inode,/*!< in: segment inode */ - ulint space, /*!< in: space id */ - ulint zip_size,/*!< in: compressed page size in bytes - or 0 for uncompressed pages */ ulint page, /*!< in: page offset */ + xdes_t* descr, /* extent descriptor */ mtr_t* mtr) /*!< in: mtr */ { - xdes_t* descr; ulint not_full_n_used; - ut_ad(seg_inode && mtr); ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); - descr = xdes_get_descriptor(space, zip_size, page, mtr); - ut_ad(mtr_read_ulint(seg_inode + FSEG_ID, MLOG_4BYTES, mtr) == mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr)); @@ -3344,6 +3388,8 @@ crash: descr + XDES_FLST_NODE, mtr); fsp_free_extent(space, zip_size, page, mtr); } + + mtr->n_freed_pages++; } /**********************************************************************//** diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 705eeaf5f9c..c9d4a28868d 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -26,8 +26,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -1499,70 +1499,87 @@ values we want to reserve for multi-value inserts e.g., INSERT INTO T VALUES(), (), (); -innobase_next_autoinc() will be called with increment set to -n * 3 where autoinc_lock_mode != TRADITIONAL because we want -to reserve 3 values for the multi-value INSERT above. +innobase_next_autoinc() will be called with increment set to 3 where +autoinc_lock_mode != TRADITIONAL because we want to reserve 3 values for +the multi-value INSERT above. @return the next value */ static ulonglong innobase_next_autoinc( /*==================*/ ulonglong current, /*!< in: Current value */ - ulonglong increment, /*!< in: increment current by */ + ulonglong need, /*!< in: count of values needed */ + ulonglong step, /*!< in: AUTOINC increment step */ ulonglong offset, /*!< in: AUTOINC offset */ ulonglong max_value) /*!< in: max value for type */ { ulonglong next_value; + ulonglong block = need * step; /* Should never be 0. */ - ut_a(increment > 0); + ut_a(need > 0); + ut_a(block > 0); + ut_a(max_value > 0); + + /* Current value should never be greater than the maximum. */ + ut_a(current <= max_value); /* According to MySQL documentation, if the offset is greater than - the increment then the offset is ignored. */ - if (offset > increment) { + the step then the offset is ignored. */ + if (offset > block) { offset = 0; } - if (max_value <= current) { + /* Check for overflow. */ + if (block >= max_value + || offset > max_value + || current == max_value + || max_value - offset <= offset) { + next_value = max_value; - } else if (offset <= 1) { - /* Offset 0 and 1 are the same, because there must be at - least one node in the system. */ - if (max_value - current <= increment) { + } else { + ut_a(max_value > current); + + ulonglong free = max_value - current; + + if (free < offset || free - offset <= block) { next_value = max_value; } else { - next_value = current + increment; + next_value = 0; } - } else if (max_value > current) { + } + + if (next_value == 0) { + ulonglong next; + if (current > offset) { - next_value = ((current - offset) / increment) + 1; + next = (current - offset) / step; } else { - next_value = ((offset - current) / increment) + 1; + next = (offset - current) / step; } - ut_a(increment > 0); - ut_a(next_value > 0); - + ut_a(max_value > next); + next_value = next * step; /* Check for multiplication overflow. */ - if (increment > (max_value / next_value)) { + ut_a(next_value >= next); + ut_a(max_value > next_value); - next_value = max_value; - } else { - next_value *= increment; + /* Check for overflow */ + if (max_value - next_value >= block) { - ut_a(max_value >= next_value); + next_value += block; - /* Check for overflow. */ - if (max_value - next_value <= offset) { - next_value = max_value; - } else { + if (max_value - next_value >= offset) { next_value += offset; + } else { + next_value = max_value; } + } else { + next_value = max_value; } - } else { - next_value = max_value; } + ut_a(next_value != 0); ut_a(next_value <= max_value); return(next_value); @@ -3426,37 +3443,114 @@ normalize_table_name_low( { char* name_ptr; char* db_ptr; + ulint db_len; char* ptr; /* Scan name from the end */ - ptr = strend(name)-1; + ptr = strend(name) - 1; + /* seek to the last path separator */ while (ptr >= name && *ptr != '\\' && *ptr != '/') { ptr--; } name_ptr = ptr + 1; - DBUG_ASSERT(ptr > name); + /* skip any number of path separators */ + while (ptr >= name && (*ptr == '\\' || *ptr == '/')) { + ptr--; + } - ptr--; + DBUG_ASSERT(ptr >= name); + /* seek to the last but one path separator or one char before + the beginning of name */ + db_len = 0; while (ptr >= name && *ptr != '\\' && *ptr != '/') { ptr--; + db_len++; } db_ptr = ptr + 1; - memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name)); + memcpy(norm_name, db_ptr, db_len); + + norm_name[db_len] = '/'; - norm_name[name_ptr - db_ptr - 1] = '/'; + memcpy(norm_name + db_len + 1, name_ptr, strlen(name_ptr) + 1); if (set_lower_case) { innobase_casedn_str(norm_name); } } +#if !defined(DBUG_OFF) +/********************************************************************* +Test normalize_table_name_low(). */ +static +void +test_normalize_table_name_low() +/*===========================*/ +{ + char norm_name[128]; + const char* test_data[][2] = { + /* input, expected result */ + {"./mysqltest/t1", "mysqltest/t1"}, + {"./test/#sql-842b_2", "test/#sql-842b_2"}, + {"./test/#sql-85a3_10", "test/#sql-85a3_10"}, + {"./test/#sql2-842b-2", "test/#sql2-842b-2"}, + {"./test/bug29807", "test/bug29807"}, + {"./test/foo", "test/foo"}, + {"./test/innodb_bug52663", "test/innodb_bug52663"}, + {"./test/t", "test/t"}, + {"./test/t1", "test/t1"}, + {"./test/t10", "test/t10"}, + {"/a/b/db/table", "db/table"}, + {"/a/b/db///////table", "db/table"}, + {"/a/b////db///////table", "db/table"}, + {"/var/tmp/mysqld.1/#sql842b_2_10", "mysqld.1/#sql842b_2_10"}, + {"db/table", "db/table"}, + {"ddd/t", "ddd/t"}, + {"d/ttt", "d/ttt"}, + {"d/t", "d/t"}, + {".\\mysqltest\\t1", "mysqltest/t1"}, + {".\\test\\#sql-842b_2", "test/#sql-842b_2"}, + {".\\test\\#sql-85a3_10", "test/#sql-85a3_10"}, + {".\\test\\#sql2-842b-2", "test/#sql2-842b-2"}, + {".\\test\\bug29807", "test/bug29807"}, + {".\\test\\foo", "test/foo"}, + {".\\test\\innodb_bug52663", "test/innodb_bug52663"}, + {".\\test\\t", "test/t"}, + {".\\test\\t1", "test/t1"}, + {".\\test\\t10", "test/t10"}, + {"C:\\a\\b\\db\\table", "db/table"}, + {"C:\\a\\b\\db\\\\\\\\\\\\\\table", "db/table"}, + {"C:\\a\\b\\\\\\\\db\\\\\\\\\\\\\\table", "db/table"}, + {"C:\\var\\tmp\\mysqld.1\\#sql842b_2_10", "mysqld.1/#sql842b_2_10"}, + {"db\\table", "db/table"}, + {"ddd\\t", "ddd/t"}, + {"d\\ttt", "d/ttt"}, + {"d\\t", "d/t"}, + }; + + for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) { + printf("test_normalize_table_name_low(): " + "testing \"%s\", expected \"%s\"... ", + test_data[i][0], test_data[i][1]); + + normalize_table_name_low(norm_name, test_data[i][0], FALSE); + + if (strcmp(norm_name, test_data[i][1]) == 0) { + printf("ok\n"); + } else { + printf("got \"%s\"\n", norm_name); + ut_error; + } + } +} +#endif /* !DBUG_OFF */ + /********************************************************************//** Get the upper limit of the MySQL integral and floating-point type. @return maximum allowed value for the field */ @@ -3803,7 +3897,7 @@ ha_innobase::innobase_initialize_autoinc() nor the offset, so use a default increment of 1. */ auto_inc = innobase_next_autoinc( - read_auto_inc, 1, 1, col_max_value); + read_auto_inc, 1, 1, 0, col_max_value); break; } @@ -5651,15 +5745,16 @@ set_max_autoinc: if (auto_inc <= col_max_value) { ut_a(prebuilt->autoinc_increment > 0); - ulonglong need; ulonglong offset; + ulonglong increment; offset = prebuilt->autoinc_offset; - need = prebuilt->autoinc_increment; + increment = prebuilt->autoinc_increment; auto_inc = innobase_next_autoinc( auto_inc, - need, offset, col_max_value); + 1, increment, offset, + col_max_value); err = innobase_set_max_autoinc( auto_inc); @@ -5941,14 +6036,14 @@ ha_innobase::update_row( if (auto_inc <= col_max_value && auto_inc != 0) { - ulonglong need; ulonglong offset; + ulonglong increment; offset = prebuilt->autoinc_offset; - need = prebuilt->autoinc_increment; + increment = prebuilt->autoinc_increment; auto_inc = innobase_next_autoinc( - auto_inc, need, offset, col_max_value); + auto_inc, 1, increment, offset, col_max_value); error = innobase_set_max_autoinc(auto_inc); } @@ -7682,6 +7777,8 @@ ha_innobase::create( DBUG_RETURN(HA_ERR_TO_BIG_ROW); } + ut_a(strlen(name) < sizeof(name2)); + strcpy(name2, name); normalize_table_name(norm_name, name2); @@ -8099,6 +8196,11 @@ ha_innobase::delete_table( DBUG_ENTER("ha_innobase::delete_table"); + DBUG_EXECUTE_IF( + "test_normalize_table_name_low", + test_normalize_table_name_low(); + ); + /* Strangely, MySQL passes the table name without the '.frm' extension, in contrast to ::create */ normalize_table_name(norm_name, name); @@ -10866,16 +10968,15 @@ ha_innobase::get_auto_increment( /* With old style AUTOINC locking we only update the table's AUTOINC counter after attempting to insert the row. */ if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) { - ulonglong need; ulonglong current; ulonglong next_value; current = *first_value > col_max_value ? autoinc : *first_value; - need = *nb_reserved_values * increment; /* Compute the last value in the interval */ next_value = innobase_next_autoinc( - current, need, offset, col_max_value); + current, *nb_reserved_values, increment, offset, + col_max_value); prebuilt->autoinc_last_value = next_value; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index f05bcb844d5..9b34275ec9f 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 2005, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -1147,7 +1147,9 @@ ha_innobase::prepare_drop_index( goto func_exit; } + rw_lock_x_lock(dict_index_get_lock(index)); index->to_be_dropped = TRUE; + rw_lock_x_unlock(dict_index_get_lock(index)); } /* If FOREIGN_KEY_CHECKS = 1 you may not drop an index defined @@ -1266,7 +1268,9 @@ func_exit: = dict_table_get_first_index(prebuilt->table); do { + rw_lock_x_lock(dict_index_get_lock(index)); index->to_be_dropped = FALSE; + rw_lock_x_unlock(dict_index_get_lock(index)); index = dict_table_get_next_index(index); } while (index); } @@ -1326,7 +1330,9 @@ ha_innobase::final_drop_index( for (index = dict_table_get_first_index(prebuilt->table); index; index = dict_table_get_next_index(index)) { + rw_lock_x_lock(dict_index_get_lock(index)); index->to_be_dropped = FALSE; + rw_lock_x_unlock(dict_index_get_lock(index)); } goto func_exit; diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index 96af9038be2..e534e165c0c 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -2180,14 +2180,14 @@ ibool ibuf_add_free_page(void) /*====================*/ { - mtr_t mtr; - page_t* header_page; - ulint flags; - ulint zip_size; - ulint page_no; - page_t* page; - page_t* root; - page_t* bitmap_page; + mtr_t mtr; + page_t* header_page; + ulint flags; + ulint zip_size; + buf_block_t* block; + page_t* page; + page_t* root; + page_t* bitmap_page; mtr_start(&mtr); @@ -2208,28 +2208,23 @@ ibuf_add_free_page(void) of a deadlock. This is the reason why we created a special ibuf header page apart from the ibuf tree. */ - page_no = fseg_alloc_free_page( + block = fseg_alloc_free_page( header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP, &mtr); - if (UNIV_UNLIKELY(page_no == FIL_NULL)) { + if (block == NULL) { mtr_commit(&mtr); return(FALSE); - } else { - buf_block_t* block = buf_page_get( - IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr); - - ibuf_enter(&mtr); - - mutex_enter(&ibuf_mutex); - - root = ibuf_tree_root_get(&mtr); + } - buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW); + ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1); + ibuf_enter(&mtr); + mutex_enter(&ibuf_mutex); + root = ibuf_tree_root_get(&mtr); - page = buf_block_get_frame(block); - } + buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW); + page = buf_block_get_frame(block); /* Add the page to the free list and update the ibuf size data */ @@ -2246,12 +2241,13 @@ ibuf_add_free_page(void) (level 2 page) */ bitmap_page = ibuf_bitmap_get_map_page( - IBUF_SPACE_ID, page_no, zip_size, &mtr); + IBUF_SPACE_ID, buf_block_get_page_no(block), zip_size, &mtr); mutex_exit(&ibuf_mutex); ibuf_bitmap_page_set_bits( - bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr); + bitmap_page, buf_block_get_page_no(block), zip_size, + IBUF_BITMAP_IBUF, TRUE, &mtr); ibuf_mtr_commit(&mtr); @@ -3931,9 +3927,10 @@ ibuf_insert_to_index_page( "InnoDB: but the number of fields does not match!\n", stderr); dump: - buf_page_print(page, 0); + buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH); dtuple_print(stderr, entry); + ut_ad(0); fputs("InnoDB: The table where where" " this index record belongs\n" @@ -4431,7 +4428,7 @@ ibuf_merge_or_delete_for_page( function. When the counter is > 0, that prevents tablespace from being dropped. */ - tablespace_being_deleted = fil_inc_pending_ibuf_merges(space); + tablespace_being_deleted = fil_inc_pending_ops(space); if (UNIV_UNLIKELY(tablespace_being_deleted)) { /* Do not try to read the bitmap page from space; @@ -4457,7 +4454,7 @@ ibuf_merge_or_delete_for_page( /* No inserts buffered for this page */ if (!tablespace_being_deleted) { - fil_decr_pending_ibuf_merges(space); + fil_decr_pending_ops(space); } return; @@ -4506,12 +4503,14 @@ ibuf_merge_or_delete_for_page( bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, &mtr); - buf_page_print(bitmap_page, 0); + buf_page_print(bitmap_page, 0, + BUF_PAGE_PRINT_NO_CRASH); ibuf_mtr_commit(&mtr); fputs("\nInnoDB: Dump of the page:\n", stderr); - buf_page_print(block->frame, 0); + buf_page_print(block->frame, 0, + BUF_PAGE_PRINT_NO_CRASH); fprintf(stderr, "InnoDB: Error: corruption in the tablespace." @@ -4531,6 +4530,7 @@ ibuf_merge_or_delete_for_page( (ulong) page_no, (ulong) fil_page_get_type(block->frame)); + ut_ad(0); } } @@ -4753,7 +4753,7 @@ reset_bit: if (update_ibuf_bitmap && !tablespace_being_deleted) { - fil_decr_pending_ibuf_merges(space); + fil_decr_pending_ops(space); } #ifdef UNIV_IBUF_COUNT_DEBUG diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index 93b59fdfafb..f531b785786 100644 --- a/storage/innobase/include/btr0btr.h +++ b/storage/innobase/include/btr0btr.h @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -519,11 +519,14 @@ UNIV_INTERN ibool btr_compress( /*=========*/ - btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift; - the page must not be empty: in record delete - use btr_discard_page if the page would become - empty */ - mtr_t* mtr); /*!< in: mtr */ + btr_cur_t* cursor, /*!< in/out: cursor on the page to merge + or lift; the page must not be empty: + when deleting records, use btr_discard_page() + if the page would become empty */ + ibool adjust, /*!< in: TRUE if should adjust the + cursor position even if compression occurs */ + mtr_t* mtr) /*!< in/out: mini-transaction */ + __attribute__((nonnull)); /*************************************************************//** Discards a page from a B-tree. This is used to remove the last record from a B-tree page: the whole page must be removed at the same time. This cannot @@ -564,17 +567,23 @@ btr_parse_page_reorganize( #ifndef UNIV_HOTBACKUP /**************************************************************//** Gets the number of pages in a B-tree. -@return number of pages */ +@return number of pages, or ULINT_UNDEFINED if the index is unavailable */ UNIV_INTERN ulint btr_get_size( /*=========*/ dict_index_t* index, /*!< in: index */ - ulint flag); /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */ + ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */ + mtr_t* mtr) /*!< in/out: mini-transaction where index + is s-latched */ + __attribute__((nonnull, warn_unused_result)); /**************************************************************//** Allocates a new file page to be used in an index tree. NOTE: we assume that the caller has made the reservation for free extents! -@return new allocated block, x-latched; NULL if out of space */ +@retval NULL if no page could be allocated +@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded +(init_mtr == mtr, or the page was not previously freed in mtr) +@retval block (not allocated or initialized) otherwise */ UNIV_INTERN buf_block_t* btr_page_alloc( @@ -585,7 +594,12 @@ btr_page_alloc( page split is made */ ulint level, /*!< in: level where the page is placed in the tree */ - mtr_t* mtr); /*!< in: mtr */ + mtr_t* mtr, /*!< in/out: mini-transaction + for the allocation */ + mtr_t* init_mtr) /*!< in/out: mini-transaction + for x-latching and initializing + the page */ + __attribute__((nonnull, warn_unused_result)); /**************************************************************//** Frees a file page used in an index tree. NOTE: cannot free field external storage pages because the page must contain info on its level. */ diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic index 1bd22a0ebc6..55bdb289b21 100644 --- a/storage/innobase/include/btr0btr.ic +++ b/storage/innobase/include/btr0btr.ic @@ -277,7 +277,7 @@ btr_node_ptr_get_child_page_no( "InnoDB: a nonsensical page number 0" " in a node ptr record at offset %lu\n", (ulong) page_offset(rec)); - buf_page_print(page_align(rec), 0); + buf_page_print(page_align(rec), 0, 0); } return(page_no); diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h index 4f33aacc48e..cbc6103c2ee 100644 --- a/storage/innobase/include/btr0cur.h +++ b/storage/innobase/include/btr0cur.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1994, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -36,6 +36,9 @@ Created 10/16/1994 Heikki Tuuri #define BTR_NO_LOCKING_FLAG 2 /* do no record lock checking */ #define BTR_KEEP_SYS_FLAG 4 /* sys fields will be found from the update vector or inserted entry */ +#define BTR_KEEP_POS_FLAG 8 /* btr_cur_pessimistic_update() + must keep cursor position when + moving columns to big_rec */ #ifndef UNIV_HOTBACKUP #include "que0types.h" @@ -310,7 +313,9 @@ btr_cur_pessimistic_update( /*=======================*/ ulint flags, /*!< in: undo logging, locking, and rollback flags */ - btr_cur_t* cursor, /*!< in: cursor on the record to update */ + btr_cur_t* cursor, /*!< in/out: cursor on the record to update; + cursor may become invalid if *big_rec == NULL + || !(flags & BTR_KEEP_POS_FLAG) */ mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */ big_rec_t** big_rec,/*!< out: big rec vector whose fields have to be stored externally by the caller, or NULL */ @@ -364,10 +369,13 @@ UNIV_INTERN ibool btr_cur_compress_if_useful( /*=======================*/ - btr_cur_t* cursor, /*!< in: cursor on the page to compress; + btr_cur_t* cursor, /*!< in/out: cursor on the page to compress; cursor does not stay valid if compression occurs */ - mtr_t* mtr); /*!< in: mtr */ + ibool adjust, /*!< in: TRUE if should adjust the + cursor position even if compression occurs */ + mtr_t* mtr) /*!< in/out: mini-transaction */ + __attribute__((nonnull)); /*******************************************************//** Removes the record on which the tree cursor is positioned. It is assumed that the mtr has an x-latch on the page where the cursor is positioned, @@ -492,6 +500,27 @@ btr_cur_disown_inherited_fields( const upd_t* update, /*!< in: update vector */ mtr_t* mtr) /*!< in/out: mini-transaction */ __attribute__((nonnull(2,3,4,5,6))); + +/** Operation code for btr_store_big_rec_extern_fields(). */ +enum blob_op { + /** Store off-page columns for a freshly inserted record */ + BTR_STORE_INSERT = 0, + /** Store off-page columns for an insert by update */ + BTR_STORE_INSERT_UPDATE, + /** Store off-page columns for an update */ + BTR_STORE_UPDATE +}; + +/*******************************************************************//** +Determine if an operation on off-page columns is an update. +@return TRUE if op != BTR_STORE_INSERT */ +UNIV_INLINE +ibool +btr_blob_op_is_update( +/*==================*/ + enum blob_op op) /*!< in: operation */ + __attribute__((warn_unused_result)); + /*******************************************************************//** Stores the fields in big_rec_vec to the tablespace and puts pointers to them in rec. The extern flags in rec will have to be set beforehand. @@ -499,52 +528,23 @@ The fields are stored on pages allocated from leaf node file segment of the index tree. @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ UNIV_INTERN -ulint -btr_store_big_rec_extern_fields_func( -/*=================================*/ +enum db_err +btr_store_big_rec_extern_fields( +/*============================*/ dict_index_t* index, /*!< in: index of rec; the index tree MUST be X-latched */ buf_block_t* rec_block, /*!< in/out: block containing rec */ - rec_t* rec, /*!< in: record */ + rec_t* rec, /*!< in/out: record */ const ulint* offsets, /*!< in: rec_get_offsets(rec, index); the "external storage" flags in offsets will not correspond to rec when this function returns */ -#ifdef UNIV_DEBUG - mtr_t* local_mtr, /*!< in: mtr containing the - latch to rec and to the tree */ -#endif /* UNIV_DEBUG */ -#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG - ibool update_in_place,/*! in: TRUE if the record is updated - in place (not delete+insert) */ -#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ - const big_rec_t*big_rec_vec) /*!< in: vector containing fields + const big_rec_t*big_rec_vec, /*!< in: vector containing fields to be stored externally */ - __attribute__((nonnull)); - -/** Stores the fields in big_rec_vec to the tablespace and puts pointers to -them in rec. The extern flags in rec will have to be set beforehand. -The fields are stored on pages allocated from leaf node -file segment of the index tree. -@param index in: clustered index; MUST be X-latched by mtr -@param b in/out: block containing rec; MUST be X-latched by mtr -@param rec in/out: clustered index record -@param offsets in: rec_get_offsets(rec, index); - the "external storage" flags in offsets will not be adjusted -@param mtr in: mini-transaction that holds x-latch on index and b -@param upd in: TRUE if the record is updated in place (not delete+insert) -@param big in: vector containing fields to be stored externally -@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ -#ifdef UNIV_DEBUG -# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \ - btr_store_big_rec_extern_fields_func(index,b,rec,offsets,mtr,upd,big) -#elif defined UNIV_BLOB_LIGHT_DEBUG -# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \ - btr_store_big_rec_extern_fields_func(index,b,rec,offsets,upd,big) -#else -# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \ - btr_store_big_rec_extern_fields_func(index,b,rec,offsets,big) -#endif + mtr_t* btr_mtr, /*!< in: mtr containing the + latches to the clustered index */ + enum blob_op op) /*! in: operation code */ + __attribute__((nonnull, warn_unused_result)); /*******************************************************************//** Frees the space in an externally stored field to the file space diff --git a/storage/innobase/include/btr0cur.ic b/storage/innobase/include/btr0cur.ic index 280583f6ccf..e31f77c77eb 100644 --- a/storage/innobase/include/btr0cur.ic +++ b/storage/innobase/include/btr0cur.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1994, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -139,7 +139,7 @@ btr_cur_compress_recommendation( btr_cur_t* cursor, /*!< in: btr cursor */ mtr_t* mtr) /*!< in: mtr */ { - page_t* page; + const page_t* page; ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), MTR_MEMO_PAGE_X_FIX)); @@ -197,4 +197,25 @@ btr_cur_can_delete_without_compress( return(TRUE); } + +/*******************************************************************//** +Determine if an operation on off-page columns is an update. +@return TRUE if op != BTR_STORE_INSERT */ +UNIV_INLINE +ibool +btr_blob_op_is_update( +/*==================*/ + enum blob_op op) /*!< in: operation */ +{ + switch (op) { + case BTR_STORE_INSERT: + return(FALSE); + case BTR_STORE_INSERT_UPDATE: + case BTR_STORE_UPDATE: + return(TRUE); + } + + ut_ad(0); + return(FALSE); +} #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 456f077a13d..d9e6801eb86 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -596,6 +596,31 @@ buf_block_get_modify_clock( #else /* !UNIV_HOTBACKUP */ # define buf_block_modify_clock_inc(block) ((void) 0) #endif /* !UNIV_HOTBACKUP */ +/*******************************************************************//** +Increments the bufferfix count. */ +UNIV_INLINE +void +buf_block_buf_fix_inc_func( +/*=======================*/ +#ifdef UNIV_SYNC_DEBUG + const char* file, /*!< in: file name */ + ulint line, /*!< in: line */ +#endif /* UNIV_SYNC_DEBUG */ + buf_block_t* block) /*!< in/out: block to bufferfix */ + __attribute__((nonnull)); +#ifdef UNIV_SYNC_DEBUG +/** Increments the bufferfix count. +@param b in/out: block to bufferfix +@param f in: file name where requested +@param l in: line number where requested */ +# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b) +#else /* UNIV_SYNC_DEBUG */ +/** Increments the bufferfix count. +@param b in/out: block to bufferfix +@param f in: file name where requested +@param l in: line number where requested */ +# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b) +#endif /* UNIV_SYNC_DEBUG */ /********************************************************************//** Calculates a page checksum which is stored to the page when it is written to a file. Note that we must be careful to calculate the same value @@ -680,6 +705,13 @@ buf_print(void); /*============*/ #endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */ #endif /* !UNIV_HOTBACKUP */ +enum buf_page_print_flags { + /** Do not crash at the end of buf_page_print(). */ + BUF_PAGE_PRINT_NO_CRASH = 1, + /** Do not print the full page dump. */ + BUF_PAGE_PRINT_NO_FULL = 2 +}; + /********************************************************************//** Prints a page to stderr. */ UNIV_INTERN @@ -687,8 +719,12 @@ void buf_page_print( /*===========*/ const byte* read_buf, /*!< in: a database page */ - ulint zip_size); /*!< in: compressed page size, or + ulint zip_size, /*!< in: compressed page size, or 0 for uncompressed pages */ + ulint flags) /*!< in: 0 or + BUF_PAGE_PRINT_NO_CRASH or + BUF_PAGE_PRINT_NO_FULL */ + __attribute__((nonnull)); /********************************************************************//** Decompress a block. @return TRUE if successful */ @@ -753,11 +789,11 @@ buf_all_freed(void); /*********************************************************************//** Checks that there currently are no pending i/o-operations for the buffer pool. -@return TRUE if there is no pending i/o */ +@return number of pending i/o operations */ UNIV_INTERN -ibool -buf_pool_check_no_pending_io(void); -/*==============================*/ +ulint +buf_pool_check_num_pending_io(void); +/*===============================*/ /*********************************************************************//** Invalidates the file pages in the buffer pool when an archive recovery is completed. All the file pages buffered must be in a replaceable state when diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic index 99e55df3312..917ee5dda84 100644 --- a/storage/innobase/include/buf0buf.ic +++ b/storage/innobase/include/buf0buf.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -18,8 +18,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -988,19 +988,6 @@ buf_block_buf_fix_inc_func( block->page.buf_fix_count++; } -#ifdef UNIV_SYNC_DEBUG -/** Increments the bufferfix count. -@param b in/out: block to bufferfix -@param f in: file name where requested -@param l in: line number where requested */ -# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b) -#else /* UNIV_SYNC_DEBUG */ -/** Increments the bufferfix count. -@param b in/out: block to bufferfix -@param f in: file name where requested -@param l in: line number where requested */ -# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b) -#endif /* UNIV_SYNC_DEBUG */ /*******************************************************************//** Decrements the bufferfix count. */ @@ -1251,7 +1238,7 @@ buf_block_dbg_add_level( where we have acquired latch */ ulint level) /*!< in: latching order level */ { - sync_thread_add_level(&block->lock, level); + sync_thread_add_level(&block->lock, level, FALSE); } #endif /* UNIV_SYNC_DEBUG */ /********************************************************************//** diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h index eb40621abbe..9ecb9de2afe 100644 --- a/storage/innobase/include/buf0lru.h +++ b/storage/innobase/include/buf0lru.h @@ -64,15 +64,14 @@ These are low-level functions #define BUF_LRU_FREE_SEARCH_LEN(b) (5 + 2 * BUF_READ_AHEAD_AREA(b)) /******************************************************************//** -Invalidates all pages belonging to a given tablespace when we are deleting -the data file(s) of that tablespace. A PROBLEM: if readahead is being started, -what guarantees that it will not try to read in pages after this operation has -completed? */ +Removes all pages belonging to a given tablespace. */ UNIV_INTERN void -buf_LRU_invalidate_tablespace( +buf_LRU_flush_or_remove_pages( /*==========================*/ - ulint id); /*!< in: space id */ + ulint id, /*!< in: space id */ + enum buf_remove_t buf_remove);/*!< in: remove or flush + strategy */ #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /********************************************************************//** Insert a compressed block into buf_pool->zip_clean in the LRU order. */ diff --git a/storage/innobase/include/buf0types.h b/storage/innobase/include/buf0types.h index 12b9e22f673..6fd48826165 100644 --- a/storage/innobase/include/buf0types.h +++ b/storage/innobase/include/buf0types.h @@ -63,6 +63,15 @@ enum buf_io_fix { the flush_list */ }; +/** Algorithm to remove the pages for a tablespace from the buffer pool. +@See buf_LRU_flush_or_remove_pages(). */ +enum buf_remove_t { + BUF_REMOVE_ALL_NO_WRITE, /*!< Remove all pages from the buffer + pool, don't write or sync to disk */ + BUF_REMOVE_FLUSH_NO_WRITE, /*!< Remove only, from the flush list, + don't write or sync to disk */ +}; + /** Parameters of binary buddy system for compressed pages (buf0buddy.h) */ /* @{ */ #define BUF_BUDDY_LOW_SHIFT PAGE_ZIP_MIN_SIZE_SHIFT diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 57e51cbb6ba..89d6fc66635 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -1087,14 +1087,6 @@ dict_index_get_page( /*================*/ const dict_index_t* tree); /*!< in: index */ /*********************************************************************//** -Sets the page number of the root of index tree. */ -UNIV_INLINE -void -dict_index_set_page( -/*================*/ - dict_index_t* index, /*!< in/out: index */ - ulint page); /*!< in: page number */ -/*********************************************************************//** Gets the read-write lock of the index tree. @return read-write lock */ UNIV_INLINE diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index ade9e627e29..7533ce01401 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -762,21 +762,6 @@ dict_index_get_page( } /*********************************************************************//** -Sets the page number of the root of index tree. */ -UNIV_INLINE -void -dict_index_set_page( -/*================*/ - dict_index_t* index, /*!< in/out: index */ - ulint page) /*!< in: page number */ -{ - ut_ad(index); - ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); - - index->page = page; -} - -/*********************************************************************//** Gets the read-write lock of the index tree. @return read-write lock */ UNIV_INLINE diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 3389c7d72b3..25a3a5a82e0 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -399,7 +399,9 @@ struct dict_index_struct{ unsigned to_be_dropped:1; /*!< TRUE if this index is marked to be dropped in ha_innobase::prepare_drop_index(), - otherwise FALSE */ + otherwise FALSE. Protected by + dict_sys->mutex, dict_operation_lock and + index->lock.*/ dict_field_t* fields; /*!< array of field descriptions */ #ifndef UNIV_HOTBACKUP UT_LIST_NODE_T(dict_index_t) diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index d50b0cb4162..610bd4b0e5c 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -346,20 +346,19 @@ fil_read_first_page( ib_uint64_t* max_flushed_lsn); /*!< out: max of flushed lsn values in data files */ /*******************************************************************//** -Increments the count of pending insert buffer page merges, if space is not -being deleted. -@return TRUE if being deleted, and ibuf merges should be skipped */ +Increments the count of pending operation, if space is not being deleted. +@return TRUE if being deleted, and operation should be skipped */ UNIV_INTERN ibool -fil_inc_pending_ibuf_merges( -/*========================*/ +fil_inc_pending_ops( +/*================*/ ulint id); /*!< in: space id */ /*******************************************************************//** -Decrements the count of pending insert buffer page merges. */ +Decrements the count of pending operations. */ UNIV_INTERN void -fil_decr_pending_ibuf_merges( -/*=========================*/ +fil_decr_pending_ops( +/*=================*/ ulint id); /*!< in: space id */ #endif /* !UNIV_HOTBACKUP */ /*******************************************************************//** @@ -398,7 +397,9 @@ UNIV_INTERN ibool fil_delete_tablespace( /*==================*/ - ulint id); /*!< in: space id */ + ulint id, /*!< in: space id */ + ibool evict_all); /*!< in: TRUE if we want all pages + evicted from LRU. */ #ifndef UNIV_HOTBACKUP /*******************************************************************//** Discards a single-table tablespace. The tablespace must be cached in the diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index 4efabacb2cb..f07e3decc66 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2012, 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 @@ -260,30 +260,33 @@ fseg_n_reserved_pages( Allocates a single free page from a segment. This function implements the intelligent allocation strategy which tries to minimize file space fragmentation. -@return the allocated page offset FIL_NULL if no page could be allocated */ -UNIV_INTERN -ulint -fseg_alloc_free_page( -/*=================*/ - fseg_header_t* seg_header, /*!< in: segment header */ - ulint hint, /*!< in: hint of which page would be desirable */ - byte direction, /*!< in: if the new page is needed because +@param[in/out] seg_header segment header +@param[in] hint hint of which page would be desirable +@param[in] direction if the new page is needed because of an index page split, and records are inserted there in order, into which direction they go alphabetically: FSP_DOWN, - FSP_UP, FSP_NO_DIR */ - mtr_t* mtr); /*!< in: mtr handle */ + FSP_UP, FSP_NO_DIR +@param[in/out] mtr mini-transaction +@return X-latched block, or NULL if no page could be allocated */ +#define fseg_alloc_free_page(seg_header, hint, direction, mtr) \ + fseg_alloc_free_page_general(seg_header, hint, direction, \ + FALSE, mtr, mtr) /**********************************************************************//** Allocates a single free page from a segment. This function implements the intelligent allocation strategy which tries to minimize file space fragmentation. -@return allocated page offset, FIL_NULL if no page could be allocated */ +@retval NULL if no page could be allocated +@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded +(init_mtr == mtr, or the page was not previously freed in mtr) +@retval block (not allocated or initialized) otherwise */ UNIV_INTERN -ulint +buf_block_t* fseg_alloc_free_page_general( /*=========================*/ - fseg_header_t* seg_header,/*!< in: segment header */ - ulint hint, /*!< in: hint of which page would be desirable */ + fseg_header_t* seg_header,/*!< in/out: segment header */ + ulint hint, /*!< in: hint of which page would be + desirable */ byte direction,/*!< in: if the new page is needed because of an index page split, and records are inserted there in order, into which @@ -294,8 +297,12 @@ fseg_alloc_free_page_general( with fsp_reserve_free_extents, then there is no need to do the check for this individual page */ - mtr_t* mtr) /*!< in/out: mini-transaction */ - __attribute__((warn_unused_result, nonnull(1,5))); + mtr_t* mtr, /*!< in/out: mini-transaction */ + mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction + in which the page should be initialized. + If init_mtr!=mtr, but the page is already + latched in mtr, do not initialize the page. */ + __attribute__((warn_unused_result, nonnull)); /**********************************************************************//** Reserves free pages from a tablespace. All mini-transactions which may use several pages from the tablespace should call this function beforehand diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 1ae94a332e5..f2ab6a9898d 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2010, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -18,8 +18,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 7f608546cc2..46f1ff9310c 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -50,7 +50,9 @@ first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */ #define MTR_MEMO_PAGE_S_FIX RW_S_LATCH #define MTR_MEMO_PAGE_X_FIX RW_X_LATCH #define MTR_MEMO_BUF_FIX RW_NO_LATCH -#define MTR_MEMO_MODIFY 54 +#ifdef UNIV_DEBUG +# define MTR_MEMO_MODIFY 54 +#endif /* UNIV_DEBUG */ #define MTR_MEMO_S_LOCK 55 #define MTR_MEMO_X_LOCK 56 @@ -376,6 +378,9 @@ struct mtr_struct{ ulint n_log_recs; /* count of how many page initial log records have been written to the mtr log */ + ulint n_freed_pages; + /* number of pages that have been freed in + this mini-transaction */ ulint log_mode; /* specifies which operations should be logged; default value MTR_LOG_ALL */ ib_uint64_t start_lsn;/* start lsn of the possible log entry for diff --git a/storage/innobase/include/mtr0mtr.ic b/storage/innobase/include/mtr0mtr.ic index 1db4a4bd735..a03a0271535 100644 --- a/storage/innobase/include/mtr0mtr.ic +++ b/storage/innobase/include/mtr0mtr.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -46,6 +46,7 @@ mtr_start( mtr->modifications = FALSE; mtr->inside_ibuf = FALSE; mtr->n_log_recs = 0; + mtr->n_freed_pages = 0; ut_d(mtr->state = MTR_ACTIVE); ut_d(mtr->magic_n = MTR_MAGIC_N); @@ -248,7 +249,7 @@ mtr_s_lock_func( ut_ad(mtr); ut_ad(lock); - rw_lock_s_lock_func(lock, 0, file, line); + rw_lock_s_lock_inline(lock, 0, file, line); mtr_memo_push(mtr, lock, MTR_MEMO_S_LOCK); } @@ -267,7 +268,7 @@ mtr_x_lock_func( ut_ad(mtr); ut_ad(lock); - rw_lock_x_lock_func(lock, 0, file, line); + rw_lock_x_lock_inline(lock, 0, file, line); mtr_memo_push(mtr, lock, MTR_MEMO_X_LOCK); } diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h index 540ec7855bc..74e9ceca959 100644 --- a/storage/innobase/include/page0page.h +++ b/storage/innobase/include/page0page.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1994, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -281,16 +281,42 @@ page_get_supremum_offset( const page_t* page); /*!< in: page which must have record(s) */ #define page_get_infimum_rec(page) ((page) + page_get_infimum_offset(page)) #define page_get_supremum_rec(page) ((page) + page_get_supremum_offset(page)) + /************************************************************//** -Returns the middle record of record list. If there are an even number -of records in the list, returns the first record of upper half-list. -@return middle record */ +Returns the nth record of the record list. +This is the inverse function of page_rec_get_n_recs_before(). +@return nth record */ UNIV_INTERN +const rec_t* +page_rec_get_nth_const( +/*===================*/ + const page_t* page, /*!< in: page */ + ulint nth) /*!< in: nth record */ + __attribute__((nonnull, warn_unused_result)); +/************************************************************//** +Returns the nth record of the record list. +This is the inverse function of page_rec_get_n_recs_before(). +@return nth record */ +UNIV_INLINE +rec_t* +page_rec_get_nth( +/*=============*/ + page_t* page, /*< in: page */ + ulint nth) /*!< in: nth record */ + __attribute__((nonnull, warn_unused_result)); + +#ifndef UNIV_HOTBACKUP +/************************************************************//** +Returns the middle record of the records on the page. If there is an +even number of records in the list, returns the first record of the +upper half-list. +@return middle record */ +UNIV_INLINE rec_t* page_get_middle_rec( /*================*/ - page_t* page); /*!< in: page */ -#ifndef UNIV_HOTBACKUP + page_t* page) /*!< in: page */ + __attribute__((nonnull, warn_unused_result)); /*************************************************************//** Compares a data tuple to a physical record. Differs from the function cmp_dtuple_rec_with_match in the way that the record must reside on an @@ -345,6 +371,7 @@ page_get_n_recs( /***************************************************************//** Returns the number of records before the given record in chain. The number includes infimum and supremum records. +This is the inverse function of page_rec_get_nth(). @return number of records */ UNIV_INTERN ulint diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index 115cee64f8b..781ad029e87 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1994, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -419,7 +419,37 @@ page_rec_is_infimum( return(page_rec_is_infimum_low(page_offset(rec))); } +/************************************************************//** +Returns the nth record of the record list. +This is the inverse function of page_rec_get_n_recs_before(). +@return nth record */ +UNIV_INLINE +rec_t* +page_rec_get_nth( +/*=============*/ + page_t* page, /*!< in: page */ + ulint nth) /*!< in: nth record */ +{ + return((rec_t*) page_rec_get_nth_const(page, nth)); +} + #ifndef UNIV_HOTBACKUP +/************************************************************//** +Returns the middle record of the records on the page. If there is an +even number of records in the list, returns the first record of the +upper half-list. +@return middle record */ +UNIV_INLINE +rec_t* +page_get_middle_rec( +/*================*/ + page_t* page) /*!< in: page */ +{ + ulint middle = (page_get_n_recs(page) + PAGE_HEAP_NO_USER_LOW) / 2; + + return(page_rec_get_nth(page, middle)); +} + /*************************************************************//** Compares a data tuple to a physical record. Differs from the function cmp_dtuple_rec_with_match in the way that the record must reside on an @@ -710,7 +740,7 @@ page_rec_get_next_low( (void*) rec, (ulong) page_get_space_id(page), (ulong) page_get_page_no(page)); - buf_page_print(page, 0); + buf_page_print(page, 0, 0); ut_error; } diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index edfea04bed3..90accf471a2 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -682,12 +682,14 @@ srv_que_task_enqueue_low( que_thr_t* thr); /*!< in: query thread */ /**********************************************************************//** -Check whether any background thread is active. -@return FALSE if all are are suspended or have exited. */ +Check whether any background thread is active. If so, return the thread +type. +@return ULINT_UNDEFINED if all are are suspended or have exited, thread +type if any are still active. */ UNIV_INTERN -ibool -srv_is_any_background_thread_active(void); -/*======================================*/ +ulint +srv_get_active_thread_type(void); +/*============================*/ /** Status variables to be passed to MySQL */ struct export_var_struct{ diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h index dedf080d00a..2cab266d86a 100644 --- a/storage/innobase/include/sync0rw.h +++ b/storage/innobase/include/sync0rw.h @@ -154,6 +154,9 @@ unlocking, not the corresponding function. */ # define rw_lock_s_lock(M) \ rw_lock_s_lock_func((M), 0, __FILE__, __LINE__) +# define rw_lock_s_lock_inline(M, P, F, L) \ + rw_lock_s_lock_func((M), (P), (F), (L)) + # define rw_lock_s_lock_gen(M, P) \ rw_lock_s_lock_func((M), (P), __FILE__, __LINE__) @@ -170,12 +173,18 @@ unlocking, not the corresponding function. */ # define rw_lock_x_lock(M) \ rw_lock_x_lock_func((M), 0, __FILE__, __LINE__) +# define rw_lock_x_lock_inline(M, P, F, L) \ + rw_lock_x_lock_func((M), (P), (F), (L)) + # define rw_lock_x_lock_gen(M, P) \ rw_lock_x_lock_func((M), (P), __FILE__, __LINE__) # define rw_lock_x_lock_nowait(M) \ rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__) +# define rw_lock_x_lock_func_nowait_inline(M, F, L) \ + rw_lock_x_lock_func_nowait((M), (F), (L)) + # ifdef UNIV_SYNC_DEBUG # define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(P, L) # else @@ -207,6 +216,9 @@ unlocking, not the corresponding function. */ # define rw_lock_s_lock(M) \ pfs_rw_lock_s_lock_func((M), 0, __FILE__, __LINE__) +# define rw_lock_s_lock_inline(M, P, F, L) \ + pfs_rw_lock_s_lock_func((M), (P), (F), (L)) + # define rw_lock_s_lock_gen(M, P) \ pfs_rw_lock_s_lock_func((M), (P), __FILE__, __LINE__) @@ -222,12 +234,18 @@ unlocking, not the corresponding function. */ # define rw_lock_x_lock(M) \ pfs_rw_lock_x_lock_func((M), 0, __FILE__, __LINE__) +# define rw_lock_x_lock_inline(M, P, F, L) \ + pfs_rw_lock_x_lock_func((M), (P), (F), (L)) + # define rw_lock_x_lock_gen(M, P) \ pfs_rw_lock_x_lock_func((M), (P), __FILE__, __LINE__) # define rw_lock_x_lock_nowait(M) \ pfs_rw_lock_x_lock_func_nowait((M), __FILE__, __LINE__) +# define rw_lock_x_lock_func_nowait_inline(M, F, L) \ + pfs_rw_lock_x_lock_func_nowait((M), (F), (L)) + # ifdef UNIV_SYNC_DEBUG # define rw_lock_x_unlock_gen(L, P) pfs_rw_lock_x_unlock_func(P, L) # else diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic index 51cf7121b4c..a5a7cda14f9 100644 --- a/storage/innobase/include/sync0rw.ic +++ b/storage/innobase/include/sync0rw.ic @@ -90,7 +90,7 @@ rw_lock_set_waiter_flag( rw_lock_t* lock) /*!< in/out: rw-lock */ { #ifdef INNODB_RW_LOCKS_USE_ATOMICS - os_compare_and_swap_ulint(&lock->waiters, 0, 1); + (void) os_compare_and_swap_ulint(&lock->waiters, 0, 1); #else /* INNODB_RW_LOCKS_USE_ATOMICS */ lock->waiters = 1; #endif /* INNODB_RW_LOCKS_USE_ATOMICS */ @@ -107,7 +107,7 @@ rw_lock_reset_waiter_flag( rw_lock_t* lock) /*!< in/out: rw-lock */ { #ifdef INNODB_RW_LOCKS_USE_ATOMICS - os_compare_and_swap_ulint(&lock->waiters, 1, 0); + (void) os_compare_and_swap_ulint(&lock->waiters, 1, 0); #else /* INNODB_RW_LOCKS_USE_ATOMICS */ lock->waiters = 0; #endif /* INNODB_RW_LOCKS_USE_ATOMICS */ @@ -564,8 +564,6 @@ rw_lock_x_unlock_func( if (lock->lock_word == 0) { /* Last caller in a possible recursive chain. */ lock->recursive = FALSE; - UNIV_MEM_INVALID(&lock->writer_thread, - sizeof lock->writer_thread); } #ifdef UNIV_SYNC_DEBUG @@ -610,8 +608,6 @@ rw_lock_x_unlock_direct( if (lock->lock_word == 0) { lock->recursive = FALSE; - UNIV_MEM_INVALID(&lock->writer_thread, - sizeof lock->writer_thread); } lock->lock_word += X_LOCK_DECR; diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h index b5bf30e758c..9b07c4758c9 100644 --- a/storage/innobase/include/sync0sync.h +++ b/storage/innobase/include/sync0sync.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -18,8 +18,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -400,8 +400,10 @@ void sync_thread_add_level( /*==================*/ void* latch, /*!< in: pointer to a mutex or an rw-lock */ - ulint level); /*!< in: level in the latching order; if + ulint level, /*!< in: level in the latching order; if SYNC_LEVEL_VARYING, nothing is done */ + ibool relock) /*!< in: TRUE if re-entering an x-lock */ + __attribute__((nonnull)); /******************************************************************//** Removes a latch from the thread level array if it is found there. @return TRUE if found in the array; it is no error if the latch is diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h index 0b83a76cab7..2bd9e64476b 100644 --- a/storage/innobase/include/trx0purge.h +++ b/storage/innobase/include/trx0purge.h @@ -143,9 +143,9 @@ struct trx_purge_struct{ obtaining an s-latch here. */ read_view_t* view; /*!< The purge will not remove undo logs which are >= this view (purge view) */ - ulint n_pages_handled;/*!< Approximate number of undo log + ulonglong n_pages_handled;/*!< Approximate number of undo log pages processed in purge */ - ulint handle_limit; /*!< Target of how many pages to get + ulonglong handle_limit; /*!< Target of how many pages to get processed in the current purge */ /*------------------------------*/ /* The following two fields form the 'purge pointer' which advances diff --git a/storage/innobase/include/trx0rec.ic b/storage/innobase/include/trx0rec.ic index f0b3276ed44..4fc5a7147f9 100644 --- a/storage/innobase/include/trx0rec.ic +++ b/storage/innobase/include/trx0rec.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -107,6 +107,7 @@ trx_undo_rec_copy( len = mach_read_from_2(undo_rec) - ut_align_offset(undo_rec, UNIV_PAGE_SIZE); + ut_ad(len < UNIV_PAGE_SIZE); return(mem_heap_dup(heap, undo_rec, len)); } #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h index 50aa6d0ac09..4a1e40af505 100644 --- a/storage/innobase/include/trx0undo.h +++ b/storage/innobase/include/trx0undo.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -194,16 +194,17 @@ trx_undo_get_first_rec( mtr_t* mtr); /*!< in: mtr */ /********************************************************************//** Tries to add a page to the undo log segment where the undo log is placed. -@return page number if success, else FIL_NULL */ +@return X-latched block if success, else NULL */ UNIV_INTERN -ulint +buf_block_t* trx_undo_add_page( /*==============*/ trx_t* trx, /*!< in: transaction */ trx_undo_t* undo, /*!< in: undo log memory object */ - mtr_t* mtr); /*!< in: mtr which does not have a latch to any + mtr_t* mtr) /*!< in: mtr which does not have a latch to any undo log page; the caller must have reserved the rollback segment mutex */ + __attribute__((nonnull, warn_unused_result)); /********************************************************************//** Frees the last undo log page. The caller must hold the rollback segment mutex. */ diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h index cad39e9a34f..47ab6eb9b74 100644 --- a/storage/innobase/include/ut0ut.h +++ b/storage/innobase/include/ut0ut.h @@ -63,16 +63,16 @@ typedef time_t ib_time_t; # define UT_RELAX_CPU() __asm__ __volatile__ ("pause") #elif defined(HAVE_FAKE_PAUSE_INSTRUCTION) # define UT_RELAX_CPU() __asm__ __volatile__ ("rep; nop") -#elif defined(HAVE_ATOMIC_BUILTINS) -# define UT_RELAX_CPU() do { \ - volatile lint volatile_var; \ - os_compare_and_swap_lint(&volatile_var, 0, 1); \ - } while (0) #elif defined(HAVE_WINDOWS_ATOMICS) /* In the Win32 API, the x86 PAUSE instruction is executed by calling the YieldProcessor macro defined in WinNT.h. It is a CPU architecture- independent way by using YieldProcessor. */ # define UT_RELAX_CPU() YieldProcessor() +#elif defined(HAVE_ATOMIC_BUILTINS) +# define UT_RELAX_CPU() do { \ + volatile lint volatile_var; \ + os_compare_and_swap_lint(&volatile_var, 0, 1); \ + } while (0) #else # define UT_RELAX_CPU() ((void)0) /* avoid warning for an empty statement */ #endif diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 35cbb228e05..99a2cdc9b73 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -1655,7 +1655,7 @@ lock_sec_rec_some_has_impl_off_kernel( if (!lock_check_trx_id_sanity(page_get_max_trx_id(page), rec, index, offsets, TRUE)) { - buf_page_print(page, 0); + buf_page_print(page, 0, 0); /* The page is corrupt: try to avoid a crash by returning NULL */ @@ -5236,6 +5236,79 @@ function_exit: } /*********************************************************************//** +Validate record locks up to a limit. +@return lock at limit or NULL if no more locks in the hash bucket */ +static __attribute__((nonnull, warn_unused_result)) +const lock_t* +lock_rec_validate( +/*==============*/ + ulint start, /*!< in: lock_sys->rec_hash + bucket */ + ib_uint64_t* limit) /*!< in/out: upper limit of + (space, page_no) */ +{ + lock_t* lock; + ut_ad(mutex_own(&kernel_mutex)); + + for (lock = HASH_GET_FIRST(lock_sys->rec_hash, start); + lock != NULL; + lock = HASH_GET_NEXT(hash, lock)) { + + ib_uint64_t current; + + ut_a(trx_in_trx_list(lock->trx)); + ut_a(lock_get_type(lock) == LOCK_REC); + + current = ut_ull_create( + lock->un_member.rec_lock.space, + lock->un_member.rec_lock.page_no); + + if (current > *limit) { + *limit = current + 1; + return(lock); + } + } + + return(NULL); +} + +/*********************************************************************//** +Validate a record lock's block */ +static +void +lock_rec_block_validate( +/*====================*/ + ulint space, + ulint page_no) +{ + /* The lock and the block that it is referring to may be freed at + this point. We pass BUF_GET_POSSIBLY_FREED to skip a debug check. + If the lock exists in lock_rec_validate_page() we assert + !block->page.file_page_was_freed. */ + + mtr_t mtr; + buf_block_t* block; + + /* Make sure that the tablespace is not deleted while we are + trying to access the page. */ + if (!fil_inc_pending_ops(space)) { + mtr_start(&mtr); + block = buf_page_get_gen( + space, fil_space_get_zip_size(space), + page_no, RW_X_LATCH, NULL, + BUF_GET_POSSIBLY_FREED, + __FILE__, __LINE__, &mtr); + + buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); + + ut_ad(lock_rec_validate_page(block)); + mtr_commit(&mtr); + + fil_decr_pending_ops(space); + } +} + +/*********************************************************************//** Validates the lock system. @return TRUE if ok */ static @@ -5267,60 +5340,21 @@ lock_validate(void) trx = UT_LIST_GET_NEXT(trx_list, trx); } - for (i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) { - - ulint space; - ulint page_no; - ib_uint64_t limit = 0; - - for (;;) { - mtr_t mtr; - buf_block_t* block; - - lock = HASH_GET_FIRST(lock_sys->rec_hash, i); - - while (lock) { - ib_uint64_t space_page; - ut_a(trx_in_trx_list(lock->trx)); - - space = lock->un_member.rec_lock.space; - page_no = lock->un_member.rec_lock.page_no; - - space_page = ut_ull_create(space, page_no); + /* Iterate over all the record locks and validate the locks. We + don't want to hog the lock_sys_t::mutex and the trx_sys_t::mutex. + Release both mutexes during the validation check. */ - if (space_page >= limit) { - break; - } - - lock = HASH_GET_NEXT(hash, lock); - } + for (i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) { + const lock_t* lock; + ib_uint64_t limit = 0; - if (!lock) { + while ((lock = lock_rec_validate(i, &limit)) != NULL) { - break; - } + ulint space = lock->un_member.rec_lock.space; + ulint page_no = lock->un_member.rec_lock.page_no; lock_mutex_exit_kernel(); - - /* The lock and the block that it is referring - to may be freed at this point. We pass - BUF_GET_POSSIBLY_FREED to skip a debug check. - If the lock exists in lock_rec_validate_page() - we assert !block->page.file_page_was_freed. */ - - mtr_start(&mtr); - block = buf_page_get_gen( - space, fil_space_get_zip_size(space), - page_no, RW_X_LATCH, NULL, - BUF_GET_POSSIBLY_FREED, - __FILE__, __LINE__, &mtr); - buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); - - ut_ad(lock_rec_validate_page(block)); - mtr_commit(&mtr); - - limit++; - + lock_rec_block_validate(space, page_no); lock_mutex_enter_kernel(); } } diff --git a/storage/innobase/log/log0log.c b/storage/innobase/log/log0log.c index fd2258945b6..8bae95f0a5d 100644 --- a/storage/innobase/log/log0log.c +++ b/storage/innobase/log/log0log.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2010, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -18,8 +18,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -3076,9 +3076,12 @@ void logs_empty_and_mark_files_at_shutdown(void) /*=======================================*/ { - ib_uint64_t lsn; - ulint arch_log_no; - ibool server_busy; + ib_uint64_t lsn; + ulint arch_log_no; + ibool server_busy; + ulint count = 0; + ulint pending_io; + ulint active_thd; if (srv_print_verbose_log) { ut_print_timestamp(stderr); @@ -3091,6 +3094,8 @@ logs_empty_and_mark_files_at_shutdown(void) loop: os_thread_sleep(100000); + count++; + mutex_enter(&kernel_mutex); /* We need the monitor threads to stop before we proceed with @@ -3099,6 +3104,21 @@ loop: if (srv_error_monitor_active || srv_lock_timeout_active || srv_monitor_active) { + const char* thread_active = NULL; + + /* Print a message every 60 seconds if we are waiting + for the monitor thread to exit. Master and worker threads + check will be done later. */ + if (srv_print_verbose_log && count > 600) { + + if (srv_error_monitor_active) { + thread_active = "srv_error_monitor_thread"; + } else if (srv_lock_timeout_active) { + thread_active = "srv_lock_timeout thread"; + } else if (srv_monitor_active) { + thread_active = "srv_monitor_thread"; + } + } mutex_exit(&kernel_mutex); @@ -3106,6 +3126,13 @@ loop: os_event_set(srv_monitor_event); os_event_set(srv_timeout_event); + if (thread_active) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Waiting for %s to exit\n", + thread_active); + count = 0; + } + goto loop; } @@ -3116,9 +3143,54 @@ loop: server_busy = trx_n_mysql_transactions > 0 || UT_LIST_GET_LEN(trx_sys->trx_list) > trx_n_prepared; + + if (server_busy) { + ulint total_trx = UT_LIST_GET_LEN(trx_sys->trx_list) + + trx_n_mysql_transactions; + + mutex_exit(&kernel_mutex); + + if (srv_print_verbose_log && count > 600) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Waiting for %lu " + "active transactions to finish\n", + (ulong) total_trx); + count = 0; + } + + goto loop; + } + mutex_exit(&kernel_mutex); - if (server_busy || srv_is_any_background_thread_active()) { + /* Check that the background threads are suspended */ + active_thd = srv_get_active_thread_type(); + + if (active_thd != ULINT_UNDEFINED) { + + /* The srv_lock_timeout_thread, srv_error_monitor_thread + and srv_monitor_thread should already exit by now. The + only threads to be suspended are the master threads + and worker threads (purge threads). Print the thread + type if any of such threads not in suspended mode */ + if (srv_print_verbose_log && count > 600) { + const char* thread_type = "<null>"; + + switch (active_thd) { + case SRV_WORKER: + thread_type = "worker threads"; + break; + case SRV_MASTER: + thread_type = "master thread"; + break; + } + + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Waiting for %s " + "to be suspended\n", thread_type); + count = 0; + } + goto loop; } @@ -3130,10 +3202,35 @@ loop: || log_sys->n_pending_writes; mutex_exit(&log_sys->mutex); - if (server_busy || !buf_pool_check_no_pending_io()) { + if (server_busy) { + if (srv_print_verbose_log && count > 600) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Pending checkpoint_writes: %lu\n" + " InnoDB: Pending log flush writes: %lu\n", + (ulong) log_sys->n_pending_checkpoint_writes, + (ulong) log_sys->n_pending_writes); + count = 0; + } + goto loop; } + pending_io = buf_pool_check_num_pending_io(); + + if (pending_io) { + if (srv_print_verbose_log && count > 600) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Waiting for %lu buffer page " + "I/Os to complete\n", + (ulong) pending_io); + count = 0; + } + + goto loop; + } + + #ifdef UNIV_LOG_ARCHIVE log_archive_all(); #endif /* UNIV_LOG_ARCHIVE */ @@ -3157,7 +3254,7 @@ loop: log_buffer_flush_to_disk(); /* Check that the background threads stay suspended */ - if (srv_is_any_background_thread_active()) { + if (srv_get_active_thread_type() != ULINT_UNDEFINED) { fprintf(stderr, "InnoDB: Warning: some background thread" " woke up during shutdown\n"); @@ -3166,7 +3263,7 @@ loop: srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE; fil_close_all_files(); - ut_a(!srv_is_any_background_thread_active()); + ut_a(srv_get_active_thread_type() == ULINT_UNDEFINED); return; } @@ -3204,7 +3301,7 @@ loop: mutex_exit(&log_sys->mutex); /* Check that the background threads stay suspended */ - if (srv_is_any_background_thread_active()) { + if (srv_get_active_thread_type() != ULINT_UNDEFINED) { fprintf(stderr, "InnoDB: Warning: some background thread woke up" " during shutdown\n"); @@ -3222,13 +3319,20 @@ loop: if (!buf_all_freed()) { + if (srv_print_verbose_log && count > 600) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Waiting for dirty buffer " + "pages to be flushed\n"); + count = 0; + } + goto loop; } srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE; /* Make some checks that the server really is quiet */ - ut_a(!srv_is_any_background_thread_active()); + ut_a(srv_get_active_thread_type() == ULINT_UNDEFINED); ut_a(buf_all_freed()); ut_a(lsn == log_sys->lsn); @@ -3250,7 +3354,7 @@ loop: fil_close_all_files(); /* Make some checks that the server really is quiet */ - ut_a(!srv_is_any_background_thread_active()); + ut_a(srv_get_active_thread_type() == ULINT_UNDEFINED); ut_a(buf_all_freed()); ut_a(lsn == log_sys->lsn); diff --git a/storage/innobase/mtr/mtr0mtr.c b/storage/innobase/mtr/mtr0mtr.c index 08234609ff0..d852ed6f496 100644 --- a/storage/innobase/mtr/mtr0mtr.c +++ b/storage/innobase/mtr/mtr0mtr.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c index a9069708e98..cc8dff3b621 100644 --- a/storage/innobase/os/os0file.c +++ b/storage/innobase/os/os0file.c @@ -2817,7 +2817,7 @@ retry: "InnoDB: Check also that the disk is not full" " or a disk quota exceeded.\n", name, (ulong) offset_high, (ulong) offset, - (ulong) n, (ulong) len, (ulong) err); + (ulong) n, ret ? len : 0, (ulong) err); if (strerror((int)err) != NULL) { fprintf(stderr, diff --git a/storage/innobase/page/page0cur.c b/storage/innobase/page/page0cur.c index 936762b986a..d49b121afab 100644 --- a/storage/innobase/page/page0cur.c +++ b/storage/innobase/page/page0cur.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1994, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -900,7 +900,7 @@ page_cur_parse_insert_rec( ut_print_buf(stderr, ptr2, 300); putc('\n', stderr); - buf_page_print(page, 0); + buf_page_print(page, 0, 0); ut_error; } @@ -1180,14 +1180,15 @@ page_cur_insert_rec_zip_reorg( /* Before trying to reorganize the page, store the number of preceding records on the page. */ pos = page_rec_get_n_recs_before(rec); + ut_ad(pos > 0); if (page_zip_reorganize(block, index, mtr)) { /* The page was reorganized: Find rec by seeking to pos, and update *current_rec. */ - rec = page + PAGE_NEW_INFIMUM; - - while (--pos) { - rec = page + rec_get_next_offs(rec, TRUE); + if (pos > 1) { + rec = page_rec_get_nth(page, pos - 1); + } else { + rec = page + PAGE_NEW_INFIMUM; } *current_rec = rec; @@ -1283,6 +1284,12 @@ page_cur_insert_rec_zip( insert_rec = page_cur_insert_rec_zip_reorg( current_rec, block, index, insert_rec, page, page_zip, mtr); +#ifdef UNIV_DEBUG + if (insert_rec) { + rec_offs_make_valid( + insert_rec, index, offsets); + } +#endif /* UNIV_DEBUG */ } return(insert_rec); diff --git a/storage/innobase/page/page0page.c b/storage/innobase/page/page0page.c index e250bb359fe..5f0380cb55f 100644 --- a/storage/innobase/page/page0page.c +++ b/storage/innobase/page/page0page.c @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -148,7 +148,7 @@ page_dir_find_owner_slot( fputs("\n" "InnoDB: on that page!\n", stderr); - buf_page_print(page, 0); + buf_page_print(page, 0, 0); ut_error; } @@ -569,8 +569,10 @@ page_copy_rec_list_end_no_locks( /* Track an assertion failure reported on the mailing list on June 18th, 2003 */ - buf_page_print(new_page, 0); - buf_page_print(page_align(rec), 0); + buf_page_print(new_page, 0, + BUF_PAGE_PRINT_NO_CRASH); + buf_page_print(page_align(rec), 0, + BUF_PAGE_PRINT_NO_CRASH); ut_print_timestamp(stderr); fprintf(stderr, @@ -1452,55 +1454,54 @@ page_dir_balance_slot( } } -#ifndef UNIV_HOTBACKUP /************************************************************//** -Returns the middle record of the record list. If there are an even number -of records in the list, returns the first record of the upper half-list. -@return middle record */ +Returns the nth record of the record list. +This is the inverse function of page_rec_get_n_recs_before(). +@return nth record */ UNIV_INTERN -rec_t* -page_get_middle_rec( -/*================*/ - page_t* page) /*!< in: page */ +const rec_t* +page_rec_get_nth_const( +/*===================*/ + const page_t* page, /*!< in: page */ + ulint nth) /*!< in: nth record */ { - page_dir_slot_t* slot; - ulint middle; + const page_dir_slot_t* slot; ulint i; ulint n_owned; - ulint count; - rec_t* rec; - - /* This many records we must leave behind */ - middle = (page_get_n_recs(page) + PAGE_HEAP_NO_USER_LOW) / 2; + const rec_t* rec; - count = 0; + ut_ad(nth < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1)); for (i = 0;; i++) { slot = page_dir_get_nth_slot(page, i); n_owned = page_dir_slot_get_n_owned(slot); - if (count + n_owned > middle) { + if (n_owned > nth) { break; } else { - count += n_owned; + nth -= n_owned; } } ut_ad(i > 0); slot = page_dir_get_nth_slot(page, i - 1); - rec = (rec_t*) page_dir_slot_get_rec(slot); - rec = page_rec_get_next(rec); - - /* There are now count records behind rec */ + rec = page_dir_slot_get_rec(slot); - for (i = 0; i < middle - count; i++) { - rec = page_rec_get_next(rec); + if (page_is_comp(page)) { + do { + rec = page_rec_get_next_low(rec, TRUE); + ut_ad(rec); + } while (nth--); + } else { + do { + rec = page_rec_get_next_low(rec, FALSE); + ut_ad(rec); + } while (nth--); } return(rec); } -#endif /* !UNIV_HOTBACKUP */ /***************************************************************//** Returns the number of records before the given record in chain. @@ -1562,6 +1563,7 @@ page_rec_get_n_recs_before( n--; ut_ad(n >= 0); + ut_ad(n < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1)); return((ulint) n); } @@ -1834,7 +1836,7 @@ page_check_dir( fprintf(stderr, "InnoDB: Page directory corruption:" " infimum not pointed to\n"); - buf_page_print(page, 0); + buf_page_print(page, 0, 0); } if (UNIV_UNLIKELY(!page_rec_is_supremum_low(supremum_offs))) { @@ -1842,7 +1844,7 @@ page_check_dir( fprintf(stderr, "InnoDB: Page directory corruption:" " supremum not pointed to\n"); - buf_page_print(page, 0); + buf_page_print(page, 0, 0); } } #endif /* !UNIV_HOTBACKUP */ @@ -2546,7 +2548,7 @@ func_exit2: (ulong) page_get_space_id(page), (ulong) page_get_page_no(page), index->name); - buf_page_print(page, 0); + buf_page_print(page, 0, 0); } return(ret); diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index 19da93f55eb..172b997ac08 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -23,6 +23,8 @@ Insert into a table Created 4/20/1996 Heikki Tuuri *******************************************************/ +#include "m_string.h" /* for my_sys.h */ +#include "my_sys.h" /* DEBUG_SYNC_C */ #include "row0ins.h" #ifdef UNIV_NONINL @@ -348,9 +350,9 @@ row_ins_clust_index_entry_by_modify( return(DB_LOCK_TABLE_FULL); } - err = btr_cur_pessimistic_update(0, cursor, - heap, big_rec, update, - 0, thr, mtr); + err = btr_cur_pessimistic_update( + BTR_KEEP_POS_FLAG, cursor, heap, big_rec, update, + 0, thr, mtr); } return(err); @@ -2025,6 +2027,7 @@ row_ins_index_entry_low( ulint modify = 0; /* remove warning */ rec_t* insert_rec; rec_t* rec; + ulint* offsets; ulint err; ulint n_unique; big_rec_t* big_rec = NULL; @@ -2132,6 +2135,64 @@ row_ins_index_entry_low( err = row_ins_clust_index_entry_by_modify( mode, &cursor, &heap, &big_rec, entry, thr, &mtr); + + if (big_rec) { + ut_a(err == DB_SUCCESS); + /* Write out the externally stored + columns while still x-latching + index->lock and block->lock. Allocate + pages for big_rec in the mtr that + modified the B-tree, but be sure to skip + any pages that were freed in mtr. We will + write out the big_rec pages before + committing the B-tree mini-transaction. If + the system crashes so that crash recovery + will not replay the mtr_commit(&mtr), the + big_rec pages will be left orphaned until + the pages are allocated for something else. + + TODO: If the allocation extends the + tablespace, it will not be redo + logged, in either mini-transaction. + Tablespace extension should be + redo-logged in the big_rec + mini-transaction, so that recovery + will not fail when the big_rec was + written to the extended portion of the + file, in case the file was somehow + truncated in the crash. */ + + rec = btr_cur_get_rec(&cursor); + offsets = rec_get_offsets( + rec, index, NULL, + ULINT_UNDEFINED, &heap); + + DEBUG_SYNC_C("before_row_ins_upd_extern"); + err = btr_store_big_rec_extern_fields( + index, btr_cur_get_block(&cursor), + rec, offsets, big_rec, &mtr, + BTR_STORE_INSERT_UPDATE); + DEBUG_SYNC_C("after_row_ins_upd_extern"); + /* If writing big_rec fails (for + example, because of DB_OUT_OF_FILE_SPACE), + the record will be corrupted. Even if + we did not update any externally + stored columns, our update could cause + the record to grow so that a + non-updated column was selected for + external storage. This non-update + would not have been written to the + undo log, and thus the record cannot + be rolled back. + + However, because we have not executed + mtr_commit(mtr) yet, the update will + not be replayed in crash recovery, and + the following assertion failure will + effectively "roll back" the operation. */ + ut_a(err == DB_SUCCESS); + goto stored_big_rec; + } } else { ut_ad(!n_ext); err = row_ins_sec_index_entry_by_modify( @@ -2160,10 +2221,13 @@ function_exit: mtr_commit(&mtr); if (UNIV_LIKELY_NULL(big_rec)) { - rec_t* rec; - ulint* offsets; + DBUG_EXECUTE_IF( + "row_ins_extern_checkpoint", + log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE);); + mtr_start(&mtr); + DEBUG_SYNC_C("before_row_ins_extern_latch"); btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, BTR_MODIFY_TREE, &cursor, 0, __FILE__, __LINE__, &mtr); @@ -2171,10 +2235,13 @@ function_exit: offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); + DEBUG_SYNC_C("before_row_ins_extern"); err = btr_store_big_rec_extern_fields( index, btr_cur_get_block(&cursor), - rec, offsets, &mtr, FALSE, big_rec); + rec, offsets, big_rec, &mtr, BTR_STORE_INSERT); + DEBUG_SYNC_C("after_row_ins_extern"); +stored_big_rec: if (modify) { dtuple_big_rec_free(big_rec); } else { diff --git a/storage/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c index d42f21241ca..750f9d72cf2 100644 --- a/storage/innobase/row/row0merge.c +++ b/storage/innobase/row/row0merge.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2012, 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 @@ -582,7 +582,7 @@ row_merge_buf_write( REC_STATUS_ORDINARY, entry, n_fields, &extra_size); - ut_ad(size > extra_size); + ut_ad(size >= extra_size); ut_ad(extra_size >= REC_N_NEW_EXTRA_BYTES); extra_size -= REC_N_NEW_EXTRA_BYTES; size -= REC_N_NEW_EXTRA_BYTES; @@ -1599,22 +1599,29 @@ row_merge( const dict_index_t* index, /*!< in: index being created */ merge_file_t* file, /*!< in/out: file containing index entries */ - ulint* half, /*!< in/out: half the file */ row_merge_block_t* block, /*!< in/out: 3 buffers */ int* tmpfd, /*!< in/out: temporary file handle */ - struct TABLE* table) /*!< in/out: MySQL table, for + struct TABLE* table, /*!< in/out: MySQL table, for reporting erroneous key value if applicable */ + ulint* num_run,/*!< in/out: Number of runs remain + to be merged */ + ulint* run_offset) /*!< in/out: Array contains the + first offset number for each merge + run */ { ulint foffs0; /*!< first input offset */ ulint foffs1; /*!< second input offset */ ulint error; /*!< error code */ merge_file_t of; /*!< output file */ - const ulint ihalf = *half; + const ulint ihalf = run_offset[*num_run / 2]; /*!< half the input file */ - ulint ohalf; /*!< half the output file */ + ulint n_run = 0; + /*!< num of runs generated from this merge */ + UNIV_MEM_ASSERT_W(block[0], 3 * sizeof block[0]); + ut_ad(ihalf < file->offset); of.fd = *tmpfd; @@ -1630,17 +1637,20 @@ row_merge( #endif /* POSIX_FADV_SEQUENTIAL */ /* Merge blocks to the output file. */ - ohalf = 0; foffs0 = 0; foffs1 = ihalf; + UNIV_MEM_INVALID(run_offset, *num_run * sizeof *run_offset); + for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) { - ulint ahalf; /*!< arithmetic half the input file */ if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { return(DB_INTERRUPTED); } + /* Remember the offset number for this run */ + run_offset[n_run++] = of.offset; + error = row_merge_blocks(index, file, block, &foffs0, &foffs1, &of, table); @@ -1648,21 +1658,6 @@ row_merge( return(error); } - /* Record the offset of the output file when - approximately half the output has been generated. In - this way, the next invocation of row_merge() will - spend most of the time in this loop. The initial - estimate is ohalf==0. */ - ahalf = file->offset / 2; - ut_ad(ohalf <= of.offset); - - /* Improve the estimate until reaching half the input - file size, or we can not get any closer to it. All - comparands should be non-negative when !(ohalf < ahalf) - because ohalf <= of.offset. */ - if (ohalf < ahalf || of.offset - ahalf < ohalf - ahalf) { - ohalf = of.offset; - } } /* Copy the last blocks, if there are any. */ @@ -1672,6 +1667,9 @@ row_merge( return(DB_INTERRUPTED); } + /* Remember the offset number for this run */ + run_offset[n_run++] = of.offset; + if (!row_merge_blocks_copy(index, file, block, &foffs0, &of)) { return(DB_CORRUPTION); } @@ -1684,6 +1682,9 @@ row_merge( return(DB_INTERRUPTED); } + /* Remember the offset number for this run */ + run_offset[n_run++] = of.offset; + if (!row_merge_blocks_copy(index, file, block, &foffs1, &of)) { return(DB_CORRUPTION); } @@ -1695,10 +1696,23 @@ row_merge( return(DB_CORRUPTION); } + ut_ad(n_run <= *num_run); + + *num_run = n_run; + + /* Each run can contain one or more offsets. As merge goes on, + the number of runs (to merge) will reduce until we have one + single run. So the number of runs will always be smaller than + the number of offsets in file */ + ut_ad((*num_run) <= file->offset); + + /* The number of offsets in output file is always equal or + smaller than input file */ + ut_ad(of.offset <= file->offset); + /* Swap file descriptors for the next pass. */ *tmpfd = file->fd; *file = of; - *half = ohalf; UNIV_MEM_INVALID(block[0], 3 * sizeof block[0]); @@ -1723,27 +1737,44 @@ row_merge_sort( if applicable */ { ulint half = file->offset / 2; + ulint num_runs; + ulint* run_offset; + ulint error = DB_SUCCESS; + + /* Record the number of merge runs we need to perform */ + num_runs = file->offset; + + /* If num_runs are less than 1, nothing to merge */ + if (num_runs <= 1) { + return(error); + } + + /* "run_offset" records each run's first offset number */ + run_offset = (ulint*) mem_alloc(file->offset * sizeof(ulint)); + + /* This tells row_merge() where to start for the first round + of merge. */ + run_offset[half] = half; /* The file should always contain at least one byte (the end of file marker). Thus, it must be at least one block. */ ut_ad(file->offset > 0); + /* Merge the runs until we have one big run */ do { - ulint error; + error = row_merge(trx, index, file, block, tmpfd, + table, &num_runs, run_offset); - error = row_merge(trx, index, file, &half, - block, tmpfd, table); + UNIV_MEM_ASSERT_RW(run_offset, num_runs * sizeof *run_offset); if (error != DB_SUCCESS) { - return(error); + break; } + } while (num_runs > 1); - /* half > 0 should hold except when the file consists - of one block. No need to merge further then. */ - ut_ad(half > 0 || file->offset == 1); - } while (half < file->offset && half > 0); + mem_free(run_offset); - return(DB_SUCCESS); + return(error); } /*************************************************************//** @@ -2010,7 +2041,7 @@ row_merge_drop_index( tables in Innobase. Deleting a row from SYS_INDEXES table also frees the file segments of the B-tree associated with the index. */ - static const char str1[] = + static const char sql[] = "PROCEDURE DROP_INDEX_PROC () IS\n" "BEGIN\n" /* Rename the index, so that it will be dropped by @@ -2034,9 +2065,19 @@ row_merge_drop_index( ut_a(trx->dict_operation_lock_mode == RW_X_LATCH); - err = que_eval_sql(info, str1, FALSE, trx); + err = que_eval_sql(info, sql, FALSE, trx); + - ut_a(err == DB_SUCCESS); + if (err != DB_SUCCESS) { + /* Even though we ensure that DDL transactions are WAIT + and DEADLOCK free, we could encounter other errors e.g., + DB_TOO_MANY_TRANSACTIONS. */ + trx->error_state = DB_SUCCESS; + + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Error: row_merge_drop_index failed " + "with error code: %lu.\n", (ulint) err); + } /* Replace this index with another equivalent index for all foreign key constraints on this table where this index is used */ @@ -2336,7 +2377,7 @@ row_merge_rename_indexes( /* We use the private SQL parser of Innobase to generate the query graphs needed in renaming indexes. */ - static const char rename_indexes[] = + static const char sql[] = "PROCEDURE RENAME_INDEXES_PROC () IS\n" "BEGIN\n" "UPDATE SYS_INDEXES SET NAME=SUBSTR(NAME,1,LENGTH(NAME)-1)\n" @@ -2352,7 +2393,7 @@ row_merge_rename_indexes( pars_info_add_ull_literal(info, "tableid", table->id); - err = que_eval_sql(info, rename_indexes, FALSE, trx); + err = que_eval_sql(info, sql, FALSE, trx); if (err == DB_SUCCESS) { dict_index_t* index = dict_table_get_first_index(table); @@ -2362,6 +2403,15 @@ row_merge_rename_indexes( } index = dict_table_get_next_index(index); } while (index); + } else { + /* Even though we ensure that DDL transactions are WAIT + and DEADLOCK free, we could encounter other errors e.g., + DB_TOO_MANY_TRANSACTIONS. */ + trx->error_state = DB_SUCCESS; + + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Error: row_merge_rename_indexes " + "failed with error code: %lu.\n", (ulint) err); } trx->op_info = ""; @@ -2399,7 +2449,7 @@ row_merge_rename_tables( memcpy(old_name, old_table->name, strlen(old_table->name) + 1); } else { ut_print_timestamp(stderr); - fprintf(stderr, "InnoDB: too long table name: '%s', " + fprintf(stderr, " InnoDB: too long table name: '%s', " "max length is %d\n", old_table->name, MAX_FULL_NAME_LEN); ut_error; diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 3f81604a1a2..8ea09b5c6ee 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -1783,7 +1783,7 @@ row_mysql_freeze_data_dictionary_func( { ut_a(trx->dict_operation_lock_mode == 0); - rw_lock_s_lock_func(&dict_operation_lock, 0, file, line); + rw_lock_s_lock_inline(&dict_operation_lock, 0, file, line); trx->dict_operation_lock_mode = RW_S_LATCH; } @@ -1820,7 +1820,7 @@ row_mysql_lock_data_dictionary_func( /* Serialize data dictionary operations with dictionary mutex: no deadlocks or lock waits can occur then in these operations */ - rw_lock_x_lock_func(&dict_operation_lock, 0, file, line); + rw_lock_x_lock_inline(&dict_operation_lock, 0, file, line); trx->dict_operation_lock_mode = RW_X_LATCH; mutex_enter(&(dict_sys->mutex)); @@ -1994,7 +1994,8 @@ err_exit: case DB_TOO_MANY_CONCURRENT_TRXS: /* We already have .ibd file here. it should be deleted. */ - if (table->space && !fil_delete_tablespace(table->space)) { + if (table->space && !fil_delete_tablespace(table->space, + FALSE)) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error: not able to" @@ -3075,6 +3076,7 @@ row_drop_table_for_mysql( { dict_foreign_t* foreign; dict_table_t* table; + dict_index_t* index; ulint space_id; ulint err; const char* table_name; @@ -3282,6 +3284,18 @@ check_next_foreign: trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); trx->table_id = table->id; + /* Mark all indexes unavailable in the data dictionary cache + before starting to drop the table. */ + + for (index = dict_table_get_first_index(table); + index != NULL; + index = dict_table_get_next_index(index)) { + rw_lock_x_lock(dict_index_get_lock(index)); + ut_ad(!index->to_be_dropped); + index->to_be_dropped = TRUE; + rw_lock_x_unlock(dict_index_get_lock(index)); + } + /* We use the private SQL parser of Innobase to generate the query graphs needed in deleting the dictionary data from system tables in Innobase. Deleting a row from SYS_INDEXES table also @@ -3420,7 +3434,7 @@ check_next_foreign: "InnoDB: of table "); ut_print_name(stderr, trx, TRUE, name); fprintf(stderr, ".\n"); - } else if (!fil_delete_tablespace(space_id)) { + } else if (!fil_delete_tablespace(space_id, FALSE)) { fprintf(stderr, "InnoDB: We removed now the InnoDB" " internal data dictionary entry\n" @@ -3447,6 +3461,17 @@ check_next_foreign: the undo log. We can directly exit here and return the DB_TOO_MANY_CONCURRENT_TRXS error. */ + + /* Mark all indexes available in the data dictionary + cache again. */ + + for (index = dict_table_get_first_index(table); + index != NULL; + index = dict_table_get_next_index(index)) { + rw_lock_x_lock(dict_index_get_lock(index)); + index->to_be_dropped = FALSE; + rw_lock_x_unlock(dict_index_get_lock(index)); + } break; case DB_OUT_OF_FILE_SPACE: diff --git a/storage/innobase/row/row0row.c b/storage/innobase/row/row0row.c index 20fd475343e..c15e2bbf739 100644 --- a/storage/innobase/row/row0row.c +++ b/storage/innobase/row/row0row.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -241,13 +241,18 @@ row_build( ut_ad(rec_offs_validate(rec, index, offsets)); } -#if 0 && defined UNIV_BLOB_NULL_DEBUG - /* This one can fail in trx_rollback_active() if - the server crashed during an insert before the - btr_store_big_rec_extern_fields() did mtr_commit() - all BLOB pointers to the clustered index record. */ - ut_a(!rec_offs_any_null_extern(rec, offsets)); -#endif /* 0 && UNIV_BLOB_NULL_DEBUG */ +#ifdef UNIV_BLOB_NULL_DEBUG + if (rec_offs_any_null_extern(rec, offsets)) { + /* This condition can occur during crash recovery + before trx_rollback_active() has completed execution, + or when a concurrently executing + row_ins_index_entry_low() has committed the B-tree + mini-transaction but has not yet managed to restore + the cursor position for writing the big_rec. */ + ut_a(trx_undo_roll_ptr_is_insert( + row_get_rec_roll_ptr(rec, index, offsets))); + } +#endif /* UNIV_BLOB_NULL_DEBUG */ if (type != ROW_COPY_POINTERS) { /* Take a copy of rec to heap */ diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index 0d1d3aad1c6..7bec0a26225 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -3998,7 +3998,8 @@ rec_loop: wrong_offs: if (srv_force_recovery == 0 || moves_up == FALSE) { ut_print_timestamp(stderr); - buf_page_print(page_align(rec), 0); + buf_page_print(page_align(rec), 0, + BUF_PAGE_PRINT_NO_CRASH); fprintf(stderr, "\nInnoDB: rec address %p," " buf block fix count %lu\n", @@ -4017,7 +4018,7 @@ wrong_offs: "InnoDB: restore from a backup, or" " dump + drop + reimport the table.\n", stderr); - + ut_ad(0); err = DB_CORRUPTION; goto lock_wait_or_error; @@ -4369,7 +4370,9 @@ no_gap_lock: applicable to unique secondary indexes. Current behaviour is to widen the scope of a lock on an already delete marked record if the same record is deleted twice by the same transaction */ - if (index == clust_index && unique_search) { + if (index == clust_index && unique_search + && !prebuilt->used_in_HANDLER) { + err = DB_RECORD_NOT_FOUND; goto normal_return; diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index c57b829a1ca..4f5096a162b 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -23,6 +23,8 @@ Update of a row Created 12/27/1996 Heikki Tuuri *******************************************************/ +#include "m_string.h" /* for my_sys.h */ +#include "my_sys.h" /* DEBUG_SYNC_C */ #include "row0upd.h" #ifdef UNIV_NONINL @@ -2000,28 +2002,62 @@ row_upd_clust_rec( ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur), dict_table_is_comp(index->table))); - err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG, btr_cur, - &heap, &big_rec, node->update, - node->cmpl_info, thr, mtr); - mtr_commit(mtr); - - if (err == DB_SUCCESS && big_rec) { - ulint offsets_[REC_OFFS_NORMAL_SIZE]; - rec_t* rec; + err = btr_cur_pessimistic_update( + BTR_NO_LOCKING_FLAG | BTR_KEEP_POS_FLAG, btr_cur, + &heap, &big_rec, node->update, node->cmpl_info, thr, mtr); + if (big_rec) { + ulint offsets_[REC_OFFS_NORMAL_SIZE]; + rec_t* rec; rec_offs_init(offsets_); - mtr_start(mtr); + ut_a(err == DB_SUCCESS); + /* Write out the externally stored + columns while still x-latching + index->lock and block->lock. Allocate + pages for big_rec in the mtr that + modified the B-tree, but be sure to skip + any pages that were freed in mtr. We will + write out the big_rec pages before + committing the B-tree mini-transaction. If + the system crashes so that crash recovery + will not replay the mtr_commit(&mtr), the + big_rec pages will be left orphaned until + the pages are allocated for something else. + + TODO: If the allocation extends the tablespace, it + will not be redo logged, in either mini-transaction. + Tablespace extension should be redo-logged in the + big_rec mini-transaction, so that recovery will not + fail when the big_rec was written to the extended + portion of the file, in case the file was somehow + truncated in the crash. */ - ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr)); rec = btr_cur_get_rec(btr_cur); + DEBUG_SYNC_C("before_row_upd_extern"); err = btr_store_big_rec_extern_fields( index, btr_cur_get_block(btr_cur), rec, rec_get_offsets(rec, index, offsets_, ULINT_UNDEFINED, &heap), - mtr, TRUE, big_rec); - mtr_commit(mtr); + big_rec, mtr, BTR_STORE_UPDATE); + DEBUG_SYNC_C("after_row_upd_extern"); + /* If writing big_rec fails (for example, because of + DB_OUT_OF_FILE_SPACE), the record will be corrupted. + Even if we did not update any externally stored + columns, our update could cause the record to grow so + that a non-updated column was selected for external + storage. This non-update would not have been written + to the undo log, and thus the record cannot be rolled + back. + + However, because we have not executed mtr_commit(mtr) + yet, the update will not be replayed in crash + recovery, and the following assertion failure will + effectively "roll back" the operation. */ + ut_a(err == DB_SUCCESS); } + mtr_commit(mtr); + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index 04370e8fe13..57046ff644c 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -2595,21 +2595,23 @@ loop: } /**********************************************************************//** -Check whether any background thread is active. -@return FALSE if all are are suspended or have exited. */ +Check whether any background thread is active. If so return the thread +type +@return ULINT_UNDEFINED if all are suspended or have exited, thread +type if any are still active. */ UNIV_INTERN -ibool -srv_is_any_background_thread_active(void) -/*=====================================*/ +ulint +srv_get_active_thread_type(void) +/*============================*/ { ulint i; - ibool ret = FALSE; + ibool ret = ULINT_UNDEFINED; mutex_enter(&kernel_mutex); for (i = 0; i <= SRV_MASTER; ++i) { if (srv_n_threads_active[i] != 0) { - ret = TRUE; + ret = i; break; } } @@ -2619,6 +2621,57 @@ srv_is_any_background_thread_active(void) return(ret); } +/*********************************************************************//** +This function prints progress message every 60 seconds during server +shutdown, for any activities that master thread is pending on. */ +static +void +srv_shutdown_print_master_pending( +/*==============================*/ + ib_time_t* last_print_time, /*!< last time the function + print the message */ + ulint n_tables_to_drop, /*!< number of tables to + be dropped */ + ulint n_bytes_merged, /*!< number of change buffer + just merged */ + ulint n_pages_flushed) /*!< number of pages flushed */ +{ + ib_time_t current_time; + double time_elapsed; + + current_time = ut_time(); + time_elapsed = ut_difftime(current_time, *last_print_time); + + if (time_elapsed > 60) { + *last_print_time = ut_time(); + + if (n_tables_to_drop) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Waiting for " + "%lu table(s) to be dropped\n", + (ulong) n_tables_to_drop); + } + + /* Check change buffer merge, we only wait for change buffer + merge if it is a slow shutdown */ + if (!srv_fast_shutdown && n_bytes_merged) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Waiting for change " + "buffer merge to complete\n" + " InnoDB: number of bytes of change buffer " + "just merged: %lu\n", + n_bytes_merged); + } + + if (n_pages_flushed) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Waiting for " + "%lu pages to be flushed\n", + (ulong) n_pages_flushed); + } + } +} + /*******************************************************************//** Tells the InnoDB server that there has been activity in the database and wakes up the master thread if it is suspended (not sleeping). Used @@ -2774,6 +2827,7 @@ srv_master_thread( ulint n_pend_ios; ulint next_itr_time; ulint i; + ib_time_t last_print_time; #ifdef UNIV_DEBUG_THREAD_CREATION fprintf(stderr, "Master thread starts, id %lu\n", @@ -2795,6 +2849,7 @@ srv_master_thread( mutex_exit(&kernel_mutex); + last_print_time = ut_time(); loop: /*****************************************************************/ /* ---- When there is database activity by users, we cycle in this @@ -3140,6 +3195,14 @@ flush_loop: */ n_bytes_archived = 0; + /* Print progress message every 60 seconds during shutdown */ + if (srv_shutdown_state > 0 && srv_print_verbose_log) { + srv_shutdown_print_master_pending(&last_print_time, + n_tables_to_drop, + n_bytes_merged, + n_pages_flushed); + } + /* Keep looping in the background loop if still work to do */ if (srv_fast_shutdown && srv_shutdown_state > 0) { @@ -3158,6 +3221,7 @@ flush_loop: } else if (n_tables_to_drop + n_pages_purged + n_bytes_merged + n_pages_flushed + n_bytes_archived != 0) { + /* In a 'slow' shutdown we run purge and the insert buffer merge to completion */ diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c index edc655e93b9..343e41fe376 100644 --- a/storage/innobase/srv/srv0start.c +++ b/storage/innobase/srv/srv0start.c @@ -922,8 +922,9 @@ skip_size_check: #endif /* UNIV_LOG_ARCHIVE */ min_flushed_lsn, max_flushed_lsn); - if (UNIV_PAGE_SIZE - != fsp_flags_get_page_size(flags)) { + if (!one_opened + && UNIV_PAGE_SIZE + != fsp_flags_get_page_size(flags)) { ut_print_timestamp(stderr); fprintf(stderr, diff --git a/storage/innobase/sync/sync0rw.c b/storage/innobase/sync/sync0rw.c index fc4f987fe65..8de9b40ef67 100644 --- a/storage/innobase/sync/sync0rw.c +++ b/storage/innobase/sync/sync0rw.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -18,8 +18,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -785,7 +785,9 @@ rw_lock_add_debug_info( rw_lock_debug_mutex_exit(); if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) { - sync_thread_add_level(lock, lock->level); + sync_thread_add_level(lock, lock->level, + lock_type == RW_LOCK_EX + && lock->lock_word < 0); } } diff --git a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c index 81efe50d9bd..fb7101fdb8d 100644 --- a/storage/innobase/sync/sync0sync.c +++ b/storage/innobase/sync/sync0sync.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2011, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -18,8 +18,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -693,7 +693,7 @@ mutex_set_debug_info( ut_ad(mutex); ut_ad(file_name); - sync_thread_add_level(mutex, mutex->level); + sync_thread_add_level(mutex, mutex->level, FALSE); mutex->file_name = file_name; mutex->line = line; @@ -1136,8 +1136,9 @@ void sync_thread_add_level( /*==================*/ void* latch, /*!< in: pointer to a mutex or an rw-lock */ - ulint level) /*!< in: level in the latching order; if + ulint level, /*!< in: level in the latching order; if SYNC_LEVEL_VARYING, nothing is done */ + ibool relock) /*!< in: TRUE if re-entering an x-lock */ { ulint i; sync_level_t* slot; @@ -1188,6 +1189,10 @@ sync_thread_add_level( array = thread_slot->levels; + if (relock) { + goto levels_ok; + } + /* NOTE that there is a problem with _NODE and _LEAF levels: if the B-tree height changes, then a leaf can change to an internal node or the other way around. We do not know at present if this can cause @@ -1363,6 +1368,7 @@ sync_thread_add_level( ut_error; } +levels_ok: if (array->next_free == ULINT_UNDEFINED) { ut_a(array->n_elems < array->max_elems); diff --git a/storage/innobase/trx/trx0purge.c b/storage/innobase/trx/trx0purge.c index 2370d3deab0..96f01ea81b5 100644 --- a/storage/innobase/trx/trx0purge.c +++ b/storage/innobase/trx/trx0purge.c @@ -1202,7 +1202,7 @@ trx_purge( (ulong) purge_sys->n_pages_handled); } - return(purge_sys->n_pages_handled - old_pages_handled); + return((ulint) (purge_sys->n_pages_handled - old_pages_handled)); } /******************************************************************//** diff --git a/storage/innobase/trx/trx0rec.c b/storage/innobase/trx/trx0rec.c index 786c7be36a4..2f1389ae263 100644 --- a/storage/innobase/trx/trx0rec.c +++ b/storage/innobase/trx/trx0rec.c @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -1198,6 +1198,7 @@ trx_undo_report_row_operation( trx_t* trx; trx_undo_t* undo; ulint page_no; + buf_block_t* undo_block; trx_rseg_t* rseg; mtr_t mtr; ulint err = DB_SUCCESS; @@ -1240,10 +1241,13 @@ trx_undo_report_row_operation( if (UNIV_UNLIKELY(!undo)) { /* Did not succeed */ + ut_ad(err != DB_SUCCESS); mutex_exit(&(trx->undo_mutex)); return(err); } + + ut_ad(err == DB_SUCCESS); } else { ut_ad(op_type == TRX_UNDO_MODIFY_OP); @@ -1257,30 +1261,30 @@ trx_undo_report_row_operation( if (UNIV_UNLIKELY(!undo)) { /* Did not succeed */ + ut_ad(err != DB_SUCCESS); mutex_exit(&(trx->undo_mutex)); return(err); } + ut_ad(err == DB_SUCCESS); offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); } - page_no = undo->last_page_no; - mtr_start(&mtr); + page_no = undo->last_page_no; + undo_block = buf_page_get_gen( + undo->space, undo->zip_size, page_no, RW_X_LATCH, + undo->guess_block, BUF_GET, __FILE__, __LINE__, &mtr); + buf_block_dbg_add_level(undo_block, SYNC_TRX_UNDO_PAGE); + do { - buf_block_t* undo_block; page_t* undo_page; ulint offset; - undo_block = buf_page_get_gen(undo->space, undo->zip_size, - page_no, RW_X_LATCH, - undo->guess_block, BUF_GET, - __FILE__, __LINE__, &mtr); - buf_block_dbg_add_level(undo_block, SYNC_TRX_UNDO_PAGE); - undo_page = buf_block_get_frame(undo_block); + ut_ad(page_no == buf_block_get_page_no(undo_block)); if (op_type == TRX_UNDO_INSERT_OP) { offset = trx_undo_page_report_insert( @@ -1357,12 +1361,11 @@ trx_undo_report_row_operation( a pessimistic insert in a B-tree, and we must reserve the counterpart of the tree latch, which is the rseg mutex. */ - mutex_enter(&(rseg->mutex)); - - page_no = trx_undo_add_page(trx, undo, &mtr); - - mutex_exit(&(rseg->mutex)); - } while (UNIV_LIKELY(page_no != FIL_NULL)); + mutex_enter(&rseg->mutex); + undo_block = trx_undo_add_page(trx, undo, &mtr); + mutex_exit(&rseg->mutex); + page_no = undo->last_page_no; + } while (undo_block != NULL); /* Did not succeed: out of space */ err = DB_OUT_OF_FILE_SPACE; diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c index 5d8c967e323..35230eb4715 100644 --- a/storage/innobase/trx/trx0sys.c +++ b/storage/innobase/trx/trx0sys.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -259,9 +259,7 @@ trx_sys_create_doublewrite_buf(void) { buf_block_t* block; buf_block_t* block2; -#ifdef UNIV_SYNC_DEBUG buf_block_t* new_block; -#endif /* UNIV_SYNC_DEBUG */ byte* doublewrite; byte* fseg_header; ulint page_no; @@ -340,10 +338,9 @@ start_again: for (i = 0; i < 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE + FSP_EXTENT_SIZE / 2; i++) { - page_no = fseg_alloc_free_page(fseg_header, - prev_page_no + 1, - FSP_UP, &mtr); - if (page_no == FIL_NULL) { + new_block = fseg_alloc_free_page( + fseg_header, prev_page_no + 1, FSP_UP, &mtr); + if (new_block == NULL) { fprintf(stderr, "InnoDB: Cannot create doublewrite" " buffer: you must\n" @@ -364,13 +361,8 @@ start_again: the page position in the tablespace, then the page has not been written to in doublewrite. */ -#ifdef UNIV_SYNC_DEBUG - new_block = -#endif /* UNIV_SYNC_DEBUG */ - buf_page_get(TRX_SYS_SPACE, 0, page_no, - RW_X_LATCH, &mtr); - buf_block_dbg_add_level(new_block, - SYNC_NO_ORDER_CHECK); + ut_ad(rw_lock_get_x_lock_count(&new_block->lock) == 1); + page_no = buf_block_get_page_no(new_block); if (i == FSP_EXTENT_SIZE / 2) { ut_a(page_no == FSP_EXTENT_SIZE); @@ -590,12 +582,16 @@ trx_sys_doublewrite_init_or_restore_pages( if (buf_page_is_corrupted(page, zip_size)) { fprintf(stderr, "InnoDB: Dump of the page:\n"); - buf_page_print(read_buf, zip_size); + buf_page_print( + read_buf, zip_size, + BUF_PAGE_PRINT_NO_CRASH); fprintf(stderr, "InnoDB: Dump of" " corresponding page" " in doublewrite buffer:\n"); - buf_page_print(page, zip_size); + buf_page_print( + page, zip_size, + BUF_PAGE_PRINT_NO_CRASH); fprintf(stderr, "InnoDB: Also the page in the" @@ -609,7 +605,7 @@ trx_sys_doublewrite_init_or_restore_pages( "InnoDB: option:\n" "InnoDB:" " innodb_force_recovery=6\n"); - exit(1); + ut_error; } /* Write the good page from the diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c index 82f54b8295a..23cac1e11db 100644 --- a/storage/innobase/trx/trx0trx.c +++ b/storage/innobase/trx/trx0trx.c @@ -1084,6 +1084,8 @@ trx_commit_off_kernel( } #endif UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx); + + trx->error_state = DB_SUCCESS; } /****************************************************************//** diff --git a/storage/innobase/trx/trx0undo.c b/storage/innobase/trx/trx0undo.c index dae0637f72c..3d794c69c8b 100644 --- a/storage/innobase/trx/trx0undo.c +++ b/storage/innobase/trx/trx0undo.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2012, 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 @@ -11,8 +11,8 @@ 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 +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -876,9 +876,9 @@ trx_undo_discard_latest_update_undo( #ifndef UNIV_HOTBACKUP /********************************************************************//** Tries to add a page to the undo log segment where the undo log is placed. -@return page number if success, else FIL_NULL */ +@return X-latched block if success, else NULL */ UNIV_INTERN -ulint +buf_block_t* trx_undo_add_page( /*==============*/ trx_t* trx, /*!< in: transaction */ @@ -888,11 +888,10 @@ trx_undo_add_page( the rollback segment mutex */ { page_t* header_page; + buf_block_t* new_block; page_t* new_page; trx_rseg_t* rseg; - ulint page_no; ulint n_reserved; - ibool success; ut_ad(mutex_own(&(trx->undo_mutex))); ut_ad(!mutex_own(&kernel_mutex)); @@ -902,37 +901,37 @@ trx_undo_add_page( if (rseg->curr_size == rseg->max_size) { - return(FIL_NULL); + return(NULL); } header_page = trx_undo_page_get(undo->space, undo->zip_size, undo->hdr_page_no, mtr); - success = fsp_reserve_free_extents(&n_reserved, undo->space, 1, - FSP_UNDO, mtr); - if (!success) { + if (!fsp_reserve_free_extents(&n_reserved, undo->space, 1, + FSP_UNDO, mtr)) { - return(FIL_NULL); + return(NULL); } - page_no = fseg_alloc_free_page_general(header_page + TRX_UNDO_SEG_HDR - + TRX_UNDO_FSEG_HEADER, - undo->top_page_no + 1, FSP_UP, - TRUE, mtr); + new_block = fseg_alloc_free_page_general( + TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + + header_page, + undo->top_page_no + 1, FSP_UP, TRUE, mtr, mtr); fil_space_release_free_extents(undo->space, n_reserved); - if (page_no == FIL_NULL) { + if (new_block == NULL) { /* No space left */ - return(FIL_NULL); + return(NULL); } - undo->last_page_no = page_no; + ut_ad(rw_lock_get_x_lock_count(&new_block->lock) == 1); + buf_block_dbg_add_level(new_block, SYNC_TRX_UNDO_PAGE); + undo->last_page_no = buf_block_get_page_no(new_block); - new_page = trx_undo_page_get(undo->space, undo->zip_size, - page_no, mtr); + new_page = buf_block_get_frame(new_block); trx_undo_page_init(new_page, undo->type, mtr); @@ -941,7 +940,7 @@ trx_undo_add_page( undo->size++; rseg->curr_size++; - return(page_no); + return(new_block); } /********************************************************************//** diff --git a/storage/maria/CMakeLists.txt b/storage/maria/CMakeLists.txt index 7f6e35b0a31..bd6c200be90 100644 --- a/storage/maria/CMakeLists.txt +++ b/storage/maria/CMakeLists.txt @@ -41,6 +41,11 @@ SET(ARIA_SOURCES ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c ma_norec.c ) +IF(APPLE) + # Workaround linker bug on OSX 10.7 + ADD_DEFINITIONS(-fno-common) +ENDIF() + MYSQL_ADD_PLUGIN(aria ${ARIA_SOURCES} STORAGE_ENGINE STATIC_ONLY DEFAULT RECOMPILE_FOR_EMBEDDED) diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 7205a1042ef..ae7e686d2f0 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -58,6 +58,9 @@ C_MODE_END ulong pagecache_division_limit, pagecache_age_threshold; ulonglong pagecache_buffer_size; +const char *zerofill_error_msg= + "Table is from another system and must be zerofilled or repaired to be " + "usable on this system"; /** As the auto-repair is initiated when opened from the SQL layer @@ -1152,7 +1155,15 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked) } if (!(file= maria_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER))) + { + if (my_errno == HA_ERR_OLD_FILE) + { + push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_CRASHED_ON_USAGE, + zerofill_error_msg); + } return (my_errno ? my_errno : -1); + } file->s->chst_invalidator= query_cache_invalidate_by_MyISAM_filename_ref; /* Set external_ref, mainly for temporary tables */ @@ -1266,6 +1277,14 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt) return HA_ADMIN_ALREADY_DONE; maria_chk_init_for_check(¶m, file); + + if ((file->s->state.changed & (STATE_CRASHED_FLAGS | STATE_MOVED)) == + STATE_MOVED) + { + _ma_check_print_error(¶m, "%s", zerofill_error_msg); + return HA_ADMIN_CORRUPT; + } + old_proc_info= thd_proc_info(thd, "Checking status"); thd_progress_init(thd, 3); (void) maria_chk_status(¶m, file); // Not fatal @@ -1633,7 +1652,7 @@ int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize) { DBUG_PRINT("info", ("Reseting crashed state")); share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS | - STATE_IN_REPAIR); + STATE_IN_REPAIR | STATE_MOVED); file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; } /* @@ -2135,6 +2154,11 @@ bool ha_maria::check_and_repair(THD *thd) if ((file->s->state.changed & (STATE_CRASHED_FLAGS | STATE_MOVED)) == STATE_MOVED) { + /* Remove error about crashed table */ + thd->warning_info->clear_warning_info(thd->query_id); + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_CRASHED_ON_USAGE, + "Zerofilling moved table %s", table->s->path.str); sql_print_information("Zerofilling moved table: '%s'", table->s->path.str); if (!(error= zerofill(thd, &check_opt))) @@ -2463,18 +2487,26 @@ int ha_maria::extra(enum ha_extra_function operation) without calling commit/rollback in between. If file->trn is not set we can't remove file->share from the transaction list in the extra() call. + We also ensure that we set file->trn to 0 if THD_TRN is 0 as in + this case we have already freed the trn. This can happen when one + implicit_commit() is called as part of alter table. + table->in_use is not set in the case this is a done as part of closefrm() as part of drop table. */ - if (file->s->now_transactional && !file->trn && table->in_use && + if (file->s->now_transactional && table->in_use && (operation == HA_EXTRA_PREPARE_FOR_DROP || - operation == HA_EXTRA_PREPARE_FOR_RENAME)) + operation == HA_EXTRA_PREPARE_FOR_RENAME || + operation == HA_EXTRA_PREPARE_FOR_FORCED_CLOSE)) { THD *thd= table->in_use; TRN *trn= THD_TRN; _ma_set_trn_for_table(file, trn); } + DBUG_ASSERT(file->s->base.born_transactional || file->trn == 0 || + file->trn == &dummy_transaction_object); + tmp= maria_extra(file, operation, 0); file->trn= old_trn; // Reset trn if was used return tmp; @@ -2767,6 +2799,11 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn) error= 1; if (!new_trn) { + /* + To be extra safe, we should also reset file->trn for all open + tables as some calls, like extra() may access it. We take care + of this in extra() by resetting file->trn if THD_TRN is 0. + */ THD_TRN= NULL; goto end; } diff --git a/storage/maria/ha_maria.h b/storage/maria/ha_maria.h index 6232333a160..35c98cc52d7 100644 --- a/storage/maria/ha_maria.h +++ b/storage/maria/ha_maria.h @@ -152,8 +152,14 @@ public: bool check_and_repair(THD * thd); bool is_crashed() const; bool is_changed() const; - bool auto_repair() const - { return test(maria_recover_options & HA_RECOVER_ANY); } + bool auto_repair(int error) const + { + /* Always auto-repair moved tables (error == HA_ERR_OLD_FILE) */ + return ((test(maria_recover_options & HA_RECOVER_ANY) && + error == HA_ERR_CRASHED_ON_USAGE) || + error == HA_ERR_OLD_FILE); + + } int optimize(THD * thd, HA_CHECK_OPT * check_opt); int restore(THD * thd, HA_CHECK_OPT * check_opt); int backup(THD * thd, HA_CHECK_OPT * check_opt); diff --git a/storage/maria/ma_close.c b/storage/maria/ma_close.c index a29fe607d6e..973adf2b91e 100644 --- a/storage/maria/ma_close.c +++ b/storage/maria/ma_close.c @@ -36,6 +36,21 @@ int maria_close(register MARIA_HA *info) /* Check that we have unlocked key delete-links properly */ DBUG_ASSERT(info->key_del_used == 0); + if (share->reopen == 1) + { + /* + If we are going to close the file, flush page cache without + a global mutex + */ + if (flush_pagecache_blocks(share->pagecache, &share->kfile, + ((share->temporary || share->deleting) ? + FLUSH_IGNORE_CHANGED : + FLUSH_RELEASE))) + error= my_errno; + } + + + /* Ensure no one can open this file while we are closing it */ mysql_mutex_lock(&THR_LOCK_maria); if (info->lock_type == F_EXTRA_LCK) info->lock_type=F_UNLCK; /* HA_EXTRA_NO_USER_CHANGE */ @@ -81,6 +96,10 @@ int maria_close(register MARIA_HA *info) if ((*share->once_end)(share)) error= my_errno; + /* + Extra flush, just in case someone opened and closed the file + since the start of the function (very unlikely) + */ if (flush_pagecache_blocks(share->pagecache, &share->kfile, ((share->temporary || share->deleting) ? FLUSH_IGNORE_CHANGED : diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 2173d2cac8f..28c3491730f 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -1340,11 +1340,12 @@ int _ma_update_state_lsns(MARIA_SHARE *share, LSN lsn, TrID create_trid, my_bool do_sync, my_bool update_create_rename_lsn) { int res; + DBUG_ENTER("_ma_update_state_lsns"); mysql_mutex_lock(&share->intern_lock); res= _ma_update_state_lsns_sub(share, lsn, create_trid, do_sync, update_create_rename_lsn); mysql_mutex_unlock(&share->intern_lock); - return res; + DBUG_RETURN(res); } diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c index c8b969363fa..0847f3c729c 100644 --- a/storage/maria/ma_extra.c +++ b/storage/maria/ma_extra.c @@ -348,6 +348,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, /* Ensure we don't point to the deleted data in trn */ info->state= info->state_start= &share->state.state; } + /* Remove history for table */ + _ma_reset_state(info); type= do_flush ? FLUSH_RELEASE : FLUSH_IGNORE_CHANGED; save_global_changed= share->global_changed; diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 64717f7d89d..a526c0d4276 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -860,7 +860,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) { /* Move history from hash to share. This is safe to do as we - don't have a lock on share->intern_lock. + know we are the only one that is using the share. */ share->state_history= _ma_remove_not_visible_states(history->state_history, 0, 0); @@ -1002,8 +1002,6 @@ err: tmp_name.length= strlen(name); _ma_report_error(save_errno, &tmp_name); } - if (save_errno == HA_ERR_OLD_FILE) /* uuid is different ? */ - save_errno= HA_ERR_CRASHED_ON_USAGE; /* the code to trigger auto-repair */ switch (errpos) { case 5: if (data_file >= 0) @@ -1352,6 +1350,7 @@ uint _ma_state_info_write_sub(File file, MARIA_STATE_INFO *state, uint pWrite) uint i, keys= (uint) state->header.keys; size_t res; DBUG_ENTER("_ma_state_info_write_sub"); + DBUG_PRINT("info", ("Records: %lld", state->state.records)); memcpy(ptr,&state->header,sizeof(state->header)); ptr+=sizeof(state->header); @@ -1423,6 +1422,8 @@ uint _ma_state_info_write_sub(File file, MARIA_STATE_INFO *state, uint pWrite) static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state) { uint i,keys,key_parts; + DBUG_ENTER("_ma_state_info_read"); + memcpy(&state->header,ptr, sizeof(state->header)); ptr+= sizeof(state->header); keys= (uint) state->header.keys; @@ -1471,7 +1472,9 @@ static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state) float8get(state->rec_per_key_part[i], ptr); ptr+= 8; state->nulls_per_key_part[i]= mi_uint4korr(ptr); ptr+= 4; } - return ptr; + + DBUG_PRINT("info", ("Records: %lld", state->state.records)); + DBUG_RETURN(ptr); } diff --git a/storage/maria/ma_rename.c b/storage/maria/ma_rename.c index 7db397617d4..2f798a95dc5 100644 --- a/storage/maria/ma_rename.c +++ b/storage/maria/ma_rename.c @@ -103,6 +103,7 @@ int maria_rename(const char *old_name, const char *new_name) } } + _ma_reset_state(info); maria_close(info); fn_format(from,old_name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT); diff --git a/storage/maria/ma_state.c b/storage/maria/ma_state.c index ca698bc7245..1f4a7504c56 100644 --- a/storage/maria/ma_state.c +++ b/storage/maria/ma_state.c @@ -229,13 +229,14 @@ void _ma_remove_not_visible_states_with_lock(MARIA_SHARE *share, to current state. @notes - Used after repair as then all rows are visible for everyone + Used after repair/rename/drop as then all rows are visible for everyone */ void _ma_reset_state(MARIA_HA *info) { MARIA_SHARE *share= info->s; MARIA_STATE_HISTORY *history= share->state_history; + DBUG_ENTER("_ma_reset_state"); if (history) { @@ -253,6 +254,7 @@ void _ma_reset_state(MARIA_HA *info) share->state_history->next= 0; share->state_history->trid= 0; /* Visibile for all */ } + DBUG_VOID_RETURN; } @@ -433,6 +435,7 @@ my_bool _ma_trnman_end_trans_hook(TRN *trn, my_bool commit, my_bool error= 0; MARIA_USED_TABLES *tables, *next; DBUG_ENTER("_ma_trnman_end_trans_hook"); + DBUG_PRINT("enter", ("trn: %p used_tables: %p", trn, trn->used_tables)); for (tables= (MARIA_USED_TABLES*) trn->used_tables; tables; @@ -547,8 +550,8 @@ void _ma_remove_table_from_trnman(MARIA_SHARE *share, TRN *trn) { MARIA_USED_TABLES *tables, **prev; DBUG_ENTER("_ma_remove_table_from_trnman"); - DBUG_PRINT("enter", ("share: 0x%lx in_trans: %d", - (ulong) share, share->in_trans)); + DBUG_PRINT("enter", ("trn: %p used_tables: %p share: %p in_trans: %d", + trn, trn->used_tables, share, share->in_trans)); mysql_mutex_assert_owner(&share->intern_lock); @@ -560,7 +563,6 @@ void _ma_remove_table_from_trnman(MARIA_SHARE *share, TRN *trn) { *prev= tables->next; share->in_trans--; - DBUG_PRINT("info", ("in_trans: %d", share->in_trans)); my_free(tables); break; } @@ -730,6 +732,10 @@ void _ma_copy_nontrans_state_information(MARIA_HA *info) info->s->state.state.checksum= info->state->checksum; } +/** + Reset history + This is only called during repair when we the only one using the table. +*/ void _ma_reset_history(MARIA_SHARE *share) { diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 25c09e8de33..a2a19924a73 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -749,7 +749,7 @@ struct st_maria_handler @note cast of newtrn is because %p of NULL gives warning (NULL is int) */ #define _ma_set_trn_for_table(tbl, newtrn) do { \ - DBUG_PRINT("info",("table: %p trn: %p -> %p", \ + DBUG_PRINT("info",("table: %p trn: %p -> %p", \ (tbl), (tbl)->trn, (void *)(newtrn))); \ (tbl)->trn= (newtrn); \ } while (0) diff --git a/storage/maria/trnman.c b/storage/maria/trnman.c index 0734e12cbe4..2e27d8a4dc5 100644 --- a/storage/maria/trnman.c +++ b/storage/maria/trnman.c @@ -413,7 +413,7 @@ my_bool trnman_end_trn(TRN *trn, my_bool commit) TRN *free_me= 0; LF_PINS *pins= trn->pins; DBUG_ENTER("trnman_end_trn"); - DBUG_PRINT("enter", ("trn=0x%lx commit=%d", (ulong) trn, commit)); + DBUG_PRINT("enter", ("trn: %p commit: %d", trn, commit)); /* if a rollback, all UNDO records should have been executed */ DBUG_ASSERT(commit || trn->undo_lsn == 0); diff --git a/storage/maria/unittest/ma_control_file-t.c b/storage/maria/unittest/ma_control_file-t.c index 8533e461361..b4e757788c2 100644 --- a/storage/maria/unittest/ma_control_file-t.c +++ b/storage/maria/unittest/ma_control_file-t.c @@ -23,7 +23,9 @@ #include <my_global.h> #include <my_sys.h> #include <tap.h> - +#ifdef _WIN32 +#include <direct.h> /* rmdir */ +#endif #ifndef WITH_ARIA_STORAGE_ENGINE /* If Aria is not compiled in, normally we don't come to building this test. diff --git a/storage/maria/unittest/ma_test_loghandler_multithread-t.c b/storage/maria/unittest/ma_test_loghandler_multithread-t.c index 5933059263a..18fbaeace5a 100644 --- a/storage/maria/unittest/ma_test_loghandler_multithread-t.c +++ b/storage/maria/unittest/ma_test_loghandler_multithread-t.c @@ -289,7 +289,7 @@ int main(int argc __attribute__((unused)), fprintf(stderr, "End of memory\n"); exit(1); } - for (i= 0; i < (LONG_BUFFER_SIZE + 7 * 2 + 2); i++) + for (i= 0; i < (uint32)(LONG_BUFFER_SIZE + 7 * 2 + 2); i++) long_buffer[i]= (i & 0xFF); #ifndef DBUG_OFF diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index 56d0149a748..f419ac3d689 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2001, 2011, 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 diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index 6b36891ccf6..e31075e55d1 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -1,5 +1,4 @@ -/* - Copyright (c) 2001, 2010, Oracle and/or its affiliates +/* Copyright (c) 2001, 2011, 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 diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 87fccb6f449..3f99dfc2186 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates + Copyright (c) 2000, 2012, 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 @@ -74,10 +74,10 @@ static MYSQL_THDVAR_ULONG(repair_threads, PLUGIN_VAR_RQCMDARG, "disables parallel repair", NULL, NULL, 1, 1, ULONG_MAX, 1); -static MYSQL_THDVAR_ULONG(sort_buffer_size, PLUGIN_VAR_RQCMDARG, +static MYSQL_THDVAR_ULONGLONG(sort_buffer_size, PLUGIN_VAR_RQCMDARG, "The buffer that is allocated when sorting the index when doing " "a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE", NULL, NULL, - 8192*1024, (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), ULONG_MAX, 1); + 8192 * 1024, (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), SIZE_T_MAX, 1); static MYSQL_SYSVAR_BOOL(use_mmap, opt_myisam_use_mmap, PLUGIN_VAR_NOCMDARG, "Use memory mapping for reading and writing MyISAM tables", NULL, NULL, FALSE); diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h index 7439ea290c6..579ef061af4 100644 --- a/storage/myisam/ha_myisam.h +++ b/storage/myisam/ha_myisam.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates + Copyright (c) 2000, 2012, 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 @@ -36,7 +36,6 @@ typedef struct st_ha_create_information HA_CREATE_INFO; #define HA_RECOVER_FULL_BACKUP 16 /* Make a copy of index file too */ #define HA_RECOVER_OFF 32 /* No automatic recover */ -extern ulong myisam_sort_buffer_size; extern TYPELIB myisam_recover_typelib; extern const char *myisam_recover_names[]; extern ulonglong myisam_recover_options; @@ -141,7 +140,11 @@ class ha_myisam: public handler int repair(THD* thd, HA_CHECK_OPT* check_opt); bool check_and_repair(THD *thd); bool is_crashed() const; - bool auto_repair() const { return myisam_recover_options != HA_RECOVER_OFF; } + bool auto_repair(int error) const + { + return (myisam_recover_options != HA_RECOVER_OFF && + error == HA_ERR_CRASHED_ON_USAGE); + } int optimize(THD* thd, HA_CHECK_OPT* check_opt); int assign_to_keycache(THD* thd, HA_CHECK_OPT* check_opt); int preload_keys(THD* thd, HA_CHECK_OPT* check_opt); diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 04d2263ab5b..7e97a751376 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates + Copyright (c) 2000, 2012, 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 @@ -2406,7 +2406,7 @@ int mi_repair_by_sort(HA_CHECK *param, register MI_INFO *info, if (_create_index_by_sort(&sort_param, (my_bool) (!(param->testflag & T_VERBOSE)), - (uint) param->sort_buffer_length)) + param->sort_buffer_length)) { param->retry_repair= 1; if (! param->error_printed) @@ -4312,14 +4312,6 @@ int recreate_table(HA_CHECK *param, MI_INFO **org_info, char *filename) u_ptr->seg=keyseg; keyseg+=u_ptr->keysegs+1; } - if (share.options & HA_OPTION_COMPRESS_RECORD) - share.base.records=max_records=info.state->records; - else if (share.base.min_pack_length) - max_records=(ha_rows) (mysql_file_seek(info.dfile, 0L, MY_SEEK_END, - MYF(0)) / - (ulong) share.base.min_pack_length); - else - max_records=0; unpack= (share.options & HA_OPTION_COMPRESS_RECORD) && (param->testflag & T_UNPACK); share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD; @@ -4329,10 +4321,17 @@ int recreate_table(HA_CHECK *param, MI_INFO **org_info, char *filename) set_if_bigger(file_length,param->max_data_file_length); set_if_bigger(file_length,tmp_length); set_if_bigger(file_length,(ulonglong) share.base.max_data_file_length); + + if (share.options & HA_OPTION_COMPRESS_RECORD) + share.base.records= max_records= info.state->records; + else if (!(share.options & HA_OPTION_PACK_RECORD)) + max_records= (ha_rows) (file_length / share.base.pack_reclength); + else + max_records= 0; (void) mi_close(*org_info); bzero((char*) &create_info,sizeof(create_info)); - create_info.max_rows=max(max_records,share.base.records); + create_info.max_rows= max_records; create_info.reloc_rows=share.base.reloc; create_info.old_options=(share.options | (unpack ? HA_OPTION_TEMP_COMPRESS_RECORD : 0)); diff --git a/storage/myisam/mi_packrec.c b/storage/myisam/mi_packrec.c index c154ec3b817..7e2403b64c9 100644 --- a/storage/myisam/mi_packrec.c +++ b/storage/myisam/mi_packrec.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2011, 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 diff --git a/storage/myisam/mi_preload.c b/storage/myisam/mi_preload.c index 767858a6ea0..1a2d5aac94f 100644 --- a/storage/myisam/mi_preload.c +++ b/storage/myisam/mi_preload.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2003, 2011, 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 diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c index 32d39e5a09d..fa8cc679997 100644 --- a/storage/myisam/myisamchk.c +++ b/storage/myisam/myisamchk.c @@ -1,5 +1,4 @@ -/* - Copyright (c) 2000, 2011, Oracle and/or its affiliates +/* Copyright (c) 2000, 2012, 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 @@ -297,9 +296,9 @@ static struct my_option my_long_options[] = INT_MAX32, (long) MALLOC_OVERHEAD, (long) 1L, 0}, { "sort_buffer_size", OPT_SORT_BUFFER_SIZE, "", &check_param.sort_buffer_length, - &check_param.sort_buffer_length, 0, GET_ULONG, REQUIRED_ARG, + &check_param.sort_buffer_length, 0, GET_ULL, REQUIRED_ARG, (long) SORT_BUFFER_INIT, (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), - ULONG_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0}, + SIZE_T_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0}, { "sort_key_blocks", OPT_SORT_KEY_BLOCKS, "", &check_param.sort_key_blocks, &check_param.sort_key_blocks, 0, GET_ULONG, REQUIRED_ARG, diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index a72b329a4c0..e3c1647cd59 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2011, Oracle and/or its affiliates + Copyright (c) 2000, 2012, 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 diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index 6da2c5c7816..2c4639b3143 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -1,5 +1,4 @@ -/* - Copyright (c) 2000, 2011, Oracle and/or its affiliates +/* Copyright (c) 2000, 2012, 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 @@ -100,10 +99,11 @@ my_var_write(MI_SORT_PARAM *info, IO_CACHE *to_file, uchar *bufs); */ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, - ulong sortbuff_size) + ulonglong sortbuff_size) { int error,maxbuffer,skr; - uint memavl,old_memavl,keys,sort_length; + uint sort_length, keys; + ulonglong memavl, old_memavl; DYNAMIC_ARRAY buffpek; ha_rows records; uchar **sort_keys; @@ -135,6 +135,9 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, sort_length= info->key_length; LINT_INIT(keys); + if ((memavl - sizeof(BUFFPEK)) / (sort_length + sizeof(char *)) > UINT_MAX32) + memavl= sizeof(BUFFPEK) + UINT_MAX32 * (sort_length + sizeof(char *)); + while (memavl >= MIN_SORT_BUFFER) { if ((records < UINT_MAX32) && @@ -311,7 +314,8 @@ pthread_handler_t thr_find_all_keys(void *arg) { MI_SORT_PARAM *sort_param= (MI_SORT_PARAM*) arg; int error; - uint memavl,old_memavl,keys,sort_length; + ulonglong memavl, old_memavl; + uint keys, sort_length; uint idx, maxbuffer; uchar **sort_keys=0; @@ -352,6 +356,10 @@ pthread_handler_t thr_find_all_keys(void *arg) sort_length= sort_param->key_length; maxbuffer= 1; + if ((memavl - sizeof(BUFFPEK)) / (sort_length + + sizeof(char *)) > UINT_MAX32) + memavl= sizeof(BUFFPEK) + UINT_MAX32 * (sort_length + sizeof(char *)); + while (memavl >= MIN_SORT_BUFFER) { if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc index d7771de7fb8..0fb86cfe5cd 100644 --- a/storage/perfschema/ha_perfschema.cc +++ b/storage/perfschema/ha_perfschema.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2011, 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 diff --git a/storage/perfschema/pfs.cc b/storage/perfschema/pfs.cc index 27350c59604..9a6ada2f814 100644 --- a/storage/perfschema/pfs.cc +++ b/storage/perfschema/pfs.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2011, 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 diff --git a/storage/perfschema/pfs_instr.cc b/storage/perfschema/pfs_instr.cc index f46a2862b6f..8da1a9862e1 100644 --- a/storage/perfschema/pfs_instr.cc +++ b/storage/perfschema/pfs_instr.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2012, 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 @@ -839,6 +839,22 @@ void destroy_thread(PFS_thread *pfs) } /** + Get the hash pins for @filename_hash. + @param thread The running thread. + @returns The LF_HASH pins for the thread. +*/ +LF_PINS* get_filename_hash_pins(PFS_thread *thread) +{ + if (unlikely(thread->m_filename_hash_pins == NULL)) + { + if (! filename_hash_inited) + return NULL; + thread->m_filename_hash_pins= lf_hash_get_pins(&filename_hash); + } + return thread->m_filename_hash_pins; +} + +/** Find or create instrumentation for a file instance by file name. @param thread the executing instrumented thread @param klass the file class @@ -854,23 +870,13 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, PFS_scan scan; DBUG_ENTER("find_or_create_file"); - if (! filename_hash_inited) + LF_PINS *pins= get_filename_hash_pins(thread); + if (unlikely(pins == NULL)) { - /* File instrumentation can be turned off. */ file_lost++; DBUG_RETURN(NULL); } - if (unlikely(thread->m_filename_hash_pins == NULL)) - { - thread->m_filename_hash_pins= lf_hash_get_pins(&filename_hash); - if (unlikely(thread->m_filename_hash_pins == NULL)) - { - file_lost++; - DBUG_RETURN(NULL); - } - } - char safe_buffer[FN_REFLEN]; const char *safe_filename; @@ -942,7 +948,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, /* Append the unresolved file name to the resolved path */ char *ptr= buffer + strlen(buffer); char *buf_end= &buffer[sizeof(buffer)-1]; - if (buf_end > ptr) + if ((buf_end > ptr) && (*(ptr-1) != FN_LIBCHAR)) *ptr++= FN_LIBCHAR; if (buf_end > ptr) strncpy(ptr, safe_filename + dirlen, buf_end - ptr); @@ -956,16 +962,18 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, const uint retry_max= 3; search: entry= reinterpret_cast<PFS_file**> - (lf_hash_search(&filename_hash, thread->m_filename_hash_pins, + (lf_hash_search(&filename_hash, pins, normalized_filename, normalized_length)); if (entry && (entry != MY_ERRPTR)) { pfs= *entry; pfs->m_file_stat.m_open_count++; - lf_hash_search_unpin(thread->m_filename_hash_pins); + lf_hash_search_unpin(pins); DBUG_RETURN(pfs); } + lf_hash_search_unpin(pins); + /* filename is not constant, just using it for noise on create */ uint random= randomized_index(filename, file_max); @@ -992,7 +1000,7 @@ search: reset_single_stat_link(&pfs->m_wait_stat); int res; - res= lf_hash_insert(&filename_hash, thread->m_filename_hash_pins, + res= lf_hash_insert(&filename_hash, pins, &pfs); if (likely(res == 0)) { @@ -1049,9 +1057,12 @@ void destroy_file(PFS_thread *thread, PFS_file *pfs) DBUG_ENTER("destroy_file"); DBUG_ASSERT(thread != NULL); - DBUG_ASSERT(thread->m_filename_hash_pins != NULL); DBUG_ASSERT(pfs != NULL); - lf_hash_delete(&filename_hash, thread->m_filename_hash_pins, + + LF_PINS *pins= get_filename_hash_pins(thread); + DBUG_ASSERT(pins != NULL); + + lf_hash_delete(&filename_hash, pins, pfs->m_filename, pfs->m_filename_length); pfs->m_lock.allocated_to_free(); DBUG_VOID_RETURN; diff --git a/storage/perfschema/pfs_instr_class.cc b/storage/perfschema/pfs_instr_class.cc index d99ca4d513c..8bad6e99b3a 100644 --- a/storage/perfschema/pfs_instr_class.cc +++ b/storage/perfschema/pfs_instr_class.cc @@ -823,16 +823,14 @@ const char *sanitize_table_schema_name(const char *unsafe) intptr first= (intptr) &table_share_array[0]; intptr last= (intptr) &table_share_array[table_share_max]; - PFS_table_share dummy; /* Check if unsafe points inside table_share_array[] */ if (likely((first <= ptr) && (ptr < last))) { intptr offset= (ptr - first) % sizeof(PFS_table_share); intptr from= my_offsetof(PFS_table_share, m_key.m_hash_key); - intptr len= sizeof(dummy.m_key.m_hash_key); /* Check if unsafe points inside PFS_table_share::m_key::m_hash_key */ - if (likely((from <= offset) && (offset < from + len))) + if (likely((from <= offset) && (offset < from + PFS_TABLESHARE_HASHKEY_SIZE))) { PFS_table_share *base= (PFS_table_share*) (ptr - offset); /* Check if unsafe really is the schema name */ @@ -849,16 +847,14 @@ const char *sanitize_table_object_name(const char *unsafe) intptr first= (intptr) &table_share_array[0]; intptr last= (intptr) &table_share_array[table_share_max]; - PFS_table_share dummy; /* Check if unsafe points inside table_share_array[] */ if (likely((first <= ptr) && (ptr < last))) { intptr offset= (ptr - first) % sizeof(PFS_table_share); intptr from= my_offsetof(PFS_table_share, m_key.m_hash_key); - intptr len= sizeof(dummy.m_key.m_hash_key); /* Check if unsafe points inside PFS_table_share::m_key::m_hash_key */ - if (likely((from <= offset) && (offset < from + len))) + if (likely((from <= offset) && (offset < from + PFS_TABLESHARE_HASHKEY_SIZE))) { PFS_table_share *base= (PFS_table_share*) (ptr - offset); /* Check if unsafe really is the table name */ diff --git a/storage/perfschema/pfs_instr_class.h b/storage/perfschema/pfs_instr_class.h index 107db628226..b84691ccde5 100644 --- a/storage/perfschema/pfs_instr_class.h +++ b/storage/perfschema/pfs_instr_class.h @@ -128,6 +128,8 @@ struct PFS_thread_class bool m_enabled; }; +#define PFS_TABLESHARE_HASHKEY_SIZE (NAME_LEN + 1 + NAME_LEN + 1) + /** Key identifying a table share. */ struct PFS_table_share_key { @@ -137,7 +139,7 @@ struct PFS_table_share_key the format is "<schema_name><0x00><object_name><0x00>" @see create_table_def_key */ - char m_hash_key[NAME_LEN + 1 + NAME_LEN + 1]; + char m_hash_key[PFS_TABLESHARE_HASHKEY_SIZE]; /** Length in bytes of @c m_hash_key. */ uint m_key_length; }; diff --git a/storage/perfschema/table_ews_global_by_event_name.cc b/storage/perfschema/table_ews_global_by_event_name.cc index 01d9bc5678f..3177584231d 100644 --- a/storage/perfschema/table_ews_global_by_event_name.cc +++ b/storage/perfschema/table_ews_global_by_event_name.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 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 diff --git a/storage/perfschema/table_ews_global_by_event_name.h b/storage/perfschema/table_ews_global_by_event_name.h index 9b2b5cba5a8..7e66448e96c 100644 --- a/storage/perfschema/table_ews_global_by_event_name.h +++ b/storage/perfschema/table_ews_global_by_event_name.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2010, 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 diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index 4d6b729196c..27a463bf61f 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -50,7 +50,6 @@ #else // Windows-specific #include <io.h> - #define strcasecmp stricmp #define snprintf _snprintf #define RECV_FLAGS 0 diff --git a/storage/xtradb/fsp/fsp0fsp.c b/storage/xtradb/fsp/fsp0fsp.c index 6102c5decd8..0c96aab0356 100644 --- a/storage/xtradb/fsp/fsp0fsp.c +++ b/storage/xtradb/fsp/fsp0fsp.c @@ -211,15 +211,13 @@ fseg_n_reserved_pages_low( /********************************************************************//** Marks a page used. The page must reside within the extents of the given segment. */ -static +static __attribute__((nonnull)) void fseg_mark_page_used( /*================*/ fseg_inode_t* seg_inode,/*!< in: segment inode */ - ulint space, /*!< in: space id */ - ulint zip_size,/*!< in: compressed page size in bytes - or 0 for uncompressed pages */ ulint page, /*!< in: page offset */ + xdes_t* descr, /* extent descriptor */ mtr_t* mtr); /*!< in: mtr */ /**********************************************************************//** Returns the first extent descriptor for a segment. We think of the extent @@ -677,19 +675,10 @@ xdes_get_descriptor_with_space_hdr( zip_size = dict_table_flags_to_zip_size( mach_read_from_4(sp_header + FSP_SPACE_FLAGS)); - /* If offset is >= size or > limit, return NULL */ - - if ((offset >= size) || (offset > limit)) { - + if ((offset >= size) || (offset >= limit)) { return(NULL); } - /* If offset is == limit, fill free list of the space. */ - - if (offset == limit) { - fsp_fill_free_list(FALSE, space, sp_header, mtr); - } - descr_page_no = xdes_calc_descriptor_page(zip_size, offset); if (descr_page_no == 0) { @@ -711,14 +700,11 @@ xdes_get_descriptor_with_space_hdr( } /********************************************************************//** -Gets pointer to a the extent descriptor of a page. The page where the -extent descriptor resides is x-locked. If the page offset is equal to -the free limit of the space, adds new extents from above the free limit -to the space free list, if not free limit == space size. This adding -is necessary to make the descriptor defined, as they are uninitialized -above the free limit. +Gets pointer to a the extent descriptor of a page. The page where the extent +descriptor resides is x-locked. This function no longer extends the data +file. @return pointer to the extent descriptor, NULL if the page does not -exist in the space or if the offset exceeds the free limit */ +exist in the space or if the offset is >= the free limit */ static xdes_t* xdes_get_descriptor( @@ -2763,7 +2749,7 @@ fseg_alloc_free_page_low( ut_ad(xdes_get_bit(ret_descr, XDES_FREE_BIT, ret_page % FSP_EXTENT_SIZE, mtr) == TRUE); - fseg_mark_page_used(seg_inode, space, zip_size, ret_page, mtr); + fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr); } buf_reset_check_index_page_at_flush(space, ret_page); @@ -3183,27 +3169,21 @@ fsp_get_available_space_in_free_extents( /********************************************************************//** Marks a page used. The page must reside within the extents of the given segment. */ -static +static __attribute__((nonnull)) void fseg_mark_page_used( /*================*/ fseg_inode_t* seg_inode,/*!< in: segment inode */ - ulint space, /*!< in: space id */ - ulint zip_size,/*!< in: compressed page size in bytes - or 0 for uncompressed pages */ ulint page, /*!< in: page offset */ + xdes_t* descr, /* extent descriptor */ mtr_t* mtr) /*!< in: mtr */ { - xdes_t* descr; ulint not_full_n_used; - ut_ad(seg_inode && mtr); ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); - descr = xdes_get_descriptor(space, zip_size, page, mtr); - ut_ad(mtr_read_ulint(seg_inode + FSEG_ID, MLOG_4BYTES, mtr) == mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr)); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index ae16bb24adf..9e10cbc5d34 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -1669,70 +1669,87 @@ values we want to reserve for multi-value inserts e.g., INSERT INTO T VALUES(), (), (); -innobase_next_autoinc() will be called with increment set to -n * 3 where autoinc_lock_mode != TRADITIONAL because we want -to reserve 3 values for the multi-value INSERT above. +innobase_next_autoinc() will be called with increment set to 3 where +autoinc_lock_mode != TRADITIONAL because we want to reserve 3 values for +the multi-value INSERT above. @return the next value */ static ulonglong innobase_next_autoinc( /*==================*/ ulonglong current, /*!< in: Current value */ - ulonglong increment, /*!< in: increment current by */ + ulonglong need, /*!< in: count of values needed */ + ulonglong step, /*!< in: AUTOINC increment step */ ulonglong offset, /*!< in: AUTOINC offset */ ulonglong max_value) /*!< in: max value for type */ { ulonglong next_value; + ulonglong block = need * step; /* Should never be 0. */ - ut_a(increment > 0); + ut_a(need > 0); + ut_a(block > 0); + ut_a(max_value > 0); + + /* Current value should never be greater than the maximum. */ + ut_a(current <= max_value); /* According to MySQL documentation, if the offset is greater than - the increment then the offset is ignored. */ - if (offset > increment) { + the step then the offset is ignored. */ + if (offset > block) { offset = 0; } - if (max_value <= current) { + /* Check for overflow. */ + if (block >= max_value + || offset > max_value + || current == max_value + || max_value - offset <= offset) { + next_value = max_value; - } else if (offset <= 1) { - /* Offset 0 and 1 are the same, because there must be at - least one node in the system. */ - if (max_value - current <= increment) { + } else { + ut_a(max_value > current); + + ulonglong free = max_value - current; + + if (free < offset || free - offset <= block) { next_value = max_value; } else { - next_value = current + increment; + next_value = 0; } - } else if (max_value > current) { + } + + if (next_value == 0) { + ulonglong next; + if (current > offset) { - next_value = ((current - offset) / increment) + 1; + next = (current - offset) / step; } else { - next_value = ((offset - current) / increment) + 1; + next = (offset - current) / step; } - ut_a(increment > 0); - ut_a(next_value > 0); - + ut_a(max_value > next); + next_value = next * step; /* Check for multiplication overflow. */ - if (increment > (max_value / next_value)) { + ut_a(next_value >= next); + ut_a(max_value > next_value); - next_value = max_value; - } else { - next_value *= increment; + /* Check for overflow */ + if (max_value - next_value >= block) { - ut_a(max_value >= next_value); + next_value += block; - /* Check for overflow. */ - if (max_value - next_value <= offset) { - next_value = max_value; - } else { + if (max_value - next_value >= offset) { next_value += offset; + } else { + next_value = max_value; } + } else { + next_value = max_value; } - } else { - next_value = max_value; } + ut_a(next_value != 0); ut_a(next_value <= max_value); return(next_value); @@ -4271,7 +4288,7 @@ ha_innobase::innobase_initialize_autoinc() nor the offset, so use a default increment of 1. */ auto_inc = innobase_next_autoinc( - read_auto_inc, 1, 1, col_max_value); + read_auto_inc, 1, 1, 0, col_max_value); break; } @@ -6323,15 +6340,16 @@ set_max_autoinc: if (auto_inc <= col_max_value) { ut_a(prebuilt->autoinc_increment > 0); - ulonglong need; ulonglong offset; + ulonglong increment; offset = prebuilt->autoinc_offset; - need = prebuilt->autoinc_increment; + increment = prebuilt->autoinc_increment; auto_inc = innobase_next_autoinc( auto_inc, - need, offset, col_max_value); + 1, increment, offset, + col_max_value); err = innobase_set_max_autoinc( auto_inc); @@ -6609,14 +6627,14 @@ ha_innobase::update_row( if (auto_inc <= col_max_value && auto_inc != 0) { - ulonglong need; ulonglong offset; + ulonglong increment; offset = prebuilt->autoinc_offset; - need = prebuilt->autoinc_increment; + increment = prebuilt->autoinc_increment; auto_inc = innobase_next_autoinc( - auto_inc, need, offset, col_max_value); + auto_inc, 1, increment, offset, col_max_value); error = innobase_set_max_autoinc(auto_inc); } @@ -11703,16 +11721,15 @@ ha_innobase::get_auto_increment( /* With old style AUTOINC locking we only update the table's AUTOINC counter after attempting to insert the row. */ if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) { - ulonglong need; ulonglong current; ulonglong next_value; current = *first_value > col_max_value ? autoinc : *first_value; - need = *nb_reserved_values * increment; /* Compute the last value in the interval */ next_value = innobase_next_autoinc( - current, need, offset, col_max_value); + current, *nb_reserved_values, increment, offset, + col_max_value); prebuilt->autoinc_last_value = next_value; diff --git a/storage/xtradb/include/ut0ut.h b/storage/xtradb/include/ut0ut.h index cad39e9a34f..47ab6eb9b74 100644 --- a/storage/xtradb/include/ut0ut.h +++ b/storage/xtradb/include/ut0ut.h @@ -63,16 +63,16 @@ typedef time_t ib_time_t; # define UT_RELAX_CPU() __asm__ __volatile__ ("pause") #elif defined(HAVE_FAKE_PAUSE_INSTRUCTION) # define UT_RELAX_CPU() __asm__ __volatile__ ("rep; nop") -#elif defined(HAVE_ATOMIC_BUILTINS) -# define UT_RELAX_CPU() do { \ - volatile lint volatile_var; \ - os_compare_and_swap_lint(&volatile_var, 0, 1); \ - } while (0) #elif defined(HAVE_WINDOWS_ATOMICS) /* In the Win32 API, the x86 PAUSE instruction is executed by calling the YieldProcessor macro defined in WinNT.h. It is a CPU architecture- independent way by using YieldProcessor. */ # define UT_RELAX_CPU() YieldProcessor() +#elif defined(HAVE_ATOMIC_BUILTINS) +# define UT_RELAX_CPU() do { \ + volatile lint volatile_var; \ + os_compare_and_swap_lint(&volatile_var, 0, 1); \ + } while (0) #else # define UT_RELAX_CPU() ((void)0) /* avoid warning for an empty statement */ #endif diff --git a/storage/xtradb/os/os0file.c b/storage/xtradb/os/os0file.c index b0bfdc6c2bb..875aea7878d 100644 --- a/storage/xtradb/os/os0file.c +++ b/storage/xtradb/os/os0file.c @@ -2924,7 +2924,7 @@ retry: "InnoDB: Check also that the disk is not full" " or a disk quota exceeded.\n", name, (ulong) offset_high, (ulong) offset, - (ulong) n, (ulong) len, (ulong) err); + (ulong) n, ret ? len : 0, (ulong) err); if (strerror((int)err) != NULL) { fprintf(stderr, diff --git a/storage/xtradb/row/row0merge.c b/storage/xtradb/row/row0merge.c index 30cfa7c23af..9390946ad88 100644 --- a/storage/xtradb/row/row0merge.c +++ b/storage/xtradb/row/row0merge.c @@ -583,7 +583,7 @@ row_merge_buf_write( REC_STATUS_ORDINARY, entry, n_fields, &extra_size); - ut_ad(size > extra_size); + ut_ad(size >= extra_size); ut_ad(extra_size >= REC_N_NEW_EXTRA_BYTES); extra_size -= REC_N_NEW_EXTRA_BYTES; size -= REC_N_NEW_EXTRA_BYTES; diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c index f4a91e68024..8e6b01f2a6d 100644 --- a/storage/xtradb/row/row0sel.c +++ b/storage/xtradb/row/row0sel.c @@ -4604,7 +4604,9 @@ no_gap_lock: applicable to unique secondary indexes. Current behaviour is to widen the scope of a lock on an already delete marked record if the same record is deleted twice by the same transaction */ - if (index == clust_index && unique_search) { + if (index == clust_index && unique_search + && !prebuilt->used_in_HANDLER) { + err = DB_RECORD_NOT_FOUND; goto normal_return; diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index e60f9307e39..e25c0783abf 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -306,19 +306,24 @@ void my_hash_sort_simple(CHARSET_INFO *cs, { register const uchar *sort_order=cs->sort_order; const uchar *end; + ulong n1, n2; /* Remove end space. We have to do this to be able to compare 'A ' and 'A' as identical */ end= skip_trailing_space(key, len); - + + n1= *nr1; + n2= *nr2; for (; key < (uchar*) end ; key++) { - nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * - ((uint) sort_order[(uint) *key])) + (nr1[0] << 8); - nr2[0]+=3; + n1^=(ulong) ((((uint) n1 & 63)+n2) * + ((uint) sort_order[(uint) *key])) + (n1 << 8); + n2+=3; } + *nr1= n1; + *nr2= n2; } diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c index 7dc1527002f..e4a8d7a4067 100644 --- a/strings/ctype-uca.c +++ b/strings/ctype-uca.c @@ -1,6 +1,5 @@ -/* Copyright (c) 2004-2007 MySQL AB, 2009 Sun Microsystems, Inc. - Copyright (c) 2009-2011, Monty Program Ab - Use is subject to license terms. +/* Copyright (c) 2004, 2011, Oracle and/or its affiliates. + Copyright (c) 2009, 2011, Monty Program Ab This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 7fd1e595eca..83ea3739f4c 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2003, 2010, Oracle and/or its affiliates - Copyright (c) 2009-2011, Monty Program Ab +/* Copyright (c) 2003, 2012, Oracle and/or its affiliates + Copyright (c) 2009, 2011, Monty Program Ab This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index b9f8b57c6b0..88bab1fac76 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -1,6 +1,5 @@ -/* Copyright (c) 2002-2008 MySQL AB, 2009 Sun Microsystems, Inc. - Copyright (c) 2009-2011, Monty Program Ab - Use is subject to license terms. +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2009, 2011, Monty Program Ab This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -1679,7 +1678,7 @@ MY_UNICASE_INFO *const my_unicase_default[256]={ /* Reproduce old utf8_general_ci behaviour before we fixed Bug#27877. */ -MY_UNICASE_INFO *my_unicase_mysql500[256]={ +MY_UNICASE_INFO *const my_unicase_mysql500[256]={ plane00_mysql500, plane01, plane02, plane03, plane04, plane05, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/strings/decimal.c b/strings/decimal.c index 1a99816b914..51c4457d934 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1,5 +1,5 @@ /* Copyright (c) 2004, 2011, Oracle and/or its affiliates. - Copyright (c) 2009-2011, Monty Program Ab + Copyright (c) 2009, 2011, 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 diff --git a/strings/dtoa.c b/strings/dtoa.c index 2af561d0564..6b216056f66 100644 --- a/strings/dtoa.c +++ b/strings/dtoa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public diff --git a/support-files/CMakeLists.txt b/support-files/CMakeLists.txt index d0a7f89d150..58e59e2f938 100644 --- a/support-files/CMakeLists.txt +++ b/support-files/CMakeLists.txt @@ -70,7 +70,14 @@ IF(UNIX) INSTALL(FILES mysql.m4 DESTINATION ${INSTALL_SHAREDIR}/aclocal COMPONENT Development) CONFIGURE_FILE(MySQL-shared-compat.spec.sh ${CMAKE_CURRENT_BINARY_DIR}/MySQL-shared-compat.spec @ONLY) CONFIGURE_FILE(mysql.spec.sh ${CMAKE_CURRENT_BINARY_DIR}/mysql.spec @ONLY) - CONFIGURE_FILE(mysql.spec.sh ${CMAKE_CURRENT_BINARY_DIR}/mysql.${VERSION}.spec @ONLY) + + SET(SPECFILENAME "mysql.${VERSION}.spec") + IF("${VERSION}" MATCHES "-ndb-") + STRING(REGEX REPLACE "^.*-ndb-" "" NDBVERSION "${VERSION}") + SET(SPECFILENAME "mysql-cluster-${NDBVERSION}.spec") + ENDIF() + CONFIGURE_FILE(mysql.spec.sh ${CMAKE_CURRENT_BINARY_DIR}/${SPECFILENAME} @ONLY) + CONFIGURE_FILE(MySQL-shared-compat.spec.sh ${CMAKE_CURRENT_BINARY_DIR}/MySQL-shared-compat.spec @ONLY) SET(bindir ${prefix}/${INSTALL_BINDIR}) diff --git a/unittest/mysys/bitmap-t.c b/unittest/mysys/bitmap-t.c index 062a0963e76..bcfb9835c10 100644 --- a/unittest/mysys/bitmap-t.c +++ b/unittest/mysys/bitmap-t.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2006, 2011, Oracle and/or its affiliates +/* + Copyright (c) 2006, 2012, 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 diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c index ae9bb6903f5..35e782eb360 100644 --- a/unittest/mysys/my_atomic-t.c +++ b/unittest/mysys/my_atomic-t.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2011, 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 diff --git a/unittest/mysys/thr_template.c b/unittest/mysys/thr_template.c index 5bb9809b1e1..7304eb50955 100644 --- a/unittest/mysys/thr_template.c +++ b/unittest/mysys/thr_template.c @@ -54,7 +54,7 @@ void test_concurrently(const char *test, pthread_handler handler, int n, int m) int main(int argc __attribute__((unused)), char **argv) { - MY_INIT("thd_template"); + MY_INIT(argv[0]); if (argv[1] && *argv[1]) DBUG_SET_INITIAL(argv[1]); diff --git a/win/packaging/ca/CustomAction.cpp b/win/packaging/ca/CustomAction.cpp index ed26dd45a94..50b39adc0b1 100644 --- a/win/packaging/ca/CustomAction.cpp +++ b/win/packaging/ca/CustomAction.cpp @@ -73,6 +73,82 @@ LExit: return WcaFinalize(er); } +/* + Escape command line parameter fpr pass to CreateProcess(). + + We assume out has enough space to include encoded string + 2*wcslen(in) is enough. + + It is assumed that called will add double quotation marks before and after + the string. +*/ +static void EscapeCommandLine(const wchar_t *in, wchar_t *out, size_t buflen) +{ + const wchar_t special_chars[]=L" \t\n\v\""; + bool needs_escaping= false; + size_t pos; + + for(int i=0; i< sizeof(special_chars) -1; i++) + { + if (wcschr(in, special_chars[i])) + { + needs_escaping = true; + break; + } + } + + if(!needs_escaping) + { + wcscpy_s(out, buflen, in); + return; + } + + pos= 0; + for(int i = 0 ; ; i++)
+ {
+ size_t n_backslashes = 0;
+ wchar_t c;
+ while (in[i] == L'\\')
+ {
+ i++;
+ n_backslashes++;
+ }
+
+ c= in[i];
+ if (c == 0)
+ {
+ /*
+ Escape all backslashes, but let the terminating double quotation mark
+ that caller adds be interpreted as a metacharacter.
+ */
+ for(size_t j= 0; j < 2*n_backslashes;j++)
+ {
+ out[pos++]=L'\\';
+ }
+ break;
+ }
+ else if (c == L'"')
+ {
+ /*
+ Escape all backslashes and the following double quotation mark.
+ */
+ for(size_t j= 0; j < 2*n_backslashes + 1; j++)
+ {
+ out[pos++]=L'\\';
+ }
+ out[pos++]= L'"';
+ }
+ else
+ {
+ /* Backslashes aren't special here. */
+ for (size_t j=0; j < n_backslashes; j++)
+ out[pos++] = L'\\';
+
+ out[pos++]= c;
+ }
+ } + out[pos++]= 0; +} /* Check for if directory is empty during install, sets "<PROPERTY>_NOT_EMPTY" otherise @@ -462,6 +538,8 @@ unsigned long long GetMaxBufferSize(unsigned long long totalPhys) return totalPhys; #endif } + + /* Checks SERVICENAME, PORT and BUFFERSIZE parameters */ @@ -470,6 +548,8 @@ extern "C" UINT __stdcall CheckDatabaseProperties (MSIHANDLE hInstall) wchar_t ServiceName[MAX_PATH]={0}; wchar_t SkipNetworking[MAX_PATH]={0}; wchar_t QuickConfig[MAX_PATH]={0}; + wchar_t Password[MAX_PATH]={0}; + wchar_t EscapedPassword[2*MAX_PATH+2]; wchar_t Port[6]; wchar_t BufferPoolSize[16]; DWORD PortLen=6; @@ -512,8 +592,13 @@ extern "C" UINT __stdcall CheckDatabaseProperties (MSIHANDLE hInstall) } } - DWORD SkipNetworkingLen= MAX_PATH; + DWORD PasswordLen= MAX_PATH; + MsiGetPropertyW (hInstall, L"PASSWORD", Password, &PasswordLen); + EscapeCommandLine(Password, EscapedPassword, + sizeof(EscapedPassword)/sizeof(EscapedPassword[0])); + MsiSetPropertyW(hInstall,L"ESCAPEDPASSWORD",EscapedPassword); + DWORD SkipNetworkingLen= MAX_PATH; MsiGetPropertyW(hInstall, L"SKIPNETWORKING", SkipNetworking, &SkipNetworkingLen); MsiGetPropertyW(hInstall, L"PORT", Port, &PortLen); diff --git a/win/packaging/extra.wxs.in b/win/packaging/extra.wxs.in index 37b12575328..d4adc959333 100644 --- a/win/packaging/extra.wxs.in +++ b/win/packaging/extra.wxs.in @@ -34,6 +34,7 @@ <!-- Root password -->
<Property Id="PASSWORD" Hidden="yes" Secure="yes" />
+ <Property Id="ESCAPEDPASSWORD" Hidden="yes" Secure="yes" />
<!-- Database port -->
<Property Id="PORT" Value="3306" Secure="yes"/>
<!-- Whether to allow remote access for root user -->
@@ -233,7 +234,7 @@ </Control>
<Control Id="CheckBoxModifyRootPassword" Type="CheckBox" X="8" Y="62" Width="222" Height="18" Property="ModifyRootPassword" CheckBoxValue="1" TabSkip="no">
- <Text>{\Font1}Modify root password</Text>
+ <Text>{\Font1}Modify password for database user 'root'</Text>
<Publish Property="PASSWORD" >NOT ModifyRootPassword</Publish>
<Publish Property="RootPasswordConfirm">NOT ModifyRootPassword</Publish>
<Publish Property="ALLOWREMOTEROOTACCESS">NOT ModifyRootPassword</Publish>
@@ -255,7 +256,7 @@ </Control>
<Control Id="CheckBoxALLOWREMOTEROOTACCESS" Type="CheckBox" X="23" Y="122" Width="196" Height="18" Property="ALLOWREMOTEROOTACCESS"
CheckBoxValue="--allow-remote-root-access" TabSkip="no">
- <Text>{\Font1}Enable root access from remote machines</Text>
+ <Text>{\Font1}Enable access from remote machines for 'root' user</Text>
<Condition Action="enable">ModifyRootPassword</Condition>
<Condition Action="disable">NOT ModifyRootPassword</Condition>
</Control>
@@ -668,7 +669,7 @@ <CustomAction Id='PresetDatabaseProperties' BinaryKey='wixca.dll' DllEntry='PresetDatabaseProperties' />
<CustomAction Id="CreateDatabaseCommand" Property="CreateDatabase"
Value=
- ""[#F.bin.mysql_install_db.exe]" "--service=[SERVICENAME]" --port=[PORT] "--password=[PASSWORD]" "--datadir=[DATADIR]\" [SKIPNETWORKING] [ALLOWREMOTEROOTACCESS] [DEFAULTUSER]"
+ ""[#F.bin.mysql_install_db.exe]" "--service=[SERVICENAME]" --port=[PORT] "--password=[ESCAPEDPASSWORD]" "--datadir=[DATADIR]\" [SKIPNETWORKING] [ALLOWREMOTEROOTACCESS] [DEFAULTUSER]"
Execute="immediate"
HideTarget="yes"
/>
@@ -703,7 +704,7 @@ <![CDATA[&DBInstance=3 AND NOT !DBInstance=3 AND OLDERVERSIONBEINGUPGRADED=""]]>
</Custom>
<Custom Action="ErrorDataDirNotEmpty" After="CheckDataDirectoryEmpty" >DATADIRNOTEMPTY</Custom>
-
+ <Custom Action="CheckDatabaseProperties" Before="CreateDatabaseCommand">SERVICENAME</Custom>
<Custom Action="CreateDatabaseCommand" After="CostFinalize" >
<![CDATA[&DBInstance=3 AND NOT !DBInstance=3 AND OLDERVERSIONBEINGUPGRADED=""]]>
</Custom>
|