From 9b1930152db6ecd30b8cbcc7200af2baf7f82295 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 Aug 2002 03:33:46 +0300 Subject: Changed IF(expr, column, NULL) to take type from column Fixed some windows portability problems and removed some compiler warnings Cleaned up QUOTE() function and fixed bug in \0 and \Z handling. Docs/manual.texi: Changelog Added information about new IF() behaviour. libmysql/libmysql.def: Removed mysql_ssl_clear myisam/mi_dynrec.c: Minor cleanup mysql-test/r/func_str.result: Added more tests for QUOTE mysql-test/t/func_str.test: Added more tests for QUOTE mysys/mf_iocache.c: Removed compiler warnings sql/ha_innodb.cc: Added missing null to generated string. sql/item_cmpfunc.cc: Changed IF(expr, column, NULL) to take type from column sql/item_strfunc.cc: Cleaned up QUOTE() function and fixed bug in \0 and \Z handling. sql/log.cc: Minor cleanup sql/mysql_priv.h: Fixed problem with opt_enable_named_pipe sql/mysqld.cc: Fixed problem with opt_enable_named_pipe Fixed some syntax errors in windows code sql/set_var.cc: Removed compiler warnings sql/slave.cc: Removed compiler warnings sql/sql_show.cc: Removed compiler warnings --- Docs/manual.texi | 11 +++++- libmysql/libmysql.def | 1 - myisam/mi_dynrec.c | 1 - mysql-test/r/func_str.result | 3 ++ mysql-test/t/func_str.test | 1 + mysys/mf_iocache.c | 5 ++- sql/ha_innodb.cc | 3 +- sql/item_cmpfunc.cc | 27 ++++++++++--- sql/item_strfunc.cc | 93 +++++++++++++++++++++++++++++++++----------- sql/log.cc | 11 +++--- sql/mysql_priv.h | 2 +- sql/mysqld.cc | 28 ++++++------- sql/set_var.cc | 4 +- sql/slave.cc | 8 ++-- 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 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) { -- cgit v1.2.1