diff options
author | Michael Widenius <monty@mysql.com> | 2009-04-25 13:05:32 +0300 |
---|---|---|
committer | Michael Widenius <monty@mysql.com> | 2009-04-25 13:05:32 +0300 |
commit | e726e587ec6287472dd450dbcbddf07669b3e028 (patch) | |
tree | e644a6134bfe892512501c648c938a2e93f08130 /sql | |
parent | 210a412522b10115d34b431c66acf403faab7bfe (diff) | |
parent | 086185089e6c7bef58dde49b02950689af9fee63 (diff) | |
download | mariadb-git-e726e587ec6287472dd450dbcbddf07669b3e028.tar.gz |
Merged with mysql-5.1 tree.
client/mysqltest.cc:
Manually merged
configure.in:
Manually merged
mysql-test/r/variables.result:
Manually merged
mysql-test/t/variables.test:
Manually merged
mysys/my_pread.c:
Manually merged
mysys/my_read.c:
Manually merged
sql/mysqld.cc:
Manually merged
storage/csv/ha_tina.h:
Manually merged
storage/myisam/ha_myisam.cc:
Manually merged
storage/myisam/mi_check.c:
Manually merged
storage/myisam/mi_search.c:
Manually merged
Diffstat (limited to 'sql')
54 files changed, 889 insertions, 213 deletions
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index b98922e2408..fdc18954c55 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -380,7 +380,7 @@ bool Event_job_data::load_from_row(THD *thd, TABLE *table) { char *ptr; - uint len; + size_t len; LEX_STRING tz_name; DBUG_ENTER("Event_job_data::load_from_row"); @@ -580,7 +580,7 @@ bool Event_timed::load_from_row(THD *thd, TABLE *table) { char *ptr; - uint len; + size_t len; DBUG_ENTER("Event_timed::load_from_row"); diff --git a/sql/event_parse_data.cc b/sql/event_parse_data.cc index 63ecc3006dd..86905b38627 100644 --- a/sql/event_parse_data.cc +++ b/sql/event_parse_data.cc @@ -527,8 +527,8 @@ Event_parse_data::init_definer(THD *thd) const char *definer_user= thd->lex->definer->user.str; const char *definer_host= thd->lex->definer->host.str; - int definer_user_len= thd->lex->definer->user.length; - int definer_host_len= thd->lex->definer->host.length; + size_t definer_user_len= thd->lex->definer->user.length; + size_t definer_host_len= thd->lex->definer->host.length; DBUG_PRINT("info",("init definer_user thd->mem_root: 0x%lx " "definer_user: 0x%lx", (long) thd->mem_root, diff --git a/sql/events.cc b/sql/events.cc index d7443695f4a..e1b4dd4d513 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -693,7 +693,7 @@ send_show_create_event(THD *thd, Event_timed *et, Protocol *protocol) &sql_mode)) DBUG_RETURN(TRUE); - field_list.push_back(new Item_empty_string("sql_mode", sql_mode.length)); + field_list.push_back(new Item_empty_string("sql_mode", (uint) sql_mode.length)); tz_name= et->time_zone->get_name(); diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 214ee4c99d2..5a0904f87b9 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -204,7 +204,7 @@ void insert_symbols() for (cur= symbols; i<array_elements(symbols); cur++, i++){ hash_lex_struct *root= get_hash_struct_by_len(&root_by_len,cur->length,&max_len); - insert_into_hash(root,cur->name,0,i,0); + insert_into_hash(root,cur->name,0,(uint) i,0); } } @@ -516,7 +516,7 @@ static SYMBOL *get_hash_symbol(const char *s,\n\ res= symbols+ires;\n\ else\n\ res= sql_functions-ires-1;\n\ - register uint count= cur_str-s;\n\ + register uint count= (uint) (cur_str - s);\n\ return lex_casecmp(cur_str,res->name+count,len-count) ? 0 : res;\n\ }\n\ \n\ @@ -545,7 +545,7 @@ static SYMBOL *get_hash_symbol(const char *s,\n\ register int16 ires= (int16)(cur_struct>>16);\n\ if (ires==array_elements(symbols)) return 0;\n\ register SYMBOL *res= symbols+ires;\n\ - register uint count= cur_str-s;\n\ + register uint count= (uint) (cur_str - s);\n\ return lex_casecmp(cur_str,res->name+count,len-count)!=0 ? 0 : res;\n\ }\n\ \n\ diff --git a/sql/item.cc b/sql/item.cc index 35a88d10fe0..010e4cb441a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1527,7 +1527,8 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags) else { // Cannot apply conversion - set(0, DERIVATION_NONE, 0); + set(&my_charset_bin, DERIVATION_NONE, + (dt.repertoire|repertoire)); return 1; } } @@ -1610,15 +1611,31 @@ bool agg_item_collations(DTCollation &c, const char *fname, { uint i; Item **arg; + bool unknown_cs= 0; + c.set(av[0]->collation); for (i= 1, arg= &av[item_sep]; i < count; i++, arg++) { if (c.aggregate((*arg)->collation, flags)) { + if (c.derivation == DERIVATION_NONE && + c.collation == &my_charset_bin) + { + unknown_cs= 1; + continue; + } my_coll_agg_error(av, count, fname, item_sep); return TRUE; } } + + if (unknown_cs && + c.derivation != DERIVATION_EXPLICIT) + { + my_coll_agg_error(av, count, fname, item_sep); + return TRUE; + } + if ((flags & MY_COLL_DISALLOW_NONE) && c.derivation == DERIVATION_NONE) { diff --git a/sql/item.h b/sql/item.h index eb1b28b4004..9daf353998d 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1093,7 +1093,7 @@ inline void Item_sp_variable::make_field(Send_field *field) if (name) it->set_name(name, (uint) strlen(name), system_charset_info); else - it->set_name(m_name.str, m_name.length, system_charset_info); + it->set_name(m_name.str, (uint) m_name.length, system_charset_info); it->make_field(field); } diff --git a/sql/item_create.cc b/sql/item_create.cc index 4a440c00da5..35c757309e5 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -3791,6 +3791,7 @@ Create_func_load_file Create_func_load_file::s_singleton; Item* Create_func_load_file::create(THD *thd, Item *arg1) { + thd->lex->set_stmt_unsafe(); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_load_file(arg1); } diff --git a/sql/item_func.cc b/sql/item_func.cc index fb4594e0e63..fa835542eb1 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2737,7 +2737,7 @@ longlong Item_func_find_in_set::val_int() if (is_last_item && !is_separator) str_end= substr_end; if (!my_strnncoll(cs, (const uchar *) str_begin, - str_end - str_begin, + (uint) (str_end - str_begin), find_str, find_str_len)) return (longlong) position; else @@ -4828,7 +4828,7 @@ Item_func_get_system_var(sys_var *var_arg, enum_var_type var_type_arg, component(*component_arg), cache_present(0) { /* set_name() will allocate the name */ - set_name(name_arg, name_len_arg, system_charset_info); + set_name(name_arg, (uint) name_len_arg, system_charset_info); } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 298fbc39144..59f9dccfc79 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1827,17 +1827,17 @@ bool Item_func_user::init(const char *user, const char *host) if (user) { CHARSET_INFO *cs= str_value.charset(); - uint res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen; + size_t res_length= (strlen(user)+strlen(host)+2) * cs->mbmaxlen; - if (str_value.alloc(res_length)) + if (str_value.alloc((uint) res_length)) { null_value=1; return TRUE; } - res_length=cs->cset->snprintf(cs, (char*)str_value.ptr(), res_length, + res_length=cs->cset->snprintf(cs, (char*)str_value.ptr(), (uint) res_length, "%s@%s", user, host); - str_value.length(res_length); + str_value.length((uint) res_length); str_value.mark_as_const(); } return FALSE; @@ -2541,7 +2541,7 @@ String *Item_func_rpad::val_str(String *str) memcpy(to,ptr_pad,(size_t) pad_byte_length); to+= pad_byte_length; } - res->length(to- (char*) res->ptr()); + res->length((uint) (to- (char*) res->ptr())); return (res); err: @@ -2809,7 +2809,7 @@ String *Item_func_charset::val_str(String *str) CHARSET_INFO *cs= args[0]->collation.collation; null_value= 0; - str->copy(cs->csname, strlen(cs->csname), + str->copy(cs->csname, (uint) strlen(cs->csname), &my_charset_latin1, collation.collation, &dummy_errors); return str; } @@ -2821,7 +2821,7 @@ String *Item_func_collation::val_str(String *str) CHARSET_INFO *cs= args[0]->collation.collation; null_value= 0; - str->copy(cs->name, strlen(cs->name), + str->copy(cs->name, (uint) strlen(cs->name), &my_charset_latin1, collation.collation, &dummy_errors); return str; } diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index deffb0d56ca..c1b8cab600b 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -391,7 +391,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, if (tmp - val > 6) tmp= (char*) val + 6; l_time->second_part= (int) my_strtoll10(val, &tmp, &error); - frac_part= 6 - (tmp - val); + frac_part= 6 - (uint) (tmp - val); if (frac_part > 0) l_time->second_part*= (ulong) log_10_int[frac_part]; val= tmp; @@ -643,14 +643,14 @@ bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, if (!l_time->month) return 1; str->append(locale->month_names->type_names[l_time->month-1], - strlen(locale->month_names->type_names[l_time->month-1]), + (uint) strlen(locale->month_names->type_names[l_time->month-1]), system_charset_info); break; case 'b': if (!l_time->month) return 1; str->append(locale->ab_month_names->type_names[l_time->month-1], - strlen(locale->ab_month_names->type_names[l_time->month-1]), + (uint) strlen(locale->ab_month_names->type_names[l_time->month-1]), system_charset_info); break; case 'W': @@ -659,7 +659,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, weekday= calc_weekday(calc_daynr(l_time->year,l_time->month, l_time->day),0); str->append(locale->day_names->type_names[weekday], - strlen(locale->day_names->type_names[weekday]), + (uint) strlen(locale->day_names->type_names[weekday]), system_charset_info); break; case 'a': @@ -668,13 +668,13 @@ bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, weekday=calc_weekday(calc_daynr(l_time->year,l_time->month, l_time->day),0); str->append(locale->ab_day_names->type_names[weekday], - strlen(locale->ab_day_names->type_names[weekday]), + (uint) strlen(locale->ab_day_names->type_names[weekday]), system_charset_info); break; case 'D': if (type == MYSQL_TIMESTAMP_TIME) return 1; - length= int10_to_str(l_time->day, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(l_time->day, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 1, '0'); if (l_time->day >= 10 && l_time->day <= 19) str->append(STRING_WITH_LEN("th")); @@ -697,62 +697,62 @@ bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, } break; case 'Y': - length= int10_to_str(l_time->year, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(l_time->year, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 4, '0'); break; case 'y': - length= int10_to_str(l_time->year%100, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(l_time->year%100, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 2, '0'); break; case 'm': - length= int10_to_str(l_time->month, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(l_time->month, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 2, '0'); break; case 'c': - length= int10_to_str(l_time->month, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(l_time->month, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 1, '0'); break; case 'd': - length= int10_to_str(l_time->day, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(l_time->day, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 2, '0'); break; case 'e': - length= int10_to_str(l_time->day, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(l_time->day, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 1, '0'); break; case 'f': - length= int10_to_str(l_time->second_part, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(l_time->second_part, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 6, '0'); break; case 'H': - length= int10_to_str(l_time->hour, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(l_time->hour, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 2, '0'); break; case 'h': case 'I': hours_i= (l_time->hour%24 + 11)%12+1; - length= int10_to_str(hours_i, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(hours_i, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 2, '0'); break; case 'i': /* minutes */ - length= int10_to_str(l_time->minute, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(l_time->minute, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 2, '0'); break; case 'j': if (type == MYSQL_TIMESTAMP_TIME) return 1; - length= int10_to_str(calc_daynr(l_time->year,l_time->month, + length= (uint) (int10_to_str(calc_daynr(l_time->year,l_time->month, l_time->day) - - calc_daynr(l_time->year,1,1) + 1, intbuff, 10) - intbuff; + calc_daynr(l_time->year,1,1) + 1, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 3, '0'); break; case 'k': - length= int10_to_str(l_time->hour, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(l_time->hour, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 1, '0'); break; case 'l': hours_i= (l_time->hour%24 + 11)%12+1; - length= int10_to_str(hours_i, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(hours_i, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 1, '0'); break; case 'p': @@ -771,7 +771,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, break; case 'S': case 's': - length= int10_to_str(l_time->second, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(l_time->second, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 2, '0'); break; case 'T': @@ -789,11 +789,11 @@ bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, uint year; if (type == MYSQL_TIMESTAMP_TIME) return 1; - length= int10_to_str(calc_week(l_time, + length= (uint) (int10_to_str(calc_week(l_time, (*ptr) == 'U' ? WEEK_FIRST_WEEKDAY : WEEK_MONDAY_FIRST, &year), - intbuff, 10) - intbuff; + intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 2, '0'); } break; @@ -803,12 +803,12 @@ bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, uint year; if (type == MYSQL_TIMESTAMP_TIME) return 1; - length= int10_to_str(calc_week(l_time, + length= (uint) (int10_to_str(calc_week(l_time, ((*ptr) == 'V' ? (WEEK_YEAR | WEEK_FIRST_WEEKDAY) : (WEEK_YEAR | WEEK_MONDAY_FIRST)), &year), - intbuff, 10) - intbuff; + intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 2, '0'); } break; @@ -823,7 +823,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, WEEK_YEAR | WEEK_FIRST_WEEKDAY : WEEK_YEAR | WEEK_MONDAY_FIRST), &year); - length= int10_to_str(year, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(year, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 4, '0'); } break; @@ -832,7 +832,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time, return 1; weekday=calc_weekday(calc_daynr(l_time->year,l_time->month, l_time->day),1); - length= int10_to_str(weekday, intbuff, 10) - intbuff; + length= (uint) (int10_to_str(weekday, intbuff, 10) - intbuff); str->append_with_prefill(intbuff, length, 1, '0'); break; @@ -882,7 +882,7 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, value= value*LL(10) + (longlong) (*str - '0'); if (transform_msec && i == count - 1) // microseconds always last { - long msec_length= 6 - (str - start); + long msec_length= 6 - (uint) (str - start); if (msec_length > 0) value*= (long) log_10_int[msec_length]; } @@ -1061,7 +1061,7 @@ String* Item_func_monthname::val_str(String* str) } null_value=0; month_name= locale->month_names->type_names[month-1]; - str->copy(month_name, strlen(month_name), &my_charset_utf8_bin, + str->copy(month_name, (uint) strlen(month_name), &my_charset_utf8_bin, collation.collation, &err); return str; } @@ -1211,7 +1211,7 @@ String* Item_func_dayname::val_str(String* str) return (String*) 0; day_name= locale->day_names->type_names[weekday]; - str->copy(day_name, strlen(day_name), &my_charset_utf8_bin, + str->copy(day_name, (uint) strlen(day_name), &my_charset_utf8_bin, collation.collation, &err); return str; } @@ -3177,14 +3177,14 @@ String *Item_func_get_format::val_str(String *str) format++) { uint format_name_len; - format_name_len= strlen(format_name); + format_name_len= (uint) strlen(format_name); if (val_len == format_name_len && !my_strnncoll(&my_charset_latin1, (const uchar *) val->ptr(), val_len, (const uchar *) format_name, val_len)) { const char *format_str= get_date_time_format_str(format, type); - str->set(format_str, strlen(format_str), &my_charset_bin); + str->set(format_str, (uint) strlen(format_str), &my_charset_bin); return str; } } diff --git a/sql/lock.cc b/sql/lock.cc index 8f58dd6ee86..e75186d276e 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -461,7 +461,7 @@ void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock) for (i= 0; i < sql_lock->table_count; i++) { TABLE *tbl= *table; - tbl->lock_position= table - sql_lock->table; + tbl->lock_position= (uint) (table - sql_lock->table); tbl->lock_data_start= found; found+= tbl->lock_count; table++; @@ -862,7 +862,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, { my_error(ER_OPEN_AS_READONLY,MYF(0),table->alias); /* Clear the lock type of the lock data that are stored already. */ - sql_lock->lock_count= locks - sql_lock->locks; + sql_lock->lock_count= (uint) (locks - sql_lock->locks); reset_lock_data(sql_lock); my_free((uchar*) sql_lock,MYF(0)); DBUG_RETURN(0); diff --git a/sql/log_event.cc b/sql/log_event.cc index 68d4c69f398..4c82d686d5a 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -382,7 +382,7 @@ static void cleanup_load_tmpdir() uint i; char fname[FN_REFLEN], prefbuf[31], *p; - if (!(dirp=my_dir(slave_load_tmpdir,MYF(MY_WME)))) + if (!(dirp=my_dir(slave_load_tmpdir,MYF(0)))) return; /* @@ -1279,7 +1279,7 @@ void Log_event::print_header(IO_CACHE* file, char emit_buf[256]; // Enough for storing one line my_b_printf(file, "# Position Timestamp Type Master ID " "Size Master Pos Flags \n"); - int const bytes_written= + size_t const bytes_written= my_snprintf(emit_buf, sizeof(emit_buf), "# %8.8lx %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x " @@ -1288,7 +1288,6 @@ void Log_event::print_header(IO_CACHE* file, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]); - DBUG_ASSERT(bytes_written >= 0); DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf)); my_b_write(file, (uchar*) emit_buf, bytes_written); ptr += LOG_EVENT_MINIMAL_HEADER_LEN; @@ -1314,12 +1313,11 @@ void Log_event::print_header(IO_CACHE* file, TODO: Rewrite my_b_printf() to support full printf() syntax. */ char emit_buf[256]; - int const bytes_written= + size_t const bytes_written= my_snprintf(emit_buf, sizeof(emit_buf), "# %8.8lx %-48.48s |%16s|\n", (unsigned long) (hexdump_from + (i & 0xfffffff0)), hex_string, char_string); - DBUG_ASSERT(bytes_written >= 0); DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf)); my_b_write(file, (uchar*) emit_buf, bytes_written); hex_string[0]= 0; @@ -1334,12 +1332,11 @@ void Log_event::print_header(IO_CACHE* file, if (hex_string[0]) { char emit_buf[256]; - int const bytes_written= + size_t const bytes_written= my_snprintf(emit_buf, sizeof(emit_buf), "# %8.8lx %-48.48s |%s|\n", (unsigned long) (hexdump_from + (i & 0xfffffff0)), hex_string, char_string); - DBUG_ASSERT(bytes_written >= 0); DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf)); my_b_write(file, (uchar*) emit_buf, bytes_written); } @@ -1627,7 +1624,7 @@ beg: case MYSQL_TYPE_DATETIME: { - uint d, t; + size_t d, t; uint64 i64= uint8korr(ptr); /* YYYYMMDDhhmmss */ d= i64 / 1000000; t= i64 % 1000000; @@ -4197,7 +4194,7 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len, table_name = fields + field_block_len; db = table_name + table_name_len + 1; fname = db + db_len + 1; - fname_len = strlen(fname); + fname_len = (uint) strlen(fname); // null termination is accomplished by the caller doing buf[event_len]=0 DBUG_RETURN(0); @@ -5699,7 +5696,7 @@ void Slave_log_event::init_from_mem_pool(int data_size) master_pos = uint8korr(mem_pool + SL_MASTER_POS_OFFSET); master_port = uint2korr(mem_pool + SL_MASTER_PORT_OFFSET); master_host = mem_pool + SL_MASTER_HOST_OFFSET; - master_host_len = strlen(master_host); + master_host_len = (uint) strlen(master_host); // safety master_log = master_host + master_host_len + 1; if (master_log > mem_pool + data_size) @@ -5707,7 +5704,7 @@ void Slave_log_event::init_from_mem_pool(int data_size) master_host = 0; return; } - master_log_len = strlen(master_log); + master_log_len = (uint) strlen(master_log); } @@ -6180,6 +6177,12 @@ int Append_block_log_event::do_apply_event(Relay_log_info const *rli) thd_proc_info(thd, proc_info); if (get_create_or_append()) { + /* + Usually lex_start() is called by mysql_parse(), but we need it here + as the present method does not call mysql_parse(). + */ + lex_start(thd); + mysql_reset_thd_for_next_command(thd); my_delete(fname, MYF(0)); // old copy may exist already if ((fd= my_create(fname, CREATE_MODE, O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, @@ -6199,6 +6202,10 @@ int Append_block_log_event::do_apply_event(Relay_log_info const *rli) get_type_str(), fname); goto err; } + + DBUG_EXECUTE_IF("remove_slave_load_file_before_write", + my_close(fd,MYF(0)); fd= -1; my_delete(fname, MYF(0));); + if (my_write(fd, (uchar*) block, block_len, MYF(MY_WME+MY_NABP))) { rli->report(ERROR_LEVEL, my_errno, @@ -6620,7 +6627,7 @@ void Execute_load_query_log_event::print(FILE* file, my_b_printf(&cache, "\'"); if (dup_handling == LOAD_DUP_REPLACE) my_b_printf(&cache, " REPLACE"); - my_b_printf(&cache, " INTO"); + my_b_printf(&cache, " INTO "); my_b_write(&cache, (uchar*) query + fn_pos_end, q_len-fn_pos_end); my_b_printf(&cache, "\n%s\n", print_event_info->delimiter); } @@ -6701,7 +6708,7 @@ Execute_load_query_log_event::do_apply_event(Relay_log_info const *rli) /* Ordinary load data */ break; } - p= strmake(p, STRING_WITH_LEN(" INTO")); + p= strmake(p, STRING_WITH_LEN(" INTO ")); p= strmake(p, query+fn_pos_end, q_len-fn_pos_end); error= Query_log_event::do_apply_event(rli, buf, p-buf); @@ -6988,8 +6995,8 @@ int Rows_log_event::get_data_size() { int const type_code= get_type_code(); - uchar buf[sizeof(m_width)+1]; - uchar *end= net_store_length(buf, (m_width + 7) / 8); + uchar buf[sizeof(m_width) + 1]; + uchar *end= net_store_length(buf, m_width); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", return 6 + no_bytes_in_map(&m_cols) + (end - buf) + @@ -6997,12 +7004,12 @@ int Rows_log_event::get_data_size() (m_rows_cur - m_rows_buf);); int data_size= ROWS_HEADER_LEN; data_size+= no_bytes_in_map(&m_cols); - data_size+= end - buf; + data_size+= (uint) (end - buf); if (type_code == UPDATE_ROWS_EVENT) data_size+= no_bytes_in_map(&m_cols_ai); - data_size+= (m_rows_cur - m_rows_buf); + data_size+= (uint) (m_rows_cur - m_rows_buf); return data_size; } @@ -7578,7 +7585,7 @@ bool Rows_log_event::write_data_body(IO_CACHE*file) Note that this should be the number of *bits*, not the number of bytes. */ - uchar sbuf[sizeof(m_width)]; + uchar sbuf[sizeof(m_width) + 1]; my_ptrdiff_t const data_size= m_rows_cur - m_rows_buf; bool res= false; uchar *const sbuf_end= net_store_length(sbuf, (size_t) m_width); @@ -7740,6 +7747,8 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, m_null_bits(0), m_meta_memory(NULL) { + uchar cbuf[sizeof(m_colcnt) + 1]; + uchar *cbuf_end; DBUG_ASSERT(m_table_id != ~0UL); /* In TABLE_SHARE, "db" and "table_name" are 0-terminated (see this comment in @@ -7756,7 +7765,9 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", m_data_size= 6;); m_data_size+= m_dblen + 2; // Include length and terminating \0 m_data_size+= m_tbllen + 2; // Include length and terminating \0 - m_data_size+= 1 + m_colcnt; // COLCNT and column types + cbuf_end= net_store_length(cbuf, (size_t) m_colcnt); + DBUG_ASSERT(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf)); + m_data_size+= (cbuf_end - cbuf) + m_colcnt; // COLCNT and column types /* If malloc fails, caught in is_valid() */ if ((m_memory= (uchar*) my_malloc(m_colcnt, MYF(MY_WME)))) @@ -7895,7 +7906,7 @@ Table_map_log_event::Table_map_log_event(const char *buf, uint event_len, memcpy(m_coltype, ptr_after_colcnt, m_colcnt); ptr_after_colcnt= ptr_after_colcnt + m_colcnt; - bytes_read= ptr_after_colcnt - (uchar *)buf; + bytes_read= (uint) (ptr_after_colcnt - (uchar *)buf); DBUG_PRINT("info", ("Bytes read: %d.\n", bytes_read)); if (bytes_read < event_len) { @@ -8048,7 +8059,7 @@ bool Table_map_log_event::write_data_body(IO_CACHE *file) uchar const dbuf[]= { (uchar) m_dblen }; uchar const tbuf[]= { (uchar) m_tbllen }; - uchar cbuf[sizeof(m_colcnt)]; + uchar cbuf[sizeof(m_colcnt) + 1]; uchar *const cbuf_end= net_store_length(cbuf, (size_t) m_colcnt); DBUG_ASSERT(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf)); @@ -9269,7 +9280,7 @@ bool Incident_log_event::write_data_body(IO_CACHE *file) { DBUG_ENTER("Incident_log_event::write_data_body"); - DBUG_RETURN(write_str(file, m_message.str, m_message.length)); + DBUG_RETURN(write_str(file, m_message.str, (uint) m_message.length)); } diff --git a/sql/log_event.h b/sql/log_event.h index 82fc8d771e1..bda53da8ab0 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -3316,7 +3316,7 @@ public: virtual Log_event_type get_type_code() { return TABLE_MAP_EVENT; } virtual bool is_valid() const { return m_memory != NULL; /* we check malloc */ } - virtual int get_data_size() { return m_data_size; } + virtual int get_data_size() { return (uint) m_data_size; } #ifndef MYSQL_CLIENT virtual int save_field_metadata(); virtual bool write_data_header(IO_CACHE *file); @@ -3899,7 +3899,7 @@ public: return m_incident > INCIDENT_NONE && m_incident < INCIDENT_COUNT; } virtual int get_data_size() { - return INCIDENT_HEADER_LEN + 1 + m_message.length; + return INCIDENT_HEADER_LEN + 1 + (uint) m_message.length; } private: diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index cc4d24bc2dd..37eeee05a4d 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1382,9 +1382,9 @@ int Old_rows_log_event::get_data_size() (m_rows_cur - m_rows_buf);); int data_size= ROWS_HEADER_LEN; data_size+= no_bytes_in_map(&m_cols); - data_size+= end - buf; + data_size+= (uint) (end - buf); - data_size+= (m_rows_cur - m_rows_buf); + data_size+= (uint) (m_rows_cur - m_rows_buf); return data_size; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a8c7246d7e3..816efe05c18 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -523,6 +523,20 @@ protected: #define MODE_NO_ENGINE_SUBSTITUTION (MODE_HIGH_NOT_PRECEDENCE*2) #define MODE_PAD_CHAR_TO_FULL_LENGTH (ULL(1) << 31) +/* @@optimizer_switch flags. These must be in sync with optimizer_switch_typelib */ +#define OPTIMIZER_SWITCH_INDEX_MERGE 1 +#define OPTIMIZER_SWITCH_INDEX_MERGE_UNION 2 +#define OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION 4 +#define OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT 8 +#define OPTIMIZER_SWITCH_LAST 16 + +/* The following must be kept in sync with optimizer_switch_str in mysqld.cc */ +#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \ + OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \ + OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION | \ + OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT) + + /* Replication uses 8 bytes to store SQL_MODE in the binary log. The day you use strictly more than 64 bits by adding one more define above, you should @@ -1829,6 +1843,10 @@ extern enum_field_types agg_field_type(Item **items, uint nitems); /* strfunc.cc */ ulonglong find_set(TYPELIB *lib, const char *x, uint length, CHARSET_INFO *cs, char **err_pos, uint *err_len, bool *set_warning); +ulonglong find_set_from_flags(TYPELIB *lib, uint default_name, + ulonglong cur_set, ulonglong default_set, + const char *str, uint length, CHARSET_INFO *cs, + char **err_pos, uint *err_len, bool *set_warning); uint find_type(const TYPELIB *lib, const char *find, uint length, bool part_match); uint find_type2(const TYPELIB *lib, const char *find, uint length, @@ -2058,6 +2076,9 @@ extern SHOW_COMP_OPTION have_geometry, have_rtree_keys; extern SHOW_COMP_OPTION have_crypt; extern SHOW_COMP_OPTION have_compress; +extern int orig_argc; +extern char **orig_argv; +extern const char *load_default_groups[]; #ifndef __WIN__ extern pthread_t signal_thread; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8af23d7fb2b..44e1cafcb87 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -300,6 +300,25 @@ static const unsigned int sql_mode_names_len[]= TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"", sql_mode_names, (unsigned int *)sql_mode_names_len }; + +static const char *optimizer_switch_names[]= +{ + "index_merge","index_merge_union","index_merge_sort_union", + "index_merge_intersection", "default", NullS +}; +/* Corresponding defines are named OPTIMIZER_SWITCH_XXX */ +static const unsigned int optimizer_switch_names_len[]= +{ + sizeof("index_merge") - 1, + sizeof("index_merge_union") - 1, + sizeof("index_merge_sort_union") - 1, + sizeof("index_merge_intersection") - 1, + sizeof("default") - 1 +}; +TYPELIB optimizer_switch_typelib= { array_elements(optimizer_switch_names)-1,"", + optimizer_switch_names, + (unsigned int *)optimizer_switch_names_len }; + static const char *tc_heuristic_recover_names[]= { "COMMIT", "ROLLBACK", NullS @@ -366,6 +385,10 @@ static ulong max_used_connections; static ulong my_bind_addr; /**< the address we bind to */ static volatile ulong cached_thread_count= 0; static const char *sql_mode_str= "OFF"; +/* Text representation for OPTIMIZER_SWITCH_DEFAULT */ +static const char *optimizer_switch_str="index_merge=on,index_merge_union=on," + "index_merge_sort_union=on," + "index_merge_intersection=on"; static char *mysqld_user, *mysqld_chroot, *log_error_file_ptr; static char *opt_init_slave, *language_ptr, *opt_init_connect; static char *default_character_set_name; @@ -653,6 +676,9 @@ static int defaults_argc; static char **defaults_argv; static char *opt_bin_logname; +int orig_argc; +char **orig_argv; + static my_socket unix_sock, base_ip_sock, extra_ip_sock; struct my_rnd_struct sql_rand; ///< used by sql_class.cc:THD::THD() @@ -3014,8 +3040,7 @@ pthread_handler_t handle_shutdown(void *arg) } #endif -#if !defined(EMBEDDED_LIBRARY) -static const char *load_default_groups[]= { +const char *load_default_groups[]= { #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE "mysql_cluster", #endif @@ -3023,11 +3048,10 @@ static const char *load_default_groups[]= { "mariadb", MARIADB_BASE_VERSION, 0, 0}; -#if defined(__WIN__) +#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY) static const int load_default_groups_sz= sizeof(load_default_groups)/sizeof(load_default_groups[0]); #endif -#endif /*!EMBEDDED_LIBRARY*/ /** @@ -3313,6 +3337,8 @@ static int init_common_variables(const char *conf_file_name, int argc, SQLCOM_END + 8); #endif + orig_argc=argc; + orig_argv=argv; load_defaults(conf_file_name, groups, &argc, &argv); defaults_argv=argv; defaults_argc=argc; @@ -3989,6 +4015,7 @@ server."); if ((ho_error= handle_options(&defaults_argc, &tmp_argv, no_opts, mysqld_get_one_option))) unireg_abort(ho_error); + my_getopt_skip_unknown= TRUE; if (defaults_argc) { @@ -5707,6 +5734,7 @@ enum options_mysqld OPT_SYSDATE_IS_NOW, OPT_OPTIMIZER_SEARCH_DEPTH, OPT_OPTIMIZER_PRUNE_LEVEL, + OPT_OPTIMIZER_SWITCH, OPT_UPDATABLE_VIEWS_WITH_LIMIT, OPT_SP_AUTOMATIC_PRIVILEGES, OPT_MAX_SP_RECURSION_DEPTH, @@ -6905,6 +6933,13 @@ The minimum value for this variable is 4096.", (uchar**) &global_system_variables.optimizer_search_depth, (uchar**) &max_system_variables.optimizer_search_depth, 0, GET_ULONG, OPT_ARG, MAX_TABLES+1, 0, MAX_TABLES+2, 0, 1, 0}, + {"optimizer_switch", OPT_OPTIMIZER_SWITCH, + "optimizer_switch=option=val[,option=val...], where option={index_merge, " + "index_merge_union, index_merge_sort_union, index_merge_intersection} and " + "val={on, off, default}.", + (uchar**) &optimizer_switch_str, (uchar**) &optimizer_switch_str, 0, GET_STR, REQUIRED_ARG, + /*OPTIMIZER_SWITCH_DEFAULT*/0, + 0, 0, 0, 0, 0}, {"plugin_dir", OPT_PLUGIN_DIR, "Directory for plugins.", (uchar**) &opt_plugin_dir_ptr, (uchar**) &opt_plugin_dir_ptr, 0, @@ -7819,7 +7854,8 @@ static int mysql_init_variables(void) when collecting index statistics for MyISAM tables. */ global_system_variables.myisam_stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL; - + + global_system_variables.optimizer_switch= OPTIMIZER_SWITCH_DEFAULT; /* Variables that depends on compile options */ #ifndef DBUG_OFF default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace", @@ -8460,6 +8496,29 @@ mysqld_get_one_option(int optid, sql_mode); break; } + case OPT_OPTIMIZER_SWITCH: + { + bool not_used; + char *error= 0; + uint error_len= 0; + optimizer_switch_str= argument; + global_system_variables.optimizer_switch= + (ulong)find_set_from_flags(&optimizer_switch_typelib, + optimizer_switch_typelib.count, + global_system_variables.optimizer_switch, + global_system_variables.optimizer_switch, + argument, strlen(argument), NULL, + &error, &error_len, ¬_used); + if (error) + { + char buf[512]; + char *cbuf= buf; + cbuf += my_snprintf(buf, 512, "Error in parsing optimizer_switch setting near %*s\n", error_len, error); + sql_perror(buf); + return 1; + } + break; + } case OPT_ONE_THREAD: global_system_variables.thread_handling= SCHEDULER_ONE_THREAD_PER_CONNECTION; diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 1098e8e6832..0a8720bae64 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -249,7 +249,7 @@ static int net_data_is_ready(my_socket sd) tv.tv_sec= tv.tv_usec= 0; - if ((res= select(sd+1, &sfds, NULL, NULL, &tv)) < 0) + if ((res= select((int) (sd + 1), &sfds, NULL, NULL, &tv)) < 0) return 0; else return test(res ? FD_ISSET(sd, &sfds) : 0); @@ -429,7 +429,7 @@ net_write_command(NET *net,uchar command, const uchar *header, size_t head_len, const uchar *packet, size_t len) { - ulong length=len+1+head_len; /* 1 extra byte for command */ + size_t length=len+1+head_len; /* 1 extra byte for command */ uchar buff[NET_HEADER_SIZE+1]; uint header_size=NET_HEADER_SIZE+1; DBUG_ENTER("net_write_command"); @@ -495,7 +495,7 @@ net_write_buff(NET *net, const uchar *packet, ulong len) { ulong left_length; if (net->compress && net->max_packet > MAX_PACKET_LENGTH) - left_length= MAX_PACKET_LENGTH - (net->write_pos - net->buff); + left_length= (ulong) (MAX_PACKET_LENGTH - (net->write_pos - net->buff)); else left_length= (ulong) (net->buff_end - net->write_pos); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index c17b7cf270a..220d281cf33 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2386,7 +2386,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, objects are not allowed so don't use ROR-intersection for table deletes. */ - if ((thd->lex->sql_command != SQLCOM_DELETE)) + if ((thd->lex->sql_command != SQLCOM_DELETE) && + optimizer_flag(thd, OPTIMIZER_SWITCH_INDEX_MERGE)) { /* Get best non-covering ROR-intersection plan and prepare data for @@ -2410,25 +2411,28 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, } else { - /* Try creating index_merge/ROR-union scan. */ - SEL_IMERGE *imerge; - TABLE_READ_PLAN *best_conj_trp= NULL, *new_conj_trp; - LINT_INIT(new_conj_trp); /* no empty index_merge lists possible */ - DBUG_PRINT("info",("No range reads possible," - " trying to construct index_merge")); - List_iterator_fast<SEL_IMERGE> it(tree->merges); - while ((imerge= it++)) + if (optimizer_flag(thd, OPTIMIZER_SWITCH_INDEX_MERGE)) { - new_conj_trp= get_best_disjunct_quick(¶m, imerge, best_read_time); - if (new_conj_trp) - set_if_smaller(param.table->quick_condition_rows, - new_conj_trp->records); - if (!best_conj_trp || (new_conj_trp && new_conj_trp->read_cost < - best_conj_trp->read_cost)) - best_conj_trp= new_conj_trp; + /* Try creating index_merge/ROR-union scan. */ + SEL_IMERGE *imerge; + TABLE_READ_PLAN *best_conj_trp= NULL, *new_conj_trp; + LINT_INIT(new_conj_trp); /* no empty index_merge lists possible */ + DBUG_PRINT("info",("No range reads possible," + " trying to construct index_merge")); + List_iterator_fast<SEL_IMERGE> it(tree->merges); + while ((imerge= it++)) + { + new_conj_trp= get_best_disjunct_quick(¶m, imerge, best_read_time); + if (new_conj_trp) + set_if_smaller(param.table->quick_condition_rows, + new_conj_trp->records); + if (!best_conj_trp || (new_conj_trp && new_conj_trp->read_cost < + best_conj_trp->read_cost)) + best_conj_trp= new_conj_trp; + } + if (best_conj_trp) + best_trp= best_conj_trp; } - if (best_conj_trp) - best_trp= best_conj_trp; } } @@ -3768,11 +3772,19 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, "full table scan, bailing out")); DBUG_RETURN(NULL); } - if (all_scans_rors) + + /* + If all scans happen to be ROR, proceed to generate a ROR-union plan (it's + guaranteed to be cheaper than non-ROR union), unless ROR-unions are + disabled in @@optimizer_switch + */ + if (all_scans_rors && + optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_UNION)) { roru_read_plans= (TABLE_READ_PLAN**)range_scans; goto skip_to_ror_scan; } + if (cpk_scan) { /* @@ -3786,8 +3798,11 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, imerge_cost += get_sweep_read_cost(param, non_cpk_scan_records); DBUG_PRINT("info",("index_merge cost with rowid-to-row scan: %g", imerge_cost)); - if (imerge_cost > read_time) + if (imerge_cost > read_time || + !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION)) + { goto build_ror_index_merge; + } /* Add Unique operations cost */ unique_calc_buff_size= @@ -3823,7 +3838,9 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, } build_ror_index_merge: - if (!all_scans_ror_able || param->thd->lex->sql_command == SQLCOM_DELETE) + if (!all_scans_ror_able || + param->thd->lex->sql_command == SQLCOM_DELETE || + !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_UNION)) DBUG_RETURN(imerge_trp); /* Ok, it is possible to build a ROR-union, try it. */ @@ -4496,7 +4513,8 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, double min_cost= DBL_MAX; DBUG_ENTER("get_best_ror_intersect"); - if ((tree->n_ror_scans < 2) || !param->table->file->stats.records) + if ((tree->n_ror_scans < 2) || !param->table->file->stats.records || + !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT)) DBUG_RETURN(NULL); /* @@ -4686,6 +4704,9 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, ROR_SCAN_INFO **ror_scans_end= tree->ror_scans_end; DBUG_ENTER("get_best_covering_ror_intersect"); + if (!optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT)) + DBUG_RETURN(NULL); + for (ROR_SCAN_INFO **scan= tree->ror_scans; scan != ror_scans_end; ++scan) (*scan)->key_components= param->table->key_info[(*scan)->keynr].key_parts; @@ -9474,7 +9495,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) } /* If we got to this point, cur_index_info passes the test. */ - key_infix_parts= cur_key_infix_len ? + key_infix_parts= cur_key_infix_len ? (uint) (first_non_infix_part - first_non_group_part) : 0; cur_used_key_parts= cur_group_key_parts + key_infix_parts; diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h index 8e2f4a7374f..1f4ca246ff1 100644 --- a/sql/rpl_utility.h +++ b/sql/rpl_utility.h @@ -294,12 +294,14 @@ namespace { } #endif +// NB. number of printed bit values is limited to sizeof(buf) - 1 #define DBUG_PRINT_BITSET(N,FRM,BS) \ do { \ char buf[256]; \ - for (uint i = 0 ; i < (BS)->n_bits ; ++i) \ + uint i; \ + for (i = 0 ; i < min(sizeof(buf) - 1, (BS)->n_bits) ; i++) \ buf[i] = bitmap_is_set((BS), i) ? '1' : '0'; \ - buf[(BS)->n_bits] = '\0'; \ + buf[i] = '\0'; \ DBUG_PRINT((N), ((FRM), buf)); \ } while (0) diff --git a/sql/set_var.cc b/sql/set_var.cc index c1071c90223..21500666f49 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -487,6 +487,8 @@ static sys_var_thd_ulong sys_optimizer_prune_level(&vars, "optimizer_prun &SV::optimizer_prune_level); static sys_var_thd_ulong sys_optimizer_search_depth(&vars, "optimizer_search_depth", &SV::optimizer_search_depth); +static sys_var_thd_optimizer_switch sys_optimizer_switch(&vars, "optimizer_switch", + &SV::optimizer_switch); static sys_var_const sys_pid_file(&vars, "pid_file", OPT_GLOBAL, SHOW_CHAR, (uchar*) pidfile_name); @@ -3943,6 +3945,97 @@ ulong fix_sql_mode(ulong sql_mode) } +bool +sys_var_thd_optimizer_switch:: +symbolic_mode_representation(THD *thd, ulonglong val, LEX_STRING *rep) +{ + char buff[STRING_BUFFER_USUAL_SIZE*8]; + String tmp(buff, sizeof(buff), &my_charset_latin1); + int i; + ulonglong bit; + tmp.length(0); + + for (i= 0, bit=1; bit != OPTIMIZER_SWITCH_LAST; i++, bit= bit << 1) + { + tmp.append(optimizer_switch_typelib.type_names[i], + optimizer_switch_typelib.type_lengths[i]); + tmp.append('='); + tmp.append((val & bit)? "on":"off"); + tmp.append(','); + } + + if (tmp.length()) + tmp.length(tmp.length() - 1); /* trim the trailing comma */ + + rep->str= thd->strmake(tmp.ptr(), tmp.length()); + + rep->length= rep->str ? tmp.length() : 0; + + return rep->length != tmp.length(); +} + + +uchar *sys_var_thd_optimizer_switch::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) +{ + LEX_STRING opts; + ulonglong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset : + thd->variables.*offset); + (void) symbolic_mode_representation(thd, val, &opts); + return (uchar *) opts.str; +} + + +/* + Check (and actually parse) string representation of @@optimizer_switch. +*/ + +bool sys_var_thd_optimizer_switch::check(THD *thd, set_var *var) +{ + bool not_used; + char buff[STRING_BUFFER_USUAL_SIZE], *error= 0; + uint error_len= 0; + String str(buff, sizeof(buff), system_charset_info), *res; + + if (!(res= var->value->val_str(&str))) + { + strmov(buff, "NULL"); + goto err; + } + + if (res->length() == 0) + { + buff[0]= 0; + goto err; + } + + var->save_result.ulong_value= + (ulong)find_set_from_flags(&optimizer_switch_typelib, + optimizer_switch_typelib.count, + thd->variables.optimizer_switch, + global_system_variables.optimizer_switch, + res->c_ptr_safe(), res->length(), NULL, + &error, &error_len, ¬_used); + if (error_len) + { + strmake(buff, error, min(sizeof(buff) - 1, error_len)); + goto err; + } + return FALSE; +err: + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buff); + return TRUE; +} + + +void sys_var_thd_optimizer_switch::set_default(THD *thd, enum_var_type type) +{ + if (type == OPT_GLOBAL) + global_system_variables.*offset= OPTIMIZER_SWITCH_DEFAULT; + else + thd->variables.*offset= global_system_variables.*offset; +} + /**************************************************************************** Named list handling ****************************************************************************/ diff --git a/sql/set_var.h b/sql/set_var.h index b6c67d1ab4a..10e6e0f9c35 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -31,7 +31,7 @@ typedef struct system_variables SV; typedef struct my_locale_st MY_LOCALE; extern TYPELIB bool_typelib, delay_key_write_typelib, sql_mode_typelib, - slave_exec_mode_typelib; + optimizer_switch_typelib, slave_exec_mode_typelib; typedef int (*sys_check_func)(THD *, set_var *); typedef bool (*sys_update_func)(THD *, set_var *); @@ -532,6 +532,20 @@ public: }; +class sys_var_thd_optimizer_switch :public sys_var_thd_enum +{ +public: + sys_var_thd_optimizer_switch(sys_var_chain *chain, const char *name_arg, + ulong SV::*offset_arg) + :sys_var_thd_enum(chain, name_arg, offset_arg, &optimizer_switch_typelib) + {} + bool check(THD *thd, set_var *var); + void set_default(THD *thd, enum_var_type type); + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + static bool symbolic_mode_representation(THD *thd, ulonglong sql_mode, + LEX_STRING *rep); +}; + extern void fix_sql_mode_var(THD *thd, enum_var_type type); class sys_var_thd_sql_mode :public sys_var_thd_enum diff --git a/sql/slave.cc b/sql/slave.cc index 6d48e57d298..f5e8a11efe9 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2633,6 +2633,41 @@ err: DBUG_RETURN(0); // Can't return anything here } +/* + Check the temporary directory used by commands like + LOAD DATA INFILE. + */ +static +int check_temp_dir(char* tmp_dir, char *tmp_file) +{ + int fd; + MY_DIR *dirp; + + DBUG_ENTER("check_temp_dir"); + + /* + Check if the directory exists. + */ + if (!(dirp=my_dir(tmp_dir,MYF(MY_WME)))) + DBUG_RETURN(1); + my_dirend(dirp); + + /* + Check permissions to create a file. + */ + if ((fd= my_create(tmp_file, CREATE_MODE, + O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, + MYF(MY_WME))) < 0) + DBUG_RETURN(1); + + /* + Clean up. + */ + my_close(fd, MYF(0)); + my_delete(tmp_file, MYF(0)); + + DBUG_RETURN(0); +} /** Slave SQL thread entry point. @@ -2764,6 +2799,14 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME, llstr(rli->group_master_log_pos,llbuff),rli->group_relay_log_name, llstr(rli->group_relay_log_pos,llbuff1)); + if (check_temp_dir(slave_load_tmpdir, rli->slave_patternload_file)) + { + rli->report(ERROR_LEVEL, thd->main_da.sql_errno(), + "Unable to use slave's temporary directory %s - %s", + slave_load_tmpdir, thd->main_da.message()); + goto err; + } + /* execute init_slave variable */ if (sys_init_slave.value_length) { diff --git a/sql/sp_head.cc b/sql/sp_head.cc index ef6cb556f4c..fcf51aac1b5 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -956,6 +956,8 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) qbuf.length(0); cur= query_str->str; prev_pos= res= 0; + thd->query_name_consts= 0; + for (Item_splocal **splocal= sp_vars_uses.front(); splocal < sp_vars_uses.back(); splocal++) { @@ -989,6 +991,8 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) res|= qbuf.append(')'); if (res) break; + + thd->query_name_consts++; } res|= qbuf.append(cur + prev_pos, query_str->length - prev_pos); if (res) @@ -2853,6 +2857,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) *nextp= m_ip+1; thd->query= query; thd->query_length= query_length; + thd->query_name_consts= 0; if (!thd->is_error()) thd->main_da.reset_diagnostics_area(); diff --git a/sql/sp_head.h b/sql/sp_head.h index 3d7597e2402..c17b67f962a 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -367,7 +367,7 @@ public: char *name(uint *lenp = 0) const { if (lenp) - *lenp= m_name.length; + *lenp= (uint) m_name.length; return m_name.str; } diff --git a/sql/spatial.h b/sql/spatial.h index 69a1f24506e..dbf5da6665b 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -281,7 +281,7 @@ public: uint32 len, String *res); int as_wkt(String *wkt, const char **end) { - uint32 len= get_class_info()->m_name.length; + uint32 len= (uint) get_class_info()->m_name.length; if (wkt->reserve(len + 2, 512)) return 1; wkt->qs_append(get_class_info()->m_name.str, len); diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 5ff5e596f63..d56e246edae 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1114,7 +1114,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", { memcpy(thd->query+thd->query_length+1, thd->db, thd->db_length); DBUG_PRINT("qcache", ("database: %s length: %u", - thd->db, thd->db_length)); + thd->db, (unsigned) thd->db_length)); } else { @@ -1310,7 +1310,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) { memcpy(sql+query_length+1, thd->db, thd->db_length); DBUG_PRINT("qcache", ("database: '%s' length: %u", - thd->db, thd->db_length)); + thd->db, (unsigned)thd->db_length)); } else { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 2ed0a339628..6b990aea537 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -606,6 +606,7 @@ THD::THD() one_shot_set= 0; file_id = 0; query_id= 0; + query_name_consts= 0; warn_id= 0; db_charset= global_system_variables.collation_database; bzero(ha_data, sizeof(ha_data)); @@ -2358,7 +2359,7 @@ void Query_arena::set_query_arena(Query_arena *set) void Query_arena::cleanup_stmt() { - DBUG_ASSERT("Query_arena::cleanup_stmt()" == "not implemented"); + DBUG_ASSERT(! "Query_arena::cleanup_stmt() not implemented"); } /* @@ -2860,6 +2861,14 @@ Security_context::restore_security_context(THD *thd, } #endif + +bool Security_context::user_matches(Security_context *them) +{ + return ((user != NULL) && (them->user != NULL) && + !strcmp(user, them->user)); +} + + /**************************************************************************** Handling of open and locked tables states. diff --git a/sql/sql_class.h b/sql/sql_class.h index 16956e07274..3183699fcd0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -323,6 +323,8 @@ struct system_variables ulong net_write_timeout; ulong optimizer_prune_level; ulong optimizer_search_depth; + /* A bitmap for switching optimizations on/off */ + ulong optimizer_switch; ulong preload_buff_size; ulong profiling_history_size; ulong query_cache_type; @@ -670,7 +672,7 @@ public: */ char *db; - uint db_length; + size_t db_length; public: @@ -817,6 +819,7 @@ public: void restore_security_context(THD *thd, Security_context *backup); #endif + bool user_matches(Security_context *); }; @@ -1782,6 +1785,9 @@ public: sp_cache *sp_proc_cache; sp_cache *sp_func_cache; + /** number of name_const() substitutions, see sp_head.cc:subst_spvars() */ + uint query_name_consts; + /* If we do a purge of binary logs, log index info of the threads that are currently reading it needs to be adjusted. To do that diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index ef3cfaa4e11..1b6c337a43e 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -54,7 +54,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, USER_RESOURCES *mqh) { int return_val= 0; - uint temp_len, user_len; + size_t temp_len, user_len; char temp_user[USER_HOST_BUFF_SIZE]; struct user_conn *uc; diff --git a/sql/sql_crypt.cc b/sql/sql_crypt.cc index 53babf517c1..f7f63efa077 100644 --- a/sql/sql_crypt.cc +++ b/sql/sql_crypt.cc @@ -31,7 +31,7 @@ SQL_CRYPT::SQL_CRYPT(const char *password) { ulong rand_nr[2]; - hash_password(rand_nr,password, strlen(password)); + hash_password(rand_nr,password, (uint) strlen(password)); crypt_init(rand_nr); } diff --git a/sql/sql_error.cc b/sql/sql_error.cc index bd8f9469571..9ea7facbe41 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -251,7 +251,7 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show) protocol->store(warning_level_names[err->level].str, warning_level_names[err->level].length, system_charset_info); protocol->store((uint32) err->code); - protocol->store(err->msg, strlen(err->msg), system_charset_info); + protocol->store(err->msg, (uint) strlen(err->msg), system_charset_info); if (protocol->write()) DBUG_RETURN(TRUE); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index aa8c6099fca..09e977ea801 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1680,11 +1680,12 @@ public: ulong auto_increment_offset; timestamp_auto_set_type timestamp_field_type; LEX_STRING query; + Time_zone *time_zone; delayed_row(LEX_STRING const query_arg, enum_duplicates dup_arg, bool ignore_arg, bool log_query_arg) : record(0), dup(dup_arg), ignore(ignore_arg), log_query(log_query_arg), - forced_insert_id(0), query(query_arg) + forced_insert_id(0), query(query_arg), time_zone(0) {} ~delayed_row() { @@ -1906,7 +1907,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) pthread_mutex_lock(&LOCK_thread_count); thread_count++; pthread_mutex_unlock(&LOCK_thread_count); - di->thd.set_db(table_list->db, strlen(table_list->db)); + di->thd.set_db(table_list->db, (uint) strlen(table_list->db)); di->thd.query= my_strdup(table_list->table_name, MYF(MY_WME)); if (di->thd.db == NULL || di->thd.query == NULL) { @@ -2174,6 +2175,19 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, thd->first_successful_insert_id_in_prev_stmt; row->timestamp_field_type= table->timestamp_field_type; + /* Add session variable timezone + Time_zone object will not be freed even the thread is ended. + So we can get time_zone object from thread which handling delayed statement. + See the comment of my_tz_find() for detail. + */ + if (thd->time_zone_used) + { + row->time_zone = thd->variables.time_zone; + } + else + { + row->time_zone = NULL; + } /* Copy session variables. */ row->auto_increment_increment= thd->variables.auto_increment_increment; row->auto_increment_offset= thd->variables.auto_increment_offset; @@ -2674,6 +2688,14 @@ bool Delayed_insert::handle_inserts(void) if (log_query && mysql_bin_log.is_open()) { + bool backup_time_zone_used = thd.time_zone_used; + Time_zone *backup_time_zone = thd.variables.time_zone; + if (row->time_zone != NULL) + { + thd.time_zone_used = true; + thd.variables.time_zone = row->time_zone; + } + /* If the query has several rows to insert, only the first row will come here. In row-based binlogging, this means that the first row will be @@ -2685,6 +2707,9 @@ bool Delayed_insert::handle_inserts(void) thd.binlog_query(THD::ROW_QUERY_TYPE, row->query.str, row->query.length, FALSE, FALSE); + + thd.time_zone_used = backup_time_zone_used; + thd.variables.time_zone = backup_time_zone; } if (table->s->blob_fields) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 1c1f3bbe06f..da00ab7a239 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -253,7 +253,7 @@ void Lex_input_stream::body_utf8_append_literal(THD *thd, { thd->convert_string(&utf_txt, &my_charset_utf8_general_ci, - txt->str, txt->length, + txt->str, (uint) txt->length, txt_cs); } else @@ -435,7 +435,7 @@ bool is_keyword(const char *name, uint len) bool is_lex_native_function(const LEX_STRING *name) { DBUG_ASSERT(name != NULL); - return (get_hash_symbol(name->str, name->length, 1) != 0); + return (get_hash_symbol(name->str, (uint) name->length, 1) != 0); } /* make a copy of token before ptr and set yytoklen */ @@ -1082,7 +1082,7 @@ int MYSQLlex(void *arg, void *yythd) if (c != '.') { // Found complete integer number. yylval->lex_str=get_token(lip, 0, lip->yyLength()); - return int_token(yylval->lex_str.str,yylval->lex_str.length); + return int_token(yylval->lex_str.str, (uint) yylval->lex_str.length); } // fall through case MY_LEX_REAL: // Incomplete real number @@ -1988,8 +1988,8 @@ void st_select_lex::print_order(String *str, if (order->counter_used) { char buffer[20]; - uint length= my_snprintf(buffer, 20, "%d", order->counter); - str->append(buffer, length); + size_t length= my_snprintf(buffer, 20, "%d", order->counter); + str->append(buffer, (uint) length); } else (*order->item)->print(str, query_type); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a48b99d07c7..f34a1c7c36f 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1370,7 +1370,7 @@ public: /** Get the utf8-body length. */ uint get_body_utf8_length() { - return m_body_utf8_ptr - m_body_utf8; + return (uint) (m_body_utf8_ptr - m_body_utf8); } void body_utf8_start(THD *thd, const char *begin_ptr); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 41c96a13829..278e01d4de6 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -557,8 +557,8 @@ static bool write_execute_load_query_log_event(THD *thd, { Execute_load_query_log_event e(thd, thd->query, thd->query_length, - (char*)thd->lex->fname_start - (char*)thd->query, - (char*)thd->lex->fname_end - (char*)thd->query, + (uint) ((char*)thd->lex->fname_start - (char*)thd->query), + (uint) ((char*)thd->lex->fname_end - (char*)thd->query), (duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE : (ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR), transactional_table, FALSE, killed_err_arg); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 5b316f130b9..54365da5496 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2578,6 +2578,43 @@ mysql_execute_command(THD *thd) { select_result *result; + /* + If: + a) we inside an SP and there was NAME_CONST substitution, + b) binlogging is on (STMT mode), + c) we log the SP as separate statements + raise a warning, as it may cause problems + (see 'NAME_CONST issues' in 'Binary Logging of Stored Programs') + */ + if (thd->query_name_consts && + mysql_bin_log.is_open() && + thd->variables.binlog_format == BINLOG_FORMAT_STMT && + !mysql_bin_log.is_query_in_union(thd, thd->query_id)) + { + List_iterator_fast<Item> it(select_lex->item_list); + Item *item; + uint splocal_refs= 0; + /* Count SP local vars in the top-level SELECT list */ + while ((item= it++)) + { + if (item->is_splocal()) + splocal_refs++; + } + /* + If it differs from number of NAME_CONST substitution applied, + we may have a SOME_FUNC(NAME_CONST()) in the SELECT list, + that may cause a problem with binary log (see BUG#35383), + raise a warning. + */ + if (splocal_refs != thd->query_name_consts) + push_warning(thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_UNKNOWN_ERROR, +"Invoked routine ran a statement that may cause problems with " +"binary log, see 'NAME_CONST issues' in 'Binary Logging of Stored Programs' " +"section of the manual."); + } + select_lex->options|= SELECT_NO_UNLOCK; unit->set_limit(select_lex); @@ -4151,9 +4188,32 @@ end_with_restore_list: res= (sp_result= lex->sphead->create(thd)); switch (sp_result) { - case SP_OK: + case SP_OK: { #ifndef NO_EMBEDDED_ACCESS_CHECKS /* only add privileges if really neccessary */ + + Security_context security_context; + bool restore_backup_context= false; + Security_context *backup= NULL; + LEX_USER *definer= thd->lex->definer; + /* + Check if the definer exists on slave, + then use definer privilege to insert routine privileges to mysql.procs_priv. + + For current user of SQL thread has GLOBAL_ACL privilege, + which doesn't any check routine privileges, + so no routine privilege record will insert into mysql.procs_priv. + */ + if (thd->slave_thread && is_acl_user(definer->host.str, definer->user.str)) + { + security_context.change_security_context(thd, + &thd->lex->definer->user, + &thd->lex->definer->host, + &thd->lex->sphead->m_db, + &backup); + restore_backup_context= true; + } + if (sp_automatic_privileges && !opt_noacl && check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS, lex->sphead->m_db.str, name, @@ -4165,8 +4225,19 @@ end_with_restore_list: ER_PROC_AUTO_GRANT_FAIL, ER(ER_PROC_AUTO_GRANT_FAIL)); } + + /* + Restore current user with GLOBAL_ACL privilege of SQL thread + */ + if (restore_backup_context) + { + DBUG_ASSERT(thd->slave_thread == 1); + thd->security_ctx->restore_security_context(thd, backup); + } + #endif break; + } case SP_WRITE_ROW_FAILED: my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name); break; @@ -6878,8 +6949,26 @@ uint kill_one_thread(THD *thd, ulong id, bool only_kill_query) VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (tmp) { + + /* + If we're SUPER, we can KILL anything, including system-threads. + No further checks. + + KILLer: thd->security_ctx->user could in theory be NULL while + we're still in "unauthenticated" state. This is a theoretical + case (the code suggests this could happen, so we play it safe). + + KILLee: tmp->security_ctx->user will be NULL for system threads. + We need to check so Jane Random User doesn't crash the server + when trying to kill a) system threads or b) unauthenticated users' + threads (Bug#43748). + + If user of both killer and killee are non-NULL, proceed with + slayage if both are string-equal. + */ + if ((thd->security_ctx->master_access & SUPER_ACL) || - !strcmp(thd->security_ctx->user, tmp->security_ctx->user)) + thd->security_ctx->user_matches(tmp->security_ctx)) { tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION); error=0; diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 6a59154dd22..a1748c0f5f5 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1139,8 +1139,9 @@ int plugin_init(int *argc, char **argv, int flags) for (plugin= *builtins; plugin->info; plugin++) { if (opt_ignore_builtin_innodb && - !my_strcasecmp(&my_charset_latin1, plugin->name, "InnoDB")) - continue; + !my_strnncoll(&my_charset_latin1, (const uchar*) plugin->name, + 6, (const uchar*) "InnoDB", 6)) + continue; /* by default, ndbcluster and federated are disabled */ def_enabled= my_strcasecmp(&my_charset_latin1, plugin->name, "NDBCLUSTER") != 0 && @@ -1633,8 +1634,8 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl { TABLE_LIST tables; TABLE *table; - int error, argc; - char *argv[2]; + int error, argc=orig_argc; + char **argv=orig_argv; struct st_plugin_int *tmp; DBUG_ENTER("mysql_install_plugin"); @@ -1650,21 +1651,31 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl pthread_mutex_lock(&LOCK_plugin); rw_wrlock(&LOCK_system_variables_hash); - /* handle_options() assumes arg0 (program name) always exists */ - argv[0]= const_cast<char*>(""); // without a cast gcc emits a warning - argv[1]= 0; - argc= 1; + + my_load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv, NULL); error= plugin_add(thd->mem_root, name, dl, &argc, argv, REPORT_TO_USER); + if (argv) + free_defaults(argv); rw_unlock(&LOCK_system_variables_hash); if (error || !(tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN))) goto err; - if (plugin_initialize(tmp)) + if (tmp->state == PLUGIN_IS_DISABLED) { - my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str, - "Plugin initialization function failed."); - goto deinit; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_CANT_INITIALIZE_UDF, ER(ER_CANT_INITIALIZE_UDF), + name->str, "Plugin is disabled"); + } + else + { + DBUG_ASSERT(tmp->state == PLUGIN_IS_UNINITIALIZED); + if (plugin_initialize(tmp)) + { + my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str, + "Plugin initialization function failed."); + goto deinit; + } } /* diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 19a782a514c..427402133d2 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -759,13 +759,13 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, Item_param *param= *it; if (param->state != Item_param::LONG_DATA_VALUE) { - if (is_param_null(null_array, it - begin)) + if (is_param_null(null_array, (uint) (it - begin))) param->set_null(); else { if (read_pos >= data_end) DBUG_RETURN(1); - param->set_param_func(param, &read_pos, data_end - read_pos); + param->set_param_func(param, &read_pos, (uint) (data_end - read_pos)); if (param->state == Item_param::NO_VALUE) DBUG_RETURN(1); } @@ -797,13 +797,13 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array, Item_param *param= *it; if (param->state != Item_param::LONG_DATA_VALUE) { - if (is_param_null(null_array, it - begin)) + if (is_param_null(null_array, (uint) (it - begin))) param->set_null(); else { if (read_pos >= data_end) DBUG_RETURN(1); - param->set_param_func(param, &read_pos, data_end - read_pos); + param->set_param_func(param, &read_pos, (uint) (data_end - read_pos)); if (param->state == Item_param::NO_VALUE) DBUG_RETURN(1); } diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index 320360b2587..de501b9089e 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -116,7 +116,7 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table) if (field) { field->set_name(field_info->old_name, - strlen(field_info->old_name), + (uint) strlen(field_info->old_name), system_charset_info); if (add_item_to_list(thd, field)) return 1; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 14088961ea2..57319e4cda7 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -205,7 +205,7 @@ void adjust_linfo_offsets(my_off_t purge_offset) bool log_in_use(const char* log_name) { - int log_name_len = strlen(log_name) + 1; + size_t log_name_len = strlen(log_name) + 1; THD *tmp; bool result = 0; @@ -1366,8 +1366,8 @@ int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1, const char* log_file_name2, ulonglong log_pos2) { int res; - uint log_file_name1_len= strlen(log_file_name1); - uint log_file_name2_len= strlen(log_file_name2); + size_t log_file_name1_len= strlen(log_file_name1); + size_t log_file_name2_len= strlen(log_file_name2); // We assume that both log names match up to '.' if (log_file_name1_len == log_file_name2_len) @@ -1687,7 +1687,7 @@ int log_loaded_block(IO_CACHE* file) lf_info->last_pos_in_file >= my_b_get_pos_in_file(file)) DBUG_RETURN(0); - for (block_len= my_b_get_bytes_in_buffer(file); block_len > 0; + for (block_len= (uint) (my_b_get_bytes_in_buffer(file)); block_len > 0; buffer += min(block_len, max_event_size), block_len -= min(block_len, max_event_size)) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d7eed19d619..5cf6c9b1dbe 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7658,7 +7658,7 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond, if (and_level) { /* - Retrieve all conjucts of this level detecting the equality + Retrieve all conjuncts of this level detecting the equality that are subject to substitution by multiple equality items and removing each such predicate from the conjunction after having found/created a multiple equality whose inference the predicate is. @@ -7674,6 +7674,15 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond, li.remove(); } + /* + Check if we eliminated all the predicates of the level, e.g. + (a=a AND b=b AND a=a). + */ + if (!args->elements && + !cond_equal.current_level.elements && + !eq_list.elements) + return new Item_int((longlong) 1, 1); + List_iterator_fast<Item_equal> it(cond_equal.current_level); while ((item_equal= it++)) { @@ -9820,6 +9829,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, table->in_use= thd; table->quick_keys.init(); table->covering_keys.init(); + table->merge_keys.init(); table->keys_in_use_for_query.init(); table->s= share; diff --git a/sql/sql_select.h b/sql/sql_select.h index 43e26a6b4b2..5e97185a7b9 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -730,3 +730,9 @@ bool error_if_full_join(JOIN *join); int report_error(TABLE *table, int error); int safe_index_read(JOIN_TAB *tab); COND *remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value); + +inline bool optimizer_flag(THD *thd, uint flag) +{ + return (thd->variables.optimizer_switch & flag); +} + diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index 13bed8001a3..f8a8dea18ff 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -60,7 +60,7 @@ prepare_server_struct_for_insert(LEX_SERVER_OPTIONS *server_options); /* drop functions */ static int delete_server_record(TABLE *table, char *server_name, - int server_name_length); + size_t server_name_length); static int delete_server_record_in_cache(LEX_SERVER_OPTIONS *server_options); /* update functions */ @@ -301,7 +301,7 @@ get_server_from_table_to_cache(TABLE *table) /* get each field into the server struct ptr */ server->server_name= get_field(&mem, table->field[0]); - server->server_name_length= strlen(server->server_name); + server->server_name_length= (uint) strlen(server->server_name); ptr= get_field(&mem, table->field[1]); server->host= ptr ? ptr : blank; ptr= get_field(&mem, table->field[2]); @@ -911,7 +911,7 @@ end: static int delete_server_record(TABLE *table, - char *server_name, int server_name_length) + char *server_name, size_t server_name_length) { int error; DBUG_ENTER("delete_server_record"); @@ -1271,7 +1271,7 @@ static FOREIGN_SERVER *clone_server(MEM_ROOT *mem, const FOREIGN_SERVER *server, FOREIGN_SERVER *get_server_by_name(MEM_ROOT *mem, const char *server_name, FOREIGN_SERVER *buff) { - uint server_name_length; + size_t server_name_length; FOREIGN_SERVER *server; DBUG_ENTER("get_server_by_name"); DBUG_PRINT("info", ("server_name %s", server_name)); @@ -1290,8 +1290,8 @@ FOREIGN_SERVER *get_server_by_name(MEM_ROOT *mem, const char *server_name, (uchar*) server_name, server_name_length))) { - DBUG_PRINT("info", ("server_name %s length %d not found!", - server_name, server_name_length)); + DBUG_PRINT("info", ("server_name %s length %u not found!", + server_name, (unsigned) server_name_length)); server= (FOREIGN_SERVER *) NULL; } /* otherwise, make copy of server */ diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 8deb564e02b..3687dc0751d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1705,7 +1705,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) field_list.push_back(field=new Item_empty_string("db",NAME_CHAR_LEN)); field->maybe_null=1; field_list.push_back(new Item_empty_string("Command",16)); - field_list.push_back(new Item_return_int("Time",7, MYSQL_TYPE_LONG)); + field_list.push_back(field= new Item_return_int("Time",7, MYSQL_TYPE_LONG)); + field->unsigned_flag= 0; field_list.push_back(field=new Item_empty_string("State",30)); field->maybe_null=1; field_list.push_back(field=new Item_empty_string("Info",max_query_length)); @@ -1798,7 +1799,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) else protocol->store(command_name[thd_info->command].str, system_charset_info); if (thd_info->start_time) - protocol->store((uint32) (now - thd_info->start_time)); + protocol->store_long ((longlong) (now - thd_info->start_time)); else protocol->store_null(); protocol->store(thd_info->state_info, system_charset_info); @@ -1873,8 +1874,8 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) table->field[4]->store(command_name[tmp->command].str, command_name[tmp->command].length, cs); /* MYSQL_TIME */ - table->field[5]->store((uint32)(tmp->start_time ? - now - tmp->start_time : 0), TRUE); + table->field[5]->store((longlong)(tmp->start_time ? + now - tmp->start_time : 0), FALSE); /* STATE */ #ifndef EMBEDDED_LIBRARY val= (char*) (tmp->locked ? "Locked" : @@ -6551,7 +6552,7 @@ ST_FIELD_INFO processlist_fields_info[]= SKIP_OPEN_TABLE}, {"DB", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Db", SKIP_OPEN_TABLE}, {"COMMAND", 16, MYSQL_TYPE_STRING, 0, 0, "Command", SKIP_OPEN_TABLE}, - {"TIME", 7, MYSQL_TYPE_LONGLONG, 0, 0, "Time", SKIP_OPEN_TABLE}, + {"TIME", 7, MYSQL_TYPE_LONG, 0, 0, "Time", SKIP_OPEN_TABLE}, {"STATE", 64, MYSQL_TYPE_STRING, 0, 1, "State", SKIP_OPEN_TABLE}, {"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info", SKIP_OPEN_TABLE}, diff --git a/sql/sql_string.cc b/sql/sql_string.cc index f2c5b2750ef..f0324da328f 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -455,7 +455,7 @@ bool String::append(const char *s,uint32 arg_length) bool String::append(const char *s) { - return append(s, strlen(s)); + return append(s, (uint) strlen(s)); } @@ -1048,7 +1048,7 @@ outp: } } *from_end_pos= from; - res= to - to_start; + res= (uint) (to - to_start); } return (uint32) res; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 7b76d9d6c56..7cee3a20fef 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -84,7 +84,7 @@ static void wait_for_kill_signal(THD *thd) uint filename_to_tablename(const char *from, char *to, uint to_length) { uint errors; - uint res; + size_t res; DBUG_ENTER("filename_to_tablename"); DBUG_PRINT("enter", ("from '%s'", from)); @@ -224,7 +224,7 @@ uint build_table_filename(char *buff, size_t bufflen, const char *db, char *end = buff + bufflen; /* Don't add FN_ROOTDIR if mysql_data_home already includes it */ char *pos = strnmov(buff, mysql_data_home, bufflen); - int rootdir_len= strlen(FN_ROOTDIR); + size_t rootdir_len= strlen(FN_ROOTDIR); if (pos - rootdir_len >= buff && memcmp(pos - rootdir_len, FN_ROOTDIR, rootdir_len) != 0) pos= strnmov(pos, FN_ROOTDIR, end - pos); @@ -273,7 +273,7 @@ uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen) my_casedn_str(files_charset_info, p); } - uint length= unpack_filename(buff, buff); + size_t length= unpack_filename(buff, buff); DBUG_PRINT("exit", ("buff: '%s'", buff)); DBUG_RETURN(length); } @@ -1991,7 +1991,7 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval, for (pos= interval->type_names, len= interval->type_lengths; *pos ; pos++, len++) { - uint length= cs->cset->numchars(cs, *pos, *pos + *len); + size_t length= cs->cset->numchars(cs, *pos, *pos + *len); *tot_length+= length; set_if_bigger(*max_length, (uint32)length); } @@ -2320,7 +2320,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, DBUG_ASSERT(comma_length > 0); for (uint i= 0; (tmp= int_it++); i++) { - uint lengthsp; + size_t lengthsp; if (String::needs_conversion(tmp->length(), tmp->charset(), cs, &dummy)) { @@ -4245,7 +4245,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, (!(alter_info->flags & ALTER_ALL_PARTITION))) { char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE]; - uint length; + size_t length; DBUG_PRINT("admin", ("sending non existent partition error")); protocol->prepare_for_resend(); protocol->store(table_name, system_charset_info); @@ -4334,7 +4334,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, { /* purecov: begin inspected */ char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE]; - uint length; + size_t length; DBUG_PRINT("admin", ("sending error message")); protocol->prepare_for_resend(); protocol->store(table_name, system_charset_info); @@ -4452,7 +4452,7 @@ send_result_message: case HA_ADMIN_NOT_IMPLEMENTED: { char buf[MYSQL_ERRMSG_SIZE]; - uint length=my_snprintf(buf, sizeof(buf), + size_t length=my_snprintf(buf, sizeof(buf), ER(ER_CHECK_NOT_IMPLEMENTED), operator_name); protocol->store(STRING_WITH_LEN("note"), system_charset_info); protocol->store(buf, length, system_charset_info); @@ -4462,7 +4462,7 @@ send_result_message: case HA_ADMIN_NOT_BASE_TABLE: { char buf[MYSQL_ERRMSG_SIZE]; - uint length= my_snprintf(buf, sizeof(buf), + size_t length= my_snprintf(buf, sizeof(buf), ER(ER_BAD_TABLE_ERROR), table_name); protocol->store(STRING_WITH_LEN("note"), system_charset_info); protocol->store(buf, length, system_charset_info); @@ -4590,7 +4590,7 @@ send_result_message: case HA_ADMIN_NEEDS_ALTER: { char buf[MYSQL_ERRMSG_SIZE]; - uint length; + size_t length; protocol->store(STRING_WITH_LEN("error"), system_charset_info); length=my_snprintf(buf, sizeof(buf), ER(ER_TABLE_NEEDS_UPGRADE), @@ -4603,7 +4603,7 @@ send_result_message: default: // Probably HA_ADMIN_INTERNAL_ERROR { char buf[MYSQL_ERRMSG_SIZE]; - uint length=my_snprintf(buf, sizeof(buf), + size_t length=my_snprintf(buf, sizeof(buf), "Unknown - internal error %d during operation", result_code); protocol->store(STRING_WITH_LEN("error"), system_charset_info); diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index bad8db56f02..c055268ecca 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1728,7 +1728,7 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd, List_iterator_fast<LEX_STRING> it_def(definitions_list); List_iterator_fast<LEX_STRING> it_on_table_name(on_table_names_list); List_iterator_fast<ulonglong> it_mode(definition_modes_list); - uint on_q_table_name_len, before_on_len; + size_t on_q_table_name_len, before_on_len; String buff; DBUG_ASSERT(definitions_list.elements == on_table_names_list.elements && diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index ebd183c6803..c60dac42fb8 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -159,7 +159,7 @@ void udf_init() DBUG_PRINT("info",("init udf record")); LEX_STRING name; name.str=get_field(&mem, table->field[0]); - name.length = strlen(name.str); + name.length = (uint) strlen(name.str); char *dl_name= get_field(&mem, table->field[2]); bool new_dl=0; Item_udftype udftype=UDFTYPE_FUNCTION; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 58448f82d82..07ab7df0d92 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -61,7 +61,8 @@ static void make_unique_view_field_name(Item *target, char *name= (target->orig_name ? target->orig_name : target->name); - uint name_len, attempt; + size_t name_len; + uint attempt; char buff[NAME_LEN+1]; List_iterator_fast<Item> itc(item_list); @@ -545,7 +546,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, } while ((item= it++, name= nm++)) { - item->set_name(name->str, name->length, system_charset_info); + item->set_name(name->str, (uint) name->length, system_charset_info); item->is_autogenerated_name= FALSE; } } @@ -1681,7 +1682,7 @@ frm_type_enum mysql_frm_type(THD *thd, char *path, enum legacy_db_type *dbt) { File file; uchar header[10]; //"TYPE=VIEW\n" it is 10 characters - int error; + size_t error; DBUG_ENTER("mysql_frm_type"); *dbt= DB_TYPE_UNKNOWN; diff --git a/sql/strfunc.cc b/sql/strfunc.cc index d6f9784e4ad..5ff2efe2020 100644 --- a/sql/strfunc.cc +++ b/sql/strfunc.cc @@ -89,6 +89,208 @@ ulonglong find_set(TYPELIB *lib, const char *str, uint length, } +static const char *on_off_default_names[]= +{ + "off","on","default", NullS +}; + +static const unsigned int on_off_default_names_len[]= +{ + sizeof("off") - 1, + sizeof("on") - 1, + sizeof("default") - 1 +}; + +static TYPELIB on_off_default_typelib= {array_elements(on_off_default_names)-1, + "", on_off_default_names, + (unsigned int *)on_off_default_names_len}; + + +/* + Parse a TYPELIB name from the buffer + + SYNOPSIS + parse_name() + lib Set of names to scan for. + strpos INOUT Start of the buffer (updated to point to the next + character after the name) + end End of the buffer + cs Charset used in the buffer + + DESCRIPTION + Parse a TYPELIB name from the buffer. The buffer is assumed to contain + one of the names specified in the TYPELIB, followed by comma, '=', or + end of the buffer. + + RETURN + 0 No matching name + >0 Offset+1 in typelib for matched name +*/ + +static uint parse_name(TYPELIB *lib, const char **strpos, const char *end, + CHARSET_INFO *cs) +{ + const char *pos= *strpos; + const char *start= pos; + + /* Find the length */ + if (cs && cs->mbminlen > 1) + { + int mblen= 0; + for ( ; pos < end; pos+= mblen) + { + my_wc_t wc; + if ((mblen= cs->cset->mb_wc(cs, &wc, (const uchar *) pos, + (const uchar *) end)) < 1) + mblen= 1; // Not to hang on a wrong multibyte sequence + if (wc == (my_wc_t) '=' || wc == (my_wc_t) ',') + break; + } + } + else + for (; pos != end && *pos != '=' && *pos !=',' ; pos++); + + uint var_len= (uint) (pos - start); + /* Determine which flag it is */ + uint find= cs ? find_type2(lib, start, var_len, cs) : + find_type(lib, start, var_len, (bool) 0); + *strpos= pos; + return find; +} + + +/* Read next character from the buffer in a charset-aware way */ + +static my_wc_t get_next_char(const char **pos, const char *end, CHARSET_INFO *cs) +{ + my_wc_t wc; + if (*pos == end) + return (my_wc_t)-1; + + if (cs && cs->mbminlen > 1) + { + int mblen; + if ((mblen= cs->cset->mb_wc(cs, &wc, (const uchar *) *pos, + (const uchar *) end)) < 1) + mblen= 1; // Not to hang on a wrong multibyte sequence + *pos += mblen; + return wc; + } + else + return *((*pos)++); +} + + +/* + Parse and apply a set of flag assingments + + SYNOPSIS + find_set_from_flags() + lib Flag names + default_name Number of "default" in the typelib + cur_set Current set of flags (start from this state) + default_set Default set of flags (use this for assign-default + keyword and flag=default assignments) + str String to be parsed + length Length of the string + cs String charset + err_pos OUT If error, set to point to start of wrong set string + NULL on success + err_len OUT If error, set to the length of wrong set string + set_warning OUT TRUE <=> Some string in set couldn't be used + + DESCRIPTION + Parse a set of flag assignments, that is, parse a string in form: + + param_name1=value1,param_name2=value2,... + + where the names are specified in the TYPELIB, and each value can be + either 'on','off', or 'default'. Setting the same name twice is not + allowed. + + Besides param=val assignments, we support the "default" keyword (keyword + #default_name in the typelib). It can be used one time, if specified it + causes us to build the new set over the default_set rather than cur_set + value. + + RETURN + Parsed set value if (*errpos == NULL) + Otherwise undefined +*/ + +ulonglong find_set_from_flags(TYPELIB *lib, uint default_name, + ulonglong cur_set, ulonglong default_set, + const char *str, uint length, CHARSET_INFO *cs, + char **err_pos, uint *err_len, bool *set_warning) +{ + CHARSET_INFO *strip= cs ? cs : &my_charset_latin1; + const char *end= str + strip->cset->lengthsp(strip, str, length); + ulonglong flags_to_set= 0, flags_to_clear= 0; + bool set_defaults= 0; + *err_pos= 0; // No error yet + if (str != end) + { + const char *start= str; + for (;;) + { + const char *pos= start; + uint flag_no, value; + + if (!(flag_no= parse_name(lib, &pos, end, cs))) + goto err; + + if (flag_no == default_name) + { + /* Using 'default' twice isn't allowed. */ + if (set_defaults) + goto err; + set_defaults= TRUE; + } + else + { + ulonglong bit= ((longlong) 1 << (flag_no - 1)); + /* parse the '=on|off|default' */ + if ((flags_to_clear | flags_to_set) & bit || + get_next_char(&pos, end, cs) != '=' || + !(value= parse_name(&on_off_default_typelib, &pos, end, cs))) + { + goto err; + } + + if (value == 1) // this is '=off' + flags_to_clear|= bit; + else if (value == 2) // this is '=on' + flags_to_set|= bit; + else // this is '=default' + { + if (default_set & bit) + flags_to_set|= bit; + else + flags_to_clear|= bit; + } + } + if (pos >= end) + break; + + if (get_next_char(&pos, end, cs) != ',') + goto err; + + start=pos; + continue; + err: + *err_pos= (char*)start; + *err_len= end - start; + *set_warning= TRUE; + break; + } + } + ulonglong res= set_defaults? default_set : cur_set; + res|= flags_to_set; + res&= ~flags_to_clear; + return res; +} + + /* Function to find a string in a TYPELIB (Same format as mysys/typelib.c) diff --git a/sql/table.cc b/sql/table.cc index 7184f145339..787709e1f25 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1652,6 +1652,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, goto err; outparam->quick_keys.init(); outparam->covering_keys.init(); + outparam->merge_keys.init(); outparam->keys_in_use_for_query.init(); /* Allocate handler */ diff --git a/sql/tztime.cc b/sql/tztime.cc index 860a604b545..cd6e63be039 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1825,6 +1825,13 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) #ifdef ABBR_ARE_USED char chars[max(TZ_MAX_CHARS + 1, (2 * (MY_TZNAME_MAX + 1)))]; #endif + /* + Used as a temporary tz_info until we decide that we actually want to + allocate and keep the tz info and tz name in tz_storage. + */ + TIME_ZONE_INFO tmp_tz_info; + memset(&tmp_tz_info, 0, sizeof(TIME_ZONE_INFO)); + DBUG_ENTER("tz_load_from_open_tables"); /* Prepare tz_info for loading also let us make copy of time zone name */ @@ -1866,7 +1873,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) Most probably user has mistyped time zone name, so no need to bark here unless we need it for debugging. */ - sql_print_error("Can't find description of time zone '%s'", tz_name_buff); + sql_print_error("Can't find description of time zone '%.*s'", + tz_name->length(), tz_name->ptr()); #endif goto end; } @@ -1895,8 +1903,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) /* If Uses_leap_seconds == 'Y' */ if (table->field[1]->val_int() == 1) { - tz_info->leapcnt= tz_leapcnt; - tz_info->lsis= tz_lsis; + tmp_tz_info.leapcnt= tz_leapcnt; + tmp_tz_info.lsis= tz_lsis; } (void)table->file->ha_index_end(); @@ -1932,18 +1940,18 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) #ifdef ABBR_ARE_USED // FIXME should we do something with duplicates here ? table->field[4]->val_str(&abbr, &abbr); - if (tz_info->charcnt + abbr.length() + 1 > sizeof(chars)) + if (tmp_tz_info.charcnt + abbr.length() + 1 > sizeof(chars)) { sql_print_error("Error while loading time zone description from " "mysql.time_zone_transition_type table: not enough " "room for abbreviations"); goto end; } - ttis[ttid].tt_abbrind= tz_info->charcnt; - memcpy(chars + tz_info->charcnt, abbr.ptr(), abbr.length()); - tz_info->charcnt+= abbr.length(); - chars[tz_info->charcnt]= 0; - tz_info->charcnt++; + ttis[ttid].tt_abbrind= tmp_tz_info.charcnt; + memcpy(chars + tmp_tz_info.charcnt, abbr.ptr(), abbr.length()); + tmp_tz_info.charcnt+= abbr.length(); + chars[tmp_tz_info.charcnt]= 0; + tmp_tz_info.charcnt++; DBUG_PRINT("info", ("time_zone_transition_type table: tz_id=%u tt_id=%u tt_gmtoff=%ld " @@ -1956,9 +1964,9 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) #endif /* ttid is increasing because we are reading using index */ - DBUG_ASSERT(ttid >= tz_info->typecnt); + DBUG_ASSERT(ttid >= tmp_tz_info.typecnt); - tz_info->typecnt= ttid + 1; + tmp_tz_info.typecnt= ttid + 1; res= table->file->index_next_same(table->record[0], table->field[0]->ptr, 4); @@ -1990,14 +1998,14 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) ttime= (my_time_t)table->field[1]->val_int(); ttid= (uint)table->field[2]->val_int(); - if (tz_info->timecnt + 1 > TZ_MAX_TIMES) + if (tmp_tz_info.timecnt + 1 > TZ_MAX_TIMES) { sql_print_error("Error while loading time zone description from " "mysql.time_zone_transition table: " "too much transitions"); goto end; } - if (ttid + 1 > tz_info->typecnt) + if (ttid + 1 > tmp_tz_info.typecnt) { sql_print_error("Error while loading time zone description from " "mysql.time_zone_transition table: " @@ -2005,9 +2013,9 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) goto end; } - ats[tz_info->timecnt]= ttime; - types[tz_info->timecnt]= ttid; - tz_info->timecnt++; + ats[tmp_tz_info.timecnt]= ttime; + types[tmp_tz_info.timecnt]= ttid; + tmp_tz_info.timecnt++; DBUG_PRINT("info", ("time_zone_transition table: tz_id: %u tt_time: %lu tt_id: %u", @@ -2032,6 +2040,34 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) table= 0; /* + Let us check how correct our time zone description is. We don't check for + tz->timecnt < 1 since it is ok for GMT. + */ + if (tmp_tz_info.typecnt < 1) + { + sql_print_error("loading time zone without transition types"); + goto end; + } + + /* Allocate memory for the timezone info and timezone name in tz_storage. */ + if (!(alloc_buff= (char*) alloc_root(&tz_storage, sizeof(TIME_ZONE_INFO) + + tz_name->length() + 1))) + { + sql_print_error("Out of memory while loading time zone description"); + return 0; + } + + /* Move the temporary tz_info into the allocated area */ + tz_info= (TIME_ZONE_INFO *)alloc_buff; + memcpy(tz_info, &tmp_tz_info, sizeof(TIME_ZONE_INFO)); + tz_name_buff= alloc_buff + sizeof(TIME_ZONE_INFO); + /* + By writing zero to the end we guarantee that we can call ptr() + instead of c_ptr() for time zone name. + */ + strmake(tz_name_buff, tz_name->ptr(), tz_name->length()); + + /* Now we will allocate memory and init TIME_ZONE_INFO structure. */ if (!(alloc_buff= (char*) alloc_root(&tz_storage, @@ -2062,15 +2098,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) tz_info->ttis= (TRAN_TYPE_INFO *)alloc_buff; memcpy(tz_info->ttis, ttis, tz_info->typecnt * sizeof(TRAN_TYPE_INFO)); - /* - Let us check how correct our time zone description and build - reversed map. We don't check for tz->timecnt < 1 since it ok for GMT. - */ - if (tz_info->typecnt < 1) - { - sql_print_error("loading time zone without transition types"); - goto end; - } + /* Build reversed map. */ if (prepare_tz_info(tz_info, &tz_storage)) { sql_print_error("Unable to build mktime map for time zone"); diff --git a/sql/udf_example.c b/sql/udf_example.c index a3d149f0971..30d85d95034 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -1099,7 +1099,7 @@ char * is_const(UDF_INIT *initid, UDF_ARGS *args __attribute__((unused)), sprintf(result, "not const"); } *is_null= 0; - *length= strlen(result); + *length= (uint) strlen(result); return result; } @@ -1133,7 +1133,7 @@ char * check_const_len(UDF_INIT *initid, UDF_ARGS *args __attribute__((unused)), char *is_null, char *error __attribute__((unused))) { strmov(result, initid->ptr); - *length= strlen(result); + *length= (uint) strlen(result); *is_null= 0; return result; } diff --git a/sql/uniques.cc b/sql/uniques.cc index c2f16f2e05b..3d1ea9243b9 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -130,7 +130,7 @@ static double get_merge_buffers_cost(uint *buff_elems, uint elem_size, total_buf_elems+= *pbuf; *last= total_buf_elems; - int n_buffers= last - first + 1; + size_t n_buffers= last - first + 1; /* Using log2(n)=log(n)/log(2) formula */ return 2*((double)total_buf_elems*elem_size) / IO_SIZE + |