summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Docs/manual.texi11
-rw-r--r--libmysql/libmysql.def1
-rw-r--r--myisam/mi_dynrec.c1
-rw-r--r--mysql-test/r/func_str.result3
-rw-r--r--mysql-test/t/func_str.test1
-rw-r--r--mysys/mf_iocache.c5
-rw-r--r--sql/ha_innodb.cc3
-rw-r--r--sql/item_cmpfunc.cc27
-rw-r--r--sql/item_strfunc.cc93
-rw-r--r--sql/log.cc11
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/mysqld.cc28
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/slave.cc8
-rw-r--r--sql/sql_show.cc3
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) {