Commit c99c1fd3 authored by monty@hundin.mysql.fi's avatar monty@hundin.mysql.fi

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.
parent deaec7b0
......@@ -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
......@@ -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
......
......@@ -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");
......
......@@ -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("")
......
......@@ -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
......
......@@ -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;
......
......@@ -306,7 +306,8 @@ innobase_mysql_print_thd(
*buf++=' ';
buf=strnmov(buf, thd->query, 150);
}
*buf='\n';
buf[0]='\n';
buf[1]=0;
}
}
......
......@@ -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)
else
{
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
}
}
......
......@@ -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,
/*
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};
String *arg= args[0]->val_str(str);
char *from, *to, *end;
uint delta= 2; /* for beginning and ending ' signs */
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:
......
......@@ -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);
......@@ -603,14 +602,14 @@ bool MYSQL_LOG::reset_logs(THD* thd)
RETURN VALUES
0 ok
1 error
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");
/*
......
......@@ -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;
......
......@@ -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,7 +2286,7 @@ 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, " ",
*strxnmov(file_path + length, sizeof(file_path)-length-2, " ",
argv[2], NullS)= '\0';
if (!default_service_handling(argv, argv[2], argv[2], file_path))
......@@ -2309,7 +2310,7 @@ 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, " ",
*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)
{
......
......@@ -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);
......
......@@ -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;
......
......@@ -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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment