diff --git a/Makefile.am b/Makefile.am index e71520bf887..49ab3103c25 100644 --- a/Makefile.am +++ b/Makefile.am @@ -196,6 +196,10 @@ test-bt-fast: -cd mysql-test ; MTR_BUILD_THREAD=auto \ @PERL@ ./mysql-test-run.pl --force --comment=stress --suite=stress +test-bt-fast: + -cd mysql-test ; MTR_BUILD_THREAD=auto \ + @PERL@ ./mysql-test-run.pl --force --comment=ps --ps-protocol --report-features + test-bt-debug: -cd mysql-test ; MTR_BUILD_THREAD=auto \ @PERL@ ./mysql-test-run.pl --comment=debug --force --timer \ @@ -203,6 +207,8 @@ test-bt-debug: test-bt-debug-fast: +test-bt-debug-fast: + # Keep these for a while test-pl: test test-full-pl: test-full diff --git a/client/mysql.cc b/client/mysql.cc index d46f18332ab..b76a3d624ab 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1280,21 +1280,35 @@ sig_handler handle_sigint(int sig) MYSQL *kill_mysql= NULL; /* terminate if no query being executed, or we already tried interrupting */ - if (!executing_query || interrupted_query) + /* terminate if no query being executed, or we already tried interrupting */ + if (!executing_query || (interrupted_query == 2)) + { + tee_fprintf(stdout, "Ctrl-C -- exit!\n"); goto err; + } kill_mysql= mysql_init(kill_mysql); if (!mysql_real_connect(kill_mysql,current_host, current_user, opt_password, "", opt_mysql_port, opt_mysql_unix_port,0)) + { + tee_fprintf(stdout, "Ctrl-C -- sorry, cannot connect to server to kill query, giving up ...\n"); goto err; + } + + interrupted_query++; + + /* mysqld < 5 does not understand KILL QUERY, skip to KILL CONNECTION */ + if ((interrupted_query == 1) && (mysql_get_server_version(&mysql) < 50000)) + interrupted_query= 2; /* kill_buffer is always big enough because max length of %lu is 15 */ - sprintf(kill_buffer, "KILL /*!50000 QUERY */ %lu", mysql_thread_id(&mysql)); - mysql_real_query(kill_mysql, kill_buffer, strlen(kill_buffer)); + sprintf(kill_buffer, "KILL %s%lu", + (interrupted_query == 1) ? "QUERY " : "", + mysql_thread_id(&mysql)); + tee_fprintf(stdout, "Ctrl-C -- sending \"%s\" to server ...\n", kill_buffer); + mysql_real_query(kill_mysql, kill_buffer, (uint) strlen(kill_buffer)); mysql_close(kill_mysql); - tee_fprintf(stdout, "Query aborted by Ctrl+C\n"); - - interrupted_query= 1; + tee_fprintf(stdout, "Ctrl-C -- query aborted.\n"); return; diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 894a3ac9146..cf56713ec0d 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -78,6 +78,9 @@ static const char* host = 0; static int port= 0; static uint my_end_arg; static const char* sock= 0; +#ifdef HAVE_SMEM +static char *shared_memory_base_name= 0; +#endif static const char* user = 0; static char* pass = 0; static char *charset= 0; @@ -1009,13 +1012,13 @@ static struct my_option my_long_options[] = /* 'unspec' is not mentioned because it is just a placeholder. */ "Determine when the output statements should be base64-encoded BINLOG " "statements: 'never' disables it and works only for binlogs without " - "row-based events; 'auto' is the default and prints base64 only when " - "necessary (i.e., for row-based events and format description events); " - "'decode-rows' suppresses BINLOG statements for row events, but does " - "not exit as an error if a row event is found, unlike 'never'; " - "'always' prints base64 whenever possible. 'always' is for debugging " - "only and should not be used in a production system. The default is " - "'auto'. --base64-output is a short form for --base64-output=always." + "row-based events; 'decode-rows' decodes row events into commented SQL " + "statements if the --verbose option is also given; 'auto' prints base64 " + "only when necessary (i.e., for row-based events and format description " + "events); 'always' prints base64 whenever possible. 'always' is for " + "debugging only and should not be used in a production system. If this " + "argument is not given, the default is 'auto'; if it is given with no " + "argument, 'always' is used." ,(uchar**) &opt_base64_output_mode_str, (uchar**) &opt_base64_output_mode_str, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, @@ -1094,6 +1097,12 @@ static struct my_option my_long_options[] = {"set-charset", OPT_SET_CHARSET, "Add 'SET NAMES character_set' to the output.", (uchar**) &charset, (uchar**) &charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef HAVE_SMEM + {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, + "Base name of shared memory.", (uchar**) &shared_memory_base_name, + (uchar**) &shared_memory_base_name, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#endif {"short-form", 's', "Just show regular queries: no extra info and no " "row-based events. This is for testing only, and should not be used in " "production systems. If you want to suppress base64-output, consider " @@ -1395,6 +1404,11 @@ static Exit_status safe_connect() if (opt_protocol) mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol); +#ifdef HAVE_SMEM + if (shared_memory_base_name) + mysql_options(mysql, MYSQL_SHARED_MEMORY_BASE_NAME, + shared_memory_base_name); +#endif if (!mysql_real_connect(mysql, host, user, pass, 0, port, sock, 0)) { error("Failed on connect: %s", mysql_error(mysql)); diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 8de2f0c79b0..cb1d21ebe8a 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -81,6 +81,9 @@ enum { static int record= 0, opt_sleep= -1; static char *opt_db= 0, *opt_pass= 0; const char *opt_user= 0, *opt_host= 0, *unix_sock= 0, *opt_basedir= "./"; +#ifdef HAVE_SMEM +static char *shared_memory_base_name=0; +#endif const char *opt_logdir= ""; const char *opt_include= 0, *opt_charsets_dir; static int opt_port= 0; @@ -4896,6 +4899,8 @@ do_handle_error: - options to use for the connection * SSL - use SSL if available * COMPRESS - use compression if available + * SHM - use shared memory if available + * PIPE - use named pipe if available */ @@ -4904,6 +4909,7 @@ void do_connect(struct st_command *command) int con_port= opt_port; char *con_options; my_bool con_ssl= 0, con_compress= 0; + my_bool con_pipe= 0, con_shm= 0; struct st_connection* con_slot; static DYNAMIC_STRING ds_connection_name; @@ -4914,6 +4920,9 @@ void do_connect(struct st_command *command) static DYNAMIC_STRING ds_port; static DYNAMIC_STRING ds_sock; static DYNAMIC_STRING ds_options; +#ifdef HAVE_SMEM + static DYNAMIC_STRING ds_shm; +#endif const struct command_arg connect_args[] = { { "connection name", ARG_STRING, TRUE, &ds_connection_name, "Name of the connection" }, { "host", ARG_STRING, TRUE, &ds_host, "Host to connect to" }, @@ -4941,6 +4950,11 @@ void do_connect(struct st_command *command) die("Illegal argument for port: '%s'", ds_port.str); } +#ifdef HAVE_SMEM + /* Shared memory */ + init_dynamic_string(&ds_shm, ds_sock.str, 0, 0); +#endif + /* Sock */ if (ds_sock.length) { @@ -4979,6 +4993,10 @@ void do_connect(struct st_command *command) con_ssl= 1; else if (!strncmp(con_options, "COMPRESS", 8)) con_compress= 1; + else if (!strncmp(con_options, "PIPE", 4)) + con_pipe= 1; + else if (!strncmp(con_options, "SHM", 3)) + con_shm= 1; else die("Illegal option to connect: %.*s", (int) (end - con_options), con_options); @@ -5026,6 +5044,31 @@ void do_connect(struct st_command *command) } #endif +#ifdef __WIN__ + if (con_pipe) + { + uint protocol= MYSQL_PROTOCOL_PIPE; + mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, &protocol); + } +#endif + +#ifdef HAVE_SMEM + if (con_shm) + { + uint protocol= MYSQL_PROTOCOL_MEMORY; + if (!ds_shm.length) + die("Missing shared memory base name"); + mysql_options(&con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME, ds_shm.str); + mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, &protocol); + } + else if(shared_memory_base_name) + { + mysql_options(&con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME, + shared_memory_base_name); + } +#endif + + /* Use default db name */ if (ds_database.length == 0) dynstr_set(&ds_database, opt_db); @@ -5058,6 +5101,9 @@ void do_connect(struct st_command *command) dynstr_free(&ds_port); dynstr_free(&ds_sock); dynstr_free(&ds_options); +#ifdef HAVE_SMEM + dynstr_free(&ds_shm); +#endif DBUG_VOID_RETURN; } @@ -5724,6 +5770,12 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"server-file", 'F', "Read embedded server arguments from file.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef HAVE_SMEM + {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, + "Base name of shared memory.", (uchar**) &shared_memory_base_name, + (uchar**) &shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, + 0, 0, 0}, +#endif {"silent", 's', "Suppress all normal output. Synonym for --quiet.", (uchar**) &silent, (uchar**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-safemalloc", OPT_SKIP_SAFEMALLOC, @@ -6913,35 +6965,39 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command, Need to grab affected rows information before getting warnings here */ - if (!disable_info) - affected_rows= mysql_affected_rows(mysql); - - if (!disable_warnings) { - /* Get the warnings from execute */ + ulonglong affected_rows; + LINT_INIT(affected_rows); - /* Append warnings to ds - if there are any */ - if (append_warnings(&ds_execute_warnings, mysql) || - ds_execute_warnings.length || - ds_prepare_warnings.length || - ds_warnings->length) + if (!disable_info) + affected_rows= mysql_affected_rows(mysql); + + if (!disable_warnings) { - dynstr_append_mem(ds, "Warnings:\n", 10); - if (ds_warnings->length) - dynstr_append_mem(ds, ds_warnings->str, - ds_warnings->length); - if (ds_prepare_warnings.length) - dynstr_append_mem(ds, ds_prepare_warnings.str, - ds_prepare_warnings.length); - if (ds_execute_warnings.length) - dynstr_append_mem(ds, ds_execute_warnings.str, - ds_execute_warnings.length); + /* Get the warnings from execute */ + + /* Append warnings to ds - if there are any */ + if (append_warnings(&ds_execute_warnings, mysql) || + ds_execute_warnings.length || + ds_prepare_warnings.length || + ds_warnings->length) + { + dynstr_append_mem(ds, "Warnings:\n", 10); + if (ds_warnings->length) + dynstr_append_mem(ds, ds_warnings->str, + ds_warnings->length); + if (ds_prepare_warnings.length) + dynstr_append_mem(ds, ds_prepare_warnings.str, + ds_prepare_warnings.length); + if (ds_execute_warnings.length) + dynstr_append_mem(ds, ds_execute_warnings.str, + ds_execute_warnings.length); + } } + + if (!disable_info) + append_info(ds, affected_rows, mysql_info(mysql)); } - - if (!disable_info) - append_info(ds, affected_rows, mysql_info(mysql)); - } end: @@ -7673,6 +7729,11 @@ int main(int argc, char **argv) } #endif +#ifdef HAVE_SMEM + if (shared_memory_base_name) + mysql_options(&con->mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); +#endif + if (!(con->name = my_strdup("default", MYF(MY_WME)))) die("Out of memory"); diff --git a/configure.in b/configure.in index d479088356b..fb5517659ba 100644 --- a/configure.in +++ b/configure.in @@ -10,7 +10,7 @@ AC_CANONICAL_SYSTEM # # When changing major version number please also check switch statement # in mysqlbinlog::check_master_version(). -AM_INIT_AUTOMAKE(mysql, 5.1.41) +AM_INIT_AUTOMAKE(mysql, 5.1.42) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp index 89fd5f7c7bc..2bbc0a85e8b 100644 --- a/extra/yassl/taocrypt/src/random.cpp +++ b/extra/yassl/taocrypt/src/random.cpp @@ -27,7 +27,6 @@ #include #if defined(_WIN32) - #define _WIN32_WINNT 0x0400 #include #include #else diff --git a/include/myisam.h b/include/myisam.h index 02251eeacb4..19b35538c65 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -432,6 +432,10 @@ typedef struct st_mi_check_param const char *db_name, *table_name; const char *op_name; enum_mi_stats_method stats_method; +#ifdef THREAD + pthread_mutex_t print_msg_mutex; + my_bool need_print_msg_lock; +#endif } MI_CHECK; typedef struct st_sort_ft_buf diff --git a/include/mysql.h b/include/mysql.h index d114afb6c93..68cce3196a0 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -557,6 +557,16 @@ unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, unsigned long length); void STDCALL mysql_debug(const char *debug); +char * STDCALL mysql_odbc_escape_string(MYSQL *mysql, + char *to, + unsigned long to_length, + const char *from, + unsigned long from_length, + void *param, + char * + (*extend_buffer) + (void *, char *to, + unsigned long *length)); void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name); unsigned int STDCALL mysql_thread_safe(void); my_bool STDCALL mysql_embedded(void); diff --git a/include/mysql.h.pp b/include/mysql.h.pp index 633cde41130..bd4c79916dd 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -518,6 +518,16 @@ unsigned long mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, unsigned long length); void mysql_debug(const char *debug); +char * mysql_odbc_escape_string(MYSQL *mysql, + char *to, + unsigned long to_length, + const char *from, + unsigned long from_length, + void *param, + char * + (*extend_buffer) + (void *, char *to, + unsigned long *length)); void myodbc_remove_escape(MYSQL *mysql,char *name); unsigned int mysql_thread_safe(void); my_bool mysql_embedded(void); diff --git a/include/violite.h b/include/violite.h index f833606233c..3f68ccde10f 100644 --- a/include/violite.h +++ b/include/violite.h @@ -44,7 +44,7 @@ enum enum_vio_type Vio* vio_new(my_socket sd, enum enum_vio_type type, uint flags); #ifdef __WIN__ Vio* vio_new_win32pipe(HANDLE hPipe); -Vio* vio_new_win32shared_memory(NET *net,HANDLE handle_file_map, +Vio* vio_new_win32shared_memory(HANDLE handle_file_map, HANDLE handle_map, HANDLE event_server_wrote, HANDLE event_server_read, @@ -221,7 +221,11 @@ struct st_vio HANDLE event_conn_closed; size_t shared_memory_remain; char *shared_memory_pos; - NET *net; #endif /* HAVE_SMEM */ +#ifdef _WIN32 + OVERLAPPED pipe_overlapped; + DWORD read_timeout_millis; + DWORD write_timeout_millis; +#endif }; #endif /* vio_violite_h_ */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 1264f2765ba..77ff2a01d7c 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1629,6 +1629,20 @@ mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, return (uint) escape_string_for_mysql(mysql->charset, to, 0, from, length); } + +char * STDCALL +mysql_odbc_escape_string(MYSQL *mysql __attribute__((unused)), + char *to __attribute__((unused)), + ulong to_length __attribute__((unused)), + const char *from __attribute__((unused)), + ulong from_length __attribute__((unused)), + void *param __attribute__((unused)), + char * (*extend_buffer)(void *, char *, ulong *) + __attribute__((unused))) +{ + return NULL; +} + void STDCALL myodbc_remove_escape(MYSQL *mysql,char *name) { diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index 81f86dc8726..8c6b71d9553 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -78,6 +78,7 @@ EXPORTS mysql_next_result mysql_num_fields mysql_num_rows + mysql_odbc_escape_string mysql_options mysql_stmt_param_count mysql_stmt_param_metadata diff --git a/libmysqld/libmysqld.def b/libmysqld/libmysqld.def index 047cfe0fe57..e0f02003963 100644 --- a/libmysqld/libmysqld.def +++ b/libmysqld/libmysqld.def @@ -50,6 +50,7 @@ EXPORTS mysql_next_result mysql_num_fields mysql_num_rows + mysql_odbc_escape_string mysql_options mysql_ping mysql_query diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index f3163d8e84d..b4e934735a6 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -18,6 +18,7 @@ main.plugin_load @solaris # Bug#42144 ndb.* # joro : NDB tests marked as experimental as agreed with bochklin +rpl.rpl_cross_version* # Bug #43913 2009-10-26 joro rpl_cross_version can't pass on conflicts complainig clash with --slave-load-tm rpl.rpl_get_master_version_and_clock* # Bug#46931 2009-08-26 alik rpl.rpl_get_master_version_and_clock fails on hpux11.31 rpl.rpl_innodb_bug28430* @solaris # Bug#46029 rpl.rpl_row_create_table* # Bug#45576: rpl_row_create_table fails on PB2 diff --git a/mysql-test/extra/binlog_tests/drop_temp_table.test b/mysql-test/extra/binlog_tests/drop_temp_table.test index 5616fb4a643..63833c10c14 100644 --- a/mysql-test/extra/binlog_tests/drop_temp_table.test +++ b/mysql-test/extra/binlog_tests/drop_temp_table.test @@ -48,6 +48,16 @@ DROP TABLE IF EXISTS tmp2, t; --enable_warnings SELECT GET_LOCK("a",10); + +# +# BUG48216 Replication fails on all slaves after upgrade to 5.0.86 on master +# +# When the session is closed, any temporary tables of the session are dropped +# and are binlogged. But it will be binlogged with a wrong database name when +# the length of the database name('drop-temp-table-test') is greater than the +# current database name('test'). +# +USE test; disconnect con1; connection con2; diff --git a/mysql-test/extra/rpl_tests/rpl_loaddata.test b/mysql-test/extra/rpl_tests/rpl_loaddata.test index 129a39ac509..e159242ed10 100644 --- a/mysql-test/extra/rpl_tests/rpl_loaddata.test +++ b/mysql-test/extra/rpl_tests/rpl_loaddata.test @@ -158,4 +158,65 @@ LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1; DROP TABLE IF EXISTS t1; +# BUG#48297: Schema name is ignored when LOAD DATA is written into binlog, +# replication aborts +-- source include/master-slave-reset.inc + +-- let $db1= b48297_db1 +-- let $db2= b42897_db2 + +-- connection master + +-- disable_warnings +-- eval drop database if exists $db1 +-- eval drop database if exists $db2 +-- enable_warnings + +-- eval create database $db1 +-- eval create database $db2 + +-- eval use $db1 +-- eval CREATE TABLE t1 (c1 VARCHAR(256)) engine=$engine_type; + +-- eval use $db2 + +-- echo ### assertion: works with cross-referenced database +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 + +-- eval use $db1 +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- echo ### assertion: works with fully qualified name on current database +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 + +-- echo ### assertion: works without fully qualified name on current database +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1 + +-- echo ### create connection without default database +-- echo ### connect (conn2,localhost,root,,*NO-ONE*); +connect (conn2,localhost,root,,*NO-ONE*); +-- connection conn2 +-- echo ### assertion: works without stating the default database +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 +-- echo ### disconnect and switch back to master connection +-- disconnect conn2 +-- connection master + +-- sync_slave_with_master +-- eval use $db1 + +let $diff_table_1=master:$db1.t1; +let $diff_table_2=slave:$db1.t1; +source include/diff_tables.inc; + +-- connection master + +-- eval DROP DATABASE $db1 +-- eval DROP DATABASE $db2 + +-- sync_slave_with_master + # End of 4.1 tests diff --git a/mysql-test/extra/rpl_tests/rpl_stm_000001.test b/mysql-test/extra/rpl_tests/rpl_stm_000001.test index 61d443158d0..323d626c95f 100644 --- a/mysql-test/extra/rpl_tests/rpl_stm_000001.test +++ b/mysql-test/extra/rpl_tests/rpl_stm_000001.test @@ -93,7 +93,7 @@ kill @id; # We don't drop t3 as this is a temporary table drop table t2; connection master; ---error 1053,2013 +--error 1317,2013 reap; connection slave; # The SQL slave thread should now have stopped because the query was killed on diff --git a/mysql-test/include/have_case_insensitive_fs.inc b/mysql-test/include/have_case_insensitive_fs.inc new file mode 100644 index 00000000000..de4ad73d780 --- /dev/null +++ b/mysql-test/include/have_case_insensitive_fs.inc @@ -0,0 +1,4 @@ +--require r/case_insensitive_fs.require +--disable_query_log +show variables like 'lower_case_file_system'; +--enable_query_log diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm index c1e8f7cd826..c4d68e7127c 100644 --- a/mysql-test/lib/My/ConfigFactory.pm +++ b/mysql-test/lib/My/ConfigFactory.pm @@ -7,6 +7,7 @@ use Carp; use My::Config; use My::Find; +use My::Platform; use File::Basename; @@ -218,7 +219,13 @@ my @mysqld_rules= { 'ssl-key' => \&fix_ssl_server_key }, ); - +if (IS_WINDOWS) +{ + # For simplicity, we use the same names for shared memory and + # named pipes. + push(@mysqld_rules, {'shared-memory-base-name' => \&fix_socket}); +} + sub fix_ndb_mgmd_port { my ($self, $config, $group_name, $group)= @_; my $hostname= $group->value('HostName'); @@ -347,6 +354,16 @@ sub post_check_client_group { } $config->insert($client_group_name, $name_to, $option->value()) } + + if (IS_WINDOWS) + { + # Shared memory base may or may not be defined (e.g not defined in embedded) + my $shm = $group_to_copy_from->option("shared-memory-base-name"); + if (defined $shm) + { + $config->insert($client_group_name,"shared-memory-base-name", $shm->value()); + } + } } @@ -393,6 +410,7 @@ sub post_check_embedded_group { ( '#log-error', # Embedded server writes stderr to mysqltest's log file 'slave-net-timeout', # Embedded server are not build with replication + 'shared-memory-base-name', # No shared memory for embedded ); foreach my $option ( $mysqld->options(), $first_mysqld->options() ) { diff --git a/mysql-test/lib/My/SafeProcess/safe_process_win.cc b/mysql-test/lib/My/SafeProcess/safe_process_win.cc index 455262b29f5..aa9093fb2b4 100755 --- a/mysql-test/lib/My/SafeProcess/safe_process_win.cc +++ b/mysql-test/lib/My/SafeProcess/safe_process_win.cc @@ -50,9 +50,6 @@ is killed. */ -/* Requires Windows 2000 or higher */ -#define _WIN32_WINNT 0x0500 - #include #include #include diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index ea05b4b23c0..bf73b45ecdf 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -518,10 +518,8 @@ sub collect_one_suite($) next if ($test->{'name'} eq 'sys_vars.innodb_lock_wait_timeout_basic'); # Diff around innodb_thread_concurrency variable next if ($test->{'name'} eq 'sys_vars.innodb_thread_concurrency_basic'); - # Disable for Innodb Plugin until the fix for Plugin is received + # Can't work with InnoPlug. Test framework needs to be re-designed. next if ($test->{'name'} eq 'main.innodb_bug46000'); - # Disable for Innodb Plugin until the fix for Plugin is received - next if ($test->{'name'} eq 'main.innodb_bug44369'); # Copy test options my $new_test= My::Test->new(); while (my ($key, $value) = each(%$test)) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index db7173d0b47..06f4e7fbe8a 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -1330,4 +1330,12 @@ ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6','a7','a8','a9', affected rows: 2 info: Records: 2 Duplicates: 0 Warnings: 0 DROP TABLE t1; +CREATE TABLE t1 (f1 TIMESTAMP NULL DEFAULT NULL, +f2 INT(11) DEFAULT NULL) ENGINE=MYISAM DEFAULT CHARSET=utf8; +INSERT INTO t1 VALUES (NULL, NULL), ("2009-10-09 11:46:19", 2); +this should affect no rows as there is no real change +ALTER TABLE t1 CHANGE COLUMN f1 f1_no_real_change TIMESTAMP NULL DEFAULT NULL; +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result index 6eaa8731dc6..1820782d2f8 100644 --- a/mysql-test/r/analyse.result +++ b/mysql-test/r/analyse.result @@ -19,81 +19,10 @@ test.t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL create table t2 select * from t1 procedure analyse(); -select * from t2; -Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -test.t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL -test.t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL -test.t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL -test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL -test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL -drop table t1,t2; +ERROR HY000: Incorrect usage of PROCEDURE and non-SELECT +drop table t1; EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(); ERROR HY000: Incorrect usage of PROCEDURE and subquery -create table t1 (a int not null); -create table t2 select * from t1 where 0=1 procedure analyse(); -show create table t2; -Table Create Table -t2 CREATE TABLE `t2` ( - `Field_name` varbinary(255) NOT NULL DEFAULT '', - `Min_value` varbinary(255) DEFAULT NULL, - `Max_value` varbinary(255) DEFAULT NULL, - `Min_length` bigint(11) NOT NULL DEFAULT '0', - `Max_length` bigint(11) NOT NULL DEFAULT '0', - `Empties_or_zeros` bigint(11) NOT NULL DEFAULT '0', - `Nulls` bigint(11) NOT NULL DEFAULT '0', - `Avg_value_or_avg_length` varbinary(255) NOT NULL DEFAULT '', - `Std` varbinary(255) DEFAULT NULL, - `Optimal_fieldtype` varbinary(64) NOT NULL DEFAULT '' -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -select * from t1 where 0=1 procedure analyse(); -Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -insert into t1 values(1); -drop table t2; -create table t2 select * from t1 where 0=1 procedure analyse(); -show create table t2; -Table Create Table -t2 CREATE TABLE `t2` ( - `Field_name` varbinary(255) NOT NULL DEFAULT '', - `Min_value` varbinary(255) DEFAULT NULL, - `Max_value` varbinary(255) DEFAULT NULL, - `Min_length` bigint(11) NOT NULL DEFAULT '0', - `Max_length` bigint(11) NOT NULL DEFAULT '0', - `Empties_or_zeros` bigint(11) NOT NULL DEFAULT '0', - `Nulls` bigint(11) NOT NULL DEFAULT '0', - `Avg_value_or_avg_length` varbinary(255) NOT NULL DEFAULT '', - `Std` varbinary(255) DEFAULT NULL, - `Optimal_fieldtype` varbinary(64) NOT NULL DEFAULT '' -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -select * from t2; -Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -insert into t2 select * from t1 procedure analyse(); -select * from t2; -Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -test.t1.a 1 1 1 1 0 0 1.0000 0.0000 ENUM('1') NOT NULL -insert into t1 values(2); -drop table t2; -create table t2 select * from t1 where 0=1 procedure analyse(); -show create table t2; -Table Create Table -t2 CREATE TABLE `t2` ( - `Field_name` varbinary(255) NOT NULL DEFAULT '', - `Min_value` varbinary(255) DEFAULT NULL, - `Max_value` varbinary(255) DEFAULT NULL, - `Min_length` bigint(11) NOT NULL DEFAULT '0', - `Max_length` bigint(11) NOT NULL DEFAULT '0', - `Empties_or_zeros` bigint(11) NOT NULL DEFAULT '0', - `Nulls` bigint(11) NOT NULL DEFAULT '0', - `Avg_value_or_avg_length` varbinary(255) NOT NULL DEFAULT '', - `Std` varbinary(255) DEFAULT NULL, - `Optimal_fieldtype` varbinary(64) NOT NULL DEFAULT '' -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -select * from t2; -Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -insert into t2 select * from t1 procedure analyse(); -select * from t2; -Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype -test.t1.a 1 2 1 1 0 0 1.5000 0.5000 ENUM('1','2') NOT NULL -drop table t1,t2; create table t1 (v varchar(128)); insert into t1 values ('abc'),('abc\'def\\hij\"klm\0opq'),('\''),('\"'),('\\'),('a\0'),('b\''),('c\"'),('d\\'),('\'b'),('\"c'),('\\d'),('a\0\0\0b'),('a\'\'\'\'b'),('a\"\"\"\"b'),('a\\\\\\\\b'),('\'\0\\\"'),('\'\''),('\"\"'),('\\\\'),('The\ZEnd'); select * from t1 procedure analyse(); @@ -157,3 +86,40 @@ SELECT * FROM (SELECT * FROM t1) d PROCEDURE ANALYSE(); ERROR HY000: Incorrect usage of PROCEDURE and subquery DROP TABLE t1; End of 4.1 tests +# +# Bug #48293: crash with procedure analyse, view with > 10 columns, +# having clause... +# +CREATE TABLE t1(a INT, b INT, c INT, d INT, e INT, +f INT, g INT, h INT, i INT, j INT,k INT); +INSERT INTO t1 VALUES (),(); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +#should have a derived table +EXPLAIN SELECT * FROM v1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 2 +2 DERIVED t1 ALL NULL NULL NULL NULL 2 +#should not crash +SELECT * FROM v1 PROCEDURE analyse(); +ERROR HY000: Incorrect usage of PROCEDURE and view +#should not crash +SELECT * FROM t1 a, v1, t1 b PROCEDURE analyse(); +ERROR HY000: Incorrect usage of PROCEDURE and view +#should not crash +SELECT * FROM (SELECT * FROM t1 having a > 1) x PROCEDURE analyse(); +ERROR HY000: Incorrect usage of PROCEDURE and subquery +#should not crash +SELECT * FROM t1 a, (SELECT * FROM t1 having a > 1) x, t1 b PROCEDURE analyse(); +ERROR HY000: Incorrect usage of PROCEDURE and subquery +#should not crash +SELECT 1 FROM t1 group by a having a > 1 order by 1 PROCEDURE analyse(); +ERROR HY000: Can't use ORDER clause with this procedure +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1),(2); +# should not crash +CREATE TABLE t2 SELECT 1 FROM t1, t1 t3 GROUP BY t3.a PROCEDURE ANALYSE(); +ERROR HY000: Incorrect usage of PROCEDURE and non-SELECT +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/r/bug40113.result b/mysql-test/r/bug40113.result deleted file mode 100644 index 289037a3f35..00000000000 --- a/mysql-test/r/bug40113.result +++ /dev/null @@ -1,29 +0,0 @@ -# -# Bug #40113: Embedded SELECT inside UPDATE or DELETE can timeout -# without error -# -CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)) ENGINE=InnoDB; -INSERT INTO t1 (a,b) VALUES (1070109,99); -CREATE TABLE t2 (b int, a int, PRIMARY KEY (b)) ENGINE=InnoDB; -INSERT INTO t2 (b,a) VALUES (7,1070109); -SELECT * FROM t1; -a b -1070109 99 -BEGIN; -SELECT b FROM t2 WHERE b=7 FOR UPDATE; -b -7 -BEGIN; -SELECT b FROM t2 WHERE b=7 FOR UPDATE; -ERROR HY000: Lock wait timeout exceeded; try restarting transaction -INSERT INTO t1 (a) VALUES ((SELECT a FROM t2 WHERE b=7)); -ERROR HY000: Lock wait timeout exceeded; try restarting transaction -UPDATE t1 SET a='7000000' WHERE a=(SELECT a FROM t2 WHERE b=7); -ERROR HY000: Lock wait timeout exceeded; try restarting transaction -DELETE FROM t1 WHERE a=(SELECT a FROM t2 WHERE b=7); -ERROR HY000: Lock wait timeout exceeded; try restarting transaction -SELECT * FROM t1; -a b -1070109 99 -DROP TABLE t2, t1; -End of 5.0 tests diff --git a/mysql-test/r/case_insensitive_fs.require b/mysql-test/r/case_insensitive_fs.require new file mode 100644 index 00000000000..062ac610ddd --- /dev/null +++ b/mysql-test/r/case_insensitive_fs.require @@ -0,0 +1,2 @@ +Variable_name Value +lower_case_file_system ON diff --git a/mysql-test/r/ctype_ldml.result b/mysql-test/r/ctype_ldml.result index fe870f82743..d5585dcfad9 100644 --- a/mysql-test/r/ctype_ldml.result +++ b/mysql-test/r/ctype_ldml.result @@ -41,6 +41,14 @@ efgh efgh ijkl ijkl DROP TABLE t1; # +# Bug#45645 Mysql server close all connection and restart using lower function +# +CREATE TABLE t1 (a VARCHAR(10)) CHARACTER SET utf8 COLLATE utf8_test_ci; +INSERT INTO t1 (a) VALUES ('hello!'); +SELECT * FROM t1 WHERE LOWER(a)=LOWER('N'); +a +DROP TABLE t1; +# # Bug#43827 Server closes connections and restarts # CREATE TABLE t1 (c1 VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_test_ci); diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result index 96fcbc33d3f..5a1bf1a1290 100644 --- a/mysql-test/r/explain.result +++ b/mysql-test/r/explain.result @@ -194,4 +194,20 @@ dt 2001-01-01 01:01:01 2001-01-01 01:01:01 drop tables t1, t2; +# +# Bug#48295: +# explain extended crash with subquery and ONLY_FULL_GROUP_BY sql_mode +# +CREATE TABLE t1 (f1 INT); +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; +EXPLAIN EXTENDED SELECT 1 FROM t1 +WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t ); +ERROR 42000: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause +SHOW WARNINGS; +Level Code Message +Error 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause +Note 1003 select 1 AS `1` from `test`.`t1` where ((...)) +SET SESSION sql_mode=@old_sql_mode; +DROP TABLE t1; End of 5.1 tests. diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result index b030139e40e..68c4a6a13e5 100644 --- a/mysql-test/r/gis-rtree.result +++ b/mysql-test/r/gis-rtree.result @@ -1487,4 +1487,43 @@ MBRINTERSECTS(b, GEOMFROMTEXT('LINESTRING(1 1,1102219 2)') ); COUNT(*) 2 DROP TABLE t1; +# +# Bug #48258: Assertion failed when using a spatial index +# +CREATE TABLE t1(a LINESTRING NOT NULL, SPATIAL KEY(a)); +INSERT INTO t1 VALUES +(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')), +(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')); +EXPLAIN SELECT 1 FROM t1 WHERE a = GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where +SELECT 1 FROM t1 WHERE a = GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +1 +1 +1 +EXPLAIN SELECT 1 FROM t1 WHERE a < GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where +SELECT 1 FROM t1 WHERE a < GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +1 +EXPLAIN SELECT 1 FROM t1 WHERE a <= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where +SELECT 1 FROM t1 WHERE a <= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +1 +1 +1 +EXPLAIN SELECT 1 FROM t1 WHERE a > GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where +SELECT 1 FROM t1 WHERE a > GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +1 +EXPLAIN SELECT 1 FROM t1 WHERE a >= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 2 Using where +SELECT 1 FROM t1 WHERE a >= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +1 +1 +1 +DROP TABLE t1; End of 5.0 tests. diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index a3708d06a1c..b40ff6be160 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -972,6 +972,18 @@ select min(`col002`) from t1 union select `col002` from t1; min(`col002`) NULL drop table t1; +# +# Bug #47780: crash when comparing GIS items from subquery +# +CREATE TABLE t1(a INT, b MULTIPOLYGON); +INSERT INTO t1 VALUES +(0, +GEOMFROMTEXT( +'multipolygon(((1 2,3 4,5 6,7 8,9 8),(7 6,5 4,3 2,1 2,3 4)))')); +# must not crash +SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); +1 +DROP TABLE t1; End of 5.0 tests create table t1 (f1 tinyint(1), f2 char(1), f3 varchar(1), f4 geometry, f5 datetime); create view v1 as select * from t1; diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index a677d71b266..92beccd2a9e 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -1007,8 +1007,8 @@ DROP TABLE mysqltest1.t2; SHOW GRANTS; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' -GRANT SELECT, INSERT, CREATE, DROP, ALTER ON `mysqltest1`.`t2` TO 'mysqltest_1'@'localhost' GRANT SELECT, INSERT, CREATE, DROP, ALTER ON `mysqltest1`.`t1` TO 'mysqltest_1'@'localhost' +GRANT SELECT, INSERT, CREATE, DROP, ALTER ON `mysqltest1`.`t2` TO 'mysqltest_1'@'localhost' RENAME TABLE t1 TO t2; RENAME TABLE t2 TO t1; ALTER TABLE t1 RENAME TO t2; @@ -1018,8 +1018,8 @@ REVOKE DROP, INSERT ON mysqltest1.t2 FROM mysqltest_1@localhost; SHOW GRANTS; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' -GRANT SELECT, CREATE, ALTER ON `mysqltest1`.`t2` TO 'mysqltest_1'@'localhost' GRANT SELECT, CREATE, ALTER ON `mysqltest1`.`t1` TO 'mysqltest_1'@'localhost' +GRANT SELECT, CREATE, ALTER ON `mysqltest1`.`t2` TO 'mysqltest_1'@'localhost' RENAME TABLE t1 TO t2; ERROR 42000: DROP command denied to user 'mysqltest_1'@'localhost' for table 't1' ALTER TABLE t1 RENAME TO t2; diff --git a/mysql-test/r/grant3.result b/mysql-test/r/grant3.result index f38848111ad..59c64ee84ae 100644 --- a/mysql-test/r/grant3.result +++ b/mysql-test/r/grant3.result @@ -154,4 +154,42 @@ SELECT * FROM mysqltest_1.t1; a DROP USER 'mysqltest1'@'%'; DROP DATABASE mysqltest_1; +# +# Bug#41597 - After rename of user, there are additional grants +# when grants are reapplied. +# +CREATE DATABASE temp; +CREATE TABLE temp.t1(a INT, b VARCHAR(10)); +INSERT INTO temp.t1 VALUES(1, 'name1'); +INSERT INTO temp.t1 VALUES(2, 'name2'); +INSERT INTO temp.t1 VALUES(3, 'name3'); +CREATE USER 'user1'@'%'; +RENAME USER 'user1'@'%' TO 'user2'@'%'; +# Show privileges after rename and BEFORE grant +SHOW GRANTS FOR 'user2'@'%'; +Grants for user2@% +GRANT USAGE ON *.* TO 'user2'@'%' +GRANT SELECT (a), INSERT (b) ON `temp`.`t1` TO 'user2'@'%'; +# Show privileges after rename and grant +SHOW GRANTS FOR 'user2'@'%'; +Grants for user2@% +GRANT USAGE ON *.* TO 'user2'@'%' +GRANT SELECT (a), INSERT (b) ON `temp`.`t1` TO 'user2'@'%' +# Connect as the renamed user +SHOW GRANTS; +Grants for user2@% +GRANT USAGE ON *.* TO 'user2'@'%' +GRANT SELECT (a), INSERT (b) ON `temp`.`t1` TO 'user2'@'%' +SELECT a FROM temp.t1; +a +1 +2 +3 +# Check for additional privileges by accessing a +# non privileged column. We shouldn't be able to +# access this column. +SELECT b FROM temp.t1; +ERROR 42000: SELECT command denied to user 'user2'@'localhost' for column 'b' in table 't1' +DROP USER 'user2'@'%'; +DROP DATABASE temp; End of 5.0 tests diff --git a/mysql-test/r/grant_lowercase_fs.result b/mysql-test/r/grant_lowercase_fs.result new file mode 100644 index 00000000000..5a3087ed5cd --- /dev/null +++ b/mysql-test/r/grant_lowercase_fs.result @@ -0,0 +1,16 @@ +create database db1; +GRANT CREATE ON db1.* to user_1@localhost; +GRANT SELECT ON db1.* to USER_1@localhost; +CREATE TABLE t1(f1 int); +SELECT * FROM t1; +ERROR 42000: SELECT command denied to user 'user_1'@'localhost' for table 't1' +SELECT * FROM t1; +f1 +CREATE TABLE t2(f1 int); +ERROR 42000: CREATE command denied to user 'USER_1'@'localhost' for table 't2' +REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM USER_1@localhost; +DROP USER user_1@localhost; +DROP USER USER_1@localhost; +DROP DATABASE db1; +use test; diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result index d2e8eb19e0c..a40a13dbe9f 100644 --- a/mysql-test/r/innodb-autoinc.result +++ b/mysql-test/r/innodb-autoinc.result @@ -867,6 +867,7 @@ INSERT INTO t2 SELECT NULL FROM t1; Got one of the listed errors DROP TABLE t1; DROP TABLE t2; +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; INSERT INTO t1 VALUES (null); INSERT INTO t1 VALUES (null); @@ -882,6 +883,12 @@ d1 INSERT INTO t1 VALUES(null); Got one of the listed errors ALTER TABLE t1 AUTO_INCREMENT = 3; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `d1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`d1`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 INSERT INTO t1 VALUES(null); SELECT * FROM t1; d1 @@ -889,3 +896,233 @@ d1 3 4 DROP TABLE t1; +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; +SHOW VARIABLES LIKE "%auto_inc%"; +Variable_name Value +auto_increment_increment 1 +auto_increment_offset 1 +CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-127, 'innodb'); +INSERT INTO t1 VALUES (NULL, 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=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-127 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-127, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` tinyint(3) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 SMALLINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-32767, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` smallint(6) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-32767 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-32757, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` smallint(5) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 MEDIUMINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-8388607, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` mediumint(9) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-8388607 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 MEDIUMINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-8388607, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-2147483647, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-2147483647 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-2147483647, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` int(10) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 BIGINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-9223372036854775807, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` bigint(20) NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +-9223372036854775807 innodb +-1 innodb +1 NULL +2 NULL +DROP TABLE t1; +CREATE TABLE t1 (c1 BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (-9223372036854775807, 'innodb'); +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `c2` varchar(10) DEFAULT NULL, + PRIMARY KEY (`c1`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 +SELECT * FROM t1; +c1 c2 +1 NULL +2 innodb +3 innodb +4 NULL +DROP TABLE t1; +CREATE TABLE T1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) AUTO_INCREMENT=10 ENGINE=InnoDB; +CREATE INDEX i1 on T1(c2); +SHOW CREATE TABLE T1; +Table Create Table +T1 CREATE TABLE `T1` ( + `c1` int(11) NOT NULL AUTO_INCREMENT, + `c2` int(11) DEFAULT NULL, + PRIMARY KEY (`c1`), + KEY `i1` (`c2`) +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1 +INSERT INTO T1 (c2) values (0); +SELECT * FROM T1; +c1 c2 +10 0 +DROP TABLE T1; diff --git a/mysql-test/r/innodb_bug44369.result b/mysql-test/r/innodb_bug44369.result index e4b84ecac19..9cf79aeffab 100644 --- a/mysql-test/r/innodb_bug44369.result +++ b/mysql-test/r/innodb_bug44369.result @@ -2,13 +2,13 @@ create table bug44369 (DB_ROW_ID int) engine=innodb; ERROR HY000: Can't create table 'test.bug44369' (errno: -1) create table bug44369 (db_row_id int) engine=innodb; ERROR HY000: Can't create table 'test.bug44369' (errno: -1) -show errors; +show warnings; Level Code Message -Error 1005 Error creating table 'test/bug44369' with column name 'db_row_id'. 'db_row_id' is a reserved name. Please try to re-create the table with a different column name. +Warning 1005 Error creating table 'test/bug44369' with column name 'db_row_id'. 'db_row_id' is a reserved name. Please try to re-create the table with a different column name. Error 1005 Can't create table 'test.bug44369' (errno: -1) create table bug44369 (db_TRX_Id int) engine=innodb; ERROR HY000: Can't create table 'test.bug44369' (errno: -1) -show errors; +show warnings; Level Code Message -Error 1005 Error creating table 'test/bug44369' with column name 'db_TRX_Id'. 'db_TRX_Id' is a reserved name. Please try to re-create the table with a different column name. +Warning 1005 Error creating table 'test/bug44369' with column name 'db_TRX_Id'. 'db_TRX_Id' is a reserved name. Please try to re-create the table with a different column name. Error 1005 Can't create table 'test.bug44369' (errno: -1) diff --git a/mysql-test/r/innodb_bug46000.result b/mysql-test/r/innodb_bug46000.result index ccff888a48d..ccf7cc56859 100644 --- a/mysql-test/r/innodb_bug46000.result +++ b/mysql-test/r/innodb_bug46000.result @@ -2,16 +2,16 @@ create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb; ERROR HY000: Can't create table 'test.bug46000' (errno: -1) create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb; ERROR HY000: Can't create table 'test.bug46000' (errno: -1) -show errors; +show warnings; Level Code Message -Error 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index. +Warning 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index. Error 1005 Can't create table 'test.bug46000' (errno: -1) create table bug46000(id int) engine=innodb; create index GEN_CLUST_INDEX on bug46000(id); ERROR HY000: Can't create table '#sql-temporary' (errno: -1) -show errors; +show warnings; Level Code Message -Error 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index. +Warning 1005 Cannot Create Index with name 'GEN_CLUST_INDEX'. The name is reserved for the system default primary index. Error 1005 Can't create table '#sql-temporary' (errno: -1) create index idx on bug46000(id); drop table bug46000; diff --git a/mysql-test/r/innodb_bug47777.result b/mysql-test/r/innodb_bug47777.result new file mode 100644 index 00000000000..fbba47edcfc --- /dev/null +++ b/mysql-test/r/innodb_bug47777.result @@ -0,0 +1,13 @@ +create table bug47777(c2 linestring not null, primary key (c2(1))) engine=innodb; +insert into bug47777 values (geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)')); +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); +count(*) +1 +update bug47777 set c2=GeomFromText('POINT(1 1)'); +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); +count(*) +0 +select count(*) from bug47777 where c2 = GeomFromText('POINT(1 1)'); +count(*) +1 +drop table bug47777; diff --git a/mysql-test/r/innodb_lock_wait_timeout_1.result b/mysql-test/r/innodb_lock_wait_timeout_1.result new file mode 100644 index 00000000000..a635b0d527a --- /dev/null +++ b/mysql-test/r/innodb_lock_wait_timeout_1.result @@ -0,0 +1,357 @@ +# +# Bug #40113: Embedded SELECT inside UPDATE or DELETE can timeout +# without error +# +CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)) ENGINE=InnoDB; +INSERT INTO t1 (a,b) VALUES (1070109,99); +CREATE TABLE t2 (b int, a int, PRIMARY KEY (b)) ENGINE=InnoDB; +INSERT INTO t2 (b,a) VALUES (7,1070109); +SELECT * FROM t1; +a b +1070109 99 +BEGIN; +SELECT b FROM t2 WHERE b=7 FOR UPDATE; +b +7 +BEGIN; +SELECT b FROM t2 WHERE b=7 FOR UPDATE; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +INSERT INTO t1 (a) VALUES ((SELECT a FROM t2 WHERE b=7)); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +UPDATE t1 SET a='7000000' WHERE a=(SELECT a FROM t2 WHERE b=7); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +DELETE FROM t1 WHERE a=(SELECT a FROM t2 WHERE b=7); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SELECT * FROM t1; +a b +1070109 99 +DROP TABLE t2, t1; +# End of 5.0 tests +# +# Bug#46539 Various crashes on INSERT IGNORE SELECT + SELECT +# FOR UPDATE +# +drop table if exists t1; +create table t1 (a int primary key auto_increment, +b int, index(b)) engine=innodb; +insert into t1 (b) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +set autocommit=0; +begin; +select * from t1 where b=5 for update; +a b +5 5 +insert ignore into t1 (b) select a as b from t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +# Cleanup +# +commit; +set autocommit=default; +drop table t1; +# +# Bug#41756 Strange error messages about locks from InnoDB +# +drop table if exists t1; +# In the default transaction isolation mode, and/or with +# innodb_locks_unsafe_for_binlog=OFF, handler::unlock_row() +# in InnoDB does nothing. +# Thus in order to reproduce the condition that led to the +# warning, one needs to relax isolation by either +# setting a weaker tx_isolation value, or by turning on +# the unsafe replication switch. +# For testing purposes, choose to tweak the isolation level, +# since it's settable at runtime, unlike +# innodb_locks_unsafe_for_binlog, which is +# only a command-line switch. +# +set @@session.tx_isolation="read-committed"; +# Prepare data. We need a table with a unique index, +# for join_read_key to be used. The other column +# allows to control what passes WHERE clause filter. +create table t1 (a int primary key, b int) engine=innodb; +# Let's make sure t1 has sufficient amount of rows +# to exclude JT_ALL access method when reading it, +# i.e. make sure that JT_EQ_REF(a) is always preferred. +insert into t1 values (1,1), (2,null), (3,1), (4,1), +(5,1), (6,1), (7,1), (8,1), (9,1), (10,1), +(11,1), (12,1), (13,1), (14,1), (15,1), +(16,1), (17,1), (18,1), (19,1), (20,1); +# +# Demonstrate that for the SELECT statement +# used later in the test JT_EQ_REF access method is used. +# +explain +select 1 from t1 natural join (select 2 as a, 1 as b union all +select 2 as a, 2 as b) as t2 for update; +id 1 +select_type PRIMARY +table +type ALL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows 2 +Extra +id 1 +select_type PRIMARY +table t1 +type eq_ref +possible_keys PRIMARY +key PRIMARY +key_len 4 +ref t2.a +rows 1 +Extra Using where +id 2 +select_type DERIVED +table NULL +type NULL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra No tables used +id 3 +select_type UNION +table NULL +type NULL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra No tables used +id NULL +select_type UNION RESULT +table +type ALL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra +# +# Demonstrate that the reported SELECT statement +# no longer produces warnings. +# +select 1 from t1 natural join (select 2 as a, 1 as b union all +select 2 as a, 2 as b) as t2 for update; +1 +commit; +# +# Demonstrate that due to lack of inter-sweep "reset" function, +# we keep some non-matching records locked, even though we know +# we could unlock them. +# To do that, show that if there is only one distinct value +# for a in t2 (a=2), we will keep record (2,null) in t1 locked. +# But if we add another value for "a" to t2, say 6, +# join_read_key cache will be pruned at least once, +# and thus record (2, null) in t1 will get unlocked. +# +begin; +select 1 from t1 natural join (select 2 as a, 1 as b union all +select 2 as a, 2 as b) as t2 for update; +1 +# +# Switching to connection con1 +# We should be able to delete all records from t1 except (2, null), +# since they were not locked. +begin; +# Delete in series of 3 records so that full scan +# is not used and we're not blocked on record (2,null) +delete from t1 where a in (1,3,4); +delete from t1 where a in (5,6,7); +delete from t1 where a in (8,9,10); +delete from t1 where a in (11,12,13); +delete from t1 where a in (14,15,16); +delete from t1 where a in (17,18); +delete from t1 where a in (19,20); +# +# Record (2, null) is locked. This is actually unnecessary, +# because the previous select returned no rows. +# Just demonstrate the effect. +# +delete from t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +rollback; +# +# Switching to connection default +# +# Show that the original contents of t1 is intact: +select * from t1; +a b +1 1 +2 NULL +3 1 +4 1 +5 1 +6 1 +7 1 +8 1 +9 1 +10 1 +11 1 +12 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +commit; +# +# Have a one more record in t2 to show that +# if join_read_key cache is purned, the current +# row under the cursor is unlocked (provided, this row didn't +# match the partial WHERE clause, of course). +# Sic: the result of this test dependent on the order of retrieval +# of records --echo # from the derived table, if ! +# We use DELETE to disable the JOIN CACHE. This DELETE modifies no +# records. It also should leave no InnoDB row locks. +# +begin; +delete t1.* from t1 natural join (select 2 as a, 2 as b union all +select 0 as a, 0 as b) as t2; +# Demonstrate that nothing was deleted form t1 +select * from t1; +a b +1 1 +2 NULL +3 1 +4 1 +5 1 +6 1 +7 1 +8 1 +9 1 +10 1 +11 1 +12 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +# +# Switching to connection con1 +begin; +# Since there is another distinct record in the derived table +# the previous matching record in t1 -- (2,null) -- was unlocked. +delete from t1; +# We will need the contents of the table again. +rollback; +select * from t1; +a b +1 1 +2 NULL +3 1 +4 1 +5 1 +6 1 +7 1 +8 1 +9 1 +10 1 +11 1 +12 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +commit; +# +# Switching to connection default +rollback; +begin; +# +# Before this patch, we could wrongly unlock a record +# that was cached and later used in a join. Demonstrate that +# this is no longer the case. +# Sic: this test is also order-dependent (i.e. the +# the bug would show up only if the first record in the union +# is retreived and processed first. +# +# Verify that JT_EQ_REF is used. +explain +select 1 from t1 natural join (select 3 as a, 2 as b union all +select 3 as a, 1 as b) as t2 for update; +id 1 +select_type PRIMARY +table +type ALL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows 2 +Extra +id 1 +select_type PRIMARY +table t1 +type eq_ref +possible_keys PRIMARY +key PRIMARY +key_len 4 +ref t2.a +rows 1 +Extra Using where +id 2 +select_type DERIVED +table NULL +type NULL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra No tables used +id 3 +select_type UNION +table NULL +type NULL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra No tables used +id NULL +select_type UNION RESULT +table +type ALL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra +# Lock the record. +select 1 from t1 natural join (select 3 as a, 2 as b union all +select 3 as a, 1 as b) as t2 for update; +1 +1 +# Switching to connection con1 +# +# We should not be able to delete record (3,1) from t1, +# (previously it was possible). +# +delete from t1 where a=3; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +# Switching to connection default +commit; +set @@session.tx_isolation=default; +drop table t1; +# +# End of 5.1 tests +# diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index b112bde4f27..c882d2af1ed 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -2209,4 +2209,46 @@ EXPLAIN SELECT * FROM t1 FORCE INDEX(PRIMARY) WHERE b=1 AND c=1 ORDER BY a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL PRIMARY 4 NULL 128 Using where DROP TABLE t1; +# +# Bug #47963: Wrong results when index is used +# +CREATE TABLE t1( +a VARCHAR(5) NOT NULL, +b VARCHAR(5) NOT NULL, +c DATETIME NOT NULL, +KEY (c) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES('TEST', 'TEST', '2009-10-09 00:00:00'); +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00.0'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00.0'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.000' AND c <= '2009-10-09 00:00:00.000'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.00' AND c <= '2009-10-09 00:00:00.001'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; +a b c +EXPLAIN SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 77f73532474..baabf48cb2f 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -1063,6 +1063,60 @@ a b c d 127 NULL 127 NULL 128 NULL 128 NULL DROP TABLE IF EXISTS t1,t2; +# +# Bug #42116: Mysql crash on specific query +# +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT); +CREATE TABLE t3 (a INT, INDEX (a)); +CREATE TABLE t4 (a INT); +CREATE TABLE t5 (a INT); +CREATE TABLE t6 (a INT); +INSERT INTO t1 VALUES (1), (1), (1); +INSERT INTO t2 VALUES +(2), (2), (2), (2), (2), (2), (2), (2), (2), (2); +INSERT INTO t3 VALUES +(3), (3), (3), (3), (3), (3), (3), (3), (3), (3); +EXPLAIN +SELECT * +FROM +t1 JOIN t2 ON t1.a = t2.a +LEFT JOIN +( +( +t3 LEFT JOIN t4 ON t3.a = t4.a +) +LEFT JOIN +( +t5 LEFT JOIN t6 ON t5.a = t6.a +) +ON t4.a = t5.a +) +ON t1.a = t3.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t3 ref a a 5 test.t1.a 2 Using index +1 SIMPLE t4 ALL NULL NULL NULL NULL 0 +1 SIMPLE t5 ALL NULL NULL NULL NULL 0 +1 SIMPLE t6 ALL NULL NULL NULL NULL 0 +1 SIMPLE t2 ALL NULL NULL NULL NULL 10 Using where; Using join buffer +SELECT * +FROM +t1 JOIN t2 ON t1.a = t2.a +LEFT JOIN +( +( +t3 LEFT JOIN t4 ON t3.a = t4.a +) +LEFT JOIN +( +t5 LEFT JOIN t6 ON t5.a = t6.a +) +ON t4.a = t5.a +) +ON t1.a = t3.a; +a a a a a a +DROP TABLE t1,t2,t3,t4,t5,t6; End of 5.0 tests. CREATE TABLE t1 (f1 int); CREATE TABLE t2 (f1 int); diff --git a/mysql-test/r/locale.result b/mysql-test/r/locale.result new file mode 100644 index 00000000000..89883b070d2 --- /dev/null +++ b/mysql-test/r/locale.result @@ -0,0 +1,29 @@ +DROP TABLE IF EXISTS t1; +Start of 5.4 tests +# +# Bug#43207 wrong LC_TIME names for romanian locale +# +SET NAMES utf8; +SET lc_time_names=ro_RO; +SELECT DATE_FORMAT('2001-01-01', '%w %a %W'); +DATE_FORMAT('2001-01-01', '%w %a %W') +1 Lu Luni +SELECT DATE_FORMAT('2001-01-02', '%w %a %W'); +DATE_FORMAT('2001-01-02', '%w %a %W') +2 Ma Marţi +SELECT DATE_FORMAT('2001-01-03', '%w %a %W'); +DATE_FORMAT('2001-01-03', '%w %a %W') +3 Mi Miercuri +SELECT DATE_FORMAT('2001-01-04', '%w %a %W'); +DATE_FORMAT('2001-01-04', '%w %a %W') +4 Jo Joi +SELECT DATE_FORMAT('2001-01-05', '%w %a %W'); +DATE_FORMAT('2001-01-05', '%w %a %W') +5 Vi Vineri +SELECT DATE_FORMAT('2001-01-06', '%w %a %W'); +DATE_FORMAT('2001-01-06', '%w %a %W') +6 Sâ Sâmbătă +SELECT DATE_FORMAT('2001-01-07', '%w %a %W'); +DATE_FORMAT('2001-01-07', '%w %a %W') +0 Du Duminică +End of 5.4 tests diff --git a/mysql-test/r/lowercase_fs_off.result b/mysql-test/r/lowercase_fs_off.result index ecb21261987..4a59801692d 100644 --- a/mysql-test/r/lowercase_fs_off.result +++ b/mysql-test/r/lowercase_fs_off.result @@ -10,3 +10,48 @@ create database D1; ERROR 42000: Access denied for user 'sample'@'localhost' to database 'D1' drop user 'sample'@'localhost'; drop database if exists d1; +CREATE DATABASE d1; +USE d1; +CREATE TABLE T1(f1 INT); +CREATE TABLE t1(f1 INT); +GRANT SELECT ON T1 to user_1@localhost; +select * from t1; +ERROR 42000: SELECT command denied to user 'user_1'@'localhost' for table 't1' +select * from T1; +f1 +GRANT SELECT ON t1 to user_1@localhost; +select * from information_schema.table_privileges; +GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE +'user_1'@'localhost' NULL d1 T1 SELECT NO +'user_1'@'localhost' NULL d1 t1 SELECT NO +REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost; +DROP USER user_1@localhost; +DROP DATABASE d1; +USE test; +CREATE DATABASE db1; +USE db1; +CREATE PROCEDURE p1() BEGIN END; +CREATE FUNCTION f1(i INT) RETURNS INT RETURN i+1; +GRANT USAGE ON db1.* to user_1@localhost; +GRANT EXECUTE ON PROCEDURE db1.P1 to user_1@localhost; +GRANT EXECUTE ON FUNCTION db1.f1 to user_1@localhost; +GRANT UPDATE ON db1.* to USER_1@localhost; +call p1(); +call P1(); +select f1(1); +f1(1) +2 +call p1(); +ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.p1' +call P1(); +ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.p1' +select f1(1); +ERROR 42000: execute command denied to user 'USER_1'@'localhost' for routine 'db1.f1' +REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM USER_1@localhost; +DROP FUNCTION f1; +DROP PROCEDURE p1; +DROP USER user_1@localhost; +DROP USER USER_1@localhost; +DROP DATABASE db1; +use test; diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index f5050ccf1c0..95fdc4fb93d 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -2290,6 +2290,12 @@ Table Op Msg_type Msg_text test.t1 repair error myisam_sort_buffer_size is too small test.t1 repair warning Number of rows changed from 0 to 7168 test.t1 repair status OK +SET myisam_repair_threads=2; +REPAIR TABLE t1; +SET myisam_repair_threads=@@global.myisam_repair_threads; SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size; +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/r/myisam_crash_before_flush_keys.result b/mysql-test/r/myisam_crash_before_flush_keys.result index 372f2e41590..d3545ea47d0 100644 --- a/mysql-test/r/myisam_crash_before_flush_keys.result +++ b/mysql-test/r/myisam_crash_before_flush_keys.result @@ -15,31 +15,13 @@ SET SESSION debug="d,crash_before_flush_keys"; # Run the crashing query FLUSH TABLE t1; ERROR HY000: Lost connection to MySQL server during query -# Run MYISAMCHK tool to check the table t1 and repair -myisamchk: MyISAM file MYSQLD_DATADIR/test/t1 -myisamchk: warning: 1 client is using or hasn't closed the table properly -myisamchk: error: Size of indexfile is: 1024 Should be: 3072 -MYISAMCHK: Unknown error 126 -myisamchk: error: Can't read indexpage from filepos: 1024 -MyISAM-table 'MYSQLD_DATADIR/test/t1' is corrupted -Fix it using switch "-r" or "-o" # Write file to make mysql-test-run.pl start the server # Turn on reconnect # Call script that will poll the server waiting for # it to be back online again -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `a` int(11) NOT NULL DEFAULT '0', - `b` int(11) NOT NULL DEFAULT '0', - PRIMARY KEY (`a`,`b`), - KEY `b` (`b`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 DELAY_KEY_WRITE=1 -SELECT * FROM t1 FORCE INDEX (PRIMARY); -a b -1 2 -2 3 -3 4 -4 5 -5 6 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check warning 1 client is using or hasn't closed the table properly +test.t1 check error Size of indexfile is: 1024 Should be: 3072 +test.t1 check error Corrupt DROP TABLE t1; diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index 4540c9d5218..a7516d97888 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -733,4 +733,24 @@ SELECT 1 FROM t1 GROUP BY (DATE(NULL)) WITH ROLLUP; 1 1 DROP TABLE t1; +# +# Bug #48131: crash group by with rollup, distinct, +# filesort, with temporary tables +# +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY); +INSERT INTO t1 VALUES (1), (2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (100); +SELECT a, b FROM t1, t2 GROUP BY a, b WITH ROLLUP; +a b +1 100 +1 NULL +2 100 +2 NULL +NULL NULL +SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP; +b +100 +NULL +DROP TABLE t1, t2; End of 5.0 tests diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result index 769d499fc0a..3128c57b2cf 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -1272,10 +1272,9 @@ INSERT INTO t1 VALUES (1, '2009-01-01'), (2, NULL); # test with an invalid date, which lead to item->null_value is set. EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-99' AS DATETIME); id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p20090401 ALL NULL NULL NULL NULL 2 Using where +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables Warnings: Warning 1292 Incorrect datetime value: '2009-04-99' -Warning 1292 Incorrect datetime value: '2009-04-99' DROP TABLE t1; CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, diff --git a/mysql-test/r/ps_grant.result b/mysql-test/r/ps_grant.result index 8b16123ccea..672db74d9c0 100644 --- a/mysql-test/r/ps_grant.result +++ b/mysql-test/r/ps_grant.result @@ -32,19 +32,19 @@ identified by 'looser' ; show grants for second_user@localhost ; Grants for second_user@localhost GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3' -GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' +GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' drop table mysqltest.t9 ; show grants for second_user@localhost ; Grants for second_user@localhost GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3' -GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' +GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' show grants for second_user@localhost ; Grants for second_user@localhost GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3' -GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' +GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' prepare s_t1 from 'select a as my_col from t1' ; execute s_t1 ; my_col diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 6cabc24d0eb..2817bec2198 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -1708,6 +1708,7 @@ Qcache_hits 2 DROP TABLE t1; SET GLOBAL query_cache_size= default; End of 5.0 tests +SET GLOBAL query_cache_size=1024*1024*512; CREATE TABLE t1 (a ENUM('rainbow')); INSERT INTO t1 VALUES (),(),(),(),(); SELECT 1 FROM t1 GROUP BY (SELECT 1 FROM t1 ORDER BY AVG(LAST_INSERT_ID())); @@ -1722,4 +1723,5 @@ SELECT 1 FROM t1 GROUP BY 1 1 DROP TABLE t1; +SET GLOBAL query_cache_size= default; End of 5.1 tests diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index c98a7696ea6..2306f8b501e 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -1398,3 +1398,209 @@ a < 10; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t3 range a a 5 NULL 8 Using where; Using index DROP TABLE t1, t2, t3; +# +# Bug #47123: Endless 100% CPU loop with STRAIGHT_JOIN +# +CREATE TABLE t1(a INT, KEY(a)); +INSERT INTO t1 VALUES (1), (NULL); +SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL); +a +DROP TABLE t1; +# +# Bug#47925: regression of range optimizer and date comparison in 5.1.39! +# +CREATE TABLE t1 ( a DATE, KEY ( a ) ); +CREATE TABLE t2 ( a DATETIME, KEY ( a ) ); +# Make optimizer choose range scan +INSERT INTO t1 VALUES ('2009-09-22'), ('2009-09-22'), ('2009-09-22'); +INSERT INTO t1 VALUES ('2009-09-23'), ('2009-09-23'), ('2009-09-23'); +INSERT INTO t2 VALUES ('2009-09-22 12:00:00'), ('2009-09-22 12:00:00'), +('2009-09-22 12:00:00'); +INSERT INTO t2 VALUES ('2009-09-23 12:00:00'), ('2009-09-23 12:00:00'), +('2009-09-23 12:00:00'); +# DATE vs DATE +EXPLAIN +SELECT * FROM t1 WHERE a >= '2009/09/23'; +id select_type table type possible_keys key key_len ref rows Extra +X X X range a a X X X X +SELECT * FROM t1 WHERE a >= '2009/09/23'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '20090923'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= 20090923; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009-9-23'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009.09.23'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009:09:23'; +a +2009-09-23 +2009-09-23 +2009-09-23 +# DATE vs DATETIME +EXPLAIN +SELECT * FROM t2 WHERE a >= '2009/09/23'; +id select_type table type possible_keys key key_len ref rows Extra +X X X range a a X X X X +SELECT * FROM t2 WHERE a >= '2009/09/23'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009/09/23'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '20090923'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= 20090923; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009-9-23'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009.09.23'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009:09:23'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +# DATETIME vs DATETIME +EXPLAIN +SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +X X X range a a X X X X +SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '20090923120000'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= 20090923120000; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009-9-23 12:00:00'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009.09.23 12:00:00'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +SELECT * FROM t2 WHERE a >= '2009:09:23 12:00:00'; +a +2009-09-23 12:00:00 +2009-09-23 12:00:00 +2009-09-23 12:00:00 +# DATETIME vs DATE +EXPLAIN +SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00'; +id select_type table type possible_keys key key_len ref rows Extra +X X X range a a X X X X +SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '20090923000000'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= 20090923000000; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009-9-23 00:00:00'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009.09.23 00:00:00'; +a +2009-09-23 +2009-09-23 +2009-09-23 +SELECT * FROM t1 WHERE a >= '2009:09:23 00:00:00'; +a +2009-09-23 +2009-09-23 +2009-09-23 +# Test of the new get_date_from_str implementation +# Behavior differs slightly between the trunk and mysql-pe. +# The former may give errors for the truncated values, while the latter +# gives warnings. The purpose of this test is not to interfere, and only +# preserve existing behavior. +SELECT str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND +str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20'; +str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND +str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20' +1 +Warnings: +Warning 1292 Truncated incorrect date value: '' +SELECT str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND +str_to_date('2007-20-00', '%Y-%m-%d') <= ''; +str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND +str_to_date('2007-20-00', '%Y-%m-%d') <= '' +NULL +Warnings: +Warning 1292 Truncated incorrect date value: '' +Error 1411 Incorrect datetime value: '2007-20-00' for function str_to_date +Error 1411 Incorrect datetime value: '2007-20-00' for function str_to_date +SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'; +str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20' +1 +Warnings: +Warning 1292 Truncated incorrect datetime value: '' +SELECT str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND ''; +str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND '' +NULL +Warnings: +Error 1411 Incorrect datetime value: '2007-20-00' for function str_to_date +SELECT str_to_date('', '%Y-%m-%d'); +str_to_date('', '%Y-%m-%d') +0000-00-00 +DROP TABLE t1, t2; +End of 5.1 tests diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 50b5c3c13fb..1b615233a14 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4386,6 +4386,47 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = `test`.`t1`.`b`) and (`test`.`t1`.`a` > 1)) limit 2 DROP TABLE t1; +# +# Bug#47019: Assertion failed: 0, file .\rt_mbr.c, line 138 when +# forcing a spatial index +# +CREATE TABLE t1(a LINESTRING NOT NULL, SPATIAL KEY(a)); +INSERT INTO t1 VALUES +(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')), +(GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')); +EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 +1 SIMPLE t2 ALL a NULL NULL NULL 2 +SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2; +1 +1 +1 +1 +1 +EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 +1 SIMPLE t2 ALL a NULL NULL NULL 2 +SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a); +1 +1 +1 +1 +1 +DROP TABLE t1; +# +# Bug #48291 : crash with row() operator,select into @var, and +# subquery returning multiple rows +# +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (2),(3); +# Should not crash +SELECT 1 FROM t1 WHERE a <> 1 AND NOT +ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1)) +INTO @var0; +ERROR 21000: Subquery returns more than 1 row +DROP TABLE t1; End of 5.0 tests create table t1(a INT, KEY (a)); INSERT INTO t1 VALUES (1),(2),(3),(4),(5); diff --git a/mysql-test/r/sp-bugs.result b/mysql-test/r/sp-bugs.result new file mode 100644 index 00000000000..14c5311bbe5 --- /dev/null +++ b/mysql-test/r/sp-bugs.result @@ -0,0 +1,47 @@ +# +# Bug #47412: Valgrind warnings / user can read uninitalized memory +# using SP variables +# +CREATE SCHEMA testdb; +USE testdb; +CREATE FUNCTION f2 () RETURNS INTEGER +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1; +RETURN f_not_exists () ; +END| +CREATE PROCEDURE p3 ( arg1 VARCHAR(32) ) +BEGIN +CALL p_not_exists ( ); +END| +# should not return valgrind warnings +CALL p3 ( f2 () ); +ERROR 42000: PROCEDURE testdb.p_not_exists does not exist +DROP SCHEMA testdb; +CREATE SCHEMA testdb; +USE testdb; +CREATE FUNCTION f2 () RETURNS INTEGER +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1; +RETURN f_not_exists () ; +END| +CREATE PROCEDURE p3 ( arg2 INTEGER ) +BEGIN +CALL p_not_exists ( ); +END| +# should not return valgrind warnings +CALL p3 ( f2 () ); +ERROR 42000: PROCEDURE testdb.p_not_exists does not exist +DROP SCHEMA testdb; +CREATE SCHEMA testdb; +USE testdb; +CREATE FUNCTION f2 () RETURNS INTEGER +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1; +RETURN f_not_exists () ; +END| +# should not return valgrind warnings +SELECT f2 (); +f2 () +NULL +DROP SCHEMA testdb; +End of 5.1 tests diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 8a8cbd751a0..ef51f5e37fb 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1652,3 +1652,19 @@ NULL SELECT non_existent (a) FROM t1 WHERE b = 999999; ERROR 42000: FUNCTION test.non_existent does not exist DROP TABLE t1; +# +# Bug #47788: Crash in TABLE_LIST::hide_view_error on UPDATE + VIEW + +# SP + MERGE + ALTER +# +CREATE TABLE t1 (pk INT, b INT, KEY (b)); +CREATE ALGORITHM = TEMPTABLE VIEW v1 AS SELECT * FROM t1; +CREATE PROCEDURE p1 (a int) UPDATE IGNORE v1 SET b = a; +CALL p1(5); +ERROR HY000: The target table v1 of the UPDATE is not updatable +ALTER TABLE t1 CHANGE COLUMN b b2 INT; +CALL p1(7); +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +DROP PROCEDURE p1; +DROP VIEW v1; +DROP TABLE t1; +End of 5.1 tests diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index c60ac9790c5..665473df3ef 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -75,7 +75,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a)); select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1)); ERROR HY000: Incorrect usage of PROCEDURE and subquery SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1)); -ERROR HY000: Incorrect usage of PROCEDURE and subquery +ERROR HY000: Incorrect parameters to procedure 'ANALYSE' SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL; ERROR 42S22: Unknown column 'a' in 'field list' SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL; @@ -4403,8 +4403,7 @@ FROM t1 WHERE a = 230; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables -2 DEPENDENT SUBQUERY st1 index NULL a 5 NULL 2 Using index -2 DEPENDENT SUBQUERY st2 index b b 5 NULL 2 Using where; Using index; Using join buffer +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) FROM t1 WHERE a = 230; @@ -4564,4 +4563,18 @@ id g v s 51 50 NULL l 61 60 NULL l drop table t1, t2; +CREATE TABLE t1 (a ENUM('rainbow')); +INSERT INTO t1 VALUES (),(),(),(),(); +SELECT 1 FROM t1 GROUP BY (SELECT 1 FROM t1 ORDER BY AVG(LAST_INSERT_ID())); +1 +1 +DROP TABLE t1; +CREATE TABLE t1 (a LONGBLOB); +INSERT INTO t1 SET a = 'aaaa'; +INSERT INTO t1 SET a = 'aaaa'; +SELECT 1 FROM t1 GROUP BY +(SELECT LAST_INSERT_ID() FROM t1 ORDER BY MIN(a) ASC LIMIT 1); +1 +1 +DROP TABLE t1; End of 5.1 tests. diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result index f055b40116a..d5fb1a7bbde 100644 --- a/mysql-test/r/subselect3.result +++ b/mysql-test/r/subselect3.result @@ -895,3 +895,72 @@ t1.a < (select t4.a+10 from t4, t5 limit 2)); ERROR 21000: Subquery returns more than 1 row drop table t0, t1, t2, t3, t4, t5; +# +# BUG#48177 - SELECTs with NOT IN subqueries containing NULL +# values return too many records +# +CREATE TABLE t1 ( +i1 int DEFAULT NULL, +i2 int DEFAULT NULL +) ; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (2, 3); +INSERT INTO t1 VALUES (4, NULL); +INSERT INTO t1 VALUES (4, 0); +INSERT INTO t1 VALUES (NULL, NULL); +CREATE TABLE t2 ( +i1 int DEFAULT NULL, +i2 int DEFAULT NULL +) ; +INSERT INTO t2 VALUES (4, NULL); +INSERT INTO t2 VALUES (5, 0); + +Data in t1 +SELECT i1, i2 FROM t1; +i1 i2 +1 NULL +2 3 +4 NULL +4 0 +NULL NULL + +Data in subquery (should be filtered out) +SELECT i1, i2 FROM t2 ORDER BY i1; +i1 i2 +4 NULL +5 0 +FLUSH STATUS; + +SELECT i1, i2 +FROM t1 +WHERE (i1, i2) +NOT IN (SELECT i1, i2 FROM t2); +i1 i2 +1 NULL +2 3 + +# Check that the subquery only has to be evaluated once +# for all-NULL values even though there are two (NULL,NULL) records +# Baseline: +SHOW STATUS LIKE '%Handler_read_rnd_next'; +Variable_name Value +Handler_read_rnd_next 17 + +INSERT INTO t1 VALUES (NULL, NULL); +FLUSH STATUS; + +SELECT i1, i2 +FROM t1 +WHERE (i1, i2) +NOT IN (SELECT i1, i2 FROM t2); +i1 i2 +1 NULL +2 3 + +# Handler_read_rnd_next should be one more than baseline +# (read record from t1, but do not read from t2) +SHOW STATUS LIKE '%Handler_read_rnd_next'; +Variable_name Value +Handler_read_rnd_next 18 +DROP TABLE t1,t2; +End of 5.1 tests diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index e252331cd1a..17fd95ab1c8 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -161,7 +161,7 @@ procs_priv CREATE TABLE `procs_priv` ( `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', `Db` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', `User` char(16) COLLATE utf8_bin NOT NULL DEFAULT '', - `Routine_name` char(64) COLLATE utf8_bin NOT NULL DEFAULT '', + `Routine_name` char(64) CHARACTER SET utf8 NOT NULL DEFAULT '', `Routine_type` enum('FUNCTION','PROCEDURE') COLLATE utf8_bin NOT NULL, `Grantor` char(77) COLLATE utf8_bin NOT NULL DEFAULT '', `Proc_priv` set('Execute','Alter Routine','Grant') CHARACTER SET utf8 NOT NULL DEFAULT '', diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index c3d1e400b23..748aadee4fb 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1495,9 +1495,9 @@ CREATE TABLE t1 (a int DEFAULT NULL, b int DEFAULT NULL); INSERT INTO t1 VALUES (3,30), (1,10), (2,10); SELECT a+CAST(1 AS decimal(65,30)) AS aa, SUM(b) FROM t1 GROUP BY aa; aa SUM(b) -2.00000000000000000000000000000 10 -3.00000000000000000000000000000 10 -4.00000000000000000000000000000 30 +2.000000000000000000000000000000 10 +3.000000000000000000000000000000 10 +4.000000000000000000000000000000 30 SELECT a+CAST(1 AS decimal(65,31)) AS aa, SUM(b) FROM t1 GROUP BY aa; ERROR 42000: Too big scale 31 specified for column '1'. Maximum is 30. DROP TABLE t1; @@ -1521,13 +1521,13 @@ f1 DROP TABLE t1; CREATE TABLE t1 SELECT 123451234512345123451234512345123451234512345.678906789067890678906789067890678906789067890 AS f1; Warnings: -Note 1265 Data truncated for column 'f1' at row 1 +Warning 1264 Out of range value for column 'f1' at row 1 DESC t1; Field Type Null Key Default Extra -f1 decimal(65,20) NO 0.00000000000000000000 +f1 decimal(65,30) NO 0.000000000000000000000000000000 SELECT f1 FROM t1; f1 -123451234512345123451234512345123451234512345.67890678906789067891 +99999999999999999999999999999999999.999999999999999999999999999999 DROP TABLE t1; select (1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 * 1.01500000 * 1.01500000 * 0.99500000); @@ -1595,7 +1595,7 @@ Warnings: Note 1265 Data truncated for column 'my_col' at row 1 DESCRIBE t1; Field Type Null Key Default Extra -my_col decimal(32,30) NO 0.000000000000000000000000000000 +my_col decimal(65,30) NO 0.000000000000000000000000000000 SELECT my_col FROM t1; my_col 1.123456789123456789123456789123 @@ -1625,212 +1625,8 @@ Warnings: Note 1265 Data truncated for column 'my_col' at row 1 DESCRIBE t1; Field Type Null Key Default Extra -my_col decimal(30,30) YES NULL +my_col decimal(65,30) YES NULL SELECT my_col FROM t1; my_col 0.012345687012345687012345687012 DROP TABLE t1; -# -# Bug#45261: Crash, stored procedure + decimal -# -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 SELECT -/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001 -AS c1; -Warnings: -Warning 1264 Out of range value for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,0) NO 0 -SELECT * FROM t1; -c1 -99999999999999999999999999999999999999999999999999999999999999999 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001. -AS c1; -Warnings: -Warning 1264 Out of range value for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,0) NO 0 -SELECT * FROM t1; -c1 -99999999999999999999999999999999999999999999999999999999999999999 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */ -AS c1; -Warnings: -Warning 1264 Out of range value for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,0) NO 0 -SELECT * FROM t1; -c1 -99999999999999999999999999999999999999999999999999999999999999999 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001 -AS c1; -Warnings: -Error 1292 Truncated incorrect DECIMAL value: '' -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,0) NO 0 -SELECT * FROM t1; -c1 -99999999999999999999999999999999999999999999999999999999999999999 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */ -AS c1; -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,25) NO 0.0000000000000000000000000 -SELECT * FROM t1; -c1 -1000000000000000000000000000000000000001.1000000000000000000000000 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */ -AS c1; -DESC t1; -Field Type Null Key Default Extra -c1 decimal(31,30) NO 0.000000000000000000000000000000 -SELECT * FROM t1; -c1 -1.100000000000000000000000000000 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ -AS c1; -DESC t1; -Field Type Null Key Default Extra -c1 decimal(31,30) NO 0.000000000000000000000000000000 -SELECT * FROM t1; -c1 -1.100000000000000000000000000000 -DROP TABLE t1; -CREATE TABLE t1 SELECT -.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ -AS c1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(30,30) NO 0.000000000000000000000000000000 -SELECT * FROM t1; -c1 -0.100000000000000000000000000000 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */ -AS c1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,20) NO 0.00000000000000000000 -SELECT * FROM t1; -c1 -123456789012345678901234567890123456789012345.12345678901234567890 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */ -AS c1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,0) NO 0 -SELECT * FROM t1; -c1 -12345678901234567890123456789012345678901234567890123456789012345 -DROP TABLE t1; -CREATE TABLE t1 SELECT -/* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */ -AS c1; -Warnings: -Warning 1264 Out of range value for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,0) NO 0 -SELECT * FROM t1; -c1 -99999999999999999999999999999999999999999999999999999999999999999 -DROP TABLE t1; -CREATE TABLE t1 SELECT -.123456789012345678901234567890123456789012345678901234567890123456 /* 66 */ -AS c1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(30,30) NO 0.000000000000000000000000000000 -SELECT * FROM t1; -c1 -0.123456789012345678901234567890 -DROP TABLE t1; -CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -DESC t1; -Field Type Null Key Default Extra -c1 decimal(33,30) NO 0.000000000000000000000000000000 -SELECT * FROM t1; -c1 -123.123456789012345678901234567890 -DROP TABLE t1; -CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1; -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,29) NO 0.00000000000000000000000000000 -SELECT * FROM t1; -c1 -2.10000000000000000000000000000 -DROP TABLE t1; -# -# Test that the integer and decimal parts are properly calculated. -# -CREATE TABLE t1 (a DECIMAL(30,30)); -INSERT INTO t1 VALUES (0.1),(0.2),(0.3); -CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 3 -DESC t2; -Field Type Null Key Default Extra -c1 decimal(32,30) YES NULL -DROP TABLE t1,t2; -CREATE TABLE t1 (a DECIMAL(30,30)); -INSERT INTO t1 VALUES (0.1),(0.2),(0.3); -CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -Note 1265 Data truncated for column 'c1' at row 2 -Note 1265 Data truncated for column 'c1' at row 3 -DESC t2; -Field Type Null Key Default Extra -c1 decimal(32,30) YES NULL -DROP TABLE t1,t2; -CREATE TABLE t1 (a DECIMAL(30,30)); -INSERT INTO t1 VALUES (0.1),(0.2),(0.3); -CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1; -Warnings: -Note 1265 Data truncated for column 'c1' at row 1 -DESC t2; -Field Type Null Key Default Extra -c1 decimal(31,30) YES NULL -DROP TABLE t1,t2; -# -# Test that variables get maximum precision. -# -SET @decimal= 1.1; -CREATE TABLE t1 SELECT @decimal AS c1; -DESC t1; -Field Type Null Key Default Extra -c1 decimal(65,30) YES NULL -SELECT * FROM t1; -c1 -1.100000000000000000000000000000 -DROP TABLE t1; diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 7a51649fac5..d859579e835 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -503,3 +503,14 @@ ERROR HY000: Recursive stored functions and triggers are not allowed. DROP TABLE t1; DROP FUNCTION f1; End of 5.0 tests +# +# Bug #47919 assert in open_table during ALTER temporary table +# +CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT, PRIMARY KEY (f1)); +CREATE TEMPORARY TABLE t2 LIKE t1; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +ALTER TABLE t2 COMMENT = 'ABC'; +UPDATE t2, t1 SET t2.f1 = 2, t1.f1 = 9; +ALTER TABLE t2 COMMENT = 'DEF'; +DROP TABLE t1, t2; diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index a9d4164cda4..83cacc315d8 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -1218,3 +1218,22 @@ Warnings: Note 1449 The user specified as a definer ('no_such_user'@'no_such_host') does not exist DROP TABLE t1; DROP VIEW v1; +# +# Bug #46019: ERROR 1356 When selecting from within another +# view that has Group By +# +CREATE DATABASE mysqltest1; +USE mysqltest1; +CREATE TABLE t1 (a INT); +CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT a FROM t1 GROUP BY a; +CREATE SQL SECURITY INVOKER VIEW v2 AS SELECT a FROM v1; +CREATE USER mysqluser1; +GRANT SELECT ON TABLE t1 TO mysqluser1; +GRANT SELECT, SHOW VIEW ON TABLE v1 TO mysqluser1; +GRANT SELECT, SHOW VIEW ON TABLE v2 TO mysqluser1; +SELECT a FROM v1; +a +SELECT a FROM v2; +a +DROP USER mysqluser1; +DROP DATABASE mysqltest1; diff --git a/mysql-test/r/xa.result b/mysql-test/r/xa.result index a597806d897..d23c8e672b0 100644 --- a/mysql-test/r/xa.result +++ b/mysql-test/r/xa.result @@ -89,3 +89,28 @@ xa start 'a'; xa end 'a'; xa prepare 'a'; xa commit 'a'; +CREATE TABLE t1(a INT, KEY(a)) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1),(2); +BEGIN; +UPDATE t1 SET a=3 WHERE a=1; +BEGIN; +UPDATE t1 SET a=4 WHERE a=2; +UPDATE t1 SET a=5 WHERE a=2; +UPDATE t1 SET a=5 WHERE a=1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +ROLLBACK; +ROLLBACK; +BEGIN; +UPDATE t1 SET a=3 WHERE a=1; +XA START 'xid1'; +UPDATE t1 SET a=4 WHERE a=2; +UPDATE t1 SET a=5 WHERE a=2; +UPDATE t1 SET a=5 WHERE a=1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +XA END 'xid1'; +ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected +XA ROLLBACK 'xid1'; +XA START 'xid1'; +XA END 'xid1'; +XA ROLLBACK 'xid1'; +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/r/binlog_delete_and_flush_index.result b/mysql-test/suite/binlog/r/binlog_delete_and_flush_index.result new file mode 100644 index 00000000000..036ccf131bb --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_delete_and_flush_index.result @@ -0,0 +1,50 @@ +RESET MASTER; +CREATE TABLE t1 (a int); +### assertion: index file contains regular entries +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000001 + +### assertion: show original binlogs +show binary logs; +Log_name File_size +master-bin.000001 # +### assertion: binlog contents from regular entries +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a int) +FLUSH LOGS; +### assertion: index file contains renamed binlog and the new one +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin-b34582.000001 +master-bin.000002 + +### assertion: original binlog content still exists, despite we +### renamed and changed the index file +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin-b34582.000001 # Query # # use `test`; CREATE TABLE t1 (a int) +### assertion: user changed binlog index shows correct entries +show binary logs; +Log_name File_size +master-bin-b34582.000001 # +master-bin.000002 # +DROP TABLE t1; +### assertion: purging binlogs up to binlog created after instrumenting index file should work +PURGE BINARY LOGS TO 'master-bin.000002'; +### assertion: show binary logs should only contain latest binlog +show binary logs; +Log_name File_size +master-bin.000002 # +### assertion: assert that binlog files were indeed purged (using file_exists calls) +### assertion: assert that not purged binlog file exists +### assertion: show index file contents and these should match show binary logs issued above +SET @index=LOAD_FILE('MYSQLTEST_VARDIR/mysqld.1/data//master-bin.index'); +SELECT @index; +@index +master-bin.000002 + +RESET MASTER; diff --git a/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result b/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result index 0a6ff1d4400..75c088e595d 100644 --- a/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result +++ b/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result @@ -19,6 +19,7 @@ DROP TABLE IF EXISTS tmp2, t; SELECT GET_LOCK("a",10); GET_LOCK("a",10) 1 +USE test; SELECT GET_LOCK("a",10); GET_LOCK("a",10) 1 diff --git a/mysql-test/suite/binlog/r/binlog_stm_do_db.result b/mysql-test/suite/binlog/r/binlog_stm_do_db.result new file mode 100644 index 00000000000..ab4ba7cdca1 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_stm_do_db.result @@ -0,0 +1,42 @@ +SET @old_isolation_level= @@session.tx_isolation; +SET @@session.tx_isolation= 'READ-COMMITTED'; +CREATE DATABASE b42829; +use b42829; +CREATE TABLE t1 (x int, y int) engine=InnoDB; +CREATE TABLE t2 (x int, y int) engine=InnoDB; +CREATE DATABASE b42829_filtered; +use b42829_filtered; +CREATE TABLE t1 (x int, y int) engine=InnoDB; +CREATE TABLE t2 (x int, y int) engine=InnoDB; +SET @@session.sql_log_bin= 0; +INSERT INTO b42829_filtered.t1 VALUES (100,100); +INSERT INTO b42829.t1 VALUES (100,100); +SET @@session.sql_log_bin= 1; +### assertion: the inserts will not raise log error because +### binlog-do-db is filtering used database +INSERT INTO t2 VALUES (1,2), (1,3), (1,4); +INSERT INTO t1 SELECT * FROM t2; +### assertion: assert that despite updating a not filtered +### database this wont trigger an error as the +### used database is the filtered one. +UPDATE b42829_filtered.t1 ft1, b42829.t1 nft1 SET ft1.x=1, nft1.x=2; +use b42829; +### assertion: the statements *will* raise log error because +### binlog-do-db is not filtering used database +BEGIN; +INSERT INTO t2 VALUES (1,2), (1,3), (1,4); +ERROR HY000: Binary logging not possible. Message: Transaction level 'READ-COMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT' +UPDATE b42829_filtered.t1 ft1, b42829.t1 nft1 SET ft1.x=1, nft1.x=2; +ERROR HY000: Binary logging not possible. Message: Transaction level 'READ-COMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT' +INSERT INTO t1 SELECT * FROM t2; +ERROR HY000: Binary logging not possible. Message: Transaction level 'READ-COMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT' +COMMIT; +### assertion: filtered events did not make into the binlog +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # CREATE DATABASE b42829 +master-bin.000001 # Query # # use `b42829`; CREATE TABLE t1 (x int, y int) engine=InnoDB +master-bin.000001 # Query # # use `b42829`; CREATE TABLE t2 (x int, y int) engine=InnoDB +DROP DATABASE b42829; +DROP DATABASE b42829_filtered; +SET @@session.tx_isolation= @old_isolation_level; diff --git a/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result b/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result index 8bbf1bccc63..19ddcf49080 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result +++ b/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result @@ -19,6 +19,7 @@ DROP TABLE IF EXISTS tmp2, t; SELECT GET_LOCK("a",10); GET_LOCK("a",10) 1 +USE test; SELECT GET_LOCK("a",10); GET_LOCK("a",10) 1 diff --git a/mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test b/mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test new file mode 100644 index 00000000000..84c83687486 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_delete_and_flush_index.test @@ -0,0 +1,114 @@ +# BUG#34582: FLUSH LOGS does not close and reopen the binlog index +# file +# +# WHAT +# ==== +# +# We want to test that FLUSH LOGS closes and reopens binlog index +# file. +# +# HOW +# === +# +# PREPARE: +# 1. create some binlog events +# 2. show index content, binlog events and binlog contents +# for mysql-bin.000001 +# 3. copy the mysql-bin.000001 to mysql-bin-b34582.000001 +# 4. change the index file so that mysql-bin.000001 is replaced +# with mysql-bin-b34582.000001 +# 5. FLUSH the logs so that new index is closed and reopened +# +# ASSERTIONS: +# 1. index file contents shows mysql-bin-b34582.000001 and +# mysql-bin.000002 +# 1. show binary logs shows current index entries +# 2. binlog contents for mysql-bin-b34582.000001 are displayed +# 3. Purge binlogs up to the latest one succeeds +# 4. SHOW BINARY LOGS presents the latest one only after purging +# 5. Purged binlogs files don't exist in the filesystem +# 6. Not purged binlog file exists in the filesystem +# +# CLEAN UP: +# 1. RESET MASTER +# + +-- source include/have_log_bin.inc + +RESET MASTER; + +-- let $datadir= `SELECT @@datadir` +-- let $index=$datadir/master-bin.index +-- chmod 0644 $index + +# action: issue one command so that binlog gets some event +CREATE TABLE t1 (a int); + +-- echo ### assertion: index file contains regular entries +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +--echo ### assertion: show original binlogs +-- source include/show_binary_logs.inc + +--echo ### assertion: binlog contents from regular entries +-- source include/show_binlog_events.inc + +# action: copy binlogs to other names and change entries in index file +-- copy_file $datadir/master-bin.000001 $datadir/master-bin-b34582.000001 +let INDEX_FILE=$index; +perl; +$file= $ENV{'INDEX_FILE'}; +open(FILE, ">$file") || die "Unable to open $file."; +truncate(FILE,0); +close ($file); +EOF + +-- append_file $index +master-bin-b34582.000001 +EOF + +# action: should cause rotation, and creation of new binlogs +FLUSH LOGS; + +# file is not used anymore - remove it (mysql closed on flush logs). +-- remove_file $datadir/master-bin.000001 + +-- echo ### assertion: index file contains renamed binlog and the new one +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +-- echo ### assertion: original binlog content still exists, despite we +-- echo ### renamed and changed the index file +-- source include/show_binlog_events.inc + +-- echo ### assertion: user changed binlog index shows correct entries +-- source include/show_binary_logs.inc + +DROP TABLE t1; + +-- echo ### assertion: purging binlogs up to binlog created after instrumenting index file should work +-- let $current_binlog= query_get_value(SHOW MASTER STATUS, File, 1) +-- eval PURGE BINARY LOGS TO '$current_binlog' + +-- echo ### assertion: show binary logs should only contain latest binlog +-- source include/show_binary_logs.inc + +-- echo ### assertion: assert that binlog files were indeed purged (using file_exists calls) +-- error 1 +-- file_exists $datadir/master-bin-b34852.000001 + +-- echo ### assertion: assert that not purged binlog file exists +-- file_exists $datadir/$current_binlog + +-- echo ### assertion: show index file contents and these should match show binary logs issued above +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +-- eval SET @index=LOAD_FILE('$index') +-- replace_regex /\.[\\\/]master/master/ +SELECT @index; + +RESET MASTER; diff --git a/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt b/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt new file mode 100644 index 00000000000..e2cfcb299cf --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_do_db-master.opt @@ -0,0 +1 @@ +--binlog-do-db=b42829 diff --git a/mysql-test/suite/binlog/t/binlog_stm_do_db.test b/mysql-test/suite/binlog/t/binlog_stm_do_db.test new file mode 100644 index 00000000000..858bc8cc683 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_do_db.test @@ -0,0 +1,90 @@ +# BUG#42829: binlogging enabled for all schemas regardless of +# binlog-db-db / binlog-ignore-db +# +# WHAT +# ==== +# +# We want to test whether filtered events from binlog will cause +# raising an error mentioning that statement is unable to be logged or +# not, when: +# +# 1. isolation level READ-COMMITTED; AND +# +# 2. using InnoDB engine; AND +# +# 3. using SBL (in which case InnoDB will only allow RBL). +# +# HOW +# === +# +# The test is implemented as follows: +# +# i) set tx_isolation to read-committed. +# +# ii) create two databases (one filtered other not - using +# binlog-do-db) +# +# iii) Create statements that are to be filtered on filtered db +# +# - At this point, before fix, an error would be raised +# +# iv) do the same thing for not the filtered database and check +# that events throw an error: +# +# - Error: ER_BINLOG_STMT_MODE_AND_ROW_ENGINE +# + +-- source include/have_log_bin.inc +-- source include/have_innodb.inc +-- source include/have_binlog_format_statement.inc + +SET @old_isolation_level= @@session.tx_isolation; +SET @@session.tx_isolation= 'READ-COMMITTED'; + +-- let $engine= InnoDB +-- let $filtered= b42829_filtered +-- let $not_filtered= b42829 + +-- eval CREATE DATABASE $not_filtered +-- eval use $not_filtered +-- eval CREATE TABLE t1 (x int, y int) engine=$engine +-- eval CREATE TABLE t2 (x int, y int) engine=$engine + +-- eval CREATE DATABASE $filtered +-- eval use $filtered +-- eval CREATE TABLE t1 (x int, y int) engine=$engine +-- eval CREATE TABLE t2 (x int, y int) engine=$engine + +SET @@session.sql_log_bin= 0; +-- eval INSERT INTO $filtered.t1 VALUES (100,100) +-- eval INSERT INTO $not_filtered.t1 VALUES (100,100) +SET @@session.sql_log_bin= 1; + +-- echo ### assertion: the inserts will not raise log error because +-- echo ### binlog-do-db is filtering used database +INSERT INTO t2 VALUES (1,2), (1,3), (1,4); +INSERT INTO t1 SELECT * FROM t2; + +-- echo ### assertion: assert that despite updating a not filtered +-- echo ### database this wont trigger an error as the +-- echo ### used database is the filtered one. +-- eval UPDATE $filtered.t1 ft1, $not_filtered.t1 nft1 SET ft1.x=1, nft1.x=2 + +-- eval use $not_filtered +-- echo ### assertion: the statements *will* raise log error because +-- echo ### binlog-do-db is not filtering used database +BEGIN; +-- error ER_BINLOG_LOGGING_IMPOSSIBLE +INSERT INTO t2 VALUES (1,2), (1,3), (1,4); +-- error ER_BINLOG_LOGGING_IMPOSSIBLE +-- eval UPDATE $filtered.t1 ft1, $not_filtered.t1 nft1 SET ft1.x=1, nft1.x=2 +-- error ER_BINLOG_LOGGING_IMPOSSIBLE +INSERT INTO t1 SELECT * FROM t2; +COMMIT; + +-- echo ### assertion: filtered events did not make into the binlog +source include/show_binlog_events.inc; + +-- eval DROP DATABASE $not_filtered +-- eval DROP DATABASE $filtered +SET @@session.tx_isolation= @old_isolation_level; diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index 2f1f61c0525..98eeacdb74c 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -130,7 +130,7 @@ NULL mysql procs_priv Db 2 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI NULL mysql procs_priv Grantor 6 NO char 77 231 NULL NULL utf8 utf8_bin char(77) MUL select,insert,update,references NULL mysql procs_priv Host 1 NO char 60 180 NULL NULL utf8 utf8_bin char(60) PRI select,insert,update,references NULL mysql procs_priv Proc_priv 7 NO set 27 81 NULL NULL utf8 utf8_general_ci set('Execute','Alter Routine','Grant') select,insert,update,references -NULL mysql procs_priv Routine_name 4 NO char 64 192 NULL NULL utf8 utf8_bin char(64) PRI select,insert,update,references +NULL mysql procs_priv Routine_name 4 NO char 64 192 NULL NULL utf8 utf8_general_ci char(64) PRI select,insert,update,references NULL mysql procs_priv Routine_type 5 NULL NO enum 9 27 NULL NULL utf8 utf8_bin enum('FUNCTION','PROCEDURE') PRI select,insert,update,references NULL mysql procs_priv Timestamp 8 CURRENT_TIMESTAMP NO timestamp NULL NULL NULL NULL NULL NULL timestamp on update CURRENT_TIMESTAMP select,insert,update,references NULL mysql procs_priv User 3 NO char 16 48 NULL NULL utf8 utf8_bin char(16) PRI select,insert,update,references @@ -411,7 +411,7 @@ NULL mysql proc modified timestamp NULL NULL NULL NULL timestamp 3.0000 mysql procs_priv Host char 60 180 utf8 utf8_bin char(60) 3.0000 mysql procs_priv Db char 64 192 utf8 utf8_bin char(64) 3.0000 mysql procs_priv User char 16 48 utf8 utf8_bin char(16) -3.0000 mysql procs_priv Routine_name char 64 192 utf8 utf8_bin char(64) +3.0000 mysql procs_priv Routine_name char 64 192 utf8 utf8_general_ci char(64) 3.0000 mysql procs_priv Routine_type enum 9 27 utf8 utf8_bin enum('FUNCTION','PROCEDURE') 3.0000 mysql procs_priv Grantor char 77 231 utf8 utf8_bin char(77) 3.0000 mysql procs_priv Proc_priv set 27 81 utf8 utf8_general_ci set('Execute','Alter Routine','Grant') diff --git a/mysql-test/suite/funcs_1/r/is_statistics.result b/mysql-test/suite/funcs_1/r/is_statistics.result index 989fd9dc4e6..8452536d4ed 100644 --- a/mysql-test/suite/funcs_1/r/is_statistics.result +++ b/mysql-test/suite/funcs_1/r/is_statistics.result @@ -166,8 +166,8 @@ NULL db_datadict_2 t4 0 db_datadict_2 PRIMARY 1 f1 NULL 0 NULL NULL HASH SHOW GRANTS FOR 'testuser1'@'localhost'; Grants for testuser1@localhost GRANT USAGE ON *.* TO 'testuser1'@'localhost' -GRANT SELECT (f5, f1) ON `db_datadict_2`.`t3` TO 'testuser1'@'localhost' GRANT SELECT ON `db_datadict`.`t1` TO 'testuser1'@'localhost' WITH GRANT OPTION +GRANT SELECT (f5, f1) ON `db_datadict_2`.`t3` TO 'testuser1'@'localhost' SHOW GRANTS FOR 'testuser2'@'localhost'; Grants for testuser2@localhost GRANT USAGE ON *.* TO 'testuser2'@'localhost' @@ -185,8 +185,8 @@ NULL db_datadict_2 t3 0 db_datadict_2 PRIMARY 1 f1 NULL 0 NULL NULL HASH SHOW GRANTS FOR 'testuser1'@'localhost'; Grants for testuser1@localhost GRANT USAGE ON *.* TO 'testuser1'@'localhost' -GRANT SELECT (f5, f1) ON `db_datadict_2`.`t3` TO 'testuser1'@'localhost' GRANT SELECT ON `db_datadict`.`t1` TO 'testuser1'@'localhost' WITH GRANT OPTION +GRANT SELECT (f5, f1) ON `db_datadict_2`.`t3` TO 'testuser1'@'localhost' SHOW GRANTS FOR 'testuser2'@'localhost'; ERROR 42000: Access denied for user 'testuser1'@'localhost' to database 'mysql' # Switch to connection testuser2 diff --git a/mysql-test/suite/innodb/r/innodb-zip.result b/mysql-test/suite/innodb/r/innodb-zip.result index b26c4112826..21396d81ba8 100644 --- a/mysql-test/suite/innodb/r/innodb-zip.result +++ b/mysql-test/suite/innodb/r/innodb-zip.result @@ -196,15 +196,15 @@ drop table t1; set innodb_strict_mode = on; create table t1 (id int primary key) engine = innodb key_block_size = 0; ERROR HY000: Can't create table 'test.t1' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 0. Valid values are [1, 2, 4, 8, 16] +Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 0. Valid values are [1, 2, 4, 8, 16] Error 1005 Can't create table 'test.t1' (errno: 1478) create table t2 (id int primary key) engine = innodb key_block_size = 9; ERROR HY000: Can't create table 'test.t2' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] +Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] Error 1005 Can't create table 'test.t2' (errno: 1478) create table t3 (id int primary key) engine = innodb key_block_size = 1; create table t4 (id int primary key) engine = innodb key_block_size = 2; @@ -233,30 +233,30 @@ key_block_size = 8 row_format = compressed; create table t2 (id int primary key) engine = innodb key_block_size = 8 row_format = redundant; ERROR HY000: Can't create table 'test.t2' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t2' (errno: 1478) create table t3 (id int primary key) engine = innodb key_block_size = 8 row_format = compact; ERROR HY000: Can't create table 'test.t3' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t3' (errno: 1478) create table t4 (id int primary key) engine = innodb key_block_size = 8 row_format = dynamic; ERROR HY000: Can't create table 'test.t4' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t4' (errno: 1478) create table t5 (id int primary key) engine = innodb key_block_size = 8 row_format = default; ERROR HY000: Can't create table 'test.t5' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t5' (errno: 1478) SELECT table_schema, table_name, row_format FROM information_schema.tables WHERE engine='innodb'; @@ -266,26 +266,26 @@ drop table t1; create table t1 (id int primary key) engine = innodb key_block_size = 9 row_format = redundant; ERROR HY000: Can't create table 'test.t1' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] -Error 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] +Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t1' (errno: 1478) create table t2 (id int primary key) engine = innodb key_block_size = 9 row_format = compact; ERROR HY000: Can't create table 'test.t2' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] -Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] +Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t2' (errno: 1478) create table t2 (id int primary key) engine = innodb key_block_size = 9 row_format = dynamic; ERROR HY000: Can't create table 'test.t2' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] -Error 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE. +Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] +Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE. Error 1005 Can't create table 'test.t2' (errno: 1478) SELECT table_schema, table_name, row_format FROM information_schema.tables WHERE engine='innodb'; @@ -293,45 +293,45 @@ table_schema table_name row_format set global innodb_file_per_table = off; create table t1 (id int primary key) engine = innodb key_block_size = 1; ERROR HY000: Can't create table 'test.t1' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. Error 1005 Can't create table 'test.t1' (errno: 1478) create table t2 (id int primary key) engine = innodb key_block_size = 2; ERROR HY000: Can't create table 'test.t2' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. Error 1005 Can't create table 'test.t2' (errno: 1478) create table t3 (id int primary key) engine = innodb key_block_size = 4; ERROR HY000: Can't create table 'test.t3' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. Error 1005 Can't create table 'test.t3' (errno: 1478) create table t4 (id int primary key) engine = innodb key_block_size = 8; ERROR HY000: Can't create table 'test.t4' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. Error 1005 Can't create table 'test.t4' (errno: 1478) create table t5 (id int primary key) engine = innodb key_block_size = 16; ERROR HY000: Can't create table 'test.t5' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. Error 1005 Can't create table 'test.t5' (errno: 1478) create table t6 (id int primary key) engine = innodb row_format = compressed; ERROR HY000: Can't create table 'test.t6' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table. Error 1005 Can't create table 'test.t6' (errno: 1478) create table t7 (id int primary key) engine = innodb row_format = dynamic; ERROR HY000: Can't create table 'test.t7' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table. +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table. Error 1005 Can't create table 'test.t7' (errno: 1478) create table t8 (id int primary key) engine = innodb row_format = compact; create table t9 (id int primary key) engine = innodb row_format = redundant; @@ -345,45 +345,45 @@ set global innodb_file_per_table = on; set global innodb_file_format = `0`; create table t1 (id int primary key) engine = innodb key_block_size = 1; ERROR HY000: Can't create table 'test.t1' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t1' (errno: 1478) create table t2 (id int primary key) engine = innodb key_block_size = 2; ERROR HY000: Can't create table 'test.t2' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t2' (errno: 1478) create table t3 (id int primary key) engine = innodb key_block_size = 4; ERROR HY000: Can't create table 'test.t3' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t3' (errno: 1478) create table t4 (id int primary key) engine = innodb key_block_size = 8; ERROR HY000: Can't create table 'test.t4' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t4' (errno: 1478) create table t5 (id int primary key) engine = innodb key_block_size = 16; ERROR HY000: Can't create table 'test.t5' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t5' (errno: 1478) create table t6 (id int primary key) engine = innodb row_format = compressed; ERROR HY000: Can't create table 'test.t6' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t6' (errno: 1478) create table t7 (id int primary key) engine = innodb row_format = dynamic; ERROR HY000: Can't create table 'test.t7' (errno: 1478) -show errors; +show warnings; Level Code Message -Error 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. Error 1005 Can't create table 'test.t7' (errno: 1478) create table t8 (id int primary key) engine = innodb row_format = compact; create table t9 (id int primary key) engine = innodb row_format = redundant; diff --git a/mysql-test/suite/innodb/t/disabled.def b/mysql-test/suite/innodb/t/disabled.def index 176963df340..baf8c89f539 100644 --- a/mysql-test/suite/innodb/t/disabled.def +++ b/mysql-test/suite/innodb/t/disabled.def @@ -1,2 +1 @@ innodb-index: InnoDB: Error: table `test`.`t1#1` already exists in InnoDB internal -innodb_information_schema: Bug #47808 joro : innodb_information_schema.test fails when run under valgrind diff --git a/mysql-test/suite/innodb/t/innodb-zip.test b/mysql-test/suite/innodb/t/innodb-zip.test index 09320570546..c27392ac4fa 100644 --- a/mysql-test/suite/innodb/t/innodb-zip.test +++ b/mysql-test/suite/innodb/t/innodb-zip.test @@ -175,11 +175,11 @@ set innodb_strict_mode = on; --error ER_CANT_CREATE_TABLE create table t1 (id int primary key) engine = innodb key_block_size = 0; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t2 (id int primary key) engine = innodb key_block_size = 9; -show errors; +show warnings; create table t3 (id int primary key) engine = innodb key_block_size = 1; @@ -205,22 +205,22 @@ key_block_size = 8 row_format = compressed; --error ER_CANT_CREATE_TABLE create table t2 (id int primary key) engine = innodb key_block_size = 8 row_format = redundant; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t3 (id int primary key) engine = innodb key_block_size = 8 row_format = compact; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t4 (id int primary key) engine = innodb key_block_size = 8 row_format = dynamic; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t5 (id int primary key) engine = innodb key_block_size = 8 row_format = default; -show errors; +show warnings; SELECT table_schema, table_name, row_format FROM information_schema.tables WHERE engine='innodb'; @@ -230,17 +230,17 @@ drop table t1; --error ER_CANT_CREATE_TABLE create table t1 (id int primary key) engine = innodb key_block_size = 9 row_format = redundant; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t2 (id int primary key) engine = innodb key_block_size = 9 row_format = compact; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t2 (id int primary key) engine = innodb key_block_size = 9 row_format = dynamic; -show errors; +show warnings; SELECT table_schema, table_name, row_format FROM information_schema.tables WHERE engine='innodb'; @@ -250,25 +250,25 @@ set global innodb_file_per_table = off; --error ER_CANT_CREATE_TABLE create table t1 (id int primary key) engine = innodb key_block_size = 1; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t2 (id int primary key) engine = innodb key_block_size = 2; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t3 (id int primary key) engine = innodb key_block_size = 4; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t4 (id int primary key) engine = innodb key_block_size = 8; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t5 (id int primary key) engine = innodb key_block_size = 16; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t6 (id int primary key) engine = innodb row_format = compressed; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t7 (id int primary key) engine = innodb row_format = dynamic; -show errors; +show warnings; create table t8 (id int primary key) engine = innodb row_format = compact; create table t9 (id int primary key) engine = innodb row_format = redundant; @@ -282,25 +282,25 @@ set global innodb_file_format = `0`; --error ER_CANT_CREATE_TABLE create table t1 (id int primary key) engine = innodb key_block_size = 1; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t2 (id int primary key) engine = innodb key_block_size = 2; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t3 (id int primary key) engine = innodb key_block_size = 4; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t4 (id int primary key) engine = innodb key_block_size = 8; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t5 (id int primary key) engine = innodb key_block_size = 16; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t6 (id int primary key) engine = innodb row_format = compressed; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table t7 (id int primary key) engine = innodb row_format = dynamic; -show errors; +show warnings; create table t8 (id int primary key) engine = innodb row_format = compact; create table t9 (id int primary key) engine = innodb row_format = redundant; diff --git a/mysql-test/suite/innodb/t/innodb_information_schema.test b/mysql-test/suite/innodb/t/innodb_information_schema.test index df65139448c..599215e9ca4 100644 --- a/mysql-test/suite/innodb/t/innodb_information_schema.test +++ b/mysql-test/suite/innodb/t/innodb_information_schema.test @@ -110,14 +110,18 @@ SELECT * FROM ```t'\"_str` WHERE c1 = '3' FOR UPDATE; -- send SELECT * FROM ```t'\"_str` WHERE c1 = '4' FOR UPDATE; -# Give time to the above 2 queries to execute before continuing. -# Without this sleep it sometimes happens that the SELECT from innodb_locks -# executes before some of them, resulting in less than expected number -# of rows being selected from innodb_locks. --- sleep 0.1 - -- enable_result_log -- connection con_verify_innodb_locks +# Wait for the above queries to execute before continuing. +# Without this, it sometimes happens that the SELECT from innodb_locks +# executes before some of them, resulting in less than expected number +# of rows being selected from innodb_locks. If there is a bug and there +# are no 14 rows in innodb_locks then this test will fail with timeout. +let $count = 14; +let $table = INFORMATION_SCHEMA.INNODB_LOCKS; +-- source include/wait_until_rows_count.inc +# the above enables the query log, re-disable it +-- disable_query_log SELECT lock_mode, lock_type, lock_table, lock_index, lock_rec, lock_data FROM INFORMATION_SCHEMA.INNODB_LOCKS ORDER BY lock_data; diff --git a/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result b/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result index ae3554a5420..5f2a55b5e35 100644 --- a/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result +++ b/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result @@ -4,8 +4,10 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -call mtr.add_suppression("Slave I/O: .* failed with error: Lost connection to MySQL server at 'reading initial communication packet'"); +call mtr.add_suppression("Get master clock failed with error: "); +call mtr.add_suppression("Get master SERVER_ID failed with error: "); call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again"); +call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*"); SELECT IS_FREE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP"); IS_FREE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP") 1 diff --git a/mysql-test/suite/rpl/r/rpl_loaddata.result b/mysql-test/suite/rpl/r/rpl_loaddata.result index 4c6fd43da13..4e81d90a970 100644 --- a/mysql-test/suite/rpl/r/rpl_loaddata.result +++ b/mysql-test/suite/rpl/r/rpl_loaddata.result @@ -200,3 +200,32 @@ CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB; LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1; ERROR 23000: Duplicate entry 'Aarhus' for key 'PRIMARY' DROP TABLE IF EXISTS t1; +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +drop database if exists b48297_db1; +drop database if exists b42897_db2; +create database b48297_db1; +create database b42897_db2; +use b48297_db1; +CREATE TABLE t1 (c1 VARCHAR(256)) engine=MyISAM;; +use b42897_db2; +### assertion: works with cross-referenced database +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +use b48297_db1; +### assertion: works with fully qualified name on current database +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +### assertion: works without fully qualified name on current database +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1; +### create connection without default database +### connect (conn2,localhost,root,,*NO-ONE*); +### assertion: works without stating the default database +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +### disconnect and switch back to master connection +use b48297_db1; +Comparing tables master:b48297_db1.t1 and slave:b48297_db1.t1 +DROP DATABASE b48297_db1; +DROP DATABASE b42897_db2; diff --git a/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test b/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test index 4a6741a2db6..a955de02c0f 100644 --- a/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test +++ b/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test @@ -46,7 +46,7 @@ kill @id; drop table t2,t3; insert into t4 values (3),(4); connection master; ---error 0,1053,2013 +--error 0,1317,2013 reap; connection master1; sync_slave_with_master; diff --git a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt new file mode 100644 index 00000000000..f9aa8c0367e --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock-slave.opt @@ -0,0 +1 @@ +--master-retry-count=60 diff --git a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test index a391b1f5344..69c63eaa69f 100644 --- a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test +++ b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test @@ -16,8 +16,10 @@ source include/master-slave.inc; source include/have_debug.inc; -call mtr.add_suppression("Slave I/O: .* failed with error: Lost connection to MySQL server at 'reading initial communication packet'"); +call mtr.add_suppression("Get master clock failed with error: "); +call mtr.add_suppression("Get master SERVER_ID failed with error: "); call mtr.add_suppression("Slave I/O: Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again"); +call mtr.add_suppression("Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; .*"); #Test case 1: Try to get the value of the UNIX_TIMESTAMP from master under network disconnection connection slave; let $debug_saved= `select @@global.debug`; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 17549745203..5534aa0a234 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -1046,4 +1046,19 @@ ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6','a7','a8','a9', --disable_info DROP TABLE t1; +# +# Bug#43508: Renaming timestamp or date column triggers table copy +# + +CREATE TABLE t1 (f1 TIMESTAMP NULL DEFAULT NULL, + f2 INT(11) DEFAULT NULL) ENGINE=MYISAM DEFAULT CHARSET=utf8; + +INSERT INTO t1 VALUES (NULL, NULL), ("2009-10-09 11:46:19", 2); + +--echo this should affect no rows as there is no real change +--enable_info +ALTER TABLE t1 CHANGE COLUMN f1 f1_no_real_change TIMESTAMP NULL DEFAULT NULL; +--disable_info +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test index d8466df14bf..05f739bfd69 100644 --- a/mysql-test/t/analyse.test +++ b/mysql-test/t/analyse.test @@ -10,36 +10,13 @@ insert into t1 values (1,2,"","Y","2002-03-03"), (3,4,"","N","2002-03-04"), (5,6 select count(*) from t1 procedure analyse(); select * from t1 procedure analyse(); select * from t1 procedure analyse(2); +--error ER_WRONG_USAGE create table t2 select * from t1 procedure analyse(); -select * from t2; -drop table t1,t2; +drop table t1; --error ER_WRONG_USAGE EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(); -# -# Test with impossible where -# -create table t1 (a int not null); -create table t2 select * from t1 where 0=1 procedure analyse(); -show create table t2; -select * from t1 where 0=1 procedure analyse(); -insert into t1 values(1); -drop table t2; -create table t2 select * from t1 where 0=1 procedure analyse(); -show create table t2; -select * from t2; -insert into t2 select * from t1 procedure analyse(); -select * from t2; -insert into t1 values(2); -drop table t2; -create table t2 select * from t1 where 0=1 procedure analyse(); -show create table t2; -select * from t2; -insert into t2 select * from t1 procedure analyse(); -select * from t2; -drop table t1,t2; - # # Bug#2813 - analyse does not quote string values in enums from string # @@ -113,3 +90,46 @@ SELECT * FROM (SELECT * FROM t1) d PROCEDURE ANALYSE(); DROP TABLE t1; --echo End of 4.1 tests + +--echo # +--echo # Bug #48293: crash with procedure analyse, view with > 10 columns, +--echo # having clause... +--echo # + +CREATE TABLE t1(a INT, b INT, c INT, d INT, e INT, + f INT, g INT, h INT, i INT, j INT,k INT); +INSERT INTO t1 VALUES (),(); + +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +--echo #should have a derived table +EXPLAIN SELECT * FROM v1; +--echo #should not crash +--error ER_WRONG_USAGE +SELECT * FROM v1 PROCEDURE analyse(); +--echo #should not crash +--error ER_WRONG_USAGE +SELECT * FROM t1 a, v1, t1 b PROCEDURE analyse(); +--echo #should not crash +--error ER_WRONG_USAGE +SELECT * FROM (SELECT * FROM t1 having a > 1) x PROCEDURE analyse(); +--echo #should not crash +--error ER_WRONG_USAGE +SELECT * FROM t1 a, (SELECT * FROM t1 having a > 1) x, t1 b PROCEDURE analyse(); +--echo #should not crash +--error ER_ORDER_WITH_PROC +SELECT 1 FROM t1 group by a having a > 1 order by 1 PROCEDURE analyse(); + +DROP VIEW v1; +DROP TABLE t1; + +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (1),(2); + +--echo # should not crash +--error ER_WRONG_USAGE +CREATE TABLE t2 SELECT 1 FROM t1, t1 t3 GROUP BY t3.a PROCEDURE ANALYSE(); + +DROP TABLE t1; + + +--echo End of 5.0 tests diff --git a/mysql-test/t/bug40113.test b/mysql-test/t/bug40113.test deleted file mode 100644 index 6d35d0b73d3..00000000000 --- a/mysql-test/t/bug40113.test +++ /dev/null @@ -1,46 +0,0 @@ ---source include/have_innodb.inc - ---echo # ---echo # Bug #40113: Embedded SELECT inside UPDATE or DELETE can timeout ---echo # without error ---echo # - -CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)) ENGINE=InnoDB; - -INSERT INTO t1 (a,b) VALUES (1070109,99); - -CREATE TABLE t2 (b int, a int, PRIMARY KEY (b)) ENGINE=InnoDB; - -INSERT INTO t2 (b,a) VALUES (7,1070109); - -SELECT * FROM t1; - -BEGIN; - -SELECT b FROM t2 WHERE b=7 FOR UPDATE; - -CONNECT (addconroot, localhost, root,,); -CONNECTION addconroot; - -BEGIN; - ---error ER_LOCK_WAIT_TIMEOUT -SELECT b FROM t2 WHERE b=7 FOR UPDATE; - ---error ER_LOCK_WAIT_TIMEOUT -INSERT INTO t1 (a) VALUES ((SELECT a FROM t2 WHERE b=7)); - ---error ER_LOCK_WAIT_TIMEOUT -UPDATE t1 SET a='7000000' WHERE a=(SELECT a FROM t2 WHERE b=7); - ---error ER_LOCK_WAIT_TIMEOUT -DELETE FROM t1 WHERE a=(SELECT a FROM t2 WHERE b=7); - -SELECT * FROM t1; - -CONNECTION default; -DISCONNECT addconroot; - -DROP TABLE t2, t1; - ---echo End of 5.0 tests diff --git a/mysql-test/t/ctype_ldml.test b/mysql-test/t/ctype_ldml.test index bc04b93a935..0395de273de 100644 --- a/mysql-test/t/ctype_ldml.test +++ b/mysql-test/t/ctype_ldml.test @@ -37,6 +37,14 @@ UPDATE t1 SET col2=col1; SELECT * FROM t1 WHERE col1=col2 ORDER BY col1; DROP TABLE t1; +--echo # +--echo # Bug#45645 Mysql server close all connection and restart using lower function +--echo # +CREATE TABLE t1 (a VARCHAR(10)) CHARACTER SET utf8 COLLATE utf8_test_ci; +INSERT INTO t1 (a) VALUES ('hello!'); +SELECT * FROM t1 WHERE LOWER(a)=LOWER('N'); +DROP TABLE t1; + --echo # --echo # Bug#43827 Server closes connections and restarts --echo # diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 6f0b1716d38..ad7617b9403 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -10,7 +10,8 @@ # ############################################################################## kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild. -innodb_bug39438 : Bug#42383 2009-01-28 lsoares "This fails in embedded and on windows. Note that this test is not run on windows and on embedded in PB for main trees currently" query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically partition_innodb_builtin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes partition_innodb_plugin : Bug#32430 2009-09-25 mattiasj Waiting for push of Innodb changes +innodb-autoinc : Bug#48482 2009-11-02 svoj innodb-autoinc.test fails with results difference +rpl_killed_ddl : Bug#45520: rpl_killed_ddl fails sporadically in pb2 diff --git a/mysql-test/t/explain.test b/mysql-test/t/explain.test index 18f1145a25d..77b49a8b1a5 100644 --- a/mysql-test/t/explain.test +++ b/mysql-test/t/explain.test @@ -167,4 +167,24 @@ flush tables; SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN ( SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.t < '2005-11-13 7:41:31' ); drop tables t1, t2; +--echo # +--echo # Bug#48295: +--echo # explain extended crash with subquery and ONLY_FULL_GROUP_BY sql_mode +--echo # + +CREATE TABLE t1 (f1 INT); + +SELECT @@session.sql_mode INTO @old_sql_mode; +SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; + +# EXPLAIN EXTENDED (with subselect). used to crash. should give NOTICE. +--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS +EXPLAIN EXTENDED SELECT 1 FROM t1 + WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t ); +SHOW WARNINGS; + +SET SESSION sql_mode=@old_sql_mode; + +DROP TABLE t1; + --echo End of 5.1 tests. diff --git a/mysql-test/t/flush_read_lock_kill.test b/mysql-test/t/flush_read_lock_kill.test index aeb09d52460..2d359383949 100644 --- a/mysql-test/t/flush_read_lock_kill.test +++ b/mysql-test/t/flush_read_lock_kill.test @@ -57,7 +57,7 @@ connection con1; # debug build running without our --debug=make_global..., will be # error 0 (no error). The only important thing to test is that on # debug builds with our --debug=make_global... we don't hang forever. ---error 0,1053,2013 +--error 0,1317,2013 reap; connection con2; diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test index 19bbcf19cca..c325b3bd223 100644 --- a/mysql-test/t/gis-rtree.test +++ b/mysql-test/t/gis-rtree.test @@ -881,4 +881,25 @@ SELECT COUNT(*) FROM t1 IGNORE INDEX (b) WHERE DROP TABLE t1; + +--echo # +--echo # Bug #48258: Assertion failed when using a spatial index +--echo # +CREATE TABLE t1(a LINESTRING NOT NULL, SPATIAL KEY(a)); +INSERT INTO t1 VALUES + (GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')), + (GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')); +EXPLAIN SELECT 1 FROM t1 WHERE a = GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +SELECT 1 FROM t1 WHERE a = GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +EXPLAIN SELECT 1 FROM t1 WHERE a < GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +SELECT 1 FROM t1 WHERE a < GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +EXPLAIN SELECT 1 FROM t1 WHERE a <= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +SELECT 1 FROM t1 WHERE a <= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +EXPLAIN SELECT 1 FROM t1 WHERE a > GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +SELECT 1 FROM t1 WHERE a > GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +EXPLAIN SELECT 1 FROM t1 WHERE a >= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +SELECT 1 FROM t1 WHERE a >= GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)'); +DROP TABLE t1; + + --echo End of 5.0 tests. diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 4a60e777cc7..2d10c3bf1e1 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -655,6 +655,22 @@ insert into t1 values (),(),(); select min(`col002`) from t1 union select `col002` from t1; drop table t1; +--echo # +--echo # Bug #47780: crash when comparing GIS items from subquery +--echo # + +CREATE TABLE t1(a INT, b MULTIPOLYGON); +INSERT INTO t1 VALUES + (0, + GEOMFROMTEXT( + 'multipolygon(((1 2,3 4,5 6,7 8,9 8),(7 6,5 4,3 2,1 2,3 4)))')); + +--echo # must not crash +SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); + +DROP TABLE t1; + + --echo End of 5.0 tests diff --git a/mysql-test/t/grant3.test b/mysql-test/t/grant3.test index 9a635048774..437fc9a278f 100644 --- a/mysql-test/t/grant3.test +++ b/mysql-test/t/grant3.test @@ -163,6 +163,41 @@ connection default; DROP USER 'mysqltest1'@'%'; DROP DATABASE mysqltest_1; +--echo # +--echo # Bug#41597 - After rename of user, there are additional grants +--echo # when grants are reapplied. +--echo # + +CREATE DATABASE temp; +CREATE TABLE temp.t1(a INT, b VARCHAR(10)); +INSERT INTO temp.t1 VALUES(1, 'name1'); +INSERT INTO temp.t1 VALUES(2, 'name2'); +INSERT INTO temp.t1 VALUES(3, 'name3'); + + +CREATE USER 'user1'@'%'; +RENAME USER 'user1'@'%' TO 'user2'@'%'; +--echo # Show privileges after rename and BEFORE grant +SHOW GRANTS FOR 'user2'@'%'; +GRANT SELECT (a), INSERT (b) ON `temp`.`t1` TO 'user2'@'%'; +--echo # Show privileges after rename and grant +SHOW GRANTS FOR 'user2'@'%'; + +--echo # Connect as the renamed user +connect (conn1, localhost, user2,,); +connection conn1; +SHOW GRANTS; +SELECT a FROM temp.t1; +--echo # Check for additional privileges by accessing a +--echo # non privileged column. We shouldn't be able to +--echo # access this column. +--error ER_COLUMNACCESS_DENIED_ERROR +SELECT b FROM temp.t1; +disconnect conn1; + +connection default; +DROP USER 'user2'@'%'; +DROP DATABASE temp; --echo End of 5.0 tests diff --git a/mysql-test/t/grant_lowercase_fs.test b/mysql-test/t/grant_lowercase_fs.test new file mode 100644 index 00000000000..f57f950ec8c --- /dev/null +++ b/mysql-test/t/grant_lowercase_fs.test @@ -0,0 +1,30 @@ +-- source include/have_case_insensitive_fs.inc +-- source include/not_embedded.inc + + +# +# Bug#41049 does syntax "grant" case insensitive? +# +create database db1; +GRANT CREATE ON db1.* to user_1@localhost; +GRANT SELECT ON db1.* to USER_1@localhost; + +connect (con1,localhost,user_1,,db1); +CREATE TABLE t1(f1 int); +--error 1142 +SELECT * FROM t1; +connect (con2,localhost,USER_1,,db1); +SELECT * FROM t1; +--error 1142 +CREATE TABLE t2(f1 int); + +connection default; +disconnect con1; +disconnect con2; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM USER_1@localhost; +DROP USER user_1@localhost; +DROP USER USER_1@localhost; +DROP DATABASE db1; +use test; diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test index 61c42f45733..3f45bb9d003 100644 --- a/mysql-test/t/innodb-autoinc.test +++ b/mysql-test/t/innodb-autoinc.test @@ -482,6 +482,7 @@ DROP TABLE t2; # 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from # the index (PRIMARY) # This test requires a restart of the server +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; INSERT INTO t1 VALUES (null); INSERT INTO t1 VALUES (null); @@ -492,9 +493,130 @@ SELECT * FROM t1; # The MySQL and InnoDB data dictionaries should now be out of sync. # The select should print message to the error log SELECT * FROM t1; +# MySQL have made a change (http://lists.mysql.com/commits/75268) that no +# longer results in the two data dictionaries being out of sync. If they +# revert their changes then this check for ER_AUTOINC_READ_FAILED will need +# to be enabled. -- error ER_AUTOINC_READ_FAILED,1467 INSERT INTO t1 VALUES(null); ALTER TABLE t1 AUTO_INCREMENT = 3; +SHOW CREATE TABLE t1; INSERT INTO t1 VALUES(null); SELECT * FROM t1; DROP TABLE t1; + +# If the user has specified negative values for an AUTOINC column then +# InnoDB should ignore those values when setting the table's max value. +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; +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); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-127, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-127, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# SMALLINT +# +CREATE TABLE t1 (c1 SMALLINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-32767, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-32757, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# MEDIUMINT +# +CREATE TABLE t1 (c1 MEDIUMINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-8388607, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 MEDIUMINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-8388607, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# INT +# +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-2147483647, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-2147483647, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# BIGINT +# +CREATE TABLE t1 (c1 BIGINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-9223372036854775807, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (-1, 'innodb'); +INSERT INTO t1 VALUES (-9223372036854775807, 'innodb'); +INSERT INTO t1 VALUES (NULL, NULL); +SHOW CREATE TABLE t1; +SELECT * FROM t1; +DROP TABLE t1; +# +# End negative number check + +## +# 47125: auto_increment start value is ignored if an index is created +# and engine=innodb +# +CREATE TABLE T1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) AUTO_INCREMENT=10 ENGINE=InnoDB; +CREATE INDEX i1 on T1(c2); +SHOW CREATE TABLE T1; +INSERT INTO T1 (c2) values (0); +SELECT * FROM T1; +DROP TABLE T1; diff --git a/mysql-test/t/innodb_bug34300.test b/mysql-test/t/innodb_bug34300.test index ecec381da14..432ddd03547 100644 --- a/mysql-test/t/innodb_bug34300.test +++ b/mysql-test/t/innodb_bug34300.test @@ -9,7 +9,6 @@ -- disable_result_log # set packet size and reconnect -let $max_packet=`select @@global.max_allowed_packet`; SET @@global.max_allowed_packet=16777216; --connect (newconn, localhost, root,,) diff --git a/mysql-test/t/innodb_bug39438.test b/mysql-test/t/innodb_bug39438.test index 4dc3d957c39..2a51e5fcbb8 100644 --- a/mysql-test/t/innodb_bug39438.test +++ b/mysql-test/t/innodb_bug39438.test @@ -9,6 +9,10 @@ -- source include/have_innodb.inc +--disable_query_log +call mtr.add_suppression("InnoDB: Error: table 'test/bug39438'"); +--enable_query_log + SET storage_engine=InnoDB; # we care only that the following SQL commands do not crash the server diff --git a/mysql-test/t/innodb_bug44369.test b/mysql-test/t/innodb_bug44369.test index 495059eb5e6..238dc3d8fb1 100644 --- a/mysql-test/t/innodb_bug44369.test +++ b/mysql-test/t/innodb_bug44369.test @@ -13,9 +13,9 @@ create table bug44369 (DB_ROW_ID int) engine=innodb; --error ER_CANT_CREATE_TABLE create table bug44369 (db_row_id int) engine=innodb; -show errors; +show warnings; --error ER_CANT_CREATE_TABLE create table bug44369 (db_TRX_Id int) engine=innodb; -show errors; +show warnings; diff --git a/mysql-test/t/innodb_bug46000.test b/mysql-test/t/innodb_bug46000.test index 80c18c58ef0..eb10d866e54 100644 --- a/mysql-test/t/innodb_bug46000.test +++ b/mysql-test/t/innodb_bug46000.test @@ -14,7 +14,7 @@ create table bug46000(`id` int,key `GEN_CLUST_INDEX`(`id`))engine=innodb; --error ER_CANT_CREATE_TABLE create table bug46000(`id` int, key `GEN_clust_INDEX`(`id`))engine=innodb; -show errors; +show warnings; create table bug46000(id int) engine=innodb; @@ -24,7 +24,7 @@ create table bug46000(id int) engine=innodb; create index GEN_CLUST_INDEX on bug46000(id); --replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/ -show errors; +show warnings; # This 'create index' operation should succeed, no # temp table left from last failed create index diff --git a/mysql-test/t/innodb_bug47777.test b/mysql-test/t/innodb_bug47777.test new file mode 100644 index 00000000000..8f2985b2cf0 --- /dev/null +++ b/mysql-test/t/innodb_bug47777.test @@ -0,0 +1,24 @@ +# This is the test for bug 47777. GEOMETRY +# data is treated as BLOB data in innodb. +# Consequently, its key value generation/storing +# should follow the process for the BLOB +# datatype as well. + +--source include/have_innodb.inc + +create table bug47777(c2 linestring not null, primary key (c2(1))) engine=innodb; + +insert into bug47777 values (geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)')); + +# Verify correct row get inserted. +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); + +# Update table bug47777 should be successful. +update bug47777 set c2=GeomFromText('POINT(1 1)'); + +# Verify the row get updated successfully. The original +# c2 value should be changed to GeomFromText('POINT(1 1)'). +select count(*) from bug47777 where c2 =geomfromtext('linestring(1 2,3 4,5 6,7 8,9 10)'); +select count(*) from bug47777 where c2 = GeomFromText('POINT(1 1)'); + +drop table bug47777; diff --git a/mysql-test/t/bug40113-master.opt b/mysql-test/t/innodb_lock_wait_timeout_1-master.opt similarity index 100% rename from mysql-test/t/bug40113-master.opt rename to mysql-test/t/innodb_lock_wait_timeout_1-master.opt diff --git a/mysql-test/t/innodb_lock_wait_timeout_1.test b/mysql-test/t/innodb_lock_wait_timeout_1.test new file mode 100644 index 00000000000..e42e9f3e37c --- /dev/null +++ b/mysql-test/t/innodb_lock_wait_timeout_1.test @@ -0,0 +1,230 @@ +--source include/have_innodb.inc + +--echo # +--echo # Bug #40113: Embedded SELECT inside UPDATE or DELETE can timeout +--echo # without error +--echo # + +CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)) ENGINE=InnoDB; + +INSERT INTO t1 (a,b) VALUES (1070109,99); + +CREATE TABLE t2 (b int, a int, PRIMARY KEY (b)) ENGINE=InnoDB; + +INSERT INTO t2 (b,a) VALUES (7,1070109); + +SELECT * FROM t1; + +BEGIN; + +SELECT b FROM t2 WHERE b=7 FOR UPDATE; + +CONNECT (addconroot, localhost, root,,); +CONNECTION addconroot; + +BEGIN; + +--error ER_LOCK_WAIT_TIMEOUT +SELECT b FROM t2 WHERE b=7 FOR UPDATE; + +--error ER_LOCK_WAIT_TIMEOUT +INSERT INTO t1 (a) VALUES ((SELECT a FROM t2 WHERE b=7)); + +--error ER_LOCK_WAIT_TIMEOUT +UPDATE t1 SET a='7000000' WHERE a=(SELECT a FROM t2 WHERE b=7); + +--error ER_LOCK_WAIT_TIMEOUT +DELETE FROM t1 WHERE a=(SELECT a FROM t2 WHERE b=7); + +SELECT * FROM t1; + +CONNECTION default; +DISCONNECT addconroot; + +DROP TABLE t2, t1; + +--echo # End of 5.0 tests + +--echo # +--echo # Bug#46539 Various crashes on INSERT IGNORE SELECT + SELECT +--echo # FOR UPDATE +--echo # +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (a int primary key auto_increment, + b int, index(b)) engine=innodb; +insert into t1 (b) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +set autocommit=0; +begin; +select * from t1 where b=5 for update; +connect (con1, localhost, root,,); +connection con1; +--error ER_LOCK_WAIT_TIMEOUT +insert ignore into t1 (b) select a as b from t1; +connection default; +--echo # Cleanup +--echo # +disconnect con1; +commit; +set autocommit=default; +drop table t1; + +--echo # +--echo # Bug#41756 Strange error messages about locks from InnoDB +--echo # +--disable_warnings +drop table if exists t1; +--enable_warnings +--echo # In the default transaction isolation mode, and/or with +--echo # innodb_locks_unsafe_for_binlog=OFF, handler::unlock_row() +--echo # in InnoDB does nothing. +--echo # Thus in order to reproduce the condition that led to the +--echo # warning, one needs to relax isolation by either +--echo # setting a weaker tx_isolation value, or by turning on +--echo # the unsafe replication switch. +--echo # For testing purposes, choose to tweak the isolation level, +--echo # since it's settable at runtime, unlike +--echo # innodb_locks_unsafe_for_binlog, which is +--echo # only a command-line switch. +--echo # +set @@session.tx_isolation="read-committed"; + +--echo # Prepare data. We need a table with a unique index, +--echo # for join_read_key to be used. The other column +--echo # allows to control what passes WHERE clause filter. +create table t1 (a int primary key, b int) engine=innodb; +--echo # Let's make sure t1 has sufficient amount of rows +--echo # to exclude JT_ALL access method when reading it, +--echo # i.e. make sure that JT_EQ_REF(a) is always preferred. +insert into t1 values (1,1), (2,null), (3,1), (4,1), + (5,1), (6,1), (7,1), (8,1), (9,1), (10,1), + (11,1), (12,1), (13,1), (14,1), (15,1), + (16,1), (17,1), (18,1), (19,1), (20,1); +--echo # +--echo # Demonstrate that for the SELECT statement +--echo # used later in the test JT_EQ_REF access method is used. +--echo # +--vertical_results +explain +select 1 from t1 natural join (select 2 as a, 1 as b union all + select 2 as a, 2 as b) as t2 for update; +--horizontal_results +--echo # +--echo # Demonstrate that the reported SELECT statement +--echo # no longer produces warnings. +--echo # +select 1 from t1 natural join (select 2 as a, 1 as b union all + select 2 as a, 2 as b) as t2 for update; +commit; +--echo # +--echo # Demonstrate that due to lack of inter-sweep "reset" function, +--echo # we keep some non-matching records locked, even though we know +--echo # we could unlock them. +--echo # To do that, show that if there is only one distinct value +--echo # for a in t2 (a=2), we will keep record (2,null) in t1 locked. +--echo # But if we add another value for "a" to t2, say 6, +--echo # join_read_key cache will be pruned at least once, +--echo # and thus record (2, null) in t1 will get unlocked. +--echo # +begin; +select 1 from t1 natural join (select 2 as a, 1 as b union all + select 2 as a, 2 as b) as t2 for update; +connect (con1,localhost,root,,); +--echo # +--echo # Switching to connection con1 +connection con1; +--echo # We should be able to delete all records from t1 except (2, null), +--echo # since they were not locked. +begin; +--echo # Delete in series of 3 records so that full scan +--echo # is not used and we're not blocked on record (2,null) +delete from t1 where a in (1,3,4); +delete from t1 where a in (5,6,7); +delete from t1 where a in (8,9,10); +delete from t1 where a in (11,12,13); +delete from t1 where a in (14,15,16); +delete from t1 where a in (17,18); +delete from t1 where a in (19,20); +--echo # +--echo # Record (2, null) is locked. This is actually unnecessary, +--echo # because the previous select returned no rows. +--echo # Just demonstrate the effect. +--echo # +--error ER_LOCK_WAIT_TIMEOUT +delete from t1; +rollback; +--echo # +--echo # Switching to connection default +connection default; +--echo # +--echo # Show that the original contents of t1 is intact: +select * from t1; +commit; +--echo # +--echo # Have a one more record in t2 to show that +--echo # if join_read_key cache is purned, the current +--echo # row under the cursor is unlocked (provided, this row didn't +--echo # match the partial WHERE clause, of course). +--echo # Sic: the result of this test dependent on the order of retrieval +--echo # of records --echo # from the derived table, if ! +--echo # We use DELETE to disable the JOIN CACHE. This DELETE modifies no +--echo # records. It also should leave no InnoDB row locks. +--echo # +begin; +delete t1.* from t1 natural join (select 2 as a, 2 as b union all + select 0 as a, 0 as b) as t2; +--echo # Demonstrate that nothing was deleted form t1 +select * from t1; +--echo # +--echo # Switching to connection con1 +connection con1; +begin; +--echo # Since there is another distinct record in the derived table +--echo # the previous matching record in t1 -- (2,null) -- was unlocked. +delete from t1; +--echo # We will need the contents of the table again. +rollback; +select * from t1; +commit; +--echo # +--echo # Switching to connection default +connection default; +rollback; +begin; +--echo # +--echo # Before this patch, we could wrongly unlock a record +--echo # that was cached and later used in a join. Demonstrate that +--echo # this is no longer the case. +--echo # Sic: this test is also order-dependent (i.e. the +--echo # the bug would show up only if the first record in the union +--echo # is retreived and processed first. +--echo # +--echo # Verify that JT_EQ_REF is used. +--vertical_results +explain +select 1 from t1 natural join (select 3 as a, 2 as b union all + select 3 as a, 1 as b) as t2 for update; +--horizontal_results +--echo # Lock the record. +select 1 from t1 natural join (select 3 as a, 2 as b union all + select 3 as a, 1 as b) as t2 for update; +--echo # Switching to connection con1 +connection con1; +--echo # +--echo # We should not be able to delete record (3,1) from t1, +--echo # (previously it was possible). +--echo # +--error ER_LOCK_WAIT_TIMEOUT +delete from t1 where a=3; +--echo # Switching to connection default +connection default; +commit; + +disconnect con1; +set @@session.tx_isolation=default; +drop table t1; + +--echo # +--echo # End of 5.1 tests +--echo # diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index c643465b2f3..7055879ce1a 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -461,4 +461,33 @@ EXPLAIN SELECT * FROM t1 FORCE INDEX(PRIMARY) WHERE b=1 AND c=1 ORDER BY a; DROP TABLE t1; +--echo # +--echo # Bug #47963: Wrong results when index is used +--echo # +CREATE TABLE t1( + a VARCHAR(5) NOT NULL, + b VARCHAR(5) NOT NULL, + c DATETIME NOT NULL, + KEY (c) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES('TEST', 'TEST', '2009-10-09 00:00:00'); +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00.0'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00.0'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.000' AND c <= '2009-10-09 00:00:00.000'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.00' AND c <= '2009-10-09 00:00:00.001'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; +EXPLAIN SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; +DROP TABLE t1; + + --echo End of 5.1 tests diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 1cd05c8cb65..dbf36dedec8 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -730,6 +730,60 @@ SELECT * FROM t1 JOIN t2 ON a=c ORDER BY a; DROP TABLE IF EXISTS t1,t2; + +--echo # +--echo # Bug #42116: Mysql crash on specific query +--echo # +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT); +CREATE TABLE t3 (a INT, INDEX (a)); +CREATE TABLE t4 (a INT); +CREATE TABLE t5 (a INT); +CREATE TABLE t6 (a INT); + +INSERT INTO t1 VALUES (1), (1), (1); + +INSERT INTO t2 VALUES +(2), (2), (2), (2), (2), (2), (2), (2), (2), (2); + +INSERT INTO t3 VALUES +(3), (3), (3), (3), (3), (3), (3), (3), (3), (3); + +EXPLAIN +SELECT * +FROM + t1 JOIN t2 ON t1.a = t2.a + LEFT JOIN + ( + ( + t3 LEFT JOIN t4 ON t3.a = t4.a + ) + LEFT JOIN + ( + t5 LEFT JOIN t6 ON t5.a = t6.a + ) + ON t4.a = t5.a + ) + ON t1.a = t3.a; + +SELECT * +FROM + t1 JOIN t2 ON t1.a = t2.a + LEFT JOIN + ( + ( + t3 LEFT JOIN t4 ON t3.a = t4.a + ) + LEFT JOIN + ( + t5 LEFT JOIN t6 ON t5.a = t6.a + ) + ON t4.a = t5.a + ) + ON t1.a = t3.a; + +DROP TABLE t1,t2,t3,t4,t5,t6; + --echo End of 5.0 tests. diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index 8ef668f542b..02b033df2e5 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -97,7 +97,7 @@ select ((@id := kill_id) - kill_id) from t3; kill @id; connection conn1; --- error 1053,2013 +-- error 1317,2013 reap; connection default; diff --git a/mysql-test/t/locale.test b/mysql-test/t/locale.test new file mode 100644 index 00000000000..7ceb49fd1f4 --- /dev/null +++ b/mysql-test/t/locale.test @@ -0,0 +1,18 @@ +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo Start of 5.4 tests +--echo # +--echo # Bug#43207 wrong LC_TIME names for romanian locale +--echo # +SET NAMES utf8; +SET lc_time_names=ro_RO; +SELECT DATE_FORMAT('2001-01-01', '%w %a %W'); +SELECT DATE_FORMAT('2001-01-02', '%w %a %W'); +SELECT DATE_FORMAT('2001-01-03', '%w %a %W'); +SELECT DATE_FORMAT('2001-01-04', '%w %a %W'); +SELECT DATE_FORMAT('2001-01-05', '%w %a %W'); +SELECT DATE_FORMAT('2001-01-06', '%w %a %W'); +SELECT DATE_FORMAT('2001-01-07', '%w %a %W'); +--echo End of 5.4 tests diff --git a/mysql-test/t/lowercase_fs_off.test b/mysql-test/t/lowercase_fs_off.test index 878564c32ab..86d1e084c29 100644 --- a/mysql-test/t/lowercase_fs_off.test +++ b/mysql-test/t/lowercase_fs_off.test @@ -29,3 +29,65 @@ disconnect master; connection default; # End of 4.1 tests + +# +# Bug#41049 does syntax "grant" case insensitive? +# +CREATE DATABASE d1; +USE d1; +CREATE TABLE T1(f1 INT); +CREATE TABLE t1(f1 INT); +GRANT SELECT ON T1 to user_1@localhost; + +connect (con1,localhost,user_1,,d1); +--error ER_TABLEACCESS_DENIED_ERROR +select * from t1; +select * from T1; +connection default; +GRANT SELECT ON t1 to user_1@localhost; +connection con1; +select * from information_schema.table_privileges; +connection default; +disconnect con1; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost; +DROP USER user_1@localhost; +DROP DATABASE d1; +USE test; + +CREATE DATABASE db1; +USE db1; +CREATE PROCEDURE p1() BEGIN END; +CREATE FUNCTION f1(i INT) RETURNS INT RETURN i+1; + +GRANT USAGE ON db1.* to user_1@localhost; +GRANT EXECUTE ON PROCEDURE db1.P1 to user_1@localhost; +GRANT EXECUTE ON FUNCTION db1.f1 to user_1@localhost; +GRANT UPDATE ON db1.* to USER_1@localhost; + +connect (con1,localhost,user_1,,db1); +call p1(); +call P1(); +select f1(1); +connect (con2,localhost,USER_1,,db1); +--error ER_PROCACCESS_DENIED_ERROR +call p1(); +--error ER_PROCACCESS_DENIED_ERROR +call P1(); +--error ER_PROCACCESS_DENIED_ERROR +select f1(1); + +connection default; +disconnect con1; +disconnect con2; + +REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM USER_1@localhost; +DROP FUNCTION f1; +DROP PROCEDURE p1; +DROP USER user_1@localhost; +DROP USER USER_1@localhost; +DROP DATABASE db1; +use test; + +# End of 5.0 tests diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index e4ea939f348..56fe103adc9 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1539,14 +1539,14 @@ INSERT INTO t1 SELECT a+5120,b FROM t1; SET myisam_sort_buffer_size=4; REPAIR TABLE t1; -# !!! Disabled until additional fix for BUG#47073 is pushed. -#SET myisam_repair_threads=2; +SET myisam_repair_threads=2; # May report different values depending on threads activity. -#--replace_regex /changed from [0-9]+/changed from #/ -#REPAIR TABLE t1; -#SET myisam_repair_threads=@@global.myisam_repair_threads; - +--disable_result_log +REPAIR TABLE t1; +--enable_result_log +SET myisam_repair_threads=@@global.myisam_repair_threads; SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size; +CHECK TABLE t1; DROP TABLE t1; --echo End of 5.1 tests diff --git a/mysql-test/t/myisam_crash_before_flush_keys.test b/mysql-test/t/myisam_crash_before_flush_keys.test index d6559f7760d..1860ddd27e3 100644 --- a/mysql-test/t/myisam_crash_before_flush_keys.test +++ b/mysql-test/t/myisam_crash_before_flush_keys.test @@ -26,12 +26,6 @@ SET SESSION debug="d,crash_before_flush_keys"; --error 2013 FLUSH TABLE t1; ---echo # Run MYISAMCHK tool to check the table t1 and repair ---replace_result $MYISAMCHK MYISAMCHK $MYSQLD_DATADIR MYSQLD_DATADIR ---error 255 ---exec $MYISAMCHK -cs $MYSQLD_DATADIR/test/t1 2>&1 ---exec $MYISAMCHK -rs $MYSQLD_DATADIR/test/t1 - --echo # Write file to make mysql-test-run.pl start the server --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect @@ -42,8 +36,6 @@ FLUSH TABLE t1; --echo # it to be back online again --source include/wait_until_connected_again.inc -SHOW CREATE TABLE t1; - -SELECT * FROM t1 FORCE INDEX (PRIMARY); - +# Must report that the table wasn't closed properly +CHECK TABLE t1; DROP TABLE t1; diff --git a/mysql-test/t/named_pipe.test b/mysql-test/t/named_pipe.test index e3dfd24bb52..e88fd8e1ef8 100644 --- a/mysql-test/t/named_pipe.test +++ b/mysql-test/t/named_pipe.test @@ -9,6 +9,11 @@ if (`SELECT '$nmp' != 'ON'`){ skip No named pipe support; } +# Connect using named pipe for testing +connect(pipe_con,localhost,root,,,,,PIPE); + # Source select test case -- source include/common-tests.inc +connection default; +disconnect pipe_con; diff --git a/mysql-test/t/olap.test b/mysql-test/t/olap.test index d1e40024733..8f672af40a3 100644 --- a/mysql-test/t/olap.test +++ b/mysql-test/t/olap.test @@ -375,4 +375,19 @@ INSERT INTO t1 VALUES(0); SELECT 1 FROM t1 GROUP BY (DATE(NULL)) WITH ROLLUP; DROP TABLE t1; +--echo # +--echo # Bug #48131: crash group by with rollup, distinct, +--echo # filesort, with temporary tables +--echo # + +CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY); +INSERT INTO t1 VALUES (1), (2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (100); + +SELECT a, b FROM t1, t2 GROUP BY a, b WITH ROLLUP; +SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP; + +DROP TABLE t1, t2; + --echo End of 5.0 tests diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index 7841e7274dd..0edc9cca385 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -1294,7 +1294,7 @@ SET GLOBAL query_cache_size= default; # Bug #31157: Crash when select+order by the avg of some field within the # group by # - +SET GLOBAL query_cache_size=1024*1024*512; CREATE TABLE t1 (a ENUM('rainbow')); INSERT INTO t1 VALUES (),(),(),(),(); SELECT 1 FROM t1 GROUP BY (SELECT 1 FROM t1 ORDER BY AVG(LAST_INSERT_ID())); @@ -1305,6 +1305,7 @@ INSERT INTO t1 SET a = 'aaaa'; SELECT 1 FROM t1 GROUP BY (SELECT LAST_INSERT_ID() FROM t1 ORDER BY MIN(a) ASC LIMIT 1); DROP TABLE t1; +SET GLOBAL query_cache_size= default; --echo End of 5.1 tests diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index dc119b6a77e..3a845471cd0 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -1171,3 +1171,93 @@ a < 5 OR a < 10; DROP TABLE t1, t2, t3; + +--echo # +--echo # Bug #47123: Endless 100% CPU loop with STRAIGHT_JOIN +--echo # + +CREATE TABLE t1(a INT, KEY(a)); +INSERT INTO t1 VALUES (1), (NULL); +SELECT * FROM t1 WHERE a <> NULL and (a <> NULL or a <= NULL); +DROP TABLE t1; + +--echo # +--echo # Bug#47925: regression of range optimizer and date comparison in 5.1.39! +--echo # +CREATE TABLE t1 ( a DATE, KEY ( a ) ); +CREATE TABLE t2 ( a DATETIME, KEY ( a ) ); + +--echo # Make optimizer choose range scan +INSERT INTO t1 VALUES ('2009-09-22'), ('2009-09-22'), ('2009-09-22'); +INSERT INTO t1 VALUES ('2009-09-23'), ('2009-09-23'), ('2009-09-23'); + +INSERT INTO t2 VALUES ('2009-09-22 12:00:00'), ('2009-09-22 12:00:00'), + ('2009-09-22 12:00:00'); +INSERT INTO t2 VALUES ('2009-09-23 12:00:00'), ('2009-09-23 12:00:00'), + ('2009-09-23 12:00:00'); + +--echo # DATE vs DATE +--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X +EXPLAIN +SELECT * FROM t1 WHERE a >= '2009/09/23'; +SELECT * FROM t1 WHERE a >= '2009/09/23'; +SELECT * FROM t1 WHERE a >= '20090923'; +SELECT * FROM t1 WHERE a >= 20090923; +SELECT * FROM t1 WHERE a >= '2009-9-23'; +SELECT * FROM t1 WHERE a >= '2009.09.23'; +SELECT * FROM t1 WHERE a >= '2009:09:23'; + +--echo # DATE vs DATETIME +--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X +EXPLAIN +SELECT * FROM t2 WHERE a >= '2009/09/23'; +SELECT * FROM t2 WHERE a >= '2009/09/23'; +SELECT * FROM t2 WHERE a >= '2009/09/23'; +SELECT * FROM t2 WHERE a >= '20090923'; +SELECT * FROM t2 WHERE a >= 20090923; +SELECT * FROM t2 WHERE a >= '2009-9-23'; +SELECT * FROM t2 WHERE a >= '2009.09.23'; +SELECT * FROM t2 WHERE a >= '2009:09:23'; + +--echo # DATETIME vs DATETIME +--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X +EXPLAIN +SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00'; +SELECT * FROM t2 WHERE a >= '2009/09/23 12:00:00'; +SELECT * FROM t2 WHERE a >= '20090923120000'; +SELECT * FROM t2 WHERE a >= 20090923120000; +SELECT * FROM t2 WHERE a >= '2009-9-23 12:00:00'; +SELECT * FROM t2 WHERE a >= '2009.09.23 12:00:00'; +SELECT * FROM t2 WHERE a >= '2009:09:23 12:00:00'; + +--echo # DATETIME vs DATE +--replace_column 1 X 2 X 3 X 7 X 8 X 9 X 10 X +EXPLAIN +SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00'; +SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00'; +SELECT * FROM t1 WHERE a >= '2009/09/23 00:00:00'; +SELECT * FROM t1 WHERE a >= '20090923000000'; +SELECT * FROM t1 WHERE a >= 20090923000000; +SELECT * FROM t1 WHERE a >= '2009-9-23 00:00:00'; +SELECT * FROM t1 WHERE a >= '2009.09.23 00:00:00'; +SELECT * FROM t1 WHERE a >= '2009:09:23 00:00:00'; + +--echo # Test of the new get_date_from_str implementation +--echo # Behavior differs slightly between the trunk and mysql-pe. +--echo # The former may give errors for the truncated values, while the latter +--echo # gives warnings. The purpose of this test is not to interfere, and only +--echo # preserve existing behavior. +SELECT str_to_date('2007-10-00', '%Y-%m-%d') >= '' AND + str_to_date('2007-10-00', '%Y-%m-%d') <= '2007/10/20'; + +SELECT str_to_date('2007-20-00', '%Y-%m-%d') >= '2007/10/20' AND + str_to_date('2007-20-00', '%Y-%m-%d') <= ''; + +SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'; +SELECT str_to_date('2007-20-00', '%Y-%m-%d') BETWEEN '2007/10/20' AND ''; + +SELECT str_to_date('', '%Y-%m-%d'); + +DROP TABLE t1, t2; + +--echo End of 5.1 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 7d3785ecccc..51f0cd73374 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -3739,7 +3739,40 @@ EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND a = b LIMIT 2; EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND b = a LIMIT 2; DROP TABLE t1; + + +--echo # +--echo # Bug#47019: Assertion failed: 0, file .\rt_mbr.c, line 138 when +--echo # forcing a spatial index +--echo # +CREATE TABLE t1(a LINESTRING NOT NULL, SPATIAL KEY(a)); +INSERT INTO t1 VALUES + (GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')), + (GEOMFROMTEXT('LINESTRING(-1 -1, 1 -1, -1 -1, -1 1, 1 1)')); +EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2; +SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2; +EXPLAIN SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a); +SELECT 1 FROM t1 NATURAL LEFT JOIN t1 AS t2 FORCE INDEX(a); +DROP TABLE t1; + + +--echo # +--echo # Bug #48291 : crash with row() operator,select into @var, and +--echo # subquery returning multiple rows +--echo # + +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES (2),(3); + +--echo # Should not crash +--error ER_SUBQUERY_NO_1_ROW +SELECT 1 FROM t1 WHERE a <> 1 AND NOT +ROW(a,a) <=> ROW((SELECT 1 FROM t1 WHERE 1=2),(SELECT 1 FROM t1)) +INTO @var0; + +DROP TABLE t1; + --echo End of 5.0 tests # diff --git a/mysql-test/t/sp-bugs.test b/mysql-test/t/sp-bugs.test new file mode 100644 index 00000000000..7b94e65a5e9 --- /dev/null +++ b/mysql-test/t/sp-bugs.test @@ -0,0 +1,61 @@ +# Test file for stored procedure bugfixes + +--echo # +--echo # Bug #47412: Valgrind warnings / user can read uninitalized memory +--echo # using SP variables +--echo # + +CREATE SCHEMA testdb; +USE testdb; +DELIMITER |; +CREATE FUNCTION f2 () RETURNS INTEGER +BEGIN + DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1; + RETURN f_not_exists () ; +END| +CREATE PROCEDURE p3 ( arg1 VARCHAR(32) ) +BEGIN + CALL p_not_exists ( ); +END| +DELIMITER ;| +--echo # should not return valgrind warnings +--error ER_SP_DOES_NOT_EXIST +CALL p3 ( f2 () ); + +DROP SCHEMA testdb; + +CREATE SCHEMA testdb; +USE testdb; +DELIMITER |; +CREATE FUNCTION f2 () RETURNS INTEGER +BEGIN + DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1; + RETURN f_not_exists () ; +END| +CREATE PROCEDURE p3 ( arg2 INTEGER ) +BEGIN + CALL p_not_exists ( ); +END| +DELIMITER ;| +--echo # should not return valgrind warnings +--error ER_SP_DOES_NOT_EXIST +CALL p3 ( f2 () ); + +DROP SCHEMA testdb; + +CREATE SCHEMA testdb; +USE testdb; +DELIMITER |; +CREATE FUNCTION f2 () RETURNS INTEGER +BEGIN + DECLARE CONTINUE HANDLER FOR SQLSTATE '42000' SET @aux = 1; + RETURN f_not_exists () ; +END| +DELIMITER ;| +--echo # should not return valgrind warnings +SELECT f2 (); + +DROP SCHEMA testdb; + + +--echo End of 5.1 tests diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 63b92451a65..f61088086b9 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -2431,3 +2431,27 @@ SELECT AVG (a) FROM t1 WHERE b = 999999; --error ER_SP_DOES_NOT_EXIST SELECT non_existent (a) FROM t1 WHERE b = 999999; DROP TABLE t1; + +--echo # +--echo # Bug #47788: Crash in TABLE_LIST::hide_view_error on UPDATE + VIEW + +--echo # SP + MERGE + ALTER +--echo # + +CREATE TABLE t1 (pk INT, b INT, KEY (b)); +CREATE ALGORITHM = TEMPTABLE VIEW v1 AS SELECT * FROM t1; + +CREATE PROCEDURE p1 (a int) UPDATE IGNORE v1 SET b = a; + +--error ER_NON_UPDATABLE_TABLE +CALL p1(5); + +ALTER TABLE t1 CHANGE COLUMN b b2 INT; + +--error ER_VIEW_INVALID +CALL p1(7); + +DROP PROCEDURE p1; +DROP VIEW v1; +DROP TABLE t1; + +--echo End of 5.1 tests diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 544017ebb97..7f2dba00ba8 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -30,7 +30,7 @@ SELECT 1 IN (SELECT 1); SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a)); -- error ER_WRONG_USAGE select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1)); --- error ER_WRONG_USAGE +-- error ER_WRONG_PARAMETERS_TO_PROCEDURE SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1)); -- error ER_BAD_FIELD_ERROR SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL; @@ -3544,4 +3544,19 @@ where v in(select v where t1.g=t2.g) is unknown; drop table t1, t2; +# +# Bug #31157: Crash when select+order by the avg of some field within the +# group by +# +CREATE TABLE t1 (a ENUM('rainbow')); +INSERT INTO t1 VALUES (),(),(),(),(); +SELECT 1 FROM t1 GROUP BY (SELECT 1 FROM t1 ORDER BY AVG(LAST_INSERT_ID())); +DROP TABLE t1; +CREATE TABLE t1 (a LONGBLOB); +INSERT INTO t1 SET a = 'aaaa'; +INSERT INTO t1 SET a = 'aaaa'; +SELECT 1 FROM t1 GROUP BY + (SELECT LAST_INSERT_ID() FROM t1 ORDER BY MIN(a) ASC LIMIT 1); +DROP TABLE t1; + --echo End of 5.1 tests. diff --git a/mysql-test/t/subselect3.test b/mysql-test/t/subselect3.test index 7a2a9f328ef..fab0a462157 100644 --- a/mysql-test/t/subselect3.test +++ b/mysql-test/t/subselect3.test @@ -728,3 +728,69 @@ where from t4, t5 limit 2)); drop table t0, t1, t2, t3, t4, t5; + +--echo # +--echo # BUG#48177 - SELECTs with NOT IN subqueries containing NULL +--echo # values return too many records +--echo # + +CREATE TABLE t1 ( + i1 int DEFAULT NULL, + i2 int DEFAULT NULL +) ; + +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (2, 3); +INSERT INTO t1 VALUES (4, NULL); +INSERT INTO t1 VALUES (4, 0); +INSERT INTO t1 VALUES (NULL, NULL); + +CREATE TABLE t2 ( + i1 int DEFAULT NULL, + i2 int DEFAULT NULL +) ; + +INSERT INTO t2 VALUES (4, NULL); +INSERT INTO t2 VALUES (5, 0); + +--echo +--echo Data in t1 +SELECT i1, i2 FROM t1; + +--echo +--echo Data in subquery (should be filtered out) +SELECT i1, i2 FROM t2 ORDER BY i1; + +FLUSH STATUS; + +--echo +SELECT i1, i2 +FROM t1 +WHERE (i1, i2) + NOT IN (SELECT i1, i2 FROM t2); + +--echo +--echo # Check that the subquery only has to be evaluated once +--echo # for all-NULL values even though there are two (NULL,NULL) records +--echo # Baseline: +SHOW STATUS LIKE '%Handler_read_rnd_next'; + +--echo +INSERT INTO t1 VALUES (NULL, NULL); +FLUSH STATUS; + +--echo +SELECT i1, i2 +FROM t1 +WHERE (i1, i2) + NOT IN (SELECT i1, i2 FROM t2); + +--echo +--echo # Handler_read_rnd_next should be one more than baseline +--echo # (read record from t1, but do not read from t2) +SHOW STATUS LIKE '%Handler_read_rnd_next'; + + +DROP TABLE t1,t2; + +--echo End of 5.1 tests diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 65bafaae77e..cd3c3f81510 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1286,137 +1286,3 @@ CREATE TABLE t1 SELECT 1 % .1234567891234567891234567891234567891234567891234567 DESCRIBE t1; SELECT my_col FROM t1; DROP TABLE t1; - ---echo # ---echo # Bug#45261: Crash, stored procedure + decimal ---echo # - ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings - -CREATE TABLE t1 SELECT - /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001 - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001. - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001 - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - .100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - /* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT - .123456789012345678901234567890123456789012345678901234567890123456 /* 66 */ - AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; - ---echo # ---echo # Test that the integer and decimal parts are properly calculated. ---echo # - -CREATE TABLE t1 (a DECIMAL(30,30)); -INSERT INTO t1 VALUES (0.1),(0.2),(0.3); -CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1; -DESC t2; -DROP TABLE t1,t2; - -CREATE TABLE t1 (a DECIMAL(30,30)); -INSERT INTO t1 VALUES (0.1),(0.2),(0.3); -CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1; -DESC t2; -DROP TABLE t1,t2; - -CREATE TABLE t1 (a DECIMAL(30,30)); -INSERT INTO t1 VALUES (0.1),(0.2),(0.3); -CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1; -DESC t2; -DROP TABLE t1,t2; - ---echo # ---echo # Test that variables get maximum precision. ---echo # - -SET @decimal= 1.1; -CREATE TABLE t1 SELECT @decimal AS c1; -DESC t1; -SELECT * FROM t1; -DROP TABLE t1; diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index 7d56df259ba..02e8763a630 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -452,3 +452,18 @@ DROP TABLE t1; DROP FUNCTION f1; --echo End of 5.0 tests + +--echo # +--echo # Bug #47919 assert in open_table during ALTER temporary table +--echo # + +CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT, PRIMARY KEY (f1)); +CREATE TEMPORARY TABLE t2 LIKE t1; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); + +ALTER TABLE t2 COMMENT = 'ABC'; +UPDATE t2, t1 SET t2.f1 = 2, t1.f1 = 9; +ALTER TABLE t2 COMMENT = 'DEF'; + +DROP TABLE t1, t2; diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 2ad488b7529..175468db702 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -1506,3 +1506,29 @@ DROP VIEW v1; # Wait till we reached the initial number of concurrent sessions --source include/wait_until_count_sessions.inc +--echo # +--echo # Bug #46019: ERROR 1356 When selecting from within another +--echo # view that has Group By +--echo # +CREATE DATABASE mysqltest1; +USE mysqltest1; + +CREATE TABLE t1 (a INT); + +CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT a FROM t1 GROUP BY a; +CREATE SQL SECURITY INVOKER VIEW v2 AS SELECT a FROM v1; + +CREATE USER mysqluser1; + +GRANT SELECT ON TABLE t1 TO mysqluser1; +GRANT SELECT, SHOW VIEW ON TABLE v1 TO mysqluser1; +GRANT SELECT, SHOW VIEW ON TABLE v2 TO mysqluser1; + +--connect (mysqluser1, localhost, mysqluser1,,mysqltest1) +SELECT a FROM v1; +SELECT a FROM v2; + +--connection default +--disconnect mysqluser1 +DROP USER mysqluser1; +DROP DATABASE mysqltest1; diff --git a/mysql-test/t/xa.test b/mysql-test/t/xa.test index 7b1c6a268d5..f84d822170f 100644 --- a/mysql-test/t/xa.test +++ b/mysql-test/t/xa.test @@ -149,6 +149,68 @@ xa end 'a'; xa prepare 'a'; xa commit 'a'; +# +# BUG#43171 - Assertion failed: thd->transaction.xid_state.xid.is_null() +# +CREATE TABLE t1(a INT, KEY(a)) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1),(2); +connect(con1,localhost,root,,); + +# Part 1: Prepare to test XA START after regular transaction deadlock +BEGIN; +UPDATE t1 SET a=3 WHERE a=1; + +connection default; +BEGIN; +UPDATE t1 SET a=4 WHERE a=2; + +connection con1; +let $conn_id= `SELECT CONNECTION_ID()`; +SEND UPDATE t1 SET a=5 WHERE a=2; + +connection default; +let $wait_timeout= 2; +let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE ID=$conn_id AND STATE='Searching rows for update'; +--source include/wait_condition.inc + +--error ER_LOCK_DEADLOCK +UPDATE t1 SET a=5 WHERE a=1; +ROLLBACK; + +# Part 2: Prepare to test XA START after XA transaction deadlock +connection con1; +REAP; +ROLLBACK; +BEGIN; +UPDATE t1 SET a=3 WHERE a=1; + +connection default; +XA START 'xid1'; +UPDATE t1 SET a=4 WHERE a=2; + +connection con1; +SEND UPDATE t1 SET a=5 WHERE a=2; + +connection default; +let $wait_timeout= 2; +let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE ID=$conn_id AND STATE='Searching rows for update'; +--source include/wait_condition.inc + +--error ER_LOCK_DEADLOCK +UPDATE t1 SET a=5 WHERE a=1; +--error ER_XA_RBDEADLOCK +XA END 'xid1'; +XA ROLLBACK 'xid1'; + +XA START 'xid1'; +XA END 'xid1'; +XA ROLLBACK 'xid1'; + +disconnect con1; +DROP TABLE t1; + # Wait till all disconnects are completed --source include/wait_until_count_sessions.inc diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 22b1216f99c..f444e0f0c94 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -1041,9 +1041,11 @@ static void init_one_value(const struct my_option *option, uchar* *variable, *((longlong*) variable)= (longlong) getopt_ll_limit_value((longlong) value, option, NULL); break; case GET_ULL: - case GET_SET: *((ulonglong*) variable)= (ulonglong) getopt_ull_limit_value((ulonglong) value, option, NULL); break; + case GET_SET: + *((ulonglong*) variable)= (ulonglong) value; + break; case GET_DOUBLE: *((double*) variable)= (double) value; break; diff --git a/mysys/typelib.c b/mysys/typelib.c index 92ffe9316ff..a0fe8a96a89 100644 --- a/mysys/typelib.c +++ b/mysys/typelib.c @@ -182,7 +182,10 @@ my_ulonglong find_typeset(char *x, TYPELIB *lib, int *err) { (*err)++; i= x; - while (*x && *x != field_separator) x++; + while (*x && *x != field_separator) + x++; + if (x[0] && x[1]) // skip separator if found + x++; if ((find= find_type(i, lib, 2 | 8) - 1) < 0) DBUG_RETURN(0); result|= (ULL(1) << find); diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index 1d7e80658fd..a81c0964fdd 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -62,7 +62,7 @@ CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint sign CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures'; -CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; +CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; -- Create general_log if CSV is enabled. diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 6f5e385f87d..3ebfc4b1941 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -337,6 +337,10 @@ ALTER TABLE procs_priv MODIFY Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL; +ALTER IGNORE TABLE procs_priv + MODIFY Routine_name char(64) + COLLATE utf8_general_ci DEFAULT '' NOT NULL; + ALTER TABLE procs_priv ADD Routine_type enum('FUNCTION','PROCEDURE') COLLATE utf8_general_ci NOT NULL AFTER Routine_name; diff --git a/sql-common/client.c b/sql-common/client.c index cbed3a5e2a8..a4a2e518edf 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -389,7 +389,7 @@ HANDLE create_named_pipe(MYSQL *mysql, uint connect_timeout, char **arg_host, 0, NULL, OPEN_EXISTING, - 0, + FILE_FLAG_OVERLAPPED, NULL )) != INVALID_HANDLE_VALUE) break; if (GetLastError() != ERROR_PIPE_BUSY) @@ -623,7 +623,7 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) err2: if (error_allow == 0) { - net->vio= vio_new_win32shared_memory(net,handle_file_map,handle_map, + net->vio= vio_new_win32shared_memory(handle_file_map,handle_map, event_server_wrote, event_server_read,event_client_wrote, event_client_read,event_conn_closed); @@ -2030,7 +2030,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, } else { - net->vio=vio_new_win32pipe(hPipe); + net->vio= vio_new_win32pipe(hPipe); my_snprintf(host_info=buff, sizeof(buff)-1, ER(CR_NAMEDPIPE_CONNECTION), unix_socket); } diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index dba32cac6b2..f2ec0e8cf64 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -1433,7 +1433,7 @@ Event_job_data::execute(THD *thd, bool drop) thd->set_query(sp_sql.c_ptr_safe(), sp_sql.length()); { - Parser_state parser_state(thd, thd->query, thd->query_length); + Parser_state parser_state(thd, thd->query(), thd->query_length()); lex_start(thd); if (parse_sql(thd, & parser_state, creation_ctx)) diff --git a/sql/events.cc b/sql/events.cc index 34da0e185b7..458ad61718d 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -465,7 +465,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, if (!dropped) { /* Binlog the create event. */ - DBUG_ASSERT(thd->query && thd->query_length); + DBUG_ASSERT(thd->query() && thd->query_length()); String log_query; if (create_query_string(thd, &log_query)) { @@ -595,8 +595,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, event_queue->update_event(thd, parse_data->dbname, parse_data->name, new_element); /* Binlog the alter event. */ - DBUG_ASSERT(thd->query && thd->query_length); - write_bin_log(thd, TRUE, thd->query, thd->query_length); + DBUG_ASSERT(thd->query() && thd->query_length()); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } } pthread_mutex_unlock(&LOCK_event_metadata); @@ -670,8 +670,8 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) if (event_queue) event_queue->drop_event(thd, dbname, name); /* Binlog the drop event. */ - DBUG_ASSERT(thd->query && thd->query_length); - write_bin_log(thd, TRUE, thd->query, thd->query_length); + DBUG_ASSERT(thd->query() && thd->query_length()); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } pthread_mutex_unlock(&LOCK_event_metadata); DBUG_RETURN(ret); diff --git a/sql/field.cc b/sql/field.cc index 0df9b0fc2e4..354c911e1c0 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. 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 @@ -2480,97 +2480,12 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg, { precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg); set_if_smaller(precision, DECIMAL_MAX_PRECISION); - DBUG_ASSERT(precision >= dec); DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) && (dec <= DECIMAL_MAX_SCALE)); bin_size= my_decimal_get_binary_size(precision, dec); } -/** - Create a field to hold a decimal value from an item. - - @remark The MySQL DECIMAL data type has a characteristic that needs to be - taken into account when deducing the type from a Item_decimal. - - But first, let's briefly recap what is the new MySQL DECIMAL type: - - The declaration syntax for a decimal is DECIMAL(M,D), where: - - * M is the maximum number of digits (the precision). - It has a range of 1 to 65. - * D is the number of digits to the right of the decimal separator (the scale). - It has a range of 0 to 30 and must be no larger than M. - - D and M are used to determine the storage requirements for the integer - and fractional parts of each value. The integer part is to the left of - the decimal separator and to the right is the fractional part. Hence: - - M is the number of digits for the integer and fractional part. - D is the number of digits for the fractional part. - - Consequently, M - D is the number of digits for the integer part. For - example, a DECIMAL(20,10) column has ten digits on either side of - the decimal separator. - - The characteristic that needs to be taken into account is that the - backing type for Item_decimal is a my_decimal that has a higher - precision (DECIMAL_MAX_POSSIBLE_PRECISION, see my_decimal.h) than - DECIMAL. - - Drawing a comparison between my_decimal and DECIMAL: - - * M has a range of 1 to 81. - * D has a range of 0 to 81. - - There can be a difference in range if the decimal contains a integer - part. This is because the fractional part must always be on a group - boundary, leaving at least one group for the integer part. Since each - group is 9 (DIG_PER_DEC1) digits and there are 9 (DECIMAL_BUFF_LENGTH) - groups, the fractional part is limited to 72 digits if there is at - least one digit in the integral part. - - Although the backing type for a DECIMAL is also my_decimal, every - time a my_decimal is stored in a DECIMAL field, the precision and - scale are explicitly capped at 65 (DECIMAL_MAX_PRECISION) and 30 - (DECIMAL_MAX_SCALE) digits, following my_decimal truncation procedure - (FIX_INTG_FRAC_ERROR). -*/ - -Field_new_decimal * -Field_new_decimal::new_decimal_field(const Item *item) -{ - uint32 len; - uint intg= item->decimal_int_part(), scale= item->decimals; - - DBUG_ASSERT(item->decimal_precision() >= item->decimals); - - /* - Employ a procedure along the lines of the my_decimal truncation process: - - If the integer part is equal to or bigger than the maximum precision: - Truncate integer part to fit and the fractional becomes zero. - - Otherwise: - Truncate fractional part to fit. - */ - if (intg >= DECIMAL_MAX_PRECISION) - { - intg= DECIMAL_MAX_PRECISION; - scale= 0; - } - else - { - uint room= min(DECIMAL_MAX_PRECISION - intg, DECIMAL_MAX_SCALE); - if (scale > room) - scale= room; - } - - len= my_decimal_precision_to_length(intg + scale, scale, item->unsigned_flag); - - return new Field_new_decimal(len, item->maybe_null, item->name, scale, - item->unsigned_flag); -} - - int Field_new_decimal::reset(void) { store_value(&decimal_zero); @@ -6550,20 +6465,9 @@ uint Field::is_equal(Create_field *new_field) } -/* If one of the fields is binary and the other one isn't return 1 else 0 */ - -bool Field_str::compare_str_field_flags(Create_field *new_field, uint32 flag_arg) -{ - return (((new_field->flags & (BINCMP_FLAG | BINARY_FLAG)) && - !(flag_arg & (BINCMP_FLAG | BINARY_FLAG))) || - (!(new_field->flags & (BINCMP_FLAG | BINARY_FLAG)) && - (flag_arg & (BINCMP_FLAG | BINARY_FLAG)))); -} - - uint Field_str::is_equal(Create_field *new_field) { - if (compare_str_field_flags(new_field, flags)) + if (field_flags_are_binary() != new_field->field_flags_are_binary()) return 0; return ((new_field->sql_type == real_type()) && @@ -8329,7 +8233,7 @@ uint Field_blob::max_packed_col_length(uint max_length) uint Field_blob::is_equal(Create_field *new_field) { - if (compare_str_field_flags(new_field, flags)) + if (field_flags_are_binary() != new_field->field_flags_are_binary()) return 0; return ((new_field->sql_type == get_blob_type_from_length(max_data_length())) @@ -8889,7 +8793,7 @@ uint Field_enum::is_equal(Create_field *new_field) The fields are compatible if they have the same flags, type, charset and have the same underlying length. */ - if (compare_str_field_flags(new_field, flags) || + if (new_field->field_flags_are_binary() != field_flags_are_binary() || new_field->sql_type != real_type() || new_field->charset != field_charset || new_field->pack_length != pack_length()) @@ -9658,7 +9562,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, } if (length == 0) - fld_length= 0; /* purecov: inspected */ + fld_length= NULL; /* purecov: inspected */ } sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1; @@ -9810,8 +9714,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, case MYSQL_TYPE_TIMESTAMP: if (fld_length == NULL) { - /* Compressed date YYYYMMDDHHMMSS */ - length= MAX_DATETIME_COMPRESSED_WIDTH; + length= MAX_DATETIME_WIDTH; } else if (length != MAX_DATETIME_WIDTH) { @@ -9876,7 +9779,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, sql_type= MYSQL_TYPE_NEWDATE; /* fall trough */ case MYSQL_TYPE_NEWDATE: - length= 10; + length= MAX_DATE_WIDTH; break; case MYSQL_TYPE_TIME: length= 10; @@ -9957,6 +9860,17 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type, DBUG_RETURN(TRUE); } + switch (fld_type) { + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_NEWDATE: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_TIMESTAMP: + charset= &my_charset_bin; + flags|= BINCMP_FLAG; + default: break; + } + DBUG_RETURN(FALSE); /* success */ } diff --git a/sql/field.h b/sql/field.h index 51397cad7b1..18b017516a7 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1,7 +1,7 @@ #ifndef FIELD_INCLUDED #define FIELD_INCLUDED -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc. 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 @@ -613,15 +613,17 @@ protected: handle_int64(to, from, low_byte_first_from, table->s->db_low_byte_first); return from + sizeof(int64); } + + bool field_flags_are_binary() + { + return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0; + } + }; class Field_num :public Field { public: - /** - The scale of the Field's value, i.e. the number of digits to the right - of the decimal point. - */ const uint8 dec; bool zerofill,unsigned_flag; // Purify cannot handle bit fields Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, @@ -672,7 +674,6 @@ public: friend class Create_field; my_decimal *val_decimal(my_decimal *); virtual bool str_needs_quotes() { return TRUE; } - bool compare_str_field_flags(Create_field *new_field, uint32 flags); uint is_equal(Create_field *new_field); }; @@ -780,11 +781,6 @@ public: Field_new_decimal(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, uint8 dec_arg, bool unsigned_arg); - /* - Create a field to hold a decimal value from an item. - Truncates the precision and/or scale if necessary. - */ - static Field_new_decimal *new_decimal_field(const Item *item); enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } Item_result result_type () const { return DECIMAL_RESULT; } @@ -1287,12 +1283,12 @@ public: Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, CHARSET_INFO *cs) - :Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg, + :Field_str(ptr_arg, MAX_DATE_WIDTH, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, cs) {} Field_date(bool maybe_null_arg, const char *field_name_arg, CHARSET_INFO *cs) - :Field_str((uchar*) 0,10, maybe_null_arg ? (uchar*) "": 0,0, + :Field_str((uchar*) 0, MAX_DATE_WIDTH, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, cs) {} enum_field_types type() const { return MYSQL_TYPE_DATE;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } @@ -1402,12 +1398,12 @@ public: Field_datetime(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, CHARSET_INFO *cs) - :Field_str(ptr_arg, 19, null_ptr_arg, null_bit_arg, + :Field_str(ptr_arg, MAX_DATETIME_WIDTH, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, cs) {} Field_datetime(bool maybe_null_arg, const char *field_name_arg, CHARSET_INFO *cs) - :Field_str((uchar*) 0,19, maybe_null_arg ? (uchar*) "": 0,0, + :Field_str((uchar*) 0, MAX_DATETIME_WIDTH, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, cs) {} enum_field_types type() const { return MYSQL_TYPE_DATETIME;} #ifdef HAVE_LONG_LONG @@ -2079,6 +2075,11 @@ public: Item *on_update_value, LEX_STRING *comment, char *change, List *interval_list, CHARSET_INFO *cs, uint uint_geom_type); + + bool field_flags_are_binary() + { + return (flags & (BINCMP_FLAG | BINARY_FLAG)) != 0; + } }; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index dfd7ddc4d6c..9fdb8b628ca 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -5525,7 +5525,7 @@ int ha_ndbcluster::create(const char *name, if (share && !do_event_op) share->flags|= NSF_NO_BINLOG; ndbcluster_log_schema_op(thd, share, - thd->query, thd->query_length, + thd->query(), thd->query_length(), share->db, share->table_name, m_table->getObjectId(), m_table->getObjectVersion(), @@ -5967,7 +5967,8 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) */ if (!is_old_table_tmpfile) ndbcluster_log_schema_op(current_thd, share, - current_thd->query, current_thd->query_length, + current_thd->query(), + current_thd->query_length(), old_dbname, m_tabname, ndb_table_id, ndb_table_version, SOT_RENAME_TABLE, @@ -6162,7 +6163,7 @@ retry_temporary_error1: current_thd->lex->sql_command != SQLCOM_TRUNCATE) { ndbcluster_log_schema_op(thd, share, - thd->query, thd->query_length, + thd->query(), thd->query_length(), share->db, share->table_name, ndb_table_id, ndb_table_version, SOT_DROP_TABLE, 0, 0, 1); @@ -6884,7 +6885,7 @@ static void ndbcluster_drop_database(handlerton *hton, char *path) THD *thd= current_thd; ha_ndbcluster::set_dbname(path, db); ndbcluster_log_schema_op(thd, 0, - thd->query, thd->query_length, + thd->query(), thd->query_length(), db, "", 0, 0, SOT_DROP_DB, 0, 0, 0); #endif DBUG_VOID_RETURN; @@ -10251,13 +10252,13 @@ int ndbcluster_alter_tablespace(handlerton *hton, #ifdef HAVE_NDB_BINLOG if (is_tablespace) ndbcluster_log_schema_op(thd, 0, - thd->query, thd->query_length, + thd->query(), thd->query_length(), "", alter_info->tablespace_name, 0, 0, SOT_TABLESPACE, 0, 0, 0); else ndbcluster_log_schema_op(thd, 0, - thd->query, thd->query_length, + thd->query(), thd->query_length(), "", alter_info->logfile_group_name, 0, 0, SOT_LOGFILE_GROUP, 0, 0, 0); diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index 2a87697c7fa..27af3f2cf2f 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -241,8 +241,8 @@ static void dbug_print_table(const char *info, TABLE *table) static void run_query(THD *thd, char *buf, char *end, const int *no_print_error, my_bool disable_binlog) { - ulong save_thd_query_length= thd->query_length; - char *save_thd_query= thd->query; + ulong save_thd_query_length= thd->query_length(); + char *save_thd_query= thd->query(); ulong save_thread_id= thd->variables.pseudo_thread_id; struct system_status_var save_thd_status_var= thd->status_var; THD_TRANS save_thd_transaction_all= thd->transaction.all; @@ -259,12 +259,12 @@ static void run_query(THD *thd, char *buf, char *end, if (disable_binlog) thd->options&= ~OPTION_BIN_LOG; - DBUG_PRINT("query", ("%s", thd->query)); + DBUG_PRINT("query", ("%s", thd->query())); DBUG_ASSERT(!thd->in_sub_stmt); DBUG_ASSERT(!thd->prelocked_mode); - mysql_parse(thd, thd->query, thd->query_length, &found_semicolon); + mysql_parse(thd, thd->query(), thd->query_length(), &found_semicolon); if (no_print_error && thd->is_slave_error) { diff --git a/sql/handler.cc b/sql/handler.cc index 0a7ea682313..2414ba64196 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1331,7 +1331,8 @@ int ha_rollback_trans(THD *thd, bool all) } trans->ha_list= 0; trans->no_2pc=0; - if (is_real_trans && thd->transaction_rollback_request) + if (is_real_trans && thd->transaction_rollback_request && + thd->transaction.xid_state.xa_state != XA_NOTR) thd->transaction.xid_state.rm_error= thd->main_da.sql_errno(); if (all) thd->variables.tx_isolation=thd->session_tx_isolation; diff --git a/sql/handler.h b/sql/handler.h index 577b239fba1..4fe38b659bb 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -408,7 +408,6 @@ struct xid_t { my_xid get_my_xid() { return gtrid_length == MYSQL_XID_GTRID_LEN && bqual_length == 0 && - !memcmp(data+MYSQL_XID_PREFIX_LEN, &server_id, sizeof(server_id)) && !memcmp(data, MYSQL_XID_PREFIX, MYSQL_XID_PREFIX_LEN) ? quick_get_my_xid() : 0; } diff --git a/sql/item.cc b/sql/item.cc index 86e4551e55b..8f487872f1b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -435,26 +435,17 @@ Item::Item(THD *thd, Item *item): } -/** - Decimal precision of the item. - - @remark The precision must not be capped as it can be used in conjunction - with Item::decimals to determine the size of the integer part when - constructing a decimal data type. - - @see Item::decimal_int_part() - @see Item::decimals -*/ - uint Item::decimal_precision() const { - uint precision= max_length; Item_result restype= result_type(); if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT)) - precision= my_decimal_length_to_precision(max_length, decimals, unsigned_flag); - - return precision; + { + uint prec= + my_decimal_length_to_precision(max_length, decimals, unsigned_flag); + return min(prec, DECIMAL_MAX_PRECISION); + } + return min(max_length, DECIMAL_MAX_PRECISION); } @@ -4908,7 +4899,9 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) switch (field_type()) { case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: - field= Field_new_decimal::new_decimal_field(this); + field= new Field_new_decimal((uchar*) 0, max_length, null_ptr, 0, + Field::NONE, name, decimals, 0, + unsigned_flag); break; case MYSQL_TYPE_TINY: field= new Field_tiny((uchar*) 0, max_length, null_ptr, 0, Field::NONE, @@ -6866,52 +6859,61 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) } /** - Compare the value stored in field, with the original item. + Compare the value stored in field with the expression from the query. - @param field field which the item is converted and stored in - @param item original item + @param field Field which the Item is stored in after conversion + @param item Original expression from query - @return Return an integer greater than, equal to, or less than 0 if - the value stored in the field is greater than, equal to, - or less than the original item + @return Returns an integer greater than, equal to, or less than 0 if + the value stored in the field is greater than, equal to, + or less than the original Item. A 0 may also be returned if + out of memory. @note We only use this on the range optimizer/partition pruning, because in some cases we can't store the value in the field without some precision/character loss. */ -int stored_field_cmp_to_item(Field *field, Item *item) +int stored_field_cmp_to_item(THD *thd, Field *field, Item *item) { - Item_result res_type=item_cmp_type(field->result_type(), item->result_type()); if (res_type == STRING_RESULT) { char item_buff[MAX_FIELD_WIDTH]; char field_buff[MAX_FIELD_WIDTH]; - String item_tmp(item_buff,sizeof(item_buff),&my_charset_bin),*item_result; + + String item_tmp(item_buff,sizeof(item_buff),&my_charset_bin); String field_tmp(field_buff,sizeof(field_buff),&my_charset_bin); - enum_field_types field_type; - item_result=item->val_str(&item_tmp); + String *item_result= item->val_str(&item_tmp); + /* + Some implementations of Item::val_str(String*) actually modify + the field Item::null_value, hence we can't check it earlier. + */ if (item->null_value) return 0; - field->val_str(&field_tmp); + String *field_result= field->val_str(&field_tmp); - /* - If comparing DATE with DATETIME, append the time-part to the DATE. - So that the strings are equally formatted. - A DATE converted to string is 10 characters, and a DATETIME converted - to string is 19 characters. - */ - field_type= field->type(); - if (field_type == MYSQL_TYPE_DATE && - item_result->length() == 19) - field_tmp.append(" 00:00:00"); - else if (field_type == MYSQL_TYPE_DATETIME && - item_result->length() == 10) - item_result->append(" 00:00:00"); + enum_field_types field_type= field->type(); - return stringcmp(&field_tmp,item_result); + if (field_type == MYSQL_TYPE_DATE || field_type == MYSQL_TYPE_DATETIME) + { + enum_mysql_timestamp_type type= MYSQL_TIMESTAMP_ERROR; + + if (field_type == MYSQL_TYPE_DATE) + type= MYSQL_TIMESTAMP_DATE; + + if (field_type == MYSQL_TYPE_DATETIME) + type= MYSQL_TIMESTAMP_DATETIME; + + const char *field_name= field->field_name; + MYSQL_TIME field_time, item_time; + get_mysql_time_from_str(thd, field_result, type, field_name, &field_time); + get_mysql_time_from_str(thd, item_result, type, field_name, &item_time); + + return my_time_compare(&field_time, &item_time); + } + return stringcmp(field_result, item_result); } if (res_type == INT_RESULT) return 0; // Both are of type int diff --git a/sql/item.h b/sql/item.h index b44e84f4b15..e83634843be 100644 --- a/sql/item.h +++ b/sql/item.h @@ -765,10 +765,9 @@ public: virtual cond_result eq_cmp_result() const { return COND_OK; } inline uint float_length(uint decimals_par) const { return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;} - /** Returns the uncapped decimal precision of this item. */ virtual uint decimal_precision() const; inline int decimal_int_part() const - { return decimal_precision() - decimals; } + { return my_decimal_int_part(decimal_precision(), decimals); } /* Returns true if this is constant (during query execution, i.e. its value will not change until next fix_fields) and its value is known. @@ -3128,6 +3127,6 @@ void mark_select_range_as_dependent(THD *thd, extern Cached_item *new_Cached_item(THD *thd, Item *item); extern Item_result item_cmp_type(Item_result a,Item_result b); extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item); -extern int stored_field_cmp_to_item(Field *field, Item *item); - +extern int stored_field_cmp_to_item(THD *thd, Field *field, Item *item); #endif /* ITEM_INCLUDED */ + diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index c29031d25b5..c6b88cd8188 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -636,6 +636,62 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) return 0; } +/** + Parse date provided in a string to a MYSQL_TIME. + + @param[in] thd Thread handle + @param[in] str A string to convert + @param[in] warn_type Type of the timestamp for issuing the warning + @param[in] warn_name Field name for issuing the warning + @param[out] l_time The MYSQL_TIME objects is initialized. + + Parses a date provided in the string str into a MYSQL_TIME object. If the + string contains an incorrect date or doesn't correspond to a date at all + then a warning is issued. The warn_type and the warn_name arguments are used + as the name and the type of the field when issuing the warning. If any input + was discarded (trailing or non-timestamp-y characters), return value will be + TRUE. + + @return Status flag + @retval FALSE Success. + @retval True Indicates failure. +*/ + +bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type, + const char *warn_name, MYSQL_TIME *l_time) +{ + bool value; + int error; + enum_mysql_timestamp_type timestamp_type; + + timestamp_type= + str_to_datetime(str->ptr(), str->length(), l_time, + (TIME_FUZZY_DATE | MODE_INVALID_DATES | + (thd->variables.sql_mode & + (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE))), + &error); + + if (timestamp_type == MYSQL_TIMESTAMP_DATETIME || + timestamp_type == MYSQL_TIMESTAMP_DATE) + /* + Do not return yet, we may still want to throw a "trailing garbage" + warning. + */ + value= FALSE; + else + { + value= TRUE; + error= 1; /* force warning */ + } + + if (error > 0) + make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + str->ptr(), str->length(), + warn_type, warn_name); + + return value; +} + /** @brief Convert date provided in a string to the int representation. @@ -650,51 +706,21 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) representation. If the string contains wrong date or doesn't contain it at all then a warning is issued. The warn_type and the warn_name arguments are used as the name and the type of the - field when issuing the warning. If any input was discarded - (trailing or non-timestampy characters), was_cut will be non-zero. - was_type will return the type str_to_datetime() could correctly - extract. + field when issuing the warning. @return converted value. 0 on error and on zero-dates -- check 'failure' */ - -static ulonglong -get_date_from_str(THD *thd, String *str, timestamp_type warn_type, - char *warn_name, bool *error_arg) +static ulonglong get_date_from_str(THD *thd, String *str, + timestamp_type warn_type, + const char *warn_name, bool *error_arg) { - ulonglong value= 0; - int error; MYSQL_TIME l_time; - enum_mysql_timestamp_type ret; + *error_arg= get_mysql_time_from_str(thd, str, warn_type, warn_name, &l_time); - ret= str_to_datetime(str->ptr(), str->length(), &l_time, - (TIME_FUZZY_DATE | MODE_INVALID_DATES | - (thd->variables.sql_mode & - (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE))), - &error); - - if (ret == MYSQL_TIMESTAMP_DATETIME || ret == MYSQL_TIMESTAMP_DATE) - { - /* - Do not return yet, we may still want to throw a "trailing garbage" - warning. - */ - *error_arg= FALSE; - value= TIME_to_ulonglong_datetime(&l_time); - } - else - { - *error_arg= TRUE; - error= 1; /* force warning */ - } - - if (error > 0) - make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - str->ptr(), str->length(), - warn_type, warn_name); - - return value; + if (*error_arg) + return 0; + return TIME_to_ulonglong_datetime(&l_time); } @@ -1559,61 +1585,73 @@ longlong Item_in_optimizer::val_int() if (cache->null_value) { + /* + We're evaluating + " [NOT] IN (SELECT ...)" + where one or more of the outer values is NULL. + */ if (((Item_in_subselect*)args[1])->is_top_level_item()) { /* - We're evaluating "NULL IN (SELECT ...)". The result can be NULL or - FALSE, and we can return one instead of another. Just return NULL. + We're evaluating a top level item, e.g. + " IN (SELECT ...)", + and in this case a NULL value in the outer_value_list means + that the result shall be NULL/FALSE (makes no difference for + top level items). The cached value is NULL, so just return + NULL. */ null_value= 1; } else { - if (!((Item_in_subselect*)args[1])->is_correlated && - result_for_null_param != UNKNOWN) + /* + We're evaluating an item where a NULL value in either the + outer or inner value list does not automatically mean that we + can return NULL/FALSE. An example of such a query is + " NOT IN (SELECT ...)" + The result when there is at least one NULL value is: NULL if the + SELECT evaluated over the non-NULL values produces at least + one row, FALSE otherwise + */ + Item_in_subselect *item_subs=(Item_in_subselect*)args[1]; + bool all_left_cols_null= true; + const uint ncols= cache->cols(); + + /* + Turn off the predicates that are based on column compares for + which the left part is currently NULL + */ + for (uint i= 0; i < ncols; i++) { - /* Use cached value from previous execution */ - null_value= result_for_null_param; + if (cache->element_index(i)->null_value) + item_subs->set_cond_guard_var(i, FALSE); + else + all_left_cols_null= false; } - else + + if (!((Item_in_subselect*)args[1])->is_correlated && + all_left_cols_null && result_for_null_param != UNKNOWN) { - /* - We're evaluating "NULL IN (SELECT ...)". The result is: - FALSE if SELECT produces an empty set, or - NULL otherwise. - We disable the predicates we've pushed down into subselect, run the - subselect and see if it has produced any rows. + /* + This is a non-correlated subquery, all values in the outer + value list are NULL, and we have already evaluated the + subquery for all NULL values: Return the same result we + did last time without evaluating the subquery. */ - Item_in_subselect *item_subs=(Item_in_subselect*)args[1]; - if (cache->cols() == 1) - { - item_subs->set_cond_guard_var(0, FALSE); - (void) args[1]->val_bool_result(); - result_for_null_param= null_value= !item_subs->engine->no_rows(); - item_subs->set_cond_guard_var(0, TRUE); - } - else - { - uint i; - uint ncols= cache->cols(); - /* - Turn off the predicates that are based on column compares for - which the left part is currently NULL - */ - for (i= 0; i < ncols; i++) - { - if (cache->element_index(i)->null_value) - item_subs->set_cond_guard_var(i, FALSE); - } - - (void) args[1]->val_bool_result(); - result_for_null_param= null_value= !item_subs->engine->no_rows(); - - /* Turn all predicates back on */ - for (i= 0; i < ncols; i++) - item_subs->set_cond_guard_var(i, TRUE); - } + null_value= result_for_null_param; + } + else + { + /* The subquery has to be evaluated */ + (void) args[1]->val_bool_result(); + null_value= !item_subs->engine->no_rows(); + if (all_left_cols_null) + result_for_null_param= null_value; } + + /* Turn all predicates back on */ + for (uint i= 0; i < ncols; i++) + item_subs->set_cond_guard_var(i, TRUE); } return 0; } @@ -2191,7 +2229,7 @@ uint Item_func_ifnull::decimal_precision() const int arg1_int_part= args[1]->decimal_int_part(); int max_int_part= max(arg0_int_part, arg1_int_part); int precision= max_int_part + decimals; - return precision; + return min(precision, DECIMAL_MAX_PRECISION); } @@ -2375,7 +2413,7 @@ uint Item_func_if::decimal_precision() const int arg1_prec= args[1]->decimal_int_part(); int arg2_prec= args[2]->decimal_int_part(); int precision=max(arg1_prec,arg2_prec) + decimals; - return precision; + return min(precision, DECIMAL_MAX_PRECISION); } @@ -2783,7 +2821,7 @@ uint Item_func_case::decimal_precision() const if (else_expr_num != -1) set_if_bigger(max_int_part, args[else_expr_num]->decimal_int_part()); - return max_int_part + decimals; + return min(max_int_part + decimals, DECIMAL_MAX_PRECISION); } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 3462bed94a2..ec703d0a9f9 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1725,4 +1725,6 @@ inline Item *and_conds(Item *a, Item *b) Item *and_expressions(Item *a, Item *b, Item **org_item); +bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type, + const char *warn_name, MYSQL_TIME *l_time); #endif /* ITEM_CMPFUNC_INCLUDED */ diff --git a/sql/item_func.cc b/sql/item_func.cc index d9e6f76dd6b..ac52f36474a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -451,8 +451,45 @@ Field *Item_func::tmp_table_field(TABLE *table) return make_string_field(table); break; case DECIMAL_RESULT: - field= Field_new_decimal::new_decimal_field(this); + { + uint8 dec= decimals; + uint8 intg= decimal_precision() - dec; + uint32 len= max_length; + + /* + Trying to put too many digits overall in a DECIMAL(prec,dec) + will always throw a warning. We must limit dec to + DECIMAL_MAX_SCALE however to prevent an assert() later. + */ + + if (dec > 0) + { + int overflow; + + dec= min(dec, DECIMAL_MAX_SCALE); + + /* + If the value still overflows the field with the corrected dec, + we'll throw out decimals rather than integers. This is still + bad and of course throws a truncation warning. + */ + + const int required_length= + my_decimal_precision_to_length(intg + dec, dec, + unsigned_flag); + + overflow= required_length - len; + + if (overflow > 0) + dec= max(0, dec - overflow); // too long, discard fract + else + /* Corrected value fits. */ + len= required_length; + } + + field= new Field_new_decimal(len, maybe_null, name, dec, unsigned_flag); break; + } case ROW_RESULT: default: // This case should never be chosen @@ -4739,19 +4776,6 @@ void Item_func_get_user_var::fix_length_and_dec() } -uint Item_func_get_user_var::decimal_precision() const -{ - uint precision= max_length; - Item_result restype= result_type(); - - /* Default to maximum as the precision is unknown a priori. */ - if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT)) - precision= DECIMAL_MAX_PRECISION; - - return precision; -} - - bool Item_func_get_user_var::const_item() const { return (!var_entry || current_thd->query_id != var_entry->update_query_id); diff --git a/sql/item_func.h b/sql/item_func.h index 628878bcaed..6f2b3f0bfc2 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1396,7 +1396,6 @@ public: table_map used_tables() const { return const_item() ? 0 : RAND_TABLE_BIT; } bool eq(const Item *item, bool binary_cmp) const; - uint decimal_precision() const; private: bool set_value(THD *thd, sp_rcontext *ctx, Item **it); diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index a34204b7181..3c5990eb359 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -84,7 +84,9 @@ String *Item_func_geometry_from_wkb::val_str(String *str) if (args[0]->field_type() == MYSQL_TYPE_GEOMETRY) { - return args[0]->val_str(str); + String *str_ret= args[0]->val_str(str); + null_value= args[0]->null_value; + return str_ret; } wkb= args[0]->val_str(&arg_val); @@ -94,7 +96,10 @@ String *Item_func_geometry_from_wkb::val_str(String *str) str->set_charset(&my_charset_bin); if (str->reserve(SRID_SIZE, 512)) - return 0; + { + null_value= TRUE; /* purecov: inspected */ + return 0; /* purecov: inspected */ + } str->length(0); str->q_append(srid); if ((null_value= diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index da651cec70c..fa776ea3dca 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -311,9 +311,14 @@ void Item_subselect::update_used_tables() void Item_subselect::print(String *str, enum_query_type query_type) { - str->append('('); - engine->print(str, query_type); - str->append(')'); + if (engine) + { + str->append('('); + engine->print(str, query_type); + str->append(')'); + } + else + str->append("(...)"); } @@ -1949,6 +1954,7 @@ int subselect_single_select_engine::exec() tab->read_record.record= tab->table->record[0]; tab->read_record.thd= join->thd; tab->read_record.ref_length= tab->table->file->ref_length; + tab->read_record.unlock_row= rr_unlock_row; *(last_changed_tab++)= tab; break; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 08a48c6ce2f..38251294053 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -517,7 +517,8 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table, name, table->s, collation.collation); break; case DECIMAL_RESULT: - field= Field_new_decimal::new_decimal_field(this); + field= new Field_new_decimal(max_length, maybe_null, name, + decimals, unsigned_flag); break; case ROW_RESULT: default: diff --git a/sql/log.cc b/sql/log.cc index 1ffb2e8b5c3..3d863583859 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1579,7 +1579,6 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) trx_data->at_least_one_stmt_committed = my_b_tell(&trx_data->trans_log) > 0; -end: if (!all) trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt commit DBUG_RETURN(error); @@ -1747,7 +1746,7 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv) int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); int const error= thd->binlog_query(THD::STMT_QUERY_TYPE, - thd->query, thd->query_length, TRUE, FALSE, errcode); + thd->query(), thd->query_length(), TRUE, FALSE, errcode); DBUG_RETURN(error); } @@ -1766,7 +1765,7 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv) int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); int error= thd->binlog_query(THD::STMT_QUERY_TYPE, - thd->query, thd->query_length, TRUE, FALSE, errcode); + thd->query(), thd->query_length(), TRUE, FALSE, errcode); DBUG_RETURN(error); } binlog_trans_log_truncate(thd, *(my_off_t*)sv); @@ -3689,7 +3688,7 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock) } old_name=name; name=0; // Don't free name - close(LOG_CLOSE_TO_BE_OPENED); + close(LOG_CLOSE_TO_BE_OPENED | LOG_CLOSE_INDEX); /* Note that at this point, log_state != LOG_CLOSED (important for is_open()). @@ -3704,8 +3703,10 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock) trigger temp tables deletion on slaves. */ - open(old_name, log_type, new_name_ptr, - io_cache_type, no_auto_events, max_size, 1); + /* reopen index binlog file, BUG#34582 */ + if (!open_index_file(index_file_name, 0)) + open(old_name, log_type, new_name_ptr, + io_cache_type, no_auto_events, max_size, 1); my_free(old_name,MYF(0)); end: diff --git a/sql/log_event.cc b/sql/log_event.cc index d36b126fd2e..060b675b0e4 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3059,7 +3059,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, thd->query_id = next_query_id(); VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->variables.pseudo_thread_id= thread_id; // for temp tables - DBUG_PRINT("query",("%s",thd->query)); + DBUG_PRINT("query",("%s", thd->query())); if (ignored_error_code((expected_error= error_code)) || !unexpected_error_code(expected_error)) @@ -3153,7 +3153,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, /* Execute the query (note that we bypass dispatch_command()) */ const char* found_semicolon= NULL; - mysql_parse(thd, thd->query, thd->query_length, &found_semicolon); + mysql_parse(thd, thd->query(), thd->query_length(), &found_semicolon); log_slow_statement(thd); } else @@ -3165,7 +3165,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, we exit gracefully; otherwise we warn about the bad error and tell DBA to check/fix it. */ - if (mysql_test_parse_for_slave(thd, thd->query, thd->query_length)) + if (mysql_test_parse_for_slave(thd, thd->query(), thd->query_length())) clear_all_errors(thd, const_cast(rli)); /* Can ignore query */ else { @@ -3175,7 +3175,7 @@ Query partially completed on the master (error on master: %d) \ and was aborted. There is a chance that your master is inconsistent at this \ point. If you are sure that your master is ok, run this query manually on the \ slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; \ -START SLAVE; . Query: '%s'", expected_error, thd->query); +START SLAVE; . Query: '%s'", expected_error, thd->query()); thd->is_slave_error= 1; } goto end; @@ -3183,7 +3183,7 @@ START SLAVE; . Query: '%s'", expected_error, thd->query); /* If the query was not ignored, it is printed to the general log */ if (!thd->is_error() || thd->main_da.sql_errno() != ER_SLAVE_IGNORED_TABLE) - general_log_write(thd, COM_QUERY, thd->query, thd->query_length); + general_log_write(thd, COM_QUERY, thd->query(), thd->query_length()); compare_errors: @@ -4530,8 +4530,8 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli, new_db.length= db_len; new_db.str= (char *) rpl_filter->get_rewrite_db(db, &new_db.length); thd->set_db(new_db.str, new_db.length); - DBUG_ASSERT(thd->query == 0); - thd->query_length= 0; // Should not be needed + DBUG_ASSERT(thd->query() == 0); + thd->set_query_inner(NULL, 0); // Should not be needed thd->is_slave_error= 0; clear_all_errors(thd, const_cast(rli)); @@ -7555,7 +7555,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) } if (get_flags(STMT_END_F)) - if (error= rows_event_stmt_cleanup(rli, thd)) + if ((error= rows_event_stmt_cleanup(rli, thd))) rli->report(ERROR_LEVEL, error, "Error in %s event: commit of row events failed, " "table `%s`.`%s`", diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 18e5284490c..7ed36ed33b0 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1814,7 +1814,7 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) are involved, commit the transaction and flush the pending event to the binlog. */ - if (error= ha_autocommit_or_rollback(thd, 0)) + if ((error= ha_autocommit_or_rollback(thd, 0))) rli->report(ERROR_LEVEL, error, "Error in %s event: commit of row events failed, " "table `%s`.`%s`", diff --git a/sql/my_decimal.h b/sql/my_decimal.h index b1df1395dcd..21669e82c44 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -48,12 +48,10 @@ C_MODE_END digits * number of decimal digits in one our big digit - number of decimal digits in one our big digit decreased by 1 (because we always put decimal point on the border of our big digits)) - - This value is 65 due to historical reasons partly due to it being used - as the maximum allowed precision and not the actual maximum precision. */ #define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2) #define DECIMAL_MAX_SCALE 30 +#define DECIMAL_NOT_SPECIFIED 31 /** maximum length of string representation (number of maximum decimal @@ -77,6 +75,12 @@ inline uint my_decimal_size(uint precision, uint scale) } +inline int my_decimal_int_part(uint precision, uint decimals) +{ + return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals); +} + + /** my_decimal class limits 'decimal_t' type to what we need in MySQL. @@ -180,7 +184,7 @@ inline uint my_decimal_length_to_precision(uint length, uint scale, } inline uint32 my_decimal_precision_to_length_no_truncation(uint precision, - uint scale, + uint8 scale, bool unsigned_flag) { /* @@ -192,7 +196,7 @@ inline uint32 my_decimal_precision_to_length_no_truncation(uint precision, (unsigned_flag || !precision ? 0 : 1)); } -inline uint32 my_decimal_precision_to_length(uint precision, uint scale, +inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale, bool unsigned_flag) { /* diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 035ab0e70cc..8468e7cf79a 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1718,7 +1718,7 @@ static void network_init(void) saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor; saPipeSecurity.bInheritHandle = FALSE; if ((hPipe= CreateNamedPipe(pipe_name, - PIPE_ACCESS_DUPLEX, + PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, @@ -2521,7 +2521,7 @@ terribly wrong...\n"); } fprintf(stderr, "Trying to get some variables.\n\ Some pointers may be invalid and cause the dump to abort...\n"); - my_safe_print_str("thd->query", thd->query, 1024); + my_safe_print_str("thd->query", thd->query(), 1024); fprintf(stderr, "thd->thread_id=%lu\n", (ulong) thd->thread_id); fprintf(stderr, "thd->killed=%s\n", kreason); } @@ -5205,17 +5205,26 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) pthread_handler_t handle_connections_namedpipes(void *arg) { HANDLE hConnectedPipe; - BOOL fConnected; + OVERLAPPED connectOverlapped = {0}; THD *thd; my_thread_init(); DBUG_ENTER("handle_connections_namedpipes"); - (void) my_pthread_getprio(pthread_self()); // For debugging + connectOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); DBUG_PRINT("general",("Waiting for named pipe connections.")); while (!abort_loop) { /* wait for named pipe connection */ - fConnected = ConnectNamedPipe(hPipe, NULL); + BOOL fConnected= ConnectNamedPipe(hPipe, &connectOverlapped); + if (!fConnected && (GetLastError() == ERROR_IO_PENDING)) + { + /* + ERROR_IO_PENDING says async IO has started but not yet finished. + GetOverlappedResult will wait for completion. + */ + DWORD bytes; + fConnected= GetOverlappedResult(hPipe, &connectOverlapped,&bytes, TRUE); + } if (abort_loop) break; if (!fConnected) @@ -5224,7 +5233,7 @@ pthread_handler_t handle_connections_namedpipes(void *arg) { CloseHandle(hPipe); if ((hPipe= CreateNamedPipe(pipe_name, - PIPE_ACCESS_DUPLEX, + PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, @@ -5244,7 +5253,7 @@ pthread_handler_t handle_connections_namedpipes(void *arg) hConnectedPipe = hPipe; /* create new pipe for new connection */ if ((hPipe = CreateNamedPipe(pipe_name, - PIPE_ACCESS_DUPLEX, + PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, @@ -5266,7 +5275,7 @@ pthread_handler_t handle_connections_namedpipes(void *arg) CloseHandle(hConnectedPipe); continue; } - if (!(thd->net.vio = vio_new_win32pipe(hConnectedPipe)) || + if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) || my_net_init(&thd->net, thd->net.vio)) { close_connection(thd, ER_OUT_OF_RESOURCES, 1); @@ -5277,7 +5286,7 @@ pthread_handler_t handle_connections_namedpipes(void *arg) thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); create_new_thread(thd); } - + CloseHandle(connectOverlapped.hEvent); decrement_handler_count(); DBUG_RETURN(0); } @@ -5454,8 +5463,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg) errmsg= "Could not set client to read mode"; goto errorconn; } - if (!(thd->net.vio= vio_new_win32shared_memory(&thd->net, - handle_client_file_map, + if (!(thd->net.vio= vio_new_win32shared_memory(handle_client_file_map, handle_client_map, event_client_wrote, event_client_read, diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 119f90bc97a..5f9bae22c70 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5709,6 +5709,27 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, !(conf_func->compare_collation()->state & MY_CS_BINSORT)) goto end; + if (key_part->image_type == Field::itMBR) + { + switch (type) { + case Item_func::SP_EQUALS_FUNC: + case Item_func::SP_DISJOINT_FUNC: + case Item_func::SP_INTERSECTS_FUNC: + case Item_func::SP_TOUCHES_FUNC: + case Item_func::SP_CROSSES_FUNC: + case Item_func::SP_WITHIN_FUNC: + case Item_func::SP_CONTAINS_FUNC: + case Item_func::SP_OVERLAPS_FUNC: + break; + default: + /* + We cannot involve spatial indexes for queries that + don't use MBREQUALS(), MBRDISJOINT(), etc. functions. + */ + goto end; + } + } + if (param->using_real_indexes) optimize_range= field->optimize_range(param->real_keynr[key_part->key], key_part->part); @@ -5891,6 +5912,17 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, goto end; } field->table->in_use->variables.sql_mode= orig_sql_mode; + + /* + Any sargable predicate except "<=>" involving NULL as a constant is always + FALSE + */ + if (type != Item_func::EQUAL_FUNC && field->is_real_null()) + { + tree= &null_element; + goto end; + } + str= (uchar*) alloc_root(alloc, key_part->store_length+1); if (!str) goto end; @@ -5936,7 +5968,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, switch (type) { case Item_func::LT_FUNC: - if (stored_field_cmp_to_item(field,value) == 0) + if (stored_field_cmp_to_item(param->thd, field, value) == 0) tree->max_flag=NEAR_MAX; /* fall through */ case Item_func::LE_FUNC: @@ -5951,14 +5983,14 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, case Item_func::GT_FUNC: /* Don't use open ranges for partial key_segments */ if ((!(key_part->flag & HA_PART_KEY_SEG)) && - (stored_field_cmp_to_item(field, value) <= 0)) + (stored_field_cmp_to_item(param->thd, field, value) <= 0)) tree->min_flag=NEAR_MIN; tree->max_flag= NO_MAX_RANGE; break; case Item_func::GE_FUNC: /* Don't use open ranges for partial key_segments */ if ((!(key_part->flag & HA_PART_KEY_SEG)) && - (stored_field_cmp_to_item(field,value) < 0)) + (stored_field_cmp_to_item(param->thd, field, value) < 0)) tree->min_flag= NEAR_MIN; tree->max_flag=NO_MAX_RANGE; break; diff --git a/sql/records.cc b/sql/records.cc index 9e040de3fda..b6faf0227f9 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -57,10 +57,12 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, { empty_record(table); bzero((char*) info,sizeof(*info)); + info->thd= thd; info->table= table; info->file= table->file; info->record= table->record[0]; info->print_error= print_error; + info->unlock_row= rr_unlock_row; table->status=0; /* And it's always found */ if (!table->file->inited) @@ -186,6 +188,7 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, } info->select=select; info->print_error=print_error; + info->unlock_row= rr_unlock_row; info->ignore_not_found_rows= 0; table->status=0; /* And it's always found */ @@ -292,6 +295,12 @@ void end_read_record(READ_RECORD *info) static int rr_handle_error(READ_RECORD *info, int error) { + if (info->thd->killed) + { + info->thd->send_kill_message(); + return 1; + } + if (error == HA_ERR_END_OF_FILE) error= -1; else @@ -312,12 +321,7 @@ static int rr_quick(READ_RECORD *info) int tmp; while ((tmp= info->select->quick->get_next())) { - if (info->thd->killed) - { - my_error(ER_SERVER_SHUTDOWN, MYF(0)); - return 1; - } - if (tmp != HA_ERR_RECORD_DELETED) + if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED)) { tmp= rr_handle_error(info, tmp); break; @@ -380,16 +384,11 @@ int rr_sequential(READ_RECORD *info) int tmp; while ((tmp=info->file->rnd_next(info->record))) { - if (info->thd->killed) - { - info->thd->send_kill_message(); - return 1; - } /* rnd_next can return RECORD_DELETED for MyISAM when one thread is reading and another deleting without locks. */ - if (tmp != HA_ERR_RECORD_DELETED) + if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED)) { tmp= rr_handle_error(info, tmp); break; diff --git a/sql/slave.cc b/sql/slave.cc index 8e69066ed9b..40b476e4f17 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1458,6 +1458,199 @@ network_err: DBUG_RETURN(2); } +/* + Used by fetch_master_table (used by LOAD TABLE tblname FROM MASTER and LOAD + DATA FROM MASTER). Drops the table (if 'overwrite' is true) and recreates it + from the dump. Honours replication inclusion/exclusion rules. + db must be non-zero (guarded by assertion). + + RETURN VALUES + 0 success + 1 error +*/ + +static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, + const char* table_name, bool overwrite) +{ + ulong packet_len; + char *query, *save_db; + uint32 save_db_length; + Vio* save_vio; + HA_CHECK_OPT check_opt; + TABLE_LIST tables; + int error= 1; + handler *file; + ulonglong save_options; + NET *net= &mysql->net; + const char *found_semicolon= NULL; + DBUG_ENTER("create_table_from_dump"); + + packet_len= my_net_read(net); // read create table statement + if (packet_len == packet_error) + { + my_message(ER_MASTER_NET_READ, ER(ER_MASTER_NET_READ), MYF(0)); + DBUG_RETURN(1); + } + if (net->read_pos[0] == 255) // error from master + { + char *err_msg; + err_msg= (char*) net->read_pos + ((mysql->server_capabilities & + CLIENT_PROTOCOL_41) ? + 3+SQLSTATE_LENGTH+1 : 3); + my_error(ER_MASTER, MYF(0), err_msg); + DBUG_RETURN(1); + } + thd->command = COM_TABLE_DUMP; + if (!(query = thd->strmake((char*) net->read_pos, packet_len))) + { + sql_print_error("create_table_from_dump: out of memory"); + my_message(ER_GET_ERRNO, "Out of memory", MYF(0)); + DBUG_RETURN(1); + } + thd->set_query(query, packet_len); + thd->is_slave_error = 0; + + bzero((char*) &tables,sizeof(tables)); + tables.db = (char*)db; + tables.alias= tables.table_name= (char*)table_name; + + /* Drop the table if 'overwrite' is true */ + if (overwrite) + { + if (mysql_rm_table(thd,&tables,1,0)) /* drop if exists */ + { + sql_print_error("create_table_from_dump: failed to drop the table"); + goto err; + } + else + { + /* Clear the OK result of mysql_rm_table(). */ + thd->main_da.reset_diagnostics_area(); + } + } + + /* Create the table. We do not want to log the "create table" statement */ + save_options = thd->options; + thd->options &= ~ (OPTION_BIN_LOG); + thd_proc_info(thd, "Creating table from master dump"); + // save old db in case we are creating in a different database + save_db = thd->db; + save_db_length= thd->db_length; + thd->db = (char*)db; + DBUG_ASSERT(thd->db != 0); + thd->db_length= strlen(thd->db); + /* run create table */ + mysql_parse(thd, thd->query(), packet_len, &found_semicolon); + thd->db = save_db; // leave things the way the were before + thd->db_length= save_db_length; + thd->options = save_options; + + if (thd->is_slave_error) + goto err; // mysql_parse took care of the error send + + thd_proc_info(thd, "Opening master dump table"); + thd->main_da.reset_diagnostics_area(); /* cleanup from CREATE_TABLE */ + /* + Note: If this function starts to fail for MERGE tables, + change the next two lines to these: + tables.table= NULL; // was set by mysql_rm_table() + if (!open_n_lock_single_table(thd, &tables, TL_WRITE)) + */ + tables.lock_type = TL_WRITE; + if (!open_ltable(thd, &tables, TL_WRITE, 0)) + { + sql_print_error("create_table_from_dump: could not open created table"); + goto err; + } + + file = tables.table->file; + thd_proc_info(thd, "Reading master dump table data"); + /* Copy the data file */ + if (file->net_read_dump(net)) + { + my_message(ER_MASTER_NET_READ, ER(ER_MASTER_NET_READ), MYF(0)); + sql_print_error("create_table_from_dump: failed in\ + handler::net_read_dump()"); + goto err; + } + + check_opt.init(); + check_opt.flags|= T_VERY_SILENT | T_CALC_CHECKSUM | T_QUICK; + thd_proc_info(thd, "Rebuilding the index on master dump table"); + /* + We do not want repair() to spam us with messages + just send them to the error log, and report the failure in case of + problems. + */ + save_vio = thd->net.vio; + thd->net.vio = 0; + /* Rebuild the index file from the copied data file (with REPAIR) */ + error=file->ha_repair(thd,&check_opt) != 0; + thd->net.vio = save_vio; + if (error) + my_error(ER_INDEX_REBUILD, MYF(0), tables.table->s->table_name.str); + +err: + close_thread_tables(thd); + DBUG_RETURN(error); +} + + +int fetch_master_table(THD *thd, const char *db_name, const char *table_name, + Master_info *mi, MYSQL *mysql, bool overwrite) +{ + int error= 1; + const char *errmsg=0; + bool called_connected= (mysql != NULL); + DBUG_ENTER("fetch_master_table"); + DBUG_PRINT("enter", ("db_name: '%s' table_name: '%s'", + db_name,table_name)); + + if (!called_connected) + { + if (!(mysql = mysql_init(NULL))) + { + DBUG_RETURN(1); + } + if (connect_to_master(thd, mysql, mi)) + { + my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql)); + /* + We need to clear the active VIO since, theoretically, somebody + might issue an awake() on this thread. If we are then in the + middle of closing and destroying the VIO inside the + mysql_close(), we will have a problem. + */ +#ifdef SIGNAL_WITH_VIO_CLOSE + thd->clear_active_vio(); +#endif + mysql_close(mysql); + DBUG_RETURN(1); + } + if (thd->killed) + goto err; + } + + if (request_table_dump(mysql, db_name, table_name)) + { + error= ER_UNKNOWN_ERROR; + errmsg= "Failed on table dump request"; + goto err; + } + if (create_table_from_dump(thd, mysql, db_name, + table_name, overwrite)) + goto err; // create_table_from_dump have sent the error already + error = 0; + + err: + if (!called_connected) + mysql_close(mysql); + if (errmsg && thd->vio_ok()) + my_message(error, errmsg, MYF(0)); + DBUG_RETURN(test(error)); // Return 1 on error +} + + static bool wait_for_relay_log_space(Relay_log_info* rli) { bool slave_killed=0; diff --git a/sql/sp.cc b/sql/sp.cc index 4d840f53e2f..fd420732628 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -997,7 +997,7 @@ sp_drop_routine(THD *thd, int type, sp_name *name) if (ret == SP_OK) { - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); sp_cache_invalidate(); } @@ -1067,7 +1067,7 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) if (ret == SP_OK) { - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); sp_cache_invalidate(); } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 8ab91222bcc..6a0ab4bfc46 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -332,16 +332,18 @@ bool sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr) { Item *expr_item; + enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; + bool save_abort_on_warning= thd->abort_on_warning; + bool save_stmt_modified_non_trans_table= + thd->transaction.stmt.modified_non_trans_table; DBUG_ENTER("sp_eval_expr"); if (!*expr_item_ptr) - DBUG_RETURN(TRUE); + goto error; if (!(expr_item= sp_prepare_func_item(thd, expr_item_ptr))) - DBUG_RETURN(TRUE); - - bool err_status= FALSE; + goto error; /* Set THD flags to emit warnings/errors in case of overflow/type errors @@ -350,10 +352,6 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr) Save original values and restore them after save. */ - enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; - bool save_abort_on_warning= thd->abort_on_warning; - bool save_stmt_modified_non_trans_table= thd->transaction.stmt.modified_non_trans_table; - thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; thd->abort_on_warning= thd->variables.sql_mode & @@ -368,13 +366,18 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr) thd->abort_on_warning= save_abort_on_warning; thd->transaction.stmt.modified_non_trans_table= save_stmt_modified_non_trans_table; - if (thd->is_error()) - { - /* Return error status if something went wrong. */ - err_status= TRUE; - } + if (!thd->is_error()) + DBUG_RETURN(FALSE); - DBUG_RETURN(err_status); +error: + /* + In case of error during evaluation, leave the result field set to NULL. + Sic: we can't do it in the beginning of the function because the + result field might be needed for its own re-evaluation, e.g. case of + set x = x + 1; + */ + result_field->set_null(); + DBUG_RETURN (TRUE); } @@ -2824,8 +2827,8 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) DBUG_ENTER("sp_instr_stmt::execute"); DBUG_PRINT("info", ("command: %d", m_lex_keeper.sql_command())); - query= thd->query; - query_length= thd->query_length; + query= thd->query(); + query_length= thd->query_length(); #if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) /* This s-p instr is profilable and will be captured. */ thd->profiling.set_query_source(m_query.str, m_query.length); @@ -2838,10 +2841,11 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) queries with SP vars can't be cached) */ if (unlikely((thd->options & OPTION_LOG_OFF)==0)) - general_log_write(thd, COM_QUERY, thd->query, thd->query_length); + general_log_write(thd, COM_QUERY, thd->query(), thd->query_length()); if (query_cache_send_result_to_client(thd, - thd->query, thd->query_length) <= 0) + thd->query(), + thd->query_length()) <= 0) { res= m_lex_keeper.reset_lex_and_exec_core(thd, nextp, FALSE, this); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index d7d662f912d..0592bb3be1d 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -263,8 +263,7 @@ my_bool acl_init(bool dont_read_acl_tables) acl_cache= new hash_filo(ACL_CACHE_SIZE, 0, 0, (hash_get_key) acl_entry_get_key, (hash_free_key) free, - lower_case_file_system ? - system_charset_info : &my_charset_bin); + &my_charset_utf8_bin); if (dont_read_acl_tables) { DBUG_RETURN(0); /* purecov: tested */ @@ -2251,10 +2250,13 @@ public: ulong sort; size_t key_length; GRANT_NAME(const char *h, const char *d,const char *u, - const char *t, ulong p); - GRANT_NAME (TABLE *form); + const char *t, ulong p, bool is_routine); + GRANT_NAME (TABLE *form, bool is_routine); virtual ~GRANT_NAME() {}; virtual bool ok() { return privs != 0; } + void set_user_details(const char *h, const char *d, + const char *u, const char *t, + bool is_routine); }; @@ -2272,38 +2274,48 @@ public: }; - -GRANT_NAME::GRANT_NAME(const char *h, const char *d,const char *u, - const char *t, ulong p) - :privs(p) +void GRANT_NAME::set_user_details(const char *h, const char *d, + const char *u, const char *t, + bool is_routine) { /* Host given by user */ update_hostname(&host, strdup_root(&memex, h)); - db = strdup_root(&memex,d); + if (db != d) + { + db= strdup_root(&memex, d); + if (lower_case_table_names) + my_casedn_str(files_charset_info, db); + } user = strdup_root(&memex,u); sort= get_sort(3,host.hostname,db,user); - tname= strdup_root(&memex,t); - if (lower_case_table_names) + if (tname != t) { - my_casedn_str(files_charset_info, db); - my_casedn_str(files_charset_info, tname); + tname= strdup_root(&memex, t); + if (lower_case_table_names || is_routine) + my_casedn_str(files_charset_info, tname); } key_length= strlen(d) + strlen(u)+ strlen(t)+3; hash_key= (char*) alloc_root(&memex,key_length); strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); } +GRANT_NAME::GRANT_NAME(const char *h, const char *d,const char *u, + const char *t, ulong p, bool is_routine) + :db(0), tname(0), privs(p) +{ + set_user_details(h, d, u, t, is_routine); +} GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u, const char *t, ulong p, ulong c) - :GRANT_NAME(h,d,u,t,p), cols(c) + :GRANT_NAME(h,d,u,t,p, FALSE), cols(c) { (void) hash_init2(&hash_columns,4,system_charset_info, 0,0,0, (hash_get_key) get_key_column,0,0); } -GRANT_NAME::GRANT_NAME(TABLE *form) +GRANT_NAME::GRANT_NAME(TABLE *form, bool is_routine) { update_hostname(&host, get_field(&memex, form->field[0])); db= get_field(&memex,form->field[1]); @@ -2321,6 +2333,9 @@ GRANT_NAME::GRANT_NAME(TABLE *form) if (lower_case_table_names) { my_casedn_str(files_charset_info, db); + } + if (lower_case_table_names || is_routine) + { my_casedn_str(files_charset_info, tname); } key_length= (strlen(db) + strlen(user) + strlen(tname) + 3); @@ -2332,7 +2347,7 @@ GRANT_NAME::GRANT_NAME(TABLE *form) GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) - :GRANT_NAME(form) + :GRANT_NAME(form, FALSE) { uchar key[MAX_KEY_LENGTH]; @@ -3184,7 +3199,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (!result) /* success */ { - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } rw_unlock(&LOCK_grant); @@ -3327,7 +3342,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, } grant_name= new GRANT_NAME(Str->host.str, db_name, Str->user.str, table_name, - rights); + rights, TRUE); if (!grant_name) { result= TRUE; @@ -3349,7 +3364,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (write_to_binlog) { - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } rw_unlock(&LOCK_grant); @@ -3461,7 +3476,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, if (!result) { - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } rw_unlock(&LOCK_grant); @@ -3538,10 +3553,10 @@ static my_bool grant_load_procs_priv(TABLE *p_table) MEM_ROOT **save_mem_root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC); DBUG_ENTER("grant_load_procs_priv"); - (void) hash_init(&proc_priv_hash,system_charset_info, + (void) hash_init(&proc_priv_hash, &my_charset_utf8_bin, 0,0,0, (hash_get_key) get_grant_table, 0,0); - (void) hash_init(&func_priv_hash,system_charset_info, + (void) hash_init(&func_priv_hash, &my_charset_utf8_bin, 0,0,0, (hash_get_key) get_grant_table, 0,0); p_table->file->ha_index_init(0, 1); @@ -3555,7 +3570,7 @@ static my_bool grant_load_procs_priv(TABLE *p_table) { GRANT_NAME *mem_check; HASH *hash; - if (!(mem_check=new (memex_ptr) GRANT_NAME(p_table))) + if (!(mem_check=new (memex_ptr) GRANT_NAME(p_table, TRUE))) { /* This could only happen if we are out memory */ goto end_unlock; @@ -3639,7 +3654,7 @@ static my_bool grant_load(THD *thd, TABLE_LIST *tables) thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH; - (void) hash_init(&column_priv_hash,system_charset_info, + (void) hash_init(&column_priv_hash, &my_charset_utf8_bin, 0,0,0, (hash_get_key) get_grant_table, (hash_free_key) free_grant_table,0); @@ -5436,9 +5451,21 @@ static int handle_grant_struct(uint struct_no, bool drop, case 2: case 3: - grant_name->user= strdup_root(&mem, user_to->user.str); - update_hostname(&grant_name->host, - strdup_root(&mem, user_to->host.str)); + /* + Update the grant structure with the new user name and + host name + */ + grant_name->set_user_details(user_to->host.str, grant_name->db, + user_to->user.str, grant_name->tname, + TRUE); + + /* + Since username is part of the hash key, when the user name + is renamed, the hash key is changed. Update the hash to + ensure that the position matches the new hash key value + */ + hash_update(&column_priv_hash, (uchar*) grant_name, + (uchar*) grant_name->hash_key, grant_name->key_length); break; } } @@ -5663,7 +5690,7 @@ bool mysql_create_user(THD *thd, List &list) my_error(ER_CANNOT_USER, MYF(0), "CREATE USER", wrong_users.c_ptr_safe()); if (some_users_created) - write_bin_log(thd, FALSE, thd->query, thd->query_length); + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -5736,7 +5763,7 @@ bool mysql_drop_user(THD *thd, List &list) my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe()); if (some_users_deleted) - write_bin_log(thd, FALSE, thd->query, thd->query_length); + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -5821,7 +5848,7 @@ bool mysql_rename_user(THD *thd, List &list) my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe()); if (some_users_renamed && mysql_bin_log.is_open()) - write_bin_log(thd, FALSE, thd->query, thd->query_length); + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -6003,7 +6030,7 @@ bool mysql_revoke_all(THD *thd, List &list) VOID(pthread_mutex_unlock(&acl_cache->lock)); - write_bin_log(thd, FALSE, thd->query, thd->query_length); + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -6117,7 +6144,7 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, for (counter= 0, revoked= 0 ; counter < hash->records ; ) { GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, counter); - if (!my_strcasecmp(system_charset_info, grant_proc->db, sp_db) && + if (!my_strcasecmp(&my_charset_utf8_bin, grant_proc->db, sp_db) && !my_strcasecmp(system_charset_info, grant_proc->tname, sp_name)) { LEX_USER lex_user; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ed64242e4b1..776fea20676 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -25,6 +25,7 @@ #include #include #include +#include "rpl_filter.h" #ifdef __WIN__ #include #endif @@ -1547,6 +1548,7 @@ void close_temporary_tables(THD *thd) s_query.length() - 1 /* to remove trailing ',' */, 0, FALSE, 0); qinfo.db= db.ptr(); + qinfo.db_len= db.length(); thd->variables.character_set_client= cs_save; mysql_bin_log.write(&qinfo); thd->variables.pseudo_thread_id= save_pseudo_thread_id; @@ -5098,7 +5100,16 @@ static void mark_real_tables_as_free_for_reuse(TABLE_LIST *table) int decide_logging_format(THD *thd, TABLE_LIST *tables) { - if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG)) + /* + In SBR mode, we are only proceeding if we are binlogging this + statement, ie, the filtering rules won't later filter this out. + + This check here is needed to prevent some spurious error to be + raised in some cases (See BUG#42829). + */ + if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG) && + (thd->variables.binlog_format != BINLOG_FORMAT_STMT || + binlog_filter->db_ok(thd->db))) { /* Compute the starting vectors for the computations by creating a diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index a41b7bd40bb..861bd97928d 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1119,8 +1119,8 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) DBUG_VOID_RETURN; uint8 tables_type= 0; - if ((local_tables= is_cacheable(thd, thd->query_length, - thd->query, thd->lex, tables_used, + if ((local_tables= is_cacheable(thd, thd->query_length(), + thd->query(), thd->lex, tables_used, &tables_type))) { NET *net= &thd->net; @@ -1210,7 +1210,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", /* Key is query + database + flag */ if (thd->db_length) { - memcpy(thd->query+thd->query_length+1, thd->db, thd->db_length); + memcpy(thd->query() + thd->query_length() + 1, thd->db, + thd->db_length); DBUG_PRINT("qcache", ("database: %s length: %u", thd->db, (unsigned) thd->db_length)); } @@ -1218,24 +1219,24 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", { DBUG_PRINT("qcache", ("No active database")); } - tot_length= thd->query_length + thd->db_length + 1 + + tot_length= thd->query_length() + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE; /* We should only copy structure (don't use it location directly) because of alignment issue */ - memcpy((void *)(thd->query + (tot_length - QUERY_CACHE_FLAGS_SIZE)), + memcpy((void*) (thd->query() + (tot_length - QUERY_CACHE_FLAGS_SIZE)), &flags, QUERY_CACHE_FLAGS_SIZE); /* Check if another thread is processing the same query? */ Query_cache_block *competitor = (Query_cache_block *) - hash_search(&queries, (uchar*) thd->query, tot_length); + hash_search(&queries, (uchar*) thd->query(), tot_length); DBUG_PRINT("qcache", ("competitor 0x%lx", (ulong) competitor)); if (competitor == 0) { /* Query is not in cache and no one is working with it; Store it */ Query_cache_block *query_block; - query_block= write_block_data(tot_length, (uchar*) thd->query, + query_block= write_block_data(tot_length, (uchar*) thd->query(), ALIGN_SIZE(sizeof(Query_cache_query)), Query_cache_block::QUERY, local_tables); if (query_block != 0) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 179be88442c..a041df23cc5 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -412,14 +412,14 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length, str.append(proc_info); } - if (thd->query) + if (thd->query()) { if (max_query_len < 1) - len= thd->query_length; + len= thd->query_length(); else - len= min(thd->query_length, max_query_len); + len= min(thd->query_length(), max_query_len); str.append('\n'); - str.append(thd->query, len); + str.append(thd->query(), len); } if (str.c_ptr_safe() == buffer) return buffer; @@ -2467,12 +2467,12 @@ Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg, id(id_arg), mark_used_columns(MARK_COLUMNS_READ), lex(lex_arg), - query(0), - query_length(0), cursor(0), db(NULL), db_length(0) { + query_string.length= 0; + query_string.str= NULL; name.str= NULL; } @@ -2488,8 +2488,7 @@ void Statement::set_statement(Statement *stmt) id= stmt->id; mark_used_columns= stmt->mark_used_columns; lex= stmt->lex; - query= stmt->query; - query_length= stmt->query_length; + query_string= stmt->query_string; cursor= stmt->cursor; } @@ -2513,6 +2512,15 @@ void Statement::restore_backup_statement(Statement *stmt, Statement *backup) } +/** Assign a new value to thd->query. */ + +void Statement::set_query_inner(char *query_arg, uint32 query_length_arg) +{ + query_string.str= query_arg; + query_string.length= query_length_arg; +} + + void THD::end_statement() { /* Cleanup SQL processing state to reuse this statement in next query. */ @@ -2748,9 +2756,11 @@ bool select_dumpvar::send_data(List &items) else { Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item); - suv->fix_fields(thd, 0); + if (suv->fix_fields(thd, 0)) + DBUG_RETURN (1); suv->save_item_result(item); - suv->update(); + if (suv->update()) + DBUG_RETURN (1); } } DBUG_RETURN(thd->is_error()); @@ -3026,9 +3036,24 @@ extern "C" struct charset_info_st *thd_charset(MYSQL_THD thd) return(thd->charset()); } +/** + OBSOLETE : there's no way to ensure the string is null terminated. + Use thd_query_string instead() +*/ extern "C" char **thd_query(MYSQL_THD thd) { - return(&thd->query); + return(&thd->query_string.str); +} + +/** + Get the current query string for the thread. + + @param The MySQL internal thread pointer + @return query string and length. May be non-null-terminated. +*/ +extern "C" LEX_STRING * thd_query_string (MYSQL_THD thd) +{ + return(&thd->query_string); } extern "C" int thd_slave_thread(const MYSQL_THD thd) @@ -3053,6 +3078,11 @@ extern "C" void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all) { mark_transaction_to_rollback(thd, all); } + +extern "C" bool thd_binlog_filter_ok(const MYSQL_THD thd) +{ + return binlog_filter->db_ok(thd->db); +} #endif // INNODB_COMPATIBILITY_HOOKS */ /**************************************************************************** @@ -3207,8 +3237,7 @@ void THD::set_statement(Statement *stmt) void THD::set_query(char *query_arg, uint32 query_length_arg) { pthread_mutex_lock(&LOCK_thd_data); - query= query_arg; - query_length= query_length_arg; + set_query_inner(query_arg, query_length_arg); pthread_mutex_unlock(&LOCK_thd_data); } @@ -3226,6 +3255,16 @@ void mark_transaction_to_rollback(THD *thd, bool all) { thd->is_fatal_sub_stmt_error= TRUE; thd->transaction_rollback_request= all; + /* + Aborted transactions can not be IGNOREd. + Switch off the IGNORE flag for the current + SELECT_LEX. This should allow my_error() + to report the error and abort the execution + flow, even in presence + of IGNORE clause. + */ + if (thd->lex->current_select) + thd->lex->current_select->no_error= FALSE; } } /*************************************************************************** diff --git a/sql/sql_class.h b/sql/sql_class.h index 8c3a4f2e62d..05f2cb50ff6 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -97,6 +97,8 @@ extern char internal_table_name[2]; extern char empty_c_string[1]; extern MYSQL_PLUGIN_IMPORT const char **errmesg; +extern bool volatile shutdown_in_progress; + #define TC_LOG_PAGE_SIZE 8192 #define TC_LOG_MIN_SIZE (3*TC_LOG_PAGE_SIZE) @@ -646,10 +648,13 @@ public: This printing is needed at least in SHOW PROCESSLIST and SHOW ENGINE INNODB STATUS. */ - char *query; - uint32 query_length; // current query length + LEX_STRING query_string; Server_side_cursor *cursor; + inline char *query() { return query_string.str; } + inline uint32 query_length() { return query_string.length; } + void set_query_inner(char *query_arg, uint32 query_length_arg); + /** Name of the current (default) database. @@ -2122,7 +2127,11 @@ public: { int err= killed_errno(); if (err) + { + if ((err == KILL_CONNECTION) && !shutdown_in_progress) + err = KILL_QUERY; my_message(err, ER(err), MYF(0)); + } } /* return TRUE if we will abort query if we make a warning now */ inline bool really_abort_on_warning() diff --git a/sql/sql_db.cc b/sql/sql_db.cc index c19bfba9fc1..e6ccd9aa594 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -703,7 +703,7 @@ not_silent: char *query; uint query_length; - if (!thd->query) // Only in replication + if (!thd->query()) // Only in replication { query= tmp_query; query_length= (uint) (strxmov(tmp_query,"create database `", @@ -711,8 +711,8 @@ not_silent: } else { - query= thd->query; - query_length= thd->query_length; + query= thd->query(); + query_length= thd->query_length(); } ha_binlog_log_query(thd, 0, LOGCOM_CREATE_DB, @@ -805,13 +805,13 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) } ha_binlog_log_query(thd, 0, LOGCOM_ALTER_DB, - thd->query, thd->query_length, + thd->query(), thd->query_length(), db, ""); if (mysql_bin_log.is_open()) { int errcode= query_error_code(thd, TRUE); - Query_log_event qinfo(thd, thd->query, thd->query_length, 0, + Query_log_event qinfo(thd, thd->query(), thd->query_length(), 0, /* suppress_use */ TRUE, errcode); /* @@ -948,7 +948,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) { const char *query; ulong query_length; - if (!thd->query) + if (!thd->query()) { /* The client used the old obsolete mysql_drop_db() call */ query= path; @@ -957,8 +957,8 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) } else { - query =thd->query; - query_length= thd->query_length; + query= thd->query(); + query_length= thd->query_length(); } if (mysql_bin_log.is_open()) { @@ -1964,7 +1964,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) if (mysql_bin_log.is_open()) { int errcode= query_error_code(thd, TRUE); - Query_log_event qinfo(thd, thd->query, thd->query_length, + Query_log_event qinfo(thd, thd->query(), thd->query_length(), 0, TRUE, errcode); thd->clear_error(); mysql_bin_log.write(&qinfo); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index a81a5f4641f..b80138af7f2 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -413,7 +413,7 @@ cleanup: therefore be treated as a DDL. */ int log_result= thd->binlog_query(query_type, - thd->query, thd->query_length, + thd->query(), thd->query_length(), is_trans, FALSE, errcode); if (log_result) @@ -850,7 +850,7 @@ void multi_delete::abort() { int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query, thd->query_length, + thd->query(), thd->query_length(), transactional_tables, FALSE, errcode); } thd->transaction.all.modified_non_trans_table= true; @@ -1024,7 +1024,7 @@ bool multi_delete::send_eof() else errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); if (thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query, thd->query_length, + thd->query(), thd->query_length(), transactional_tables, FALSE, errcode) && !normal_tables) { @@ -1166,7 +1166,7 @@ end: TRUNCATE must always be statement-based binlogged (not row-based) so we don't test current_stmt_binlog_row_based. */ - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); my_ok(thd); // This should return record count } VOID(pthread_mutex_lock(&LOCK_open)); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3ac40ae825a..6e2b3903b52 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -567,7 +567,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, Name_resolution_context *context; Name_resolution_context_state ctx_state; #ifndef EMBEDDED_LIBRARY - char *query= thd->query; + char *query= thd->query(); /* log_on is about delayed inserts only. By default, both logs are enabled (this won't cause problems if the server @@ -801,7 +801,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, #ifndef EMBEDDED_LIBRARY if (lock_type == TL_WRITE_DELAYED) { - LEX_STRING const st_query = { query, thd->query_length }; + LEX_STRING const st_query = { query, thd->query_length() }; error=write_delayed(thd, table, duplic, st_query, ignore, log_on); query=0; } @@ -894,7 +894,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, */ DBUG_ASSERT(thd->killed != THD::KILL_BAD_DATA || error > 0); if (thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query, thd->query_length, + thd->query(), thd->query_length(), transactional_table, FALSE, errcode)) { @@ -1764,7 +1764,7 @@ public: pthread_cond_destroy(&cond); pthread_cond_destroy(&cond_client); thd.unlink(); // Must be unlinked under lock - x_free(thd.query); + x_free(thd.query()); thd.security_ctx->user= thd.security_ctx->host=0; thread_count--; delayed_insert_threads--; @@ -1910,7 +1910,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) pthread_mutex_unlock(&LOCK_thread_count); di->thd.set_db(table_list->db, (uint) strlen(table_list->db)); di->thd.set_query(my_strdup(table_list->table_name, MYF(MY_WME)), 0); - if (di->thd.db == NULL || di->thd.query == NULL) + if (di->thd.db == NULL || di->thd.query() == NULL) { /* The error is reported */ delete di; @@ -1919,7 +1919,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) } di->table_list= *table_list; // Needed to open table /* Replace volatile strings with local copies */ - di->table_list.alias= di->table_list.table_name= di->thd.query; + di->table_list.alias= di->table_list.table_name= di->thd.query(); di->table_list.db= di->thd.db; di->lock(); pthread_mutex_lock(&di->mutex); @@ -3250,7 +3250,7 @@ bool select_insert::send_eof() else errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query, thd->query_length, + thd->query(), thd->query_length(), trans_table, FALSE, errcode); } table->file->ha_release_auto_increment(); @@ -3320,7 +3320,8 @@ void select_insert::abort() { if (mysql_bin_log.is_open()) { int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); - thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length, + thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), + thd->query_length(), transactional_table, FALSE, errcode); } if (!thd->current_stmt_binlog_row_based && !can_rollback_data()) diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 5c278467179..8dda4a52466 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -84,7 +84,7 @@ static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, bool ignore_check_option_errors); #ifndef EMBEDDED_LIBRARY static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, - const char* db_arg, + const char* db_arg, /* table's database */ const char* table_name_arg, enum enum_duplicates duplicates, bool ignore, @@ -502,7 +502,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, if (thd->transaction.stmt.modified_non_trans_table) write_execute_load_query_log_event(thd, ex, - tdb, table_list->table_name, + table_list->db, + table_list->table_name, handle_duplicates, ignore, transactional_table, errcode); @@ -549,7 +550,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, { int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); write_execute_load_query_log_event(thd, ex, - tdb, table_list->table_name, + table_list->db, table_list->table_name, handle_duplicates, ignore, transactional_table, errcode); @@ -574,7 +575,7 @@ err: /* Not a very useful function; just to avoid duplication of code */ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, - const char* db_arg, + const char* db_arg, /* table's database */ const char* table_name_arg, enum enum_duplicates duplicates, bool ignore, @@ -591,8 +592,27 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, Item *item, *val; String pfield, pfields; int n; + const char *tbl= table_name_arg; + const char *tdb= (thd->db != NULL ? thd->db : db_arg); + String string_buf; - Load_log_event lle(thd, ex, db_arg, table_name_arg, fv, duplicates, + if (!thd->db || strcmp(db_arg, thd->db)) + { + /* + If used database differs from table's database, + prefix table name with database name so that it + becomes a FQ name. + */ + string_buf.set_charset(system_charset_info); + string_buf.append(db_arg); + string_buf.append("`"); + string_buf.append("."); + string_buf.append("`"); + string_buf.append(table_name_arg); + tbl= string_buf.c_ptr_safe(); + } + + Load_log_event lle(thd, ex, tdb, tbl, fv, duplicates, ignore, transactional_table); /* @@ -655,13 +675,12 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, strcpy(end, p); end += pl; - thd->query_length= end - load_data_query; - thd->query= load_data_query; + thd->set_query_inner(load_data_query, end - load_data_query); Execute_load_query_log_event - e(thd, thd->query, thd->query_length, - (uint) ((char*)fname_start - (char*)thd->query - 1), - (uint) ((char*)fname_end - (char*)thd->query), + e(thd, thd->query(), thd->query_length(), + (uint) ((char*) fname_start - (char*) thd->query() - 1), + (uint) ((char*) fname_end - (char*) thd->query()), (duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE : (ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR), transactional_table, FALSE, errcode); diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc index 3def9864c29..5ddf65cd1b7 100644 --- a/sql/sql_locale.cc +++ b/sql/sql_locale.cc @@ -1309,9 +1309,9 @@ static const char *my_locale_month_names_ro_RO[13] = static const char *my_locale_ab_month_names_ro_RO[13] = {"ian","feb","mar","apr","mai","iun","iul","aug","sep","oct","nov","dec", NullS }; static const char *my_locale_day_names_ro_RO[8] = - {"Luni","Marţi","Miercuri","Joi","Vineri","SîmbĂtĂ","DuminicĂ", NullS }; + {"Luni","Marţi","Miercuri","Joi","Vineri","Sâmbătă","Duminică", NullS }; static const char *my_locale_ab_day_names_ro_RO[8] = - {"Lu","Ma","Mi","Jo","Vi","Sî","Du", NullS }; + {"Lu","Ma","Mi","Jo","Vi","Sâ","Du", NullS }; static TYPELIB my_locale_typelib_month_names_ro_RO = { array_elements(my_locale_month_names_ro_RO)-1, "", my_locale_month_names_ro_RO, NULL }; static TYPELIB my_locale_typelib_ab_month_names_ro_RO = diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7c19cd7f82a..80f366d774a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -123,6 +123,14 @@ static bool xa_trans_rolled_back(XID_STATE *xid_state) */ static bool xa_trans_rollback(THD *thd) { + /* + Resource Manager error is meaningless at this point, as we perform + explicit rollback request by user. We must reset rm_error before + calling ha_rollback(), so thd->transaction.xid structure gets reset + by ha_rollback()/THD::transaction::cleanup(). + */ + thd->transaction.xid_state.rm_error= 0; + bool status= test(ha_rollback(thd)); thd->options&= ~(ulong) OPTION_BEGIN; @@ -130,7 +138,6 @@ static bool xa_trans_rollback(THD *thd) thd->server_status&= ~SERVER_STATUS_IN_TRANS; xid_cache_delete(&thd->transaction.xid_state); thd->transaction.xid_state.xa_state= XA_NOTR; - thd->transaction.xid_state.rm_error= 0; return status; } @@ -476,10 +483,10 @@ static void handle_bootstrap_impl(THD *thd) thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE); thd->set_query(query, length); - DBUG_PRINT("query",("%-.4096s",thd->query)); + DBUG_PRINT("query",("%-.4096s", thd->query())); #if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) thd->profiling.start_new_query(); - thd->profiling.set_query_source(thd->query, length); + thd->profiling.set_query_source(thd->query(), length); #endif /* @@ -488,7 +495,7 @@ static void handle_bootstrap_impl(THD *thd) */ thd->query_id=next_query_id(); thd->set_time(); - mysql_parse(thd, thd->query, length, & found_semicolon); + mysql_parse(thd, thd->query(), length, & found_semicolon); close_thread_tables(thd); // Free tables bootstrap_error= thd->is_error(); @@ -1107,20 +1114,20 @@ bool dispatch_command(enum enum_server_command command, THD *thd, { if (alloc_query(thd, packet, packet_length)) break; // fatal error is set - char *packet_end= thd->query + thd->query_length; + char *packet_end= thd->query() + thd->query_length(); /* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */ const char* end_of_stmt= NULL; - general_log_write(thd, command, thd->query, thd->query_length); - DBUG_PRINT("query",("%-.4096s",thd->query)); + general_log_write(thd, command, thd->query(), thd->query_length()); + DBUG_PRINT("query",("%-.4096s",thd->query())); #if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) - thd->profiling.set_query_source(thd->query, thd->query_length); + thd->profiling.set_query_source(thd->query(), thd->query_length()); #endif if (!(specialflag & SPECIAL_NO_PRIOR)) my_pthread_setprio(pthread_self(),QUERY_PRIOR); - mysql_parse(thd, thd->query, thd->query_length, &end_of_stmt); + mysql_parse(thd, thd->query(), thd->query_length(), &end_of_stmt); while (!thd->killed && (end_of_stmt != NULL) && ! thd->is_error()) { @@ -1563,7 +1570,8 @@ void log_slow_statement(THD *thd) { thd_proc_info(thd, "logging slow query"); thd->status_var.long_query_count++; - slow_log_print(thd, thd->query, thd->query_length, end_utime_of_query); + slow_log_print(thd, thd->query(), thd->query_length(), + end_utime_of_query); } } DBUG_VOID_RETURN; @@ -2816,7 +2824,7 @@ end_with_restore_list: /* Presumably, REPAIR and binlog writing doesn't require synchronization */ - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; @@ -2848,7 +2856,7 @@ end_with_restore_list: /* Presumably, ANALYZE and binlog writing doesn't require synchronization */ - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; @@ -2871,7 +2879,7 @@ end_with_restore_list: /* Presumably, OPTIMIZE and binlog writing doesn't require synchronization */ - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; @@ -3823,7 +3831,7 @@ end_with_restore_list: */ if (!lex->no_write_to_binlog && write_to_binlog) { - write_bin_log(thd, FALSE, thd->query, thd->query_length); + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); } my_ok(thd); } @@ -4400,7 +4408,7 @@ create_sp_error: case SP_KEY_NOT_FOUND: if (lex->drop_if_exists) { - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST), SP_COM_STRING(lex), lex->spname->m_name.str); @@ -4930,8 +4938,6 @@ bool check_single_table_access(THD *thd, ulong privilege, /* Show only 1 table for check_grant */ if (!(all_tables->belong_to_view && (thd->lex->sql_command == SQLCOM_SHOW_FIELDS)) && - !(all_tables->view && - all_tables->effective_algorithm == VIEW_ALGORITHM_TMPTABLE) && check_grant(thd, privilege, all_tables, 0, 1, no_errors)) goto deny; @@ -5791,9 +5797,10 @@ void mysql_parse(THD *thd, const char *inBuf, uint length, PROCESSLIST. Note that we don't need LOCK_thread_count to modify query_length. */ - if (*found_semicolon && - (thd->query_length= (ulong)(*found_semicolon - thd->query))) - thd->query_length--; + if (*found_semicolon && (ulong) (*found_semicolon - thd->query())) + thd->set_query_inner(thd->query(), + (uint32) (*found_semicolon - + thd->query() - 1)); /* Actually execute the query */ if (*found_semicolon) { diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index a7b35caeb8a..5a622740638 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -4081,7 +4081,7 @@ static int fast_end_partition(THD *thd, ulonglong copied, if ((!is_empty) && (!written_bin_log) && (!thd->lex->no_write_to_binlog)) - write_bin_log(thd, FALSE, thd->query, thd->query_length); + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO), (ulong) (copied + deleted), @@ -6239,7 +6239,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, ERROR_INJECT_CRASH("crash_drop_partition_5") || ((!thd->lex->no_write_to_binlog) && (write_bin_log(thd, FALSE, - thd->query, thd->query_length), FALSE)) || + thd->query(), thd->query_length()), FALSE)) || ERROR_INJECT_CRASH("crash_drop_partition_6") || ((frm_install= TRUE), FALSE) || mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) || @@ -6306,7 +6306,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, ERROR_INJECT_CRASH("crash_add_partition_5") || ((!thd->lex->no_write_to_binlog) && (write_bin_log(thd, FALSE, - thd->query, thd->query_length), FALSE)) || + thd->query(), thd->query_length()), FALSE)) || ERROR_INJECT_CRASH("crash_add_partition_6") || write_log_rename_frm(lpt) || (not_completed= FALSE) || @@ -6396,7 +6396,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, ERROR_INJECT_CRASH("crash_change_partition_6") || ((!thd->lex->no_write_to_binlog) && (write_bin_log(thd, FALSE, - thd->query, thd->query_length), FALSE)) || + thd->query(), thd->query_length()), FALSE)) || ERROR_INJECT_CRASH("crash_change_partition_7") || mysql_write_frm(lpt, WFRM_INSTALL_SHADOW) || ERROR_INJECT_CRASH("crash_change_partition_8") || diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 5500e44d1b2..e4cecdecc7e 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -2061,7 +2061,7 @@ static int check_func_set(THD *thd, struct st_mysql_sys_var *var, const char *strvalue= "NULL", *str; TYPELIB *typelib; ulonglong result; - uint error_len; + uint error_len= 0; // init as only set on error bool not_used; int length; @@ -2660,7 +2660,9 @@ uchar* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type, { if (!(value & mask)) continue; - str.append(typelib->type_names[i], typelib->type_lengths[i]); + str.append(typelib->type_names[i], typelib->type_lengths + ? typelib->type_lengths[i] + : strlen(typelib->type_names[i])); str.append(','); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index c1839b7220f..e2a24f7da1e 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -752,7 +752,7 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, const String *res; DBUG_ENTER("insert_params_with_log"); - if (query->copy(stmt->query, stmt->query_length, default_charset_info)) + if (query->copy(stmt->query(), stmt->query_length(), default_charset_info)) DBUG_RETURN(1); for (Item_param **it= begin; it < end; ++it) @@ -914,7 +914,7 @@ static bool emb_insert_params_with_log(Prepared_statement *stmt, DBUG_ENTER("emb_insert_params_with_log"); - if (query->copy(stmt->query, stmt->query_length, default_charset_info)) + if (query->copy(stmt->query(), stmt->query_length(), default_charset_info)) DBUG_RETURN(1); for (; it < end; ++it, ++client_param) @@ -1065,7 +1065,7 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt, DBUG_ENTER("insert_params_from_vars"); - if (query->copy(stmt->query, stmt->query_length, default_charset_info)) + if (query->copy(stmt->query(), stmt->query_length(), default_charset_info)) DBUG_RETURN(1); for (Item_param **it= begin; it < end; ++it) @@ -2342,6 +2342,9 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) /* Fix ORDER list */ for (order= (ORDER *)sl->order_list.first; order; order= order->next) order->item= &order->item_ptr; + + /* clear the no_error flag for INSERT/UPDATE IGNORE */ + sl->no_error= FALSE; } { SELECT_LEX_UNIT *unit= sl->master_unit(); @@ -2457,9 +2460,9 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length) } #if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) - thd->profiling.set_query_source(stmt->query, stmt->query_length); + thd->profiling.set_query_source(stmt->query(), stmt->query_length()); #endif - DBUG_PRINT("exec_query", ("%s", stmt->query)); + DBUG_PRINT("exec_query", ("%s", stmt->query())); DBUG_PRINT("info",("stmt: 0x%lx", (long) stmt)); sp_cache_flush_obsolete(&thd->sp_proc_cache); @@ -3029,7 +3032,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) old_stmt_arena= thd->stmt_arena; thd->stmt_arena= this; - Parser_state parser_state(thd, thd->query, thd->query_length); + Parser_state parser_state(thd, thd->query(), thd->query_length()); parser_state.m_lip.stmt_prepare_mode= TRUE; lex_start(thd); @@ -3118,7 +3121,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) the general log. */ if (thd->spcont == NULL) - general_log_write(thd, COM_STMT_PREPARE, query, query_length); + general_log_write(thd, COM_STMT_PREPARE, query(), query_length()); } DBUG_RETURN(error); } @@ -3309,7 +3312,7 @@ Prepared_statement::reprepare() return TRUE; error= ((name.str && copy.set_name(&name)) || - copy.prepare(query, query_length) || + copy.prepare(query(), query_length()) || validate_metadata(©)); if (cur_db_changed) @@ -3547,8 +3550,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) to point at it even after we restore from backup. This is ok, as expanded query was allocated in thd->mem_root. */ - stmt_backup.query= thd->query; - stmt_backup.query_length= thd->query_length; + stmt_backup.set_query_inner(thd->query(), thd->query_length()); /* At first execution of prepared statement we may perform logical @@ -3573,8 +3575,8 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) Note that multi-statements cannot exist here (they are not supported in prepared statements). */ - if (query_cache_send_result_to_client(thd, thd->query, - thd->query_length) <= 0) + if (query_cache_send_result_to_client(thd, thd->query(), + thd->query_length()) <= 0) { error= mysql_execute_command(thd); } @@ -3619,7 +3621,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) the general log. */ if (error == 0 && thd->spcont == NULL) - general_log_write(thd, COM_STMT_EXECUTE, thd->query, thd->query_length); + general_log_write(thd, COM_STMT_EXECUTE, thd->query(), thd->query_length()); error: flags&= ~ (uint) IS_IN_USE; diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 0e0b8eb60b9..dac96f2e9c4 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -177,7 +177,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) /* Lets hope this doesn't fail as the result will be messy */ if (!silent && !error) { - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); my_ok(thd); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c5e0bce498d..cdaebef49f6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -149,6 +149,7 @@ static int join_read_const_table(JOIN_TAB *tab, POSITION *pos); static int join_read_system(JOIN_TAB *tab); static int join_read_const(JOIN_TAB *tab); static int join_read_key(JOIN_TAB *tab); +static void join_read_key_unlock_row(st_join_table *tab); static int join_read_always_key(JOIN_TAB *tab); static int join_read_last_key(JOIN_TAB *tab); static int join_no_more_records(READ_RECORD *info); @@ -633,6 +634,18 @@ JOIN::prepare(Item ***rref_pointer_array, MYF(0)); /* purecov: inspected */ goto err; /* purecov: inspected */ } + if (thd->lex->derived_tables) + { + my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", + thd->lex->derived_tables & DERIVED_VIEW ? + "view" : "subquery"); + goto err; + } + if (thd->lex->sql_command != SQLCOM_SELECT) + { + my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "non-SELECT"); + goto err; + } } if (!procedure && result && result->prepare(fields_list, unit_arg)) @@ -969,6 +982,12 @@ JOIN::optimize() DBUG_RETURN(1); } + if (select_lex->olap == ROLLUP_TYPE && rollup_process_const_fields()) + { + DBUG_PRINT("error", ("Error: rollup_process_fields() failed")); + DBUG_RETURN(1); + } + /* Remove distinct if only const tables */ select_distinct= select_distinct && (const_tables != tables); thd_proc_info(thd, "preparing"); @@ -1099,7 +1118,7 @@ JOIN::optimize() join_tab[const_tables].select->quick->get_type() != QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)) { - if (group_list && + if (group_list && rollup.state == ROLLUP::STATE_NONE && list_contains_unique_index(join_tab[const_tables].table, find_field_in_order_list, (void *) group_list)) @@ -1143,7 +1162,8 @@ JOIN::optimize() if (! hidden_group_fields && rollup.state == ROLLUP::STATE_NONE) select_distinct=0; } - else if (select_distinct && tables - const_tables == 1) + else if (select_distinct && tables - const_tables == 1 && + rollup.state == ROLLUP::STATE_NONE) { /* We are only using one table. In this case we change DISTINCT to a @@ -3560,7 +3580,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field) { if (!(form->keys_in_use_for_query.is_set(key))) continue; - if (form->key_info[key].flags & HA_FULLTEXT) + if (form->key_info[key].flags & (HA_FULLTEXT | HA_SPATIAL)) continue; // ToDo: ft-keys in non-ft queries. SerG uint key_parts= (uint) form->key_info[key].key_parts; @@ -5609,7 +5629,9 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, } j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length); j->ref.key_err=1; + j->ref.has_record= FALSE; j->ref.null_rejecting= 0; + j->ref.use_count= 0; keyuse=org_keyuse; store_key **ref_key= j->ref.key_copy; @@ -6442,6 +6464,20 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) DBUG_RETURN(0); } + +/** + The default implementation of unlock-row method of READ_RECORD, + used in all access methods. +*/ + +void rr_unlock_row(st_join_table *tab) +{ + READ_RECORD *info= &tab->read_record; + info->file->unlock_row(); +} + + + static void make_join_readinfo(JOIN *join, ulonglong options) { @@ -6457,6 +6493,7 @@ make_join_readinfo(JOIN *join, ulonglong options) TABLE *table=tab->table; tab->read_record.table= table; tab->read_record.file=table->file; + tab->read_record.unlock_row= rr_unlock_row; tab->next_select=sub_select; /* normal select */ /* @@ -6502,6 +6539,7 @@ make_join_readinfo(JOIN *join, ulonglong options) delete tab->quick; tab->quick=0; tab->read_first_record= join_read_key; + tab->read_record.unlock_row= join_read_key_unlock_row; tab->read_record.read_record= join_no_more_records; if (table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) @@ -8964,7 +9002,10 @@ static void restore_prev_nj_state(JOIN_TAB *last) join->cur_embedding_map&= ~last_emb->nested_join->nj_map; else if (last_emb->nested_join->join_list.elements-1 == last_emb->nested_join->counter) + { join->cur_embedding_map|= last_emb->nested_join->nj_map; + break; + } else break; last_emb= last_emb->embedding; @@ -9411,8 +9452,47 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, new_field->set_derivation(item->collation.derivation); break; case DECIMAL_RESULT: - new_field= Field_new_decimal::new_decimal_field(item); + { + uint8 dec= item->decimals; + uint8 intg= ((Item_decimal *) item)->decimal_precision() - dec; + uint32 len= item->max_length; + + /* + Trying to put too many digits overall in a DECIMAL(prec,dec) + will always throw a warning. We must limit dec to + DECIMAL_MAX_SCALE however to prevent an assert() later. + */ + + if (dec > 0) + { + signed int overflow; + + dec= min(dec, DECIMAL_MAX_SCALE); + + /* + If the value still overflows the field with the corrected dec, + we'll throw out decimals rather than integers. This is still + bad and of course throws a truncation warning. + +1: for decimal point + */ + + const int required_length= + my_decimal_precision_to_length(intg + dec, dec, + item->unsigned_flag); + + overflow= required_length - len; + + if (overflow > 0) + dec= max(0, dec - overflow); // too long, discard fract + else + /* Corrected value fits. */ + len= required_length; + } + + new_field= new Field_new_decimal(len, maybe_null, item->name, + dec, item->unsigned_flag); break; + } case ROW_RESULT: default: // This case should never be choosen @@ -10212,6 +10292,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, for (; cur_group ; cur_group= cur_group->next, key_part_info++) { Field *field=(*cur_group->item)->get_tmp_table_field(); + DBUG_ASSERT(field->table == table); bool maybe_null=(*cur_group->item)->maybe_null; key_part_info->null_bit=0; key_part_info->field= field; @@ -11189,6 +11270,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, bool not_used_in_distinct=join_tab->not_used_in_distinct; ha_rows found_records=join->found_records; COND *select_cond= join_tab->select_cond; + bool select_cond_result= TRUE; if (error > 0 || (join->thd->is_error())) // Fatal error return NESTED_LOOP_ERROR; @@ -11200,7 +11282,17 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, return NESTED_LOOP_KILLED; /* purecov: inspected */ } DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond)); - if (!select_cond || select_cond->val_int()) + + if (select_cond) + { + select_cond_result= test(select_cond->val_int()); + + /* check for errors evaluating the condition */ + if (join->thd->is_error()) + return NESTED_LOOP_ERROR; + } + + if (!select_cond || select_cond_result) { /* There is no select condition or the attached pushed down @@ -11284,7 +11376,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, return NESTED_LOOP_NO_MORE_ROWS; } else - join_tab->read_record.file->unlock_row(); + join_tab->read_record.unlock_row(join_tab); } else { @@ -11294,7 +11386,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab, */ join->examined_rows++; join->thd->row_count++; - join_tab->read_record.file->unlock_row(); + join_tab->read_record.unlock_row(join_tab); } return NESTED_LOOP_OK; } @@ -11654,18 +11746,55 @@ join_read_key(JOIN_TAB *tab) table->status=STATUS_NOT_FOUND; return -1; } + /* + Moving away from the current record. Unlock the row + in the handler if it did not match the partial WHERE. + */ + if (tab->ref.has_record && tab->ref.use_count == 0) + { + tab->read_record.file->unlock_row(); + tab->ref.has_record= FALSE; + } error=table->file->index_read_map(table->record[0], tab->ref.key_buff, make_prev_keypart_map(tab->ref.key_parts), HA_READ_KEY_EXACT); if (error && error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) return report_error(table, error); + + if (! error) + { + tab->ref.has_record= TRUE; + tab->ref.use_count= 1; + } + } + else if (table->status == 0) + { + DBUG_ASSERT(tab->ref.has_record); + tab->ref.use_count++; } table->null_row=0; return table->status ? -1 : 0; } +/** + Since join_read_key may buffer a record, do not unlock + it if it was not used in this invocation of join_read_key(). + Only count locks, thus remembering if the record was left unused, + and unlock already when pruning the current value of + TABLE_REF buffer. + @sa join_read_key() +*/ + +static void +join_read_key_unlock_row(st_join_table *tab) +{ + DBUG_ASSERT(tab->ref.use_count); + if (tab->ref.use_count) + tab->ref.use_count--; +} + /* ref access method implementation: "read_first" function @@ -15637,32 +15766,7 @@ bool JOIN::rollup_init() { item->maybe_null= 1; found_in_group= 1; - if (item->const_item()) - { - /* - For ROLLUP queries each constant item referenced in GROUP BY list - is wrapped up into an Item_func object yielding the same value - as the constant item. The objects of the wrapper class are never - considered as constant items and besides they inherit all - properties of the Item_result_field class. - This wrapping allows us to ensure writing constant items - into temporary tables whenever the result of the ROLLUP - operation has to be written into a temporary table, e.g. when - ROLLUP is used together with DISTINCT in the SELECT list. - Usually when creating temporary tables for a intermidiate - result we do not include fields for constant expressions. - */ - Item* new_item= new Item_func_rollup_const(item); - if (!new_item) - return 1; - new_item->fix_fields(thd, (Item **) 0); - thd->change_item_tree(it.ref(), new_item); - for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next) - { - if (*tmp->item == item) - thd->change_item_tree(tmp->item, new_item); - } - } + break; } } if (item->type() == Item::FUNC_ITEM && !found_in_group) @@ -15681,6 +15785,59 @@ bool JOIN::rollup_init() } return 0; } + +/** + Wrap all constant Items in GROUP BY list. + + For ROLLUP queries each constant item referenced in GROUP BY list + is wrapped up into an Item_func object yielding the same value + as the constant item. The objects of the wrapper class are never + considered as constant items and besides they inherit all + properties of the Item_result_field class. + This wrapping allows us to ensure writing constant items + into temporary tables whenever the result of the ROLLUP + operation has to be written into a temporary table, e.g. when + ROLLUP is used together with DISTINCT in the SELECT list. + Usually when creating temporary tables for a intermidiate + result we do not include fields for constant expressions. + + @retval + 0 if ok + @retval + 1 on error +*/ + +bool JOIN::rollup_process_const_fields() +{ + ORDER *group_tmp; + Item *item; + List_iterator it(all_fields); + + for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next) + { + if (!(*group_tmp->item)->const_item()) + continue; + while ((item= it++)) + { + if (*group_tmp->item == item) + { + Item* new_item= new Item_func_rollup_const(item); + if (!new_item) + return 1; + new_item->fix_fields(thd, (Item **) 0); + thd->change_item_tree(it.ref(), new_item); + for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next) + { + if (*tmp->item == item) + thd->change_item_tree(tmp->item, new_item); + } + break; + } + } + it.rewind(); + } + return 0; +} /** diff --git a/sql/sql_select.h b/sql/sql_select.h index 0b9aa3576c7..e44d416380e 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -61,6 +61,8 @@ class store_key; typedef struct st_table_ref { bool key_err; + /** True if something was read into buffer in join_read_key. */ + bool has_record; uint key_parts; ///< num of ... uint key_length; ///< length of key_buff int key; ///< key no @@ -88,6 +90,11 @@ typedef struct st_table_ref table_map depend_map; ///< Table depends on these tables. /* null byte position in the key_buf. Used for REF_OR_NULL optimization */ uchar *null_ref_key; + /* + The number of times the record associated with this key was used + in the join. + */ + ha_rows use_count; } TABLE_REF; @@ -515,6 +522,7 @@ public: } bool rollup_init(); + bool rollup_process_const_fields(); bool rollup_make_fields(List &all_fields, List &fields, Item_sum ***func); int rollup_send_data(uint idx); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1747da1a149..413733c0148 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1835,10 +1835,10 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) thd_info->query=0; /* Lock THD mutex that protects its data when looking at it. */ pthread_mutex_lock(&tmp->LOCK_thd_data); - if (tmp->query) + if (tmp->query()) { - uint length= min(max_query_length, tmp->query_length); - thd_info->query=(char*) thd->strmake(tmp->query,length); + uint length= min(max_query_length, tmp->query_length()); + thd_info->query= (char*) thd->strmake(tmp->query(),length); } pthread_mutex_unlock(&tmp->LOCK_thd_data); thread_infos.append(thd_info); @@ -1963,11 +1963,11 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) pthread_mutex_unlock(&mysys_var->mutex); /* INFO */ - if (tmp->query) + if (tmp->query()) { - table->field[7]->store(tmp->query, + table->field[7]->store(tmp->query(), min(PROCESS_LIST_INFO_WIDTH, - tmp->query_length), cs); + tmp->query_length()), cs); table->field[7]->set_notnull(); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8fd80d04af9..cb9ff6163a8 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2089,7 +2089,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, tables). In this case, we can write the original query into the binary log. */ - write_bin_log(thd, !error, thd->query, thd->query_length); + write_bin_log(thd, !error, thd->query(), thd->query_length()); } else if (thd->current_stmt_binlog_row_based && tmp_table_deleted) @@ -3554,7 +3554,7 @@ static inline void write_create_table_bin_log(THD *thd, (!thd->current_stmt_binlog_row_based || (thd->current_stmt_binlog_row_based && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)))) - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } @@ -5337,14 +5337,14 @@ binlog: write_bin_log(thd, TRUE, query.ptr(), query.length()); } else // Case 1 - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } /* Case 3 and 4 does nothing under RBR */ } else - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); res= FALSE; @@ -5432,7 +5432,7 @@ mysql_discard_or_import_tablespace(THD *thd, error=1; if (error) goto err; - write_bin_log(thd, FALSE, thd->query, thd->query_length); + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); err: ha_autocommit_or_rollback(thd, error); @@ -6441,7 +6441,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (mysql_bin_log.is_open()) { thd->clear_error(); - Query_log_event qinfo(thd, thd->query, thd->query_length, + Query_log_event qinfo(thd, thd->query(), thd->query_length(), 0, FALSE, 0); mysql_bin_log.write(&qinfo); } @@ -6695,7 +6695,7 @@ view_err: if (!error) { - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); my_ok(thd); } else if (error > 0) @@ -7185,7 +7185,7 @@ view_err: goto err1; /* We don't replicate alter table statement on temporary tables */ if (!thd->current_stmt_binlog_row_based) - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); goto end_temporary; } @@ -7342,13 +7342,13 @@ view_err: DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000);); ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE, - thd->query, thd->query_length, + thd->query(), thd->query_length(), db, table_name); DBUG_ASSERT(!(mysql_bin_log.is_open() && thd->current_stmt_binlog_row_based && (create_info->options & HA_LEX_CREATE_TMP_TABLE))); - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME)) { diff --git a/sql/sql_tablespace.cc b/sql/sql_tablespace.cc index 9fec0e3bc63..fcc442a8f9a 100644 --- a/sql/sql_tablespace.cc +++ b/sql/sql_tablespace.cc @@ -66,6 +66,6 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info) ha_resolve_storage_engine_name(hton), "TABLESPACE or LOGFILE GROUP"); } - write_bin_log(thd, FALSE, thd->query, thd->query_length); + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); DBUG_RETURN(FALSE); } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index c055268ecca..a251a533622 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -409,7 +409,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) */ result= FALSE; /* Still, we need to log the query ... */ - stmt_query.append(thd->query, thd->query_length); + stmt_query.append(thd->query(), thd->query_length()); goto end; } } @@ -918,7 +918,7 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables, List_iterator it_connection_cl_name(connection_cl_names); List_iterator it_db_cl_name(db_cl_names); - stmt_query->append(thd->query, thd->query_length); + stmt_query->append(thd->query(), thd->query_length()); while ((name= it_name++)) { diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index c60dac42fb8..c6b41b59a3f 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -506,7 +506,7 @@ int mysql_create_function(THD *thd,udf_func *udf) rw_unlock(&THR_LOCK_udf); /* Binlog the create function. */ - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); DBUG_RETURN(0); @@ -581,7 +581,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) rw_unlock(&THR_LOCK_udf); /* Binlog the drop function. */ - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_bin_log(thd, TRUE, thd->query(), thd->query_length()); DBUG_RETURN(0); err: diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 152613c0009..cfa383ce9cb 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -810,7 +810,7 @@ int mysql_update(THD *thd, errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); if (thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query, thd->query_length, + thd->query(), thd->query_length(), transactional_table, FALSE, errcode)) { error=1; // Rollback update @@ -1696,6 +1696,11 @@ bool multi_update::send_data(List ¬_used_values) TRG_EVENT_UPDATE)) DBUG_RETURN(1); + /* + Reset the table->auto_increment_field_not_null as it is valid for + only one row. + */ + table->auto_increment_field_not_null= FALSE; found++; if (!can_compare_record || compare_record(table)) { @@ -1860,7 +1865,7 @@ void multi_update::abort() */ int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query, thd->query_length, + thd->query(), thd->query_length(), transactional_tables, FALSE, errcode); } thd->transaction.all.modified_non_trans_table= TRUE; @@ -2093,7 +2098,7 @@ bool multi_update::send_eof() else errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); if (thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query, thd->query_length, + thd->query(), thd->query_length(), transactional_tables, FALSE, errcode)) { local_error= 1; // Rollback update diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 43d0b9fade0..ae3af0640a3 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1652,7 +1652,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) /* if something goes wrong, bin-log with possible error code, otherwise bin-log with error code cleared. */ - write_bin_log(thd, !something_wrong, thd->query, thd->query_length); + write_bin_log(thd, !something_wrong, thd->query(), thd->query_length()); } VOID(pthread_mutex_unlock(&LOCK_open)); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4b2d4634ee7..1b85e5afdce 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9117,8 +9117,7 @@ procedure_clause: MYSQL_YYABORT; } - if (&lex->select_lex != lex->current_select || - lex->select_lex.get_table_list()->derived) + if (&lex->select_lex != lex->current_select) { my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery"); MYSQL_YYABORT; @@ -10698,7 +10697,7 @@ param_marker: my_error(ER_VIEW_SELECT_VARIABLE, MYF(0)); MYSQL_YYABORT; } - item= new (thd->mem_root) Item_param((uint) (lip->get_tok_start() - thd->query)); + item= new (thd->mem_root) Item_param((uint) (lip->get_tok_start() - thd->query())); if (!($$= item) || lex->param_list.push_back(item)) { my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); diff --git a/sql/structs.h b/sql/structs.h index bcda7b1e787..d54921791a1 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -118,16 +118,22 @@ typedef struct st_reginfo { /* Extra info about reg */ } REGINFO; -struct st_read_record; /* For referense later */ class SQL_SELECT; class THD; class handler; +struct st_join_table; -typedef struct st_read_record { /* Parameter to read_record */ +void rr_unlock_row(st_join_table *tab); + +struct READ_RECORD { /* Parameter to read_record */ + typedef int (*Read_func)(READ_RECORD*); + typedef void (*Unlock_row_func)(st_join_table *); struct st_table *table; /* Head-form */ handler *file; struct st_table **forms; /* head and ref forms */ - int (*read_record)(struct st_read_record *); + + Read_func read_record; + Unlock_row_func unlock_row; THD *thd; SQL_SELECT *select; uint cache_records; @@ -139,7 +145,7 @@ typedef struct st_read_record { /* Parameter to read_record */ uchar *cache,*cache_pos,*cache_end,*read_positions; IO_CACHE *io_cache; bool print_error, ignore_not_found_rows; -} READ_RECORD; +}; /* diff --git a/sql/time.cc b/sql/time.cc index 962b65e454c..8b554beb94b 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -965,20 +965,22 @@ calc_time_diff(MYSQL_TIME *l_time1, MYSQL_TIME *l_time2, int l_sign, longlong *s 0 - a == b 1 - a > b - NOTES - TIME.second_part is not considered during comparison */ -int -my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b) +int my_time_compare(MYSQL_TIME *a, MYSQL_TIME *b) { - my_ulonglong a_t= TIME_to_ulonglong_datetime(a); - my_ulonglong b_t= TIME_to_ulonglong_datetime(b); + ulonglong a_t= TIME_to_ulonglong_datetime(a); + ulonglong b_t= TIME_to_ulonglong_datetime(b); + if (a_t < b_t) + return -1; if (a_t > b_t) return 1; - else if (a_t < b_t) + + if (a->second_part < b->second_part) return -1; + if (a->second_part > b->second_part) + return 1; return 0; } diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc index 357496fe095..e3ba111043b 100644 --- a/storage/blackhole/ha_blackhole.cc +++ b/storage/blackhole/ha_blackhole.cc @@ -105,7 +105,7 @@ int ha_blackhole::update_row(const uchar *old_data, uchar *new_data) { DBUG_ENTER("ha_blackhole::update_row"); THD *thd= ha_thd(); - if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query == NULL) + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL) DBUG_RETURN(0); DBUG_RETURN(HA_ERR_WRONG_COMMAND); } @@ -114,7 +114,7 @@ int ha_blackhole::delete_row(const uchar *buf) { DBUG_ENTER("ha_blackhole::delete_row"); THD *thd= ha_thd(); - if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query == NULL) + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL) DBUG_RETURN(0); DBUG_RETURN(HA_ERR_WRONG_COMMAND); } @@ -130,7 +130,7 @@ int ha_blackhole::rnd_next(uchar *buf) { DBUG_ENTER("ha_blackhole::rnd_next"); THD *thd= ha_thd(); - if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query == NULL) + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL) DBUG_RETURN(0); DBUG_RETURN(HA_ERR_END_OF_FILE); } @@ -212,7 +212,7 @@ int ha_blackhole::index_read_map(uchar * buf, const uchar * key, { DBUG_ENTER("ha_blackhole::index_read"); THD *thd= ha_thd(); - if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query == NULL) + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL) DBUG_RETURN(0); DBUG_RETURN(HA_ERR_END_OF_FILE); } @@ -224,7 +224,7 @@ int ha_blackhole::index_read_idx_map(uchar * buf, uint idx, const uchar * key, { DBUG_ENTER("ha_blackhole::index_read_idx"); THD *thd= ha_thd(); - if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query == NULL) + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL) DBUG_RETURN(0); DBUG_RETURN(HA_ERR_END_OF_FILE); } @@ -235,7 +235,7 @@ int ha_blackhole::index_read_last_map(uchar * buf, const uchar * key, { DBUG_ENTER("ha_blackhole::index_read_last"); THD *thd= ha_thd(); - if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query == NULL) + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL) DBUG_RETURN(0); DBUG_RETURN(HA_ERR_END_OF_FILE); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a8b9b678282..41d76c5ec55 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -41,7 +41,7 @@ have disabled the InnoDB inlining in this file. */ #include #ifndef MYSQL_SERVER -/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t +/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t is defined the same in both builds: the MySQL server and the InnoDB plugin. */ extern pthread_mutex_t LOCK_thread_count; #endif /* MYSQL_SERVER */ @@ -54,6 +54,7 @@ static ulong commit_threads = 0; static pthread_mutex_t commit_threads_m; static pthread_cond_t commit_cond; static pthread_mutex_t commit_cond_m; +static pthread_mutex_t analyze_mutex; static bool innodb_inited = 0; /* @@ -1932,6 +1933,7 @@ innobase_init( pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST); pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST); pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST); + pthread_mutex_init(&analyze_mutex, MY_MUTEX_INIT_FAST); pthread_cond_init(&commit_cond, NULL); innodb_inited= 1; @@ -1971,6 +1973,7 @@ innobase_end(handlerton *hton, ha_panic_function type) pthread_mutex_destroy(&prepare_commit_mutex); pthread_mutex_destroy(&commit_threads_m); pthread_mutex_destroy(&commit_cond_m); + pthread_mutex_destroy(&analyze_mutex); pthread_cond_destroy(&commit_cond); } @@ -2215,6 +2218,8 @@ innobase_rollback( innobase_release_stat_resources(trx); + trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */ + /* If we had reserved the auto-inc lock for some table (if we come here to roll back the latest SQL statement) we release it now before a possibly lengthy rollback */ @@ -3240,7 +3245,10 @@ ha_innobase::store_key_val_for_row( } else if (mysql_type == MYSQL_TYPE_TINY_BLOB || mysql_type == MYSQL_TYPE_MEDIUM_BLOB || mysql_type == MYSQL_TYPE_BLOB - || mysql_type == MYSQL_TYPE_LONG_BLOB) { + || mysql_type == MYSQL_TYPE_LONG_BLOB + /* MYSQL_TYPE_GEOMETRY data is treated + as BLOB data in innodb. */ + || mysql_type == MYSQL_TYPE_GEOMETRY) { CHARSET_INFO* cs; ulint key_len; @@ -5186,7 +5194,7 @@ create_table_def( if (dict_col_name_is_reserved(field->field_name)){ push_warning_printf( (THD*) trx->mysql_thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_CANT_CREATE_TABLE, "Error creating table '%s' with " "column name '%s'. '%s' is a " @@ -5433,13 +5441,15 @@ ha_innobase::create( 1. /: for normal table creation 2. full path: for temp table creation, or sym link - When srv_file_per_table is on, check for full path pattern, i.e. + When srv_file_per_table is on and mysqld_embedded is off, + check for full path pattern, i.e. X:\dir\..., X is a driver letter, or \\dir1\dir2\..., UNC path returns error if it is in full path format, but not creating a temp. table. Currently InnoDB does not support symbolic link on Windows. */ if (srv_file_per_table + && !mysqld_embedded && (!create_info->options & HA_LEX_CREATE_TMP_TABLE)) { if ((name[1] == ':') @@ -5595,18 +5605,22 @@ ha_innobase::create( setup at this stage and so we use thd. */ /* We need to copy the AUTOINC value from the old table if - this is an ALTER TABLE. */ + this is an ALTER TABLE or CREATE INDEX because CREATE INDEX + does a table copy too. */ if (((create_info->used_fields & HA_CREATE_USED_AUTO) - || thd_sql_command(thd) == SQLCOM_ALTER_TABLE) - && create_info->auto_increment_value != 0) { + || thd_sql_command(thd) == SQLCOM_ALTER_TABLE + || thd_sql_command(thd) == SQLCOM_CREATE_INDEX) + && create_info->auto_increment_value > 0) { - /* Query was ALTER TABLE...AUTO_INCREMENT = x; or - CREATE TABLE ...AUTO_INCREMENT = x; Find out a table - definition from the dictionary and get the current value - of the auto increment field. Set a new value to the - auto increment field if the value is greater than the - maximum value in the column. */ + /* Query was one of : + CREATE TABLE ...AUTO_INCREMENT = x; or + ALTER TABLE...AUTO_INCREMENT = x; or + CREATE INDEX x on t(...); + Find out a table definition from the dictionary and get + the current value of the auto increment field. Set a new + value to the auto increment field if the value is greater + than the maximum value in the column. */ auto_inc_value = create_info->auto_increment_value; @@ -6428,9 +6442,15 @@ ha_innobase::analyze( THD* thd, /* in: connection thread handle */ HA_CHECK_OPT* check_opt) /* in: currently ignored */ { + /* Serialize ANALYZE TABLE inside InnoDB, see + Bug#38996 Race condition in ANALYZE TABLE */ + pthread_mutex_lock(&analyze_mutex); + /* Simply call ::info() with all the flags */ info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE); + pthread_mutex_unlock(&analyze_mutex); + return(0); } @@ -7027,8 +7047,9 @@ ha_innobase::external_lock( { ulong const binlog_format= thd_binlog_format(thd); ulong const tx_isolation = thd_tx_isolation(current_thd); - if (tx_isolation <= ISO_READ_COMMITTED && - binlog_format == BINLOG_FORMAT_STMT) + if (tx_isolation <= ISO_READ_COMMITTED + && binlog_format == BINLOG_FORMAT_STMT + && thd_binlog_filter_ok(thd)) { char buf[256]; my_snprintf(buf, sizeof(buf), @@ -7865,6 +7886,7 @@ ha_innobase::get_auto_increment( AUTOINC counter after attempting to insert the row. */ if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) { ulonglong need; + ulonglong current; ulonglong next_value; ulonglong col_max_value; @@ -7873,11 +7895,12 @@ ha_innobase::get_auto_increment( col_max_value = innobase_get_int_col_max_value( table->next_number_field); + 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( - *first_value, need, offset, col_max_value); + current, need, offset, col_max_value); prebuilt->autoinc_last_value = next_value; @@ -8502,7 +8525,7 @@ innobase_index_name_is_reserved( innobase_index_reserve_name) == 0) { /* Push warning to mysql */ push_warning_printf((THD*) trx->mysql_thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_CANT_CREATE_TABLE, "Cannot Create Index with name " "'%s'. The name is reserved " diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 8ca72ee1a60..9ddb516c3dc 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -252,4 +252,11 @@ int thd_binlog_format(const MYSQL_THD thd); @param all TRUE <=> rollback main transaction. */ void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all); + +/** + Check if binary logging is filtered for thread's current db. + @param thd Thread handle + @retval 1 the query is not filtered, 0 otherwise. +*/ +bool thd_binlog_filter_ok(const MYSQL_THD thd); } diff --git a/storage/innobase/os/os0proc.c b/storage/innobase/os/os0proc.c index a99fe8b6a0e..f00475fc528 100644 --- a/storage/innobase/os/os0proc.c +++ b/storage/innobase/os/os0proc.c @@ -591,6 +591,7 @@ os_mem_alloc_large( fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to" " attach shared memory segment, errno %d\n", errno); + ptr = NULL; } /* Remove the shared memory segment so that it will be diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index d0364c9c568..4fcb1fbf9f2 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -2089,7 +2089,7 @@ Scans a table create SQL string and adds to the data dictionary the foreign key constraints declared in the string. This function should be called after the indexes for a table have been created. Each foreign key constraint must be accompanied with indexes in -bot participating tables. The indexes are allowed to contain more +both participating tables. The indexes are allowed to contain more fields than mentioned in the constraint. Check also that foreign key constraints which reference this table are ok. */ diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 0f8f4c4d071..70225ffd9d9 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,9 +1,89 @@ +2009-10-29 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb-autoinc.result, + mysql-test/innodb-autoinc.test: + Fix Bug#47125 auto_increment start value is ignored if an index is + created and engine=innodb + +2009-10-29 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb_bug47777.result, + mysql-test/innodb_bug47777.test: + Fix Bug#47777 innodb dies with spatial pk: Failing assertion: buf <= + original_buf + buf_len + +2009-10-29 The InnoDB Team + + * handler/ha_innodb.cc: + Fix Bug#38996 Race condition in ANALYZE TABLE + +2009-10-29 The InnoDB Team + + * handler/ha_innodb.cc: + Fix bug#42383: Can't create table 'test.bug39438' + +2009-10-29 The InnoDB Team + + * os/os0proc.c: + Fix Bug#48237 Error handling in os_mem_alloc_large appears to + be incorrect + +2009-10-29 The InnoDB Team + + * buf/buf0buf.c, buf/buf0lru.c, include/buf0buf.h, include/buf0buf.ic: + Fix corruption of the buf_pool->LRU_old list and improve debug + assertions. + +2009-10-28 The InnoDB Team + + * srv/srv0start.c: + Fix Bug#41490 After enlargement of InnoDB page size, the error message + become inaccurate + +2009-10-26 The InnoDB Team + + * row/row0ins.c: + When allocating a data tuple, zero out the system fields in order + to avoid Valgrind warnings about uninitialized fields in + dtuple_validate(). + +2009-10-22 The InnoDB Team + + * handler/ha_innodb.cc, mysql-test/innodb-zip.result, + mysql-test/innodb-zip.test, mysql-test/innodb_bug44369.result, + mysql-test/innodb_bug44369.test: + Fix Bug#47233 Innodb calls push_warning(MYSQL_ERROR::WARN_LEVEL_ERROR) + +2009-10-19 The InnoDB Team + + * mysql-test/innodb_information_schema.test: + Fix Bug#47808 innodb_information_schema.test fails when run under + valgrind + +2009-10-15 The InnoDB Team + + * include/page0page.ic: + Fix Bug#47058 Failure to compile innodb_plugin on solaris 10u7 + spro + cc/CC 5.10 + +2009-10-05 The InnoDB Team + + * buf/buf0buf.c: + Do not invalidate buffer pool while an LRU batch is active. Added code + to buf_pool_invalidate() to wait for the running batches to finish. + +2009-10-01 The InnoDB Team + + * handler/ha_innodb.cc: + Fix Bug#47763 typo in error message: Failed to open table %s after %lu + attemtps. + 2009-10-01 The InnoDB Team * fsp/fsp0fsp.c, row/row0merge.c: - Clean up after a crash during DROP INDEX. When InnoDB crashes + Clean up after a crash during DROP INDEX. When InnoDB crashes while dropping an index, ensure that the index will be completely - dropped during crash recovery. The MySQL .frm file may still + dropped during crash recovery. The MySQL .frm file may still contain the dropped index, but there is little that we can do about it. @@ -20,15 +100,15 @@ include/page0zip.h, page/page0cur.c, page/page0page.c, page/page0zip.c: Do not write to PAGE_INDEX_ID when restoring an uncompressed page - after a compression failure. The field should only be written - when creating a B-tree page. This fix addresses a race condition + after a compression failure. The field should only be written + when creating a B-tree page. This fix addresses a race condition in a debug assertion. 2009-09-28 The InnoDB Team * fil/fil0fil.c: Try to prevent the reuse of tablespace identifiers after InnoDB - has crashed during table creation. Also, refuse to start if files + has crashed during table creation. Also, refuse to start if files with duplicate tablespace identifiers are encountered. 2009-09-25 The InnoDB Team diff --git a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c index d87abbd0ed9..ff31457d200 100644 --- a/storage/innodb_plugin/buf/buf0buf.c +++ b/storage/innodb_plugin/buf/buf0buf.c @@ -1163,10 +1163,15 @@ buf_relocate( #ifdef UNIV_LRU_DEBUG /* buf_pool->LRU_old must be the first item in the LRU list whose "old" flag is set. */ + ut_a(buf_pool->LRU_old->old); ut_a(!UT_LIST_GET_PREV(LRU, buf_pool->LRU_old) || !UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)->old); ut_a(!UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old) || UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)->old); + } else { + /* Check that the "old" flag is consistent in + the block and its neighbours. */ + buf_page_set_old(dpage, buf_page_is_old(dpage)); #endif /* UNIV_LRU_DEBUG */ } diff --git a/storage/innodb_plugin/buf/buf0flu.c b/storage/innodb_plugin/buf/buf0flu.c index 74dd0c07ca6..8b614ce90e5 100644 --- a/storage/innodb_plugin/buf/buf0flu.c +++ b/storage/innodb_plugin/buf/buf0flu.c @@ -303,6 +303,28 @@ buf_flush_write_complete( } } +/********************************************************************//** +Flush a batch of writes to the datafiles that have already been +written by the OS. */ +static +void +buf_flush_sync_datafiles(void) +/*==========================*/ +{ + /* Wake possible simulated aio thread to actually post the + writes to the operating system */ + os_aio_simulated_wake_handler_threads(); + + /* Wait that all async writes to tablespaces have been posted to + the OS */ + os_aio_wait_until_no_pending_writes(); + + /* Now we flush the data to disk (for example, with fsync) */ + fil_flush_file_spaces(FIL_TABLESPACE); + + return; +} + /********************************************************************//** Flushes possible buffered writes from the doublewrite memory buffer to disk, and also wakes up the aio thread if simulated aio is used. It is very @@ -320,8 +342,8 @@ buf_flush_buffered_writes(void) ulint i; if (!srv_use_doublewrite_buf || trx_doublewrite == NULL) { - os_aio_simulated_wake_handler_threads(); - + /* Sync the writes to the disk. */ + buf_flush_sync_datafiles(); return; } @@ -529,22 +551,10 @@ flush: buf_LRU_stat_inc_io(); } - /* Wake possible simulated aio thread to actually post the - writes to the operating system */ - - os_aio_simulated_wake_handler_threads(); - - /* Wait that all async writes to tablespaces have been posted to - the OS */ - - os_aio_wait_until_no_pending_writes(); - - /* Now we flush the data to disk (for example, with fsync) */ - - fil_flush_file_spaces(FIL_TABLESPACE); + /* Sync the writes to the disk. */ + buf_flush_sync_datafiles(); /* We can now reuse the doublewrite memory buffer: */ - trx_doublewrite->first_free = 0; mutex_exit(&(trx_doublewrite->mutex)); diff --git a/storage/innodb_plugin/buf/buf0lru.c b/storage/innodb_plugin/buf/buf0lru.c index d3a79d62d3f..4f19fd13fa5 100644 --- a/storage/innodb_plugin/buf/buf0lru.c +++ b/storage/innodb_plugin/buf/buf0lru.c @@ -978,14 +978,14 @@ buf_LRU_old_adjust_len(void) #ifdef UNIV_LRU_DEBUG ut_a(!LRU_old->old); #endif /* UNIV_LRU_DEBUG */ - buf_page_set_old(LRU_old, TRUE); old_len = ++buf_pool->LRU_old_len; + buf_page_set_old(LRU_old, TRUE); } else if (old_len > new_len + BUF_LRU_OLD_TOLERANCE) { - buf_page_set_old(LRU_old, FALSE); buf_pool->LRU_old = UT_LIST_GET_NEXT(LRU, LRU_old); old_len = --buf_pool->LRU_old_len; + buf_page_set_old(LRU_old, FALSE); } else { return; } @@ -1009,13 +1009,13 @@ buf_LRU_old_init(void) the adjust function to move the LRU_old pointer to the right position */ - bpage = UT_LIST_GET_FIRST(buf_pool->LRU); - - while (bpage != NULL) { + for (bpage = UT_LIST_GET_LAST(buf_pool->LRU); bpage != NULL; + bpage = UT_LIST_GET_PREV(LRU, bpage)) { ut_ad(bpage->in_LRU_list); ut_ad(buf_page_in_file(bpage)); - buf_page_set_old(bpage, TRUE); - bpage = UT_LIST_GET_NEXT(LRU, bpage); + /* This loop temporarily violates the + assertions of buf_page_set_old(). */ + bpage->old = TRUE; } buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU); @@ -1091,10 +1091,19 @@ buf_LRU_remove_block( buf_unzip_LRU_remove_block_if_needed(bpage); - /* If the LRU list is so short that LRU_old not defined, return */ + /* If the LRU list is so short that LRU_old is not defined, + clear the "old" flags and return */ if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) { + for (bpage = UT_LIST_GET_FIRST(buf_pool->LRU); bpage != NULL; + bpage = UT_LIST_GET_NEXT(LRU, bpage)) { + /* This loop temporarily violates the + assertions of buf_page_set_old(). */ + bpage->old = FALSE; + } + buf_pool->LRU_old = NULL; + buf_pool->LRU_old_len = 0; return; } @@ -1155,14 +1164,13 @@ buf_LRU_add_block_to_end_low( UT_LIST_ADD_LAST(LRU, buf_pool->LRU, bpage); ut_d(bpage->in_LRU_list = TRUE); - buf_page_set_old(bpage, TRUE); - if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) { ut_ad(buf_pool->LRU_old); /* Adjust the length of the old block list if necessary */ + buf_page_set_old(bpage, TRUE); buf_pool->LRU_old_len++; buf_LRU_old_adjust_len(); @@ -1171,8 +1179,9 @@ buf_LRU_add_block_to_end_low( /* The LRU list is now long enough for LRU_old to become defined: init it */ - buf_pool->LRU_old_len++; buf_LRU_old_init(); + } else { + buf_page_set_old(bpage, buf_pool->LRU_old != NULL); } /* If this is a zipped block with decompressed frame as well @@ -1223,14 +1232,13 @@ buf_LRU_add_block_low( ut_d(bpage->in_LRU_list = TRUE); - buf_page_set_old(bpage, old); - if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) { ut_ad(buf_pool->LRU_old); /* Adjust the length of the old block list if necessary */ + buf_page_set_old(bpage, old); buf_LRU_old_adjust_len(); } else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) { @@ -1239,6 +1247,8 @@ buf_LRU_add_block_low( defined: init it */ buf_LRU_old_init(); + } else { + buf_page_set_old(bpage, buf_pool->LRU_old != NULL); } /* If this is a zipped block with decompressed frame as well @@ -1436,15 +1446,6 @@ alloc: buf_pool->LRU_old = b; } -#ifdef UNIV_LRU_DEBUG - ut_a(prev_b->old - || !UT_LIST_GET_NEXT(LRU, b) - || UT_LIST_GET_NEXT(LRU, b)->old); - } else { - ut_a(!prev_b->old - || !UT_LIST_GET_NEXT(LRU, b) - || !UT_LIST_GET_NEXT(LRU, b)->old); -#endif /* UNIV_LRU_DEBUG */ } lru_len = UT_LIST_GET_LEN(buf_pool->LRU); @@ -1460,6 +1461,11 @@ alloc: defined: init it */ buf_LRU_old_init(); } +#ifdef UNIV_LRU_DEBUG + /* Check that the "old" flag is consistent + in the block and its neighbours. */ + buf_page_set_old(b, buf_page_is_old(b)); +#endif /* UNIV_LRU_DEBUG */ } else { ut_d(b->in_LRU_list = FALSE); buf_LRU_add_block_low(b, buf_page_is_old(b)); @@ -1966,19 +1972,24 @@ buf_LRU_validate(void) } if (buf_page_is_old(bpage)) { - old_len++; - } + const buf_page_t* prev + = UT_LIST_GET_PREV(LRU, bpage); + const buf_page_t* next + = UT_LIST_GET_NEXT(LRU, bpage); - if (buf_pool->LRU_old && (old_len == 1)) { - ut_a(buf_pool->LRU_old == bpage); + if (!old_len++) { + ut_a(buf_pool->LRU_old == bpage); + } else { + ut_a(!prev || buf_page_is_old(prev)); + } + + ut_a(!next || buf_page_is_old(next)); } bpage = UT_LIST_GET_NEXT(LRU, bpage); } - if (buf_pool->LRU_old) { - ut_a(buf_pool->LRU_old_len == old_len); - } + ut_a(buf_pool->LRU_old_len == old_len); UT_LIST_VALIDATE(list, buf_page_t, buf_pool->free, ut_ad(ut_list_node_313->in_free_list)); diff --git a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c index df6dad86990..ba6f2f8666f 100644 --- a/storage/innodb_plugin/fil/fil0fil.c +++ b/storage/innodb_plugin/fil/fil0fil.c @@ -659,6 +659,7 @@ fil_node_open_file( #ifdef UNIV_HOTBACKUP if (space->id == 0) { node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE); + os_file_close(node->handle); goto add_size; } #endif /* UNIV_HOTBACKUP */ @@ -3244,7 +3245,7 @@ fil_load_single_table_tablespace( fprintf(stderr, "InnoDB: Renaming tablespace %s of id %lu,\n" "InnoDB: to %s_ibbackup_old_vers_\n" - "InnoDB: because its size %lld is too small" + "InnoDB: because its size %" PRId64 " is too small" " (< 4 pages 16 kB each),\n" "InnoDB: or the space id in the file header" " is not sensible.\n" diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 8ac804ca9b6..ac710ea2b15 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -110,7 +110,7 @@ extern "C" { # ifndef MYSQL_PLUGIN_IMPORT # define MYSQL_PLUGIN_IMPORT /* nothing */ # endif /* MYSQL_PLUGIN_IMPORT */ -/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t +/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t is defined the same in both builds: the MySQL server and the InnoDB plugin. */ extern MYSQL_PLUGIN_IMPORT pthread_mutex_t LOCK_thread_count; @@ -129,6 +129,7 @@ static ulong commit_threads = 0; static pthread_mutex_t commit_threads_m; static pthread_cond_t commit_cond; static pthread_mutex_t commit_cond_m; +static pthread_mutex_t analyze_mutex; static bool innodb_inited = 0; #define INSIDE_HA_INNOBASE_CC @@ -229,21 +230,6 @@ static handler *innobase_create_handler(handlerton *hton, TABLE_SHARE *table, MEM_ROOT *mem_root); -/*********************************************************************** -This function checks each index name for a table against reserved -system default primary index name 'GEN_CLUST_INDEX'. If a name matches, -this function pushes an error message to the client, and returns true. */ -static -bool -innobase_index_name_is_reserved( -/*============================*/ - /* out: true if index name matches a - reserved name */ - const trx_t* trx, /* in: InnoDB transaction handle */ - const TABLE* form, /* in: information on table - columns and indexes */ - const char* norm_name); /* in: table name */ - /* "GEN_CLUST_INDEX" is the name reserved for Innodb default system primary index. */ static const char innobase_index_reserve_name[]= "GEN_CLUST_INDEX"; @@ -2266,6 +2252,7 @@ innobase_change_buffering_inited_ok: pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST); pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST); pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST); + pthread_mutex_init(&analyze_mutex, MY_MUTEX_INIT_FAST); pthread_cond_init(&commit_cond, NULL); innodb_inited= 1; #ifdef MYSQL_DYNAMIC_PLUGIN @@ -2320,6 +2307,7 @@ innobase_end( pthread_mutex_destroy(&prepare_commit_mutex); pthread_mutex_destroy(&commit_threads_m); pthread_mutex_destroy(&commit_cond_m); + pthread_mutex_destroy(&analyze_mutex); pthread_cond_destroy(&commit_cond); } @@ -2598,6 +2586,8 @@ innobase_rollback( innobase_release_stat_resources(trx); + trx->n_autoinc_rows = 0; /* Reset the number AUTO-INC rows required */ + /* If we had reserved the auto-inc lock for some table (if we come here to roll back the latest SQL statement) we release it now before a possibly lengthy rollback */ @@ -3758,7 +3748,10 @@ ha_innobase::store_key_val_for_row( } else if (mysql_type == MYSQL_TYPE_TINY_BLOB || mysql_type == MYSQL_TYPE_MEDIUM_BLOB || mysql_type == MYSQL_TYPE_BLOB - || mysql_type == MYSQL_TYPE_LONG_BLOB) { + || mysql_type == MYSQL_TYPE_LONG_BLOB + /* MYSQL_TYPE_GEOMETRY data is treated + as BLOB data in innodb. */ + || mysql_type == MYSQL_TYPE_GEOMETRY) { CHARSET_INFO* cs; ulint key_len; @@ -5688,7 +5681,7 @@ create_table_def( number fits in one byte in prtype */ push_warning_printf( (THD*) trx->mysql_thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_CANT_CREATE_TABLE, "In InnoDB, charset-collation codes" " must be below 256." @@ -5722,7 +5715,7 @@ create_table_def( if (dict_col_name_is_reserved(field->field_name)){ push_warning_printf( (THD*) trx->mysql_thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_CANT_CREATE_TABLE, "Error creating table '%s' with " "column name '%s'. '%s' is a " @@ -5956,7 +5949,7 @@ create_options_are_valid( /* Valid value. */ break; default: - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: invalid" " KEY_BLOCK_SIZE = %lu." @@ -5970,7 +5963,7 @@ create_options_are_valid( /* If KEY_BLOCK_SIZE was specified, check for its dependencies. */ if (kbs_specified && !srv_file_per_table) { - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: KEY_BLOCK_SIZE" " requires innodb_file_per_table."); @@ -5978,7 +5971,7 @@ create_options_are_valid( } if (kbs_specified && srv_file_format < DICT_TF_FORMAT_ZIP) { - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: KEY_BLOCK_SIZE" " requires innodb_file_format >" @@ -6002,7 +5995,7 @@ create_options_are_valid( if (!srv_file_per_table) { push_warning_printf( thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: ROW_FORMAT=%s" " requires innodb_file_per_table.", @@ -6014,7 +6007,7 @@ create_options_are_valid( if (srv_file_format < DICT_TF_FORMAT_ZIP) { push_warning_printf( thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: ROW_FORMAT=%s" " requires innodb_file_format >" @@ -6031,7 +6024,7 @@ create_options_are_valid( && form->s->row_type == ROW_TYPE_DYNAMIC) { push_warning_printf( thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: cannot specify" " ROW_FORMAT = DYNAMIC with" @@ -6055,7 +6048,7 @@ create_options_are_valid( if (kbs_specified) { push_warning_printf( thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: cannot specify" " ROW_FORMAT = %s with" @@ -6068,7 +6061,7 @@ create_options_are_valid( default: push_warning(thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, + MYSQL_ERROR::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: invalid ROW_FORMAT specifier."); ret = FALSE; @@ -6132,13 +6125,15 @@ ha_innobase::create( 1. /: for normal table creation 2. full path: for temp table creation, or sym link - When srv_file_per_table is on, check for full path pattern, i.e. + When srv_file_per_table is on and mysqld_embedded is off, + check for full path pattern, i.e. X:\dir\..., X is a driver letter, or \\dir1\dir2\..., UNC path returns error if it is in full path format, but not creating a temp. table. Currently InnoDB does not support symbolic link on Windows. */ if (srv_file_per_table + && !mysqld_embedded && (!create_info->options & HA_LEX_CREATE_TMP_TABLE)) { if ((name[1] == ':') @@ -6342,7 +6337,8 @@ ha_innobase::create( /* Check for name conflicts (with reserved name) for any user indices to be created. */ - if (innobase_index_name_is_reserved(trx, form, norm_name)) { + if (innobase_index_name_is_reserved(trx, form->key_info, + form->s->keys)) { error = -1; goto cleanup; } @@ -6429,18 +6425,22 @@ ha_innobase::create( setup at this stage and so we use thd. */ /* We need to copy the AUTOINC value from the old table if - this is an ALTER TABLE. */ + this is an ALTER TABLE or CREATE INDEX because CREATE INDEX + does a table copy too. */ if (((create_info->used_fields & HA_CREATE_USED_AUTO) - || thd_sql_command(thd) == SQLCOM_ALTER_TABLE) - && create_info->auto_increment_value != 0) { + || thd_sql_command(thd) == SQLCOM_ALTER_TABLE + || thd_sql_command(thd) == SQLCOM_CREATE_INDEX) + && create_info->auto_increment_value > 0) { - /* Query was ALTER TABLE...AUTO_INCREMENT = x; or - CREATE TABLE ...AUTO_INCREMENT = x; Find out a table - definition from the dictionary and get the current value - of the auto increment field. Set a new value to the - auto increment field if the value is greater than the - maximum value in the column. */ + /* Query was one of : + CREATE TABLE ...AUTO_INCREMENT = x; or + ALTER TABLE...AUTO_INCREMENT = x; or + CREATE INDEX x on t(...); + Find out a table definition from the dictionary and get + the current value of the auto increment field. Set a new + value to the auto increment field if the value is greater + than the maximum value in the column. */ auto_inc_value = create_info->auto_increment_value; @@ -7294,9 +7294,15 @@ ha_innobase::analyze( THD* thd, /*!< in: connection thread handle */ HA_CHECK_OPT* check_opt) /*!< in: currently ignored */ { + /* Serialize ANALYZE TABLE inside InnoDB, see + Bug#38996 Race condition in ANALYZE TABLE */ + pthread_mutex_lock(&analyze_mutex); + /* Simply call ::info() with all the flags */ info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE); + pthread_mutex_unlock(&analyze_mutex); + return(0); } @@ -7891,8 +7897,9 @@ ha_innobase::external_lock( { ulong const binlog_format= thd_binlog_format(thd); ulong const tx_isolation = thd_tx_isolation(ha_thd()); - if (tx_isolation <= ISO_READ_COMMITTED && - binlog_format == BINLOG_FORMAT_STMT) + if (tx_isolation <= ISO_READ_COMMITTED + && binlog_format == BINLOG_FORMAT_STMT + && thd_binlog_filter_ok(thd)) { char buf[256]; my_snprintf(buf, sizeof(buf), @@ -8772,6 +8779,7 @@ ha_innobase::get_auto_increment( AUTOINC counter after attempting to insert the row. */ if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) { ulonglong need; + ulonglong current; ulonglong next_value; ulonglong col_max_value; @@ -8780,11 +8788,12 @@ ha_innobase::get_auto_increment( col_max_value = innobase_get_int_col_max_value( table->next_number_field); + 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( - *first_value, need, offset, col_max_value); + current, need, offset, col_max_value); prebuilt->autoinc_last_value = next_value; @@ -9803,36 +9812,39 @@ static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff) /*********************************************************************** This function checks each index name for a table against reserved system default primary index name 'GEN_CLUST_INDEX'. If a name matches, -this function pushes an error message to the client, and returns true. */ -static +this function pushes an warning message to the client, and returns true. */ +extern "C" UNIV_INTERN bool innobase_index_name_is_reserved( /*============================*/ /* out: true if an index name matches the reserved name */ const trx_t* trx, /* in: InnoDB transaction handle */ - const TABLE* form, /* in: information on table - columns and indexes */ - const char* norm_name) /* in: table name */ + const KEY* key_info, /* in: Indexes to be created */ + ulint num_of_keys) /* in: Number of indexes to + be created. */ { - KEY* key; + const KEY* key; uint key_num; /* index number */ - for (key_num = 0; key_num < form->s->keys; key_num++) { - key = form->key_info + key_num; + for (key_num = 0; key_num < num_of_keys; key_num++) { + key = &key_info[key_num]; if (innobase_strcasecmp(key->name, innobase_index_reserve_name) == 0) { /* Push warning to mysql */ push_warning_printf((THD*) trx->mysql_thd, - MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_CANT_CREATE_TABLE, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_NAME_FOR_INDEX, "Cannot Create Index with name " "'%s'. The name is reserved " "for the system default primary " "index.", innobase_index_reserve_name); + my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), + innobase_index_reserve_name); + return(true); } } diff --git a/storage/innodb_plugin/handler/ha_innodb.h b/storage/innodb_plugin/handler/ha_innodb.h index cc98003f8ff..4779651ee27 100644 --- a/storage/innodb_plugin/handler/ha_innodb.h +++ b/storage/innodb_plugin/handler/ha_innodb.h @@ -257,6 +257,13 @@ int thd_binlog_format(const MYSQL_THD thd); @param all TRUE <=> rollback main transaction. */ void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all); + +/** + Check if binary logging is filtered for thread's current db. + @param thd Thread handle + @retval 1 the query is not filtered, 0 otherwise. +*/ +bool thd_binlog_filter_ok(const MYSQL_THD thd); } typedef struct trx_struct trx_t; @@ -282,3 +289,21 @@ trx_t* innobase_trx_allocate( /*==================*/ MYSQL_THD thd); /*!< in: user thread handle */ + + +/*********************************************************************//** +This function checks each index name for a table against reserved +system default primary index name 'GEN_CLUST_INDEX'. If a name +matches, this function pushes an warning message to the client, +and returns true. */ +extern "C" +bool +innobase_index_name_is_reserved( +/*============================*/ + /* out: true if the index name + matches the reserved name */ + const trx_t* trx, /* in: InnoDB transaction handle */ + const KEY* key_info, /* in: Indexes to be created */ + ulint num_of_keys); /* in: Number of indexes to + be created. */ + diff --git a/storage/innodb_plugin/handler/handler0alter.cc b/storage/innodb_plugin/handler/handler0alter.cc index 1aa0e6b126c..37aed06b28a 100644 --- a/storage/innodb_plugin/handler/handler0alter.cc +++ b/storage/innodb_plugin/handler/handler0alter.cc @@ -628,7 +628,7 @@ ha_innobase::add_index( ulint num_created = 0; ibool dict_locked = FALSE; ulint new_primary; - ulint error; + int error; DBUG_ENTER("ha_innobase::add_index"); ut_a(table); @@ -656,9 +656,13 @@ ha_innobase::add_index( innodb_table = indexed_table = dict_table_get(prebuilt->table->name, FALSE); - /* Check that index keys are sensible */ - - error = innobase_check_index_keys(key_info, num_of_keys); + /* Check if the index name is reserved. */ + if (innobase_index_name_is_reserved(trx, key_info, num_of_keys)) { + error = -1; + } else { + /* Check that index keys are sensible */ + error = innobase_check_index_keys(key_info, num_of_keys); + } if (UNIV_UNLIKELY(error)) { err_exit: diff --git a/storage/innodb_plugin/include/buf0buf.h b/storage/innodb_plugin/include/buf0buf.h index e9d95a14f1b..927ff893e39 100644 --- a/storage/innodb_plugin/include/buf0buf.h +++ b/storage/innodb_plugin/include/buf0buf.h @@ -1129,7 +1129,7 @@ struct buf_page_struct{ debugging */ #endif /* UNIV_DEBUG */ unsigned old:1; /*!< TRUE if the block is in the old - blocks in the LRU list */ + blocks in buf_pool->LRU_old */ unsigned freed_page_clock:31;/*!< the value of buf_pool->freed_page_clock when this block was the last @@ -1393,8 +1393,7 @@ struct buf_pool_struct{ the block to which LRU_old points onward, including that block; see buf0lru.c for the restrictions - on this value; not defined if - LRU_old == NULL; + on this value; 0 if LRU_old == NULL; NOTE: LRU_old_len must be adjusted whenever LRU_old shrinks or grows! */ diff --git a/storage/innodb_plugin/include/buf0buf.ic b/storage/innodb_plugin/include/buf0buf.ic index 8b1f904a090..0f92a59a1c7 100644 --- a/storage/innodb_plugin/include/buf0buf.ic +++ b/storage/innodb_plugin/include/buf0buf.ic @@ -466,10 +466,19 @@ buf_page_set_old( ut_ad(bpage->in_LRU_list); #ifdef UNIV_LRU_DEBUG - if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage) - && UT_LIST_GET_PREV(LRU, bpage)->old - == UT_LIST_GET_NEXT(LRU, bpage)->old) { - ut_a(UT_LIST_GET_PREV(LRU, bpage)->old == old); + ut_a((buf_pool->LRU_old_len == 0) == (buf_pool->LRU_old == NULL)); + /* If a block is flagged "old", the LRU_old list must exist. */ + ut_a(!old || buf_pool->LRU_old); + + if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)) { + const buf_page_t* prev = UT_LIST_GET_PREV(LRU, bpage); + const buf_page_t* next = UT_LIST_GET_NEXT(LRU, bpage); + if (prev->old == next->old) { + ut_a(prev->old == old); + } else { + ut_a(!prev->old); + ut_a(buf_pool->LRU_old == (old ? bpage : next)); + } } #endif /* UNIV_LRU_DEBUG */ diff --git a/storage/innodb_plugin/include/page0page.ic b/storage/innodb_plugin/include/page0page.ic index 318ec1cc1f2..8f794410f20 100644 --- a/storage/innodb_plugin/include/page0page.ic +++ b/storage/innodb_plugin/include/page0page.ic @@ -907,7 +907,7 @@ page_get_data_size( /************************************************************//** Allocates a block of memory from the free list of an index page. */ -UNIV_INTERN +UNIV_INLINE void page_mem_alloc_free( /*================*/ diff --git a/storage/innodb_plugin/include/row0mysql.h b/storage/innodb_plugin/include/row0mysql.h index 6d5d195172e..b05241f00f8 100644 --- a/storage/innodb_plugin/include/row0mysql.h +++ b/storage/innodb_plugin/include/row0mysql.h @@ -756,8 +756,6 @@ struct row_prebuilt_struct { store it here so that we can return it to MySQL */ /*----------------------*/ - UT_LIST_NODE_T(row_prebuilt_t) prebuilts; - /*!< list node of table->prebuilts */ ulint magic_n2; /*!< this should be the same as magic_n */ }; diff --git a/storage/innodb_plugin/include/univ.i b/storage/innodb_plugin/include/univ.i index 0e14f7b1cba..5d0361658af 100644 --- a/storage/innodb_plugin/include/univ.i +++ b/storage/innodb_plugin/include/univ.i @@ -237,7 +237,7 @@ by one. */ /* Linkage specifier for non-static InnoDB symbols (variables and functions) that are only referenced from within InnoDB, not from MySQL */ -#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(UNIV_HOTBACKUP) +#if defined(__GNUC__) && (__GNUC__ >= 4) || defined(__INTEL_COMPILER) # define UNIV_INTERN __attribute__((visibility ("hidden"))) #else # define UNIV_INTERN diff --git a/storage/innodb_plugin/os/os0file.c b/storage/innodb_plugin/os/os0file.c index a1d3bad2add..0cb76d1796f 100644 --- a/storage/innodb_plugin/os/os0file.c +++ b/storage/innodb_plugin/os/os0file.c @@ -832,6 +832,23 @@ next_file: ret = stat(full_path, &statinfo); if (ret) { + + if (errno == ENOENT) { + /* readdir() returned a file that does not exist, + it must have been deleted in the meantime. Do what + would have happened if the file was deleted before + readdir() - ignore and go to the next entry. + If this is the last entry then info->name will still + contain the name of the deleted file when this + function returns, but this is not an issue since the + caller shouldn't be looking at info when end of + directory is returned. */ + + ut_free(full_path); + + goto next_file; + } + os_file_handle_error_no_exit(full_path, "stat"); ut_free(full_path); diff --git a/storage/innodb_plugin/os/os0proc.c b/storage/innodb_plugin/os/os0proc.c index a0ea9a1b258..48922886f23 100644 --- a/storage/innodb_plugin/os/os0proc.c +++ b/storage/innodb_plugin/os/os0proc.c @@ -97,6 +97,7 @@ os_mem_alloc_large( fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to" " attach shared memory segment, errno %d\n", errno); + ptr = NULL; } /* Remove the shared memory segment so that it will be diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c index ab3ae70e3e2..fe51fce82c4 100644 --- a/storage/innodb_plugin/row/row0ins.c +++ b/storage/innodb_plugin/row/row0ins.c @@ -141,7 +141,7 @@ row_ins_alloc_sys_fields( dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); - ptr = mem_heap_alloc(heap, DATA_ROW_ID_LEN); + ptr = mem_heap_zalloc(heap, DATA_ROW_ID_LEN); dfield_set_data(dfield, ptr, DATA_ROW_ID_LEN); @@ -152,7 +152,7 @@ row_ins_alloc_sys_fields( col = dict_table_get_sys_col(table, DATA_TRX_ID); dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); - ptr = mem_heap_alloc(heap, DATA_TRX_ID_LEN); + ptr = mem_heap_zalloc(heap, DATA_TRX_ID_LEN); dfield_set_data(dfield, ptr, DATA_TRX_ID_LEN); @@ -163,7 +163,7 @@ row_ins_alloc_sys_fields( col = dict_table_get_sys_col(table, DATA_ROLL_PTR); dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); - ptr = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN); + ptr = mem_heap_zalloc(heap, DATA_ROLL_PTR_LEN); dfield_set_data(dfield, ptr, DATA_ROLL_PTR_LEN); } diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c index 819381fc280..540a4450045 100644 --- a/storage/innodb_plugin/row/row0mysql.c +++ b/storage/innodb_plugin/row/row0mysql.c @@ -2068,7 +2068,7 @@ Scans a table create SQL string and adds to the data dictionary the foreign key constraints declared in the string. This function should be called after the indexes for a table have been created. Each foreign key constraint must be accompanied with indexes in -bot participating tables. The indexes are allowed to contain more +both participating tables. The indexes are allowed to contain more fields than mentioned in the constraint. Check also that foreign key constraints which reference this table are ok. @return error code or DB_SUCCESS */ diff --git a/storage/innodb_plugin/srv/srv0start.c b/storage/innodb_plugin/srv/srv0start.c index 37263317126..796541a9f1a 100644 --- a/storage/innodb_plugin/srv/srv0start.c +++ b/storage/innodb_plugin/srv/srv0start.c @@ -1376,7 +1376,7 @@ innobase_start_or_create_for_mysql(void) sum_of_new_sizes += srv_data_file_sizes[i]; } - if (sum_of_new_sizes < 640) { + if (sum_of_new_sizes < 10485760 / UNIV_PAGE_SIZE) { fprintf(stderr, "InnoDB: Error: tablespace size must be" " at least 10 MB\n"); diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 931face3dc2..cdfbf16db99 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -115,6 +115,10 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type, Also we likely need to lock mutex here (in both cases with protocol and push_warning). */ +#ifdef THREAD + if (param->need_print_msg_lock) + pthread_mutex_lock(¶m->print_msg_mutex); +#endif protocol->prepare_for_resend(); protocol->store(name, length, system_charset_info); protocol->store(param->op_name, system_charset_info); @@ -123,6 +127,10 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type, if (protocol->write()) sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n", msgbuf); +#ifdef THREAD + if (param->need_print_msg_lock) + pthread_mutex_unlock(¶m->print_msg_mutex); +#endif return; } @@ -1403,8 +1411,8 @@ bool ha_myisam::check_and_repair(THD *thd) check_opt.flags|=T_QUICK; sql_print_warning("Checking table: '%s'",table->s->path.str); - old_query= thd->query; - old_query_length= thd->query_length; + old_query= thd->query(); + old_query_length= thd->query_length(); thd->set_query(table->s->table_name.str, (uint) table->s->table_name.length); diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 8f7b1399aa2..c10cfdd0c9b 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -104,6 +104,9 @@ void myisamchk_init(MI_CHECK *param) param->max_record_length= LONGLONG_MAX; param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE; param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL; +#ifdef THREAD + param->need_print_msg_lock= 0; +#endif } /* Check the status flags for the table */ @@ -2703,6 +2706,8 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, /* Initialize pthread structures before goto err. */ pthread_mutex_init(&sort_info.mutex, MY_MUTEX_INIT_FAST); pthread_cond_init(&sort_info.cond, 0); + pthread_mutex_init(¶m->print_msg_mutex, MY_MUTEX_INIT_FAST); + param->need_print_msg_lock= 1; if (!(sort_info.key_block= alloc_key_blocks(param, (uint) param->sort_key_blocks, @@ -3108,6 +3113,8 @@ err: pthread_cond_destroy (&sort_info.cond); pthread_mutex_destroy(&sort_info.mutex); + pthread_mutex_destroy(¶m->print_msg_mutex); + param->need_print_msg_lock= 0; my_free((uchar*) sort_info.ft_buf, MYF(MY_ALLOW_ZERO_PTR)); my_free((uchar*) sort_info.key_block,MYF(MY_ALLOW_ZERO_PTR)); diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index fb16af9cddf..b450d27de66 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -466,8 +466,12 @@ ok: Detach from the share if the writer is involved. Avoid others to be blocked. This includes a flush of the write buffer. This will also indicate EOF to the readers. + That means that a writer always gets here first and readers - + only when they see EOF. But if a reader finishes prematurely + because of an error it may reach this earlier - don't allow it + to detach the writer thread. */ - if (sort_param->sort_info->info->rec_cache.share) + if (sort_param->master && sort_param->sort_info->info->rec_cache.share) remove_io_thread(&sort_param->sort_info->info->rec_cache); /* Readers detach from the share if any. Avoid others to be blocked. */ @@ -789,6 +793,7 @@ cleanup: close_cached_file(to_file); /* This holds old result */ if (to_file == t_file) { + DBUG_ASSERT(t_file2.type == WRITE_CACHE); *t_file=t_file2; /* Copy result file */ t_file->current_pos= &t_file->write_pos; t_file->current_end= &t_file->write_end; diff --git a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index bc8adf6fd32..11e8c1cc191 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -14831,7 +14831,7 @@ void Dblqh::srLogLimits(Signal* signal) while(true) { ndbrequire(tmbyte < clogFileSize); if (logPartPtr.p->logExecState == LogPartRecord::LES_SEARCH_STOP) { - if (logFilePtr.p->logMaxGciCompleted[tmbyte] < logPartPtr.p->logLastGci) { + if (logFilePtr.p->logMaxGciCompleted[tmbyte] <= logPartPtr.p->logLastGci) { jam(); /* -------------------------------------------------------------------- * WE ARE STEPPING BACKWARDS FROM MBYTE TO MBYTE. THIS IS THE FIRST diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c index 2ea48ddab2f..6ae0cc3a293 100644 --- a/strings/ctype-uca.c +++ b/strings/ctype-uca.c @@ -7858,6 +7858,9 @@ static my_bool create_tailoring(CHARSET_INFO *cs, void *(*alloc)(size_t)) return 1; } + if (!cs->caseinfo) + cs->caseinfo= my_unicase_default; + if (!(newweights= (uint16**) (*alloc)(256*sizeof(uint16*)))) return 1; bzero(newweights, 256*sizeof(uint16*)); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 579685204e8..a7b10f5d587 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -46,6 +46,9 @@ static char *opt_user= 0; static char *opt_password= 0; static char *opt_host= 0; static char *opt_unix_socket= 0; +#ifdef HAVE_SMEM +static char *shared_memory_base_name= 0; +#endif static unsigned int opt_port; static my_bool tty_password= 0, opt_silent= 0; @@ -230,6 +233,26 @@ static void print_st_error(MYSQL_STMT *stmt, const char *msg) } } +/* + Enhanced version of mysql_client_init(), which may also set shared memory + base on Windows. +*/ +static MYSQL *mysql_client_init(MYSQL* con) +{ + MYSQL* res = mysql_init(con); +#ifdef HAVE_SMEM + if (res && shared_memory_base_name) + mysql_options(res, MYSQL_SHARED_MEMORY_BASE_NAME, shared_memory_base_name); +#endif + return res; +} + +/* + Disable direct calls of mysql_init, as it disregards shared memory base. +*/ +#define mysql_init(A) Please use mysql_client_init instead of mysql_init + + /* Check if the connection has InnoDB tables */ static my_bool check_have_innodb(MYSQL *conn) @@ -293,10 +316,10 @@ static MYSQL* client_connect(ulong flag, uint protocol, my_bool auto_reconnect) fprintf(stdout, "\n Establishing a connection to '%s' ...", opt_host ? opt_host : ""); - if (!(mysql= mysql_init(NULL))) + if (!(mysql= mysql_client_init(NULL))) { opt_silent= 0; - myerror("mysql_init() failed"); + myerror("mysql_client_init() failed"); exit(1); } /* enable local infile, in non-binary builds often disabled by default */ @@ -1160,9 +1183,9 @@ static my_bool thread_query(char *query) error= 0; if (!opt_silent) fprintf(stdout, "\n in thread_query(%s)", query); - if (!(l_mysql= mysql_init(NULL))) + if (!(l_mysql= mysql_client_init(NULL))) { - myerror("mysql_init() failed"); + myerror("mysql_client_init() failed"); return 1; } if (!(mysql_real_connect(l_mysql, opt_host, opt_user, @@ -2512,9 +2535,9 @@ static void test_ps_query_cache() case TEST_QCACHE_ON_WITH_OTHER_CONN: if (!opt_silent) fprintf(stdout, "\n Establishing a test connection ..."); - if (!(lmysql= mysql_init(NULL))) + if (!(lmysql= mysql_client_init(NULL))) { - printf("mysql_init() failed"); + printf("mysql_client_init() failed"); DIE_UNLESS(0); } if (!(mysql_real_connect(lmysql, opt_host, opt_user, @@ -4960,9 +4983,9 @@ static void test_stmt_close() if (!opt_silent) fprintf(stdout, "\n Establishing a test connection ..."); - if (!(lmysql= mysql_init(NULL))) + if (!(lmysql= mysql_client_init(NULL))) { - myerror("mysql_init() failed"); + myerror("mysql_client_init() failed"); exit(1); } if (!(mysql_real_connect(lmysql, opt_host, opt_user, @@ -5851,9 +5874,9 @@ DROP TABLE IF EXISTS test_multi_tab"; rc= mysql_more_results(mysql); DIE_UNLESS(rc == 0); - if (!(mysql_local= mysql_init(NULL))) + if (!(mysql_local= mysql_client_init(NULL))) { - fprintf(stdout, "\n mysql_init() failed"); + fprintf(stdout, "\n mysql_client_init() failed"); exit(1); } @@ -5976,9 +5999,9 @@ static void test_prepare_multi_statements() char query[MAX_TEST_QUERY_LENGTH]; myheader("test_prepare_multi_statements"); - if (!(mysql_local= mysql_init(NULL))) + if (!(mysql_local= mysql_client_init(NULL))) { - fprintf(stderr, "\n mysql_init() failed"); + fprintf(stderr, "\n mysql_client_init() failed"); exit(1); } @@ -7459,9 +7482,9 @@ static void test_prepare_grant() if (!opt_silent) fprintf(stdout, "\n Establishing a test connection ..."); - if (!(lmysql= mysql_init(NULL))) + if (!(lmysql= mysql_client_init(NULL))) { - myerror("mysql_init() failed"); + myerror("mysql_client_init() failed"); exit(1); } if (!(mysql_real_connect(lmysql, opt_host, "test_grant", @@ -7915,9 +7938,9 @@ static void test_drop_temp() if (!opt_silent) fprintf(stdout, "\n Establishing a test connection ..."); - if (!(lmysql= mysql_init(NULL))) + if (!(lmysql= mysql_client_init(NULL))) { - myerror("mysql_init() failed"); + myerror("mysql_client_init() failed"); exit(1); } @@ -13159,7 +13182,7 @@ static void test_bug15518() int rc; myheader("test_bug15518"); - mysql1= mysql_init(NULL); + mysql1= mysql_client_init(NULL); if (!mysql_real_connect(mysql1, opt_host, opt_user, opt_password, opt_db ? opt_db : "test", opt_port, opt_unix_socket, @@ -13315,9 +13338,9 @@ static void test_bug8378() if (!opt_silent) fprintf(stdout, "\n Establishing a test connection ..."); - if (!(lmysql= mysql_init(NULL))) + if (!(lmysql= mysql_client_init(NULL))) { - myerror("mysql_init() failed"); + myerror("mysql_client_init() failed"); exit(1); } if (mysql_options(lmysql, MYSQL_SET_CHARSET_NAME, "gbk")) @@ -13856,7 +13879,7 @@ static void test_bug9992() if (!opt_silent) printf("Establishing a connection with option CLIENT_MULTI_STATEMENTS..\n"); - mysql1= mysql_init(NULL); + mysql1= mysql_client_init(NULL); if (!mysql_real_connect(mysql1, opt_host, opt_user, opt_password, opt_db ? opt_db : "test", opt_port, opt_unix_socket, @@ -14445,9 +14468,9 @@ static void test_bug12001() myheader("test_bug12001"); - if (!(mysql_local= mysql_init(NULL))) + if (!(mysql_local= mysql_client_init(NULL))) { - fprintf(stdout, "\n mysql_init() failed"); + fprintf(stdout, "\n mysql_client_init() failed"); exit(1); } @@ -15172,9 +15195,9 @@ static void test_opt_reconnect() myheader("test_opt_reconnect"); - if (!(lmysql= mysql_init(NULL))) + if (!(lmysql= mysql_client_init(NULL))) { - myerror("mysql_init() failed"); + myerror("mysql_client_init() failed"); exit(1); } @@ -15209,9 +15232,9 @@ static void test_opt_reconnect() mysql_close(lmysql); - if (!(lmysql= mysql_init(NULL))) + if (!(lmysql= mysql_client_init(NULL))) { - myerror("mysql_init() failed"); + myerror("mysql_client_init() failed"); DIE_UNLESS(0); } @@ -15246,7 +15269,7 @@ static void test_bug12744() int rc; myheader("test_bug12744"); - lmysql= mysql_init(NULL); + lmysql= mysql_client_init(NULL); DIE_UNLESS(lmysql); if (!mysql_real_connect(lmysql, opt_host, opt_user, opt_password, @@ -15819,7 +15842,7 @@ static void test_bug15752() rc= mysql_query(mysql, "create procedure p1() select 1"); myquery(rc); - mysql_init(&mysql_local); + mysql_client_init(&mysql_local); if (! mysql_real_connect(&mysql_local, opt_host, opt_user, opt_password, current_db, opt_port, opt_unix_socket, @@ -16705,7 +16728,7 @@ static void test_bug29692() { MYSQL* conn; - if (!(conn= mysql_init(NULL))) + if (!(conn= mysql_client_init(NULL))) { myerror("test_bug29692 init failed"); exit(1); @@ -16840,7 +16863,7 @@ static void test_bug30472() /* Create a new connection. */ - DIE_UNLESS(mysql_init(&con)); + DIE_UNLESS(mysql_client_init(&con)); DIE_UNLESS(mysql_real_connect(&con, opt_host, @@ -17014,7 +17037,7 @@ static void test_bug20023() /* Create a new connection. */ - DIE_UNLESS(mysql_init(&con)); + DIE_UNLESS(mysql_client_init(&con)); DIE_UNLESS(mysql_real_connect(&con, opt_host, @@ -17151,7 +17174,7 @@ static void bug31418_impl() /* Create a new connection. */ - DIE_UNLESS(mysql_init(&con)); + DIE_UNLESS(mysql_client_init(&con)); DIE_UNLESS(mysql_real_connect(&con, opt_host, @@ -18001,7 +18024,7 @@ static void test_bug44495() "END;"); myquery(rc); - DIE_UNLESS(mysql_init(&con)); + DIE_UNLESS(mysql_client_init(&con)); DIE_UNLESS(mysql_real_connect(&con, opt_host, opt_user, opt_password, current_db, opt_port, opt_unix_socket, @@ -18064,6 +18087,11 @@ static struct my_option client_test_long_options[] = 0, 0, 0, 0, 0, 0}, {"silent", 's', "Be more silent", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef HAVE_SMEM + {"shared-memory-base-name", 'm', "Base name of shared memory.", + (uchar**) &shared_memory_base_name, (uchar**)&shared_memory_base_name, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#endif {"socket", 'S', "Socket file to use for connection", (uchar **) &opt_unix_socket, (uchar **) &opt_unix_socket, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/vio/vio.c b/vio/vio.c index e088687098b..fd8e2e5a402 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -43,7 +43,7 @@ static void vio_init(Vio* vio, enum enum_vio_type type, if ((flags & VIO_BUFFERED_READ) && !(vio->read_buffer= (char*)my_malloc(VIO_READ_BUFFER_SIZE, MYF(MY_WME)))) flags&= ~VIO_BUFFERED_READ; -#ifdef __WIN__ +#ifdef _WIN32 if (type == VIO_TYPE_NAMEDPIPE) { vio->viodelete =vio_delete; @@ -59,9 +59,16 @@ static void vio_init(Vio* vio, enum enum_vio_type type, vio->in_addr =vio_in_addr; vio->vioblocking =vio_blocking; vio->is_blocking =vio_is_blocking; - vio->timeout =vio_ignore_timeout; + + vio->timeout=vio_win32_timeout; + /* Set default timeout */ + vio->read_timeout_millis = INFINITE; + vio->write_timeout_millis = INFINITE; + + memset(&(vio->pipe_overlapped), 0, sizeof(OVERLAPPED)); + vio->pipe_overlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL); + DBUG_VOID_RETURN; } - else /* default is VIO_TYPE_TCPIP */ #endif #ifdef HAVE_SMEM if (type == VIO_TYPE_SHARED_MEMORY) @@ -79,9 +86,14 @@ static void vio_init(Vio* vio, enum enum_vio_type type, vio->in_addr =vio_in_addr; vio->vioblocking =vio_blocking; vio->is_blocking =vio_is_blocking; - vio->timeout =vio_ignore_timeout; + + /* Currently, shared memory is on Windows only, hence the below is ok*/ + vio->timeout= vio_win32_timeout; + /* Set default timeout */ + vio->read_timeout_millis= INFINITE; + vio->write_timeout_millis= INFINITE; + DBUG_VOID_RETURN; } - else #endif #ifdef HAVE_OPENSSL if (type == VIO_TYPE_SSL) @@ -100,8 +112,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type, vio->vioblocking =vio_ssl_blocking; vio->is_blocking =vio_is_blocking; vio->timeout =vio_timeout; + DBUG_VOID_RETURN; } - else /* default is VIO_TYPE_TCPIP */ #endif /* HAVE_OPENSSL */ { vio->viodelete =vio_delete; @@ -193,7 +205,7 @@ Vio *vio_new_win32pipe(HANDLE hPipe) } #ifdef HAVE_SMEM -Vio *vio_new_win32shared_memory(NET *net,HANDLE handle_file_map, HANDLE handle_map, +Vio *vio_new_win32shared_memory(HANDLE handle_file_map, HANDLE handle_map, HANDLE event_server_wrote, HANDLE event_server_read, HANDLE event_client_wrote, HANDLE event_client_read, HANDLE event_conn_closed) @@ -212,7 +224,6 @@ Vio *vio_new_win32shared_memory(NET *net,HANDLE handle_file_map, HANDLE handle_m vio->event_conn_closed= event_conn_closed; vio->shared_memory_remain= 0; vio->shared_memory_pos= handle_map; - vio->net= net; strmov(vio->desc, "shared memory"); } DBUG_RETURN(vio); diff --git a/vio/vio_priv.h b/vio/vio_priv.h index 792fad4cc66..21fa80143cd 100644 --- a/vio/vio_priv.h +++ b/vio/vio_priv.h @@ -25,7 +25,10 @@ #include #include -void vio_ignore_timeout(Vio *vio, uint which, uint timeout); +#ifdef _WIN32 +void vio_win32_timeout(Vio *vio, uint which, uint timeout); +#endif + void vio_timeout(Vio *vio,uint which, uint timeout); #ifdef HAVE_OPENSSL diff --git a/vio/viosocket.c b/vio/viosocket.c index 2d7fd0e08cd..c929cac2a05 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -261,19 +261,13 @@ int vio_close(Vio * vio) { int r=0; DBUG_ENTER("vio_close"); -#ifdef __WIN__ - if (vio->type == VIO_TYPE_NAMEDPIPE) - { -#if defined(__NT__) && defined(MYSQL_SERVER) - CancelIo(vio->hPipe); - DisconnectNamedPipe(vio->hPipe); -#endif - r=CloseHandle(vio->hPipe); - } - else -#endif /* __WIN__ */ + if (vio->type != VIO_CLOSED) { + DBUG_ASSERT(vio->type == VIO_TYPE_TCPIP || + vio->type == VIO_TYPE_SOCKET || + vio->type == VIO_TYPE_SSL); + DBUG_ASSERT(vio->sd >= 0); if (shutdown(vio->sd, SHUT_RDWR)) r= -1; @@ -417,44 +411,97 @@ void vio_timeout(Vio *vio, uint which, uint timeout) #ifdef __WIN__ -size_t vio_read_pipe(Vio * vio, uchar* buf, size_t size) + +/* + Finish pending IO on pipe. Honor wait timeout +*/ +static int pipe_complete_io(Vio* vio, char* buf, size_t size, DWORD timeout_millis) { DWORD length; + DWORD ret; + + DBUG_ENTER("pipe_complete_io"); + + ret= WaitForSingleObject(vio->pipe_overlapped.hEvent, timeout_millis); + /* + WaitForSingleObjects will normally return WAIT_OBJECT_O (success, IO completed) + or WAIT_TIMEOUT. + */ + if(ret != WAIT_OBJECT_0) + { + CancelIo(vio->hPipe); + DBUG_PRINT("error",("WaitForSingleObject() returned %d", ret)); + DBUG_RETURN(-1); + } + + if (!GetOverlappedResult(vio->hPipe,&(vio->pipe_overlapped),&length, FALSE)) + { + DBUG_PRINT("error",("GetOverlappedResult() returned last error %d", + GetLastError())); + DBUG_RETURN(-1); + } + + DBUG_RETURN(length); +} + + +size_t vio_read_pipe(Vio * vio, uchar *buf, size_t size) +{ + DWORD bytes_read; DBUG_ENTER("vio_read_pipe"); DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %u", vio->sd, (long) buf, (uint) size)); - if (!ReadFile(vio->hPipe, buf, size, &length, NULL)) - DBUG_RETURN(-1); + if (!ReadFile(vio->hPipe, buf, (DWORD)size, &bytes_read, + &(vio->pipe_overlapped))) + { + if (GetLastError() != ERROR_IO_PENDING) + { + DBUG_PRINT("error",("ReadFile() returned last error %d", + GetLastError())); + DBUG_RETURN((size_t)-1); + } + bytes_read= pipe_complete_io(vio, buf, size,vio->read_timeout_millis); + } - DBUG_PRINT("exit", ("%d", length)); - DBUG_RETURN((size_t) length); + DBUG_PRINT("exit", ("%d", bytes_read)); + DBUG_RETURN(bytes_read); } size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size) { - DWORD length; + DWORD bytes_written; DBUG_ENTER("vio_write_pipe"); DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %u", vio->sd, (long) buf, (uint) size)); - if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL)) - DBUG_RETURN(-1); + if (!WriteFile(vio->hPipe, buf, (DWORD)size, &bytes_written, + &(vio->pipe_overlapped))) + { + if (GetLastError() != ERROR_IO_PENDING) + { + DBUG_PRINT("vio_error",("WriteFile() returned last error %d", + GetLastError())); + DBUG_RETURN((size_t)-1); + } + bytes_written = pipe_complete_io(vio, (char *)buf, size, + vio->write_timeout_millis); + } - DBUG_PRINT("exit", ("%d", length)); - DBUG_RETURN((size_t) length); + DBUG_PRINT("exit", ("%d", bytes_written)); + DBUG_RETURN(bytes_written); } + int vio_close_pipe(Vio * vio) { int r; DBUG_ENTER("vio_close_pipe"); -#if defined(__NT__) && defined(MYSQL_SERVER) - CancelIo(vio->hPipe); + + CloseHandle(vio->pipe_overlapped.hEvent); DisconnectNamedPipe(vio->hPipe); -#endif - r=CloseHandle(vio->hPipe); + r= CloseHandle(vio->hPipe); if (r) { DBUG_PRINT("vio_error", ("close() failed, error: %d",GetLastError())); @@ -466,10 +513,23 @@ int vio_close_pipe(Vio * vio) } -void vio_ignore_timeout(Vio *vio __attribute__((unused)), - uint which __attribute__((unused)), - uint timeout __attribute__((unused))) +void vio_win32_timeout(Vio *vio, uint which , uint timeout_sec) { + DWORD timeout_millis; + /* + Windows is measuring timeouts in milliseconds. Check for possible int + overflow. + */ + if (timeout_sec > UINT_MAX/1000) + timeout_millis= INFINITE; + else + timeout_millis= timeout_sec * 1000; + + /* which == 1 means "write", which == 0 means "read".*/ + if(which) + vio->write_timeout_millis= timeout_millis; + else + vio->read_timeout_millis= timeout_millis; } @@ -504,7 +564,7 @@ size_t vio_read_shared_memory(Vio * vio, uchar* buf, size_t size) WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail. We can't read anything */ if (WaitForMultipleObjects(array_elements(events), events, FALSE, - vio->net->read_timeout*1000) != WAIT_OBJECT_0) + vio->read_timeout_millis) != WAIT_OBJECT_0) { DBUG_RETURN(-1); }; @@ -561,7 +621,7 @@ size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size) while (remain != 0) { if (WaitForMultipleObjects(array_elements(events), events, FALSE, - vio->net->write_timeout*1000) != WAIT_OBJECT_0) + vio->write_timeout_millis) != WAIT_OBJECT_0) { DBUG_RETURN((size_t) -1); } diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 6a6e08818c6..51d049b18b9 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -144,55 +144,6 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file, } -static int -vio_verify_callback(int ok, X509_STORE_CTX *ctx) -{ - char buf[256]; - X509 *err_cert; - - DBUG_ENTER("vio_verify_callback"); - DBUG_PRINT("enter", ("ok: %d ctx: 0x%lx", ok, (long) ctx)); - - err_cert= X509_STORE_CTX_get_current_cert(ctx); - X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); - DBUG_PRINT("info", ("cert: %s", buf)); - if (!ok) - { - int err, depth; - err= X509_STORE_CTX_get_error(ctx); - depth= X509_STORE_CTX_get_error_depth(ctx); - - DBUG_PRINT("error",("verify error: %d '%s'",err, - X509_verify_cert_error_string(err))); - /* - Approve cert if depth is greater then "verify_depth", currently - verify_depth is always 0 and there is no way to increase it. - */ - if (verify_depth >= depth) - ok= 1; - } - switch (ctx->error) - { - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256); - DBUG_PRINT("info",("issuer= %s\n", buf)); - break; - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - DBUG_PRINT("error", ("notBefore")); - /*ASN1_TIME_print_fp(stderr,X509_get_notBefore(ctx->current_cert));*/ - break; - case X509_V_ERR_CERT_HAS_EXPIRED: - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - DBUG_PRINT("error", ("notAfter error")); - /*ASN1_TIME_print_fp(stderr,X509_get_notAfter(ctx->current_cert));*/ - break; - } - DBUG_PRINT("exit", ("%d", ok)); - DBUG_RETURN(ok); -} - - #ifdef __NETWARE__ /* NetWare SSL cleanup */ @@ -354,11 +305,7 @@ new_VioSSLConnectorFd(const char *key_file, const char *cert_file, /* Init the VioSSLFd as a "connector" ie. the client side */ - /* - The verify_callback function is used to control the behaviour - when the SSL_VERIFY_PEER flag is set. - */ - SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback); + SSL_CTX_set_verify(ssl_fd->ssl_context, verify, NULL); return ssl_fd; } @@ -382,11 +329,7 @@ new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, /* Set max number of cached sessions, returns the previous size */ SSL_CTX_sess_set_cache_size(ssl_fd->ssl_context, 128); - /* - The verify_callback function is used to control the behaviour - when the SSL_VERIFY_PEER flag is set. - */ - SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback); + SSL_CTX_set_verify(ssl_fd->ssl_context, verify, NULL); /* Set session_id - an identifier for this server session