diff options
-rw-r--r-- | Docs/manual.texi | 11 | ||||
-rw-r--r-- | libmysql/libmysql.def | 1 | ||||
-rw-r--r-- | myisam/mi_dynrec.c | 1 | ||||
-rw-r--r-- | mysql-test/r/func_str.result | 3 | ||||
-rw-r--r-- | mysql-test/t/func_str.test | 1 | ||||
-rw-r--r-- | mysys/mf_iocache.c | 5 | ||||
-rw-r--r-- | sql/ha_innodb.cc | 3 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 27 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 93 | ||||
-rw-r--r-- | sql/log.cc | 11 | ||||
-rw-r--r-- | sql/mysql_priv.h | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 28 | ||||
-rw-r--r-- | sql/set_var.cc | 4 | ||||
-rw-r--r-- | sql/slave.cc | 8 | ||||
-rw-r--r-- | sql/sql_show.cc | 3 |
15 files changed, 139 insertions, 62 deletions
diff --git a/Docs/manual.texi b/Docs/manual.texi index 90c697402d4..a10c53af7a8 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -31071,6 +31071,10 @@ mysql> SELECT IF(STRCMP('test','test1'),'no','yes'); -> 'no' @end example +If @code{expr2} or @code{expr3} is explicitely @code{NULL} then the +result type of the @code{IF()} function is the type of the not +@code{NULL} column. (This behavior is new in MySQL 4.0.3). + @code{expr1} is evaluated as an integer value, which means that if you are testing floating-point or string values, you should do so using a comparison operation: @@ -50226,10 +50230,13 @@ each individual 4.0.x release. @itemize @bullet @item -Fixed security bug in database hash +Changed behavior of @code{IF(condition,column,NULL)} so that it returns +the value of the column type. +@item Made @code{safe_mysqld} a symlink to @code{mysqld_safe} in binary distribution. @item -Fixed security bug when having an empty databasename in the user.db table. +Fixed security bug when having an empty databasename in the @code{user.db} +table. @item Fixed some problems with @code{CREATE TABLE ... SELECT function()}. @item diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index 988f2b09195..46ca5acafcc 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -89,7 +89,6 @@ EXPORTS mysql_read_query_result mysql_real_escape_string mysql_ssl_set - mysql_ssl_clear mysql_real_connect mysql_master_query mysql_master_send_query diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index 8a9ca8aab34..60e6fc0519a 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -1097,7 +1097,6 @@ int _mi_cmp_dynamic_unique(MI_INFO *info, MI_UNIQUEDEF *def, const byte *record, my_off_t pos) { byte *rec_buff,*old_record; - uint alloced_rec_buff_length; int error; DBUG_ENTER("_mi_cmp_dynamic_unique"); diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 56eb9c632f7..dd5e5191536 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -152,6 +152,9 @@ quote('\'\"\\test') select quote(concat('abc\'', '\\cba')); quote(concat('abc\'', '\\cba')) 'abc\'\\cba' +select quote(1/0), quote('\0\Z'); +quote(1/0) quote('\0\Z') +NULL '\0\Z' select reverse(""); reverse("") diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 89212a74e04..daf5587b450 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -63,6 +63,7 @@ select decode(encode("abcdef","monty"),"monty")="abcdef"; select quote('\'\"\\test'); select quote(concat('abc\'', '\\cba')); +select quote(1/0), quote('\0\Z'); # # Wrong usage of functions diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index a4bf09ef7a7..6f7fb907ad5 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -521,8 +521,9 @@ int _my_b_read_r(register IO_CACHE *info, byte *Buffer, uint Count) length=(length <= info->read_length) ? length + IO_ROUND_DN(info->read_length - length) : length - IO_ROUND_UP(length - info->read_length) ; - if (info->type != READ_FIFO && (length > info->end_of_file - pos_in_file)) - length=info->end_of_file - pos_in_file; + if (info->type != READ_FIFO && + (length > (uint) (info->end_of_file - pos_in_file))) + length= (uint) (info->end_of_file - pos_in_file); if (length == 0) { info->error=(int) read_len; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 038da716abe..5d7d083ef91 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -306,7 +306,8 @@ innobase_mysql_print_thd( *buf++=' '; buf=strnmov(buf, thd->query, 150); } - *buf='\n'; + buf[0]='\n'; + buf[1]=0; } } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 90e8a0e451f..19d64812f34 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -486,6 +486,7 @@ Item_func_ifnull::val_str(String *str) return res; } + void Item_func_if::fix_length_and_dec() { @@ -494,16 +495,32 @@ Item_func_if::fix_length_and_dec() decimals=max(args[1]->decimals,args[2]->decimals); enum Item_result arg1_type=args[1]->result_type(); enum Item_result arg2_type=args[2]->result_type(); - binary=1; - if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT) + bool null1=args[1]->null_value; + bool null2=args[2]->null_value; + + if (null1) + { + cached_result_type= arg2_type; + binary= args[1]->binary; + } + else if (null2) + { + cached_result_type= arg2_type; + binary= args[2]->binary; + } + else if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT) { cached_result_type = STRING_RESULT; binary=args[1]->binary | args[2]->binary; } - else if (arg1_type == REAL_RESULT || arg2_type == REAL_RESULT) - cached_result_type = REAL_RESULT; else - cached_result_type=arg1_type; // Should be INT_RESULT + { + binary=1; // Number + if (arg1_type == REAL_RESULT || arg2_type == REAL_RESULT) + cached_result_type = REAL_RESULT; + else + cached_result_type=arg1_type; // Should be INT_RESULT + } } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 7b28a9d4550..720313f4be7 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2071,41 +2071,90 @@ String* Item_func_inet_ntoa::val_str(String* str) return str; } -#define get_esc_bit(mask, num) (1 & (*((mask) + ((num) >> 3))) >> ((num) & 7)) - /* - QUOTE() function returns argument string in single quotes, - also adds a \ before \, ' CHAR(0) and CHAR(24) + QUOTE() function returns argument string in single quotes suitable for + using in a SQL statement. + + DESCRIPTION + Adds a \ before all characters that needs to be escaped in a SQL string. + We also escape '^Z' (END-OF-FILE in windows) to avoid probelms when + running commands from a file in windows. + + This function is very useful when you want to generate SQL statements + + RETURN VALUES + str Quoted string + NULL Argument to QUOTE() was NULL or out of memory. */ + +#define get_esc_bit(mask, num) (1 & (*((mask) + ((num) >> 3))) >> ((num) & 7)) + String *Item_func_quote::val_str(String *str) { - static char escmask[32] = {0x01, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - String *arg= args[0]->val_str(str); - char *from, *to, *end; - uint delta= 2; /* for beginning and ending ' signs */ + /* + Bit mask that has 1 for set for the position of the following characters: + 0, \, ' and ^Z + */ + + static char escmask[32]= + { + 0x01, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; - if (!arg) + char *from, *to, *end, *start; + String *arg= args[0]->val_str(str); + uint arg_length, new_length; + if (!arg) // Null argument goto null; + arg_length= arg->length(); + new_length= arg_length+2; /* for beginning and ending ' signs */ - for (from= (char*) arg->ptr(), end= from + arg->length(); from < end; from++) - delta+= get_esc_bit(escmask, *from); + for (from= (char*) arg->ptr(), end= from + arg_length; from < end; from++) + new_length+= get_esc_bit(escmask, *from); - if (str->alloc(arg->length() + delta)) + /* + We have to use realloc() instead of alloc() as we want to keep the + old result in str + */ + if (str->realloc(new_length)) goto null; - to= (char*) str->ptr() + arg->length() + delta - 1; + + /* + As 'arg' and 'str' may be the same string, we must replace characters + from the end to the beginning + */ + to= (char*) str->ptr() + new_length - 1; *to--= '\''; - for (end= (char*) arg->ptr(), from= end + arg->length() - 1; from >= end; - from--, to--) + for (start= (char*) arg->ptr() ; end-- != start; to--) { - *to= *from; - if (get_esc_bit(escmask, *from)) - *--to= '\\'; + /* + We can't use the bitmask here as we want to replace \O and ^Z with 0 + and Z + */ + switch (*end) { + case 0: + *to--= '0'; + *to= '\\'; + break; + case '\032': + *to--= 'Z'; + *to= '\\'; + break; + case '\'': + case '\\': + *to--= *end; + *to= '\\'; + break; + default: + *to= *end; + break; + } } *to= '\''; - str->length(arg->length() + delta); + str->length(new_length); return str; null: diff --git a/sql/log.cc b/sql/log.cc index b6a07d9021f..06007a081ea 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -451,7 +451,6 @@ int MYSQL_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name, } } -err: if (need_lock) pthread_mutex_unlock(&LOCK_index); DBUG_RETURN(error); @@ -602,15 +601,15 @@ err: - Read the first file name from the index file and store in rli->linfo RETURN VALUES - 0 ok - 1 error + 0 ok + LOG_INFO_EOF End of log-index-file found + LOG_INFO_SEEK Could not allocate IO cache + LOG_INFO_IO Got IO error while reading file */ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli) { - File file; - bool error= 1; - my_off_t offset, init_offset; + int error; DBUG_ENTER("purge_first_log"); /* diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 18a006b5a16..e5a4f0f271f 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -640,7 +640,7 @@ extern bool opt_using_transactions, use_temp_pool, mysql_embedded; extern bool using_update_log, opt_large_files; extern bool opt_log, opt_update_log, opt_bin_log, opt_slow_log; extern bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types; -extern bool opt_disable_networking, opt_skip_show_db; +extern bool opt_disable_networking, opt_skip_show_db, opt_enable_named_pipe; extern bool volatile abort_loop, shutdown_in_progress, grant_option; extern uint volatile thread_count, thread_running, global_read_lock; extern my_bool opt_safe_show_db, opt_local_infile, lower_case_table_names; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7ac2b009d15..3b998d61207 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -181,7 +181,6 @@ static SECURITY_DESCRIPTOR sdPipeDescriptor; static HANDLE hPipe = INVALID_HANDLE_VALUE; static pthread_cond_t COND_handler_count; static uint handler_count; -static bool opt_enable_named_pipe = 0; #endif #ifdef __WIN__ static bool opt_console=0, start_mode=0, use_opt_args; @@ -258,6 +257,7 @@ ulong back_log, connect_timeout, concurrency; char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], time_zone[30]; bool opt_log, opt_update_log, opt_bin_log, opt_slow_log; bool opt_disable_networking=0, opt_skip_show_db=0; +bool opt_enable_named_pipe= 0; my_bool opt_local_infile, opt_external_locking, opt_slave_compressed_protocol; static bool opt_do_pstack = 0; @@ -1045,8 +1045,8 @@ static void server_init(void) PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, - (int) global_variables.net_buffer_length, - (int) global_variables.net_buffer_length, + (int) global_system_variables.net_buffer_length, + (int) global_system_variables.net_buffer_length, NMPWAIT_USE_DEFAULT_WAIT, &saPipeSecurity )) == INVALID_HANDLE_VALUE) { @@ -2275,7 +2275,8 @@ int main(int argc, char **argv) if (Service.IsService(argv[1])) { /* start an optional service */ - event_name = load_default_groups[0]= argv[1]; + event_name= argv[1]; + load_default_groups[0]= argv[1]; start_mode= 1; Service.Init(event_name, mysql_service); return 0; @@ -2285,8 +2286,8 @@ int main(int argc, char **argv) { /* Add service name after filename */ uint length=strlen(file_path); - strxnmov(file_path + length, sizeof(file_path)-length-2, " ", - argv[2], NullS)= '\0'; + *strxnmov(file_path + length, sizeof(file_path)-length-2, " ", + argv[2], NullS)= '\0'; if (!default_service_handling(argv, argv[2], argv[2], file_path)) return 0; @@ -2309,8 +2310,8 @@ int main(int argc, char **argv) mysqld --install-manual mysqldopt --defaults-file=c:\miguel\my.ini */ uint length=strlen(file_path); - strxnmov(file_path + length, sizeof(file_path)-length-2, " ", - argv[3], " ", argv[2], NullS)= '\0'; + *strxnmov(file_path + length, sizeof(file_path)-length-2, " ", + argv[3], " ", argv[2], NullS)= '\0'; if (!default_service_handling(argv, argv[2], argv[2], file_path)) return 0; } @@ -2724,8 +2725,8 @@ pthread_handler_decl(handle_connections_namedpipes,arg) PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, - (int) global_variables.net_buffer_length, - (int) global_variables.net_buffer_length, + (int) global_system_variables.net_buffer_length, + (int) global_systenm_ariables.net_buffer_length, NMPWAIT_USE_DEFAULT_WAIT, &saPipeSecurity )) == INVALID_HANDLE_VALUE ) @@ -2742,8 +2743,8 @@ pthread_handler_decl(handle_connections_namedpipes,arg) PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, - (int) global_variables.net_buffer_length, - (int) global_variables.net_buffer_length, + (int) global_system_variables.net_buffer_length, + (int) global_system_variables.net_buffer_length, NMPWAIT_USE_DEFAULT_WAIT, &saPipeSecurity)) == INVALID_HANDLE_VALUE) @@ -4446,7 +4447,8 @@ static void fix_paths(void) } char *end=convert_dirname(buff, opt_mysql_tmpdir, NullS); - if (!(mysql_tmpdir= my_memdup(buff,(uint) (end-buff)+1, MYF(MY_FAE)))) + if (!(mysql_tmpdir= my_memdup((byte*) buff,(uint) (end-buff)+1, + MYF(MY_FAE)))) exit(1); if (!slave_load_tmpdir) { diff --git a/sql/set_var.cc b/sql/set_var.cc index d471c0b18ba..87417354b99 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -669,7 +669,7 @@ bool sys_var_thd_ulong::update(THD *thd, set_var *var) { /* Lock is needed to make things safe on 32 bit systems */ pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.*offset=tmp; + global_system_variables.*offset= (ulong) tmp; pthread_mutex_unlock(&LOCK_global_system_variables); } else @@ -998,7 +998,7 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) if (!active_mi->rli.slave_running) { pthread_mutex_lock(&active_mi->rli.data_lock); - active_mi->rli.slave_skip_counter= var->value->val_int(); + active_mi->rli.slave_skip_counter= (ulong) var->value->val_int(); pthread_mutex_unlock(&active_mi->rli.data_lock); } pthread_mutex_unlock(&active_mi->rli.run_lock); diff --git a/sql/slave.cc b/sql/slave.cc index e5be443428f..9873831cd28 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -855,7 +855,7 @@ static int check_master_version(MYSQL* mysql, MASTER_INFO* mi) errmsg = "Master reported unrecognized MySQL version"; break; } -err: + if (errmsg) { sql_print_error(errmsg); @@ -874,7 +874,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, TABLE_LIST tables; int error= 1; handler *file; - uint save_options; + ulong save_options; if (packet_len == packet_error) { @@ -903,7 +903,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, /* we do not want to log create table statement */ save_options = thd->options; - thd->options &= ~(ulong) OPTION_BIN_LOG; + thd->options &= ~(ulong) (OPTION_BIN_LOG); thd->proc_info = "Creating table from master dump"; // save old db in case we are creating in a different database char* save_db = thd->db; @@ -2642,7 +2642,7 @@ bool flush_relay_log_info(RELAY_LOG_INFO* rli) *pos++='\n'; pos=longlong2str(rli->master_log_pos, pos, 10); *pos='\n'; - if (my_b_write(file, buff, (ulong) (pos-buff)+1)) + if (my_b_write(file, (byte*) buff, (ulong) (pos-buff)+1)) error=1; if (flush_io_cache(file)) error=1; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 6041132bd20..bf9abaaa32d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1152,7 +1152,6 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, String packet2(buff,sizeof(buff)); List<Item> field_list; CONVERT *convert=thd->variables.convert_set; - ulong offset; DBUG_ENTER("mysqld_show"); field_list.push_back(new Item_empty_string("Variable_name",30)); @@ -1173,7 +1172,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, if (show_type == SHOW_SYS) { show_type= ((sys_var*) value)->type(); - value= ((sys_var*) value)->value_ptr(thd, value_type); + value= (char*) ((sys_var*) value)->value_ptr(thd, value_type); } switch (show_type) { |