From 72139ac31563d0b3229cf8a91a399fdda632a78c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Apr 2005 15:30:17 +0200 Subject: [PATCH 01/63] Adding --show-warnings option for the mysql command line tool so warnings, if any, are shown after execution of a statement in both batch and interactive mode. In interactive mode \w means show the warnings and \W means don't show the warnings. client/client_priv.h: Adding OPT_SHOW_WARNINGS for the --show-warnings switch for the mysql command line tool. client/mysql.cc: Adding --show-warnings option so warnings, if any, are shown after execution of a statement in both batch and interactive mode. In interactive mode \w means show the warnings and \W means don't show the warnings. BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + client/client_priv.h | 1 + client/mysql.cc | 82 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 9fecb756be0..f54b7bf8a3b 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -52,6 +52,7 @@ ejonore@mc03.ndb.mysql.com gbichot@production.mysql.com gbichot@quadita2.mysql.com gbichot@quadxeon.mysql.com +geert@kriem.kemuri.org georg@beethoven.local georg@beethoven.site georg@lmy002.wdf.sap.corp diff --git a/client/client_priv.h b/client/client_priv.h index 95f4d105156..892a9185ffa 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -50,4 +50,5 @@ enum options_client ,OPT_NDBCLUSTER,OPT_NDB_CONNECTSTRING #endif ,OPT_IGNORE_TABLE + ,OPT_SHOW_WARNINGS }; diff --git a/client/mysql.cc b/client/mysql.cc index 8d5117a29e0..869194e75b6 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -135,7 +135,8 @@ static my_bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0, opt_xml=0,opt_nopager=1, opt_outfile=0, named_cmds= 0, tty_password= 0, opt_nobeep=0, opt_reconnect=1, default_charset_used= 0, opt_secure_auth= 0, - default_pager_set= 0, opt_sigint_ignore= 0; + default_pager_set= 0, opt_sigint_ignore= 0, + show_warnings = 0; static ulong opt_max_allowed_packet, opt_net_buffer_length; static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0; static my_string opt_mysql_unix_port=0; @@ -194,7 +195,8 @@ static int com_quit(String *str,char*), com_use(String *str,char*), com_source(String *str, char*), com_rehash(String *str, char*), com_tee(String *str, char*), com_notee(String *str, char*), - com_prompt(String *str, char*), com_delimiter(String *str, char*); + com_prompt(String *str, char*), com_delimiter(String *str, char*), + com_warnings(String *str, char*), com_nowarnings(String *str, char*); #ifdef USE_POPEN static int com_nopager(String *str, char*), com_pager(String *str, char*), @@ -266,6 +268,10 @@ static COMMANDS commands[] = { "Set outfile [to_outfile]. Append everything into given outfile." }, { "use", 'u', com_use, 1, "Use another database. Takes database name as argument." }, + { "warnings", 'w', com_warnings, 0, + "Show warnings after every statement." }, + { "nowarning", 'W', com_nowarnings, 0, + "Don't show warnings after every statement." }, /* Get bash-like expansion for some commands */ { "create table", 0, 0, 0, ""}, { "create database", 0, 0, 0, ""}, @@ -323,6 +329,7 @@ static void print_table_data_html(MYSQL_RES *result); static void print_table_data_xml(MYSQL_RES *result); static void print_tab_data(MYSQL_RES *result); static void print_table_data_vertically(MYSQL_RES *result); +static void print_warnings(void); static ulong start_timer(void); static void end_timer(ulong start_time,char *buff); static void mysql_end_timer(ulong start_time,char *buff); @@ -693,6 +700,9 @@ static struct my_option my_long_options[] = {"secure-auth", OPT_SECURE_AUTH, "Refuse client connecting to server if it" " uses old (pre-4.1.1) protocol", (gptr*) &opt_secure_auth, (gptr*) &opt_secure_auth, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.", + (gptr*) &show_warnings, (gptr*) &show_warnings, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -790,6 +800,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; } break; + case OPT_SHOW_WARNINGS: + show_warnings = 1; + break; case 'A': rehash= 0; break; @@ -1938,6 +1951,13 @@ com_go(String *buffer,char *line __attribute__((unused))) if (err >= 1) error= put_error(&mysql); + if( show_warnings == 1 && warnings ) /* Show warnings if any */ + { + init_pager(); + print_warnings(); + end_pager(); + } + if (!error && !status.batch && (mysql.server_status & SERVER_STATUS_DB_DROPPED)) get_current_db(); @@ -2195,6 +2215,49 @@ print_table_data_vertically(MYSQL_RES *result) } } +/* print_warnings should be called right after executing a statement */ +static void +print_warnings() +{ + MYSQL_RES *result; + MYSQL_ROW cur; + MYSQL_FIELD *field; + + char *query = 0; + + /* Get the warnings */ + query = my_strdup("show warnings",MYF(MY_WME)); + mysql_real_query_for_lazy(query,strlen(query)); + mysql_store_result_for_lazy(&result); + my_free(query,MYF(MY_WME)); + + /* Bail out when no warnings */ + my_ulonglong num_rows = mysql_num_rows(result); + if( num_rows == 0 ) + { + mysql_free_result(result); + return; + } + + /* Print the warnings */ + while ((cur= mysql_fetch_row(result))) + { + mysql_field_seek(result, 0); + /* Format as: : */ + for (uint off= 0; off < mysql_num_fields(result); off++) + { + const char *str= cur[off] ? cur[off] : "NULL"; + field = mysql_fetch_field(result); + tee_fputs(str, PAGER); + tee_fputs(" ", PAGER); + if( off == 1 ) + (void) tee_fputs(": ", PAGER); + } + (void) tee_fputs("\n", PAGER); + } + tee_fputs("\n", PAGER); + mysql_free_result(result); +} static const char *array_value(const char **array, char key) @@ -2691,6 +2754,21 @@ com_use(String *buffer __attribute__((unused)), char *line) return 0; } +static int +com_warnings(String *buffer __attribute__((unused)), + char *line __attribute__((unused))) +{ + show_warnings = 1; + return 0; +} + +static int +com_nowarnings(String *buffer __attribute__((unused)), + char *line __attribute__((unused))) +{ + show_warnings = 0; + return 0; +} /* Gets argument from a command on the command line. If get_next_arg is From 93da32acbb05cfb18e6062494825af0807dd8be0 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Apr 2005 16:54:50 +0200 Subject: [PATCH 02/63] Removing for-loop in print_warnings() --- client/mysql.cc | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 869194e75b6..9a07be07911 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2243,19 +2243,8 @@ print_warnings() while ((cur= mysql_fetch_row(result))) { mysql_field_seek(result, 0); - /* Format as: : */ - for (uint off= 0; off < mysql_num_fields(result); off++) - { - const char *str= cur[off] ? cur[off] : "NULL"; - field = mysql_fetch_field(result); - tee_fputs(str, PAGER); - tee_fputs(" ", PAGER); - if( off == 1 ) - (void) tee_fputs(": ", PAGER); - } - (void) tee_fputs("\n", PAGER); + tee_fprintf(PAGER, "%s (Code %s): %s\n", cur[0], cur[1], cur[2]); } - tee_fputs("\n", PAGER); mysql_free_result(result); } From 76164b89d13331a01d5e5d03b09d3ecaf1a405c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 9 Apr 2005 14:28:39 +0400 Subject: [PATCH 03/63] WL#2246 "IM: Add ability to change instance options, add server logs handling" ported to the current version of the IM server-tools/instance-manager/commands.cc: Log and set options commands added server-tools/instance-manager/commands.h: Log and set options commands added server-tools/instance-manager/factory.cc: Log and set options factory entries added server-tools/instance-manager/factory.h: prototypes added server-tools/instance-manager/instance_options.cc: fill_log_options() added server-tools/instance-manager/instance_options.h: log processing options and funcctions added server-tools/instance-manager/messages.cc: new error messages added (log and option processing-related) server-tools/instance-manager/mysql_connection.cc: minor fixes server-tools/instance-manager/mysql_manager_error.h: new error codes added server-tools/instance-manager/parse.cc: parser fixed to recognize new commands. function to parse command-line options added server-tools/instance-manager/parse.h: header fixed in line with .cc changes server-tools/instance-manager/parse_output.cc: cleanup server-tools/instance-manager/parse_output.h: header guards added server-tools/instance-manager/protocol.cc: Protocol support extended to provide messages in ok packet server-tools/instance-manager/protocol.h: protocol support extended: ok packet could contain messages --- server-tools/instance-manager/commands.cc | 494 +++++++++++++++++- server-tools/instance-manager/commands.h | 86 +++ server-tools/instance-manager/factory.cc | 45 ++ server-tools/instance-manager/factory.h | 20 +- .../instance-manager/instance_options.cc | 135 ++++- .../instance-manager/instance_options.h | 8 +- server-tools/instance-manager/messages.cc | 9 + .../instance-manager/mysql_connection.cc | 4 +- .../instance-manager/mysql_manager_error.h | 4 + server-tools/instance-manager/parse.cc | 209 +++++++- server-tools/instance-manager/parse.h | 20 +- server-tools/instance-manager/parse_output.cc | 3 +- server-tools/instance-manager/parse_output.h | 3 + server-tools/instance-manager/protocol.cc | 55 +- server-tools/instance-manager/protocol.h | 6 +- 15 files changed, 1053 insertions(+), 48 deletions(-) diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc index 426f0cc40b2..ad8dcff524a 100644 --- a/server-tools/instance-manager/commands.cc +++ b/server-tools/instance-manager/commands.cc @@ -27,6 +27,19 @@ #include +/* some useful functions */ + +static int put_to_buff(Buffer *buff, const char *str, uint *position) +{ + uint len= strlen(str); + if (buff->append(*position, str, len)) + return 1; + + *position+= len; + return 0; +} + + /* implementation for Show_instances: */ @@ -106,7 +119,7 @@ int Flush_instances::execute(struct st_net *net, ulong connection_id) if (instance_map->flush_instances()) return ER_OUT_OF_RESOURCES; - net_send_ok(net, connection_id); + net_send_ok(net, connection_id, NULL); return 0; } @@ -119,7 +132,7 @@ Show_instance_status::Show_instance_status(Instance_map *instance_map_arg, { Instance *instance; - /* we make a search here, since we don't want t store the name */ + /* we make a search here, since we don't want to store the name */ if ((instance= instance_map->find(name, len))) { instance_name= instance->options.instance_name; @@ -225,7 +238,7 @@ Show_instance_options::Show_instance_options(Instance_map *instance_map_arg, { Instance *instance; - /* we make a search here, since we don't want t store the name */ + /* we make a search here, since we don't want to store the name */ if ((instance= instance_map->find(name, len))) { instance_name= instance->options.instance_name; @@ -294,13 +307,17 @@ int Show_instance_options::do_command(struct st_net *net, char *tmp_option, *option_value; get_dynamic(&(instance->options.options_array), (gptr) &tmp_option, i); option_value= strchr(tmp_option, '='); - /* split the option string into two parts */ - *option_value= 0; + /* split the option string into two parts if it has a value */ position= 0; - store_to_string(&send_buff, tmp_option + 2, &position); - store_to_string(&send_buff, option_value + 1, &position); - /* join name and the value into the same option again */ - *option_value= '='; + if (option_value != NULL) + { + *option_value= 0; + store_to_string(&send_buff, tmp_option + 2, &position); + store_to_string(&send_buff, option_value + 1, &position); + /* join name and the value into the same option again */ + *option_value= '='; + } + else store_to_string(&send_buff, tmp_option + 2, &position); if (send_buff.is_error() || my_net_write(net, send_buff.buffer, (uint) position)) goto err; @@ -338,7 +355,7 @@ Start_instance::Start_instance(Instance_map *instance_map_arg, const char *name, uint len) :Command(instance_map_arg) { - /* we make a search here, since we don't want t store the name */ + /* we make a search here, since we don't want to store the name */ if ((instance= instance_map->find(name, len))) instance_name= instance->options.instance_name; } @@ -359,19 +376,470 @@ int Start_instance::execute(struct st_net *net, ulong connection_id) if (!(instance->options.nonguarded)) instance_map->guardian->guard(instance); - net_send_ok(net, connection_id); + net_send_ok(net, connection_id, "Instance started"); return 0; } } +/* implementation for Show_instance_log: */ + +Show_instance_log::Show_instance_log(Instance_map *instance_map_arg, + const char *name, uint len, + Log_type log_type_arg, + const char *size_arg, + const char *offset_arg) + :Command(instance_map_arg) +{ + Instance *instance; + + if (offset_arg != NULL) + offset= atoi(offset_arg); + else + offset= 0; + size= atoi(size_arg); + log_type= log_type_arg; + + /* we make a search here, since we don't want to store the name */ + if ((instance= instance_map->find(name, len))) + { + instance_name= instance->options.instance_name; + } + else + instance_name= NULL; +} + + +int Show_instance_log::do_command(struct st_net *net, + const char *instance_name) +{ + enum { MAX_VERSION_LENGTH= 40 }; + Buffer send_buff; /* buffer for packets */ + LIST name; + LIST *field_list; + NAME_WITH_LENGTH name_field; + uint position=0; + + /* create list of the fileds to be passed to send_fields */ + name_field.name= (char *) "Log"; + name_field.length= 20; + name.data= &name_field; + field_list= list_add(NULL, &name); + + /* cannot read negative number of bytes */ + if (offset > size) + return ER_SYNTAX_ERROR; + + send_fields(net, field_list); + + { + Instance *instance; + const char *logpath; + File fd; + + if ((instance= instance_map->find(instance_name, strlen(instance_name))) == NULL) + goto err; + + switch (log_type) + { + case LOG_ERROR: + logpath= instance->options.error_log; + break; + case LOG_GENERAL: + logpath= instance->options.query_log; + break; + case LOG_SLOW: + logpath= instance->options.slow_log; + break; + default: + logpath= NULL; + } + + /* Instance has no such log */ + if (logpath == NULL) + { + return ER_NO_SUCH_LOG; + } + else if (*logpath == '\0') + { + return ER_GUESS_LOGFILE; + } + + + if ((fd= open(logpath, O_RDONLY))) + { + size_t buff_size; + int read_len; + /* calculate buffer size */ + struct stat file_stat; + + if(fstat(fd, &file_stat)) + goto err; + + buff_size= (size - offset); + + /* read in one chunk */ + read_len= my_seek(fd, file_stat.st_size - size, MY_SEEK_SET, MYF(0)); + + char *bf= (char *) malloc(sizeof(char)*buff_size); + read_len= my_read(fd, bf, buff_size, MYF(0)); + store_to_string(&send_buff, (char *) bf, &position, read_len); + close(fd); + } + else + { + return ER_OPEN_LOGFILE; + } + + if (my_net_write(net, send_buff.buffer, (uint) position)) + goto err; + } + + send_eof(net); + net_flush(net); + + return 0; + +err: + return ER_OUT_OF_RESOURCES; +} + + +int Show_instance_log::execute(struct st_net *net, ulong connection_id) +{ + if (instance_name != NULL) + { + return do_command(net, instance_name); + } + else + { + return ER_BAD_INSTANCE_NAME; + } +} + + + +/* implementation for Show_instance_log_files: */ + +Show_instance_log_files::Show_instance_log_files + (Instance_map *instance_map_arg, const char *name, uint len) + :Command(instance_map_arg) +{ + Instance *instance; + + /* we make a search here, since we don't want to store the name */ + if ((instance= instance_map->find(name, len))) + { + instance_name= instance->options.instance_name; + } + else + instance_name= NULL; +} + + +/* + The method sends a table with a the list of the log files + used by the instance. + + SYNOPSYS + Show_instance_log_files::do_command() + net The network connection to the client. + instance_name The name of the instance. + + RETURN + 0 - ok + 1 - error occured +*/ + + +int Show_instance_log_files::do_command(struct st_net *net, + const char *instance_name) +{ + enum { MAX_VERSION_LENGTH= 40 }; + Buffer send_buff; /* buffer for packets */ + LIST name, path, size; + LIST *field_list; + NAME_WITH_LENGTH name_field, path_field, size_field; + uint position=0; + + /* create list of the fileds to be passed to send_fields */ + name_field.name= (char *) "Logfile"; + name_field.length= 20; + name.data= &name_field; + path_field.name= (char *) "Path"; + path_field.length= 20; + path.data= &path_field; + size_field.name= (char *) "Filesize"; + size_field.length= 20; + size.data= &size_field; + field_list= list_add(NULL, &size); + field_list= list_add(field_list, &path); + field_list= list_add(field_list, &name); + + send_fields(net, field_list); + + Instance *instance; + + if ((instance= instance_map-> + find(instance_name, strlen(instance_name))) == NULL) + goto err; + { + /* + We have alike structure in instance_options.cc. We use such to be able + to loop througt the options, which we need to handle in some common way. + */ + struct log_files_st + { + const char *name; + const char *value; + } logs[]= + { + {"ERROR LOG", instance->options.error_log}, + {"GENERAL LOG", instance->options.query_log}, + {"SLOW LOG", instance->options.slow_log}, + {NULL, NULL} + }; + struct log_files_st *log_files; + + + instance->options.print_argv(); + for (log_files= logs; log_files->name; log_files++) + { + if (log_files->value != NULL) + { + struct stat file_stat; + char buff[20]; + + position= 0; + /* store the type of the log in the send buffer */ + store_to_string(&send_buff, log_files->name, &position); + switch (stat(log_files->value, &file_stat)) { + case 0: + if (S_ISREG(file_stat.st_mode)) + { + store_to_string(&send_buff, + (char *) log_files->value, + &position); + int10_to_str(file_stat.st_size, buff, 10); + store_to_string(&send_buff, (char *) buff, &position); + break; + } + default: + store_to_string(&send_buff, + "", + &position); + store_to_string(&send_buff, (char *) "0", &position); + } + if (my_net_write(net, send_buff.buffer, (uint) position)) + goto err; + } + } + } + + send_eof(net); + net_flush(net); + + return 0; + +err: + return 1; +} +int Show_instance_log_files::execute(struct st_net *net, ulong connection_id) +{ + if (instance_name != NULL) + { + if (do_command(net, instance_name)) + return ER_OUT_OF_RESOURCES; + return 0; + } + else + { + return ER_BAD_INSTANCE_NAME; + } +} + + +/* implementation for SET nstance_name.option=option_value: */ + +Set_option::Set_option(Instance_map *instance_map_arg, + const char *name, uint len, + const char *option_arg, uint option_len_arg, + const char *option_value_arg, uint option_value_len_arg) + :Command(instance_map_arg) +{ + Instance *instance; + + /* we make a search here, since we don't want to store the name */ + if ((instance= instance_map->find(name, len))) + { + instance_name= instance->options.instance_name; + /* add prefix for add_option */ + if ((option_len_arg < MAX_OPTION_LEN - 1) || + (option_value_len_arg < MAX_OPTION_LEN - 1)) + { + strncpy(option, option_arg, option_len_arg); + option[option_len_arg]= 0; + strncpy(option_value, option_value_arg, option_value_len_arg); + option_value[option_value_len_arg]= 0; + } + else + { + option[0]= 0; + option_value[0]= 0; + } + instance_name_len= len; + } + else + { + instance_name= NULL; + instance_name_len= 0; + } +} + + +/* + Correct the file. skip option could be used in future if we don't want to + let user change the options file (E.g. he lacks permissions to do that) +*/ +int Set_option::correct_file(bool skip) +{ + FILE *cnf_file; + const char *default_location="/etc/my.cnf"; + char linebuff[4096], *ptr; + uint optlen; + Buffer file_buffer; + uint position= 0; + bool isfound= false; + + optlen= strlen(option); + + if (!(cnf_file= my_fopen(default_location, O_RDONLY, MYF(0)))) + goto err_fopen; + + while (fgets(linebuff, sizeof(linebuff), cnf_file)) + { + /* if the section is found traverse it */ + if (isfound) + { + /* skip the old value of the option we are changing */ + if (strncmp(linebuff, option, optlen)) + { + /* copy all other lines line */ + put_to_buff(&file_buffer, linebuff, &position); + } + } + else + put_to_buff(&file_buffer, linebuff, &position); + + /* looking for appropriate instance section */ + for (ptr= linebuff ; my_isspace(&my_charset_latin1,*ptr) ; ptr++); + if (*ptr == '[') + { + /* copy the line to the buffer */ + if (!strncmp(++ptr, instance_name, instance_name_len)) + { + isfound= true; + /* add option */ + if (!skip) + { + put_to_buff(&file_buffer, option, &position); + if (option_value[0] != 0) + { + put_to_buff(&file_buffer, "=", &position); + put_to_buff(&file_buffer, option_value, &position); + } + /* add a newline */ + put_to_buff(&file_buffer, "\n", &position); + } + } + else + isfound= false; /* mark that this section is of no interest to us */ + } + + } + + if (my_fclose(cnf_file, MYF(0))) + goto err; + + /* we must hold an instance_map mutex while changing config file */ + instance_map->lock(); + + if (!(cnf_file= my_fopen(default_location, O_WRONLY|O_TRUNC, MYF(0)))) + goto err; + if (my_fwrite(cnf_file, file_buffer.buffer, position, MYF(MY_NABP))) + goto err; + + if (my_fclose(cnf_file, MYF(0))) + goto err; + + instance_map->unlock(); + + return 0; + +err: + my_fclose(cnf_file, MYF(0)); + return ER_OUT_OF_RESOURCES; +err_fopen: + return ER_ACCESS_OPTION_FILE; +} + + +/* + The method sets an option in the the default config file (/etc/my.cnf). + + SYNOPSYS + Set_option::do_command() + net The network connection to the client. + + RETURN + 0 - ok + 1 - error occured +*/ + + +int Set_option::do_command(struct st_net *net) +{ + return correct_file(false); +} + + +int Set_option::execute(struct st_net *net, ulong connection_id) +{ + if (instance_name != NULL) + { + int val; + + val= do_command(net); + if (val == 0) + { + net_send_ok(net, connection_id, NULL); + return 0; + } + + return val; + } + else + { + return ER_BAD_INSTANCE_NAME; + } +} + + +/* the only function from Unset_option we need to Implement */ + +int Unset_option::do_command(struct st_net *net) +{ + return correct_file(true); +} + + /* Implementation for Stop_instance: */ Stop_instance::Stop_instance(Instance_map *instance_map_arg, const char *name, uint len) :Command(instance_map_arg) { - /* we make a search here, since we don't want t store the name */ + /* we make a search here, since we don't want to store the name */ if ((instance= instance_map->find(name, len))) instance_name= instance->options.instance_name; } @@ -392,7 +860,7 @@ int Stop_instance::execute(struct st_net *net, ulong connection_id) stop_guard(instance); if ((err_code= instance->stop())) return err_code; - net_send_ok(net, connection_id); + net_send_ok(net, connection_id, NULL); return 0; } } diff --git a/server-tools/instance-manager/commands.h b/server-tools/instance-manager/commands.h index bab67f9c6b4..46cd0893759 100644 --- a/server-tools/instance-manager/commands.h +++ b/server-tools/instance-manager/commands.h @@ -18,6 +18,7 @@ #include "command.h" #include "instance.h" +#include "parse.h" /* Print all instances of this instance manager. @@ -115,6 +116,45 @@ public: }; +/* + Print requested part of the log + Grammar: + SHOW log {ERROR | SLOW | GENERAL} size[, offset_from_end] +*/ + +class Show_instance_log : public Command +{ +public: + + Show_instance_log(Instance_map *instance_map_arg, const char *name, + uint len, Log_type log_type_arg, const char *size_arg, + const char *offset_arg); + int do_command(struct st_net *net, const char *instance_name); + int execute(struct st_net *net, ulong connection_id); + Log_type log_type; + const char *instance_name; + uint size; + uint offset; +}; + + +/* + Shows the list of the log files, used by an instance. + Grammar: SHOW LOG FILES +*/ + +class Show_instance_log_files : public Command +{ +public: + + Show_instance_log_files(Instance_map *instance_map_arg, const char *name, uint len); + int do_command(struct st_net *net, const char *instance_name); + int execute(struct st_net *net, ulong connection_id); + const char *instance_name; + const char *option; +}; + + /* Syntax error command. This command is issued if parser reported a syntax error. We need it to distinguish the parse error and the situation when parser internal @@ -128,4 +168,50 @@ public: int execute(struct st_net *net, ulong connection_id); }; +/* + Set an option for the instance. + Grammar: SET instance_name.option=option_value +*/ + +class Set_option : public Command +{ +public: + Set_option(Instance_map *instance_map_arg, const char *name, uint len, + const char *option_arg, uint option_len, + const char *option_value_arg, uint option_value_len); + /* + the following function is virtual to let Unset_option to use + */ + virtual int do_command(struct st_net *net); + int execute(struct st_net *net, ulong connection_id); +protected: + int correct_file(bool skip); +public: + const char *instance_name; + uint instance_name_len; + /* buffer for the option */ + enum { MAX_OPTION_LEN= 1024 }; + char option[MAX_OPTION_LEN]; + char option_value[MAX_OPTION_LEN]; +}; + + +/* + Remove option of the instance from config file + Grammar: UNSET instance_name.option +*/ + +class Unset_option: public Set_option +{ +public: + Unset_option(Instance_map *instance_map_arg, const char *name, uint len, + const char *option_arg, uint option_len, + const char *option_value_arg, uint option_value_len): + Set_option(instance_map_arg, name, len, option_arg, option_len, + option_value_arg, option_value_len) + {} + int do_command(struct st_net *net); +}; + + #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_COMMANDS_H */ diff --git a/server-tools/instance-manager/factory.cc b/server-tools/instance-manager/factory.cc index 538d9353983..58ac32a9feb 100644 --- a/server-tools/instance-manager/factory.cc +++ b/server-tools/instance-manager/factory.cc @@ -16,40 +16,85 @@ #include "factory.h" + Show_instances *Command_factory::new_Show_instances() { return new Show_instances(&instance_map); } + Flush_instances *Command_factory::new_Flush_instances() { return new Flush_instances(&instance_map); } + Show_instance_status *Command_factory:: new_Show_instance_status(const char *name, uint len) { return new Show_instance_status(&instance_map, name, len); } + Show_instance_options *Command_factory:: new_Show_instance_options(const char *name, uint len) { return new Show_instance_options(&instance_map, name, len); } + Start_instance *Command_factory:: new_Start_instance(const char *name, uint len) { return new Start_instance(&instance_map, name, len); } + Stop_instance *Command_factory::new_Stop_instance(const char *name, uint len) { return new Stop_instance(&instance_map, name, len); } + Syntax_error *Command_factory::new_Syntax_error() { return new Syntax_error(); } + + +Set_option *Command_factory:: + new_Set_option(const char* name, uint len, + const char *option_arg, uint option_len, + const char *option_value_arg, uint option_value_len) +{ + return new Set_option(&instance_map, name, len, option_arg, + option_len, option_value_arg, option_value_len); +} + + +Unset_option *Command_factory:: + new_Unset_option(const char* name, uint len, + const char *option_arg, uint option_len, + const char *option_value_arg, uint option_value_len) +{ + return new Unset_option(&instance_map, name, len, option_arg, + option_len, option_value_arg, option_value_len); +} + + +Show_instance_log *Command_factory:: + new_Show_instance_log(const char *name, uint len, + Log_type log_type_arg, + const char *size, const char *offset) +{ + return new Show_instance_log(&instance_map, name, len, + log_type_arg, size, offset); +} + + +Show_instance_log_files *Command_factory:: + new_Show_instance_log_files(const char *name, uint len) +{ + return new Show_instance_log_files(&instance_map, name, len); +} + diff --git a/server-tools/instance-manager/factory.h b/server-tools/instance-manager/factory.h index 0a1b955d156..14073eb5007 100644 --- a/server-tools/instance-manager/factory.h +++ b/server-tools/instance-manager/factory.h @@ -26,6 +26,8 @@ Http_command_factory e.t.c. Also see comment in the instance_map.cc */ +class Show_instances; + class Command_factory { public: @@ -33,12 +35,26 @@ public: {} Show_instances *new_Show_instances (); + Flush_instances *new_Flush_instances (); + Syntax_error *new_Syntax_error (); Show_instance_status *new_Show_instance_status (const char *name, uint len); Show_instance_options *new_Show_instance_options (const char *name, uint len); Start_instance *new_Start_instance (const char *name, uint len); Stop_instance *new_Stop_instance (const char *name, uint len); - Flush_instances *new_Flush_instances (); - Syntax_error *new_Syntax_error (); + Show_instance_log *new_Show_instance_log (const char *name, uint len, + Log_type log_type_arg, + const char *size, + const char *offset); + Set_option *new_Set_option (const char *name, uint len, + const char *option_arg, uint option_len, + const char *option_value_arg, + uint option_value_len); + Unset_option *new_Unset_option (const char *name, uint len, + const char *option_arg, uint option_len, + const char *option_value_arg, + uint option_value_len); + Show_instance_log_files *new_Show_instance_log_files (const char *name, + uint len); Instance_map &instance_map; }; diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index 0d602f88ad2..ce7d43db74a 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -21,10 +21,10 @@ #include "instance_options.h" #include "parse_output.h" +#include "parse.h" #include "buffer.h" #include -#include #include #include @@ -54,7 +54,7 @@ int Instance_options::get_default_option(char *result, size_t result_len, int rc= 1; char verbose_option[]= " --no-defaults --verbose --help"; - Buffer cmd(strlen(mysqld_path)+sizeof(verbose_option)+1); + Buffer cmd(strlen(mysqld_path) + sizeof(verbose_option) + 1); if (cmd.get_size()) /* malloc succeeded */ { cmd.append(position, mysqld_path, strlen(mysqld_path)); @@ -76,6 +76,135 @@ err: } +int Instance_options::fill_log_options() +{ + /* array for the log option for mysqld */ + enum { MAX_LOG_OPTIONS= 8 }; + enum { MAX_LOG_OPTION_LENGTH= 256 }; + /* the last option must be '\0', so we reserve space for it */ + char log_options[MAX_LOG_OPTIONS + 1][MAX_LOG_OPTION_LENGTH]; + Buffer buff; + uint position= 0; + char **tmp_argv= argv; + char datadir[MAX_LOG_OPTION_LENGTH]; + char hostname[MAX_LOG_OPTION_LENGTH]; + uint hostname_length; + struct log_files_st + { + const char *name; + uint length; + const char **value; + const char *default_suffix; + } logs[]= + { + {"--log-error", 11, &error_log, ".err"}, + {"--log", 5, &query_log, ".log"}, + {"--log-slow-queries", 18, &slow_log, "-slow.log"}, + {NULL, 0, NULL, NULL} + }; + struct log_files_st *log_files; + + /* clean the buffer before usage */ + bzero(log_options, sizeof(log_options)); + + /* create a "mysqld " command in the buffer */ + buff.append(position, mysqld_path, strlen(mysqld_path)); + position= strlen(mysqld_path); + + /* skip the first option */ + tmp_argv++; + + while (*tmp_argv != 0) + { + buff.append(position, " ", 1); + position++; + buff.append(position, *tmp_argv, strlen(*tmp_argv)); + position+= strlen(*tmp_argv); + tmp_argv++; + } + + buff.append(position, "\0", 1); + position++; + + /* get options and parse them */ + if (parse_arguments(buff.buffer, "--log", (char *) log_options, + MAX_LOG_OPTIONS + 1, MAX_LOG_OPTION_LENGTH)) + goto err; + /* compute hostname and datadir for the instance */ + if (mysqld_datadir == NULL) + { + if (get_default_option(datadir, + MAX_LOG_OPTION_LENGTH, "--datadir")) + goto err; + } + else /* below is safe, as --datadir always has a value */ + strncpy(datadir, strchr(mysqld_datadir, '=') + 1, + MAX_LOG_OPTION_LENGTH); + + if (gethostname(hostname,sizeof(hostname)-1) < 0) + strmov(hostname, "mysql"); + + hostname[MAX_LOG_OPTION_LENGTH - 1]= 0; /* Safety */ + hostname_length= strlen(hostname); + + + for (log_files= logs; log_files->name; log_files++) + { + for (int i=0; (i < MAX_LOG_OPTIONS) && (log_options[i][0] != '\0'); i++) + { + if (!strncmp(log_options[i], log_files->name, log_files->length)) + { + /* + This is really log_files->name option if and only if it is followed + by '=', '\0' or space character. This way we can distinguish such + options as '--log' and '--log-bin'. This is checked in the following + two statements. + */ + if (log_options[i][log_files->length] == '\0' || + my_isspace(default_charset_info, log_options[i][log_files->length])) + { + char full_name[MAX_LOG_OPTION_LENGTH]; + + fn_format(full_name, hostname, datadir, "", + MY_UNPACK_FILENAME | MY_SAFE_PATH); + + + if ((MAX_LOG_OPTION_LENGTH - strlen(full_name)) > + strlen(log_files->default_suffix)) + { + strcpy(full_name + strlen(full_name), + log_files->default_suffix); + } + else + goto err; + + *(log_files->value)= strdup_root(&alloc, datadir); + } + + if (log_options[i][log_files->length] == '=') + { + char full_name[MAX_LOG_OPTION_LENGTH]; + + fn_format(full_name, log_options[i] +log_files->length + 1, + datadir, "", MY_UNPACK_FILENAME | MY_SAFE_PATH); + + if (!(*(log_files->value)= + strdup_root(&alloc, full_name))) + goto err; + } + + } + } + } + + return 0; + +err: + return 1; + +} + + int Instance_options::get_pid_filename(char *result) { const char *pid_file= mysqld_pid_file; @@ -190,6 +319,8 @@ int Instance_options::complete_initialization(const char *default_path, options_array.elements*sizeof(char*)); argv[filled_default_options + options_array.elements]= 0; + fill_log_options(); + return 0; err: diff --git a/server-tools/instance-manager/instance_options.h b/server-tools/instance-manager/instance_options.h index 06ad0156bc0..4def59b75a2 100644 --- a/server-tools/instance-manager/instance_options.h +++ b/server-tools/instance-manager/instance_options.h @@ -40,7 +40,8 @@ public: mysqld_socket(0), mysqld_datadir(0), mysqld_bind_address(0), mysqld_pid_file(0), mysqld_port(0), mysqld_port_val(0), mysqld_path(0), nonguarded(0), shutdown_delay(0), - shutdown_delay_val(0), filled_default_options(0) + shutdown_delay_val(0), error_log(0), query_log(0), slow_log(0), + filled_default_options(0) {} ~Instance_options(); /* fills in argv */ @@ -76,9 +77,14 @@ public: const char *nonguarded; const char *shutdown_delay; uint shutdown_delay_val; + const char *error_log; + const char *query_log; + const char *slow_log; + /* this value is computed and cashed here */ DYNAMIC_ARRAY options_array; private: + int fill_log_options(); int add_to_argv(const char *option); int get_default_option(char *result, size_t result_len, const char *option_name); diff --git a/server-tools/instance-manager/messages.cc b/server-tools/instance-manager/messages.cc index d044c0f65db..69bc8507c2e 100644 --- a/server-tools/instance-manager/messages.cc +++ b/server-tools/instance-manager/messages.cc @@ -57,6 +57,15 @@ static const char *mysqld_error_message(unsigned sql_errno) " or resources shortage"; case ER_STOP_INSTANCE: return "Cannot stop instance"; + case ER_NO_SUCH_LOG: + return "The instance has no such log enabled"; + case ER_OPEN_LOGFILE: + return "Cannot open log file"; + case ER_GUESS_LOGFILE: + return "Cannot guess the log filename. Try specifying full log name" + "in the instance options"; + case ER_ACCESS_OPTION_FILE: + return "Cannot open the option file to edit. Check permissions"; default: DBUG_ASSERT(0); return 0; diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc index 215dbe51b58..036d0887d18 100644 --- a/server-tools/instance-manager/mysql_connection.cc +++ b/server-tools/instance-manager/mysql_connection.cc @@ -284,7 +284,7 @@ int Mysql_connection_thread::check_connection() net_send_error(&net, ER_ACCESS_DENIED_ERROR); return 1; } - net_send_ok(&net, connection_id); + net_send_ok(&net, connection_id, NULL); return 0; } @@ -332,7 +332,7 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command, return 1; case COM_PING: log_info("query for connection %d received ping command", connection_id); - net_send_ok(&net, connection_id); + net_send_ok(&net, connection_id, NULL); break; case COM_QUERY: { diff --git a/server-tools/instance-manager/mysql_manager_error.h b/server-tools/instance-manager/mysql_manager_error.h index 2862e01649d..afb9affe621 100644 --- a/server-tools/instance-manager/mysql_manager_error.h +++ b/server-tools/instance-manager/mysql_manager_error.h @@ -23,5 +23,9 @@ #define ER_INSTANCE_ALREADY_STARTED 3002 #define ER_CANNOT_START_INSTANCE 3003 #define ER_STOP_INSTANCE 3004 +#define ER_NO_SUCH_LOG 3005 +#define ER_OPEN_LOGFILE 3006 +#define ER_GUESS_LOGFILE 3007 +#define ER_ACCESS_OPTION_FILE 3008 #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_MANAGER_ERROR_H */ diff --git a/server-tools/instance-manager/parse.cc b/server-tools/instance-manager/parse.cc index d3fb10b7c94..8af7c88ece2 100644 --- a/server-tools/instance-manager/parse.cc +++ b/server-tools/instance-manager/parse.cc @@ -15,38 +15,56 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "parse.h" +#include "factory.h" #include + enum Token { - TOK_FLUSH = 0, + TOK_ERROR= 0, /* Encodes the "ERROR" word, it doesn't indicate error. */ + TOK_FILES, + TOK_FLUSH, + TOK_GENERAL, TOK_INSTANCE, TOK_INSTANCES, + TOK_LOG, TOK_OPTIONS, + TOK_SET, + TOK_SLOW, TOK_START, TOK_STATUS, TOK_STOP, TOK_SHOW, + TOK_UNSET, TOK_NOT_FOUND, // must be after all tokens TOK_END }; + struct tokens_st { uint length; const char *tok_name; }; + static struct tokens_st tokens[]= { + {5, "ERROR"}, + {5, "FILES"}, {5, "FLUSH"}, + {7, "GENERAL"}, {8, "INSTANCE"}, {9, "INSTANCES"}, + {3, "LOG"}, {7, "OPTIONS"}, + {3, "SET"}, + {4, "SLOW"}, {5, "START"}, {6, "STATUS"}, {4, "STOP"}, - {4, "SHOW"} + {4, "SHOW"}, + {5, "UNSET"} }; @@ -86,13 +104,6 @@ Token shift_token(const char **text, uint *word_len) } -void print_token(const char *token, uint tok_len) -{ - for (uint i= 0; i < tok_len; ++i) - printf("%c", token[i]); -} - - int get_text_id(const char **text, uint *word_len, const char **id) { get_word(text, word_len); @@ -108,7 +119,15 @@ Command *parse_command(Command_factory *factory, const char *text) uint word_len; const char *instance_name; uint instance_name_len; + const char *option; + uint option_len; + const char *option_value; + uint option_value_len; + const char *log_size; Command *command; + const char *saved_text= text; + bool skip= false; + const char *tmp; Token tok1= shift_token(&text, &word_len); @@ -143,6 +162,55 @@ Command *parse_command(Command_factory *factory, const char *text) command= factory->new_Flush_instances(); break; + case TOK_UNSET: + skip= true; + case TOK_SET: + + get_text_id(&text, &instance_name_len, &instance_name); + text+= instance_name_len; + + /* the next token should be a dot */ + get_word(&text, &word_len); + if (*text != '.') + goto syntax_error; + text++; + + get_word(&text, &option_len, NONSPACE); + option= text; + if ((tmp= strchr(text, '=')) != NULL) + option_len= tmp - text; + text+= option_len; + + get_word(&text, &word_len); + if (*text == '=') + { + text++; /* skip '=' */ + get_word(&text, &option_value_len, NONSPACE); + option_value= text; + text+= option_value_len; + } + else + { + option_value= ""; + option_value_len= 0; + } + + /* should be empty */ + get_word(&text, &word_len); + if (word_len) + { + goto syntax_error; + } + + if (skip) + command= factory->new_Unset_option(instance_name, instance_name_len, + option, option_len, option_value, + option_value_len); + else + command= factory->new_Set_option(instance_name, instance_name_len, + option, option_len, option_value, + option_value_len); + break; case TOK_SHOW: switch (shift_token(&text, &word_len)) { case TOK_INSTANCES: @@ -157,6 +225,7 @@ Command *parse_command(Command_factory *factory, const char *text) case TOK_STATUS: get_text_id(&text, &instance_name_len, &instance_name); text+= instance_name_len; + /* check that this is the end of the command */ get_word(&text, &word_len); if (word_len) goto syntax_error; @@ -172,7 +241,87 @@ Command *parse_command(Command_factory *factory, const char *text) } break; default: - goto syntax_error; + instance_name= text - word_len; + instance_name_len= word_len; + if (instance_name_len) + { + Log_type log_type; + switch (shift_token(&text, &word_len)) { + case TOK_LOG: + switch (Token tok3= shift_token(&text, &word_len)) { + case TOK_FILES: + get_word(&text, &word_len); + /* check that this is the end of the command */ + if (word_len) + goto syntax_error; + command= (Command *) + factory->new_Show_instance_log_files(instance_name, + instance_name_len); + break; + case TOK_ERROR: + case TOK_GENERAL: + case TOK_SLOW: + /* define a log type */ + switch (tok3) { + case TOK_ERROR: + log_type= LOG_ERROR; + break; + case TOK_GENERAL: + log_type= LOG_GENERAL; + break; + case TOK_SLOW: + log_type= LOG_SLOW; + break; + default: + goto syntax_error; + } + /* get the size of the log we want to retrieve */ + get_text_id(&text, &word_len, &log_size); + text+= word_len; + /* this parameter is required */ + if (!word_len) + goto syntax_error; + /* the next token should be comma, or nothing */ + get_word(&text, &word_len); + switch (*text) { + case ',': + text++; /* swallow the comma */ + /* read the next word */ + get_word(&text, &word_len); + if (!word_len) + goto syntax_error; + command= (Command *) + factory->new_Show_instance_log(instance_name, + instance_name_len, + log_type, + log_size, + text); + + //get_text_id(&text, &log_size_len, &log_size); + break; + case '\0': + command= (Command *) + factory->new_Show_instance_log(instance_name, + instance_name_len, + log_type, + log_size, + NULL); + break; /* this is ok */ + default: + goto syntax_error; + } + break; + default: + goto syntax_error; + } + break; + default: + goto syntax_error; + } + } + else + goto syntax_error; + break; } break; default: @@ -182,3 +331,43 @@ syntax_error: return command; } +/* additional parse function, needed to parse */ + +/* create an array of strings from the output, starting from "word" */ +int parse_arguments(const char *command, const char *word, char *result, + int max_result_cardinality, size_t option_len) +{ + int wordlen; + int i= 0; /* result array index */ + /* should be enough to store the string from the output */ + enum { MAX_LINE_LEN= 4096 }; + char linebuf[MAX_LINE_LEN]; + + wordlen= strlen(word); + + uint lineword_len= 0; + const char *linep= command; + get_word((const char **) &linep, &lineword_len, NONSPACE); + while ((*linep != '\0') && (i < max_result_cardinality)) + { + if (!strncmp(word, linep, wordlen)) + { + strncpy(result + i*option_len, linep, lineword_len); + *(result + i*option_len + lineword_len)= '\0'; + linep+= lineword_len; + i++; + } + else + linep+= lineword_len; + get_word((const char **) &linep, &lineword_len, NONSPACE); + + /* stop if we've filled the array */ + if (i >= max_result_cardinality) + break; + } + + + return 0; +} + + diff --git a/server-tools/instance-manager/parse.h b/server-tools/instance-manager/parse.h index 92519893302..f03ef4c8a00 100644 --- a/server-tools/instance-manager/parse.h +++ b/server-tools/instance-manager/parse.h @@ -16,10 +16,24 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "factory.h" +#include +#include + +class Command; +class Command_factory; + +enum Log_type +{ + LOG_ERROR= 0, + LOG_GENERAL, + LOG_SLOW +}; Command *parse_command(Command_factory *factory, const char *text); +int parse_arguments(const char *command, const char *word, char *result, + int max_result_cardinality, size_t option_len); + /* define kinds of the word seek method */ enum { ALPHANUM= 1, NONSPACE }; @@ -44,10 +58,12 @@ inline void get_word(const char **text, uint *word_len, while (my_isalnum(default_charset_info, *word_end)) ++word_end; else - while (!my_isspace(default_charset_info, *word_end)) + while (!my_isspace(default_charset_info, *word_end) && + (*word_end != '\0')) ++word_end; *word_len= word_end - *text; } + #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_H */ diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc index 77fa40ca352..d6adb8079ce 100644 --- a/server-tools/instance-manager/parse_output.cc +++ b/server-tools/instance-manager/parse_output.cc @@ -47,7 +47,7 @@ int parse_output_and_get_value(const char *command, const char *word, { FILE *output; uint wordlen; - /* should be enought to store the string from the output */ + /* should be enough to store the string from the output */ enum { MAX_LINE_LEN= 512 }; char linebuf[MAX_LINE_LEN]; @@ -99,3 +99,4 @@ pclose: err: return 1; } + diff --git a/server-tools/instance-manager/parse_output.h b/server-tools/instance-manager/parse_output.h index 20503a74629..48fd2ae4068 100644 --- a/server-tools/instance-manager/parse_output.h +++ b/server-tools/instance-manager/parse_output.h @@ -1,3 +1,5 @@ +#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H +#define INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H /* Copyright (C) 2004 MySQL AB This program is free software; you can redistribute it and/or modify @@ -17,3 +19,4 @@ int parse_output_and_get_value(const char *command, const char *word, char *result, size_t result_len); +#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H */ diff --git a/server-tools/instance-manager/protocol.cc b/server-tools/instance-manager/protocol.cc index 9c8975a78be..f0928743716 100644 --- a/server-tools/instance-manager/protocol.cc +++ b/server-tools/instance-manager/protocol.cc @@ -24,15 +24,25 @@ static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */ -int net_send_ok(struct st_net *net, unsigned long connection_id) -{ - char buff[1 + // packet type code - 9 + // affected rows count - 9 + // connection id - 2 + // thread return status - 2]; // warning count - char *pos= buff; +int net_send_ok(struct st_net *net, unsigned long connection_id, + const char *message) +{ + /* + The format of a packet + 1 packet type code + 1-9 affected rows count + 1-9 connection id + 2 thread return status + 2 warning count + 1-9 + message length message to send (isn't stored if no message) + */ + Buffer buff; + char *pos= buff.buffer; + + /* check that we have space to hold mandatory fields */ + buff.reserve(0, 23); + enum { OK_PACKET_CODE= 0 }; *pos++= OK_PACKET_CODE; pos= net_store_length(pos, (ulonglong) 0); @@ -43,7 +53,15 @@ int net_send_ok(struct st_net *net, unsigned long connection_id) int2store(pos, 0); pos+= 2; - return my_net_write(net, buff, pos - buff) || net_flush(net); + uint position= pos - buff.buffer; /* we might need it for message */ + + if (message != NULL) + { + buff.reserve(position, 9 + strlen(message)); + store_to_string(&buff, message, &position); + } + + return my_net_write(net, buff.buffer, position) || net_flush(net); } @@ -99,15 +117,15 @@ char *net_store_length(char *pkg, uint length) } -int store_to_string(Buffer *buf, const char *string, uint *position) +int store_to_string(Buffer *buf, const char *string, uint *position, + uint string_len) { uint currpos; - uint string_len; - string_len= strlen(string); - if (buf->reserve(*position, 2)) + if (buf->reserve(*position, 9)) goto err; - currpos= (net_store_length(buf->buffer + *position, string_len) - buf->buffer); + currpos= (net_store_length(buf->buffer + *position, + (ulonglong) string_len) - buf->buffer); if (buf->append(currpos, string, string_len)) goto err; *position= *position + string_len + (currpos - *position); @@ -118,6 +136,15 @@ err: } +int store_to_string(Buffer *buf, const char *string, uint *position) +{ + uint string_len; + + string_len= strlen(string); + return store_to_string(buf, string, position, string_len); +} + + int send_eof(struct st_net *net) { char buff[1 + /* eof packet code */ diff --git a/server-tools/instance-manager/protocol.h b/server-tools/instance-manager/protocol.h index b7b18b4b76c..c853fa10483 100644 --- a/server-tools/instance-manager/protocol.h +++ b/server-tools/instance-manager/protocol.h @@ -27,7 +27,8 @@ typedef struct field { struct st_net; -int net_send_ok(struct st_net *net, unsigned long connection_id); +int net_send_ok(struct st_net *net, unsigned long connection_id, + const char *message); int net_send_error(struct st_net *net, unsigned sql_errno); @@ -39,6 +40,9 @@ char *net_store_length(char *pkg, uint length); int store_to_string(Buffer *buf, const char *string, uint *position); +int store_to_string(Buffer *buf, const char *string, uint *position, + uint string_len); + int send_eof(struct st_net *net); #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PROTOCOL_H */ From c3995c256addd77ecd58be19237c156324a15ae8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Apr 2005 15:07:08 +0200 Subject: [PATCH 04/63] \W enables show warnings, \w disables; Showing message while interactive when using the \w and \W commands; using strmov instead of my_strdup; removed case for options, my_getopt does it --- client/mysql.cc | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 9a07be07911..5a595652606 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -268,9 +268,9 @@ static COMMANDS commands[] = { "Set outfile [to_outfile]. Append everything into given outfile." }, { "use", 'u', com_use, 1, "Use another database. Takes database name as argument." }, - { "warnings", 'w', com_warnings, 0, + { "warnings", 'W', com_warnings, 0, "Show warnings after every statement." }, - { "nowarning", 'W', com_nowarnings, 0, + { "nowarning", 'w', com_nowarnings, 0, "Don't show warnings after every statement." }, /* Get bash-like expansion for some commands */ { "create table", 0, 0, 0, ""}, @@ -800,9 +800,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; } break; - case OPT_SHOW_WARNINGS: - show_warnings = 1; - break; case 'A': rehash= 0; break; @@ -1951,7 +1948,7 @@ com_go(String *buffer,char *line __attribute__((unused))) if (err >= 1) error= put_error(&mysql); - if( show_warnings == 1 && warnings ) /* Show warnings if any */ + if (show_warnings == 1 && warnings >= 1) /* Show warnings if any */ { init_pager(); print_warnings(); @@ -2219,17 +2216,15 @@ print_table_data_vertically(MYSQL_RES *result) static void print_warnings() { + char query[30]; MYSQL_RES *result; MYSQL_ROW cur; MYSQL_FIELD *field; - char *query = 0; - /* Get the warnings */ - query = my_strdup("show warnings",MYF(MY_WME)); + strmov(query,"show warnings"); mysql_real_query_for_lazy(query,strlen(query)); mysql_store_result_for_lazy(&result); - my_free(query,MYF(MY_WME)); /* Bail out when no warnings */ my_ulonglong num_rows = mysql_num_rows(result); @@ -2748,6 +2743,7 @@ com_warnings(String *buffer __attribute__((unused)), char *line __attribute__((unused))) { show_warnings = 1; + put_info("Show warnings enabled.",INFO_INFO); return 0; } @@ -2756,6 +2752,7 @@ com_nowarnings(String *buffer __attribute__((unused)), char *line __attribute__((unused))) { show_warnings = 0; + put_info("Show warnings disabled.",INFO_INFO); return 0; } From fea116cfb5b8f2a2d7982d98d2fa7351b1175702 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Apr 2005 09:51:37 +0200 Subject: [PATCH 05/63] Removing useless mysql_field_seek --- client/mysql.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 5a595652606..1faffb7046e 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2228,7 +2228,7 @@ print_warnings() /* Bail out when no warnings */ my_ulonglong num_rows = mysql_num_rows(result); - if( num_rows == 0 ) + if (num_rows == 0) { mysql_free_result(result); return; @@ -2237,7 +2237,6 @@ print_warnings() /* Print the warnings */ while ((cur= mysql_fetch_row(result))) { - mysql_field_seek(result, 0); tee_fprintf(PAGER, "%s (Code %s): %s\n", cur[0], cur[1], cur[2]); } mysql_free_result(result); From 4f102422f4c3baeb7f54979182dd390982afb6b1 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 6 May 2005 12:46:52 +0200 Subject: [PATCH 06/63] ndb - add support for mysql servers in autotest ndb/test/run-test/main.cpp: add support for mysql servers and clients to ndb test framework ndb/test/run-test/run-test.hpp: add support for mysql servers and clients to ndb test framework --- ndb/test/run-test/main.cpp | 41 ++++++++++++++++------------------ ndb/test/run-test/run-test.hpp | 1 + 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/ndb/test/run-test/main.cpp b/ndb/test/run-test/main.cpp index 02c2cc862a3..842f658f5b6 100644 --- a/ndb/test/run-test/main.cpp +++ b/ndb/test/run-test/main.cpp @@ -116,10 +116,7 @@ main(int argc, const char ** argv){ */ if(restart){ g_logger.info("(Re)starting ndb processes"); - if(!stop_processes(g_config, atrt_process::NDB_MGM)) - goto end; - - if(!stop_processes(g_config, atrt_process::NDB_DB)) + if(!stop_processes(g_config, ~0)) goto end; if(!start_processes(g_config, atrt_process::NDB_MGM)) @@ -142,6 +139,9 @@ main(int argc, const char ** argv){ goto end; started: + if(!start_processes(g_config, p_servers)) + goto end; + g_logger.info("Ndb start completed"); } @@ -158,9 +158,6 @@ main(int argc, const char ** argv){ if(!setup_test_case(g_config, test_case)) goto end; - if(!start_processes(g_config, p_servers)) - goto end; - if(!start_processes(g_config, p_clients)) goto end; @@ -201,9 +198,6 @@ main(int argc, const char ** argv){ if(!stop_processes(g_config, p_clients)) goto end; - if(!stop_processes(g_config, p_servers)) - goto end; - if(!gather_result(g_config, &result)) goto end; @@ -476,21 +470,18 @@ setup_config(atrt_config& config){ proc.m_proc.m_path.assign(dir).append("/libexec/mysqld"); proc.m_proc.m_args = "--core-file --ndbcluster"; proc.m_proc.m_cwd.appfmt("%d.mysqld", index); - if(mysql_port_offset > 0 || g_mysqld_use_base){ - // setup mysql specific stuff - const char * basedir = proc.m_proc.m_cwd.c_str(); - proc.m_proc.m_args.appfmt("--datadir=%s", basedir); - proc.m_proc.m_args.appfmt("--pid-file=%s/mysql.pid", basedir); - proc.m_proc.m_args.appfmt("--socket=%s/mysql.sock", basedir); - proc.m_proc.m_args.appfmt("--port=%d", - g_default_base_port-(++mysql_port_offset)); - } } else if(split1[0] == "api"){ proc.m_type = atrt_process::NDB_API; proc.m_proc.m_name.assfmt("%d-%s", index, "ndb_api"); proc.m_proc.m_path = ""; proc.m_proc.m_args = ""; proc.m_proc.m_cwd.appfmt("%d.ndb_api", index); + } else if(split1[0] == "mysql"){ + proc.m_type = atrt_process::MYSQL_CLIENT; + proc.m_proc.m_name.assfmt("%d-%s", index, "mysql"); + proc.m_proc.m_path = ""; + proc.m_proc.m_args = ""; + proc.m_proc.m_cwd.appfmt("%d.mysql", index); } else { g_logger.critical("%s:%d: Unhandled process type: %s", g_process_config_filename, lineno, @@ -913,6 +904,11 @@ read_test_case(FILE * file, atrt_testcase& tc, int& line){ tc.m_report= true; else tc.m_report= false; + + if(p.get("run-all", &mt) && strcmp(mt, "yes") == 0) + tc.m_run_all= true; + else + tc.m_run_all= false; return true; } @@ -928,16 +924,17 @@ setup_test_case(atrt_config& config, const atrt_testcase& tc){ size_t i = 0; for(; im_base_dir.c_str(), tc.m_command.c_str()); proc.m_proc.m_args.assign(tc.m_args); - break; + if(!tc.m_run_all) + break; } } for(i++; i Date: Sat, 7 May 2005 08:59:12 +0200 Subject: [PATCH 07/63] typo fixed --- sql/field.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/field.h b/sql/field.h index ac9c2f351b3..97e0d0fad99 100644 --- a/sql/field.h +++ b/sql/field.h @@ -198,7 +198,7 @@ public: virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, char *new_ptr, uchar *new_null_ptr, uint new_null_bit); - virtual void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg) + inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg) { ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg; } From 1392f4820aba16e2349a46962d8b7c7cddadd800 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 7 May 2005 15:48:56 +0500 Subject: [PATCH 08/63] BUG#7709 fix - Boolean fulltext query against unsupported engines does not fail. mysql-test/r/innodb.result: Test case for BUG#7709 - Boolean fulltext query against unsupported engines does not fail added. mysql-test/t/innodb.test: Test case for BUG#7709 - Boolean fulltext query against unsupported engines does not fail added. sql/item_func.cc: Check if table supports fulltext. BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + mysql-test/r/innodb.result | 3 +++ mysql-test/t/innodb.test | 9 +++++++++ sql/item_func.cc | 5 +++++ 4 files changed, 18 insertions(+) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 5a34dbbb1d8..7052d853b00 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -142,6 +142,7 @@ serg@sergbook.mylan serg@sergbook.mysql.com sergefp@mysql.com sinisa@rhols221.adsl.netsonic.fi +svoj@mysql.com tfr@beta.frontier86.ee tfr@indrek.tfr.cafe.ee tfr@sarvik.tfr.cafe.ee diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index f00679801f8..dbfe1c3aff5 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1272,3 +1272,6 @@ Cannot delete or update a parent row: a foreign key constraint fails delete from t1 where id=15; delete from t1 where id=0; drop table t1; +CREATE TABLE t1 ( a char(10) ) ENGINE=InnoDB; +SELECT a FROM t1 WHERE MATCH (a) AGAINST ('test' IN BOOLEAN MODE); +The used table type doesn't support FULLTEXT indexes diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 2c8002ea841..c25f295cac8 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -911,3 +911,12 @@ delete from t1 where id=15; delete from t1 where id=0; drop table t1; + +# +# BUG#7709 test case - Boolean fulltext query against unsupported +# engines does not fail +# + +CREATE TABLE t1 ( a char(10) ) ENGINE=InnoDB; +--error 1214; +SELECT a FROM t1 WHERE MATCH (a) AGAINST ('test' IN BOOLEAN MODE); diff --git a/sql/item_func.cc b/sql/item_func.cc index 334be48dc9a..855e86b2382 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2257,6 +2257,11 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist) key=NO_SUCH_KEY; const_item_cache=0; table=((Item_field *)fields.head())->field->table; + if (!(table->file->table_flags() & HA_CAN_FULLTEXT)) + { + my_error(ER_TABLE_CANT_HANDLE_FULLTEXT, MYF(0)); + return 1; + } table->fulltext_searched=1; record=table->record[0]; if (key == NO_SUCH_KEY && mode != FT_BOOL) From 6e13083d658faccd5aee83f32d1e0d9c45c87ebd Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 7 May 2005 15:11:31 +0200 Subject: [PATCH 09/63] errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/czech/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/danish/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/dutch/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/english/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/estonian/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/french/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/german/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/greek/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/hungarian/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/italian/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/japanese/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/korean/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/norwegian/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/norwegian-ny/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/polish/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/portuguese/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/romanian/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/russian/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/slovak/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/spanish/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/swedish/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). sql/share/ukrainian/errmsg.txt: Add newline at EOF for proper processing by comp-err.exe on Windows where fgets() works differently than Linux (Bug #6195). BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + sql/share/czech/errmsg.txt | 1 + sql/share/danish/errmsg.txt | 1 + sql/share/dutch/errmsg.txt | 1 + sql/share/english/errmsg.txt | 1 + sql/share/estonian/errmsg.txt | 1 + sql/share/french/errmsg.txt | 1 + sql/share/german/errmsg.txt | 1 + sql/share/greek/errmsg.txt | 1 + sql/share/hungarian/errmsg.txt | 1 + sql/share/italian/errmsg.txt | 1 + sql/share/japanese/errmsg.txt | 1 + sql/share/korean/errmsg.txt | 1 + sql/share/norwegian-ny/errmsg.txt | 1 + sql/share/norwegian/errmsg.txt | 1 + sql/share/polish/errmsg.txt | 1 + sql/share/portuguese/errmsg.txt | 1 + sql/share/romanian/errmsg.txt | 1 + sql/share/russian/errmsg.txt | 1 + sql/share/slovak/errmsg.txt | 1 + sql/share/spanish/errmsg.txt | 1 + sql/share/swedish/errmsg.txt | 1 + sql/share/ukrainian/errmsg.txt | 1 + 23 files changed, 23 insertions(+) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 967f8c7cb47..998f8234343 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -107,6 +107,7 @@ monty@work.mysql.com mwagner@cash.mwagner.org mwagner@evoq.mwagner.org mwagner@here.mwagner.org +mwagner@ultrafly.mysql.com mwagner@work.mysql.com mysqldev@build.mysql2.com nick@mysql.com diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 88ecaed386b..70aea3fdf62 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -265,3 +265,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 6210bf7788c..8c0bf688311 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -256,3 +256,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index c3607f4cd0f..c2baf0240af 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -265,3 +265,4 @@ "Kreeg fatale fout %d: '%-.128s' van master tijdens lezen van data uit binaire log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 7c9d789c86e..ed5977fd78c 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -255,3 +255,4 @@ "Variable '%-.64s' is a %s variable" ] # End of error messages # Do NOT add new error messages here as this makes merges to 4.1 too hard! + diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 8157a33836e..581baf24e09 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -258,3 +258,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 3c88ccc0378..9aa430aa718 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -253,3 +253,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 91f3f91a464..7fa896bcc34 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -257,3 +257,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index aff7f8ba3c2..2a2bee5d69a 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -253,3 +253,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 60dc3204bb4..f998116410f 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -258,3 +258,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index c51c69cf298..2ab360dff4e 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -253,3 +253,4 @@ "Errore fatale %d: '%-.128s' dal master leggendo i dati dal log binario", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index fb604923e4e..4ad7cc3ec37 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -257,3 +257,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 764cbb78740..3b027796c3b 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -253,3 +253,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 424530ecf87..5b994d2dc5b 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -255,3 +255,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 73314ea647b..305bf10899b 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -255,3 +255,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index f24a54ec8e8..8d6b2fa542e 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -258,3 +258,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 2810ac134b1..6fcc044c6b6 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -255,3 +255,4 @@ "Obteve fatal erro %d: '%-.128s' do master quando lendo dados do binary log", "Slave SQL thread ignorado a consulta devido às normas de replicação-*-tabela" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 552b532c0a2..c218f19e212 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -258,3 +258,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 668b310a5dc..4419da08051 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -258,3 +258,4 @@ "ðÏÌÕÞÅÎÁ ÎÅÉÓÐÒÁ×ÉÍÁÑ ÏÛÉÂËÁ %d: '%-.128s' ÏÔ ÇÏÌÏ×ÎÏÇÏ ÓÅÒ×ÅÒÁ × ÐÒÏÃÅÓÓÅ ×ÙÂÏÒËÉ ÄÁÎÎÙÈ ÉÚ Ä×ÏÉÞÎÏÇÏ ÖÕÒÎÁÌÁ", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 8467fad5b11..bb241673706 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -261,3 +261,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 4ab76a64ca7..2daeebc8eb8 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -256,3 +256,4 @@ "Recibió fatal error %d: '%-.128s' del master cuando leyendo datos del binary log", "Slave SQL thread ignorado el query debido a las reglas de replicación-*-tabla" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 352a226ef23..a9273f6222c 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -253,3 +253,4 @@ "Fick fatalt fel %d: '%-.128s' från master vid läsning av binärloggen" "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 131cf07a8e2..371dd16d737 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -259,3 +259,4 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Slave SQL thread ignored the query because of replicate-*-table rules" "Variable '%-.64s' is a %s variable" + From 686d0ba155c01b5ef792da6debd0e5471bff7366 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 7 May 2005 06:55:47 -0700 Subject: [PATCH 10/63] Add support for slave_compressed_protocol, slave_load_tmpdir, and slave_skip_errors in SHOW VARIABLES. (Bug #7800) sql/structs.h: Add SHOW_SLAVE_SKIP_ERRORS sql/set_var.cc: Add slave_compressed_protocol, slave_load_tmpdir, slave_skip_errors to list of variables. mysql-test/t/rpl_variables.test: Add test for additional slave-related variables mysql-test/r/rpl_variables.result: Update results sql/sql_show.cc: Handle showing slave_skip_errors --- mysql-test/r/rpl_variables.result | 9 +++++++++ mysql-test/t/rpl_variables-master.opt | 1 + mysql-test/t/rpl_variables.test | 8 ++++++++ sql/set_var.cc | 4 ++++ sql/sql_show.cc | 27 +++++++++++++++++++++++++++ sql/structs.h | 2 +- 6 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 mysql-test/t/rpl_variables-master.opt diff --git a/mysql-test/r/rpl_variables.result b/mysql-test/r/rpl_variables.result index 227d8ecfad9..b6da7f76a6d 100644 --- a/mysql-test/r/rpl_variables.result +++ b/mysql-test/r/rpl_variables.result @@ -6,3 +6,12 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; set global slave_net_timeout=100; set global sql_slave_skip_counter=100; +show variables like 'slave_compressed_protocol'; +Variable_name Value +slave_compressed_protocol OFF +show variables like 'slave_load_tmpdir'; +Variable_name Value +slave_load_tmpdir MYSQL_TEST_DIR/var/tmp/ +show variables like 'slave_skip_errors'; +Variable_name Value +slave_skip_errors 3,100,137,643,1752 diff --git a/mysql-test/t/rpl_variables-master.opt b/mysql-test/t/rpl_variables-master.opt new file mode 100644 index 00000000000..a668c6bfbe8 --- /dev/null +++ b/mysql-test/t/rpl_variables-master.opt @@ -0,0 +1 @@ +--slave-skip-errors=3,100,137,643,1752 diff --git a/mysql-test/t/rpl_variables.test b/mysql-test/t/rpl_variables.test index b332c006118..a4a6e69c845 100644 --- a/mysql-test/t/rpl_variables.test +++ b/mysql-test/t/rpl_variables.test @@ -2,3 +2,11 @@ source include/master-slave.inc; set global slave_net_timeout=100; set global sql_slave_skip_counter=100; + +# BUG #7800: Add various-slave related variables to SHOW VARIABLES +show variables like 'slave_compressed_protocol'; +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR +show variables like 'slave_load_tmpdir'; +# We just set some arbitrary values in variables-master.opt so we can test +# that a list of values works correctly +show variables like 'slave_skip_errors'; diff --git a/sql/set_var.cc b/sql/set_var.cc index 4add5d6b39b..146f64e3127 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -951,7 +951,11 @@ struct show_var_st init_vars[]= { {"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL}, {"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL}, #ifdef HAVE_REPLICATION + {sys_slave_compressed_protocol.name, + (char*) &sys_slave_compressed_protocol, SHOW_SYS}, + {"slave_load_tmpdir", (char*) &slave_load_tmpdir, SHOW_CHAR_PTR}, {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS}, + {"slave_skip_errors", (char*) &slave_error_mask, SHOW_SLAVE_SKIP_ERRORS}, {sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries, SHOW_SYS}, #endif {sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS}, diff --git a/sql/sql_show.cc b/sql/sql_show.cc index ceb98740298..93445bedf98 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1345,6 +1345,33 @@ static bool show_status_array(THD *thd, const char *wild, pthread_mutex_unlock(&LOCK_active_mi); break; } + case SHOW_SLAVE_SKIP_ERRORS: + { + MY_BITMAP *bitmap= (MY_BITMAP *)value; + if (!use_slave_mask || bitmap_is_clear_all(bitmap)) + { + end= strmov(buff, "OFF"); + } + else if (bitmap_is_set_all(bitmap)) + { + end= strmov(buff, "ALL"); + } + else + { + for (int i= 1; i < MAX_SLAVE_ERROR; i++) + { + if (bitmap_is_set(bitmap, i)) + { + end+= my_snprintf((char *)end, sizeof(buff) - (end - buff), + "%d,", i); + } + } + if (end != buff) + end--; // Remove last ',' + *(char *)end= 0; + } + break; + } #endif /* HAVE_REPLICATION */ case SHOW_OPENTABLES: end= int10_to_str((long) cached_tables(), buff, 10); diff --git a/sql/structs.h b/sql/structs.h index 7a70bfc0f4f..14c0100f5be 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -184,7 +184,7 @@ enum SHOW_TYPE #endif /* HAVE_OPENSSL */ SHOW_RPL_STATUS, SHOW_SLAVE_RUNNING, SHOW_SLAVE_RETRIED_TRANS, SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_CONST_LONG, - SHOW_LONG_STATUS, SHOW_LONG_CONST_STATUS + SHOW_LONG_STATUS, SHOW_LONG_CONST_STATUS, SHOW_SLAVE_SKIP_ERRORS }; enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED}; From 1d828bb8153cbf7579d9e531ce04a76dc7c2b77e Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 7 May 2005 16:06:41 +0200 Subject: [PATCH 11/63] ndb autotest - add show version to cpcd ndb/src/cw/cpcd/APIService.cpp: Add show version to cpcd (prints date) ndb/src/cw/cpcd/APIService.hpp: Add show version to cpcd (prints date) --- ndb/src/cw/cpcd/APIService.cpp | 15 +++++++++++++++ ndb/src/cw/cpcd/APIService.hpp | 1 + 2 files changed, 16 insertions(+) diff --git a/ndb/src/cw/cpcd/APIService.cpp b/ndb/src/cw/cpcd/APIService.cpp index b009f0c0fc4..e7a2092c15d 100644 --- a/ndb/src/cw/cpcd/APIService.cpp +++ b/ndb/src/cw/cpcd/APIService.cpp @@ -136,6 +136,8 @@ ParserRow commands[] = CPCD_ARG("id", Int, Mandatory, "Id of process"), CPCD_CMD("list processes", &CPCDAPISession::listProcesses, ""), + + CPCD_CMD("show version", &CPCDAPISession::showVersion, ""), CPCD_END() }; @@ -359,6 +361,7 @@ CPCDAPISession::listProcesses(Parser_t::Context & /* unused */, m_output->println("stdout: %s", p->m_stdout.c_str()); m_output->println("stderr: %s", p->m_stderr.c_str()); m_output->println("ulimit: %s", p->m_ulimit.c_str()); + m_output->println("shutdown: %s", p->m_shutdown_options.c_str()); switch(p->m_status){ case STOPPED: m_output->println("status: stopped"); @@ -384,4 +387,16 @@ CPCDAPISession::listProcesses(Parser_t::Context & /* unused */, m_cpcd.m_processes.unlock(); } +void +CPCDAPISession::showVersion(Parser_t::Context & /* unused */, + const class Properties & args){ + Uint32 id; + CPCD::RequestStatus rs; + + m_output->println("show version"); + m_output->println("compile time: %s %s", __DATE__, __TIME__); + + m_output->println(""); +} + template class Vector const*>; diff --git a/ndb/src/cw/cpcd/APIService.hpp b/ndb/src/cw/cpcd/APIService.hpp index ef988785f89..3586d64187e 100644 --- a/ndb/src/cw/cpcd/APIService.hpp +++ b/ndb/src/cw/cpcd/APIService.hpp @@ -49,6 +49,7 @@ public: void stopProcess(Parser_t::Context & ctx, const class Properties & args); void showProcess(Parser_t::Context & ctx, const class Properties & args); void listProcesses(Parser_t::Context & ctx, const class Properties & args); + void showVersion(Parser_t::Context & ctx, const class Properties & args); }; class CPCDAPIService : public SocketServer::Service { From 8001e398df6724052bf0b1957ff1d9578f6b00a5 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 7 May 2005 08:16:43 -0700 Subject: [PATCH 12/63] Eliminate gcc 4.0 warning in libedit code. (Bug #9603) cmd-line-utils/libedit/vi.c: Eliminate compiler warning --- cmd-line-utils/libedit/vi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd-line-utils/libedit/vi.c b/cmd-line-utils/libedit/vi.c index 4a0352859dd..b977ce716c6 100644 --- a/cmd-line-utils/libedit/vi.c +++ b/cmd-line-utils/libedit/vi.c @@ -1014,7 +1014,7 @@ vi_histedit(EditLine *el, int c) return CC_ERROR; case 0: close(fd); - execlp("vi", "vi", tempfile, 0); + execlp("vi", "vi", tempfile, (char *) NULL); exit(0); /*NOTREACHED*/ default: From f5f132fdde32f1798612c8d5b17a1fecf5f1c0fa Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 7 May 2005 21:37:27 +0500 Subject: [PATCH 13/63] Test fix. DROP TABLE added. --- mysql-test/r/innodb.result | 1 + mysql-test/t/innodb.test | 1 + 2 files changed, 2 insertions(+) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index dbfe1c3aff5..f634edcbe91 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1275,3 +1275,4 @@ drop table t1; CREATE TABLE t1 ( a char(10) ) ENGINE=InnoDB; SELECT a FROM t1 WHERE MATCH (a) AGAINST ('test' IN BOOLEAN MODE); The used table type doesn't support FULLTEXT indexes +DROP TABLE t1; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index c25f295cac8..96975d54810 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -920,3 +920,4 @@ drop table t1; CREATE TABLE t1 ( a char(10) ) ENGINE=InnoDB; --error 1214; SELECT a FROM t1 WHERE MATCH (a) AGAINST ('test' IN BOOLEAN MODE); +DROP TABLE t1; From 3e1dad411598662152dd5100c2fb88219a31634f Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 8 May 2005 21:03:50 +0100 Subject: [PATCH 14/63] Bug#6236 Incomplete ALTER TABLE breaks MERGE compatibility Fix implicit NOT NULL not set on ALTER of PK columns mysql-test/r/alter_table.result: Test for Bug#6236 mysql-test/t/alter_table.test: Test for Bug#6236 sql/sql_table.cc: Implicit NOT NULL not set on ALTER of PK columns BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + mysql-test/r/alter_table.result | 20 ++++++++++++++++++++ mysql-test/t/alter_table.test | 13 +++++++++++++ sql/sql_table.cc | 23 +++++++++++++++++------ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index bf0dfb9e31d..5a34dbbb1d8 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -9,6 +9,7 @@ acurtis@pcgem.rdg.cyberkinetica.com ahlentz@co3064164-a.rochd1.qld.optusnet.com.au akishkin@work.mysql.com antony@ltantony.dsl-verizon.net +antony@ltantony.mysql.com antony@ltantony.rdg.cyberkinetica.homeunix.net arjen@bitbike.com arjen@co3064164-a.bitbike.com diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 78925a64e93..80d3ef5e0a5 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -386,3 +386,23 @@ Incorrect table name 't1\\' rename table t1 to `t1\\`; Incorrect table name 't1\\' drop table t1; +drop table if exists t1, t2; +create table t1 ( a varchar(10) not null primary key ) engine=myisam; +create table t2 ( a varchar(10) not null primary key ) engine=merge union=(t1); +flush tables; +alter table t1 modify a varchar(10); +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` varchar(10) NOT NULL default '', + PRIMARY KEY (`a`) +) TYPE=MRG_MyISAM UNION=(t1) +flush tables; +alter table t1 modify a varchar(10) not null; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` varchar(10) NOT NULL default '', + PRIMARY KEY (`a`) +) TYPE=MRG_MyISAM UNION=(t1) +drop table if exists t1, t2; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 11290134a71..c69f9aabae6 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -254,3 +254,16 @@ alter table t1 rename to `t1\\`; rename table t1 to `t1\\`; drop table t1; +# +# BUG#6236 - ALTER TABLE MODIFY should set implicit NOT NULL on PK columns +# +drop table if exists t1, t2; +create table t1 ( a varchar(10) not null primary key ) engine=myisam; +create table t2 ( a varchar(10) not null primary key ) engine=merge union=(t1); +flush tables; +alter table t1 modify a varchar(10); +show create table t2; +flush tables; +alter table t1 modify a varchar(10) not null; +show create table t2; +drop table if exists t1, t2; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index cef480fadde..e065e5dfc58 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1795,6 +1795,11 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, } KEY_PART_INFO *key_part= key_info->key_part; + enum Key::Keytype key_type= key_info->flags & HA_NOSAME ? + (!my_strcasecmp(key_name, "PRIMARY") ? + Key::PRIMARY : Key::UNIQUE) : + (key_info->flags & HA_FULLTEXT ? + Key::FULLTEXT : Key::MULTIPLE); key_parts.empty(); for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) { @@ -1824,16 +1829,22 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, cfield->pack_length <= key_part_length)) key_part_length=0; // Use whole field } + if (!(cfield->flags & NOT_NULL_FLAG)) + { + if (key_type == Key::PRIMARY) + { + /* Implicitly set primary key fields to NOT NULL for ISO conf. */ + cfield->flags|= NOT_NULL_FLAG; + cfield->pack_flag&= ~FIELDFLAG_MAYBE_NULL; + } + else + key_info->flags|= HA_NULL_PART_KEY; + } key_parts.push_back(new key_part_spec(cfield->field_name, key_part_length)); } if (key_parts.elements) - key_list.push_back(new Key(key_info->flags & HA_NOSAME ? - (!my_strcasecmp(key_name, "PRIMARY") ? - Key::PRIMARY : Key::UNIQUE) : - (key_info->flags & HA_FULLTEXT ? - Key::FULLTEXT : Key::MULTIPLE), - key_name,key_parts)); + key_list.push_back(new Key(key_type,key_name,key_parts)); } key_it.rewind(); { From 3ac2df4e4c2366d4b30b3251590207a3d07f483d Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 8 May 2005 22:56:58 +0100 Subject: [PATCH 15/63] Bug#8191 - SELECT INTO OUTFILE insists on FROM clause Fix bug + include test case. Enable outfile tests. mysql-test/t/outfile.test: Reenable outfile tests Add test for Bug#8191 sql/sql_yacc.yy: Fix Bug#8191 BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + mysql-test/include/have_outfile.inc | 5 +++ mysql-test/include/test_outfile.inc | 1 + mysql-test/r/have_outfile.require | 3 ++ mysql-test/r/outfile.result | Bin 0 -> 953 bytes mysql-test/t/outfile.test | 60 +++++++++++++++++++--------- sql/sql_yacc.yy | 7 ++-- 7 files changed, 56 insertions(+), 21 deletions(-) create mode 100644 mysql-test/include/have_outfile.inc create mode 100644 mysql-test/include/test_outfile.inc create mode 100644 mysql-test/r/have_outfile.require create mode 100644 mysql-test/r/outfile.result diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index bf0dfb9e31d..5a34dbbb1d8 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -9,6 +9,7 @@ acurtis@pcgem.rdg.cyberkinetica.com ahlentz@co3064164-a.rochd1.qld.optusnet.com.au akishkin@work.mysql.com antony@ltantony.dsl-verizon.net +antony@ltantony.mysql.com antony@ltantony.rdg.cyberkinetica.homeunix.net arjen@bitbike.com arjen@co3064164-a.bitbike.com diff --git a/mysql-test/include/have_outfile.inc b/mysql-test/include/have_outfile.inc new file mode 100644 index 00000000000..31e95f4810a --- /dev/null +++ b/mysql-test/include/have_outfile.inc @@ -0,0 +1,5 @@ +-- require r/have_outfile.require +disable_query_log; +select load_file(concat(@tmpdir,"/outfile.test")); +--exec rm $MYSQL_TEST_DIR/var/tmp/outfile.test +enable_query_log; diff --git a/mysql-test/include/test_outfile.inc b/mysql-test/include/test_outfile.inc new file mode 100644 index 00000000000..0bede4938c6 --- /dev/null +++ b/mysql-test/include/test_outfile.inc @@ -0,0 +1 @@ +eval select "Outfile OK" into outfile "$MYSQL_TEST_DIR/var/tmp/outfile.test"; diff --git a/mysql-test/r/have_outfile.require b/mysql-test/r/have_outfile.require new file mode 100644 index 00000000000..9fc2f8fdb5a --- /dev/null +++ b/mysql-test/r/have_outfile.require @@ -0,0 +1,3 @@ +load_file(concat(@tmpdir,"/outfile.test")) +Outfile OK + diff --git a/mysql-test/r/outfile.result b/mysql-test/r/outfile.result new file mode 100644 index 0000000000000000000000000000000000000000..a2720be075aeb427d4f11212b77ba3a2ad254710 GIT binary patch literal 953 zcmcIj!A`?44CU;vuzFc1twiZ|0PVsFahP`FhQ!j=V-aan5_izQC#fcFz$p?tT7J*Z zezqHDdt_A^LcK@&(w;rCTtn?hF`ZH@G2f{jR>oHIHR#ThW7HknfW@OS1Nl5VkTDiN ztuswFU*y@-6t~Lx7;c|8o51yCsAe=)HLrVZD6ef-E6yLd?HlbDnXm)LM8V|wR%Y`+ zNset_name($1,(uint) ((char*) lex->tok_end - $1)); }; -opt_into: +into: INTO OUTFILE TEXT_STRING { THD *thd= current_thd; From a6b1546676ecb06a1e2d555ab8716d89bd359c31 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 May 2005 01:59:10 +0300 Subject: [PATCH 16/63] Item::fix_field need correct pointer on item reference to chnge it if itis need, so support of correct item address added to SP commands (BUG#5963) some optimisation of IF/NOT IF ptomised to Pem mysql-test/r/sp.result: test for bug#5963 mysql-test/t/sp.test: test for bug#5963 sql/item.cc: new method which return reference on Item for SP variables support sql/item.h: comment fixed method added sql/sp_head.cc: preparation of item made separate function we do not need new constant Item to check IF/IF NOT support of passing correct address of item for fix_fields method sql/sp_rcontext.cc: support of Item address passing to fix_fields sql/sp_rcontext.h: support of correct address passing to fix_fields sql/sql_class.cc: support of correct item address passing to fix_field --- mysql-test/r/sp.result | 25 +++++++++++++++++++ mysql-test/t/sp.test | 29 ++++++++++++++++++++++ sql/item.cc | 7 ++++++ sql/item.h | 14 +++++++++-- sql/sp_head.cc | 55 ++++++++++++++++++++++++++++++++---------- sql/sp_rcontext.cc | 6 ++--- sql/sp_rcontext.h | 10 +++++++- sql/sql_class.cc | 7 +++--- 8 files changed, 130 insertions(+), 23 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index a57bd7139e2..b1e91d429ff 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3057,4 +3057,29 @@ yes yes drop procedure bug7293| delete from t1| +drop procedure if exists bug5963| +create procedure bug5963_1 () begin declare v int; set v = (select s1 from t3); select v; end;| +create table t3 (s1 int)| +insert into t3 values (5)| +call bug5963_1()| +v +5 +call bug5963_1()| +v +5 +drop procedure bug5963_1| +drop table t3| +create procedure bug5963_2 (cfk_value int) +begin +if cfk_value in (select cpk from t3) then +set @x = 5; +end if; +end; +| +create table t3 (cpk int)| +insert into t3 values (1)| +call bug5963_2(1)| +call bug5963_2(1)| +drop procedure bug5963_2| +drop table t3| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 2e45d1c6cd1..fe7f09f2cf3 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -3741,6 +3741,35 @@ call bug7293 ('secrete')| drop procedure bug7293| delete from t1| +# +# BUG#5963 subqueries in SET/IF +# +--disable_warnings +drop procedure if exists bug5963| +--enable_warnings + +create procedure bug5963_1 () begin declare v int; set v = (select s1 from t3); select v; end;| +create table t3 (s1 int)| +insert into t3 values (5)| +call bug5963_1()| +call bug5963_1()| +drop procedure bug5963_1| +drop table t3| + +create procedure bug5963_2 (cfk_value int) +begin + if cfk_value in (select cpk from t3) then + set @x = 5; + end if; + end; +| +create table t3 (cpk int)| +insert into t3 values (1)| +call bug5963_2(1)| +call bug5963_2(1)| +drop procedure bug5963_2| +drop table t3| + # # BUG#NNNN: New bug synopsis # diff --git a/sql/item.cc b/sql/item.cc index f5c7f2d7c05..ec93480499e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -740,6 +740,13 @@ Item_splocal::this_item() return thd->spcont->get_item(m_offset); } + +Item ** +Item_splocal::this_item_addr(THD *thd, Item **addr) +{ + return thd->spcont->get_item_addr(m_offset); +} + Item * Item_splocal::this_const_item() const { diff --git a/sql/item.h b/sql/item.h index 697194e2878..ab8059b8fd1 100644 --- a/sql/item.h +++ b/sql/item.h @@ -525,8 +525,17 @@ public: virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual Item *set_no_const_sub(byte *arg) { return this; } virtual Item *replace_equal_field(byte * arg) { return this; } - - virtual Item *this_item() { return this; } /* For SPs mostly. */ + + /* + For SP local variable returns pointer to Item representing its + current value and pointer to current Item otherwise. + */ + virtual Item *this_item() { return this; } + /* + For SP local variable returns address of pointer to Item representing its + current value and pointer passed via parameter otherwise. + */ + virtual Item **this_item_addr(THD *thd, Item **addr) { return addr; } virtual Item *this_const_item() const { return const_cast(this); } /* For SPs mostly. */ // Row emulation @@ -573,6 +582,7 @@ public: bool is_splocal() { return 1; } /* Needed for error checking */ Item *this_item(); + Item **this_item_addr(THD *thd, Item **); Item *this_const_item() const; bool fix_fields(THD *, struct st_table_list *, Item **); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 9fb4b1c7fac..1b336278f07 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -97,19 +97,48 @@ sp_multi_results_command(enum enum_sql_command cmd) } } + +/* + Prepare Item for execution (call of fix_fields) + + SYNOPSIS + sp_prepare_func_item() + thd thread handler + it_addr pointer on item refernce + + RETURN + NULL error + prepared item +*/ + +static Item * +sp_prepare_func_item(THD* thd, Item **it_addr) +{ + Item *it= *it_addr; + DBUG_ENTER("sp_prepare_func_item"); + it_addr= it->this_item_addr(thd, it_addr); + + if (!it->fixed && (*it_addr)->fix_fields(thd, 0, it_addr)) + { + DBUG_PRINT("info", ("fix_fields() failed")); + DBUG_RETURN(NULL); + } + DBUG_RETURN(*it_addr); +} + + /* Evaluate a (presumed) func item. Always returns an item, the parameter ** if nothing else. */ Item * -sp_eval_func_item(THD *thd, Item *it, enum enum_field_types type) +sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type) { DBUG_ENTER("sp_eval_func_item"); - it= it->this_item(); + Item *it= sp_prepare_func_item(thd, it_addr); DBUG_PRINT("info", ("type: %d", type)); - if (!it->fixed && it->fix_fields(thd, 0, &it)) + if (!it) { - DBUG_PRINT("info", ("fix_fields() failed")); DBUG_RETURN(NULL); } @@ -678,7 +707,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) for (i= 0 ; i < params && i < argcount ; i++) { sp_pvar_t *pvar = m_pcont->find_pvar(i); - Item *it= sp_eval_func_item(thd, *argp++, pvar->type); + Item *it= sp_eval_func_item(thd, argp++, pvar->type); if (it) nctx->push_item(it); @@ -760,7 +789,7 @@ sp_head::execute_procedure(THD *thd, List *args) { Item_null *nit= NULL; // Re-use this, and only create if needed uint i; - List_iterator_fast li(*args); + List_iterator li(*args); Item *it; nctx= new sp_rcontext(csize, hmax, cmax); @@ -793,7 +822,7 @@ sp_head::execute_procedure(THD *thd, List *args) } else { - Item *it2= sp_eval_func_item(thd, it, pvar->type); + Item *it2= sp_eval_func_item(thd, li.ref(), pvar->type); if (it2) nctx->push_item(it2); // IN or INOUT @@ -1438,7 +1467,7 @@ sp_instr_set::exec_core(THD *thd, uint *nextp) Item *it; int res; - it= sp_eval_func_item(thd, m_value, m_type); + it= sp_eval_func_item(thd, &m_value, m_type); if (! it) res= -1; else @@ -1568,13 +1597,13 @@ sp_instr_jump_if::exec_core(THD *thd, uint *nextp) Item *it; int res; - it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY); + it= sp_prepare_func_item(thd, &m_expr); if (!it) res= -1; else { res= 0; - if (it->val_int()) + if (it->val_bool()) *nextp = m_dest; else *nextp = m_ip+1; @@ -1626,13 +1655,13 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp) Item *it; int res; - it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY); + it= sp_prepare_func_item(thd, &m_expr); if (! it) res= -1; else { res= 0; - if (! it->val_int()) + if (! it->val_bool()) *nextp = m_dest; else *nextp = m_ip+1; @@ -1684,7 +1713,7 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp) Item *it; int res; - it= sp_eval_func_item(thd, m_value, m_type); + it= sp_eval_func_item(thd, &m_value, m_type); if (! it) res= -1; else diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index def38009eee..672491a97f2 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -41,10 +41,10 @@ sp_rcontext::sp_rcontext(uint fsize, uint hmax, uint cmax) } int -sp_rcontext::set_item_eval(uint idx, Item *i, enum_field_types type) +sp_rcontext::set_item_eval(uint idx, Item **item_addr, enum_field_types type) { - extern Item *sp_eval_func_item(THD *thd, Item *it, enum_field_types type); - Item *it= sp_eval_func_item(current_thd, i, type); + extern Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type); + Item *it= sp_eval_func_item(current_thd, item_addr, type); if (! it) return -1; diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index afcd937a369..c132032e32c 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -74,7 +74,7 @@ class sp_rcontext : public Sql_alloc /* Returns 0 on success, -1 on (eval) failure */ int - set_item_eval(uint idx, Item *i, enum_field_types type); + set_item_eval(uint idx, Item **i, enum_field_types type); inline Item * get_item(uint idx) @@ -82,6 +82,14 @@ class sp_rcontext : public Sql_alloc return m_frame[idx]; } + + inline Item ** + get_item_addr(uint idx) + { + return m_frame + idx; + } + + inline void set_result(Item *it) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a6a1f4d60ef..2d5c4722164 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1719,10 +1719,9 @@ bool select_dumpvar::send_data(List &items) List_iterator_fast li(vars); List_iterator_fast var_li(local_vars); List_iterator_fast my_li(var_list); - List_iterator_fast it(items); + List_iterator it(items); Item_func_set_user_var *xx; Item_splocal *yy; - Item *item; my_var *zz; DBUG_ENTER("send_data"); if (unit->offset_limit_cnt) @@ -1741,13 +1740,13 @@ bool select_dumpvar::send_data(List &items) my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0)); DBUG_RETURN(1); } - while ((zz=my_li++) && (item=it++)) + while ((zz=my_li++) && (it++)) { if (zz->local) { if ((yy=var_li++)) { - if (thd->spcont->set_item_eval(yy->get_offset(), item, zz->type)) + if (thd->spcont->set_item_eval(yy->get_offset(), it.ref(), zz->type)) DBUG_RETURN(1); } } From adefe15c9f623bd4dab7ed99ec1dc6ff9a24bb61 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 May 2005 08:33:45 +0100 Subject: [PATCH 17/63] Fix outfile test/results --- mysql-test/r/outfile.result | Bin 953 -> 683 bytes mysql-test/t/outfile.test | 17 +++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/outfile.result b/mysql-test/r/outfile.result index a2720be075aeb427d4f11212b77ba3a2ad254710..a7871592241104fe2a949c98379cfa21dcbe5d68 100644 GIT binary patch delta 14 WcmdnVzM6Hz0mg}i`jh`M?EwHS^#)-8 literal 953 zcmcIj!A`?44CU;vuzFc1twiZ|0PVsFahP`FhQ!j=V-aan5_izQC#fcFz$p?tT7J*Z zezqHDdt_A^LcK@&(w;rCTtn?hF`ZH@G2f{jR>oHIHR#ThW7HknfW@OS1Nl5VkTDiN ztuswFU*y@-6t~Lx7;c|8o51yCsAe=)HLrVZD6ef-E6yLd?HlbDnXm)LM8V|wR%Y`+ zN Date: Tue, 10 May 2005 14:13:58 +0500 Subject: [PATCH 18/63] bug#10344: some string function fail for UCS2 substr fix --- mysql-test/r/ctype_ucs.result | 18 ++++++++++++++++++ mysql-test/t/ctype_ucs.test | 10 ++++++++++ strings/ctype-ucs2.c | 2 +- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 3face9b1ba6..5902dd247ce 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -598,6 +598,24 @@ ucs2_bin 00610009 ucs2_bin 0061 ucs2_bin 00610020 drop table t1; +select hex(substr(_ucs2 0x00e400e50068,1)); +hex(substr(_ucs2 0x00e400e50068,1)) +00E400E50068 +select hex(substr(_ucs2 0x00e400e50068,2)); +hex(substr(_ucs2 0x00e400e50068,2)) +00E50068 +select hex(substr(_ucs2 0x00e400e50068,3)); +hex(substr(_ucs2 0x00e400e50068,3)) +0068 +select hex(substr(_ucs2 0x00e400e50068,-1)); +hex(substr(_ucs2 0x00e400e50068,-1)) +0068 +select hex(substr(_ucs2 0x00e400e50068,-2)); +hex(substr(_ucs2 0x00e400e50068,-2)) +00E50068 +select hex(substr(_ucs2 0x00e400e50068,-3)); +hex(substr(_ucs2 0x00e400e50068,-3)) +00E400E50068 SET NAMES latin1; SET collation_connection='ucs2_swedish_ci'; CREATE TABLE t1 (Field1 int(10) default '0'); diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index db5b13cf1b4..6c72c409463 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -374,6 +374,16 @@ SET NAMES latin1; SET collation_connection='ucs2_bin'; -- source include/ctype_filesort.inc +# +# Bug#10344 Some string functions fail for UCS2 +# +select hex(substr(_ucs2 0x00e400e50068,1)); +select hex(substr(_ucs2 0x00e400e50068,2)); +select hex(substr(_ucs2 0x00e400e50068,3)); +select hex(substr(_ucs2 0x00e400e50068,-1)); +select hex(substr(_ucs2 0x00e400e50068,-2)); +select hex(substr(_ucs2 0x00e400e50068,-3)); + SET NAMES latin1; # # Bug#8235 diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index f5d0721fa9b..f12cfe3256e 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1261,7 +1261,7 @@ uint my_charpos_ucs2(CHARSET_INFO *cs __attribute__((unused)), const char *e __attribute__((unused)), uint pos) { - return pos*2; + return pos > e - b ? e - b + 2 : pos * 2; } From 05a945ecf42087ad46bd120624af0c356e4041c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 May 2005 13:53:47 +0200 Subject: [PATCH 19/63] Makefile.am, configure.in: Enable creation of embedded lib when --with-darwin-mwcc configure.in: Enable creation of embedded lib when --with-darwin-mwcc libmysqld/Makefile.am: Enable creation of embedded lib when --with-darwin-mwcc --- configure.in | 3 +++ libmysqld/Makefile.am | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 00ec737e76f..9d524de125a 100644 --- a/configure.in +++ b/configure.in @@ -145,8 +145,11 @@ AC_ARG_WITH(darwin-mwcc, export CC CXX LD AR RANLIB AC_SUBST(AR) AC_SUBST(RANLIB) + with_darwin_mwcc=yes ]) +AM_CONDITIONAL(DARWIN_MWCC, test x$with_darwin_mwcc = xyes) + if test "x${CFLAGS-}" = x ; then cflags_is_set=no else diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 4cf2c3f67a7..f578e87ae4a 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -83,6 +83,9 @@ INC_LIB= $(top_builddir)/regex/libregex.a \ # generate a total libmysqld.a from all library files, libmysqld.a: libmysqld_int.a $(INC_LIB) +if DARWIN_MWCC + mwld -lib -o $@ libmysqld_int.a `ls -1 $(INC_LIB) | sort -u` +else if test "$(host_os)" = "netware" ; \ then \ $(libmysqld_a_AR) libmysqld.a libmysqld_int.a $(INC_LIB) ; \ @@ -104,7 +107,7 @@ libmysqld.a: libmysqld_int.a $(INC_LIB) rm -f tmp/* ; \ $(RANLIB) libmysqld.a ; \ fi - +endif ## XXX: any time the client interface changes, we'll need to bump ## the version info for libmysqld; however, it's possible for the From 5afb72220d81eac038c3345b7e7edd9823b973a9 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 May 2005 17:00:54 +0500 Subject: [PATCH 20/63] ctype-big5.c: additional fix for bug@10493, for sjis ctype-cp932.c: additional fix for bug#10493, for cp932 strings/ctype-cp932.c: additional fix for bug#10493, for cp932 strings/ctype-big5.c: additional fix for bug@10493, for sjis --- strings/ctype-big5.c | 2 +- strings/ctype-cp932.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 07b30205f89..52886116ff2 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6285,7 +6285,7 @@ uint my_well_formed_len_big5(CHARSET_INFO *cs __attribute__((unused)), const char *emb= e - 1; /* Last possible end of an MB character */ *error= 0; - while (pos && b < e) + while (pos-- && b < e) { if ((uchar) b[0] < 128) { diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c index 0db38afa1f7..d9e3bbd5866 100644 --- a/strings/ctype-cp932.c +++ b/strings/ctype-cp932.c @@ -5417,7 +5417,7 @@ uint my_well_formed_len_cp932(CHARSET_INFO *cs __attribute__((unused)), { const char *b0= b; *error= 0; - while (pos && b < e) + while (pos-- && b < e) { /* Cast to int8 for extra safety. From 4c2265b0aeedceb8407f2e06f4d949a711b4f534 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 May 2005 17:51:29 +0200 Subject: [PATCH 21/63] Fix for Ingo BUILD/check-cpu: Set old_flag to pentium --- BUILD/check-cpu | 1 + 1 file changed, 1 insertion(+) diff --git a/BUILD/check-cpu b/BUILD/check-cpu index 3cce4b1ab3d..7619224314b 100755 --- a/BUILD/check-cpu +++ b/BUILD/check-cpu @@ -57,6 +57,7 @@ case "$cpu_family--$model_name" in ;; *Pentium*M*pro*) cpu_flag="pentium-m"; + cpu_flag_old="pentium"; ;; *Athlon*64*) cpu_flag="athlon64"; From e02416c53cc97cb16b8d6a3c0df76568a061538d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 10 May 2005 16:31:13 -0700 Subject: [PATCH 22/63] Many files: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. view.test: Added test case for bug #8528. view.result: Added test case for bug #8528. Fixed other test cases. mysql-test/r/view.result: Added test case for bug #8528. Fixed other test cases. mysql-test/t/view.test: Added test case for bug #8528. sql/sql_base.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_delete.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_insert.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_parse.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_prepare.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_select.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_update.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_view.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/table.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/table.h: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. --- mysql-test/r/view.result | 41 ++++++++++++++++++++-------------------- mysql-test/t/view.test | 24 ++++++++++++++++++++--- sql/sql_base.cc | 4 +--- sql/sql_delete.cc | 2 -- sql/sql_insert.cc | 8 ++------ sql/sql_parse.cc | 2 +- sql/sql_prepare.cc | 6 +----- sql/sql_select.cc | 4 ++-- sql/sql_update.cc | 14 +++++++------- sql/sql_view.cc | 4 ++-- sql/table.cc | 28 +++++++++++++++------------ sql/table.h | 7 ++++++- 12 files changed, 80 insertions(+), 64 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 59ff6abdde2..1d5b492724e 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -51,7 +51,7 @@ explain extended select c from v1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Warnings: -Note 1003 select (`test`.`t1`.`b` + 1) AS `c` from `test`.`v1` +Note 1003 select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1` create algorithm=temptable view v2 (c) as select b+1 from t1; show create view v2; View Create View @@ -85,7 +85,7 @@ explain extended select c from v3; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Warnings: -Note 1003 select ((`test`.`t1`.`b` + 1) + 1) AS `c` from `test`.`v3` +Note 1003 select ((`test`.`t1`.`b` + 1) + 1) AS `c` from `test`.`t1` create algorithm=temptable view v4 (c) as select c+1 from v2; select c from v4; c @@ -114,7 +114,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 5 3 DERIVED t1 ALL NULL NULL NULL NULL 5 Warnings: -Note 1003 select (`v2`.`c` + 1) AS `c` from `test`.`v5` +Note 1003 select (`v2`.`c` + 1) AS `c` from `test`.`v2` create algorithm=temptable view v6 (c) as select c+1 from v1; select c from v6; c @@ -204,21 +204,6 @@ create table t1 (a int); insert into t1 values (1), (2), (3); create view v1 (a) as select a+1 from t1; create view v2 (a) as select a-1 from t1; -select * from t1 natural left join v1; -a a -1 NULL -2 2 -3 3 -select * from v2 natural left join t1; -a a -0 NULL -1 1 -2 2 -select * from v2 natural left join v1; -a a -0 NULL -1 NULL -2 2 drop view v1, v2; drop table t1; create table t1 (a int); @@ -378,7 +363,7 @@ explain extended select * from v1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where Warnings: -Note 1003 select `test`.`t1`.`b` AS `c` from `test`.`v1` where (`test`.`t1`.`a` < 3) +Note 1003 select `test`.`t1`.`b` AS `c` from `test`.`t1` where (`test`.`t1`.`a` < 3) update v1 set c=c+1; select * from t1; a b @@ -1393,7 +1378,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Warnings: -Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`v1` left join `test`.`v2` on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1 +Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`t1` left join (`test`.`t2`) on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1 prepare stmt1 from "select * from t3 left join v4 on (t3.a = v4.a);"; execute stmt1; a a b @@ -1694,3 +1679,19 @@ col1 col2 col2 col3 5 david NULL NULL DROP VIEW v1,v2,v3; DROP TABLE t1,t2; +CREATE TABLE t1 (a int); +CREATE TABLE t2 (b int); +INSERT INTO t1 VALUES (1), (2), (3), (4); +INSERT INTO t2 VALUES (4), (2); +CREATE VIEW v1 AS SELECT * FROM t1,t2 WHERE t1.a=t2.b; +SELECT * FROM v1; +a b +2 2 +4 4 +CREATE VIEW v2 AS SELECT * FROM v1; +SELECT * FROM v2; +a b +2 2 +4 4 +DROP VIEW v2,v1; +DROP TABLE t1,t2; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 0c3c81d0b89..e85c2751424 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -148,9 +148,10 @@ insert into t1 values (1), (2), (3); create view v1 (a) as select a+1 from t1; create view v2 (a) as select a-1 from t1; -select * from t1 natural left join v1; -select * from v2 natural left join t1; -select * from v2 natural left join v1; +# WL #2486 should enable these tests +#select * from t1 natural left join v1; +#select * from v2 natural left join t1; +#select * from v2 natural left join v1; drop view v1, v2; drop table t1; @@ -1519,3 +1520,20 @@ SELECT a.col1,a.col2,b.col2,b.col3 DROP VIEW v1,v2,v3; DROP TABLE t1,t2; + +# +# Test case for bug #8528: select from view over multi-table view +# + +CREATE TABLE t1 (a int); +CREATE TABLE t2 (b int); +INSERT INTO t1 VALUES (1), (2), (3), (4); +INSERT INTO t2 VALUES (4), (2); + +CREATE VIEW v1 AS SELECT * FROM t1,t2 WHERE t1.a=t2.b; +SELECT * FROM v1; +CREATE VIEW v2 AS SELECT * FROM v1; +SELECT * FROM v2; + +DROP VIEW v2,v1; +DROP TABLE t1,t2; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index d79811aa4e2..7280dc89993 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3157,10 +3157,8 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables) { for (TABLE_LIST *table= tables; table; table= table->next_local) { - if (table->view && !table->table) + if (table->view && table->effective_algorithm == VIEW_ALGORITHM_MERGE) { - /* it is for multi table views only, check it */ - DBUG_ASSERT(table->ancestor->next_local != 0); list= make_leaves_list(list, table->ancestor); } else diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d524bbcf164..cded9e2a13e 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -46,8 +46,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, DBUG_RETURN(TRUE); if (!(table= table_list->table)) { - DBUG_ASSERT(table_list->view && - table_list->ancestor && table_list->ancestor->next_local); my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), table_list->view_db.str, table_list->view_name.str); DBUG_RETURN(-1); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a38138ca5fd..2d882b477aa 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -81,8 +81,6 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, { if (!table) { - DBUG_ASSERT(table_list->view && - table_list->ancestor && table_list->ancestor->next_local); my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0), table_list->view_db.str, table_list->view_name.str); return -1; @@ -124,7 +122,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, thd->lex->select_lex.no_wrap_view_item= 0; if (res) return -1; - if (table == 0) + if (table_list->effective_algorithm == VIEW_ALGORITHM_MERGE) { /* it is join view => we need to find table for update */ List_iterator_fast it(fields); @@ -134,7 +132,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, while ((item= it++)) map|= item->used_tables(); - if (table_list->check_single_table(&tbl, map) || tbl == 0) + if (table_list->check_single_table(&tbl, map, table_list) || tbl == 0) { my_error(ER_VIEW_MULTIUPDATE, MYF(0), table_list->view_db.str, table_list->view_name.str); @@ -706,8 +704,6 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, thd->lex->empty_field_list_on_rset= 1; if (!table_list->table) { - DBUG_ASSERT(table_list->view && - table_list->ancestor && table_list->ancestor->next_local); my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0), table_list->view_db.str, table_list->view_name.str); DBUG_RETURN(TRUE); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c5ef9f4e713..058da7a803c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1764,7 +1764,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->lex-> select_lex.table_list.link_in_list((byte*) &table_list, (byte**) &table_list.next_local); - thd->lex->query_tables= &table_list; + thd->lex->add_to_query_tables(&table_list); /* switch on VIEW optimisation: do not fill temporary tables */ thd->lex->sql_command= SQLCOM_SHOW_FIELDS; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 56d09d7c563..28df681769b 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1006,7 +1006,7 @@ static int mysql_test_update(Prepared_statement *stmt, if (!open_tables(thd, &table_list, &table_count)) { - if (table_list->ancestor && table_list->ancestor->next_local) + if (table_list->multitable_view) { DBUG_ASSERT(table_list->view != 0); DBUG_PRINT("info", ("Switch to multi-update")); @@ -1095,8 +1095,6 @@ static int mysql_test_delete(Prepared_statement *stmt, bool res; if (!table_list->table) { - DBUG_ASSERT(table_list->view && - table_list->ancestor && table_list->ancestor->next_local); my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), table_list->view_db.str, table_list->view_name.str); DBUG_RETURN(-1); @@ -1458,8 +1456,6 @@ static int mysql_test_multidelete(Prepared_statement *stmt, return res; if (!tables->table) { - DBUG_ASSERT(tables->view && - tables->ancestor && tables->ancestor->next_local); my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), tables->view_db.str, tables->view_name.str); return -1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9b93a92c6aa..10bb45c58f1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7351,7 +7351,7 @@ simplify_joins(JOIN *join, List *join_list, COND *conds, bool top) */ if (table->on_expr) { - Item *expr; + Item *expr= table->prep_on_expr ? table->prep_on_expr : table->on_expr; /* If an on expression E is attached to the table, check all null rejected predicates in this expression. @@ -7361,7 +7361,7 @@ simplify_joins(JOIN *join, List *join_list, COND *conds, bool top) the corresponding on expression is added to E. */ expr= simplify_joins(join, &nested_join->join_list, - table->on_expr, FALSE); + expr, FALSE); table->prep_on_expr= table->on_expr= expr; } nested_join->used_tables= (table_map) 0; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 86aa0bf9890..95268c41aed 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -139,7 +139,7 @@ int mysql_update(THD *thd, if (open_tables(thd, &table_list, &table_count)) DBUG_RETURN(1); - if (table_list->ancestor && table_list->ancestor->next_local) + if (table_list->multitable_view) { DBUG_ASSERT(table_list->view != 0); DBUG_PRINT("info", ("Switch to multi-update")); @@ -706,9 +706,11 @@ bool mysql_multi_update_prepare(THD *thd) if (!tl->placeholder() && !tl->schema_table && !using_lock_tables) tl->table->reginfo.lock_type= tl->lock_type; } - + } + for(tl= table_list; tl; tl= tl->next_local) + { /* Check access privileges for table */ - if (!tl->derived && !tl->belong_to_view) + if (!tl->derived) { uint want_privilege= tl->updating ? UPDATE_ACL : SELECT_ACL; if (check_access(thd, want_privilege, @@ -721,12 +723,10 @@ bool mysql_multi_update_prepare(THD *thd) /* check single table update for view compound from several tables */ for (tl= table_list; tl; tl= tl->next_local) { - if (tl->table == 0) + if (tl->effective_algorithm == VIEW_ALGORITHM_MERGE) { - DBUG_ASSERT(tl->view && - tl->ancestor && tl->ancestor->next_local); TABLE_LIST *for_update= 0; - if (tl->check_single_table(&for_update, tables_for_update)) + if (tl->check_single_table(&for_update, tables_for_update, tl)) { my_error(ER_VIEW_MULTIUPDATE, MYF(0), tl->view_db.str, tl->view_name.str); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index be643c36d7d..333a713257f 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -773,9 +773,9 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) tbl->lock_type= table->lock_type; } - /* multi table view */ - if (view_tables->next_local) { + if (view_tables->next_local) + table->multitable_view= TRUE; /* make nested join structure for view tables */ NESTED_JOIN *nested_join; if (!(nested_join= table->nested_join= diff --git a/sql/table.cc b/sql/table.cc index 8e0f52e1910..d9a092ea416 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1644,11 +1644,13 @@ void st_table_list::set_ancestor() */ tbl->ancestor->set_ancestor(); } - tbl->table->grant= grant; + if (tbl->multitable_view) + multitable_view= TRUE; + if (tbl->table) + tbl->table->grant= grant; } while ((tbl= tbl->next_local)); - /* if view contain only one table, substitute TABLE of it */ - if (!ancestor->next_local) + if (!multitable_view) { table= ancestor->table; schema_table= ancestor->schema_table; @@ -1675,8 +1677,6 @@ void st_table_list::save_and_clear_want_privilege() } else { - DBUG_ASSERT(tbl->view && tbl->ancestor && - tbl->ancestor->next_local); tbl->save_and_clear_want_privilege(); } } @@ -1698,8 +1698,6 @@ void st_table_list::restore_want_privilege() tbl->table->grant.want_privilege= privilege_backup; else { - DBUG_ASSERT(tbl->view && tbl->ancestor && - tbl->ancestor->next_local); tbl->restore_want_privilege(); } } @@ -2053,16 +2051,17 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure) { if (check_option && check_option->val_int() == 0) { + TABLE_LIST *view= (belong_to_view ? belong_to_view : this); if (ignore_failure) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_VIEW_CHECK_FAILED, ER(ER_VIEW_CHECK_FAILED), - view_db.str, view_name.str); + view->view_db.str, view->view_name.str); return(VIEW_CHECK_SKIP); } else { - my_error(ER_VIEW_CHECK_FAILED, MYF(0), view_db.str, view_name.str); + my_error(ER_VIEW_CHECK_FAILED, MYF(0), view->view_db.str, view->view_name.str); return(VIEW_CHECK_ERROR); } } @@ -2080,13 +2079,15 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure) (should be 0 on call, to find table, or point to table for unique test) map bit mask of tables + view view for which we are looking table RETURN FALSE table not found or found only one TRUE found several tables */ -bool st_table_list::check_single_table(st_table_list **table, table_map map) +bool st_table_list::check_single_table(st_table_list **table, table_map map, + st_table_list *view) { for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) { @@ -2097,11 +2098,14 @@ bool st_table_list::check_single_table(st_table_list **table, table_map map) if (*table) return TRUE; else + { *table= tbl; + tbl->check_option= view->check_option; + } } } else - if (tbl->check_single_table(table, map)) + if (tbl->check_single_table(table, map, view)) return TRUE; } return FALSE; @@ -2131,7 +2135,7 @@ bool st_table_list::set_insert_values(MEM_ROOT *mem_root) } else { - DBUG_ASSERT(view && ancestor && ancestor->next_local); + DBUG_ASSERT(view && ancestor); for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local) if (tbl->set_insert_values(mem_root)) return TRUE; diff --git a/sql/table.h b/sql/table.h index d00ac41140e..781b5e21f9b 100644 --- a/sql/table.h +++ b/sql/table.h @@ -432,6 +432,10 @@ typedef struct st_table_list bool skip_temporary; /* this table shouldn't be temporary */ /* TRUE if this merged view contain auto_increment field */ bool contain_auto_increment; +#if 0 +#else + bool multitable_view; /* TRUE iff this is multitable view */ +#endif /* FRMTYPE_ERROR if any type is acceptable */ enum frm_type_enum required_type; char timestamp_buffer[20]; /* buffer for timestamp (19+1) */ @@ -450,7 +454,8 @@ typedef struct st_table_list void print(THD *thd, String *str); void save_and_clear_want_privilege(); void restore_want_privilege(); - bool check_single_table(st_table_list **table, table_map map); + bool check_single_table(st_table_list **table, table_map map, + st_table_list *view); bool set_insert_values(MEM_ROOT *mem_root); st_table_list *find_underlying_table(TABLE *table); } TABLE_LIST; From 913e2e12d2fa2095989b5ddbfc0fc97751da0cbf Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 May 2005 12:14:46 -0500 Subject: [PATCH 23/63] mysqldump.1.in: Remove obsolete section number. (Bug #10534) man/mysqldump.1.in: Remove obsolete section number. (Bug #10534) --- man/mysqldump.1.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/man/mysqldump.1.in b/man/mysqldump.1.in index 4d841117e59..0f581429af7 100644 --- a/man/mysqldump.1.in +++ b/man/mysqldump.1.in @@ -218,7 +218,8 @@ or ), mysqldump will create rows up to net_buffer_length length. If you increase this variable, you should also ensure that the max_allowed_packet variable in the MySQL server is bigger than the net_buffer_length. .SH EXAMPLES .TP -The most normal use of mysqldump is probably for making a backup of whole databases. See Mysql Manual section 21.2 Database Backups. +The most normal use of mysqldump is probably for making a backup of whole +databases. See the section on Database Backups in the MySQL Reference Manual. .TP mysqldump \-\-opt \fP\fIdatabase\fP > backup-file.sql .TP From 2a8556f32deb10ecf2b1f857a1038330b38af53f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 May 2005 11:16:12 +0400 Subject: [PATCH 24/63] A fix and test case for Bug#9478 "mysql_stmt_attr_set mysql_stmt_execute" (crash on attempt to re-execute a statement with an open cursor) + post-review fixes. include/errmsg.h: Add a special error message when we attempt to mysql_stmt_fetch from a statement which has no result set. libmysql/errmsg.c: Error message text for CR_NO_RESULT_SET libmysql/libmysql.c: Move the code which frees result sets on client and closes the cursor on server, resets long data state on client and server. This makes one function out of two (mysql_stmt_reset and mysql_stmt_free_result), thus aggregating all related reset work in one place. sql-common/client.c: Fix one place where we flushed the pending result set of a statement, but didn't set unbuffered_fetch_cancelled flag. sql/share/errmsg.txt: Fix format of ER_UNKNOWN_STMT_HANDLER error message (needs to be fixed separately in 4.1). Add two new error messages for the case when we fetch from when there is no cursor and for the case when we attempt to execute a statement while there is a cursor. sql/sql_prepare.cc: Return error when we fetch while there is no open cursor and when we call execute while there is a pending cursor. Fix mysql_stmt_reset to close the open cursor if there is any. sql/sql_select.cc: free_items and free_root moved to Cursor::close(). sql/sql_select.h: A comment added. tests/mysql_client_test.c: A test case for Bug#9478, test the case of mysql_stmt_reset called for client-side cached result set and for the case with open cursor. All strcpy replaced with strmov (review request). --- include/errmsg.h | 3 +- libmysql/errmsg.c | 3 + libmysql/libmysql.c | 122 +++++++++++++---------- sql-common/client.c | 2 + sql/share/errmsg.txt | 12 ++- sql/sql_prepare.cc | 27 ++++-- sql/sql_select.cc | 18 ++-- sql/sql_select.h | 4 + tests/mysql_client_test.c | 197 +++++++++++++++++++++++++++++++++----- 9 files changed, 294 insertions(+), 94 deletions(-) diff --git a/include/errmsg.h b/include/errmsg.h index ae3b04b4f3a..fd3da392df4 100644 --- a/include/errmsg.h +++ b/include/errmsg.h @@ -95,6 +95,7 @@ extern const char *client_errors[]; /* Error messages */ #define CR_FETCH_CANCELED 2050 #define CR_NO_DATA 2051 #define CR_NO_STMT_METADATA 2052 -#define CR_ERROR_LAST /*Copy last error nr:*/ 2052 +#define CR_NO_RESULT_SET 2053 +#define CR_ERROR_LAST /*Copy last error nr:*/ 2053 /* Add error numbers before CR_ERROR_LAST and change it accordingly. */ diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c index 90ad3aefaca..48e44327d0f 100644 --- a/libmysql/errmsg.c +++ b/libmysql/errmsg.c @@ -80,6 +80,7 @@ const char *client_errors[]= "Row retrieval was canceled by mysql_stmt_close() call", "Attempt to read column without prior row fetch", "Prepared statement contains no metadata", + "Attempt to read a row while there is no result set associated with the statement" "" }; @@ -141,6 +142,7 @@ const char *client_errors[]= "Row retrieval was canceled by mysql_stmt_close() call", "Attempt to read column without prior row fetch", "Prepared statement contains no metadata", + "Attempt to read a row while there is no result set associated with the statement" "" }; @@ -200,6 +202,7 @@ const char *client_errors[]= "Row retrieval was canceled by mysql_stmt_close() call", "Attempt to read column without prior row fetch", "Prepared statement contains no metadata", + "Attempt to read a row while there is no result set associated with the statement" "" }; #endif diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index bf797dfd580..3e6b29b7602 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1724,6 +1724,13 @@ static int stmt_read_row_no_data(MYSQL_STMT *stmt, unsigned char **row); static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data); static my_bool setup_one_fetch_function(MYSQL_BIND *bind, MYSQL_FIELD *field); +/* Auxilary function used to reset statement handle. */ + +#define RESET_SERVER_SIDE 1 +#define RESET_LONG_DATA 2 + +static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags); + /* Maximum sizes of MYSQL_TYPE_DATE, MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME values stored in network buffer. @@ -2019,7 +2026,8 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length) /* This is second prepare with another statement */ char buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */ - mysql_stmt_free_result(stmt); + if (reset_stmt_handle(stmt, RESET_LONG_DATA)) + DBUG_RETURN(1); /* These members must be reset for API to function in case of error or misuse. @@ -2702,12 +2710,8 @@ static int stmt_read_row_no_data(MYSQL_STMT *stmt __attribute__((unused)), unsigned char **row __attribute__((unused))) { - if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE) - { - set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate); - return 1; - } - return MYSQL_NO_DATA; + set_stmt_error(stmt, CR_NO_RESULT_SET, unknown_sqlstate); + return 1; } @@ -2817,7 +2821,8 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) DBUG_RETURN(1); } - mysql_stmt_free_result(stmt); + if (reset_stmt_handle(stmt, 0)) + DBUG_RETURN(1); /* No need to check for stmt->state: if the statement wasn't prepared we'll get 'unknown statement handler' error from server. @@ -4805,16 +4810,21 @@ my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt) DBUG_RETURN(stmt->result.rows); } -my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt) + +/* + Free the client side memory buffers, reset long data state + on client if necessary, and reset the server side statement if + this has been requested. +*/ + +static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags) { - MYSQL_DATA *result= &stmt->result; - DBUG_ENTER("mysql_stmt_free_result"); - - DBUG_ASSERT(stmt != 0); - + /* If statement hasn't been prepared there is nothing to reset */ if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE) { MYSQL *mysql= stmt->mysql; + MYSQL_DATA *result= &stmt->result; + my_bool has_cursor= stmt->read_row_func == stmt_read_row_from_cursor; if (result->data) { @@ -4824,23 +4834,58 @@ my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt) result->rows= 0; stmt->data_cursor= NULL; } - - if (mysql && stmt->field_count && - (int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE) + if (flags & RESET_LONG_DATA) { - if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled) - mysql->unbuffered_fetch_owner= 0; - if (mysql->status != MYSQL_STATUS_READY) + MYSQL_BIND *param= stmt->params, *param_end= param + stmt->param_count; + /* Clear long_data_used flags */ + for (; param < param_end; param++) + param->long_data_used= 0; + } + stmt->read_row_func= stmt_read_row_no_data; + if (mysql) + { + if ((int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE) { - /* There is a result set and it belongs to this statement */ - (*mysql->methods->flush_use_result)(mysql); - mysql->status= MYSQL_STATUS_READY; + if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled) + mysql->unbuffered_fetch_owner= 0; + if (stmt->field_count && mysql->status != MYSQL_STATUS_READY) + { + /* There is a result set and it belongs to this statement */ + (*mysql->methods->flush_use_result)(mysql); + if (mysql->unbuffered_fetch_owner) + *mysql->unbuffered_fetch_owner= TRUE; + mysql->status= MYSQL_STATUS_READY; + } + } + if (has_cursor || (flags & RESET_SERVER_SIDE)) + { + /* + Reset the server side statement and close the server side + cursor if it exists. + */ + char buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */ + int4store(buff, stmt->stmt_id); + if ((*mysql->methods->advanced_command)(mysql, COM_RESET_STMT, buff, + sizeof(buff), 0, 0, 0)) + { + set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, + mysql->net.sqlstate); + stmt->state= MYSQL_STMT_INIT_DONE; + return 1; + } } } stmt->state= MYSQL_STMT_PREPARE_DONE; - stmt->read_row_func= stmt_read_row_no_data; } - DBUG_RETURN(0); + return 0; +} + +my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt) +{ + DBUG_ENTER("mysql_stmt_free_result"); + + /* Free the client side and close the server side cursor if there is one */ + DBUG_RETURN(reset_stmt_handle(stmt, RESET_LONG_DATA)); } /******************************************************************** @@ -4913,33 +4958,10 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt) my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt) { - char buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */ - MYSQL *mysql; - MYSQL_BIND *param, *param_end; DBUG_ENTER("mysql_stmt_reset"); DBUG_ASSERT(stmt != 0); - - /* If statement hasnt been prepared there is nothing to reset */ - if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE) - DBUG_RETURN(0); - - mysql= stmt->mysql->last_used_con; - int4store(buff, stmt->stmt_id); /* Send stmt id to server */ - if ((*mysql->methods->advanced_command)(mysql, COM_RESET_STMT, buff, - sizeof(buff), 0, 0, 0)) - { - set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno, - mysql->net.sqlstate); - DBUG_RETURN(1); - } - - /* Clear long_data_used for next call (as we do in mysql_stmt_execute() */ - for (param= stmt->params, param_end= param + stmt->param_count; - param < param_end; - param++) - param->long_data_used= 0; - - DBUG_RETURN(0); + /* Reset the client and server sides of the prepared statement */ + DBUG_RETURN(reset_stmt_handle(stmt, RESET_SERVER_SIDE | RESET_LONG_DATA)); } /* diff --git a/sql-common/client.c b/sql-common/client.c index 59e27e4090a..4cbdb4b8e0d 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -864,6 +864,8 @@ mysql_free_result(MYSQL_RES *result) { (*mysql->methods->flush_use_result)(mysql); mysql->status=MYSQL_STATUS_READY; + if (mysql->unbuffered_fetch_owner) + *mysql->unbuffered_fetch_owner= TRUE; } } free_rows(result->data); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 388f47bf96f..848cc422dc2 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -4766,13 +4766,13 @@ ER_SUBQUERY_NO_1_ROW 21000 swe "Subquery returnerade mer än 1 rad" ukr "ð¦ÄÚÁÐÉÔ ÐÏ×ÅÒÔÁ¤ Â¦ÌØÛ ÎiÖ 1 ÚÁÐÉÓ" ER_UNKNOWN_STMT_HANDLER - dan "Unknown prepared statement handler (%ld) given to %s" + dan "Unknown prepared statement handler (%.*s) given to %s" eng "Unknown prepared statement handler (%.*s) given to %s" ger "Unbekannter Prepared-Statement-Handler (%.*s) für %s angegeben" por "Desconhecido manipulador de declaração preparado (%.*s) determinado para %s" - spa "Desconocido preparado comando handler (%ld) dado para %s" - swe "Okänd PREPARED STATEMENT id (%ld) var given till %s" - ukr "Unknown prepared statement handler (%ld) given to %s" + spa "Desconocido preparado comando handler (%.*s) dado para %s" + swe "Okänd PREPARED STATEMENT id (%.*s) var given till %s" + ukr "Unknown prepared statement handler (%.*s) given to %s" ER_CORRUPT_HELP_DB eng "Help database is corrupt or does not exist" ger "Die Hilfe-Datenbank ist beschädigt oder existiert nicht" @@ -5352,3 +5352,7 @@ ER_BINLOG_UNSAFE_ROUTINE eng "This routine is declared to be non-deterministic and to modify data and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)" ER_BINLOG_CREATE_ROUTINE_NEED_SUPER eng "You do not have SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)" +ER_EXEC_STMT_WITH_OPEN_CURSOR + eng "You can't execute a prepared statement which has an open cursor associated with it. Reset the statement to re-execute it." +ER_STMT_HAS_NO_OPEN_CURSOR + eng "The statement (%d) has no open cursor." diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 17c5f51f1e1..03b3df1bc22 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -135,7 +135,8 @@ find_prepared_statement(THD *thd, ulong id, const char *where) if (stmt == 0 || stmt->type() != Item_arena::PREPARED_STATEMENT) { char llbuf[22]; - my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), 22, llstr(id, llbuf), where); + my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf), llstr(id, llbuf), + where); return 0; } return (Prepared_statement *) stmt; @@ -1969,7 +1970,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) { ulong stmt_id= uint4korr(packet); ulong flags= (ulong) ((uchar) packet[4]); - Cursor *cursor= 0; + Cursor *cursor; /* Query text for binary log, or empty string if the query is not put into binary log. @@ -1995,6 +1996,13 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) DBUG_VOID_RETURN; } + cursor= stmt->cursor; + if (cursor && cursor->is_open()) + { + my_error(ER_EXEC_STMT_WITH_OPEN_CURSOR, MYF(0)); + DBUG_VOID_RETURN; + } + DBUG_ASSERT(thd->free_list == NULL); mysql_reset_thd_for_next_command(thd); if (flags & (ulong) CURSOR_TYPE_READ_ONLY) @@ -2013,7 +2021,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) else { DBUG_PRINT("info",("Using READ_ONLY cursor")); - if (!stmt->cursor && + if (!cursor && !(cursor= stmt->cursor= new (&stmt->main_mem_root) Cursor())) DBUG_VOID_RETURN; /* If lex->result is set, mysql_execute_command will use it */ @@ -2208,13 +2216,15 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) Statement *stmt; DBUG_ENTER("mysql_stmt_fetch"); - if (!(stmt= thd->stmt_map.find(stmt_id)) || - !stmt->cursor || - !stmt->cursor->is_open()) + if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch"))) + DBUG_VOID_RETURN; + + if (!stmt->cursor || !stmt->cursor->is_open()) { - my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), stmt_id, "fetch"); + my_error(ER_STMT_HAS_NO_OPEN_CURSOR, MYF(0)); DBUG_VOID_RETURN; } + thd->current_arena= stmt; thd->set_n_backup_statement(stmt, &thd->stmt_backup); stmt->cursor->init_thd(thd); @@ -2266,6 +2276,9 @@ void mysql_stmt_reset(THD *thd, char *packet) if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset"))) DBUG_VOID_RETURN; + if (stmt->cursor && stmt->cursor->is_open()) + stmt->cursor->close(); + stmt->state= Item_arena::PREPARED; /* diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 47c7de6eba7..84f3bb92a7d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1742,6 +1742,7 @@ Cursor::init_from_thd(THD *thd) /* XXX: thd->locked_tables is not changed. What problems can we have with it if cursor is open? + TODO: must be fixed because of the prelocked mode. */ /* TODO: grab thd->free_list here? @@ -1871,10 +1872,6 @@ Cursor::fetch(ulong num_rows) } else if (error != NESTED_LOOP_KILLED) my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); - /* free cursor memory */ - free_items(free_list); - free_list= 0; - free_root(&main_mem_root, MYF(0)); } } @@ -1914,6 +1911,13 @@ Cursor::close() } join= 0; unit= 0; + free_items(free_list); + free_list= 0; + /* + Must be last, as some memory might be allocated for free purposes, + like in free_tmp_table() (TODO: fix this issue) + */ + free_root(mem_root, MYF(0)); DBUG_VOID_RETURN; } @@ -1922,12 +1926,6 @@ Cursor::~Cursor() { if (is_open()) close(); - free_items(free_list); - /* - Must be last, as some memory might be allocated for free purposes, - like in free_tmp_table() (TODO: fix this issue) - */ - free_root(&main_mem_root, MYF(0)); } /*********************************************************************/ diff --git a/sql/sql_select.h b/sql/sql_select.h index a27fbc60856..49ac58e913b 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -364,6 +364,10 @@ class JOIN :public Sql_alloc /* Server-side cursor (now stands only for basic read-only cursor) See class implementation in sql_select.cc + A cursor has its own runtime state - list of used items and memory root of + used memory - which is different from Prepared statement runtime: it must + be different at least for the purpose of reusing the same prepared + statement for many cursors. */ class Cursor: public Sql_alloc, public Item_arena diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 6ab5843803e..da57fbabaf2 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -2269,7 +2269,7 @@ static void test_ps_conj_select() check_execute(stmt, rc); int_data= 1; - strcpy(str_data, "hh"); + strmov(str_data, "hh"); str_length= strlen(str_data); rc= mysql_stmt_execute(stmt); @@ -7288,7 +7288,7 @@ static void test_decimal_bug() rc= mysql_stmt_bind_param(stmt, bind); check_execute(stmt, rc); - strcpy(data, "8.0"); + strmov(data, "8.0"); rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); @@ -7306,7 +7306,7 @@ static void test_decimal_bug() rc= mysql_stmt_fetch(stmt); DIE_UNLESS(rc == MYSQL_NO_DATA); - strcpy(data, "5.61"); + strmov(data, "5.61"); rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); @@ -7331,7 +7331,7 @@ static void test_decimal_bug() rc= mysql_stmt_fetch(stmt); DIE_UNLESS(rc == MYSQL_NO_DATA); - strcpy(data, "10.22"); is_null= 0; + strmov(data, "10.22"); is_null= 0; rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); @@ -8510,13 +8510,13 @@ static void test_sqlmode() myquery(rc); /* PIPES_AS_CONCAT */ - strcpy(query, "SET SQL_MODE= \"PIPES_AS_CONCAT\""); + strmov(query, "SET SQL_MODE= \"PIPES_AS_CONCAT\""); if (!opt_silent) fprintf(stdout, "\n With %s", query); rc= mysql_query(mysql, query); myquery(rc); - strcpy(query, "INSERT INTO test_piping VALUES(?||?)"); + strmov(query, "INSERT INTO test_piping VALUES(?||?)"); if (!opt_silent) fprintf(stdout, "\n query: %s", query); stmt= mysql_simple_prepare(mysql, query); @@ -8542,7 +8542,7 @@ static void test_sqlmode() rc= mysql_stmt_bind_param(stmt, bind); check_execute(stmt, rc); - strcpy(c1, "My"); strcpy(c2, "SQL"); + strmov(c1, "My"); strmov(c2, "SQL"); rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); @@ -8552,20 +8552,20 @@ static void test_sqlmode() rc= mysql_query(mysql, "DELETE FROM test_piping"); myquery(rc); - strcpy(query, "SELECT connection_id ()"); + strmov(query, "SELECT connection_id ()"); if (!opt_silent) fprintf(stdout, "\n query: %s", query); stmt= mysql_simple_prepare(mysql, query); check_stmt_r(stmt); /* ANSI */ - strcpy(query, "SET SQL_MODE= \"ANSI\""); + strmov(query, "SET SQL_MODE= \"ANSI\""); if (!opt_silent) fprintf(stdout, "\n With %s", query); rc= mysql_query(mysql, query); myquery(rc); - strcpy(query, "INSERT INTO test_piping VALUES(?||?)"); + strmov(query, "INSERT INTO test_piping VALUES(?||?)"); if (!opt_silent) fprintf(stdout, "\n query: %s", query); stmt= mysql_simple_prepare(mysql, query); @@ -8576,7 +8576,7 @@ static void test_sqlmode() rc= mysql_stmt_bind_param(stmt, bind); check_execute(stmt, rc); - strcpy(c1, "My"); strcpy(c2, "SQL"); + strmov(c1, "My"); strmov(c2, "SQL"); rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); @@ -8584,7 +8584,7 @@ static void test_sqlmode() verify_col_data("test_piping", "name", "MySQL"); /* ANSI mode spaces ... */ - strcpy(query, "SELECT connection_id ()"); + strmov(query, "SELECT connection_id ()"); if (!opt_silent) fprintf(stdout, "\n query: %s", query); stmt= mysql_simple_prepare(mysql, query); @@ -8604,13 +8604,13 @@ static void test_sqlmode() mysql_stmt_close(stmt); /* IGNORE SPACE MODE */ - strcpy(query, "SET SQL_MODE= \"IGNORE_SPACE\""); + strmov(query, "SET SQL_MODE= \"IGNORE_SPACE\""); if (!opt_silent) fprintf(stdout, "\n With %s", query); rc= mysql_query(mysql, query); myquery(rc); - strcpy(query, "SELECT connection_id ()"); + strmov(query, "SELECT connection_id ()"); if (!opt_silent) fprintf(stdout, "\n query: %s", query); stmt= mysql_simple_prepare(mysql, query); @@ -9115,7 +9115,7 @@ static void test_bug2248() /* This too should not hang but should return proper error */ rc= mysql_stmt_fetch(stmt); - DIE_UNLESS(rc == MYSQL_NO_DATA); + DIE_UNLESS(rc == 1); /* This too should not hang but should not bark */ rc= mysql_stmt_store_result(stmt); @@ -9124,7 +9124,7 @@ static void test_bug2248() /* This should return proper error */ rc= mysql_stmt_fetch(stmt); check_execute_r(stmt, rc); - DIE_UNLESS(rc == MYSQL_NO_DATA); + DIE_UNLESS(rc == 1); mysql_stmt_close(stmt); @@ -10266,7 +10266,7 @@ static void test_union_param() my_bool my_null= FALSE; myheader("test_union_param"); - strcpy(my_val, "abc"); + strmov(my_val, "abc"); query= (char*)"select ? as my_col union distinct select ?"; stmt= mysql_simple_prepare(mysql, query); @@ -10548,14 +10548,14 @@ static void test_bug3796() if (!opt_silent) printf("Concat result: '%s'\n", out_buff); check_execute(stmt, rc); - strcpy(canonical_buff, concat_arg0); + strmov(canonical_buff, concat_arg0); strcat(canonical_buff, "ONE"); DIE_UNLESS(strlen(canonical_buff) == out_length && strncmp(out_buff, canonical_buff, out_length) == 0); rc= mysql_stmt_fetch(stmt); check_execute(stmt, rc); - strcpy(canonical_buff + strlen(concat_arg0), "TWO"); + strmov(canonical_buff + strlen(concat_arg0), "TWO"); DIE_UNLESS(strlen(canonical_buff) == out_length && strncmp(out_buff, canonical_buff, out_length) == 0); if (!opt_silent) @@ -10852,7 +10852,8 @@ static void test_view() rc= mysql_stmt_prepare(stmt, query, strlen(query)); check_execute(stmt, rc); - strcpy(str_data, "TEST"); + strmov(str_data, "TEST"); + bzero(bind, sizeof(bind)); bind[0].buffer_type= FIELD_TYPE_STRING; bind[0].buffer= (char *)&str_data; bind[0].buffer_length= 50; @@ -10971,8 +10972,9 @@ static void test_view_2where() " AENAME,T0001.DEPENDVARS AS DEPENDVARS,T0001.INACTIVE AS " " INACTIVE from LTDX T0001 where (T0001.SRTF2 = 0)"); myquery(rc); + bzero(bind, sizeof(bind)); for (i=0; i < 8; i++) { - strcpy(parms[i], "1"); + strmov(parms[i], "1"); bind[i].buffer_type = MYSQL_TYPE_VAR_STRING; bind[i].buffer = (char *)&parms[i]; bind[i].buffer_length = 100; @@ -11019,6 +11021,7 @@ static void test_view_star() myquery(rc); rc= mysql_query(mysql, "CREATE VIEW vt1 AS SELECT a FROM t1"); myquery(rc); + bzero(bind, sizeof(bind)); for (i= 0; i < 2; i++) { sprintf((char *)&parms[i], "%d", i); bind[i].buffer_type = MYSQL_TYPE_VAR_STRING; @@ -11084,6 +11087,7 @@ static void test_view_insert() rc= mysql_stmt_prepare(select_stmt, query, strlen(query)); check_execute(select_stmt, rc); + bzero(bind, sizeof(bind)); bind[0].buffer_type = FIELD_TYPE_LONG; bind[0].buffer = (char *)&my_val; bind[0].length = &my_length; @@ -11187,6 +11191,7 @@ static void test_view_insert_fields() " F7F8 AS F7F8, F6N4 AS F6N4, F5C8 AS F5C8, F9D8 AS F9D8" " from t1 T0001"); + bzero(bind, sizeof(bind)); for (i= 0; i < 11; i++) { l[i]= 20; @@ -11194,7 +11199,7 @@ static void test_view_insert_fields() bind[i].is_null= 0; bind[i].buffer= (char *)&parm[i]; - strcpy(parm[i], "1"); + strmov(parm[i], "1"); bind[i].buffer_length= 2; bind[i].length= &l[i]; } @@ -12707,6 +12712,7 @@ from t2);"); rc= mysql_query(mysql, "DROP VIEW v1"); myquery(rc); rc= mysql_query(mysql, "DROP TABLE t1, t2"); + mysql_free_result(res); myquery(rc); } @@ -12923,6 +12929,152 @@ static void test_bug9520() } +/* + We can't have more than one cursor open for a prepared statement. + Test re-executions of a PS with cursor; mysql_stmt_reset must close + the cursor attached to the statement, if there is one. +*/ + +static void test_bug9478() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + char a[6]; + ulong a_len; + int rc, i; + + myheader("test_bug9478"); + + mysql_query(mysql, "drop table if exists t1"); + mysql_query(mysql, "create table t1 (id integer not null primary key, " + " name varchar(20) not null)"); + rc= mysql_query(mysql, "insert into t1 (id, name) values " + " (1, 'aaa'), (2, 'bbb'), (3, 'ccc')"); + myquery(rc); + + stmt= open_cursor("select name from t1 where id=2"); + + bzero(bind, sizeof(bind)); + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer= (char*) a; + bind[0].buffer_length= sizeof(a); + bind[0].length= &a_len; + mysql_stmt_bind_result(stmt, bind); + + for (i= 0; i < 5; i++) + { + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + if (!opt_silent && i == 0) + printf("Fetched row: %s\n", a); + + /* + The query above is a one-row result set. Therefore, there is no + cursor associated with it, as the server won't bother with opening + a cursor for a one-row result set. The first row was read from the + server in the fetch above. But there is eof packet pending in the + network. mysql_stmt_execute will flush the packet and successfully + execute the statement. + */ + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + if (!opt_silent && i == 0) + printf("Fetched row: %s\n", a); + rc= mysql_stmt_fetch(stmt); + DIE_UNLESS(rc == MYSQL_NO_DATA); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + if (!opt_silent && i == 0) + printf("Fetched row: %s\n", a); + + rc= mysql_stmt_reset(stmt); + check_execute(stmt, rc); + rc= mysql_stmt_fetch(stmt); + DIE_UNLESS(rc && mysql_stmt_errno(stmt)); + if (!opt_silent && i == 0) + printf("Got error (as expected): %s\n", mysql_stmt_error(stmt)); + } + rc= mysql_stmt_close(stmt); + DIE_UNLESS(rc == 0); + + /* Test the case with a server side cursor */ + stmt= open_cursor("select name from t1"); + + mysql_stmt_bind_result(stmt, bind); + + for (i= 0; i < 5; i++) + { + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + if (!opt_silent && i == 0) + printf("Fetched row: %s\n", a); + /* + Although protocol-wise an attempt to execute a statement which + already has an open cursor associated with it will yield an error, + the client library behavior tested here is consistent with + the non-cursor execution scenario: mysql_stmt_execute will + silently close the cursor if necessary. + */ + { + char buff[9]; + bzero(buff, sizeof(buff)); + /* Fill in the execute packet */ + int4store(buff, stmt->stmt_id); + int4store(buff+5, 1); + rc= ((*mysql->methods->advanced_command)(mysql, COM_EXECUTE, buff, + sizeof(buff), 0,0,1) || + (*mysql->methods->read_query_result)(mysql)); + DIE_UNLESS(rc); + if (!opt_silent && i == 0) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + } + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + while (! (rc= mysql_stmt_fetch(stmt))) + { + if (!opt_silent && i == 0) + printf("Fetched row: %s\n", a); + } + DIE_UNLESS(rc == MYSQL_NO_DATA); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + if (!opt_silent && i == 0) + printf("Fetched row: %s\n", a); + + rc= mysql_stmt_reset(stmt); + check_execute(stmt, rc); + rc= mysql_stmt_fetch(stmt); + DIE_UNLESS(rc && mysql_stmt_errno(stmt)); + if (!opt_silent && i == 0) + printf("Got error (as expected): %s\n", mysql_stmt_error(stmt)); + } + + rc= mysql_stmt_close(stmt); + DIE_UNLESS(rc == 0); + + rc= mysql_query(mysql, "drop table t1"); + myquery(rc); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -13153,6 +13305,7 @@ static struct my_tests_st my_tests[]= { { "test_bug8880", test_bug8880 }, { "test_bug9159", test_bug9159 }, { "test_bug9520", test_bug9520 }, + { "test_bug9478", test_bug9478 }, { 0, 0 } }; From 362a340de34628ad38837a57ab85242540147de4 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 May 2005 15:56:04 +0500 Subject: [PATCH 25/63] fix (Bug #8295 and #8296: varchar and varbinary conversion) select, gis & gis-tree tests fails at the moment, but I will push this CS because it was tested before and I'm absolutely sure it's right. mysql-test/r/strict.result: fix (Bugs #8295 and #8296: varchar and varbinary conversion) mysql-test/r/type_blob.result: fix (Bugs #8295 and #8296: varchar and varbinary conversion) mysql-test/t/strict.test: fix (Bugs #8295 and #8296: varchar and varbinary conversion) sql/sql_table.cc: fix (Bugs #8295 and #8296: varchar and varbinary conversion): 1. fon't convert datatypes if it's strict mode; 2. better warning. --- mysql-test/r/strict.result | 5 +++++ mysql-test/r/type_blob.result | 2 +- mysql-test/t/strict.test | 10 ++++++++++ sql/sql_table.cc | 5 +++-- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index 7d1b6b67fd2..79be7a1923a 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -1232,3 +1232,8 @@ INSERT INTO t1 VALUES (DEFAULT,1); Warnings: Warning 1364 Field 'i' doesn't have a default value DROP TABLE t1; +set @@sql_mode='traditional'; +create table t1(a varchar(65537)); +ERROR 42000: Column length too big for column 'a' (max = 65535); use BLOB or TEXT instead +create table t1(a varbinary(65537)); +ERROR 42000: Column length too big for column 'a' (max = 65535); use BLOB or TEXT instead diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index 6f437ddbe0d..67a011231be 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -9,7 +9,7 @@ d mediumtext YES NULL e longtext YES NULL CREATE TABLE t2 (a char(255), b varbinary(70000), c varchar(70000000)); Warnings: -Note 1246 Converting column 'b' from VARCHAR to BLOB +Note 1246 Converting column 'b' from VARBINARY to BLOB Note 1246 Converting column 'c' from VARCHAR to TEXT CREATE TABLE t4 (c varchar(65530) character set utf8 not null); Warnings: diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test index 333ec40b1b9..298653b554a 100644 --- a/mysql-test/t/strict.test +++ b/mysql-test/t/strict.test @@ -1083,3 +1083,13 @@ INSERT INTO t1 SET j = 1, i = DEFAULT; INSERT INTO t1 SET j = 1, i = DEFAULT(i); INSERT INTO t1 VALUES (DEFAULT,1); DROP TABLE t1; + +# +# Bugs #8295 and #8296: varchar and varbinary conversion +# + +set @@sql_mode='traditional'; +--error 1074 +create table t1(a varchar(65537)); +--error 1074 +create table t1(a varbinary(65537)); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index bbe7c53147b..ad0a0baae2d 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1345,7 +1345,8 @@ static bool prepare_blob_field(THD *thd, create_field *sql_field) /* Convert long VARCHAR columns to TEXT or BLOB */ char warn_buff[MYSQL_ERRMSG_SIZE]; - if (sql_field->def) + if (sql_field->def || (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | + MODE_STRICT_ALL_TABLES))) { my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name, MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen); @@ -1354,7 +1355,7 @@ static bool prepare_blob_field(THD *thd, create_field *sql_field) sql_field->sql_type= FIELD_TYPE_BLOB; sql_field->flags|= BLOB_FLAG; sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name, - "VARCHAR", + (sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR", (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT"); push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT, warn_buff); From 7b36ac4819a02c25664a5f70f74262c3720eccab Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 May 2005 17:23:16 +0500 Subject: [PATCH 26/63] --default-extra-file handling code fix. mysys/default.c: if we check for error, we should set it. --- mysys/default.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysys/default.c b/mysys/default.c index 5afefa5463d..d35eb399b80 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -152,8 +152,8 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, } else if (defaults_extra_file) { - if (search_default_file_with_ext(func, func_ctx, "", "", - defaults_extra_file, 0) < 0) + if ((error= search_default_file_with_ext(func, func_ctx, "", "", + defaults_extra_file, 0)) < 0) goto err; /* Fatal error */ if (error > 0) { From 4acfc0b6111fb069cc718b6b87d821407190999e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 May 2005 17:37:38 +0300 Subject: [PATCH 27/63] Fixed bug 10465. --- mysql-test/r/type_newdecimal.result | 9 +++++++++ mysql-test/t/type_newdecimal.test | 10 ++++++++++ sql/field.cc | 7 ++++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 35bd8d73675..e775724ff54 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -876,3 +876,12 @@ SELECT * FROM t1; f1 f2 9999999999999999999999999999999999.00000000000000000000 0.00 DROP TABLE t1; +CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB; +INSERT INTO t1 (GRADE) VALUES (151),(252),(343); +SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300; +GRADE +252 +SELECT GRADE FROM t1 WHERE GRADE= 151; +GRADE +151 +DROP TABLE t1; diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 45a2034e8cc..78ad5ed2286 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -906,3 +906,13 @@ CREATE TABLE t1 (f1 DECIMAL (64,20), f2 DECIMAL(2,2)); INSERT INTO t1 VALUES (9999999999999999999999999999999999, 0); SELECT * FROM t1; DROP TABLE t1; + +# +# Bug #10465 +# + +CREATE TABLE t1 (GRADE DECIMAL(4) NOT NULL, PRIMARY KEY (GRADE)) ENGINE=INNODB; +INSERT INTO t1 (GRADE) VALUES (151),(252),(343); +SELECT GRADE FROM t1 WHERE GRADE > 160 AND GRADE < 300; +SELECT GRADE FROM t1 WHERE GRADE= 151; +DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index 78266441bda..34c5210b43c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8060,7 +8060,12 @@ void create_field::create_length_to_internal_length(void) } break; case MYSQL_TYPE_NEWDECIMAL: - key_length= pack_length= my_decimal_get_binary_size(length, decimals); + key_length= pack_length= + my_decimal_get_binary_size(my_decimal_length_to_precision(length, + decimals, + flags & + UNSIGNED_FLAG), + decimals); break; default: key_length= pack_length= calc_pack_length(sql_type, length); From cbbc4ff6a25accdd3e11a0e2719c2201d23a7b68 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 May 2005 17:49:34 +0200 Subject: [PATCH 28/63] If the system is under high load 'show full processlist' might report the process of the predecessing test case instead of the current test case. Shifting the command to the end of the current test case should avoid this problem. mysql-test/r/ps_grant.result: Updated result mysql-test/t/ps_grant.test: Shift ' show full processlist ' to the end of the test script --- mysql-test/r/ps_grant.result | 8 ++++---- mysql-test/t/ps_grant.test | 9 +++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/ps_grant.result b/mysql-test/r/ps_grant.result index 4c60bb03165..0787f30c643 100644 --- a/mysql-test/r/ps_grant.result +++ b/mysql-test/r/ps_grant.result @@ -1,7 +1,3 @@ -prepare stmt4 from ' show full processlist '; -execute stmt4; -Id User Host db Command Time State Info -number root localhost test Query time NULL show full processlist test_sequence ------ grant/revoke/drop affects a parallel session test ------ show grants for second_user@localhost ; @@ -79,3 +75,7 @@ commit ; show grants for second_user@localhost ; ERROR 42000: There is no such grant defined for user 'second_user' on host 'localhost' drop database mysqltest; +prepare stmt4 from ' show full processlist '; +execute stmt4; +Id User Host db Command Time State Info +number root localhost test Query time NULL show full processlist diff --git a/mysql-test/t/ps_grant.test b/mysql-test/t/ps_grant.test index 06613072824..d6448dd152a 100644 --- a/mysql-test/t/ps_grant.test +++ b/mysql-test/t/ps_grant.test @@ -1,10 +1,6 @@ # Can't test grants with embedded server -- source include/not_embedded.inc -# Tested here simply so it is not tested with embedded server -prepare stmt4 from ' show full processlist '; ---replace_column 1 number 6 time 3 localhost -execute stmt4; let $type= 'MYISAM' ; @@ -116,4 +112,9 @@ show grants for second_user@localhost ; drop database mysqltest; +# Tested here simply so it is not tested with embedded server +prepare stmt4 from ' show full processlist '; +--replace_column 1 number 6 time 3 localhost +execute stmt4; + From e3cab92054b21e5d0e6a61e3611c50970bd40442 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 11:35:02 +0400 Subject: [PATCH 29/63] Add myself to the list of users who don't automatically check out all version controlled files (should speed up bk citool) --- BitKeeper/etc/config | 1 + 1 file changed, 1 insertion(+) diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config index c609fcdbd49..1ac24031dca 100644 --- a/BitKeeper/etc/config +++ b/BitKeeper/etc/config @@ -69,6 +69,7 @@ pager: hours: [serg:]checkout:get [arjen:]checkout:get +[kostja:]checkout:get [nick:]checkout:get checkout:edit eoln:unix From 7c441dd1157c8ad525babb3fbbd43daff86a50ec Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 11:11:50 +0300 Subject: [PATCH 30/63] Change create_field->offset to store offset from start of fields, independent of null bits. Count null_bits separately from field offsets and adjust them in case of primary key parts. (Previously a CREATE TABLE with a lot of null fields that was part of a primary key caused MySQL to wrongly count the number of bytes needed to store null bits) This is a more complete bug fix for #6236 mysql-test/r/alter_table.result: More test for bug #6236 (CREATE TABLE didn't properly count not null columns for primary keys) mysql-test/t/alter_table.test: More test for bug #6236 (CREATE TABLE didn't properly count not null columns for primary keys) sql/handler.h: Add counter for null fields sql/sql_table.cc: Change create_field->offset to store offset from start of fields, independent of null bits. Count null_bits separately from field offsets and adjust them in case of primary key parts. sql/unireg.cc: Change create_field->offset to store offset from start of fields, independent of null bits. Count null_bits separately from field offsets and adjust them in case of primary key parts. --- mysql-test/r/alter_table.result | 16 +++++++ mysql-test/t/alter_table.test | 17 +++++++ sql/handler.h | 1 + sql/sql_table.cc | 37 ++++++--------- sql/unireg.cc | 83 ++++++++++++++++++++------------- 5 files changed, 98 insertions(+), 56 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 80d3ef5e0a5..19d2ca4d6ed 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -406,3 +406,19 @@ t2 CREATE TABLE `t2` ( PRIMARY KEY (`a`) ) TYPE=MRG_MyISAM UNION=(t1) drop table if exists t1, t2; +create table t1 (a int, b int, c int, d int, e int, f int, g int, h int,i int, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM; +insert into t1 (a) values(1); +show table status like 't1'; +Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Create_options Comment +t1 MyISAM Fixed 1 37 37 X X X X X X X X +alter table t1 modify a int; +show table status like 't1'; +Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Create_options Comment +t1 MyISAM Fixed 1 37 37 X X X X X X X X +drop table t1; +create table t1 (a int not null, b int not null, c int not null, d int not null, e int not null, f int not null, g int not null, h int not null,i int not null, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM; +insert into t1 (a) values(1); +show table status like 't1'; +Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Create_options Comment +t1 MyISAM Fixed 1 37 37 X X X X X X X X +drop table t1; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index c69f9aabae6..af0ec2bca16 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -267,3 +267,20 @@ flush tables; alter table t1 modify a varchar(10) not null; show create table t2; drop table if exists t1, t2; + +# The following is also part of bug #6236 (CREATE TABLE didn't properly count +# not null columns for primary keys) + +create table t1 (a int, b int, c int, d int, e int, f int, g int, h int,i int, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM; +insert into t1 (a) values(1); +--replace_column 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X +show table status like 't1'; +alter table t1 modify a int; +--replace_column 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X +show table status like 't1'; +drop table t1; +create table t1 (a int not null, b int not null, c int not null, d int not null, e int not null, f int not null, g int not null, h int not null,i int not null, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM; +insert into t1 (a) values(1); +--replace_column 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X +show table status like 't1'; +drop table t1; diff --git a/sql/handler.h b/sql/handler.h index ac00050b777..e52164a871a 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -164,6 +164,7 @@ typedef struct st_ha_create_information SQL_LIST merge_list; enum db_type db_type; enum row_type row_type; + uint null_bits; /* NULL bits at start of record */ uint options; /* OR of HA_CREATE_ options */ uint raid_type,raid_chunks; uint merge_insert_method; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e065e5dfc58..e275f902abd 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -363,7 +363,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, create_field *sql_field,*dup_field; int error= -1; uint db_options,field,null_fields,blob_columns; - ulong pos; + ulong record_offset; KEY *key_info,*key_info_buffer; KEY_PART_INFO *key_part_info; int auto_increment=0; @@ -418,10 +418,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, } it2.rewind(); } - /* If fixed row records, we need one bit to check for deleted rows */ - if (!(db_options & HA_OPTION_PACK_RECORD)) - null_fields++; - pos=(null_fields+7)/8; + + /* record_offset will be increased with 'length-of-null-bits' later */ + record_offset= 0; it.rewind(); while ((sql_field=it++)) @@ -478,10 +477,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, } if (!(sql_field->flags & NOT_NULL_FLAG)) sql_field->pack_flag|=FIELDFLAG_MAYBE_NULL; - sql_field->offset= pos; + sql_field->offset= record_offset; if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) auto_increment++; - pos+=sql_field->pack_length; + record_offset+= sql_field->pack_length; } if (auto_increment > 1) { @@ -578,11 +577,12 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, column->field_name); DBUG_RETURN(-1); } - /* for fulltext keys keyseg length is 1 for blobs (it's ignored in - ft code anyway, and 0 (set to column width later) for char's. - it has to be correct col width for char's, as char data are not - prefixed with length (unlike blobs, where ft code takes data length - from a data prefix, ignoring column->length). + /* + for fulltext keys keyseg length is 1 for blobs (it's ignored in + ft code anyway, and 0 (set to column width later) for char's. + it has to be correct col width for char's, as char data are not + prefixed with length (unlike blobs, where ft code takes data length + from a data prefix, ignoring column->length). */ if (key->type == Key::FULLTEXT) column->length=test(f_is_blob(sql_field->pack_flag)); @@ -609,6 +609,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, /* Implicitly set primary key fields to NOT NULL for ISO conf. */ sql_field->flags|= NOT_NULL_FLAG; sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL; + null_fields--; } else key_info->flags|= HA_NULL_PART_KEY; @@ -765,6 +766,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, if (thd->sql_mode & MODE_NO_DIR_IN_CREATE) create_info->data_file_name= create_info->index_file_name= 0; create_info->table_options=db_options; + create_info->null_bits= null_fields; if (rea_create_table(path, create_info, fields, key_count, key_info_buffer)) @@ -1829,17 +1831,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, cfield->pack_length <= key_part_length)) key_part_length=0; // Use whole field } - if (!(cfield->flags & NOT_NULL_FLAG)) - { - if (key_type == Key::PRIMARY) - { - /* Implicitly set primary key fields to NOT NULL for ISO conf. */ - cfield->flags|= NOT_NULL_FLAG; - cfield->pack_flag&= ~FIELDFLAG_MAYBE_NULL; - } - else - key_info->flags|= HA_NULL_PART_KEY; - } key_parts.push_back(new key_part_spec(cfield->field_name, key_part_length)); } diff --git a/sql/unireg.cc b/sql/unireg.cc index 218ea6b5b8d..f81370539c6 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -32,18 +32,21 @@ static uchar * pack_screens(List &create_fields, uint *info_length, uint *screens, bool small_file); -static uint pack_keys(uchar *keybuff,uint key_count, KEY *key_info); +static uint pack_keys(uchar *keybuff,uint key_count, KEY *key_info, + ulong data_offset); static bool pack_header(uchar *forminfo, enum db_type table_type, List &create_fields, uint info_length, uint screens, uint table_options, - handler *file); + ulong data_offset, handler *file); static uint get_interval_id(uint *int_count,List &create_fields, create_field *last_field); -static bool pack_fields(File file, List &create_fields); +static bool pack_fields(File file, List &create_fields, + ulong data_offset); static bool make_empty_rec(int file, enum db_type table_type, uint table_options, List &create_fields, - uint reclength,uint null_fields); + uint reclength, uint null_fields, + ulong data_offset); int rea_create_table(my_string file_name, @@ -53,7 +56,7 @@ int rea_create_table(my_string file_name, { uint reclength,info_length,screens,key_info_length,maxlength,null_fields; File file; - ulong filepos; + ulong filepos, data_offset; uchar fileinfo[64],forminfo[288],*keybuff; TYPELIB formnames; uchar *screen_buff; @@ -64,8 +67,15 @@ int rea_create_table(my_string file_name, if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0))) DBUG_RETURN(1); db_file=get_new_handler((TABLE*) 0, create_info->db_type); + + /* If fixed row records, we need one bit to check for deleted rows */ + if (!(create_info->table_options & HA_OPTION_PACK_RECORD)) + create_info->null_bits++; + data_offset= (create_info->null_bits + 7) / 8; + if (pack_header(forminfo, create_info->db_type,create_fields,info_length, - screens, create_info->table_options, db_file)) + screens, create_info->table_options, + data_offset, db_file)) { NET *net=my_pthread_getspecific_ptr(NET*,THR_NET); my_free((gptr) screen_buff,MYF(0)); @@ -77,7 +87,7 @@ int rea_create_table(my_string file_name, if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,1))) DBUG_RETURN(1); if (pack_header(forminfo, create_info->db_type, create_fields,info_length, - screens, create_info->table_options, db_file)) + screens, create_info->table_options, data_offset, db_file)) { my_free((gptr) screen_buff,MYF(0)); DBUG_RETURN(1); @@ -95,7 +105,7 @@ int rea_create_table(my_string file_name, uint key_buff_length=uint2korr(fileinfo+14); keybuff=(uchar*) my_alloca(key_buff_length); - key_info_length=pack_keys(keybuff,keys,key_info); + key_info_length= pack_keys(keybuff, keys, key_info, data_offset); VOID(get_form_pos(file,fileinfo,&formnames)); if (!(filepos=make_new_entry(file,fileinfo,&formnames,""))) goto err; @@ -117,13 +127,13 @@ int rea_create_table(my_string file_name, (ulong) uint2korr(fileinfo+6)+ (ulong) key_buff_length, MY_SEEK_SET,MYF(0))); if (make_empty_rec(file,create_info->db_type,create_info->table_options, - create_fields,reclength,null_fields)) + create_fields,reclength, null_fields, data_offset)) goto err; VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0))); if (my_write(file,(byte*) forminfo,288,MYF_RW) || my_write(file,(byte*) screen_buff,info_length,MYF_RW) || - pack_fields(file,create_fields)) + pack_fields(file, create_fields, data_offset)) goto err; #ifdef HAVE_CRYPTED_FRM @@ -248,7 +258,8 @@ static uchar * pack_screens(List &create_fields, /* Pack keyinfo and keynames to keybuff for save in form-file. */ -static uint pack_keys(uchar *keybuff,uint key_count,KEY *keyinfo) +static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo, + ulong data_offset) { uint key_parts,length; uchar *pos, *keyname_pos, *key_alg_pos; @@ -273,10 +284,13 @@ static uint pack_keys(uchar *keybuff,uint key_count,KEY *keyinfo) key_part++) { - DBUG_PRINT("loop",("field: %d startpos: %ld length: %ld", - key_part->fieldnr,key_part->offset,key_part->length)); + uint offset; + DBUG_PRINT("loop",("field: %d startpos: %lu length: %ld", + key_part->fieldnr, key_part->offset + data_offset, + key_part->length)); int2store(pos,key_part->fieldnr+1+FIELD_NAME_USED); - int2store(pos+2,key_part->offset+1); + offset= (uint) (key_part->offset+data_offset+1); + int2store(pos+2, offset); pos[4]=0; // Sort order int2store(pos+5,key_part->key_type); int2store(pos+7,key_part->length); @@ -316,8 +330,8 @@ static uint pack_keys(uchar *keybuff,uint key_count,KEY *keyinfo) static bool pack_header(uchar *forminfo, enum db_type table_type, List &create_fields, - uint info_length, uint screens,uint table_options, - handler *file) + uint info_length, uint screens, uint table_options, + ulong data_offset, handler *file) { uint length,int_count,int_length,no_empty, int_parts, time_stamp_pos,null_fields; @@ -351,10 +365,10 @@ static bool pack_header(uchar *forminfo, enum db_type table_type, if ((MTYP_TYPENR(field->unireg_check) == Field::TIMESTAMP_FIELD || f_packtype(field->pack_flag) == (int) FIELD_TYPE_TIMESTAMP) && !time_stamp_pos) - time_stamp_pos=(int) field->offset+1; + time_stamp_pos= (uint) field->offset+ (uint) data_offset + 1; length=field->pack_length; - if ((int) field->offset+length > reclength) - reclength=(int) field->offset+length; + if ((uint) field->offset+ (uint) data_offset+ length > reclength) + reclength=(uint) (field->offset+ data_offset + length); n_length+= (ulong) strlen(field->field_name)+1; field->interval_id=0; if (field->interval) @@ -440,7 +454,8 @@ static uint get_interval_id(uint *int_count,List &create_fields, /* Save fields, fieldnames and intervals */ -static bool pack_fields(File file,List &create_fields) +static bool pack_fields(File file, List &create_fields, + ulong data_offset) { reg2 uint i; uint int_count; @@ -455,11 +470,13 @@ static bool pack_fields(File file,List &create_fields) int_count=0; while ((field=it++)) { + uint recpos; buff[0]= (uchar) field->row; buff[1]= (uchar) field->col; buff[2]= (uchar) field->sc_length; buff[3]= (uchar) field->length; - uint recpos=(uint) field->offset+1; + /* The +1 is here becasue the col offset in .frm file have offset 1 */ + recpos= field->offset+1 + (uint) data_offset; int2store(buff+4,recpos); int2store(buff+6,field->pack_flag); int2store(buff+8,field->unireg_check); @@ -519,11 +536,12 @@ static bool pack_fields(File file,List &create_fields) static bool make_empty_rec(File file,enum db_type table_type, uint table_options, List &create_fields, - uint reclength, uint null_fields) + uint reclength, uint null_fields, + ulong data_offset) { int error; Field::utype type; - uint firstpos,null_count,null_length; + uint firstpos,null_count; uchar *buff,*null_pos; TABLE table; create_field *field; @@ -547,17 +565,16 @@ static bool make_empty_rec(File file,enum db_type table_type, firstpos=reclength; null_count=0; if (!(table_options & HA_OPTION_PACK_RECORD)) - { - null_fields++; // Need one bit for delete mark - null_count++; - } - bfill(buff,(null_length=(null_fields+7)/8),255); + null_count++; // Need one bit for delete mark + DBUG_ASSERT(data_offset == ((null_fields + null_count + 7) / 8)); + bfill(buff, (uint) data_offset, 255); null_pos=buff; List_iterator it(create_fields); while ((field=it++)) { - Field *regfield=make_field((char*) buff+field->offset,field->length, + Field *regfield=make_field((char*) buff+field->offset + data_offset, + field->length, field->flags & NOT_NULL_FLAG ? 0: null_pos+null_count/8, 1 << (null_count & 7), @@ -570,9 +587,9 @@ static bool make_empty_rec(File file,enum db_type table_type, if (!(field->flags & NOT_NULL_FLAG)) null_count++; - if ((uint) field->offset < firstpos && + if ((uint) (field->offset + data_offset) < firstpos && regfield->type() != FIELD_TYPE_NULL) - firstpos= field->offset; + firstpos= field->offset + data_offset; type= (Field::utype) MTYP_TYPENR(field->unireg_check); @@ -596,8 +613,8 @@ static bool make_empty_rec(File file,enum db_type table_type, } /* Fill not used startpos */ - bfill((byte*) buff+null_length,firstpos-null_length,255); - error=(int) my_write(file,(byte*) buff,(uint) reclength,MYF_RW); + bfill((byte*) buff+data_offset, firstpos- (uint) data_offset, 255); + error=(int) my_write(file,(byte*) buff, (uint) reclength,MYF_RW); my_free((gptr) buff,MYF(MY_FAE)); delete handler; DBUG_RETURN(error); From b21cf962e381300def1bb91d33f6ab411c0c0cc4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 12:08:08 +0300 Subject: [PATCH 31/63] concurrent-insert can now be set to 2 for concurrent inserts when there is holes in the data file myisam_max_extra_sort_file_size is depricated Ensure that myisam_data_pointer_size is honoured when creating new MyISAM files Changed default value of myisam_data_pointer_size from 4 to 6 to get rid of 'table-is-full' errors include/myisam.h: Change type of myisam_block_size and myisam_concurrent_insert to make them changeable in mysqld.cc Removed not used varaible myisam_max_extra_temp_length include/thr_lock.h: Added extra parameter to get_status myisam/mi_create.c: Ensure that myisam_data_pointer_size is honoured myisam/mi_dynrec.c: If 'append_insert_at_end' is set, only write at end of myisam record file myisam/mi_locking.c: Add extra argument to 'mi_get_status' to allow thr_lock to signal that we want to do a concurrent insert If this is used, we will append new insert rows at end of data file. Change mi_check_status() to allow concurrent_inserts even if there are holes in the file when myisam_concurent_insert=2 myisam/mi_static.c: Change behavior of myisam_concurrent_insert so that setting this to 2 allows inserts even if there is a hole in the data file. Default value is 2 for MyISAM direct usage but will be set to 1 (old default) by mysqld.cc myisam/mi_statrec.c: If 'append_insert_at_end' is set, only write at end of myisam record file myisam/mi_write.c: If 'append_insert_at_end' is set, only write at end of myisam record file myisam/myisamdef.h: Support for insert-at-end even if there is holes in data file mysql-test/r/gis-rtree.result: Test result changed because default value for myisam_data_pointer_size is changed from 4 -> 6 mysql-test/r/group_min_max.result: Test result changed because default value for myisam_data_pointer_size is changed from 4 -> 6 mysql-test/r/index_merge.result: Test result changed because default value for myisam_data_pointer_size is changed from 4 -> 6 mysql-test/r/index_merge_ror.result: Test result changed because default value for myisam_data_pointer_size is changed from 4 -> 6 mysql-test/r/merge.result: Test result changed because default value for myisam_data_pointer_size is changed from 4 -> 6 mysql-test/r/myisam.result: Test of concurrent_insert=2 mysql-test/r/null.result: Test result changed because default value for myisam_data_pointer_size is changed from 4 -> 6 mysql-test/r/preload.result: Test result changed because default value for myisam_data_pointer_size is changed from 4 -> 6 mysql-test/r/ps_1general.result: Test result changed because default value for myisam_data_pointer_size is changed from 4 -> 6 mysql-test/r/range.result: Test result changed because default value for myisam_data_pointer_size is changed from 4 -> 6 mysql-test/r/variables.result: concurrent_insert is now a integer, not a boolean myisam_extra_sort_file_size is deleted mysql-test/r/view.result: Test result changed because default value for myisam_data_pointer_size is changed from 4 -> 6 mysql-test/t/index_merge.test: Test result changed because default value for myisam_data_pointer_size is changed from 4 -> 6 mysql-test/t/myisam.test: Test of concurrent_insert=2 mysql-test/t/ps_1general.test: Drop test table mysql-test/t/variables.test: concurrent_insert is now a integer, not a boolean myisam_extra_sort_file_size is deleted mysql-test/t/view.test: Drop tables that may be left from previous tests mysys/thr_lock.c: Extra paramter to get_status to signal if concurrent_insert was used sql/mysqld.cc: concurrent-insert can now be set to 2 for concurrent inserts when there is holes in the data file myisam_max_extra_sort_file_size is depricated sql/set_var.cc: concurrent-insert is now an integer, not a bool myisam_max_extra_sort_file_size is deleted --- include/myisam.h | 6 +-- include/thr_lock.h | 4 +- myisam/mi_create.c | 7 ++-- myisam/mi_dynrec.c | 12 ++++-- myisam/mi_locking.c | 45 +++++++++++++++++++---- myisam/mi_static.c | 7 ++-- myisam/mi_statrec.c | 3 +- myisam/mi_write.c | 3 +- myisam/myisamdef.h | 3 +- mysql-test/r/gis-rtree.result | 2 +- mysql-test/r/group_min_max.result | 26 ++++++------- mysql-test/r/index_merge.result | 26 ++++++------- mysql-test/r/index_merge_ror.result | 54 +++++++++++++-------------- mysql-test/r/merge.result | 2 +- mysql-test/r/myisam.result | 57 +++++++++++++++++++++++++++++ mysql-test/r/null.result | 4 +- mysql-test/r/preload.result | 36 +++++++++--------- mysql-test/r/ps_1general.result | 6 +-- mysql-test/r/range.result | 8 ++-- mysql-test/r/variables.result | 27 ++++---------- mysql-test/r/view.result | 4 +- mysql-test/t/index_merge.test | 2 +- mysql-test/t/myisam.test | 54 +++++++++++++++++++++++++++ mysql-test/t/ps_1general.test | 2 +- mysql-test/t/variables.test | 14 ++----- mysql-test/t/view.test | 2 +- mysys/thr_lock.c | 28 +++++++++----- sql/mysqld.cc | 22 +++++++---- sql/set_var.cc | 18 +-------- 29 files changed, 306 insertions(+), 178 deletions(-) diff --git a/include/myisam.h b/include/myisam.h index e0eb8715aef..7d3f0e0c801 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -190,10 +190,10 @@ typedef struct st_columndef /* column information */ typedef void (* invalidator_by_filename)(const char * filename); extern my_string myisam_log_filename; /* Name of logfile */ -extern uint myisam_block_size; +extern ulong myisam_block_size; +extern ulong myisam_concurrent_insert; extern my_bool myisam_flush,myisam_delay_key_write,myisam_single_user; -extern my_bool myisam_concurrent_insert; -extern my_off_t myisam_max_temp_length,myisam_max_extra_temp_length; +extern my_off_t myisam_max_temp_length; extern ulong myisam_bulk_insert_tree_size, myisam_data_pointer_size; /* Prototypes for myisam-functions */ diff --git a/include/thr_lock.h b/include/thr_lock.h index 947b17bf2b6..dc4f9968cb7 100644 --- a/include/thr_lock.h +++ b/include/thr_lock.h @@ -88,10 +88,10 @@ typedef struct st_thr_lock { struct st_lock_list read; struct st_lock_list write_wait; struct st_lock_list write; -/* write_lock_count is incremented for write locks and reset on read locks */ + /* write_lock_count is incremented for write locks and reset on read locks */ ulong write_lock_count; uint read_no_write_count; - void (*get_status)(void*); /* When one gets a lock */ + void (*get_status)(void*, int); /* When one gets a lock */ void (*copy_status)(void*,void*); void (*update_status)(void*); /* Before release of write */ my_bool (*check_status)(void *); diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 8635d6bcf36..12b03e65baa 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -191,11 +191,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD)); min_pack_length+=packed; - if (!ci->data_file_length) + if (!ci->data_file_length && ci->max_rows) { - if (ci->max_rows == 0 || pack_reclength == INT_MAX32) - ci->data_file_length= INT_MAX32-1; /* Should be enough */ - else if ((~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength) + if (pack_reclength == INT_MAX32 || + (~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength) ci->data_file_length= ~(ulonglong) 0; else ci->data_file_length=(ulonglong) ci->max_rows*pack_reclength; diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index 3a4dafade23..8de500a7351 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -149,7 +149,9 @@ static int write_dynamic_record(MI_INFO *info, const byte *record, { if (_mi_find_writepos(info,reclength,&filepos,&length)) goto err; - if (_mi_write_part_record(info,filepos,length,info->s->state.dellink, + if (_mi_write_part_record(info,filepos,length, + (info->append_insert_at_end ? + HA_OFFSET_ERROR : info->s->state.dellink), (byte**) &record,&reclength,&flag)) goto err; } while (reclength); @@ -171,7 +173,8 @@ static int _mi_find_writepos(MI_INFO *info, ulong tmp; DBUG_ENTER("_mi_find_writepos"); - if (info->s->state.dellink != HA_OFFSET_ERROR) + if (info->s->state.dellink != HA_OFFSET_ERROR && + !info->append_insert_at_end) { /* Deleted blocks exists; Get last used block */ *filepos=info->s->state.dellink; @@ -420,8 +423,9 @@ int _mi_write_part_record(MI_INFO *info, else if (length-long_block < *reclength+4) { /* To short block */ if (next_filepos == HA_OFFSET_ERROR) - next_filepos=info->s->state.dellink != HA_OFFSET_ERROR ? - info->s->state.dellink : info->state->data_file_length; + next_filepos= (info->s->state.dellink != HA_OFFSET_ERROR && + !info->append_insert_at_end ? + info->s->state.dellink : info->state->data_file_length); if (*flag == 0) /* First block */ { if (*reclength > MI_MAX_BLOCK_LENGTH) diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index 789d74680ef..8d48c5242e5 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -238,13 +238,24 @@ int mi_lock_database(MI_INFO *info, int lock_type) The following functions are called by thr_lock() in threaded applications ****************************************************************************/ -void mi_get_status(void* param) +/* + Create a copy of the current status for the table + + SYNOPSIS + mi_get_status() + param Pointer to Myisam handler + concurrent_insert Set to 1 if we are going to do concurrent inserts + (THR_WRITE_CONCURRENT_INSERT was used) +*/ + +void mi_get_status(void* param, int concurrent_insert) { MI_INFO *info=(MI_INFO*) param; DBUG_ENTER("mi_get_status"); - DBUG_PRINT("info",("key_file: %ld data_file: %ld", + DBUG_PRINT("info",("key_file: %ld data_file: %ld concurrent_insert: %d", (long) info->s->state.state.key_file_length, - (long) info->s->state.state.data_file_length)); + (long) info->s->state.state.data_file_length, + concurrent_insert)); #ifndef DBUG_OFF if (info->state->key_file_length > info->s->state.state.key_file_length || info->state->data_file_length > info->s->state.state.data_file_length) @@ -254,9 +265,11 @@ void mi_get_status(void* param) #endif info->save_state=info->s->state.state; info->state= &info->save_state; + info->append_insert_at_end= concurrent_insert; DBUG_VOID_RETURN; } + void mi_update_status(void* param) { MI_INFO *info=(MI_INFO*) param; @@ -281,6 +294,7 @@ void mi_update_status(void* param) info->s->state.state= *info->state; info->state= &info->s->state.state; } + info->append_insert_at_end= 0; /* We have to flush the write cache here as other threads may start @@ -307,20 +321,37 @@ void mi_copy_status(void* to,void *from) Check if should allow concurrent inserts IMPLEMENTATION - Don't allow concurrent inserts if we have a hole in the table. + Allow concurrent inserts if we don't have a hole in the table or + if there is no active write lock and there is active read locks and + myisam_concurrent_insert == 2. In this last case the new + row('s) are inserted at end of file instead of filling up the hole. + + The last case is to allow one to inserts into a heavily read-used table + even if there is holes. NOTES - Rtree indexes are disabled in mi_open() + If there is a an rtree indexes in the table, concurrent inserts are + disabled in mi_open() RETURN 0 ok to use concurrent inserts 1 not ok */ -my_bool mi_check_status(void* param) +my_bool mi_check_status(void *param) { MI_INFO *info=(MI_INFO*) param; - return (my_bool) (info->s->state.dellink != HA_OFFSET_ERROR); + /* + The test for w_locks == 1 is here because this thread has already done an + external lock (in other words: w_locks == 1 means no other threads has + a write lock) + */ + DBUG_PRINT("info",("dellink: %ld r_locks: %u w_locks: %u", + (long) info->s->state.dellink, (uint) info->s->r_locks, + (uint) info->s->w_locks)); + return (my_bool) !(info->s->state.dellink == HA_OFFSET_ERROR || + (myisam_concurrent_insert == 2 && info->s->r_locks && + info->s->w_locks == 1)); } diff --git a/myisam/mi_static.c b/myisam/mi_static.c index f41aeff8453..4c9d814f7d6 100644 --- a/myisam/mi_static.c +++ b/myisam/mi_static.c @@ -31,14 +31,13 @@ uchar NEAR myisam_pack_file_magic[]= my_string myisam_log_filename=(char*) "myisam.log"; File myisam_log_file= -1; uint myisam_quick_table_bits=9; -uint myisam_block_size=MI_KEY_BLOCK_LENGTH; /* Best by test */ +ulong myisam_block_size= MI_KEY_BLOCK_LENGTH; /* Best by test */ my_bool myisam_flush=0, myisam_delay_key_write=0, myisam_single_user=0; #if defined(THREAD) && !defined(DONT_USE_RW_LOCKS) -my_bool myisam_concurrent_insert=1; +ulong myisam_concurrent_insert= 2; #else -my_bool myisam_concurrent_insert=0; +ulong myisam_concurrent_insert= 0; #endif -my_off_t myisam_max_extra_temp_length= (my_off_t)MI_MAX_TEMP_LENGTH; my_off_t myisam_max_temp_length= MAX_FILE_SIZE; ulong myisam_bulk_insert_tree_size=8192*1024; ulong myisam_data_pointer_size=4; diff --git a/myisam/mi_statrec.c b/myisam/mi_statrec.c index 8f5cde45e24..42352f63c66 100644 --- a/myisam/mi_statrec.c +++ b/myisam/mi_statrec.c @@ -23,7 +23,8 @@ int _mi_write_static_record(MI_INFO *info, const byte *record) { uchar temp[8]; /* max pointer length */ - if (info->s->state.dellink != HA_OFFSET_ERROR) + if (info->s->state.dellink != HA_OFFSET_ERROR && + !info->append_insert_at_end) { my_off_t filepos=info->s->state.dellink; info->rec_cache.seek_not_done=1; /* We have done a seek */ diff --git a/myisam/mi_write.c b/myisam/mi_write.c index 5d7e245c58f..dd062b79769 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -67,7 +67,8 @@ int mi_write(MI_INFO *info, byte *record) MYF(MY_SEEK_NOT_DONE) | info->lock_wait)) goto err; #endif - filepos= ((share->state.dellink != HA_OFFSET_ERROR) ? + filepos= ((share->state.dellink != HA_OFFSET_ERROR && + !info->append_insert_at_end) ? share->state.dellink : info->state->data_file_length); diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index a2d3dedf6df..5688b377d3d 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -271,6 +271,7 @@ struct st_myisam_info { uint preload_buff_size; /* When preloading indexes */ myf lock_wait; /* is 0 or MY_DONT_WAIT */ my_bool was_locked; /* Was locked in panic */ + my_bool append_insert_at_end; /* Set if concurrent insert */ my_bool quick_mode; my_bool page_changed; /* If info->buff can't be used for rnext */ my_bool buff_used; /* If info->buff has to be reread for rnext */ @@ -702,7 +703,7 @@ int _mi_cmp_dynamic_unique(MI_INFO *info, MI_UNIQUEDEF *def, const byte *record, my_off_t pos); int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b, my_bool null_are_equal); -void mi_get_status(void* param); +void mi_get_status(void* param, int concurrent_insert); void mi_update_status(void* param); void mi_copy_status(void* to,void *from); my_bool mi_check_status(void* param); diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result index 73cde35993e..22447e829a9 100644 --- a/mysql-test/r/gis-rtree.result +++ b/mysql-test/r/gis-rtree.result @@ -167,7 +167,7 @@ count(*) 150 EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))')); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range g g 32 NULL 7 Using where +1 SIMPLE t1 range g g 32 NULL 8 Using where SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))')); fid AsText(g) 1 LINESTRING(150 150,150 150) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 766e43b2299..8260bab2f97 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -287,7 +287,7 @@ b i421 l421 b m422 p422 explain select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 9 Using where; Using index for group-by +1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 Using where; Using index for group-by @@ -317,22 +317,22 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 Using where; Using index for group-by explain select a1, max(c) from t1 where a1 in ('a','b','d') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 13 Using where; Using index for group-by +1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 Using where; Using index for group-by explain select a1,a2,b, max(c) from t2 where a1 < 'd' group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 12 Using where; Using index for group-by +1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 14 Using where; Using index for group-by explain select a1,a2,b,min(c),max(c) from t2 where a1 < 'd' group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 12 Using where; Using index for group-by +1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 14 Using where; Using index for group-by explain select a1,a2,b,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 16 Using where; Using index for group-by explain select a1,a2,b, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 18 Using where; Using index for group-by +1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 17 Using where; Using index for group-by explain select a1, max(c) from t2 where a1 >= 'c' or a1 < 'b' group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 18 Using where; Using index for group-by +1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 17 Using where; Using index for group-by explain select a1,a2,b,min(c),max(c) from t2 where a1 >= 'c' or a2 < 'b' group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 21 Using where; Using index for group-by @@ -353,7 +353,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 16 Using where; Using index for group-by explain select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 13 Using where; Using index for group-by +1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 14 Using where; Using index for group-by select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b; a1 a2 b min(c) max(c) a a a a111 d111 @@ -1398,10 +1398,10 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range NULL idx_t2_1 163 NULL 21 Using where; Using index for group-by explain select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 17 Using where; Using index for group-by +1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 16 Using where; Using index for group-by explain select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122') or (c < 'h112') or (c = 'c111')) group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 17 Using where; Using index for group-by +1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL 16 Using where; Using index for group-by explain select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL 16 Using where; Using index for group-by @@ -1824,16 +1824,16 @@ ord(a1) + count(distinct a1,a2,b) 104 explain select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 9 Using where; Using index for group-by +1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by explain select concat(a1,min(c)),b from t1 where a1 < 'd' group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 9 Using where; Using index for group-by +1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by explain select concat(a1,min(c)),b,max(c) from t1 where a1 < 'd' group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 9 Using where; Using index for group-by +1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by explain select concat(a1,a2),b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 9 Using where; Using index for group-by +1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 10 Using where; Using index for group-by explain select concat(ord(min(b)),ord(max(b))),min(b),max(b) from t1 group by a1,a2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range NULL idx_t1_1 130 NULL 9 Using index for group-by diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result index 693cc63ba9e..8f5db550d8b 100644 --- a/mysql-test/r/index_merge.result +++ b/mysql-test/r/index_merge.result @@ -17,11 +17,11 @@ Table Op Msg_type Msg_text test.t0 analyze status OK explain select * from t0 where key1 < 3 or key1 > 1020; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t0 range i1 i1 4 NULL 55 Using where +1 SIMPLE t0 range i1 i1 4 NULL 78 Using where explain select * from t0 where key1 < 3 or key2 > 1020; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 31 Using sort_union(i1,i2); Using where +1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 45 Using sort_union(i1,i2); Using where select * from t0 where key1 < 3 or key2 > 1020; key1 key2 key3 key4 key5 key6 key7 key8 1 1 1 1 1 1 1 1023 @@ -36,7 +36,7 @@ id select_type table type possible_keys key key_len ref rows Extra explain select * from t0 where (key1 > 30 and key1<35) or (key2 >32 and key2 < 40); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 9 Using sort_union(i1,i2); Using where +1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 11 Using sort_union(i1,i2); Using where select * from t0 where (key1 > 30 and key1<35) or (key2 >32 and key2 < 40); key1 key2 key3 key4 key5 key6 key7 key8 31 31 31 31 31 31 31 993 @@ -90,7 +90,7 @@ id select_type table type possible_keys key key_len ref rows Extra explain select key1 from t0 where (key1 <=> null) or (key1 < 5) or (key3=10) or (key4 <=> null); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t0 index_merge i1,i3,i4 i1,i3 4,4 NULL 5 Using sort_union(i1,i3); Using where +1 SIMPLE t0 index_merge i1,i3,i4 i1,i3 4,4 NULL 6 Using sort_union(i1,i3); Using where explain select * from t0 where (key1 < 3 or key2 < 3) and (key3 < 4 or key4 < 4) and (key5 < 5 or key6 < 5); id select_type table type possible_keys key key_len ref rows Extra @@ -113,7 +113,7 @@ id select_type table type possible_keys key key_len ref rows Extra explain select * from t0 where (key1 < 3 or key2 < 3) and (key3 < 100); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t0 range i1,i2,i3 i3 4 NULL 96 Using where +1 SIMPLE t0 range i1,i2,i3 i3 4 NULL 95 Using where explain select * from t0 where (key1 < 3 or key2 < 3) and (key3 < 1000); id select_type table type possible_keys key key_len ref rows Extra @@ -152,7 +152,7 @@ explain select * from t0 where or ((key7 <7 or key8 < 4) and (key5 < 5 or key6 < 6)); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t0 index_merge i1,i2,i3,i5,i6,i7,i8 i3,i5,i7,i8 4,4,4,4 NULL 21 Using sort_union(i3,i5,i7,i8); Using where +1 SIMPLE t0 index_merge i1,i2,i3,i5,i6,i7,i8 i3,i5,i7,i8 4,4,4,4 NULL 20 Using sort_union(i3,i5,i7,i8); Using where explain select * from t0 where ((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4)) or @@ -257,7 +257,7 @@ explain select * from t0,t1 where (t0.key1=t1.key1) and (t0.key1=3 or t0.key2=4) and t1.key1<200; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t0 range i1,i2 i1 4 NULL 179 Using where +1 SIMPLE t0 ALL i1,i2 NULL NULL NULL 1024 Using where 1 SIMPLE t1 ref i1 i1 4 test.t0.key1 1 explain select * from t0,t1 where (t0.key1=t1.key1) and @@ -345,8 +345,8 @@ from t0 as A force index(i1,i2), t0 as B force index (i1,i2) where (A.key1 < 500000 or A.key2 < 3) and (B.key1 < 500000 or B.key2 < 3); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE A index_merge i1,i2 i1,i2 4,4 NULL 1016 Using sort_union(i1,i2); Using where -1 SIMPLE B index_merge i1,i2 i1,i2 4,4 NULL 1016 Using sort_union(i1,i2); Using where +1 SIMPLE A index_merge i1,i2 i1,i2 4,4 NULL 1013 Using sort_union(i1,i2); Using where +1 SIMPLE B index_merge i1,i2 i1,i2 4,4 NULL 1013 Using sort_union(i1,i2); Using where select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5) from t0 as A force index(i1,i2), t0 as B force index (i1,i2) where (A.key1 < 500000 or A.key2 < 3) @@ -371,11 +371,11 @@ alter table t0 add filler1 char(200), add filler2 char(200), add filler3 char(20 update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500; explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5) from t0 as A, t0 as B -where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7or16 = 1 or A.key8=1) -and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key7or16 = 1 or B.key8=1); +where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key# = 1 or A.key8=1) +and (B.key1 = 1 and B.key2 = 1 and B.key3 = 1 and B.key4=1 and B.key5=1 and B.key6=1 and B.key# = 1 or B.key8=1); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE A index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL 7or16 Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where -1 SIMPLE B index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL 7or16 Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where +1 SIMPLE A index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL # Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where +1 SIMPLE B index_merge i1,i2,i3,i4,i5,i6,i7?,i8 i2,i3,i4,i5,i6,i7?,i8 X NULL # Using union(intersect(i2,i3,i4,i5,i6,i7?),i8); Using where select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5) from t0 as A, t0 as B where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1) diff --git a/mysql-test/r/index_merge_ror.result b/mysql-test/r/index_merge_ror.result index a1d306c3ea4..69cd11d1dbf 100644 --- a/mysql-test/r/index_merge_ror.result +++ b/mysql-test/r/index_merge_ror.result @@ -4,13 +4,13 @@ count(*) 64801 explain select key1,key2 from t1 where key1=100 and key2=100; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 3 Using intersect(key1,key2); Using where; Using index +1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 58 Using intersect(key1,key2); Using where; Using index select key1,key2 from t1 where key1=100 and key2=100; key1 key2 100 100 explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 8 Using union(intersect(key1,key2),intersect(key3,key4)); Using where +1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 154 Using union(intersect(key1,key2),intersect(key3,key4)); Using where select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100; key1 key2 key3 key4 filler1 100 100 100 100 key1-key2-key3-key4 @@ -18,21 +18,21 @@ insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, -1, -1, 'key1 insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 100, 100, 'key4-key3'); explain select key1,key2,filler1 from t1 where key1=100 and key2=100; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 3 Using intersect(key1,key2); Using where +1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 58 Using intersect(key1,key2); Using where select key1,key2,filler1 from t1 where key1=100 and key2=100; key1 key2 filler1 100 100 key1-key2-key3-key4 100 100 key1-key2 explain select key1,key2 from t1 where key1=100 and key2=100; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 3 Using intersect(key1,key2); Using where; Using index +1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 58 Using intersect(key1,key2); Using where; Using index select key1,key2 from t1 where key1=100 and key2=100; key1 key2 100 100 100 100 explain select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 8 Using union(intersect(key1,key2),intersect(key3,key4)); Using where +1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 154 Using union(intersect(key1,key2),intersect(key3,key4)); Using where select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100; key1 key2 key3 key4 100 100 100 100 @@ -40,7 +40,7 @@ key1 key2 key3 key4 -1 -1 100 100 explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 8 Using union(intersect(key1,key2),intersect(key3,key4)); Using where +1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 154 Using union(intersect(key1,key2),intersect(key3,key4)); Using where select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100; key1 key2 key3 key4 filler1 100 100 100 100 key1-key2-key3-key4 @@ -48,14 +48,14 @@ key1 key2 key3 key4 filler1 -1 -1 100 100 key4-key3 explain select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2,key3 key1,key2,key3 5,5,5 NULL 1 Using intersect(key1,key2,key3); Using where; Using index +1 SIMPLE t1 index_merge key1,key2,key3 key1,key2,key3 5,5,5 NULL 2 Using intersect(key1,key2,key3); Using where; Using index select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100; key1 key2 key3 100 100 100 insert into t1 (key1,key2,key3,key4,filler1) values (101,101,101,101, 'key1234-101'); explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=101; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2,key3 key1,key2,key3 5,5,5 NULL 5 Using union(intersect(key1,key2),key3); Using where +1 SIMPLE t1 index_merge key1,key2,key3 key1,key2,key3 5,5,5 NULL 83 Using union(intersect(key1,key2),key3); Using where select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=101; key1 key2 key3 key4 filler1 100 100 100 100 key1-key2-key3-key4 @@ -72,19 +72,19 @@ select key1,key2,filler1 from t1 where key2=100 and key2=200; key1 key2 filler1 explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 8 Using union(intersect(key1,key2),intersect(key3,key4)); Using where +1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 152 Using union(intersect(key1,key2),intersect(key3,key4)); Using where select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100; key1 key2 key3 key4 filler1 -1 -1 100 100 key4-key3 delete from t1 where key3=100 and key4=100; explain select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 8 Using union(intersect(key1,key2),intersect(key3,key4)); Using where +1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 152 Using union(intersect(key1,key2),intersect(key3,key4)); Using where select key1,key2,key3,key4,filler1 from t1 where key1=100 and key2=100 or key3=100 and key4=100; key1 key2 key3 key4 filler1 explain select key1,key2 from t1 where key1=100 and key2=100; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 3 Using intersect(key1,key2); Using where; Using index +1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 57 Using intersect(key1,key2); Using where; Using index select key1,key2 from t1 where key1=100 and key2=100; key1 key2 insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-1'); @@ -92,7 +92,7 @@ insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 200, 200,'key1-key2-key3-key4-3'); explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2,key3,key4 key3,key1,key2,key4 5,5,5,5 NULL 16 Using union(key3,intersect(key1,key2),key4); Using where +1 SIMPLE t1 index_merge key1,key2,key3,key4 key3,key1,key2,key4 5,5,5,5 NULL 136 Using union(key3,intersect(key1,key2),key4); Using where select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200; key1 key2 key3 key4 filler1 100 100 200 200 key1-key2-key3-key4-3 @@ -101,7 +101,7 @@ key1 key2 key3 key4 filler1 insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, -1, 200,'key4'); explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2,key3,key4 key3,key1,key2,key4 5,5,5,5 NULL 18 Using union(key3,intersect(key1,key2),key4); Using where +1 SIMPLE t1 index_merge key1,key2,key3,key4 key3,key1,key2,key4 5,5,5,5 NULL 146 Using union(key3,intersect(key1,key2),key4); Using where select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200; key1 key2 key3 key4 filler1 100 100 200 200 key1-key2-key3-key4-3 @@ -111,7 +111,7 @@ key1 key2 key3 key4 filler1 insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 200, -1,'key3'); explain select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge key1,key2,key3,key4 key3,key1,key2,key4 5,5,5,5 NULL 20 Using union(key3,intersect(key1,key2),key4); Using where +1 SIMPLE t1 index_merge key1,key2,key3,key4 key3,key1,key2,key4 5,5,5,5 NULL 156 Using union(key3,intersect(key1,key2),key4); Using where select key1,key2,key3,key4,filler1 from t1 where key3=200 or (key1=100 and key2=100) or key4=200; key1 key2 key3 key4 filler1 100 100 200 200 key1-key2-key3-key4-3 @@ -121,50 +121,50 @@ key1 key2 key3 key4 filler1 -1 -1 200 -1 key3 explain select * from t1 where st_a=1 and st_b=1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b st_a,st_b 4,4 NULL 2508 Using intersect(st_a,st_b); Using where +1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b st_a,st_b 4,4 NULL 2637 Using intersect(st_a,st_b); Using where explain select st_a,st_b from t1 where st_a=1 and st_b=1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b st_a,st_b 4,4 NULL 2508 Using intersect(st_a,st_b); Using where; Using index +1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b st_a,st_b 4,4 NULL 2637 Using intersect(st_a,st_b); Using where; Using index explain select st_a from t1 ignore index (st_a) where st_a=1 and st_b=1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,stb_swt1a_2b,stb_swt1b,st_b st_b 4 const 14720 Using where +1 SIMPLE t1 ref sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,stb_swt1a_2b,stb_swt1b,st_b st_b 4 const 15093 Using where explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a sta_swt12a 12 const,const,const 958 +1 SIMPLE t1 ref sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a sta_swt21a 12 const,const,const 971 explain select * from t1 where st_b=1 and swt1b=1 and swt2b=1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref stb_swt1a_2b,stb_swt1b,st_b stb_swt1b 8 const,const 3757 Using where +1 SIMPLE t1 ref stb_swt1a_2b,stb_swt1b,st_b stb_swt1a_2b 8 const,const 3879 Using where explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt12a,stb_swt1a_2b 12,12 NULL 42 Using intersect(sta_swt12a,stb_swt1a_2b); Using where +1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt12a,stb_swt1a_2b 12,12 NULL 44 Using intersect(sta_swt12a,stb_swt1a_2b); Using where explain select * from t1 ignore index (sta_swt21a, stb_swt1a_2b) where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,st_a,stb_swt1b,st_b sta_swt12a,stb_swt1b 12,8 NULL 42 Using intersect(sta_swt12a,stb_swt1b); Using where +1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,st_a,stb_swt1b,st_b sta_swt12a,stb_swt1b 12,8 NULL 44 Using intersect(sta_swt12a,stb_swt1b); Using where explain select * from t1 ignore index (sta_swt21a, sta_swt12a, stb_swt1a_2b) where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge sta_swt1a,sta_swt2a,st_a,stb_swt1b,st_b sta_swt1a,sta_swt2a,stb_swt1b 8,8,8 NULL 41 Using intersect(sta_swt1a,sta_swt2a,stb_swt1b); Using where +1 SIMPLE t1 index_merge sta_swt1a,sta_swt2a,st_a,stb_swt1b,st_b sta_swt1a,sta_swt2a,stb_swt1b 8,8,8 NULL 43 Using intersect(sta_swt1a,sta_swt2a,stb_swt1b); Using where explain select * from t1 ignore index (sta_swt21a, sta_swt12a, stb_swt1a_2b, stb_swt1b) where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1 and swt2b=1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge sta_swt1a,sta_swt2a,st_a,st_b sta_swt1a,sta_swt2a,st_b 8,8,4 NULL 159 Using intersect(sta_swt1a,sta_swt2a,st_b); Using where +1 SIMPLE t1 index_merge sta_swt1a,sta_swt2a,st_a,st_b sta_swt1a,sta_swt2a,st_b 8,8,4 NULL 168 Using intersect(sta_swt1a,sta_swt2a,st_b); Using where explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1 and st_b=1 and swt1b=1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt12a,stb_swt1a_2b 12,12 NULL 42 Using intersect(sta_swt12a,stb_swt1a_2b); Using where +1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt12a,stb_swt1a_2b 12,12 NULL 44 Using intersect(sta_swt12a,stb_swt1a_2b); Using where explain select * from t1 where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt1a,stb_swt1b 8,8 NULL 163 Using intersect(sta_swt1a,stb_swt1b); Using where +1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt1a,stb_swt1b 8,8 NULL 174 Using intersect(sta_swt1a,stb_swt1b); Using where explain select st_a from t1 where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt1a,stb_swt1b 8,8 NULL 163 Using intersect(sta_swt1a,stb_swt1b); Using where; Using index +1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt1a,stb_swt1b 8,8 NULL 174 Using intersect(sta_swt1a,stb_swt1b); Using where; Using index explain select st_a from t1 where st_a=1 and swt1a=1 and st_b=1 and swt1b=1 and swt1b=1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt1a,stb_swt1b 8,8 NULL 163 Using intersect(sta_swt1a,stb_swt1b); Using where; Using index +1 SIMPLE t1 index_merge sta_swt12a,sta_swt1a,sta_swt2a,sta_swt21a,st_a,stb_swt1a_2b,stb_swt1b,st_b sta_swt1a,stb_swt1b 8,8 NULL 174 Using intersect(sta_swt1a,stb_swt1b); Using where; Using index drop table t0,t1; create table t2 ( a char(10), diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 54feabc6608..295ec80cd54 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -39,7 +39,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t3 range a a 4 NULL 18 Using where explain select * from t3 where a > 10 and a < 20; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t3 range a a 4 NULL 16 Using where +1 SIMPLE t3 range a a 4 NULL 17 Using where select * from t3 where a = 10; a b 10 Testing diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 1a8ace98d05..30e573fa31e 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -1203,3 +1203,60 @@ drop table t1; Got one of the listed errors drop table t1; ERROR 42S02: Unknown table 't1' +set @save_concurrent_insert=@@concurrent_insert; +set global concurrent_insert=1; +create table t1 (a int); +insert into t1 values (1),(2),(3),(4),(5); +lock table t1 read local; +insert into t1 values(6),(7); +unlock tables; +delete from t1 where a>=3 and a<=4; +lock table t1 read local; +set global concurrent_insert=2; +insert into t1 values (8),(9); +unlock tables; +insert into t1 values (10),(11),(12); +select * from t1; +a +1 +2 +11 +10 +5 +6 +7 +8 +9 +12 +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; +create table t1 (a int, b varchar(30) default "hello"); +insert into t1 (a) values (1),(2),(3),(4),(5); +lock table t1 read local; +insert into t1 (a) values(6),(7); +unlock tables; +delete from t1 where a>=3 and a<=4; +lock table t1 read local; +set global concurrent_insert=2; +insert into t1 (a) values (8),(9); +unlock tables; +insert into t1 (a) values (10),(11),(12); +select a from t1; +a +1 +2 +11 +10 +5 +6 +7 +8 +9 +12 +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +drop table t1; +set global concurrent_insert=@save_concurrent_insert; diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result index c2b925072dd..4551fed2732 100644 --- a/mysql-test/r/null.result +++ b/mysql-test/r/null.result @@ -170,7 +170,7 @@ insert into t1 select i*2 from t1; insert into t1 values(null); explain select * from t1 where i=2 or i is null; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref_or_null i i 5 const 10 Using where; Using index +1 SIMPLE t1 ref_or_null i i 5 const 9 Using where; Using index select count(*) from t1 where i=2 or i is null; count(*) 10 @@ -179,7 +179,7 @@ Warnings: Warning 1265 Data truncated for column 'i' at row 513 explain select * from t1 where i=2 or i is null; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref i i 4 const 8 Using index +1 SIMPLE t1 ref i i 4 const 7 Using index select count(*) from t1 where i=2 or i is null; count(*) 9 diff --git a/mysql-test/r/preload.result b/mysql-test/r/preload.result index b5e6dcfcdbb..b668b07b398 100644 --- a/mysql-test/r/preload.result +++ b/mysql-test/r/preload.result @@ -55,15 +55,15 @@ count(*) 4181 show status like "key_read%"; Variable_name Value -Key_read_requests 217 -Key_reads 45 +Key_read_requests 294 +Key_reads 60 select count(*) from t1 where b = 'test1'; count(*) 4181 show status like "key_read%"; Variable_name Value -Key_read_requests 434 -Key_reads 45 +Key_read_requests 588 +Key_reads 60 flush tables; flush status; select @@preload_buffer_size; @@ -74,15 +74,15 @@ Table Op Msg_type Msg_text test.t1 preload_keys status OK show status like "key_read%"; Variable_name Value -Key_read_requests 581 -Key_reads 581 +Key_read_requests 774 +Key_reads 774 select count(*) from t1 where b = 'test1'; count(*) 4181 show status like "key_read%"; Variable_name Value -Key_read_requests 798 -Key_reads 581 +Key_read_requests 1068 +Key_reads 774 flush tables; flush status; show status like "key_read%"; @@ -98,15 +98,15 @@ Table Op Msg_type Msg_text test.t1 preload_keys status OK show status like "key_read%"; Variable_name Value -Key_read_requests 10 -Key_reads 10 +Key_read_requests 17 +Key_reads 17 select count(*) from t1 where b = 'test1'; count(*) 4181 show status like "key_read%"; Variable_name Value -Key_read_requests 227 -Key_reads 52 +Key_read_requests 311 +Key_reads 75 flush tables; flush status; show status like "key_read%"; @@ -123,8 +123,8 @@ test.t1 preload_keys status OK test.t2 preload_keys status OK show status like "key_read%"; Variable_name Value -Key_read_requests 587 -Key_reads 587 +Key_read_requests 785 +Key_reads 785 select count(*) from t1 where b = 'test1'; count(*) 4181 @@ -133,8 +133,8 @@ count(*) 2584 show status like "key_read%"; Variable_name Value -Key_read_requests 938 -Key_reads 613 +Key_read_requests 1266 +Key_reads 821 flush tables; flush status; show status like "key_read%"; @@ -149,8 +149,8 @@ Warnings: Error 1146 Table 'test.t3' doesn't exist show status like "key_read%"; Variable_name Value -Key_read_requests 355 -Key_reads 355 +Key_read_requests 478 +Key_reads 478 flush tables; flush status; show status like "key_read%"; diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index 6c616a99fb0..18bc76789b1 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -290,11 +290,11 @@ t2 1 t2_idx 1 b A NULL NULL NULL YES BTREE prepare stmt4 from ' show table status from test like ''t2%'' '; execute stmt4; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t2 MyISAM 10 Fixed 0 0 0 64424509439 1024 0 NULL # # # latin1_swedish_ci NULL +t2 MyISAM 10 Fixed 0 0 0 4222124650659839 1024 0 NULL # # # latin1_swedish_ci NULL prepare stmt4 from ' show table status from test like ''t9%'' '; execute stmt4; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t9 MyISAM 10 Dynamic 2 216 432 4294967295 2048 0 NULL # # # latin1_swedish_ci NULL +t9 MyISAM 10 Dynamic 2 216 432 281474976710655 2048 0 NULL # # # latin1_swedish_ci NULL prepare stmt4 from ' show status like ''Threads_running'' '; execute stmt4; Variable_name Value @@ -803,4 +803,4 @@ prepare stmt1 from @string ; execute stmt1 ; prepare stmt1 from ' select * from t5 ' ; execute stmt1 ; -drop table t5 ; +drop table t5, t9; diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index fea5754d704..095690fde00 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -421,19 +421,19 @@ test.t1 analyze status OK test.t2 analyze status Table is already up to date explain select * from t1, t2 where t1.uid=t2.uid AND t1.uid > 0; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range uid_index uid_index 4 NULL 128 Using where +1 SIMPLE t1 range uid_index uid_index 4 NULL 112 Using where 1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38 explain select * from t1, t2 where t1.uid=t2.uid AND t2.uid > 0; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range uid_index uid_index 4 NULL 128 Using where +1 SIMPLE t1 range uid_index uid_index 4 NULL 112 Using where 1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38 explain select * from t1, t2 where t1.uid=t2.uid AND t1.uid != 0; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range uid_index uid_index 4 NULL 129 Using where +1 SIMPLE t1 range uid_index uid_index 4 NULL 113 Using where 1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38 explain select * from t1, t2 where t1.uid=t2.uid AND t2.uid != 0; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range uid_index uid_index 4 NULL 129 Using where +1 SIMPLE t1 range uid_index uid_index 4 NULL 113 Using where 1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38 select * from t1, t2 where t1.uid=t2.uid AND t1.uid > 0; id name uid id name uid diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 3479d209019..5e9a0e11c24 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -117,27 +117,23 @@ id select_type table type possible_keys key key_len ref rows Extra Warnings: Note 1003 select sql_no_cache 345 AS `@@IDENTITY`,last_insert_id() AS `last_insert_id()`,345 AS `@@identity` set big_tables=OFF, big_tables=ON, big_tables=0, big_tables=1, big_tables="OFF", big_tables="ON"; -set global concurrent_insert=ON; +set global concurrent_insert=2; show variables like 'concurrent_insert'; Variable_name Value -concurrent_insert ON +concurrent_insert 2 set global concurrent_insert=1; show variables like 'concurrent_insert'; Variable_name Value -concurrent_insert ON +concurrent_insert 1 set global concurrent_insert=0; show variables like 'concurrent_insert'; Variable_name Value -concurrent_insert OFF -set global concurrent_insert=OFF; -show variables like 'concurrent_insert'; -Variable_name Value -concurrent_insert OFF +concurrent_insert 0 set global concurrent_insert=DEFAULT; -show variables like 'concurrent_insert'; -Variable_name Value -concurrent_insert ON -set global timed_mutexes=1; +select @@concurrent_insert; +@@concurrent_insert +1 +set global timed_mutexes=ON; show variables like 'timed_mutexes'; Variable_name Value timed_mutexes ON @@ -281,8 +277,6 @@ select @@global.sql_auto_is_null; ERROR HY000: Variable 'sql_auto_is_null' is a SESSION variable set myisam_max_sort_file_size=100; ERROR HY000: Variable 'myisam_max_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL -set myisam_max_extra_sort_file_size=100; -ERROR HY000: Variable 'myisam_max_extra_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL set @@SQL_WARNINGS=NULL; ERROR 42000: Variable 'sql_warnings' can't be set to the value of 'NULL' set autocommit=1; @@ -338,11 +332,6 @@ select @@max_user_connections; @@max_user_connections 100 set global max_write_lock_count=100; -set global myisam_max_extra_sort_file_size=100; -select @@myisam_max_extra_sort_file_size; -@@myisam_max_extra_sort_file_size -100 -set global myisam_max_sort_file_size=100; set myisam_sort_buffer_size=100; set net_buffer_length=100; set net_read_timeout=100; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f8629e578f0..f25e2bb4ee6 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1,4 +1,4 @@ -drop table if exists t1,t2,`t1a``b`,v1,v2,v3,v4,v5,v6; +drop table if exists t1,t2,t9,`t1a``b`,v1,v2,v3,v4,v5,v6; drop view if exists t1,t2,`t1a``b`,v1,v2,v3,v4,v5,v6; drop database if exists mysqltest; use test; @@ -149,7 +149,7 @@ v5 VIEW v6 VIEW show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MyISAM 10 Fixed 5 9 45 38654705663 1024 0 NULL # # NULL latin1_swedish_ci NULL +t1 MyISAM 10 Fixed 5 9 45 2533274790395903 1024 0 NULL # # NULL latin1_swedish_ci NULL v1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view v2 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view v3 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view diff --git a/mysql-test/t/index_merge.test b/mysql-test/t/index_merge.test index 5acbcd8eaeb..5ac91f1f8b1 100644 --- a/mysql-test/t/index_merge.test +++ b/mysql-test/t/index_merge.test @@ -310,7 +310,7 @@ update t0 set key2=1, key3=1, key4=1, key5=1,key6=1,key7=1 where key7 < 500; # The next query will not use index i7 in intersection if the OS doesn't # support file sizes > 2GB. (ha_myisam::ref_length depends on this and index # scan cost estimates depend on ha_myisam::ref_length) ---replace_result "4,4,4,4,4,4,4" X "4,4,4,4,4,4" X "i6,i7" "i6,i7?" "i6" "i6,i7?" 7 7or16 16 7or16 +--replace_result "4,4,4,4,4,4,4" X "4,4,4,4,4,4" X "i6,i7" "i6,i7?" "i6" "i6,i7?" 7 # 16 # 18 # explain select max(A.key1 + B.key1 + A.key2 + B.key2 + A.key3 + B.key3 + A.key4 + B.key4 + A.key5 + B.key5) from t0 as A, t0 as B where (A.key1 = 1 and A.key2 = 1 and A.key3 = 1 and A.key4=1 and A.key5=1 and A.key6=1 and A.key7 = 1 or A.key8=1) diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 2b60e85fcc6..04f0de47e43 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -606,3 +606,57 @@ system rm ./var/master-data/test/t1.MYD ; drop table t1; --error 1051 drop table t1; + +# +# Test concurrent insert +# First with static record length +# +set @save_concurrent_insert=@@concurrent_insert; +set global concurrent_insert=1; +create table t1 (a int); +insert into t1 values (1),(2),(3),(4),(5); +lock table t1 read local; +connect (con1,localhost,root,,); +connection con1; +# Insert in table without hole +insert into t1 values(6),(7); +connection default; +unlock tables; +delete from t1 where a>=3 and a<=4; +lock table t1 read local; +connection con1; +set global concurrent_insert=2; +# Insert in table with hole -> Should insert at end +insert into t1 values (8),(9); +connection default; +unlock tables; +# Insert into hole +insert into t1 values (10),(11),(12); +select * from t1; +check table t1; +drop table t1; + +# Same test with dynamic record length +create table t1 (a int, b varchar(30) default "hello"); +insert into t1 (a) values (1),(2),(3),(4),(5); +lock table t1 read local; +connect (con1,localhost,root,,); +connection con1; +# Insert in table without hole +insert into t1 (a) values(6),(7); +connection default; +unlock tables; +delete from t1 where a>=3 and a<=4; +lock table t1 read local; +connection con1; +set global concurrent_insert=2; +# Insert in table with hole -> Should insert at end +insert into t1 (a) values (8),(9); +connection default; +unlock tables; +# Insert into hole +insert into t1 (a) values (10),(11),(12); +select a from t1; +check table t1; +drop table t1; +set global concurrent_insert=@save_concurrent_insert; diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test index 1fa9d30eaba..1c247240eb9 100644 --- a/mysql-test/t/ps_1general.test +++ b/mysql-test/t/ps_1general.test @@ -833,7 +833,7 @@ execute stmt1 ; --disable_metadata --horizontal_results -drop table t5 ; +drop table t5, t9; ##### RULES OF THUMB TO PRESERVE THE SYSTEMATICS OF THE PS TEST CASES ##### # diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 9931b72599f..b6059ac00e3 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -72,23 +72,20 @@ explain extended select @@IDENTITY,last_insert_id(), @@identity; set big_tables=OFF, big_tables=ON, big_tables=0, big_tables=1, big_tables="OFF", big_tables="ON"; -set global concurrent_insert=ON; +set global concurrent_insert=2; show variables like 'concurrent_insert'; set global concurrent_insert=1; show variables like 'concurrent_insert'; set global concurrent_insert=0; show variables like 'concurrent_insert'; -set global concurrent_insert=OFF; -show variables like 'concurrent_insert'; set global concurrent_insert=DEFAULT; -show variables like 'concurrent_insert'; +select @@concurrent_insert; -set global timed_mutexes=1; +set global timed_mutexes=ON; show variables like 'timed_mutexes'; set global timed_mutexes=0; show variables like 'timed_mutexes'; - set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="MERGE"; show local variables like 'storage_engine'; show global variables like 'storage_engine'; @@ -174,8 +171,6 @@ set @@global.sql_auto_is_null=1; select @@global.sql_auto_is_null; --error 1229 set myisam_max_sort_file_size=100; ---error 1229 -set myisam_max_extra_sort_file_size=100; --error 1231 set @@SQL_WARNINGS=NULL; @@ -222,9 +217,6 @@ set max_tmp_tables=100; set global max_user_connections=100; select @@max_user_connections; set global max_write_lock_count=100; -set global myisam_max_extra_sort_file_size=100; -select @@myisam_max_extra_sort_file_size; -set global myisam_max_sort_file_size=100; set myisam_sort_buffer_size=100; set net_buffer_length=100; set net_read_timeout=100; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 0303605a9ef..b5a1e9f1e0a 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1,5 +1,5 @@ --disable_warnings -drop table if exists t1,t2,`t1a``b`,v1,v2,v3,v4,v5,v6; +drop table if exists t1,t2,t9,`t1a``b`,v1,v2,v3,v4,v5,v6; drop view if exists t1,t2,`t1a``b`,v1,v2,v3,v4,v5,v6; drop database if exists mysqltest; --enable_warnings diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 9ce058f90fc..7761d2a9fc8 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -409,7 +409,7 @@ static my_bool wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, result=0; statistic_increment(locks_waited, &THR_LOCK_lock); if (data->lock->get_status) - (*data->lock->get_status)(data->status_param); + (*data->lock->get_status)(data->status_param, 0); check_locks(data->lock,"got wait_for_lock",0); } pthread_mutex_unlock(&data->lock->mutex); @@ -468,7 +468,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type) lock->read_no_write_count++; check_locks(lock,"read lock with old write lock",0); if (lock->get_status) - (*lock->get_status)(data->status_param); + (*lock->get_status)(data->status_param, 0); statistic_increment(locks_immediate,&THR_LOCK_lock); goto end; } @@ -489,7 +489,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type) data->prev=lock->read.last; lock->read.last= &data->next; if (lock->get_status) - (*lock->get_status)(data->status_param); + (*lock->get_status)(data->status_param, 0); if ((int) lock_type == (int) TL_READ_NO_INSERT) lock->read_no_write_count++; check_locks(lock,"read lock with no write locks",0); @@ -567,7 +567,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type) lock->write.last= &data->next; check_locks(lock,"second write lock",0); if (data->lock->get_status) - (*data->lock->get_status)(data->status_param); + (*data->lock->get_status)(data->status_param, 0); statistic_increment(locks_immediate,&THR_LOCK_lock); goto end; } @@ -580,9 +580,16 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type) (ulong) lock->write_wait.data)); if (!lock->write_wait.data) { /* no scheduled write locks */ - if (lock_type == TL_WRITE_CONCURRENT_INSERT && - (*lock->check_status)(data->status_param)) - data->type=lock_type= thr_upgraded_concurrent_insert_lock; + my_bool concurrent_insert= 0; + if (lock_type == TL_WRITE_CONCURRENT_INSERT) + { + concurrent_insert= 1; + if ((*lock->check_status)(data->status_param)) + { + concurrent_insert= 0; + data->type=lock_type= thr_upgraded_concurrent_insert_lock; + } + } if (!lock->read.data || (lock_type <= TL_WRITE_DELAYED && @@ -594,7 +601,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type) data->prev=lock->write.last; lock->write.last= &data->next; if (data->lock->get_status) - (*data->lock->get_status)(data->status_param); + (*data->lock->get_status)(data->status_param, concurrent_insert); check_locks(lock,"only write lock",0); statistic_increment(locks_immediate,&THR_LOCK_lock); goto end; @@ -1033,7 +1040,7 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data) if (!lock->read.data) /* No read locks */ { /* We have the lock */ if (data->lock->get_status) - (*data->lock->get_status)(data->status_param); + (*data->lock->get_status)(data->status_param, 0); pthread_mutex_unlock(&lock->mutex); DBUG_RETURN(0); } @@ -1221,7 +1228,8 @@ static ulong sum=0; /* The following functions is for WRITE_CONCURRENT_INSERT */ -static void test_get_status(void* param __attribute__((unused))) +static void test_get_status(void* param __attribute__((unused)), + int concurrent_insert __attribute__((unused))) { } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 90d4f9b9a99..12f3fe31e06 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4389,9 +4389,9 @@ Disable with --skip-bdb (will save memory).", (gptr*) &max_system_variables.completion_type, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 2, 0, 1, 0}, {"concurrent-insert", OPT_CONCURRENT_INSERT, - "Use concurrent insert with MyISAM. Disable with --skip-concurrent-insert.", + "Use concurrent insert with MyISAM. Disable with --concurrent-insert=0", (gptr*) &myisam_concurrent_insert, (gptr*) &myisam_concurrent_insert, - 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + 0, GET_LONG, OPT_ARG, 1, 0, 2, 0, 0, 0}, {"console", OPT_CONSOLE, "Write error output on screen; Don't remove the console window on windows.", (gptr*) &opt_console, (gptr*) &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -5332,9 +5332,9 @@ The minimum value for this variable is 4096.", "Default pointer size to be used for MyISAM tables.", (gptr*) &myisam_data_pointer_size, (gptr*) &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG, - 4, 2, 8, 0, 1, 0}, + 6, 2, 8, 0, 1, 0}, {"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, - "Used to help MySQL to decide when to use the slow but safe key cache index create method.", + "Depricated option", (gptr*) &global_system_variables.myisam_max_extra_sort_file_size, (gptr*) &max_system_variables.myisam_max_extra_sort_file_size, 0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH, @@ -5870,7 +5870,8 @@ static void mysql_init_variables(void) /* Things reset to zero */ opt_skip_slave_start= opt_reckless_slave = 0; mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0; - opt_log= opt_update_log= opt_bin_log= opt_slow_log= 0; + opt_log= opt_update_log= opt_slow_log= 0; + opt_bin_log= 1; // Enable binlog by default opt_disable_networking= opt_skip_show_db=0; opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0; opt_tc_log_file= (char *)"tc.log"; // no hostname in tc_log file name ! @@ -6170,7 +6171,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), opt_update_log=1; break; case (int) OPT_BIN_LOG: - opt_bin_log=1; + opt_bin_log= test(argument != disabled_my_option); break; case (int) OPT_ERROR_LOG_FILE: opt_error_log= 1; @@ -6570,6 +6571,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ha_open_options|=HA_OPEN_ABORT_IF_CRASHED; break; } + case OPT_CONCURRENT_INSERT: + /* The following code is mainly here to emulate old behavior */ + if (!argument) /* --concurrent-insert */ + myisam_concurrent_insert= 1; + else if (argument == disabled_my_option) + myisam_concurrent_insert= 0; /* --skip-concurrent-insert */ + break; case OPT_TC_HEURISTIC_RECOVER: { if ((tc_heuristic_recover=find_type(argument, @@ -6747,8 +6755,6 @@ static void get_options(int argc,char **argv) my_default_record_cache_size=global_system_variables.read_buff_size; myisam_max_temp_length= (my_off_t) global_system_variables.myisam_max_sort_file_size; - myisam_max_extra_temp_length= - (my_off_t) global_system_variables.myisam_max_extra_sort_file_size; /* Set global variables based on startup options */ myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size); diff --git a/sql/set_var.cc b/sql/set_var.cc index 4add5d6b39b..373a499f485 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -108,7 +108,6 @@ static void fix_net_retry_count(THD *thd, enum_var_type type); static void fix_max_join_size(THD *thd, enum_var_type type); static void fix_query_cache_size(THD *thd, enum_var_type type); static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type); -static void fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type); static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type); static void fix_max_binlog_size(THD *thd, enum_var_type type); static void fix_max_relay_log_size(THD *thd, enum_var_type type); @@ -158,8 +157,8 @@ sys_var_thd_ulong sys_completion_type("completion_type", sys_var_collation_connection sys_collation_connection("collation_connection"); sys_var_collation_database sys_collation_database("collation_database"); sys_var_collation_server sys_collation_server("collation_server"); -sys_var_bool_ptr sys_concurrent_insert("concurrent_insert", - &myisam_concurrent_insert); +sys_var_long_ptr sys_concurrent_insert("concurrent_insert", + &myisam_concurrent_insert); sys_var_long_ptr sys_connect_timeout("connect_timeout", &connect_timeout); sys_var_enum sys_delay_key_write("delay_key_write", @@ -270,7 +269,6 @@ sys_var_thd_ulong sys_multi_range_count("multi_range_count", &SV::multi_range_count); sys_var_long_ptr sys_myisam_data_pointer_size("myisam_data_pointer_size", &myisam_data_pointer_size); -sys_var_thd_ulonglong sys_myisam_max_extra_sort_file_size("myisam_max_extra_sort_file_size", &SV::myisam_max_extra_sort_file_size, fix_myisam_max_extra_sort_file_size, 1); sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1); sys_var_thd_ulong sys_myisam_repair_threads("myisam_repair_threads", &SV::myisam_repair_threads); sys_var_thd_ulong sys_myisam_sort_buffer_size("myisam_sort_buffer_size", &SV::myisam_sort_buff_size); @@ -623,7 +621,6 @@ sys_var *sys_variables[]= &sys_max_write_lock_count, &sys_multi_range_count, &sys_myisam_data_pointer_size, - &sys_myisam_max_extra_sort_file_size, &sys_myisam_max_sort_file_size, &sys_myisam_repair_threads, &sys_myisam_sort_buffer_size, @@ -882,9 +879,6 @@ struct show_var_st init_vars[]= { {sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS}, {sys_multi_range_count.name, (char*) &sys_multi_range_count, SHOW_SYS}, {sys_myisam_data_pointer_size.name, (char*) &sys_myisam_data_pointer_size, SHOW_SYS}, - {sys_myisam_max_extra_sort_file_size.name, - (char*) &sys_myisam_max_extra_sort_file_size, - SHOW_SYS}, {sys_myisam_max_sort_file_size.name, (char*) &sys_myisam_max_sort_file_size, SHOW_SYS}, {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR}, @@ -1140,14 +1134,6 @@ static void fix_low_priority_updates(THD *thd, enum_var_type type) } -static void -fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type) -{ - myisam_max_extra_temp_length= - (my_off_t) global_system_variables.myisam_max_extra_sort_file_size; -} - - static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type) { From db416599ff293970e722f6c4992e3b66545e9dea Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 14:29:30 +0500 Subject: [PATCH 32/63] Fix for valgrind bug in decimal code sql/item_func.cc: prec_increment should be assigned before fix_length_and_dec call --- sql/item_func.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_func.cc b/sql/item_func.cc index 3c87b6ef920..db49b7b4ae9 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1255,8 +1255,8 @@ void Item_func_div::result_precision() void Item_func_div::fix_length_and_dec() { DBUG_ENTER("Item_func_div::fix_length_and_dec"); - Item_num_op::fix_length_and_dec(); prec_increment= current_thd->variables.div_precincrement; + Item_num_op::fix_length_and_dec(); switch(hybrid_type) { case REAL_RESULT: { From 89ef3990d93762ddf24af9f4c20a63afb42e8faa Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 11:59:17 +0200 Subject: [PATCH 33/63] readline.h: Include for CodeWarrior and CTRL define cmd-line-utils/libedit/readline/readline.h: Include for CodeWarrior and CTRL define --- cmd-line-utils/libedit/readline/readline.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd-line-utils/libedit/readline/readline.h b/cmd-line-utils/libedit/readline/readline.h index 902179c208a..c43f71fb51d 100644 --- a/cmd-line-utils/libedit/readline/readline.h +++ b/cmd-line-utils/libedit/readline/readline.h @@ -73,7 +73,7 @@ typedef KEYMAP_ENTRY *Keymap; #ifndef CTRL #include -#ifdef __GLIBC__ +#if defined(__GLIBC__) || defined(__MWERKS__) #include #endif #ifndef CTRL From 2a695127a65a321b98f0db6f1b113af3403376e3 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 14:04:32 +0300 Subject: [PATCH 34/63] Fixes during review mysql-test/r/select.result: Better error message mysql-test/t/select.test: Better error message sql/hostname.cc: Join identical code sql/sql_yacc.yy: Combine code (and get a better error message) strings/ctype-ucs2.c: Cast pointer differencess --- mysql-test/r/select.result | 4 ++-- mysql-test/t/select.test | 4 ++-- sql/hostname.cc | 4 ++-- sql/sql_yacc.yy | 29 ++++++++++------------------- strings/ctype-ucs2.c | 8 +++++--- 5 files changed, 21 insertions(+), 28 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 50300ed9b76..387e7eff693 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2451,7 +2451,7 @@ a select distinct distinct * from t1; a select all distinct * from t1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'distinct * from t1' at line 1 +ERROR HY000: Incorrect usage of ALL and DISTINCT select distinct all * from t1; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'all * from t1' at line 1 +ERROR HY000: Incorrect usage of ALL and DISTINCT drop table t1; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 6d6d5f6b6e1..a46522c1510 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -1987,9 +1987,9 @@ drop table t1; create table t1 (a int(11)); select all all * from t1; select distinct distinct * from t1; ---error 1064 +--error 1221 select all distinct * from t1; ---error 1064 +--error 1221 select distinct all * from t1; drop table t1; diff --git a/sql/hostname.cc b/sql/hostname.cc index ec5c6f29a27..39223556024 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -209,8 +209,8 @@ my_string ip_to_hostname(struct in_addr *in, uint *errors) DBUG_PRINT("error",("gethostbyaddr returned %d",errno)); if (errno == HOST_NOT_FOUND || errno == NO_DATA) - add_wrong_ip(in); /* only cache negative responses, not failures */ - + goto add_wrong_ip_and_return; + /* Failure, don't cache responce */ DBUG_RETURN(0); } if (!hp->h_name[0]) // Don't allow empty hostnames diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index abe7a716a69..28d3560e5f0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2467,7 +2467,14 @@ select_from: select_options: /* empty*/ - | select_option_list; + | select_option_list + { + if (test_all_bits(Select->options, SELECT_ALL | SELECT_DISTINCT)) + { + net_printf(Lex->thd, ER_WRONG_USAGE, "ALL", "DISTINCT"); + YYABORT; + } + } select_option_list: select_option_list select_option @@ -2481,15 +2488,7 @@ select_option: YYABORT; Lex->lock_option= TL_READ_HIGH_PRIORITY; } - | DISTINCT - { - if (Select->options & SELECT_ALL) - { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; - } - Select->options|= SELECT_DISTINCT; - } + | DISTINCT { Select->options|= SELECT_DISTINCT; } | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; } | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; } | SQL_BUFFER_RESULT @@ -2509,15 +2508,7 @@ select_option: { Lex->select_lex.options|= OPTION_TO_QUERY_CACHE; } - | ALL - { - if (Select->options & SELECT_DISTINCT) - { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; - } - Select->options|= SELECT_ALL; - } + | ALL { Select->options|= SELECT_ALL; } ; select_lock_type: diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index f12cfe3256e..12c1ae905cf 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1251,7 +1251,7 @@ static uint my_numchars_ucs2(CHARSET_INFO *cs __attribute__((unused)), const char *b, const char *e) { - return (e-b)/2; + return (uint) (e-b)/2; } @@ -1261,7 +1261,8 @@ uint my_charpos_ucs2(CHARSET_INFO *cs __attribute__((unused)), const char *e __attribute__((unused)), uint pos) { - return pos > e - b ? e - b + 2 : pos * 2; + uint string_length= (uint) (e - b); + return pos > string_length ? string_length + 2 : pos * 2; } @@ -1270,7 +1271,8 @@ uint my_well_formed_len_ucs2(CHARSET_INFO *cs __attribute__((unused)), const char *b, const char *e, uint nchars, int *error) { - uint nbytes= (e-b) & ~ (uint)1; + /* Ensure string length is dividable with 2 */ + uint nbytes= ((uint) (e-b)) & ~(uint) 1; *error= 0; nchars*= 2; return min(nbytes, nchars); From 29f3f4a27fd2afa4a7fc57aaba86bb102e7cebe1 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 15:06:11 +0200 Subject: [PATCH 35/63] added function mysql_set_character_set (reviewed by Monty) as a work around for #8317 and #9637 This function sends SET NAMES command and changes mysql->charset so mysql_real_escape_string will work as expected. libmysql/libmysql.def: added new function mysql_set_character_set --- libmysql/libmysql.c | 30 ++++++++++++++++++++++++++++++ libmysql/libmysql.def | 1 + 2 files changed, 31 insertions(+) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index c663dab7476..4c9f06df38e 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1509,6 +1509,36 @@ const char * STDCALL mysql_character_set_name(MYSQL *mysql) return mysql->charset->csname; } +int STDCALL mysql_set_character_set(MYSQL *mysql, char *cs_name) +{ + struct charset_info_st *cs; + const char *save_csdir = charsets_dir; + + if (mysql->options.charset_dir) + charsets_dir = mysql->options.charset_dir; + + if ( (cs = get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))) ) + { + char buff[MY_CS_NAME_SIZE + 10]; + charsets_dir = save_csdir; + sprintf(buff, "SET NAMES %s", cs_name); + if (!mysql_query(mysql, buff)) { + mysql->charset = cs; + } + } else { + char cs_dir_name[FN_REFLEN]; + get_charsets_dir(cs_dir_name); + mysql->net.last_errno=CR_CANT_READ_CHARSET; + strmov(mysql->net.sqlstate, unknown_sqlstate); + my_snprintf(mysql->net.last_error, sizeof(mysql->net.last_error)-1, + ER(mysql->net.last_errno), + cs_name, + cs_dir_name); + + } + charsets_dir = save_csdir; + return mysql->net.last_errno; +} uint STDCALL mysql_thread_safe(void) { diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index c5579e9ec2b..57c97ab08ee 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -146,4 +146,5 @@ EXPORTS mysql_rpl_query_type mysql_slave_query mysql_embedded + mysql_set_character_set get_defaults_files From 92cb62c86fa68bacd5ab58703a704bd4d290ac72 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 15:54:35 +0200 Subject: [PATCH 36/63] added prototype for mysql_set_character_set function --- include/mysql.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/mysql.h b/include/mysql.h index d8a56126756..ab61fe694d9 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -381,6 +381,7 @@ unsigned int STDCALL mysql_warning_count(MYSQL *mysql); const char * STDCALL mysql_info(MYSQL *mysql); unsigned long STDCALL mysql_thread_id(MYSQL *mysql); const char * STDCALL mysql_character_set_name(MYSQL *mysql); +int STDCALL mysql_set_character_set(MYSQL *mysql, char *csname); MYSQL * STDCALL mysql_init(MYSQL *mysql); my_bool STDCALL mysql_ssl_set(MYSQL *mysql, const char *key, From 6f4c2486439dfcbaab7e1686860385282562d442 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 19:15:03 +0400 Subject: [PATCH 37/63] Add missing commas to errmsg.c libmysql/errmsg.c: Add missing commas --- libmysql/errmsg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c index 48e44327d0f..5d183b478ef 100644 --- a/libmysql/errmsg.c +++ b/libmysql/errmsg.c @@ -80,7 +80,7 @@ const char *client_errors[]= "Row retrieval was canceled by mysql_stmt_close() call", "Attempt to read column without prior row fetch", "Prepared statement contains no metadata", - "Attempt to read a row while there is no result set associated with the statement" + "Attempt to read a row while there is no result set associated with the statement", "" }; @@ -142,7 +142,7 @@ const char *client_errors[]= "Row retrieval was canceled by mysql_stmt_close() call", "Attempt to read column without prior row fetch", "Prepared statement contains no metadata", - "Attempt to read a row while there is no result set associated with the statement" + "Attempt to read a row while there is no result set associated with the statement", "" }; @@ -202,7 +202,7 @@ const char *client_errors[]= "Row retrieval was canceled by mysql_stmt_close() call", "Attempt to read column without prior row fetch", "Prepared statement contains no metadata", - "Attempt to read a row while there is no result set associated with the statement" + "Attempt to read a row while there is no result set associated with the statement", "" }; #endif From c4a1210fd4ef4a3bab2f5dddbdc8ededeb33a307 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 18:37:22 +0300 Subject: [PATCH 38/63] row0mysql.c: InnoDB wrongly complained in the .err log that MySQL is trying to drop a non-existent table, if tablespace ran out (Bug #10607) innobase/row/row0mysql.c: InnoDB wrongly complained in the .err log that MySQL is trying to drop a non-existent table, if tablespace ran out (Bug #10607) --- innobase/row/row0mysql.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 9410f2ce7cc..280c306cce4 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1606,10 +1606,18 @@ row_create_table_for_mysql( trx_general_rollback_for_mysql(trx, FALSE, NULL); if (err == DB_OUT_OF_FILE_SPACE) { - fputs("InnoDB: Warning: cannot create table ", stderr); + ut_print_timestamp(stderr); + + fputs(" InnoDB: Warning: cannot create table ", + stderr); ut_print_name(stderr, trx, table->name); fputs(" because tablespace full\n", stderr); - row_drop_table_for_mysql(table->name, trx, FALSE); + + if (dict_table_get_low(table->name)) { + + row_drop_table_for_mysql(table->name, trx, + FALSE); + } } else if (err == DB_DUPLICATE_KEY) { ut_print_timestamp(stderr); From 9a8d59b02c5e50d0b35e0f4271fdd18c51e80297 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 09:55:03 -0700 Subject: [PATCH 39/63] Fixup from 4.1 to 5.0 merge sql/sql_lex.h: Fix length of options member --- sql/sql_lex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 94f1a8e0df4..a33d60df0d4 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -296,7 +296,7 @@ protected: *link_next, **link_prev; /* list of whole SELECT_LEX */ public: - ulong options; + ulonglong options; /* result of this query can't be cached, bit field, can be : UNCACHEABLE_DEPENDENT From c3f73a428193150df234881352875ca3383b9740 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 21:43:26 +0200 Subject: [PATCH 40/63] sql/ha_blackhole.cc bug#10175 - blackhole.test hangs with "Warning: prev link 1 didn't point at previous lock at read: read lock with no write locks" sql/sql_base.cc libmysqld/examples/mysql.cc linking problem sql/ha_blackhole.cc: bug#10175 - blackhole.test hangs with "Warning: prev link 1 didn't point at previous lock at read: read lock with no write locks" sql/sql_base.cc: libmysqld/examples/mysql.cc linking problem --- sql/ha_blackhole.cc | 3 ++- sql/sql_base.cc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/ha_blackhole.cc b/sql/ha_blackhole.cc index 7c6e7cb56b6..c9c94b3a9d7 100644 --- a/sql/ha_blackhole.cc +++ b/sql/ha_blackhole.cc @@ -129,8 +129,9 @@ THR_LOCK_DATA **ha_blackhole::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type) { + if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) + lock.type=lock_type; *to++= &lock; - return to; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c580842ce06..e86362c857b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2522,7 +2522,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table, if ((pos= find_type(&table->keynames, name->ptr(), name->length(), 1)) <= 0) { - my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), name->c_ptr(), + my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), name->c_ptr_safe(), table->real_name); map->set_all(); return 1; From cdd6bc9bfeb1a82e7c7cfd8880f8e014ca5d9ff8 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 May 2005 23:08:29 +0300 Subject: [PATCH 41/63] Fixed wrong buffer usage for auto-increment key with blob part that caused CHECK TABLE to report that the table was wrong. (Bug #10045) myisam/mi_key.c: Fixed wrong buffer usage for auto-increment key with blob part that caused CHECK TABLE to report that the table was wrong. (Bug #10045) mysql-test/r/auto_increment.result: New test case mysql-test/t/auto_increment.test: New test case --- myisam/mi_key.c | 31 ++++++++++++++++++++---------- mysql-test/r/auto_increment.result | 14 ++++++++++++++ mysql-test/t/auto_increment.test | 12 ++++++++++++ 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/myisam/mi_key.c b/myisam/mi_key.c index 1688ab74823..06571c570e1 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -255,8 +255,25 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, } /* _mi_pack_key */ - /* Put a key in record */ - /* Used when only-keyread is wanted */ + +/* + Store found key in record + + SYNOPSIS + _mi_put_key_in_record() + info MyISAM handler + keynr Key number that was used + record Store key here + + Last read key is in info->lastkey + + NOTES + Used when only-keyread is wanted + + RETURN + 0 ok + 1 error +*/ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr, byte *record) @@ -267,14 +284,8 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr, byte *blob_ptr; DBUG_ENTER("_mi_put_key_in_record"); - if (info->s->base.blobs && info->s->keyinfo[keynr].flag & HA_VAR_LENGTH_KEY) - { - if (!(blob_ptr= - mi_alloc_rec_buff(info, info->s->keyinfo[keynr].keylength, - &info->rec_buff))) - goto err; - } - key=(byte*) info->lastkey; + blob_ptr= info->lastkey2; /* Place to put blob parts */ + key=(byte*) info->lastkey; /* KEy that was read */ key_end=key+info->lastkey_length; for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++) { diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result index 2d6b058d9c5..9345c029127 100644 --- a/mysql-test/r/auto_increment.result +++ b/mysql-test/r/auto_increment.result @@ -131,3 +131,17 @@ a 1 2 drop table t1; +CREATE TABLE t1 ( a INT AUTO_INCREMENT, b BLOB, PRIMARY KEY (a,b(10))); +INSERT INTO t1 (b) VALUES ('aaaa'); +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +INSERT INTO t1 (b) VALUES (''); +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +INSERT INTO t1 (b) VALUES ('bbbb'); +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE IF EXISTS t1; diff --git a/mysql-test/t/auto_increment.test b/mysql-test/t/auto_increment.test index c26983b5eec..e699415a838 100644 --- a/mysql-test/t/auto_increment.test +++ b/mysql-test/t/auto_increment.test @@ -89,3 +89,15 @@ select last_insert_id(); insert into t1 values (NULL); select * from t1; drop table t1; + +# +# BUG #10045: Problem with composite AUTO_INCREMENT + BLOB key + +CREATE TABLE t1 ( a INT AUTO_INCREMENT, b BLOB, PRIMARY KEY (a,b(10))); +INSERT INTO t1 (b) VALUES ('aaaa'); +CHECK TABLE t1; +INSERT INTO t1 (b) VALUES (''); +CHECK TABLE t1; +INSERT INTO t1 (b) VALUES ('bbbb'); +CHECK TABLE t1; +DROP TABLE IF EXISTS t1; From 752372f62626321f60563c6c825424801b5a7f60 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 14 May 2005 02:28:10 +0400 Subject: [PATCH 42/63] Fix wrong format specifier in error messages. Not to be pushed into 5.0 as there it's fixed differently (in the new format of error messages) sql/share/danish/errmsg.txt: Fix wrong format specifier in an error message. sql/share/serbian/errmsg.txt: Fix wrong format specifier in an error message. --- sql/share/danish/errmsg.txt | 2 +- sql/share/serbian/errmsg.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 384625f7112..4983d39714a 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -262,7 +262,7 @@ character-set=latin1 "Key reference and table reference don't match", "Operand should contain %d column(s)", "Subquery returns more than 1 row", -"Unknown prepared statement handler (%ld) given to %s", +"Unknown prepared statement handler (%.*s) given to %s", "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index accf1926abb..adda7d7cf53 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -252,7 +252,7 @@ character-set=cp1250 "Key reference and table reference don't match", "Operand should contain %d column(s)", "Subquery returns more than 1 row", -"Unknown prepared statement handler (%ld) given to %s", +"Unknown prepared statement handler (%.*s) given to %s", "Help database is corrupt or does not exist", "Cyclic reference on subqueries", "Converting column '%s' from %s to %s", From ba3540cc6991c49e0f43501e600018896b5e0dcb Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 14 May 2005 02:31:26 +0400 Subject: [PATCH 43/63] Fix a valgrind warning: memcpy does not allow its arguments to overlap. --- libmysql/libmysql.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 4c9f06df38e..3fcdc6bdc4d 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -3944,9 +3944,12 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind) /* We only need to check that stmt->field_count - if it is not null stmt->bind was initialized in mysql_stmt_prepare - */ + stmt->bind overlaps with bind if mysql_stmt_bind_param + is called from mysql_stmt_store_result. + */ - memcpy((char*) stmt->bind, (char*) bind, sizeof(MYSQL_BIND) * bind_count); + if (stmt->bind != bind) + memcpy((char*) stmt->bind, (char*) bind, sizeof(MYSQL_BIND) * bind_count); for (param= stmt->bind, end= param + bind_count, field= stmt->fields ; param < end ; From 86826f137ade6150198f500c9d55771b55264ce5 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 14 May 2005 13:26:01 +0400 Subject: [PATCH 44/63] A post-merge fix. --- mysql-test/r/ps_grant.result | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/ps_grant.result b/mysql-test/r/ps_grant.result index 3a302ba3ba8..4792a781419 100644 --- a/mysql-test/r/ps_grant.result +++ b/mysql-test/r/ps_grant.result @@ -1,7 +1,3 @@ -prepare stmt4 from ' show full processlist '; -execute stmt4; -Id User Host db Command Time State Info -number root localhost test Query time NULL show full processlist test_sequence ------ grant/revoke/drop affects a parallel session test ------ show grants for second_user@localhost ; @@ -79,6 +75,10 @@ commit ; show grants for second_user@localhost ; ERROR 42000: There is no such grant defined for user 'second_user' on host 'localhost' drop database mysqltest; +prepare stmt4 from ' show full processlist '; +execute stmt4; +Id User Host db Command Time State Info +number root localhost test Query time NULL show full processlist prepare stmt3 from ' grant all on test.t1 to drop_user@localhost identified by ''looser'' '; ERROR HY000: This command is not supported in the prepared statement protocol yet From bb2b8120615f48cd17682aa810e54b20a7002c77 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 14 May 2005 14:42:25 +0400 Subject: [PATCH 45/63] More post-merge fixes. mysql-test/t/ps_grant.test: More post-merge fixes: show processlist must be last. --- mysql-test/r/ps_grant.result | 9 +++++---- mysql-test/t/ps_grant.test | 11 +++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/ps_grant.result b/mysql-test/r/ps_grant.result index 4792a781419..8fbb06fe61b 100644 --- a/mysql-test/r/ps_grant.result +++ b/mysql-test/r/ps_grant.result @@ -75,10 +75,6 @@ commit ; show grants for second_user@localhost ; ERROR 42000: There is no such grant defined for user 'second_user' on host 'localhost' drop database mysqltest; -prepare stmt4 from ' show full processlist '; -execute stmt4; -Id User Host db Command Time State Info -number root localhost test Query time NULL show full processlist prepare stmt3 from ' grant all on test.t1 to drop_user@localhost identified by ''looser'' '; ERROR HY000: This command is not supported in the prepared statement protocol yet @@ -91,3 +87,8 @@ revoke all privileges on test.t1 from drop_user@localhost ; prepare stmt3 from ' drop user drop_user@localhost '; ERROR HY000: This command is not supported in the prepared statement protocol yet drop user drop_user@localhost; +prepare stmt4 from ' show full processlist '; +execute stmt4; +Id User Host db Command Time State Info +number root localhost test Query time NULL show full processlist +deallocate prepare stmt4; diff --git a/mysql-test/t/ps_grant.test b/mysql-test/t/ps_grant.test index f23582633b4..0b33a2dadde 100644 --- a/mysql-test/t/ps_grant.test +++ b/mysql-test/t/ps_grant.test @@ -112,10 +112,6 @@ show grants for second_user@localhost ; drop database mysqltest; -# Tested here simply so it is not tested with embedded server -prepare stmt4 from ' show full processlist '; ---replace_column 1 number 6 time 3 localhost -execute stmt4; ## grant/revoke + drop user --error 1295 @@ -131,3 +127,10 @@ revoke all privileges on test.t1 from drop_user@localhost ; prepare stmt3 from ' drop user drop_user@localhost '; drop user drop_user@localhost; +# This test must be the last one, otherwise it may produce extra +# rows in the processlist under high load. +# Tested here simply so it is not tested with embedded server +prepare stmt4 from ' show full processlist '; +--replace_column 1 number 6 time 3 localhost +execute stmt4; +deallocate prepare stmt4; From 2059908b9ce2bde6848f247c4ee4a72a7e42738a Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 14 May 2005 16:24:36 +0300 Subject: [PATCH 46/63] After merge fixes BitKeeper/deleted/.del-outfile2.result~fb702ee2518d8e6d: Delete: mysql-test/r/outfile2.result libmysql/libmysql.c: Fix indentation for new function mysql_set_character_set() mysql-test/r/alter_table.result: Fix test to be in same order as in 4.0 mysql-test/r/innodb.result: After merge fix mysql-test/r/insert_update.result: Add extra test for insert into ... on duplicate key upate mysql-test/r/outfile.result: After merge fix mysql-test/t/alter_table.test: Fix test to be in same order as in 4.0 mysql-test/t/insert_update.test: Add extra test for insert into ... on duplicate key upate mysql-test/t/outfile.test: After merge fix sql/item_func.cc: After merge fix sql/sql_table.cc: After merge fix --- libmysql/libmysql.c | 31 ++-- mysql-test/r/alter_table.result | 225 +++++++++++++++--------------- mysql-test/r/innodb.result | 2 +- mysql-test/r/insert_update.result | 9 +- mysql-test/r/outfile.result | Bin 683 -> 959 bytes mysql-test/r/outfile2.result | 10 -- mysql-test/t/alter_table.test | 102 +++++++------- mysql-test/t/insert_update.test | 6 +- mysql-test/t/outfile.test | 1 + sql/item_func.cc | 2 +- sql/sql_table.cc | 2 +- 11 files changed, 200 insertions(+), 190 deletions(-) delete mode 100644 mysql-test/r/outfile2.result diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 4c9f06df38e..ff90cfb6007 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1509,37 +1509,40 @@ const char * STDCALL mysql_character_set_name(MYSQL *mysql) return mysql->charset->csname; } + int STDCALL mysql_set_character_set(MYSQL *mysql, char *cs_name) { struct charset_info_st *cs; - const char *save_csdir = charsets_dir; + const char *save_csdir= charsets_dir; if (mysql->options.charset_dir) - charsets_dir = mysql->options.charset_dir; + charsets_dir= mysql->options.charset_dir; - if ( (cs = get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))) ) + if ((cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0)))) { char buff[MY_CS_NAME_SIZE + 10]; - charsets_dir = save_csdir; + charsets_dir= save_csdir; sprintf(buff, "SET NAMES %s", cs_name); - if (!mysql_query(mysql, buff)) { - mysql->charset = cs; - } - } else { + if (!mysql_query(mysql, buff)) + { + mysql->charset= cs; + } + } + else + { char cs_dir_name[FN_REFLEN]; get_charsets_dir(cs_dir_name); - mysql->net.last_errno=CR_CANT_READ_CHARSET; + mysql->net.last_errno= CR_CANT_READ_CHARSET; strmov(mysql->net.sqlstate, unknown_sqlstate); - my_snprintf(mysql->net.last_error, sizeof(mysql->net.last_error)-1, - ER(mysql->net.last_errno), - cs_name, - cs_dir_name); + my_snprintf(mysql->net.last_error, sizeof(mysql->net.last_error) - 1, + ER(mysql->net.last_errno), cs_name, cs_dir_name); } - charsets_dir = save_csdir; + charsets_dir= save_csdir; return mysql->net.last_errno; } + uint STDCALL mysql_thread_safe(void) { #ifdef THREAD diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 6cada0d5fb2..b7d47a09bee 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -303,6 +303,120 @@ ALTER TABLE t1 DISABLE KEYS; INSERT DELAYED INTO t1 VALUES(1),(2),(3); ALTER TABLE t1 ENABLE KEYS; drop table t1; +CREATE TABLE t1 ( +Host varchar(16) binary NOT NULL default '', +User varchar(16) binary NOT NULL default '', +PRIMARY KEY (Host,User) +) ENGINE=MyISAM; +ALTER TABLE t1 DISABLE KEYS; +LOCK TABLES t1 WRITE; +INSERT INTO t1 VALUES ('localhost','root'),('localhost',''),('games','monty'); +SHOW INDEX FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE +t1 0 PRIMARY 2 User A 3 NULL NULL BTREE +ALTER TABLE t1 ENABLE KEYS; +UNLOCK TABLES; +CHECK TABLES t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +CREATE TABLE t1 ( +Host varchar(16) binary NOT NULL default '', +User varchar(16) binary NOT NULL default '', +PRIMARY KEY (Host,User), +KEY (Host) +) ENGINE=MyISAM; +ALTER TABLE t1 DISABLE KEYS; +SHOW INDEX FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE +t1 0 PRIMARY 2 User A 0 NULL NULL BTREE +t1 1 Host 1 Host A NULL NULL NULL BTREE disabled +LOCK TABLES t1 WRITE; +INSERT INTO t1 VALUES ('localhost','root'),('localhost',''); +SHOW INDEX FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE +t1 0 PRIMARY 2 User A 2 NULL NULL BTREE +t1 1 Host 1 Host A NULL NULL NULL BTREE disabled +ALTER TABLE t1 ENABLE KEYS; +SHOW INDEX FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE +t1 0 PRIMARY 2 User A 2 NULL NULL BTREE +t1 1 Host 1 Host A 1 NULL NULL BTREE +UNLOCK TABLES; +CHECK TABLES t1; +Table Op Msg_type Msg_text +test.t1 check status OK +LOCK TABLES t1 WRITE; +ALTER TABLE t1 RENAME t2; +UNLOCK TABLES; +select * from t2; +Host User +localhost +localhost root +DROP TABLE t2; +CREATE TABLE t1 ( +Host varchar(16) binary NOT NULL default '', +User varchar(16) binary NOT NULL default '', +PRIMARY KEY (Host,User), +KEY (Host) +) ENGINE=MyISAM; +LOCK TABLES t1 WRITE; +ALTER TABLE t1 DISABLE KEYS; +SHOW INDEX FROM t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE +t1 0 PRIMARY 2 User A 0 NULL NULL BTREE +t1 1 Host 1 Host A NULL NULL NULL BTREE disabled +DROP TABLE t1; +create table t1 (a int); +alter table t1 rename to `t1\\`; +ERROR 42000: Incorrect table name 't1\\' +rename table t1 to `t1\\`; +ERROR 42000: Incorrect table name 't1\\' +drop table t1; +drop table if exists t1, t2; +Warnings: +Note 1051 Unknown table 't1' +Note 1051 Unknown table 't2' +create table t1 ( a varchar(10) not null primary key ) engine=myisam; +create table t2 ( a varchar(10) not null primary key ) engine=merge union=(t1); +flush tables; +alter table t1 modify a varchar(10); +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` varchar(10) NOT NULL default '', + PRIMARY KEY (`a`) +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`) +flush tables; +alter table t1 modify a varchar(10) not null; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` varchar(10) NOT NULL default '', + PRIMARY KEY (`a`) +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`) +drop table if exists t1, t2; +create table t1 (a int, b int, c int, d int, e int, f int, g int, h int,i int, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM; +insert into t1 (a) values(1); +show table status like 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 9 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL +alter table t1 modify a int; +show table status like 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 9 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL +drop table t1; +create table t1 (a int not null, b int not null, c int not null, d int not null, e int not null, f int not null, g int not null, h int not null,i int not null, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM; +insert into t1 (a) values(1); +show table status like 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 9 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL +drop table t1; set names koi8r; create table t1 (a char(10) character set koi8r); insert into t1 values ('ÔÅÓÔ'); @@ -382,75 +496,6 @@ t1 CREATE TABLE `t1` ( `mytext` longtext character set latin1 collate latin1_general_cs ) ENGINE=MyISAM DEFAULT CHARSET=latin2 drop table t1; -CREATE TABLE t1 ( -Host varchar(16) binary NOT NULL default '', -User varchar(16) binary NOT NULL default '', -PRIMARY KEY (Host,User) -) ENGINE=MyISAM; -ALTER TABLE t1 DISABLE KEYS; -LOCK TABLES t1 WRITE; -INSERT INTO t1 VALUES ('localhost','root'),('localhost',''),('games','monty'); -SHOW INDEX FROM t1; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE -t1 0 PRIMARY 2 User A 3 NULL NULL BTREE -ALTER TABLE t1 ENABLE KEYS; -UNLOCK TABLES; -CHECK TABLES t1; -Table Op Msg_type Msg_text -test.t1 check status OK -DROP TABLE t1; -CREATE TABLE t1 ( -Host varchar(16) binary NOT NULL default '', -User varchar(16) binary NOT NULL default '', -PRIMARY KEY (Host,User), -KEY (Host) -) ENGINE=MyISAM; -ALTER TABLE t1 DISABLE KEYS; -SHOW INDEX FROM t1; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE -t1 0 PRIMARY 2 User A 0 NULL NULL BTREE -t1 1 Host 1 Host A NULL NULL NULL BTREE disabled -LOCK TABLES t1 WRITE; -INSERT INTO t1 VALUES ('localhost','root'),('localhost',''); -SHOW INDEX FROM t1; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE -t1 0 PRIMARY 2 User A 2 NULL NULL BTREE -t1 1 Host 1 Host A NULL NULL NULL BTREE disabled -ALTER TABLE t1 ENABLE KEYS; -SHOW INDEX FROM t1; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE -t1 0 PRIMARY 2 User A 2 NULL NULL BTREE -t1 1 Host 1 Host A 1 NULL NULL BTREE -UNLOCK TABLES; -CHECK TABLES t1; -Table Op Msg_type Msg_text -test.t1 check status OK -LOCK TABLES t1 WRITE; -ALTER TABLE t1 RENAME t2; -UNLOCK TABLES; -select * from t2; -Host User -localhost -localhost root -DROP TABLE t2; -CREATE TABLE t1 ( -Host varchar(16) binary NOT NULL default '', -User varchar(16) binary NOT NULL default '', -PRIMARY KEY (Host,User), -KEY (Host) -) ENGINE=MyISAM; -LOCK TABLES t1 WRITE; -ALTER TABLE t1 DISABLE KEYS; -SHOW INDEX FROM t1; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE -t1 0 PRIMARY 2 User A 0 NULL NULL BTREE -t1 1 Host 1 Host A NULL NULL NULL BTREE disabled -DROP TABLE t1; CREATE TABLE t1 (a int PRIMARY KEY, b INT UNIQUE); ALTER TABLE t1 DROP PRIMARY KEY; SHOW CREATE TABLE t1; @@ -469,12 +514,6 @@ alter table t1 drop key no_such_key; ERROR 42000: Can't DROP 'no_such_key'; check that column/key exists alter table t1 drop key a; drop table t1; -create table t1 (a int); -alter table t1 rename to `t1\\`; -ERROR 42000: Incorrect table name 't1\\' -rename table t1 to `t1\\`; -ERROR 42000: Incorrect table name 't1\\' -drop table t1; create table t1 (a text) character set koi8r; insert into t1 values (_koi8r'ÔÅÓÔ'); select hex(a) from t1; @@ -489,39 +528,3 @@ create table t1 ( a timestamp ); alter table t1 add unique ( a(1) ); ERROR HY000: Incorrect sub part key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique sub keys drop table t1; -drop table if exists t1, t2; -create table t1 ( a varchar(10) not null primary key ) engine=myisam; -create table t2 ( a varchar(10) not null primary key ) engine=merge union=(t1); -flush tables; -alter table t1 modify a varchar(10); -show create table t2; -Table Create Table -t2 CREATE TABLE `t2` ( - `a` varchar(10) NOT NULL default '', - PRIMARY KEY (`a`) -) TYPE=MRG_MyISAM UNION=(t1) -flush tables; -alter table t1 modify a varchar(10) not null; -show create table t2; -Table Create Table -t2 CREATE TABLE `t2` ( - `a` varchar(10) NOT NULL default '', - PRIMARY KEY (`a`) -) TYPE=MRG_MyISAM UNION=(t1) -drop table if exists t1, t2; -create table t1 (a int, b int, c int, d int, e int, f int, g int, h int,i int, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM; -insert into t1 (a) values(1); -show table status like 't1'; -Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Create_options Comment -t1 MyISAM Fixed 1 37 37 X X X X X X X X -alter table t1 modify a int; -show table status like 't1'; -Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Create_options Comment -t1 MyISAM Fixed 1 37 37 X X X X X X X X -drop table t1; -create table t1 (a int not null, b int not null, c int not null, d int not null, e int not null, f int not null, g int not null, h int not null,i int not null, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM; -insert into t1 (a) values(1); -show table status like 't1'; -Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Create_options Comment -t1 MyISAM Fixed 1 37 37 X X X X X X X X -drop table t1; diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index def462fb521..4c983014d4b 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1645,5 +1645,5 @@ concat(a, b) drop table t1; CREATE TABLE t1 ( a char(10) ) ENGINE=InnoDB; SELECT a FROM t1 WHERE MATCH (a) AGAINST ('test' IN BOOLEAN MODE); -The used table type doesn't support FULLTEXT indexes +ERROR HY000: The used table type doesn't support FULLTEXT indexes DROP TABLE t1; diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index f78372541f2..2143538469b 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -167,7 +167,7 @@ a b c VALUES(a) 2 1 11 NULL DROP TABLE t1; DROP TABLE t2; -create table t1 (a int not null unique); +create table t1 (a int not null unique) engine=myisam; insert into t1 values (1),(2); insert ignore into t1 select 1 on duplicate key update a=2; select * from t1; @@ -179,4 +179,11 @@ select * from t1; a 1 3 +insert into t1 select 1 on duplicate key update a=2; +select * from t1; +a +2 +3 +insert into t1 select a from t1 on duplicate key update a=a+1 ; +ERROR 23000: Duplicate entry '3' for key 1 drop table t1; diff --git a/mysql-test/r/outfile.result b/mysql-test/r/outfile.result index a7871592241104fe2a949c98379cfa21dcbe5d68..5eb24a78ef0d0242fcdd2f0ad1dfbf47f9d60dac 100644 GIT binary patch delta 348 zcmZXQ&q~8U5XMmu*?k5NgO{j?H3(jMO4F?@Y zpG+ZwP-z*hrJ?a@?VoU_hrj<%rt>6VA7x`&;>?mb`|b(bqMOs06nvZsMldG63m&Y9oCrbW!+}TKlZ9

zvZF(N`U{1WXL|qu delta 24 gcmdnbzM6HzU&e{cG$y}ifield->table; if (!(table->file->table_flags() & HA_CAN_FULLTEXT)) { - my_error(ER_TABLE_CANT_HANDLE_FULLTEXT, MYF(0)); + my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0)); return 1; } table->fulltext_searched=1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 7b0f24bcc45..67aade519f5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1205,6 +1205,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, /* Sort keys in optimized order */ qsort((gptr) key_info_buffer, *key_count, sizeof(KEY), (qsort_cmp) sort_keys); + create_info->null_bits= null_fields; DBUG_RETURN(0); } @@ -1392,7 +1393,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) create_info->data_file_name= create_info->index_file_name= 0; create_info->table_options=db_options; - create_info->null_bits= null_fields; if (rea_create_table(thd, path, create_info, fields, key_count, key_info_buffer)) From 18d0e6a73d1dca6b967e8f006012f78e7af74140 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 14 May 2005 19:31:34 +0300 Subject: [PATCH 47/63] Don't enable binlogs by default as this gives too many warnings --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 12f3fe31e06..84a041167f1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5871,7 +5871,7 @@ static void mysql_init_variables(void) opt_skip_slave_start= opt_reckless_slave = 0; mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0; opt_log= opt_update_log= opt_slow_log= 0; - opt_bin_log= 1; // Enable binlog by default + opt_bin_log= 0; opt_disable_networking= opt_skip_show_db=0; opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0; opt_tc_log_file= (char *)"tc.log"; // no hostname in tc_log file name ! From 04b56a3efabc24e721cd2438b5df9f9585634cc6 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 May 2005 00:30:23 +0300 Subject: [PATCH 48/63] Portability fix (for 64 bit intel) --- mysql-test/t/index_merge_ror.test | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/t/index_merge_ror.test b/mysql-test/t/index_merge_ror.test index 3a484157267..15c596ce149 100644 --- a/mysql-test/t/index_merge_ror.test +++ b/mysql-test/t/index_merge_ror.test @@ -184,6 +184,8 @@ explain select st_a from t1 ignore index (st_a) where st_a=1 and st_b=1; # Check that keys that don't improve selectivity are skipped. # +# Different value on 32 and 64 bit +--replace sta_swt12a sta_swt21a explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1; explain select * from t1 where st_b=1 and swt1b=1 and swt2b=1; From f4425b50e157cf35f89ed22043b8ffd5089abdae Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 May 2005 06:59:34 +0200 Subject: [PATCH 49/63] mysqltest.c, mysql-test-run.sh: Not to conflict with Windows return code 2 for "not found", use 62 for "skip" mysql-test-run.sh, suppress.purify: Use Purify suppress file mysql-test/suppress.purify: Purify suppress file mysql-test/mysql-test-run.sh: Use Purify suppress file Not to conflict with Windows return code 2 for "not found", use 62 for "skip" client/mysqltest.c: Not to conflict with Windows return code 2 for "not found", use 62 for "skip" --- client/mysqltest.c | 2 +- mysql-test/mysql-test-run.sh | 9 +++------ mysql-test/suppress.purify | 10 ++++++++++ 3 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 mysql-test/suppress.purify diff --git a/client/mysqltest.c b/client/mysqltest.c index 3eab182a74d..362b6a0b1df 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -572,7 +572,7 @@ static void abort_not_supported_test() printf("skipped\n"); free_used_memory(); my_end(MY_CHECK_ERROR); - exit(2); + exit(62); } static void verbose_msg(const char* fmt, ...) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index bdbd46ae8dd..581c6c66fdd 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -569,10 +569,7 @@ if [ x$SOURCE_DIST = x1 ] ; then NDB_MGM="$BASEDIR/ndb/src/mgmclient/ndb_mgm" if [ -n "$USE_PURIFY" ] ; then - PSUP="$MYSQL_TEST_DIR/purify.suppress" - echo "suppress UMR rw_read_held; mi_open; ha_myisam::open64; handler::ha_open; openfrm" > $PSUP - echo "suppress UMR my_end; main" >> $PSUP - echo "suppress UMR _doprnt; fprintf; my_end; main" >> $PSUP + PSUP="$MYSQL_TEST_DIR/suppress.purify" PURIFYOPTIONS="-windows=no -log-file=%v.purifylog -append-logfile -add-suppression-files=$PSUP" if [ -f "${MYSQL_TEST}-purify" ] ; then MYSQL_TEST="${MYSQL_TEST}-purify" @@ -1660,11 +1657,11 @@ run_testcase () $ECHO "$RES$RES_SPACE [ pass ] $TIMER" else # why the following ``if'' ? That is why res==1 is special ? - if [ $res = 2 ]; then + if [ $res = 62 ]; then skip_inc $ECHO "$RES$RES_SPACE [ skipped ]" else - if [ $res -gt 2 ]; then + if [ $res -ne 1 ]; then $ECHO "mysqltest returned unexpected code $res, it has probably crashed" >> $TIMEFILE fi total_inc diff --git a/mysql-test/suppress.purify b/mysql-test/suppress.purify new file mode 100644 index 00000000000..58553130c51 --- /dev/null +++ b/mysql-test/suppress.purify @@ -0,0 +1,10 @@ +suppress UMR rw_read_held; mi_open; ha_myisam::open64; handler::ha_open; openfrm +suppress UMR my_end; main +suppress UMR _doprnt; fprintf; my_end; main +suppress umr rw_read_held; mi_open +suppress umr _putmsg; putmsg; _tx_sndudata +suppress umr rw_read_held; Query_cache::store_query(THD*,st_table_list*); mysql_execute_command(THD*) +suppress sig ...; _select; select; handle_connections_sockets; main; _start +suppress sig ...; read; vio_read; my_real_read(st_net*,unsigned long*); my_net_read; do_command(THD*) +suppress sig ...; read; vio_read; my_real_read(st_net*,unsigned long*); my_net_read; net_safe_read +suppress sig ...; write; vio_write; net_real_write; net_write_buff(st_net*,const char*,unsigned long); my_net_write From 657469bab80c56d97e375903c61c755103b36058 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 May 2005 07:34:09 +0200 Subject: [PATCH 50/63] mysql-test-run.pl: Not to conflict with Windows return code 2 for "not found", use 62 for "skip" init_db.sql: Initial db updates mysql-test/lib/init_db.sql: Initial db updates mysql-test/mysql-test-run.pl: Not to conflict with Windows return code 2 for "not found", use 62 for "skip" --- mysql-test/lib/init_db.sql | 5 +++-- mysql-test/mysql-test-run.pl | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/mysql-test/lib/init_db.sql b/mysql-test/lib/init_db.sql index 902af0b0842..6d5ec55a6ae 100644 --- a/mysql-test/lib/init_db.sql +++ b/mysql-test/lib/init_db.sql @@ -1,4 +1,5 @@ -USE mysql; +use mysql; +set table_type=myisam; CREATE TABLE db ( Host char(60) binary DEFAULT '' NOT NULL, @@ -193,7 +194,7 @@ INSERT INTO time_zone_name (Name, Time_Zone_id) VALUES CREATE TABLE time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, - Use_leap_seconds enum('Y','N') DEFAULT 'N' NOT NULL, + Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 5a188dc6927..30e92e07da1 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1497,15 +1497,15 @@ sub run_testcase ($) { { mtr_report_test_passed($tinfo); } - elsif ( $res == 2 ) + elsif ( $res == 62 ) { # Testcase itself tell us to skip this one mtr_report_test_skipped($tinfo); } else { - # Test case failed - if ( $res > 2 ) + # Test case failed, if in control mysqltest returns 1 + if ( $res != 1 ) { mtr_tofile($path_timefile, "mysqltest returned unexpected code $res, " . @@ -2129,7 +2129,7 @@ sub run_mysqltest ($$) { mysqld_arguments($args,'master',0,$tinfo->{'master_opt'},[]); } - return mtr_run_test($exe_mysqltest,$args,$tinfo->{'path'},"",$path_timefile,""); + return mtr_run_test($exe,$args,$tinfo->{'path'},"",$path_timefile,""); } ############################################################################## From bea0e79f57cff77cd74bd4063c87bd27ae62fe4a Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 May 2005 17:22:54 +0200 Subject: [PATCH 51/63] mtr_report.pl, mtr_process.pl, mysql-test-run.pl: Added option --vardir= for feature bug#10096 mysql-test/mysql-test-run.pl: Added option --vardir= for feature bug#10096 mysql-test/lib/mtr_process.pl: Added option --vardir= for feature bug#10096 mysql-test/lib/mtr_report.pl: Added option --vardir= for feature bug#10096 --- mysql-test/lib/mtr_process.pl | 2 +- mysql-test/lib/mtr_report.pl | 13 +- mysql-test/mysql-test-run.pl | 223 ++++++++++++++++++++-------------- 3 files changed, 137 insertions(+), 101 deletions(-) diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index 8aefc235d72..78758e54aa4 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -344,7 +344,7 @@ sub mtr_kill_leftovers () { # We scan the "var/run/" directory for other process id's to kill # FIXME $path_run_dir or something - my $rundir= "$::glob_mysql_test_dir/var/run"; + my $rundir= "$::opt_vardir/run"; if ( -d $rundir ) { diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl index fd665b154b8..cb41549422f 100644 --- a/mysql-test/lib/mtr_report.pl +++ b/mysql-test/lib/mtr_report.pl @@ -89,9 +89,10 @@ sub mtr_report_test_passed ($) { my $tinfo= shift; my $timer= ""; - if ( $::opt_timer and -f "$::glob_mysql_test_dir/var/log/timer" ) + if ( $::opt_timer and -f "$::opt_vardir/log/timer" ) { - $timer= mtr_fromfile("$::glob_mysql_test_dir/var/log/timer"); + $timer= mtr_fromfile("$::opt_vardir/log/timer"); + $::glob_tot_real_time += $timer; $timer= sprintf "%12s", $timer; } $tinfo->{'result'}= 'MTR_RES_PASSED'; @@ -177,8 +178,8 @@ sub mtr_report_stats ($) { # Report if there was any fatal warnings/errors in the log files # - unlink("$::glob_mysql_test_dir/var/log/warnings"); - unlink("$::glob_mysql_test_dir/var/log/warnings.tmp"); + unlink("$::opt_vardir/log/warnings"); + unlink("$::opt_vardir/log/warnings.tmp"); # Remove some non fatal warnings from the log files # FIXME what is going on ????? ;-) @@ -196,11 +197,11 @@ sub mtr_report_stats ($) { # found_error=1 # } # done -# unlink("$::glob_mysql_test_dir/var/log/warnings.tmp"); +# unlink("$::opt_vardir/log/warnings.tmp"); # if ( $found_error= "1" ) # { # print "WARNING: Got errors/warnings while running tests. Please examine\n" -# print "$::glob_mysql_test_dir/var/log/warnings for details.\n" +# print "$::opt_vardir/log/warnings for details.\n" # } # } } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 30e92e07da1..106ed2ec179 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -84,7 +84,7 @@ use Sys::Hostname; #use Carp; use IO::Socket; use IO::Socket::INET; -#use Data::Dumper; +use Data::Dumper; use strict; #use diagnostics; @@ -177,6 +177,7 @@ our $path_timefile; our $path_manager_log; # Used by mysqldadmin our $path_slave_load_tmpdir; # What is this?! our $path_my_basedir; +our $opt_vardir; # A path but set directly on cmd line our $opt_tmpdir; # A path but set directly on cmd line our $opt_usage; @@ -447,8 +448,6 @@ sub initial_setup () { $glob_basedir= dirname($glob_mysql_test_dir); $glob_mysql_bench_dir= "$glob_basedir/mysql-bench"; # FIXME make configurable - $path_timefile= "$glob_mysql_test_dir/var/log/mysqltest-time"; - # needs to be same length to test logging (FIXME what???) $path_slave_load_tmpdir= "../../var/tmp"; @@ -469,11 +468,6 @@ sub command_line_setup () { # These are defaults for things that are set on the command line $opt_suite= "main"; # Special default suite - $opt_tmpdir= "$glob_mysql_test_dir/var/tmp"; - # FIXME maybe unneded? - $path_manager_log= "$glob_mysql_test_dir/var/log/manager.log"; - $opt_current_test= "$glob_mysql_test_dir/var/log/current_test"; - my $opt_master_myport= 9306; my $opt_slave_myport= 9308; $opt_ndbcluster_port= 9350; @@ -549,6 +543,7 @@ sub command_line_setup () { 'unified-diff|udiff' => \$opt_udiff, 'user-test=s' => \$opt_user_test, 'user=s' => \$opt_user, + 'vardir=s' => \$opt_vardir, 'verbose' => \$opt_verbose, 'wait-timeout=i' => \$opt_wait_timeout, 'warnings|log-warnings' => \$opt_warnings, @@ -564,51 +559,35 @@ sub command_line_setup () { @opt_cases= @ARGV; - # Put this into a hash, will be a C struct + # -------------------------------------------------------------------------- + # Set the "var/" directory, as it is the base for everything else + # -------------------------------------------------------------------------- - $master->[0]->{'path_myddir'}= "$glob_mysql_test_dir/var/master-data"; - $master->[0]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/master.err"; - $master->[0]->{'path_mylog'}= "$glob_mysql_test_dir/var/log/master.log"; - $master->[0]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/master.pid"; - $master->[0]->{'path_mysock'}= "$opt_tmpdir/master.sock"; - $master->[0]->{'path_myport'}= $opt_master_myport; - $master->[0]->{'start_timeout'}= 400; # enough time create innodb tables + if ( ! $opt_vardir ) + { + $opt_vardir= "$glob_mysql_test_dir/var"; + } - $master->[0]->{'ndbcluster'}= 1; # ndbcluster not started + if ( $opt_vardir !~ m,^/, ) + { + # Make absolute path, relative test dir + $opt_vardir= "$glob_mysql_test_dir/$opt_vardir"; + } - $master->[1]->{'path_myddir'}= "$glob_mysql_test_dir/var/master1-data"; - $master->[1]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/master1.err"; - $master->[1]->{'path_mylog'}= "$glob_mysql_test_dir/var/log/master1.log"; - $master->[1]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/master1.pid"; - $master->[1]->{'path_mysock'}= "$opt_tmpdir/master1.sock"; - $master->[1]->{'path_myport'}= $opt_master_myport + 1; - $master->[1]->{'start_timeout'}= 400; # enough time create innodb tables + # -------------------------------------------------------------------------- + # If not set, set these to defaults + # -------------------------------------------------------------------------- - $slave->[0]->{'path_myddir'}= "$glob_mysql_test_dir/var/slave-data"; - $slave->[0]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/slave.err"; - $slave->[0]->{'path_mylog'}= "$glob_mysql_test_dir/var/log/slave.log"; - $slave->[0]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/slave.pid"; - $slave->[0]->{'path_mysock'}= "$opt_tmpdir/slave.sock"; - $slave->[0]->{'path_myport'}= $opt_slave_myport; - $slave->[0]->{'start_timeout'}= 400; - - $slave->[1]->{'path_myddir'}= "$glob_mysql_test_dir/var/slave1-data"; - $slave->[1]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/slave1.err"; - $slave->[1]->{'path_mylog'}= "$glob_mysql_test_dir/var/log/slave1.log"; - $slave->[1]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/slave1.pid"; - $slave->[1]->{'path_mysock'}= "$opt_tmpdir/slave1.sock"; - $slave->[1]->{'path_myport'}= $opt_slave_myport + 1; - $slave->[1]->{'start_timeout'}= 300; - - $slave->[2]->{'path_myddir'}= "$glob_mysql_test_dir/var/slave2-data"; - $slave->[2]->{'path_myerr'}= "$glob_mysql_test_dir/var/log/slave2.err"; - $slave->[2]->{'path_mylog'}= "$glob_mysql_test_dir/var/log/slave2.log"; - $slave->[2]->{'path_mypid'}= "$glob_mysql_test_dir/var/run/slave2.pid"; - $slave->[2]->{'path_mysock'}= "$opt_tmpdir/slave2.sock"; - $slave->[2]->{'path_myport'}= $opt_slave_myport + 2; - $slave->[2]->{'start_timeout'}= 300; + $opt_tmpdir= "$opt_vardir/tmp" unless $opt_tmpdir; + # FIXME maybe not needed? + $path_manager_log= "$opt_vardir/log/manager.log" + unless $path_manager_log; + $opt_current_test= "$opt_vardir/log/current_test" + unless $opt_current_test; + # -------------------------------------------------------------------------- # Do sanity checks of command line arguments + # -------------------------------------------------------------------------- if ( $opt_extern and $opt_local ) { @@ -621,13 +600,6 @@ sub command_line_setup () { $opt_socket= "/tmp/mysql.sock"; # FIXME } - if ( $opt_extern ) - { - $glob_use_running_server= 1; - $opt_skip_rpl= 1; # We don't run rpl test cases - $master->[0]->{'path_mysock'}= $opt_socket; - } - # -------------------------------------------------------------------------- # Look at the command line options and set script flags # -------------------------------------------------------------------------- @@ -746,6 +718,58 @@ sub command_line_setup () { } } + # Put this into a hash, will be a C struct + + $master->[0]->{'path_myddir'}= "$opt_vardir/master-data"; + $master->[0]->{'path_myerr'}= "$opt_vardir/log/master.err"; + $master->[0]->{'path_mylog'}= "$opt_vardir/log/master.log"; + $master->[0]->{'path_mypid'}= "$opt_vardir/run/master.pid"; + $master->[0]->{'path_mysock'}= "$opt_tmpdir/master.sock"; + $master->[0]->{'path_myport'}= $opt_master_myport; + $master->[0]->{'start_timeout'}= 400; # enough time create innodb tables + + $master->[0]->{'ndbcluster'}= 1; # ndbcluster not started + + $master->[1]->{'path_myddir'}= "$opt_vardir/master1-data"; + $master->[1]->{'path_myerr'}= "$opt_vardir/log/master1.err"; + $master->[1]->{'path_mylog'}= "$opt_vardir/log/master1.log"; + $master->[1]->{'path_mypid'}= "$opt_vardir/run/master1.pid"; + $master->[1]->{'path_mysock'}= "$opt_tmpdir/master1.sock"; + $master->[1]->{'path_myport'}= $opt_master_myport + 1; + $master->[1]->{'start_timeout'}= 400; # enough time create innodb tables + + $slave->[0]->{'path_myddir'}= "$opt_vardir/slave-data"; + $slave->[0]->{'path_myerr'}= "$opt_vardir/log/slave.err"; + $slave->[0]->{'path_mylog'}= "$opt_vardir/log/slave.log"; + $slave->[0]->{'path_mypid'}= "$opt_vardir/run/slave.pid"; + $slave->[0]->{'path_mysock'}= "$opt_tmpdir/slave.sock"; + $slave->[0]->{'path_myport'}= $opt_slave_myport; + $slave->[0]->{'start_timeout'}= 400; + + $slave->[1]->{'path_myddir'}= "$opt_vardir/slave1-data"; + $slave->[1]->{'path_myerr'}= "$opt_vardir/log/slave1.err"; + $slave->[1]->{'path_mylog'}= "$opt_vardir/log/slave1.log"; + $slave->[1]->{'path_mypid'}= "$opt_vardir/run/slave1.pid"; + $slave->[1]->{'path_mysock'}= "$opt_tmpdir/slave1.sock"; + $slave->[1]->{'path_myport'}= $opt_slave_myport + 1; + $slave->[1]->{'start_timeout'}= 300; + + $slave->[2]->{'path_myddir'}= "$opt_vardir/slave2-data"; + $slave->[2]->{'path_myerr'}= "$opt_vardir/log/slave2.err"; + $slave->[2]->{'path_mylog'}= "$opt_vardir/log/slave2.log"; + $slave->[2]->{'path_mypid'}= "$opt_vardir/run/slave2.pid"; + $slave->[2]->{'path_mysock'}= "$opt_tmpdir/slave2.sock"; + $slave->[2]->{'path_myport'}= $opt_slave_myport + 2; + $slave->[2]->{'start_timeout'}= 300; + + if ( $opt_extern ) + { + $glob_use_running_server= 1; + $opt_skip_rpl= 1; # We don't run rpl test cases + $master->[0]->{'path_mysock'}= $opt_socket; + } + + $path_timefile= "$opt_vardir/log/mysqltest-time"; } @@ -892,8 +916,8 @@ sub executable_setup () { } $path_ndb_backup_dir= - "$glob_mysql_test_dir/var/ndbcluster-$opt_ndbcluster_port"; - $file_ndb_testrun_log= "$glob_mysql_test_dir/var/log/ndb_testrun.log"; + "$opt_vardir/ndbcluster-$opt_ndbcluster_port"; + $file_ndb_testrun_log= "$opt_vardir/log/ndb_testrun.log"; } @@ -981,7 +1005,7 @@ sub kill_running_server () { # leftovers from previous runs. mtr_report("Killing Possible Leftover Processes"); - mkpath("$glob_mysql_test_dir/var/log"); # Needed for mysqladmin log + mkpath("$opt_vardir/log"); # Needed for mysqladmin log mtr_kill_leftovers(); ndbcluster_stop(); @@ -995,15 +1019,18 @@ sub kill_and_cleanup () { mtr_report("Removing Stale Files"); - rmtree("$glob_mysql_test_dir/var/log"); - rmtree("$glob_mysql_test_dir/var/ndbcluster-$opt_ndbcluster_port"); - rmtree("$glob_mysql_test_dir/var/run"); - rmtree("$glob_mysql_test_dir/var/tmp"); + rmtree("$opt_vardir/log"); + rmtree("$opt_vardir/ndbcluster-$opt_ndbcluster_port"); + rmtree("$opt_vardir/run"); + rmtree("$opt_vardir/tmp"); - mkpath("$glob_mysql_test_dir/var/log"); - mkpath("$glob_mysql_test_dir/var/run"); - mkpath("$glob_mysql_test_dir/var/tmp"); - mkpath($opt_tmpdir); + mkpath("$opt_vardir/log"); + mkpath("$opt_vardir/run"); + mkpath("$opt_vardir/tmp"); + if ( $opt_tmpdir ne "$opt_vardir/tmp" ) + { + mkpath($opt_tmpdir); + } # FIXME do we really need to create these all, or are they # created for us when tables are created? @@ -1027,6 +1054,16 @@ sub kill_and_cleanup () { rmtree("$slave->[2]->{'path_myddir'}"); mkpath("$slave->[2]->{'path_myddir'}/mysql"); mkpath("$slave->[2]->{'path_myddir'}/test"); + + # To make some old test cases work, we create a soft + # link from the old "var" location to the new one + + if ( ! $glob_win32 and $opt_vardir ne "$glob_mysql_test_dir/var" ) + { + # FIXME why bother with the above, why not always remove all of var?! + rmtree("$glob_mysql_test_dir/var"); # Clean old var, FIXME or rename it?! + symlink($opt_vardir, "$glob_mysql_test_dir/var"); + } } @@ -1050,7 +1087,7 @@ sub ndbcluster_install () { if ( mtr_run("$glob_mysql_test_dir/ndb/ndbcluster", ["--port=$opt_ndbcluster_port", "--port-base=$ndbcluster_port_base", - "--data-dir=$glob_mysql_test_dir/var", + "--data-dir=$opt_vardir", $ndbcluster_opts, "--initial"], "", "", "", "") ) @@ -1074,7 +1111,7 @@ sub ndbcluster_start () { # FIXME, we want to _append_ output to file $file_ndb_testrun_log instead of /dev/null if ( mtr_run("$glob_mysql_test_dir/ndb/ndbcluster", ["--port=$opt_ndbcluster_port", - "--data-dir=$glob_mysql_test_dir/var"], + "--data-dir=$opt_vardir"], "", "/dev/null", "", "") ) { mtr_error("Error ndbcluster_start"); @@ -1094,7 +1131,7 @@ sub ndbcluster_stop () { # FIXME, we want to _append_ output to file $file_ndb_testrun_log instead of /dev/null mtr_run("$glob_mysql_test_dir/ndb/ndbcluster", ["--port=$opt_ndbcluster_port", - "--data-dir=$glob_mysql_test_dir/var", + "--data-dir=$opt_vardir", "--stop"], "", "/dev/null", "", ""); @@ -1566,17 +1603,17 @@ sub do_before_start_master ($$) { $tname ne "rpl_crash_binlog_ib_3b") { # FIXME we really want separate dir for binlogs - foreach my $bin ( glob("$glob_mysql_test_dir/var/log/master*-bin.*") ) + foreach my $bin ( glob("$opt_vardir/log/master*-bin.*") ) { unlink($bin); } } # Remove old master.info and relay-log.info files - unlink("$glob_mysql_test_dir/var/master-data/master.info"); - unlink("$glob_mysql_test_dir/var/master-data/relay-log.info"); - unlink("$glob_mysql_test_dir/var/master1-data/master.info"); - unlink("$glob_mysql_test_dir/var/master1-data/relay-log.info"); + unlink("$opt_vardir/master-data/master.info"); + unlink("$opt_vardir/master-data/relay-log.info"); + unlink("$opt_vardir/master1-data/master.info"); + unlink("$opt_vardir/master1-data/relay-log.info"); # Run master initialization shell script if one exists if ( $init_script ) @@ -1603,13 +1640,13 @@ sub do_before_start_slave ($$) { $tname ne "rpl_crash_binlog_ib_3b" ) { # FIXME we really want separate dir for binlogs - foreach my $bin ( glob("$glob_mysql_test_dir/var/log/slave*-bin.*") ) + foreach my $bin ( glob("$opt_vardir/log/slave*-bin.*") ) { unlink($bin); } # FIXME really master?! - unlink("$glob_mysql_test_dir/var/slave-data/master.info"); - unlink("$glob_mysql_test_dir/var/slave-data/relay-log.info"); + unlink("$opt_vardir/slave-data/master.info"); + unlink("$opt_vardir/slave-data/relay-log.info"); } # Run slave initialization shell script if one exists @@ -1623,8 +1660,8 @@ sub do_before_start_slave ($$) { } } - `rm -f $glob_mysql_test_dir/var/slave-data/log.*`; -# unlink("$glob_mysql_test_dir/var/slave-data/log.*"); + `rm -f $opt_vardir/slave-data/log.*`; +# unlink("$opt_vardir/slave-data/log.*"); } sub mysqld_arguments ($$$$$) { @@ -1670,8 +1707,7 @@ sub mysqld_arguments ($$$$$) { if ( $type eq 'master' ) { - mtr_add_arg($args, "%s--log-bin=%s/var/log/master-bin", $prefix, - $glob_mysql_test_dir); + mtr_add_arg($args, "%s--log-bin=%s/log/master-bin", $prefix, $opt_vardir); mtr_add_arg($args, "%s--pid-file=%s", $prefix, $master->[$idx]->{'path_mypid'}); mtr_add_arg($args, "%s--port=%d", $prefix, @@ -1695,8 +1731,8 @@ sub mysqld_arguments ($$$$$) { # FIXME slave get this option twice?! mtr_add_arg($args, "%s--exit-info=256", $prefix); mtr_add_arg($args, "%s--init-rpl-role=slave", $prefix); - mtr_add_arg($args, "%s--log-bin=%s/var/log/slave%s-bin", $prefix, - $glob_mysql_test_dir, $sidx); # FIXME use own dir for binlogs + mtr_add_arg($args, "%s--log-bin=%s/log/slave%s-bin", $prefix, + $opt_vardir, $sidx); # FIXME use own dir for binlogs mtr_add_arg($args, "%s--log-slave-updates", $prefix); # FIXME option duplicated for slave mtr_add_arg($args, "%s--log=%s", $prefix, @@ -1706,8 +1742,8 @@ sub mysqld_arguments ($$$$$) { $slave->[$idx]->{'path_mypid'}); mtr_add_arg($args, "%s--port=%d", $prefix, $slave->[$idx]->{'path_myport'}); - mtr_add_arg($args, "%s--relay-log=%s/var/log/slave%s-relay-bin", $prefix, - $glob_mysql_test_dir, $sidx); + mtr_add_arg($args, "%s--relay-log=%s/log/slave%s-relay-bin", $prefix, + $opt_vardir, $sidx); mtr_add_arg($args, "%s--report-host=127.0.0.1", $prefix); mtr_add_arg($args, "%s--report-port=%d", $prefix, $slave->[$idx]->{'path_myport'}); @@ -1745,13 +1781,13 @@ sub mysqld_arguments ($$$$$) { { if ( $type eq 'master' ) { - mtr_add_arg($args, "%s--debug=d:t:i:A,%s/var/log/master%s.trace", - $prefix, $glob_mysql_test_dir, $sidx); + mtr_add_arg($args, "%s--debug=d:t:i:A,%s/log/master%s.trace", + $prefix, $opt_vardir, $sidx); } if ( $type eq 'slave' ) { - mtr_add_arg($args, "%s--debug=d:t:i:A,%s/var/log/slave%s.trace", - $prefix, $glob_mysql_test_dir, $sidx); + mtr_add_arg($args, "%s--debug=d:t:i:A,%s/log/slave%s.trace", + $prefix, $opt_vardir, $sidx); } } @@ -2003,7 +2039,7 @@ sub run_mysqltest ($$) { if ( $opt_debug ) { $cmdline_mysqldump .= - " --debug=d:t:A,$glob_mysql_test_dir/var/log/mysqldump.trace"; + " --debug=d:t:A,$opt_vardir/log/mysqldump.trace"; } my $cmdline_mysqlbinlog= @@ -2012,7 +2048,7 @@ sub run_mysqltest ($$) { if ( $opt_debug ) { $cmdline_mysqlbinlog .= - " --debug=d:t:A,$glob_mysql_test_dir/var/log/mysqlbinlog.trace"; + " --debug=d:t:A,$opt_vardir/log/mysqlbinlog.trace"; } my $cmdline_mysql= @@ -2075,13 +2111,13 @@ sub run_mysqltest ($$) { { $exe= "strace"; # FIXME there are ktrace, .... mtr_add_arg($args, "-o"); - mtr_add_arg($args, "%s/var/log/mysqltest.strace", $glob_mysql_test_dir); + mtr_add_arg($args, "%s/log/mysqltest.strace", $opt_vardir); mtr_add_arg($args, "$exe_mysqltest"); } if ( $opt_timer ) { - mtr_add_arg($args, "--timer-file=%s/var/log/timer", $glob_mysql_test_dir); + mtr_add_arg($args, "--timer-file=%s/log/timer", $opt_vardir); } if ( $opt_big_test ) @@ -2106,8 +2142,7 @@ sub run_mysqltest ($$) { if ( $opt_debug ) { - mtr_add_arg($args, "--debug=d:t:A,%s/var/log/mysqltest.trace", - $glob_mysql_test_dir); + mtr_add_arg($args, "--debug=d:t:A,%s/log/mysqltest.trace", $opt_vardir); } if ( $opt_with_openssl ) From 194745cd6331c4fe77dd8a82b70a1e9c0bbef92a Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 May 2005 17:56:39 +0200 Subject: [PATCH 52/63] ndb - testScan -n ScanRead488O fix ndb/test/ndbapi/testScan.cpp: remove added test feature --- ndb/test/ndbapi/testScan.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ndb/test/ndbapi/testScan.cpp b/ndb/test/ndbapi/testScan.cpp index 1fa1d4bd3ab..2802f1c950e 100644 --- a/ndb/test/ndbapi/testScan.cpp +++ b/ndb/test/ndbapi/testScan.cpp @@ -317,6 +317,7 @@ int runScanReadIndex(NDBT_Context* ctx, NDBT_Step* step){ g_info << i << ": "; bool sort = (rand() % 100) > 50 ? true : false; bool desc = (rand() % 100) > 50 ? true : false; + desc = false; // random causes too many deadlocks int scan_flags = (NdbScanOperation::SF_OrderBy & -(int)sort) | (NdbScanOperation::SF_Descending & -(int)desc); From db2616673f03ef4fd7fbe2da16ced78b53d87a9a Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 May 2005 18:10:30 +0200 Subject: [PATCH 53/63] ndb - wl-2451 update schemafile format change to 5.0.6 ndb/src/kernel/blocks/dbdict/Dbdict.cpp: version update ndb/src/kernel/blocks/dbdict/Dbdict.hpp: version update ndb/src/kernel/blocks/dbdict/SchemaFile.hpp: version update ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp: version update --- ndb/src/kernel/blocks/dbdict/Dbdict.cpp | 16 ++++++++-------- ndb/src/kernel/blocks/dbdict/Dbdict.hpp | 2 +- ndb/src/kernel/blocks/dbdict/SchemaFile.hpp | 4 ++-- ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index 0b68bc966d6..d51f9537154 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -1013,7 +1013,7 @@ void Dbdict::readSchemaConf(Signal* signal, ndbrequire(rr.firstPage == 0); SchemaFile * sf = &xsf->schemaPage[0]; Uint32 noOfPages; - if (sf->NdbVersion < NDB_SF_VERSION_5_0_5) { + if (sf->NdbVersion < NDB_SF_VERSION_5_0_6) { jam(); const Uint32 pageSize_old = 32 * 1024; noOfPages = pageSize_old / NDB_SF_PAGE_SIZE - 1; @@ -1032,8 +1032,8 @@ void Dbdict::readSchemaConf(Signal* signal, SchemaFile * sf0 = &xsf->schemaPage[0]; xsf->noOfPages = sf0->FileSize / NDB_SF_PAGE_SIZE; - if (sf0->NdbVersion < NDB_SF_VERSION_5_0_5 && - ! convertSchemaFileTo_5_0_5(xsf)) { + if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6 && + ! convertSchemaFileTo_5_0_6(xsf)) { jam(); ndbrequire(! crashInd); ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1); @@ -1113,7 +1113,7 @@ void Dbdict::closeReadSchemaConf(Signal* signal, }//Dbdict::closeReadSchemaConf() bool -Dbdict::convertSchemaFileTo_5_0_5(XSchemaFile * xsf) +Dbdict::convertSchemaFileTo_5_0_6(XSchemaFile * xsf) { const Uint32 pageSize_old = 32 * 1024; Uint32 page_old[pageSize_old >> 2]; @@ -2175,8 +2175,8 @@ void Dbdict::execSCHEMA_INFO(Signal* signal) releaseSections(signal); SchemaFile * sf0 = &xsf->schemaPage[0]; - if (sf0->NdbVersion < NDB_SF_VERSION_5_0_5) { - bool ok = convertSchemaFileTo_5_0_5(xsf); + if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6) { + bool ok = convertSchemaFileTo_5_0_6(xsf); ndbrequire(ok); } @@ -11922,8 +11922,8 @@ Dbdict::initSchemaFile(XSchemaFile * xsf, Uint32 firstPage, Uint32 lastPage, memset(sf, 0, NDB_SF_PAGE_SIZE); Uint32 ndb_version = NDB_VERSION; - if (ndb_version < NDB_SF_VERSION_5_0_5) - ndb_version = NDB_SF_VERSION_5_0_5; + if (ndb_version < NDB_SF_VERSION_5_0_6) + ndb_version = NDB_SF_VERSION_5_0_6; memcpy(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic)); sf->ByteOrder = 0x12345678; diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp index 54a67fc8452..68bb9b628d4 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp @@ -1703,7 +1703,7 @@ private: void readSchemaRef(Signal* signal, FsConnectRecordPtr fsPtr); void closeReadSchemaConf(Signal* signal, FsConnectRecordPtr fsPtr); - bool convertSchemaFileTo_5_0_5(XSchemaFile*); + bool convertSchemaFileTo_5_0_6(XSchemaFile*); /* ------------------------------------------------------------ */ // Get table definitions diff --git a/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp b/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp index 11bd0992711..0226991a073 100644 --- a/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp +++ b/ndb/src/kernel/blocks/dbdict/SchemaFile.hpp @@ -35,7 +35,7 @@ #define NDB_SF_MAX_PAGES 160 // versions where format changed -#define NDB_SF_VERSION_5_0_5 MAKE_VERSION(5, 0, 5) +#define NDB_SF_VERSION_5_0_6 MAKE_VERSION(5, 0, 6) // One page in schema file. struct SchemaFile { @@ -71,7 +71,7 @@ struct SchemaFile { } }; - // pre-5.0.5 + // pre-5.0.6 struct TableEntry_old { Uint32 m_tableState; Uint32 m_tableVersion; diff --git a/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp b/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp index 254b38710c5..b9b144cd977 100644 --- a/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp +++ b/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp @@ -195,7 +195,7 @@ NDB_COMMAND(printSchemafile, } SchemaFile* sf = (SchemaFile *)&buf[0]; - if (sf->NdbVersion < NDB_SF_VERSION_5_0_5) + if (sf->NdbVersion < NDB_SF_VERSION_5_0_6) print_old(filename, sf); else print(filename, sf, sz); From 8fd8d819d0ee7f048b6a40b6e96f0d5e23c0943f Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 May 2005 20:38:54 +0200 Subject: [PATCH 54/63] mysqltest.c: To solve bug#6193, also reset require when using 'eval' for running query mysql-test-run.pl: In cleanup, remove possible soft link to var directory mysql-test/mysql-test-run.pl: In cleanup, remove possible soft link to var directory client/mysqltest.c: To solve bug#6193, also reset require when using 'eval' for running query --- client/mysqltest.c | 6 ++++++ mysql-test/mysql-test-run.pl | 10 ++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 362b6a0b1df..1f95f1eaeeb 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -3522,6 +3522,12 @@ int main(int argc, char **argv) if (q->query == q->query_buf) q->query += q->first_word_len + 1; display_result_vertically= (q->type==Q_QUERY_VERTICAL); + if (save_file[0]) + { + strmov(q->record_file,save_file); + q->require_file=require_file; + save_file[0]=0; + } error|= run_query(&cur_con->mysql, q, QUERY_REAP|QUERY_SEND); display_result_vertically= old_display_result_vertically; break; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 106ed2ec179..9d809593ea7 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1019,6 +1019,11 @@ sub kill_and_cleanup () { mtr_report("Removing Stale Files"); + if ( -l $opt_vardir and ! unlink($opt_vardir) ) + { + mtr_error("Can't remove soft link \"$opt_vardir\""); + } + rmtree("$opt_vardir/log"); rmtree("$opt_vardir/ndbcluster-$opt_ndbcluster_port"); rmtree("$opt_vardir/run"); @@ -1027,10 +1032,7 @@ sub kill_and_cleanup () { mkpath("$opt_vardir/log"); mkpath("$opt_vardir/run"); mkpath("$opt_vardir/tmp"); - if ( $opt_tmpdir ne "$opt_vardir/tmp" ) - { - mkpath($opt_tmpdir); - } + mkpath($opt_tmpdir) if $opt_tmpdir ne "$opt_vardir/tmp"; # FIXME do we really need to create these all, or are they # created for us when tables are created? From 6b4dbcb4db8236d5226284ff87af9126aa83f5b6 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 May 2005 01:54:02 +0400 Subject: [PATCH 55/63] post-review fixes include/my_sys.h: added prototype for the defaults correction function libmysql/Makefile.shared: my_chsize added to libmysql to let my_correct_defaults_file be used from libmysql mysys/default.c: New defaults function added we use it to correct defaults file. Currently the function doesn't lock defaults file. This is because of the linking and backwards-compatibility issues. This needs to be fixed later. mysys/my_chsize.c: comment added server-tools/instance-manager/buffer.cc: cleanup server-tools/instance-manager/commands.cc: refactoring: removed do_command method from most of the classes server-tools/instance-manager/commands.h: cleanup server-tools/instance-manager/guardian.cc: cleanup server-tools/instance-manager/instance.cc: cleanup server-tools/instance-manager/instance_map.cc: cleanup server-tools/instance-manager/instance_options.cc: cleanup server-tools/instance-manager/instance_options.h: cleanup server-tools/instance-manager/listener.cc: cleanup server-tools/instance-manager/log.cc: cleanup server-tools/instance-manager/manager.cc: cleanup server-tools/instance-manager/messages.cc: new errors added server-tools/instance-manager/mysql_connection.cc: cleanup server-tools/instance-manager/mysql_manager_error.h: new error codes added server-tools/instance-manager/mysqlmanager.cc: clenup server-tools/instance-manager/options.cc: cleanup server-tools/instance-manager/parse.cc: removed unused function server-tools/instance-manager/parse.h: removed prototype server-tools/instance-manager/protocol.cc: cleanup server-tools/instance-manager/protocol.h: added enum to be used in protocol.cc instead of the constants --- include/my_sys.h | 5 + libmysql/Makefile.shared | 2 +- mysys/default.c | 138 +++++ mysys/my_chsize.c | 4 +- server-tools/instance-manager/buffer.cc | 4 +- server-tools/instance-manager/commands.cc | 484 ++++++++---------- server-tools/instance-manager/commands.h | 24 +- server-tools/instance-manager/guardian.cc | 2 +- server-tools/instance-manager/instance.cc | 11 +- server-tools/instance-manager/instance_map.cc | 2 +- .../instance-manager/instance_options.cc | 111 ++-- .../instance-manager/instance_options.h | 9 +- server-tools/instance-manager/listener.cc | 25 +- server-tools/instance-manager/log.cc | 8 +- server-tools/instance-manager/manager.cc | 3 +- server-tools/instance-manager/messages.cc | 4 + .../instance-manager/mysql_connection.cc | 16 +- .../instance-manager/mysql_manager_error.h | 2 + server-tools/instance-manager/mysqlmanager.cc | 3 +- server-tools/instance-manager/options.cc | 2 +- server-tools/instance-manager/parse.cc | 43 -- server-tools/instance-manager/parse.h | 3 - server-tools/instance-manager/protocol.cc | 9 +- server-tools/instance-manager/protocol.h | 3 + 24 files changed, 472 insertions(+), 445 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index f63743a4c6c..aa8ef70e237 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -773,6 +773,11 @@ extern void reset_root_defaults(MEM_ROOT *mem_root, uint block_size, extern char *strdup_root(MEM_ROOT *root,const char *str); extern char *strmake_root(MEM_ROOT *root,const char *str,uint len); extern char *memdup_root(MEM_ROOT *root,const char *str,uint len); +extern int my_correct_defaults_file(const char *file_location, + const char *option, + const char *option_value, + const char *section_name, + int remove_option); extern void get_defaults_files(int argc, char **argv, char **defaults, char **extra_defaults); extern int load_defaults(const char *conf_file, const char **groups, diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index 204c833dd21..bcd2ec6c057 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -67,7 +67,7 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \ mf_iocache2.lo my_seek.lo my_sleep.lo \ my_pread.lo mf_cache.lo md5.lo sha1.lo \ my_getopt.lo my_gethostbyname.lo my_port.lo \ - my_rename.lo + my_rename.lo my_chsize.lo sqlobjects = net.lo sql_cmn_objects = pack.lo client.lo my_time.lo diff --git a/mysys/default.c b/mysys/default.c index 0f33c94d17e..e38babb849d 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -50,8 +50,10 @@ const char *default_directories[MAX_DEFAULT_DIRS + 1]; #ifdef __WIN__ static const char *f_extensions[]= { ".ini", ".cnf", 0 }; +#define NEWLINE "\r\n" #else static const char *f_extensions[]= { ".cnf", 0 }; +#define NEWLINE "\n" #endif /* @@ -78,6 +80,142 @@ static void init_default_directories(); static char *remove_end_comment(char *ptr); +/* + Add/remove option to the option file section. + + SYNOPSYS + my_correct_file() + file_location The location of configuration file to edit + option option to look for + option value The value of the option we would like to set + section_name the name of the section + remove_option This is true if we want to remove the option. + False otherwise. + IMPLEMENTATION + We open the option file first, then read the file line-by-line, + looking for the section we need. At the same time we put these lines + into a buffer. Then we look for the option within this section and + change/remove it. In the end we get a buffer with modified version of the + file. Then we write it to the file, truncate it if needed and close it. + + RETURN + 0 - ok + 1 - some error has occured. Probably due to the lack of resourses + -1 - cannot open the file +*/ + +int my_correct_defaults_file(const char *file_location, const char *option, + const char *option_value, + const char *section_name, int remove_option) +{ + FILE *cnf_file; + struct stat file_stat; + char linebuff[512], *ptr; + uint optlen; + uint len; + char *file_buffer; + uint position= 0; + int is_found= FALSE; + + optlen= strlen(option); + + DBUG_ENTER("my_correct_file"); + + if (!(cnf_file= my_fopen(file_location, O_RDWR, MYF(0)))) + goto err_fopen; + + /* my_fstat doesn't use the flag parameter */ + if (my_fstat(fileno(cnf_file), &file_stat, MYF(0))) + goto err; + + /* + Reserve space to read the contents of the file and some more + for the option we want ot add. + */ + file_buffer= (char*) my_malloc(sizeof(char)* + (file_stat.st_size + /* current file size */ + optlen + /* option name len */ + 2 + /* reserve space for newline */ + 1 + /* reserve for '=' char */ + strlen(option_value)), /* option value len */ + MYF(MY_WME)); + + if (!file_buffer) + goto malloc_err; + while (fgets(linebuff, sizeof(linebuff), cnf_file)) + { + len= strlen(linebuff); + + /* if the section is found traverse it */ + if (is_found) + { + /* skip the old value of the option we are changing */ + if (strncmp(linebuff, option, optlen)) + { + /* copy all other lines */ + strmake(file_buffer + position, linebuff, len); + position+= len; + } + } + else + { + strmake(file_buffer + position, linebuff, len); + position+= len; + } + + + /* looking for appropriate section */ + for (ptr= linebuff ; my_isspace(&my_charset_latin1,*ptr) ; ptr++) + {} + + if (*ptr == '[') + { + /* copy the line to the buffer */ + if (!strncmp(++ptr, section_name, strlen(section_name))) + { + is_found= TRUE; + /* add option */ + if (!remove_option) + { + strmake(file_buffer + position, option, optlen); + position+= optlen; + if (*option_value) + { + *(file_buffer + position++)= '='; + strmake(file_buffer + position, option_value, + strlen(option_value)); + position+= strlen(option_value); + } + /* add a newline */ + strcat(file_buffer + position, NEWLINE); + position+= strlen(NEWLINE); + } + } + else + is_found= FALSE; /* mark that this section is of no interest to us */ + } + + } + + if (my_chsize(fileno(cnf_file), position, 0, MYF(MY_WME)) || + my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) || + my_fwrite(cnf_file, file_buffer, position, MYF(MY_NABP)) || + my_fclose(cnf_file, MYF(MY_WME))) + goto err; + + my_free(file_buffer, MYF(0)); + + DBUG_RETURN(0); + +err: + my_free(file_buffer, MYF(0)); +malloc_err: + my_fclose(cnf_file, MYF(0)); + DBUG_RETURN(1); /* out of resources */ +err_fopen: + DBUG_RETURN(-1); /* cannot access the option file */ +} + /* Process config files in default directories. diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c index c258121226d..9760de29a08 100644 --- a/mysys/my_chsize.c +++ b/mysys/my_chsize.c @@ -30,7 +30,9 @@ MyFlags Flags DESCRIPTION - my_chsize() truncates file if shorter else fill with the filler character + my_chsize() truncates file if shorter else fill with the filler character. + The function also changes the file pointer. Usually it points to the end + of the file after execution. RETURN VALUE 0 Ok diff --git a/server-tools/instance-manager/buffer.cc b/server-tools/instance-manager/buffer.cc index b000a48d5ae..26df401c3c5 100644 --- a/server-tools/instance-manager/buffer.cc +++ b/server-tools/instance-manager/buffer.cc @@ -64,7 +64,7 @@ int Buffer::append(uint position, const char *string, uint len_arg) DESCRIPTION - The method checks whether it is possible to pus a string of teh "len_arg" + The method checks whether it is possible to put a string of the "len_arg" length into the buffer, starting from "position" byte. In the case when the buffer is too small it reallocs the buffer. The total size of the buffer is restricted with 16 Mb. @@ -81,7 +81,7 @@ int Buffer::reserve(uint position, uint len_arg) if (position + len_arg >= buffer_size) { - buffer= (char *) my_realloc(buffer, + buffer= (char*) my_realloc(buffer, min(MAX_BUFFER_SIZE, max((uint) (buffer_size*1.5), position + len_arg)), MYF(0)); diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc index 3b4c43d289c..d6d4370fb7f 100644 --- a/server-tools/instance-manager/commands.cc +++ b/server-tools/instance-manager/commands.cc @@ -25,11 +25,32 @@ #include #include +#include -/* some useful functions */ +/* + Add a string to a buffer -static int put_to_buff(Buffer *buff, const char *str, uint *position) + SYNOPSYS + put_to_buff() + buff buffer to add the string + str string to add + uint offset in the buff to add a string + + DESCRIPTION + + Function to add a string to the buffer. It is different from + store_to_string, which is used in the protocol.cc. The last + one also stores the length of the string in a special way. + This is required for MySQL client/server protocol support only. + + RETURN + 0 - ok + 1 - error occured +*/ + + +static inline int put_to_buff(Buffer *buff, const char *str, uint *position) { uint len= strlen(str); if (buff->append(*position, str, len)) @@ -47,15 +68,16 @@ static int put_to_buff(Buffer *buff, const char *str, uint *position) The method sends a list of instances in the instance map to the client. SYNOPSYS - Show_instances::do_command() - net The network connection to the client. + Show_instances::execute() + net The network connection to the client. + connection_id Client connection ID RETURN 0 - ok 1 - error occured */ -int Show_instances::do_command(struct st_net *net) +int Show_instances::execute(struct st_net *net, ulong connection_id) { Buffer send_buff; /* buffer for packets */ LIST name, status; @@ -63,11 +85,11 @@ int Show_instances::do_command(struct st_net *net) LIST *field_list; uint position=0; - name_field.name= (char *) "instance_name"; - name_field.length= 20; + name_field.name= (char*) "instance_name"; + name_field.length= DEFAULT_FIELD_LENGTH; name.data= &name_field; - status_field.name= (char *) "status"; - status_field.length= 20; + status_field.name= (char*) "status"; + status_field.length= DEFAULT_FIELD_LENGTH; status.data= &status_field; field_list= list_add(NULL, &status); field_list= list_add(field_list, &name); @@ -84,9 +106,9 @@ int Show_instances::do_command(struct st_net *net) position= 0; store_to_string(&send_buff, instance->options.instance_name, &position); if (instance->is_running()) - store_to_string(&send_buff, (char *) "online", &position); + store_to_string(&send_buff, (char*) "online", &position); else - store_to_string(&send_buff, (char *) "offline", &position); + store_to_string(&send_buff, (char*) "offline", &position); if (my_net_write(net, send_buff.buffer, (uint) position)) goto err; } @@ -99,16 +121,7 @@ int Show_instances::do_command(struct st_net *net) return 0; err: - return 1; -} - - -int Show_instances::execute(struct st_net *net, ulong connection_id) -{ - if (do_command(net)) - return ER_OUT_OF_RESOURCES; - - return 0; + return ER_OUT_OF_RESOURCES; } @@ -116,10 +129,10 @@ int Show_instances::execute(struct st_net *net, ulong connection_id) int Flush_instances::execute(struct st_net *net, ulong connection_id) { - if (instance_map->flush_instances()) + if (instance_map->flush_instances() || + net_send_ok(net, connection_id, NULL)) return ER_OUT_OF_RESOURCES; - net_send_ok(net, connection_id, NULL); return 0; } @@ -134,9 +147,7 @@ Show_instance_status::Show_instance_status(Instance_map *instance_map_arg, /* we make a search here, since we don't want to store the name */ if ((instance= instance_map->find(name, len))) - { instance_name= instance->options.instance_name; - } else instance_name= NULL; } @@ -156,8 +167,8 @@ Show_instance_status::Show_instance_status(Instance_map *instance_map_arg, */ -int Show_instance_status::do_command(struct st_net *net, - const char *instance_name) +int Show_instance_status::execute(struct st_net *net, + ulong connection_id) { enum { MAX_VERSION_LENGTH= 40 }; Buffer send_buff; /* buffer for packets */ @@ -166,14 +177,17 @@ int Show_instance_status::do_command(struct st_net *net, NAME_WITH_LENGTH name_field, status_field, version_field; uint position=0; + if (!instance_name) + return ER_BAD_INSTANCE_NAME; + /* create list of the fileds to be passed to send_fields */ - name_field.name= (char *) "instance_name"; - name_field.length= 20; + name_field.name= (char*) "instance_name"; + name_field.length= DEFAULT_FIELD_LENGTH; name.data= &name_field; - status_field.name= (char *) "status"; - status_field.length= 20; + status_field.name= (char*) "status"; + status_field.length= DEFAULT_FIELD_LENGTH; status.data= &status_field; - version_field.name= (char *) "version"; + version_field.name= (char*) "version"; version_field.length= MAX_VERSION_LENGTH; version.data= &version_field; field_list= list_add(NULL, &version); @@ -185,18 +199,18 @@ int Show_instance_status::do_command(struct st_net *net, { Instance *instance; - store_to_string(&send_buff, (char *) instance_name, &position); + store_to_string(&send_buff, (char*) instance_name, &position); if (!(instance= instance_map->find(instance_name, strlen(instance_name)))) goto err; if (instance->is_running()) { - store_to_string(&send_buff, (char *) "online", &position); + store_to_string(&send_buff, (char*) "online", &position); store_to_string(&send_buff, "unknown", &position); } else { - store_to_string(&send_buff, (char *) "offline", &position); - store_to_string(&send_buff, (char *) "unknown", &position); + store_to_string(&send_buff, (char*) "offline", &position); + store_to_string(&send_buff, (char*) "unknown", &position); } @@ -205,28 +219,13 @@ int Show_instance_status::do_command(struct st_net *net, goto err; } - send_eof(net); - net_flush(net); + if (send_eof(net) || net_flush(net)) + goto err; return 0; err: - return 1; -} - - -int Show_instance_status::execute(struct st_net *net, ulong connection_id) -{ - if ((instance_name)) - { - if (do_command(net, instance_name)) - return ER_OUT_OF_RESOURCES; - return 0; - } - else - { - return ER_BAD_INSTANCE_NAME; - } + return ER_OUT_OF_RESOURCES; } @@ -240,30 +239,29 @@ Show_instance_options::Show_instance_options(Instance_map *instance_map_arg, /* we make a search here, since we don't want to store the name */ if ((instance= instance_map->find(name, len))) - { instance_name= instance->options.instance_name; - } else instance_name= NULL; } -int Show_instance_options::do_command(struct st_net *net, - const char *instance_name) +int Show_instance_options::execute(struct st_net *net, ulong connection_id) { - enum { MAX_VERSION_LENGTH= 40 }; Buffer send_buff; /* buffer for packets */ LIST name, option; LIST *field_list; NAME_WITH_LENGTH name_field, option_field; uint position=0; + if (!instance_name) + return ER_BAD_INSTANCE_NAME; + /* create list of the fileds to be passed to send_fields */ - name_field.name= (char *) "option_name"; - name_field.length= 20; + name_field.name= (char*) "option_name"; + name_field.length= DEFAULT_FIELD_LENGTH; name.data= &name_field; - option_field.name= (char *) "value"; - option_field.length= 20; + option_field.name= (char*) "value"; + option_field.length= DEFAULT_FIELD_LENGTH; option.data= &option_field; field_list= list_add(NULL, &option); field_list= list_add(field_list, &name); @@ -275,16 +273,16 @@ int Show_instance_options::do_command(struct st_net *net, if (!(instance= instance_map->find(instance_name, strlen(instance_name)))) goto err; - store_to_string(&send_buff, (char *) "instance_name", &position); - store_to_string(&send_buff, (char *) instance_name, &position); + store_to_string(&send_buff, (char*) "instance_name", &position); + store_to_string(&send_buff, (char*) instance_name, &position); if (my_net_write(net, send_buff.buffer, (uint) position)) goto err; if ((instance->options.mysqld_path)) { position= 0; - store_to_string(&send_buff, (char *) "mysqld-path", &position); + store_to_string(&send_buff, (char*) "mysqld-path", &position); store_to_string(&send_buff, - (char *) instance->options.mysqld_path, + (char*) instance->options.mysqld_path, &position); if (send_buff.is_error() || my_net_write(net, send_buff.buffer, (uint) position)) @@ -294,7 +292,7 @@ int Show_instance_options::do_command(struct st_net *net, if ((instance->options.nonguarded)) { position= 0; - store_to_string(&send_buff, (char *) "nonguarded", &position); + store_to_string(&send_buff, (char*) "nonguarded", &position); store_to_string(&send_buff, "", &position); if (send_buff.is_error() || my_net_write(net, send_buff.buffer, (uint) position)) @@ -318,7 +316,8 @@ int Show_instance_options::do_command(struct st_net *net, /* join name and the value into the same option again */ *option_value= '='; } - else store_to_string(&send_buff, tmp_option + 2, &position); + else + store_to_string(&send_buff, tmp_option + 2, &position); if (send_buff.is_error() || my_net_write(net, send_buff.buffer, (uint) position)) @@ -326,28 +325,13 @@ int Show_instance_options::do_command(struct st_net *net, } } - send_eof(net); - net_flush(net); + if (send_eof(net) || net_flush(net)) + goto err; return 0; err: - return 1; -} - - -int Show_instance_options::execute(struct st_net *net, ulong connection_id) -{ - if ((instance_name)) - { - if (do_command(net, instance_name)) - return ER_OUT_OF_RESOURCES; - return 0; - } - else - { - return ER_BAD_INSTANCE_NAME; - } + return ER_OUT_OF_RESOURCES; } @@ -367,9 +351,7 @@ int Start_instance::execute(struct st_net *net, ulong connection_id) { uint err_code; if (instance == 0) - { return ER_BAD_INSTANCE_NAME; /* haven't found an instance */ - } else { if ((err_code= instance->start())) @@ -404,33 +386,59 @@ Show_instance_log::Show_instance_log(Instance_map *instance_map_arg, /* we make a search here, since we don't want to store the name */ if ((instance= instance_map->find(name, len))) - { instance_name= instance->options.instance_name; - } else instance_name= NULL; } -int Show_instance_log::do_command(struct st_net *net, - const char *instance_name) + +/* + Open the logfile, read requested part of the log and send the info + to the client. + + SYNOPSYS + Show_instance_log::execute() + net The network connection to the client. + connection_id Client connection ID + + DESCRIPTION + + Send a table with the content of the log requested. The function also + deals with errro handling, to be verbose. + + RETURN + ER_OFFSET_ERROR We were requested to read negative number of bytes + from the log + ER_NO_SUCH_LOG The kind log being read is not enabled in the instance + ER_GUESS_LOGFILE IM wasn't able to figure out the log placement, while + it is enabled. Probably user should specify the path + to the logfile explicitly. + ER_OPEN_LOGFILE Cannot open the logfile + ER_READ_FILE Cannot read the logfile + ER_OUT_OF_RESOURCES We weren't able to allocate some resources +*/ + +int Show_instance_log::execute(struct st_net *net, ulong connection_id) { - enum { MAX_VERSION_LENGTH= 40 }; Buffer send_buff; /* buffer for packets */ LIST name; LIST *field_list; NAME_WITH_LENGTH name_field; - uint position=0; + uint position= 0; /* create list of the fileds to be passed to send_fields */ - name_field.name= (char *) "Log"; - name_field.length= 20; + name_field.name= (char*) "Log"; + name_field.length= DEFAULT_FIELD_LENGTH; name.data= &name_field; field_list= list_add(NULL, &name); + if (!instance_name) + return ER_BAD_INSTANCE_NAME; + /* cannot read negative number of bytes */ if (offset > size) - return ER_SYNTAX_ERROR; + return ER_OFFSET_ERROR; send_fields(net, field_list); @@ -439,43 +447,28 @@ int Show_instance_log::do_command(struct st_net *net, const char *logpath; File fd; - if ((instance= instance_map->find(instance_name, strlen(instance_name))) == NULL) + if ((instance= instance_map->find(instance_name, + strlen(instance_name))) == NULL) goto err; - switch (log_type) - { - case LOG_ERROR: - logpath= instance->options.error_log; - break; - case LOG_GENERAL: - logpath= instance->options.query_log; - break; - case LOG_SLOW: - logpath= instance->options.slow_log; - break; - default: - logpath= NULL; - } + logpath= instance->options.logs[log_type]; /* Instance has no such log */ if (logpath == NULL) - { return ER_NO_SUCH_LOG; - } else if (*logpath == '\0') - { return ER_GUESS_LOGFILE; - } - if ((fd= open(logpath, O_RDONLY))) + if ((fd= my_open(logpath, O_RDONLY | O_BINARY, MYF(MY_WME))) >= 0) { size_t buff_size; int read_len; /* calculate buffer size */ struct stat file_stat; - if(fstat(fd, &file_stat)) + /* my_fstat doesn't use the flag parameter */ + if (my_fstat(fd, &file_stat, MYF(0))) goto err; buff_size= (size - offset); @@ -483,22 +476,21 @@ int Show_instance_log::do_command(struct st_net *net, /* read in one chunk */ read_len= my_seek(fd, file_stat.st_size - size, MY_SEEK_SET, MYF(0)); - char *bf= (char *) malloc(sizeof(char)*buff_size); - read_len= my_read(fd, bf, buff_size, MYF(0)); - store_to_string(&send_buff, (char *) bf, &position, read_len); + char *bf= (char*) malloc(sizeof(char)*buff_size); + if ((read_len= my_read(fd, bf, buff_size, MYF(0))) < 0) + return ER_READ_FILE; + store_to_string(&send_buff, (char*) bf, &position, read_len); close(fd); } else - { return ER_OPEN_LOGFILE; - } if (my_net_write(net, send_buff.buffer, (uint) position)) goto err; } - send_eof(net); - net_flush(net); + if (send_eof(net) || net_flush(net)) + goto err; return 0; @@ -507,20 +499,6 @@ err: } -int Show_instance_log::execute(struct st_net *net, ulong connection_id) -{ - if (instance_name != NULL) - { - return do_command(net, instance_name); - } - else - { - return ER_BAD_INSTANCE_NAME; - } -} - - - /* implementation for Show_instance_log_files: */ Show_instance_log_files::Show_instance_log_files @@ -531,48 +509,47 @@ Show_instance_log_files::Show_instance_log_files /* we make a search here, since we don't want to store the name */ if ((instance= instance_map->find(name, len))) - { instance_name= instance->options.instance_name; - } else instance_name= NULL; } /* - The method sends a table with a the list of the log files + The method sends a table with a list of log files used by the instance. SYNOPSYS - Show_instance_log_files::do_command() + Show_instance_log_files::execute() net The network connection to the client. - instance_name The name of the instance. + connection_id The ID of the client connection RETURN + ER_BAD_INSTANCE_NAME The instance name specified is not valid + ER_OUT_OF_RESOURCES some error occured 0 - ok - 1 - error occured */ - -int Show_instance_log_files::do_command(struct st_net *net, - const char *instance_name) +int Show_instance_log_files::execute(struct st_net *net, ulong connection_id) { - enum { MAX_VERSION_LENGTH= 40 }; Buffer send_buff; /* buffer for packets */ LIST name, path, size; LIST *field_list; NAME_WITH_LENGTH name_field, path_field, size_field; - uint position=0; + uint position= 0; + + if (!instance_name) + return ER_BAD_INSTANCE_NAME; /* create list of the fileds to be passed to send_fields */ - name_field.name= (char *) "Logfile"; - name_field.length= 20; + name_field.name= (char*) "Logfile"; + name_field.length= DEFAULT_FIELD_LENGTH; name.data= &name_field; - path_field.name= (char *) "Path"; - path_field.length= 20; + path_field.name= (char*) "Path"; + path_field.length= DEFAULT_FIELD_LENGTH; path.data= &path_field; - size_field.name= (char *) "Filesize"; - size_field.length= 20; + size_field.name= (char*) "Filesize"; + size_field.length= DEFAULT_FIELD_LENGTH; size.data= &size_field; field_list= list_add(NULL, &size); field_list= list_add(field_list, &path); @@ -588,7 +565,7 @@ int Show_instance_log_files::do_command(struct st_net *net, { /* We have alike structure in instance_options.cc. We use such to be able - to loop througt the options, which we need to handle in some common way. + to loop through the options, which we need to handle in some common way. */ struct log_files_st { @@ -596,72 +573,59 @@ int Show_instance_log_files::do_command(struct st_net *net, const char *value; } logs[]= { - {"ERROR LOG", instance->options.error_log}, - {"GENERAL LOG", instance->options.query_log}, - {"SLOW LOG", instance->options.slow_log}, + {"ERROR LOG", instance->options.logs[LOG_ERROR]}, + {"GENERAL LOG", instance->options.logs[LOG_GENERAL]}, + {"SLOW LOG", instance->options.logs[LOG_SLOW]}, {NULL, NULL} }; struct log_files_st *log_files; - - instance->options.print_argv(); for (log_files= logs; log_files->name; log_files++) { if (log_files->value != NULL) { struct stat file_stat; - char buff[20]; + /* + Save some more space for the log file names. In fact all + we need is srtlen("GENERAL_LOG") + 1 + */ + enum { LOG_NAME_BUFFER_SIZE= 20 }; + char buff[LOG_NAME_BUFFER_SIZE]; position= 0; /* store the type of the log in the send buffer */ store_to_string(&send_buff, log_files->name, &position); - switch (stat(log_files->value, &file_stat)) { - case 0: - if (S_ISREG(file_stat.st_mode)) - { - store_to_string(&send_buff, - (char *) log_files->value, - &position); - int10_to_str(file_stat.st_size, buff, 10); - store_to_string(&send_buff, (char *) buff, &position); - break; - } - default: - store_to_string(&send_buff, - "", - &position); - store_to_string(&send_buff, (char *) "0", &position); + if (stat(log_files->value, &file_stat)) + { + store_to_string(&send_buff, "", &position); + store_to_string(&send_buff, (char*) "0", &position); } + else if (S_ISREG(file_stat.st_mode)) + { + store_to_string(&send_buff, + (char*) log_files->value, + &position); + int10_to_str(file_stat.st_size, buff, 10); + store_to_string(&send_buff, (char*) buff, &position); + } + if (my_net_write(net, send_buff.buffer, (uint) position)) goto err; } } } - send_eof(net); - net_flush(net); + if (send_eof(net) || net_flush(net)) + goto err; return 0; err: - return 1; -} -int Show_instance_log_files::execute(struct st_net *net, ulong connection_id) -{ - if (instance_name != NULL) - { - if (do_command(net, instance_name)) - return ER_OUT_OF_RESOURCES; - return 0; - } - else - { - return ER_BAD_INSTANCE_NAME; - } + return ER_OUT_OF_RESOURCES; } -/* implementation for SET nstance_name.option=option_value: */ +/* implementation for SET instance_name.option=option_value: */ Set_option::Set_option(Instance_map *instance_map_arg, const char *name, uint len, @@ -679,10 +643,12 @@ Set_option::Set_option(Instance_map *instance_map_arg, if ((option_len_arg < MAX_OPTION_LEN - 1) || (option_value_len_arg < MAX_OPTION_LEN - 1)) { - strncpy(option, option_arg, option_len_arg); + strmake(option, option_arg, option_len_arg); + strmake(option_value, option_value_arg, option_value_len_arg); +/* strncpy(option, option_arg, option_len_arg); option[option_len_arg]= 0; strncpy(option_value, option_value_arg, option_value_len_arg); - option_value[option_value_len_arg]= 0; + option_value[option_value_len_arg]= 0; */ } else { @@ -700,89 +666,38 @@ Set_option::Set_option(Instance_map *instance_map_arg, /* - Correct the file. skip option could be used in future if we don't want to - let user change the options file (E.g. he lacks permissions to do that) + The method sends a table with a list of log files + used by the instance. + + SYNOPSYS + Set_option::correct_file() + skip Skip the option, being searched while writing the result file. + That is, to delete it. + + DESCRIPTION + + Correct the option file. The "skip" option is used to remove the found + option. + + RETURN + ER_BAD_INSTANCE_NAME The instance name specified is not valid + ER_ACCESS_OPTION_FILE Cannot access the option file + 0 - ok */ -int Set_option::correct_file(bool skip) + +int Set_option::correct_file(int skip) { - FILE *cnf_file; - const char *default_location="/etc/my.cnf"; - char linebuff[4096], *ptr; - uint optlen; - Buffer file_buffer; - uint position= 0; - bool isfound= false; + int error; - optlen= strlen(option); - - if (!(cnf_file= my_fopen(default_location, O_RDONLY, MYF(0)))) - goto err_fopen; - - while (fgets(linebuff, sizeof(linebuff), cnf_file)) - { - /* if the section is found traverse it */ - if (isfound) - { - /* skip the old value of the option we are changing */ - if (strncmp(linebuff, option, optlen)) - { - /* copy all other lines line */ - put_to_buff(&file_buffer, linebuff, &position); - } - } - else - put_to_buff(&file_buffer, linebuff, &position); - - /* looking for appropriate instance section */ - for (ptr= linebuff ; my_isspace(&my_charset_latin1,*ptr) ; ptr++); - if (*ptr == '[') - { - /* copy the line to the buffer */ - if (!strncmp(++ptr, instance_name, instance_name_len)) - { - isfound= true; - /* add option */ - if (!skip) - { - put_to_buff(&file_buffer, option, &position); - if (option_value[0] != 0) - { - put_to_buff(&file_buffer, "=", &position); - put_to_buff(&file_buffer, option_value, &position); - } - /* add a newline */ - put_to_buff(&file_buffer, "\n", &position); - } - } - else - isfound= false; /* mark that this section is of no interest to us */ - } - - } - - if (my_fclose(cnf_file, MYF(0))) - goto err; - - /* we must hold an instance_map mutex while changing config file */ - instance_map->lock(); - - if (!(cnf_file= my_fopen(default_location, O_WRONLY|O_TRUNC, MYF(0)))) - goto err; - if (my_fwrite(cnf_file, file_buffer.buffer, position, MYF(MY_NABP))) - goto err; - - if (my_fclose(cnf_file, MYF(0))) - goto err; - - instance_map->unlock(); + error= my_correct_defaults_file("/etc/my.cnf", option, + option_value, instance_name, skip); + if (error > 0) + return ER_OUT_OF_RESOURCES; + else if (error < 0) + return ER_ACCESS_OPTION_FILE; + /* everything was fine */ return 0; - -err: - my_fclose(cnf_file, MYF(0)); - return ER_OUT_OF_RESOURCES; -err_fopen: - return ER_ACCESS_OPTION_FILE; } @@ -801,7 +716,14 @@ err_fopen: int Set_option::do_command(struct st_net *net) { - return correct_file(false); + int error= 0; + + /* we must hold the instance_map mutex while changing config file */ + instance_map->lock(); + error= correct_file(FALSE); + instance_map->unlock(); + + return error; } @@ -821,9 +743,7 @@ int Set_option::execute(struct st_net *net, ulong connection_id) return val; } else - { return ER_BAD_INSTANCE_NAME; - } } @@ -831,7 +751,7 @@ int Set_option::execute(struct st_net *net, ulong connection_id) int Unset_option::do_command(struct st_net *net) { - return correct_file(true); + return correct_file(TRUE); } @@ -852,9 +772,7 @@ int Stop_instance::execute(struct st_net *net, ulong connection_id) uint err_code; if (instance == 0) - { return ER_BAD_INSTANCE_NAME; /* haven't found an instance */ - } else { if (!(instance->options.nonguarded)) diff --git a/server-tools/instance-manager/commands.h b/server-tools/instance-manager/commands.h index 46cd0893759..bfd38d34889 100644 --- a/server-tools/instance-manager/commands.h +++ b/server-tools/instance-manager/commands.h @@ -31,7 +31,6 @@ public: Show_instances(Instance_map *instance_map_arg): Command(instance_map_arg) {} - int do_command(struct st_net *net); int execute(struct st_net *net, ulong connection_id); }; @@ -60,8 +59,8 @@ class Show_instance_status : public Command { public: - Show_instance_status(Instance_map *instance_map_arg, const char *name, uint len); - int do_command(struct st_net *net, const char *instance_name); + Show_instance_status(Instance_map *instance_map_arg, + const char *name, uint len); int execute(struct st_net *net, ulong connection_id); const char *instance_name; }; @@ -76,10 +75,10 @@ class Show_instance_options : public Command { public: - Show_instance_options(Instance_map *instance_map_arg, const char *name, uint len); + Show_instance_options(Instance_map *instance_map_arg, + const char *name, uint len); int execute(struct st_net *net, ulong connection_id); - int do_command(struct st_net *net, const char *instance_name); const char *instance_name; }; @@ -129,7 +128,6 @@ public: Show_instance_log(Instance_map *instance_map_arg, const char *name, uint len, Log_type log_type_arg, const char *size_arg, const char *offset_arg); - int do_command(struct st_net *net, const char *instance_name); int execute(struct st_net *net, ulong connection_id); Log_type log_type; const char *instance_name; @@ -147,8 +145,8 @@ class Show_instance_log_files : public Command { public: - Show_instance_log_files(Instance_map *instance_map_arg, const char *name, uint len); - int do_command(struct st_net *net, const char *instance_name); + Show_instance_log_files(Instance_map *instance_map_arg, + const char *name, uint len); int execute(struct st_net *net, ulong connection_id); const char *instance_name; const char *option; @@ -156,10 +154,10 @@ public: /* - Syntax error command. This command is issued if parser reported a syntax error. - We need it to distinguish the parse error and the situation when parser internal - error occured. E.g. parsing failed because we hadn't had enought memory. In the - latter case parse_command() should return an error. + Syntax error command. This command is issued if parser reported a syntax + error. We need it to distinguish the parse error and the situation when + parser internal error occured. E.g. parsing failed because we hadn't had + enought memory. In the latter case parse_command() should return an error. */ class Syntax_error : public Command @@ -185,7 +183,7 @@ public: virtual int do_command(struct st_net *net); int execute(struct st_net *net, ulong connection_id); protected: - int correct_file(bool skip); + int correct_file(int skip); public: const char *instance_name; uint instance_name_len; diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc index 5d89f167f2f..404e9f34ab5 100644 --- a/server-tools/instance-manager/guardian.cc +++ b/server-tools/instance-manager/guardian.cc @@ -315,7 +315,7 @@ int Guardian_thread::guard(Instance *instance, bool nolock) content->restart_counter= 0; content->crash_moment= 0; content->state= NOT_STARTED; - node->data= (void *) content; + node->data= (void*) content; if (nolock) guarded_instances= list_add(guarded_instances, node); diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index 9fdcab7ce7c..615f16f9e22 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -304,12 +304,11 @@ void Instance::kill_instance(int signum) */ if (!kill(pid, signum)) options.unlink_pidfile(); - else - if (signum == SIGKILL) /* really killed instance with SIGKILL */ - log_error("The instance %s is being stopped forsibly. Normally \ - it should not happed. Probably the instance has been \ - hanging. You should also check your IM setup", - options.instance_name); + else if (signum == SIGKILL) /* really killed instance with SIGKILL */ + log_error("The instance %s is being stopped forsibly. Normally \ + it should not happed. Probably the instance has been \ + hanging. You should also check your IM setup", + options.instance_name); } return; } diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc index 3e76c24a9a1..792ffff5fb6 100644 --- a/server-tools/instance-manager/instance_map.cc +++ b/server-tools/instance-manager/instance_map.cc @@ -246,7 +246,7 @@ int Instance_map::load() argv_options[1]= '\0'; if (my_search_option_files("my", &argc, (char ***) &argv, &args_used, - process_option, (void *) this) || + process_option, (void*) this) || complete_initialization()) return 1; diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index ce7d43db74a..b2602af6066 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -21,7 +21,6 @@ #include "instance_options.h" #include "parse_output.h" -#include "parse.h" #include "buffer.h" #include @@ -36,7 +35,7 @@ get_default_option() result buffer to put found value result_len buffer size - oprion_name the name of the option, prefixed with "--" + option_name the name of the option, prefixed with "--" DESCRIPTION @@ -47,6 +46,7 @@ 1 - error occured */ + int Instance_options::get_default_option(char *result, size_t result_len, const char *option_name) { @@ -76,16 +76,30 @@ err: } +/* + Get compiled-in value of default_option + + SYNOPSYS + get_default_option() + result buffer to put found value + result_len buffer size + option_name the name of the option, prefixed with "--" + + DESCRIPTION + + Get compile-in value of requested option from server + + RETURN + 0 - ok + 1 - error occured +*/ + int Instance_options::fill_log_options() { - /* array for the log option for mysqld */ - enum { MAX_LOG_OPTIONS= 8 }; - enum { MAX_LOG_OPTION_LENGTH= 256 }; - /* the last option must be '\0', so we reserve space for it */ - char log_options[MAX_LOG_OPTIONS + 1][MAX_LOG_OPTION_LENGTH]; Buffer buff; uint position= 0; char **tmp_argv= argv; + enum { MAX_LOG_OPTION_LENGTH= 256 }; char datadir[MAX_LOG_OPTION_LENGTH]; char hostname[MAX_LOG_OPTION_LENGTH]; uint hostname_length; @@ -93,43 +107,17 @@ int Instance_options::fill_log_options() { const char *name; uint length; - const char **value; + char **value; const char *default_suffix; - } logs[]= + } logs_st[]= { - {"--log-error", 11, &error_log, ".err"}, - {"--log", 5, &query_log, ".log"}, - {"--log-slow-queries", 18, &slow_log, "-slow.log"}, + {"--log-error", 11, &(logs[LOG_ERROR]), ".err"}, + {"--log", 5, &(logs[LOG_GENERAL]), ".log"}, + {"--log-slow-queries", 18, &(logs[LOG_SLOW]), "-slow.log"}, {NULL, 0, NULL, NULL} }; struct log_files_st *log_files; - /* clean the buffer before usage */ - bzero(log_options, sizeof(log_options)); - - /* create a "mysqld " command in the buffer */ - buff.append(position, mysqld_path, strlen(mysqld_path)); - position= strlen(mysqld_path); - - /* skip the first option */ - tmp_argv++; - - while (*tmp_argv != 0) - { - buff.append(position, " ", 1); - position++; - buff.append(position, *tmp_argv, strlen(*tmp_argv)); - position+= strlen(*tmp_argv); - tmp_argv++; - } - - buff.append(position, "\0", 1); - position++; - - /* get options and parse them */ - if (parse_arguments(buff.buffer, "--log", (char *) log_options, - MAX_LOG_OPTIONS + 1, MAX_LOG_OPTION_LENGTH)) - goto err; /* compute hostname and datadir for the instance */ if (mysqld_datadir == NULL) { @@ -148,11 +136,11 @@ int Instance_options::fill_log_options() hostname_length= strlen(hostname); - for (log_files= logs; log_files->name; log_files++) + for (log_files= logs_st; log_files->name; log_files++) { - for (int i=0; (i < MAX_LOG_OPTIONS) && (log_options[i][0] != '\0'); i++) + for (int i=0; (argv[i] != 0); i++) { - if (!strncmp(log_options[i], log_files->name, log_files->length)) + if (!strncmp(argv[i], log_files->name, log_files->length)) { /* This is really log_files->name option if and only if it is followed @@ -160,8 +148,8 @@ int Instance_options::fill_log_options() options as '--log' and '--log-bin'. This is checked in the following two statements. */ - if (log_options[i][log_files->length] == '\0' || - my_isspace(default_charset_info, log_options[i][log_files->length])) + if (argv[i][log_files->length] == '\0' || + my_isspace(default_charset_info, argv[i][log_files->length])) { char full_name[MAX_LOG_OPTION_LENGTH]; @@ -178,21 +166,25 @@ int Instance_options::fill_log_options() else goto err; - *(log_files->value)= strdup_root(&alloc, datadir); + /* + If there were specified two identical logfiles options, + we would loose some memory in MEM_ROOT here. However + this situation is not typical. + */ + *(log_files->value)= strdup_root(&alloc, full_name); } - if (log_options[i][log_files->length] == '=') + if (argv[i][log_files->length] == '=') { char full_name[MAX_LOG_OPTION_LENGTH]; - fn_format(full_name, log_options[i] +log_files->length + 1, + fn_format(full_name, argv[i] +log_files->length + 1, datadir, "", MY_UNPACK_FILENAME | MY_SAFE_PATH); if (!(*(log_files->value)= strdup_root(&alloc, full_name))) goto err; } - } } } @@ -205,6 +197,25 @@ err: } +/* + Get the full pid file name with path + + SYNOPSYS + get_pid_filaname() + result buffer to sotre the pidfile value + + IMPLEMENTATION + Get the data directory, then get the pid filename + (which is always set for an instance), then load the + full path with my_load_path(). It takes into account + whether it is already an absolute path or it should be + prefixed with the datadir and so on. + + RETURN + 0 - ok + 1 - error occured +*/ + int Instance_options::get_pid_filename(char *result) { const char *pid_file= mysqld_pid_file; @@ -405,7 +416,7 @@ int Instance_options::add_to_argv(const char* option) DBUG_ASSERT(filled_default_options < MAX_NUMBER_OF_DEFAULT_OPTIONS); if ((option)) - argv[filled_default_options++]= (char *) option; + argv[filled_default_options++]= (char*) option; return 0; } @@ -433,10 +444,10 @@ int Instance_options::init(const char *instance_name_arg) init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0); - if (my_init_dynamic_array(&options_array, sizeof(char *), 0, 32)) + if (my_init_dynamic_array(&options_array, sizeof(char*), 0, 32)) goto err; - if (!(instance_name= strmake_root(&alloc, (char *) instance_name_arg, + if (!(instance_name= strmake_root(&alloc, (char*) instance_name_arg, instance_name_len))) goto err; diff --git a/server-tools/instance-manager/instance_options.h b/server-tools/instance-manager/instance_options.h index 4def59b75a2..ebeeaa1978e 100644 --- a/server-tools/instance-manager/instance_options.h +++ b/server-tools/instance-manager/instance_options.h @@ -18,6 +18,7 @@ #include #include +#include "parse.h" #ifdef __GNUC__ #pragma interface @@ -40,8 +41,7 @@ public: mysqld_socket(0), mysqld_datadir(0), mysqld_bind_address(0), mysqld_pid_file(0), mysqld_port(0), mysqld_port_val(0), mysqld_path(0), nonguarded(0), shutdown_delay(0), - shutdown_delay_val(0), error_log(0), query_log(0), slow_log(0), - filled_default_options(0) + shutdown_delay_val(0), filled_default_options(0) {} ~Instance_options(); /* fills in argv */ @@ -77,9 +77,8 @@ public: const char *nonguarded; const char *shutdown_delay; uint shutdown_delay_val; - const char *error_log; - const char *query_log; - const char *slow_log; + /* log enums are defined in parse.h */ + char *logs[3]; /* this value is computed and cashed here */ DYNAMIC_ARRAY options_array; diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc index 946bab11a2e..98f5b64ca92 100644 --- a/server-tools/instance-manager/listener.cc +++ b/server-tools/instance-manager/listener.cc @@ -241,23 +241,20 @@ void Listener_thread::run() } } } - else - if (FD_ISSET(ip_socket, &read_fds_arg)) + else if (FD_ISSET(ip_socket, &read_fds_arg)) + { + int client_fd= accept(ip_socket, 0, 0); + /* accept may return -1 (failure or spurious wakeup) */ + if (client_fd >= 0) // connection established { - int client_fd= accept(ip_socket, 0, 0); - /* accept may return -1 (failure or spurious wakeup) */ - if (client_fd >= 0) // connection established + if (Vio *vio= vio_new(client_fd, VIO_TYPE_TCPIP, 0)) + handle_new_mysql_connection(vio); + else { - if (Vio *vio= vio_new(client_fd, VIO_TYPE_TCPIP, 0)) - { - handle_new_mysql_connection(vio); - } - else - { - shutdown(client_fd, SHUT_RDWR); - close(client_fd); - } + shutdown(client_fd, SHUT_RDWR); + close(client_fd); } + } } } } diff --git a/server-tools/instance-manager/log.cc b/server-tools/instance-manager/log.cc index 5491b4e70e9..88d777eeeb6 100644 --- a/server-tools/instance-manager/log.cc +++ b/server-tools/instance-manager/log.cc @@ -70,7 +70,7 @@ static inline void log(FILE *file, const char *format, va_list args) if (n < 0 || n == sizeof(buff_stack)) { int size= sizeof(buff_stack) * 2; - buff_msg= (char *) my_malloc(size, 0); + buff_msg= (char*) my_malloc(size, MYF(0)); while (true) { if (buff_msg == 0) @@ -86,16 +86,16 @@ static inline void log(FILE *file, const char *format, va_list args) size*= 2; /* realloc() does unnecessary memcpy */ my_free(buff_msg, 0); - buff_msg= (char *) my_malloc(size, 0); + buff_msg= (char*) my_malloc(size, MYF(0)); } } else if ((size_t) n > sizeof(buff_stack)) { - buff_msg= (char *) my_malloc(n + 1, 0); + buff_msg= (char*) my_malloc(n + 1, MYF(0)); #ifdef DBUG DBUG_ASSERT(n == vsnprintf(buff_msg, n + 1, format, args)); #else - vsnprintf(buff_msg, n + 1, format, args); + vsnprintf(buff_msg, n + 1, format, args); #endif } fprintf(file, "%s%s\n", buff_date, buff_msg); diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc index fd8673c4d66..a4c81739b17 100644 --- a/server-tools/instance-manager/manager.cc +++ b/server-tools/instance-manager/manager.cc @@ -197,8 +197,7 @@ void manager(const Options &options) goto err; } - switch (signo) - { + switch (signo) { case THR_SERVER_ALARM: process_alarm(signo); break; diff --git a/server-tools/instance-manager/messages.cc b/server-tools/instance-manager/messages.cc index 69bc8507c2e..a9b00b9e01f 100644 --- a/server-tools/instance-manager/messages.cc +++ b/server-tools/instance-manager/messages.cc @@ -55,8 +55,12 @@ static const char *mysqld_error_message(unsigned sql_errno) case ER_CANNOT_START_INSTANCE: return "Cannot start instance. Possible reasons are wrong instance options" " or resources shortage"; + case ER_OFFSET_ERROR: + return "Cannot read negative number of bytes"; case ER_STOP_INSTANCE: return "Cannot stop instance"; + case ER_READ_FILE: + return "Cannot read requested part of the logfile"; case ER_NO_SUCH_LOG: return "The instance has no such log enabled"; case ER_OPEN_LOGFILE: diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc index 036d0887d18..05fb6d4e0fb 100644 --- a/server-tools/instance-manager/mysql_connection.cc +++ b/server-tools/instance-manager/mysql_connection.cc @@ -261,10 +261,10 @@ int Mysql_connection_thread::check_connection() } client_capabilities|= ((ulong) uint2korr(net.read_pos + 2)) << 16; - pos= (char *) net.read_pos + 32; + pos= (char*) net.read_pos + 32; /* At least one byte for username and one byte for password */ - if (pos >= (char *) net.read_pos + pkt_len + 2) + if (pos >= (char*) net.read_pos + pkt_len + 2) { /*TODO add user and password handling in error messages*/ net_send_error(&net, ER_HANDSHAKE_ERROR); @@ -301,9 +301,7 @@ int Mysql_connection_thread::do_command() { /* Check if we can continue without closing the connection */ if (net.error != 3) // what is 3 - find out - { return 1; - } if (thread_registry.is_shutdown()) return 1; net_send_error(&net, net.last_errno); @@ -346,14 +344,12 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command, res= command->execute(&net, connection_id); delete command; if (!res) - { - log_info("query for connection %d executed ok",connection_id); - } + log_info("query for connection %d executed ok",connection_id); else { - log_info("query for connection %d executed err=%d",connection_id,res); - net_send_error(&net, res); - return 0; + log_info("query for connection %d executed err=%d",connection_id,res); + net_send_error(&net, res); + return 0; } } else diff --git a/server-tools/instance-manager/mysql_manager_error.h b/server-tools/instance-manager/mysql_manager_error.h index afb9affe621..ff782923a8e 100644 --- a/server-tools/instance-manager/mysql_manager_error.h +++ b/server-tools/instance-manager/mysql_manager_error.h @@ -27,5 +27,7 @@ #define ER_OPEN_LOGFILE 3006 #define ER_GUESS_LOGFILE 3007 #define ER_ACCESS_OPTION_FILE 3008 +#define ER_OFFSET_ERROR 3009 +#define ER_READ_FILE 3010 #endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_MANAGER_ERROR_H */ diff --git a/server-tools/instance-manager/mysqlmanager.cc b/server-tools/instance-manager/mysqlmanager.cc index 262686c3fab..5a6c398614b 100644 --- a/server-tools/instance-manager/mysqlmanager.cc +++ b/server-tools/instance-manager/mysqlmanager.cc @@ -136,7 +136,8 @@ static struct passwd *check_user(const char *user) { /* Allow a numeric uid to be used */ const char *pos; - for (pos= user; my_isdigit(default_charset_info, *pos); pos++) ; + for (pos= user; my_isdigit(default_charset_info, *pos); pos++) + {} if (*pos) /* Not numeric id */ goto err; if (!(user_info= getpwuid(atoi(user)))) diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc index 4568d6b578d..28899940e47 100644 --- a/server-tools/instance-manager/options.cc +++ b/server-tools/instance-manager/options.cc @@ -158,7 +158,7 @@ static void passwd() fprintf(stderr, "Creating record for new user.\n"); fprintf(stderr, "Enter user name: "); - if (! fgets(user, sizeof(user), stdin)) + if (!fgets(user, sizeof(user), stdin)) { fprintf(stderr, "Unable to read user.\n"); return; diff --git a/server-tools/instance-manager/parse.cc b/server-tools/instance-manager/parse.cc index 8af7c88ece2..fae69375b61 100644 --- a/server-tools/instance-manager/parse.cc +++ b/server-tools/instance-manager/parse.cc @@ -198,9 +198,7 @@ Command *parse_command(Command_factory *factory, const char *text) /* should be empty */ get_word(&text, &word_len); if (word_len) - { goto syntax_error; - } if (skip) command= factory->new_Unset_option(instance_name, instance_name_len, @@ -330,44 +328,3 @@ syntax_error: } return command; } - -/* additional parse function, needed to parse */ - -/* create an array of strings from the output, starting from "word" */ -int parse_arguments(const char *command, const char *word, char *result, - int max_result_cardinality, size_t option_len) -{ - int wordlen; - int i= 0; /* result array index */ - /* should be enough to store the string from the output */ - enum { MAX_LINE_LEN= 4096 }; - char linebuf[MAX_LINE_LEN]; - - wordlen= strlen(word); - - uint lineword_len= 0; - const char *linep= command; - get_word((const char **) &linep, &lineword_len, NONSPACE); - while ((*linep != '\0') && (i < max_result_cardinality)) - { - if (!strncmp(word, linep, wordlen)) - { - strncpy(result + i*option_len, linep, lineword_len); - *(result + i*option_len + lineword_len)= '\0'; - linep+= lineword_len; - i++; - } - else - linep+= lineword_len; - get_word((const char **) &linep, &lineword_len, NONSPACE); - - /* stop if we've filled the array */ - if (i >= max_result_cardinality) - break; - } - - - return 0; -} - - diff --git a/server-tools/instance-manager/parse.h b/server-tools/instance-manager/parse.h index f03ef4c8a00..0cfa33723c9 100644 --- a/server-tools/instance-manager/parse.h +++ b/server-tools/instance-manager/parse.h @@ -31,9 +31,6 @@ enum Log_type Command *parse_command(Command_factory *factory, const char *text); -int parse_arguments(const char *command, const char *word, char *result, - int max_result_cardinality, size_t option_len); - /* define kinds of the word seek method */ enum { ALPHANUM= 1, NONSPACE }; diff --git a/server-tools/instance-manager/protocol.cc b/server-tools/instance-manager/protocol.cc index f0928743716..62de48d0619 100644 --- a/server-tools/instance-manager/protocol.cc +++ b/server-tools/instance-manager/protocol.cc @@ -122,6 +122,7 @@ int store_to_string(Buffer *buf, const char *string, uint *position, { uint currpos; + /* reserve max amount of bytes needed to store length */ if (buf->reserve(*position, 9)) goto err; currpos= (net_store_length(buf->buffer + *position, @@ -175,10 +176,10 @@ int send_fields(struct st_net *net, LIST *fields) position= 0; field= (NAME_WITH_LENGTH *) tmp->data; - store_to_string(&send_buff, (char *) "", &position); /* catalog name */ - store_to_string(&send_buff, (char *) "", &position); /* db name */ - store_to_string(&send_buff, (char *) "", &position); /* table name */ - store_to_string(&send_buff, (char *) "", &position); /* table name alias */ + store_to_string(&send_buff, (char*) "", &position); /* catalog name */ + store_to_string(&send_buff, (char*) "", &position); /* db name */ + store_to_string(&send_buff, (char*) "", &position); /* table name */ + store_to_string(&send_buff, (char*) "", &position); /* table name alias */ store_to_string(&send_buff, field->name, &position); /* column name */ store_to_string(&send_buff, field->name, &position); /* column name alias */ send_buff.reserve(position, 12); diff --git a/server-tools/instance-manager/protocol.h b/server-tools/instance-manager/protocol.h index c853fa10483..a2ed9a31889 100644 --- a/server-tools/instance-manager/protocol.h +++ b/server-tools/instance-manager/protocol.h @@ -25,6 +25,9 @@ typedef struct field { uint length; } NAME_WITH_LENGTH; +/* default field length to be used in various field-realted functions */ +enum { DEFAULT_FIELD_LENGTH= 20 }; + struct st_net; int net_send_ok(struct st_net *net, unsigned long connection_id, From 94f3584bc7455b7ac48bac6e69d9179ff31e46d7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 May 2005 01:08:42 +0200 Subject: [PATCH 56/63] mysqltest.c: To solve bug#8455, call mysql_affected_rows() earlier, before query to find warnings client/mysqltest.c: To solve bug#8455, call mysql_affected_rows() earlier, before query to find warnings --- client/mysqltest.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 1f95f1eaeeb..e60d9ecd1c5 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2597,6 +2597,8 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) if (!disable_result_log) { + ulong affected_rows; /* Ok to be undef if 'disable_info' is set */ + if (res) { MYSQL_FIELD *field= mysql_fetch_fields(res); @@ -2619,6 +2621,13 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) append_result(ds, res); } + /* + Need to call mysql_affected_rows() before the new + query to find the warnings + */ + if (!disable_info) + affected_rows= (ulong)mysql_affected_rows(mysql); + /* Add all warnings to the result */ if (!disable_warnings && mysql_warning_count(mysql)) { @@ -2641,7 +2650,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) if (!disable_info) { char buf[40]; - sprintf(buf,"affected rows: %lu\n",(ulong) mysql_affected_rows(mysql)); + sprintf(buf,"affected rows: %lu\n", affected_rows); dynstr_append(ds, buf); if (mysql_info(mysql)) { From eaa7615eb1e1cb2f08248a64cf6bdf46fbf75117 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 May 2005 13:40:57 +0500 Subject: [PATCH 57/63] a fix (bug #10655: mysys/default.c compilation problem). mysys/default.c: a fix (bug #10655: mysys/default.c compilation problem). DBUG_ENTER() must be the first. --- mysys/default.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mysys/default.c b/mysys/default.c index a680915b6d5..ba1a6c1513b 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -117,11 +117,10 @@ int my_correct_defaults_file(const char *file_location, const char *option, char *file_buffer; uint position= 0; int is_found= FALSE; + DBUG_ENTER("my_correct_defaults_file"); optlen= strlen(option); - DBUG_ENTER("my_correct_file"); - if (!(cnf_file= my_fopen(file_location, O_RDWR, MYF(0)))) goto err_fopen; From b0fc53f336f6380117bff7b1e647f3e7a9cc9800 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 May 2005 11:24:41 +0200 Subject: [PATCH 58/63] Build fixes configure.in: Fix for build problems - Removing extra semicolon and parentheses, this is not C++ :) --- configure.in | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/configure.in b/configure.in index cd4f011e1ce..3e116d608f7 100644 --- a/configure.in +++ b/configure.in @@ -1374,20 +1374,20 @@ then AC_MSG_CHECKING("for gcc") if expr "$CC" : ".*gcc.*" then - CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; - CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; + CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" + CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" else - CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; - CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; + CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" + CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" fi else - { AC_MSG_ERROR([configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual.]) }; + AC_MSG_ERROR([configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual.]) fi else AC_MSG_RESULT("no") fi else - AC_MSG_ERROR([On SCO UNIX MySQL requires that the FSUThreads package is installed. See the Installation chapter in the Reference Manual.]); + AC_MSG_ERROR([On SCO UNIX MySQL requires that the FSUThreads package is installed. See the Installation chapter in the Reference Manual.]) fi else AC_MSG_RESULT("no") @@ -1419,15 +1419,15 @@ then AC_MSG_CHECKING("for gcc") if expr "$CC" : ".*gcc.*" then - CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; - CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; + CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" + CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" else - CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; - CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; + CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" + CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" fi AC_MSG_RESULT("yes") else - { AC_MSG_ERROR([configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual.]) }; + AC_MSG_ERROR([configure: error: Can't find thread libs on SCO UnixWare7. See the Installation chapter in the Reference Manual.]) fi else AC_MSG_RESULT("no") @@ -1462,15 +1462,15 @@ then AC_MSG_CHECKING("for gcc") if expr "$CC" : ".*gcc.*" then - CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; - CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; + CC="$CC -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" + CXX="$CXX -pthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" else - CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; - CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"; + CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" + CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK" fi AC_MSG_RESULT("yes") else - { AC_MSG_ERROR([configure: error: Can't find thread libs on Caldera OpenUNIX 8. See the Installation chapter in the Reference Manual.]) }; + AC_MSG_ERROR([configure: error: Can't find thread libs on Caldera OpenUNIX 8. See the Installation chapter in the Reference Manual.]) fi else AC_MSG_RESULT("no") From 70c4325d67256c44c47d41b7ef68ef5e7e9a3751 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 May 2005 13:34:23 +0300 Subject: [PATCH 59/63] Fixed failing tests for not 32 bit intel machines Fixed bug in mysql_stmt_fetch() when retrieving rows to return mysql-test/r/ps.result: Fix to not get warnings if mysql_client_test.test fails mysql-test/t/index_merge_ror.test: Proper fix for 64 bit intel (which gives uses another, equal good index) mysql-test/t/ps.test: Fix to not get warnings if mysql_client_test.test fails sql-common/client.c: More debugging sql/sql_prepare.cc: Fixed bug in mysql_stmt_fetch() when retrieving rows to return sql/sql_select.cc: More debugging tests/mysql_client_test.c: More debugging --- mysql-test/r/ps.result | 1 + mysql-test/t/index_merge_ror.test | 2 +- mysql-test/t/ps.test | 3 +++ sql-common/client.c | 9 ++++++--- sql/sql_prepare.cc | 10 +++++----- sql/sql_select.cc | 4 +++- tests/mysql_client_test.c | 9 ++++++--- 7 files changed, 25 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index c84c62442ef..8371437d664 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1,4 +1,5 @@ drop table if exists t1,t2; +drop database if exists client_test_db; create table t1 ( a int primary key, diff --git a/mysql-test/t/index_merge_ror.test b/mysql-test/t/index_merge_ror.test index 15c596ce149..48fe5526f11 100644 --- a/mysql-test/t/index_merge_ror.test +++ b/mysql-test/t/index_merge_ror.test @@ -185,7 +185,7 @@ explain select st_a from t1 ignore index (st_a) where st_a=1 and st_b=1; # # Different value on 32 and 64 bit ---replace sta_swt12a sta_swt21a +--replace_result sta_swt12a sta_swt21a sta_swt12a, sta_swt12a, explain select * from t1 where st_a=1 and swt1a=1 and swt2a=1; explain select * from t1 where st_b=1 and swt1b=1 and swt2b=1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index b06d3c4caf0..f4396e41a20 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -3,6 +3,9 @@ # --disable_warnings drop table if exists t1,t2; + +# Avoid wrong warnings if mysql_client_test fails +drop database if exists client_test_db; --enable_warnings create table t1 diff --git a/sql-common/client.c b/sql-common/client.c index 4cbdb4b8e0d..0bebcb0065d 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -650,6 +650,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, NET *net= &mysql->net; my_bool result= 1; init_sigpipe_variables + DBUG_ENTER("cli_advanced_command"); /* Don't give sigpipe errors if the client doesn't want them */ set_sigpipe(mysql); @@ -657,13 +658,13 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, if (mysql->net.vio == 0) { /* Do reconnect if possible */ if (mysql_reconnect(mysql)) - return 1; + DBUG_RETURN(1); } if (mysql->status != MYSQL_STATUS_READY) { DBUG_PRINT("error",("state: %d", mysql->status)); set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); - return 1; + DBUG_RETURN(1); } net->last_error[0]=0; @@ -702,7 +703,8 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, 1 : 0); end: reset_sigpipe(mysql); - return result; + DBUG_PRINT("exit",("result: %d", result)); + DBUG_RETURN(result); } void free_old_query(MYSQL *mysql) @@ -2458,6 +2460,7 @@ get_info: mysql->status= MYSQL_STATUS_GET_RESULT; mysql->field_count= (uint) field_count; mysql->warning_count= 0; + DBUG_PRINT("exit",("ok")); DBUG_RETURN(0); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index b36d835a80a..1521b206e0d 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1934,12 +1934,12 @@ void reset_stmt_for_execute(THD *thd, LEX *lex) } -/* - Clears parameters from data left from previous execution or long data +/* + Clears parameters from data left from previous execution or long data SYNOPSIS reset_stmt_params() - stmt - prepared statement for which parameters should be reset + stmt prepared statement for which parameters should be reset */ static void reset_stmt_params(Prepared_statement *stmt) @@ -1955,6 +1955,7 @@ static void reset_stmt_params(Prepared_statement *stmt) Executes previously prepared query. If there is any parameters, then replace markers with the data supplied from client, and then execute the query. + SYNOPSIS mysql_stmt_execute() thd Current thread @@ -2208,7 +2209,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length) { /* assume there is always place for 8-16 bytes */ ulong stmt_id= uint4korr(packet); - ulong num_rows= uint4korr(packet+=4); + ulong num_rows= uint4korr(packet+4); Statement *stmt; DBUG_ENTER("mysql_stmt_fetch"); @@ -2266,7 +2267,6 @@ void mysql_stmt_reset(THD *thd, char *packet) /* There is always space for 4 bytes in buffer */ ulong stmt_id= uint4korr(packet); Prepared_statement *stmt; - DBUG_ENTER("mysql_stmt_reset"); if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset"))) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5ba157cb608..b0d749889bf 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1834,13 +1834,14 @@ Cursor::fetch(ulong num_rows) THD *thd= join->thd; JOIN_TAB *join_tab= join->join_tab + join->const_tables; enum_nested_loop_state error= NESTED_LOOP_OK; + DBUG_ENTER("Cursor::fetch"); + DBUG_PRINT("enter",("rows: %lu", num_rows)); /* save references to memory, allocated during fetch */ thd->set_n_backup_item_arena(this, &thd->stmt_backup); join->fetch_limit+= num_rows; - error= sub_select(join, join_tab, 0); if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS) error= sub_select(join,join_tab,1); @@ -1873,6 +1874,7 @@ Cursor::fetch(ulong num_rows) else if (error != NESTED_LOOP_KILLED) my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); } + DBUG_VOID_RETURN; } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index da57fbabaf2..3cfed31c750 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -71,7 +71,7 @@ static const char *embedded_server_groups[]= { static time_t start_time, end_time; static double total_time; -const char *default_dbug_option= "d:t:o,/tmp/client_test.trace"; +const char *default_dbug_option= "d:t:o,/tmp/mysql_client_test.trace"; struct my_tests_st { @@ -12942,6 +12942,7 @@ static void test_bug9478() char a[6]; ulong a_len; int rc, i; + DBUG_ENTER("test_bug9478"); myheader("test_bug9478"); @@ -13014,6 +13015,7 @@ static void test_bug9478() for (i= 0; i < 5; i++) { + DBUG_PRINT("loop",("i: %d", i)); rc= mysql_stmt_execute(stmt); check_execute(stmt, rc); rc= mysql_stmt_fetch(stmt); @@ -13029,10 +13031,10 @@ static void test_bug9478() */ { char buff[9]; - bzero(buff, sizeof(buff)); /* Fill in the execute packet */ int4store(buff, stmt->stmt_id); - int4store(buff+5, 1); + buff[4]= 0; /* Flag */ + int4store(buff+5, 1); /* Return 1 row */ rc= ((*mysql->methods->advanced_command)(mysql, COM_EXECUTE, buff, sizeof(buff), 0,0,1) || (*mysql->methods->read_query_result)(mysql)); @@ -13072,6 +13074,7 @@ static void test_bug9478() rc= mysql_query(mysql, "drop table t1"); myquery(rc); + DBUG_VOID_RETURN; } From d15f89c47afd2b674e666098eee69ec8bdfb901d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 May 2005 15:21:35 +0300 Subject: [PATCH 60/63] After merge fixes mysql-test/r/alter_table.result: Fixed results after merge sql/handler.cc: Trivial optimzation sql/sql_table.cc: Trvial optimization sql/sql_yacc.yy: After merge fix sql/unireg.cc: Removed argument 'null_fields' from make_empty_rec() as it was not needed Moved assert() to right place to take bit fields into account --- mysql-test/r/alter_table.result | 19 ++++++++++++++----- sql/handler.cc | 7 ++++--- sql/sql_table.cc | 7 ++++--- sql/sql_yacc.yy | 2 +- sql/unireg.cc | 12 +++++------- 5 files changed, 28 insertions(+), 19 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index e91a164db6f..74f0e3d9425 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -389,7 +389,7 @@ alter table t1 modify a varchar(10); show create table t2; Table Create Table t2 CREATE TABLE `t2` ( - `a` varchar(10) NOT NULL default '', + `a` varchar(10) NOT NULL, PRIMARY KEY (`a`) ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`) flush tables; @@ -397,7 +397,7 @@ alter table t1 modify a varchar(10) not null; show create table t2; Table Create Table t2 CREATE TABLE `t2` ( - `a` varchar(10) NOT NULL default '', + `a` varchar(10) NOT NULL, PRIMARY KEY (`a`) ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`) drop table if exists t1, t2; @@ -405,17 +405,26 @@ create table t1 (a int, b int, c int, d int, e int, f int, g int, h int,i int, p insert into t1 (a) values(1); show table status like 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MyISAM 9 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL +t1 MyISAM 10 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL alter table t1 modify a int; show table status like 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MyISAM 9 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL +t1 MyISAM 10 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL drop table t1; create table t1 (a int not null, b int not null, c int not null, d int not null, e int not null, f int not null, g int not null, h int not null,i int not null, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM; insert into t1 (a) values(1); +Warnings: +Warning 1364 Field 'b' doesn't have a default value +Warning 1364 Field 'c' doesn't have a default value +Warning 1364 Field 'd' doesn't have a default value +Warning 1364 Field 'e' doesn't have a default value +Warning 1364 Field 'f' doesn't have a default value +Warning 1364 Field 'g' doesn't have a default value +Warning 1364 Field 'h' doesn't have a default value +Warning 1364 Field 'i' doesn't have a default value show table status like 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment -t1 MyISAM 9 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL +t1 MyISAM 10 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL drop table t1; set names koi8r; create table t1 (a char(10) character set koi8r); diff --git a/sql/handler.cc b/sql/handler.cc index a34b3bd8aac..d641628ac86 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1420,6 +1420,7 @@ void handler::update_auto_increment() ulonglong nr; THD *thd= table->in_use; struct system_variables *variables= &thd->variables; + bool auto_increment_field_not_null; DBUG_ENTER("handler::update_auto_increment"); /* @@ -1427,13 +1428,14 @@ void handler::update_auto_increment() row was not inserted */ thd->prev_insert_id= thd->next_insert_id; + auto_increment_field_not_null= table->auto_increment_field_not_null; + table->auto_increment_field_not_null= FALSE; if ((nr= table->next_number_field->val_int()) != 0 || - table->auto_increment_field_not_null && + auto_increment_field_not_null && thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) { /* Clear flag for next row */ - table->auto_increment_field_not_null= FALSE; /* Mark that we didn't generate a new value **/ auto_increment_column_changed=0; @@ -1449,7 +1451,6 @@ void handler::update_auto_increment() } DBUG_VOID_RETURN; } - table->auto_increment_field_not_null= FALSE; if (!(nr= thd->next_insert_id)) { nr= get_auto_increment(); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index b6e44f8ec25..4ddef3fc653 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -640,7 +640,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, { const char *key_name; create_field *sql_field,*dup_field; - uint field,null_fields,blob_columns; + uint field,null_fields,blob_columns,max_key_length; ulong record_offset= 0; KEY *key_info; KEY_PART_INFO *key_part_info; @@ -654,6 +654,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, select_field_pos= fields->elements - select_field_count; null_fields=blob_columns=0; create_info->varchar= 0; + max_key_length= file->max_key_length(); for (field_no=0; (sql_field=it++) ; field_no++) { @@ -1190,10 +1191,10 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, { if (f_is_blob(sql_field->pack_flag)) { - if ((length=column->length) > file->max_key_length() || + if ((length=column->length) > max_key_length || length > file->max_key_part_length()) { - length=min(file->max_key_length(), file->max_key_part_length()); + length=min(max_key_length, file->max_key_part_length()); if (key->type == Key::MULTIPLE) { /* not a critical problem */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 21a9d344e22..9328d7345c3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3990,7 +3990,7 @@ select_options: { if (test_all_bits(Select->options, SELECT_ALL | SELECT_DISTINCT)) { - net_printf(Lex->thd, ER_WRONG_USAGE, "ALL", "DISTINCT"); + my_error(ER_WRONG_USAGE, MYF(0), "ALL", "DISTINCT"); YYABORT; } } diff --git a/sql/unireg.cc b/sql/unireg.cc index 82f91d1da68..da463885f85 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -45,8 +45,7 @@ static bool pack_fields(File file, List &create_fields, static bool make_empty_rec(THD *thd, int file, enum db_type table_type, uint table_options, List &create_fields, - uint reclength, uint null_fields, - ulong data_offset); + uint reclength, ulong data_offset); /* Create a frm (table definition) file @@ -72,7 +71,7 @@ bool mysql_create_frm(THD *thd, my_string file_name, uint keys, KEY *key_info, handler *db_file) { - uint reclength,info_length,screens,key_info_length,maxlength,null_fields; + uint reclength,info_length,screens,key_info_length,maxlength; File file; ulong filepos, data_offset; uchar fileinfo[64],forminfo[288],*keybuff; @@ -111,7 +110,6 @@ bool mysql_create_frm(THD *thd, my_string file_name, } } reclength=uint2korr(forminfo+266); - null_fields=uint2korr(forminfo+282); if ((file=create_frm(file_name, reclength, fileinfo, create_info, keys)) < 0) @@ -145,7 +143,7 @@ bool mysql_create_frm(THD *thd, my_string file_name, (ulong) uint2korr(fileinfo+6)+ (ulong) key_buff_length, MY_SEEK_SET,MYF(0))); if (make_empty_rec(thd,file,create_info->db_type,create_info->table_options, - create_fields,reclength, null_fields, data_offset)) + create_fields,reclength, data_offset)) goto err; VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0))); @@ -661,7 +659,7 @@ static bool pack_fields(File file, List &create_fields, static bool make_empty_rec(THD *thd, File file,enum db_type table_type, uint table_options, List &create_fields, - uint reclength, uint null_fields, + uint reclength, ulong data_offset) { int error; @@ -696,7 +694,6 @@ static bool make_empty_rec(THD *thd, File file,enum db_type table_type, null_count++; // Need one bit for delete mark *buff|= 1; } - DBUG_ASSERT(data_offset == ((null_fields + null_count + 7) / 8)); null_pos= buff; List_iterator it(create_fields); @@ -756,6 +753,7 @@ static bool make_empty_rec(THD *thd, File file,enum db_type table_type, else regfield->reset(); } + DBUG_ASSERT(data_offset == ((null_count + 7) / 8)); /* Fill not used startpos */ if (null_count) From 4b2020c575c1604dd5955f1296f4a3f57c671d9b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 May 2005 14:06:52 +0000 Subject: [PATCH 61/63] Some improvement in Item_int_with_ref class comment. --- sql/item.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sql/item.h b/sql/item.h index 8fed871e623..2edbeef400c 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1027,12 +1027,14 @@ public: void print(String *str); }; + /* The following class is used to optimize comparing of date and bigint columns - We need to save the original item, to be able to set the field to the - original value in 'opt_range'. - An instance of Item_int_with_ref may refer to a signed or an unsigned - integer. + We need to save the original item ('ref') to be able to call + ref->save_in_field(). This is used to create index search keys. + + An instance of Item_int_with_ref may have signed or unsigned integer value. + */ class Item_int_with_ref :public Item_int From f80fa96d1c1eb867d65598fd8ad1e3044fb7362a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 May 2005 20:16:46 +0300 Subject: [PATCH 62/63] Fix memory leak client/mysql.cc: Remove usage of c_ptr_safe() as this causes a linkage problem when compiling MySQL without inline functions sql/sql_base.cc: Don't use c_ptr_safe() on this string as this causes a realloc and the String object (allocated by sql_yacc.yy) is never freed --- client/mysql.cc | 7 ++++--- sql/sql_base.cc | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 6a76a1fbd1b..a3262c818f3 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2051,7 +2051,8 @@ print_table_data(MYSQL_RES *result) separator.fill(separator.length()+length+2,'-'); separator.append('+'); } - tee_puts(separator.c_ptr_safe(), PAGER); + separator.append('\0'); // End marker for \0 + tee_puts((char*) separator.ptr(), PAGER); if (column_names) { mysql_field_seek(result,0); @@ -2064,7 +2065,7 @@ print_table_data(MYSQL_RES *result) num_flag[off]= IS_NUM(field->type); } (void) tee_fputs("\n", PAGER); - tee_puts(separator.c_ptr(), PAGER); + tee_puts((char*) separator.ptr(), PAGER); } while ((cur= mysql_fetch_row(result))) @@ -2093,7 +2094,7 @@ print_table_data(MYSQL_RES *result) } (void) tee_fputs("\n", PAGER); } - tee_puts(separator.c_ptr(), PAGER); + tee_puts((char*) separator.ptr(), PAGER); my_afree((gptr) num_flag); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e86362c857b..c580842ce06 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2522,7 +2522,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table, if ((pos= find_type(&table->keynames, name->ptr(), name->length(), 1)) <= 0) { - my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), name->c_ptr_safe(), + my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), name->c_ptr(), table->real_name); map->set_all(); return 1; From e9beb6d0aa8056d01637272d1782e2ae2482762d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 16 May 2005 10:21:28 -0700 Subject: [PATCH 63/63] Cleanups based on feedback from Monty. sql/sql_show.cc: Use int10_to_str() instead of my_snprintf() for formatting number --- sql/sql_show.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 93445bedf98..fe2ed04cf5d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1362,13 +1362,12 @@ static bool show_status_array(THD *thd, const char *wild, { if (bitmap_is_set(bitmap, i)) { - end+= my_snprintf((char *)end, sizeof(buff) - (end - buff), - "%d,", i); + end= int10_to_str(i, (char*) end, 10); + *(char*) end++= ','; } } if (end != buff) end--; // Remove last ',' - *(char *)end= 0; } break; }