diff options
author | Chad MILLER <chad@mysql.com> | 2009-04-14 13:20:13 -0400 |
---|---|---|
committer | Chad MILLER <chad@mysql.com> | 2009-04-14 13:20:13 -0400 |
commit | 14f923c0286588f9f391a2fda8b9fab5a4e2953c (patch) | |
tree | 55596b47965261462217616f8271d0c2b9d79ab0 /sql | |
parent | 9d7f61dc698ee6b1dd379cc5820c59b8a9806c2d (diff) | |
parent | bd2db28cdad7e715b9efcee2f440f432a0562e8f (diff) | |
download | mariadb-git-14f923c0286588f9f391a2fda8b9fab5a4e2953c.tar.gz |
Merge 5.0.80 release and 5.0 community. Version left at 5.0.80.
Diffstat (limited to 'sql')
63 files changed, 1148 insertions, 675 deletions
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index 2d78999017a..ef671ac7f9d 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -199,7 +199,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); } } @@ -511,7 +511,7 @@ static inline 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\ @@ -540,7 +540,7 @@ static inline 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/ha_archive.cc b/sql/ha_archive.cc index 82c81e83e54..410606704d8 100644 --- a/sql/ha_archive.cc +++ b/sql/ha_archive.cc @@ -851,7 +851,7 @@ int ha_archive::get_row(gzFile file_to_read, byte *buf) total_blob_length += ((Field_blob*) table->field[*ptr])->get_length(); /* Adjust our row buffer if we need be */ - buffer.alloc(total_blob_length); + buffer.alloc((uint) total_blob_length); last= (char *)buffer.ptr(); /* Loop through our blobs and read them */ @@ -862,10 +862,10 @@ int ha_archive::get_row(gzFile file_to_read, byte *buf) size_t size= ((Field_blob*) table->field[*ptr])->get_length(); if (size) { - read= gzread(file_to_read, last, size); + read= gzread(file_to_read, last, (uint) size); if ((size_t) read != size) DBUG_RETURN(HA_ERR_END_OF_FILE); - ((Field_blob*) table->field[*ptr])->set_ptr(size, last); + ((Field_blob*) table->field[*ptr])->set_ptr((uint) size, last); last += size; } } diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index d4144a41a2a..6944dc5a030 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -640,7 +640,7 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, share->database[share->table_name - share->database]= '\0'; share->table_name++; - share->table_name_length= strlen(share->table_name); + share->table_name_length= (uint) strlen(share->table_name); /* make sure there's not an extra / */ if ((strchr(share->table_name, '/'))) @@ -726,7 +726,7 @@ uint ha_federated::convert_row_to_internal_format(byte *record, index variable to move us through the row at the same iterative step as the field */ - int x= field - table->field; + size_t x= (field - table->field); my_ptrdiff_t old_ptr; old_ptr= (my_ptrdiff_t) (record - table->record[0]); (*field)->move_field(old_ptr); @@ -750,7 +750,7 @@ static bool emit_key_part_name(String *to, KEY_PART_INFO *part) { DBUG_ENTER("emit_key_part_name"); if (append_ident(to, part->field->field_name, - strlen(part->field->field_name), ident_quote_char)) + (uint) strlen(part->field->field_name), ident_quote_char)) DBUG_RETURN(1); // Out of memory DBUG_RETURN(0); } @@ -1290,13 +1290,13 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) for (field= table->field; *field; field++) { append_ident(&query, (*field)->field_name, - strlen((*field)->field_name), ident_quote_char); + (uint) strlen((*field)->field_name), ident_quote_char); query.append(FEDERATED_COMMA); } - query.length(query.length()- strlen(FEDERATED_COMMA)); + query.length(query.length() - (uint) strlen(FEDERATED_COMMA)); query.append(FEDERATED_FROM); - tmp_share.table_name_length= strlen(tmp_share.table_name); + tmp_share.table_name_length= (uint) strlen(tmp_share.table_name); append_ident(&query, tmp_share.table_name, tmp_share.table_name_length, ident_quote_char); @@ -1528,7 +1528,7 @@ bool ha_federated::append_stmt_insert(String *query) append_ident(&insert_string, share->table_name, share->table_name_length, ident_quote_char); insert_string.append(FEDERATED_OPENPAREN); - tmp_length= insert_string.length() - strlen(FEDERATED_COMMA); + tmp_length= insert_string.length() - (uint) strlen(FEDERATED_COMMA); /* loop through the field pointer array, add any fields to both the values @@ -1538,7 +1538,7 @@ bool ha_federated::append_stmt_insert(String *query) { /* append the field name */ append_ident(&insert_string, (*field)->field_name, - strlen((*field)->field_name), ident_quote_char); + (uint) strlen((*field)->field_name), ident_quote_char); /* append commas between both fields and fieldnames */ /* @@ -1554,7 +1554,7 @@ bool ha_federated::append_stmt_insert(String *query) /* remove trailing comma */ - insert_string.length(insert_string.length() - strlen(FEDERATED_COMMA)); + insert_string.length(insert_string.length() - (uint) strlen(FEDERATED_COMMA)); /* if there were no fields, we don't want to add a closing paren @@ -1667,7 +1667,7 @@ int ha_federated::write_row(byte *buf) if (values_string.length() > tmp_length) { /* chops off leading commas */ - values_string.length(values_string.length() - strlen(FEDERATED_COMMA)); + values_string.length(values_string.length() - (uint) strlen(FEDERATED_COMMA)); } /* we always want to append this, even if there aren't any fields */ values_string.append(FEDERATED_CLOSEPAREN); @@ -1950,10 +1950,10 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) for (Field **field= table->field; *field; field++) { - uint field_name_length= strlen((*field)->field_name); - append_ident(&where_string, (*field)->field_name, field_name_length, + size_t field_name_length= strlen((*field)->field_name); + append_ident(&where_string, (*field)->field_name, (uint) field_name_length, ident_quote_char); - append_ident(&update_string, (*field)->field_name, field_name_length, + append_ident(&update_string, (*field)->field_name, (uint) field_name_length, ident_quote_char); update_string.append(FEDERATED_EQ); @@ -2044,7 +2044,7 @@ int ha_federated::delete_row(const byte *buf) Field *cur_field= *field; data_string.length(0); append_ident(&delete_string, (*field)->field_name, - strlen((*field)->field_name), ident_quote_char); + (uint) strlen((*field)->field_name), ident_quote_char); if (cur_field->is_null()) { @@ -2359,7 +2359,7 @@ int ha_federated::rnd_init(bool scan) stored_result= 0; } - if (real_query(share->select_query, strlen(share->select_query))) + if (real_query(share->select_query, (uint) strlen(share->select_query))) goto error; stored_result= mysql_store_result(mysql); diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 83e2d025f18..f71e891e88d 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -524,6 +524,20 @@ convert_error_code_to_mysql( mark_transaction_to_rollback(thd, TRUE); return(HA_ERR_LOCK_TABLE_FULL); + } else if (error == DB_TOO_MANY_CONCURRENT_TRXS) { + + /* Once MySQL add the appropriate code to errmsg.txt then + we can get rid of this #ifdef. NOTE: The code checked by + the #ifdef is the suggested name for the error condition + and the actual error code name could very well be different. + This will require some monitoring, ie. the status + of this request on our part.*/ +#ifdef ER_TOO_MANY_CONCURRENT_TRXS + return(ER_TOO_MANY_CONCURRENT_TRXS); +#else + return(HA_ERR_RECORD_FILE_FULL); +#endif + } else if (error == DB_UNSUPPORTED) { return(HA_ERR_UNSUPPORTED); @@ -3731,7 +3745,6 @@ convert_search_mode_to_innobase( case HA_READ_MBR_WITHIN: case HA_READ_MBR_DISJOINT: case HA_READ_MBR_EQUAL: - my_error(ER_TABLE_CANT_HANDLE_SPKEYS, MYF(0)); return(PAGE_CUR_UNSUPP); /* do not use "default:" in order to produce a gcc warning: enumeration value '...' not handled in switch @@ -5212,7 +5225,7 @@ ha_innobase::records_in_range( mode2); } else { - n_rows = 0; + n_rows = HA_POS_ERROR; } dtuple_free_for_mysql(heap1); @@ -7012,7 +7025,7 @@ ha_innobase::get_error_message(int error, String *buf) { trx_t* trx = check_trx_exists(current_thd); - buf->copy(trx->detailed_error, strlen(trx->detailed_error), + buf->copy(trx->detailed_error, (uint) strlen(trx->detailed_error), system_charset_info); return FALSE; diff --git a/sql/handler.cc b/sql/handler.cc index 71d184ad84b..d069d56caae 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -188,7 +188,8 @@ retest: { if (!my_strnncoll(&my_charset_latin1, (const uchar *)name, namelen, - (const uchar *)(*types)->name, strlen((*types)->name))) + (const uchar *)(*types)->name, + (uint) strlen((*types)->name))) return (enum db_type) (*types)->db_type; } @@ -200,10 +201,10 @@ retest: if (!my_strnncoll(&my_charset_latin1, (const uchar *)name, namelen, (const uchar *)table_alias->alias, - strlen(table_alias->alias))) + (uint) strlen(table_alias->alias))) { name= table_alias->type; - namelen= strlen(name); + namelen= (uint) strlen(name); goto retest; } } diff --git a/sql/item.cc b/sql/item.cc index 2a89c86cd88..6ae52d8be59 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -321,7 +321,7 @@ int Item::save_time_in_field(Field *field) { MYSQL_TIME ltime; if (get_time(<ime)) - return set_field_to_null(field); + return set_field_to_null_with_conversions(field, 0); field->set_notnull(); return field->store_time(<ime, MYSQL_TIMESTAMP_TIME); } @@ -331,7 +331,7 @@ int Item::save_date_in_field(Field *field) { MYSQL_TIME ltime; if (get_date(<ime, TIME_FUZZY_DATE)) - return set_field_to_null(field); + return set_field_to_null_with_conversions(field, 0); field->set_notnull(); return field->store_time(<ime, MYSQL_TIMESTAMP_DATETIME); } @@ -1243,13 +1243,26 @@ Item::Type Item_name_const::type() const valid_args guarantees value_item->basic_const_item(); if type is FUNC_ITEM, then we have a fudged item_func_neg() on our hands and return the underlying type. + For Item_func_set_collation() + e.g. NAME_CONST('name', 'value' COLLATE collation) we return its + 'value' argument type. */ - return valid_args ? - (((value_item->type() == FUNC_ITEM) && - (((Item_func *) value_item)->functype() == Item_func::NEG_FUNC)) ? - ((Item_func *) value_item)->key_item()->type() : - value_item->type()) : - NULL_ITEM; + if (!valid_args) + return NULL_ITEM; + Item::Type value_type= value_item->type(); + if (value_type == FUNC_ITEM) + { + /* + The second argument of NAME_CONST('name', 'value') must be + a simple constant item or a NEG_FUNC/COLLATE_FUNC. + */ + DBUG_ASSERT(((Item_func *) value_item)->functype() == + Item_func::NEG_FUNC || + ((Item_func *) value_item)->functype() == + Item_func::COLLATE_FUNC); + return ((Item_func *) value_item)->key_item()->type(); + } + return value_type; } @@ -1485,7 +1498,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; } } @@ -1568,15 +1582,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) { @@ -1595,42 +1625,11 @@ bool agg_item_collations_for_comparison(DTCollation &c, const char *fname, } -/* - Collect arguments' character sets together. - We allow to apply automatic character set conversion in some cases. - The conditions when conversion is possible are: - - arguments A and B have different charsets - - A wins according to coercibility rules - (i.e. a column is stronger than a string constant, - an explicit COLLATE clause is stronger than a column) - - character set of A is either superset for character set of B, - or B is a string constant which can be converted into the - character set of A without data loss. - - If all of the above is true, then it's possible to convert - B into the character set of A, and then compare according - to the collation of A. - - For functions with more than two arguments: - collect(A,B,C) ::= collect(collect(A,B),C) - - Since this function calls THD::change_item_tree() on the passed Item ** - pointers, it is necessary to pass the original Item **'s, not copies. - Otherwise their values will not be properly restored (see BUG#20769). - If the items are not consecutive (eg. args[2] and args[5]), use the - item_sep argument, ie. - - agg_item_charsets(coll, fname, &args[2], 2, flags, 3) - -*/ - -bool agg_item_charsets(DTCollation &coll, const char *fname, - Item **args, uint nargs, uint flags, int item_sep) +bool agg_item_set_converter(DTCollation &coll, const char *fname, + Item **args, uint nargs, uint flags, int item_sep) { Item **arg, *safe_args[2]; - if (agg_item_collations(coll, fname, args, nargs, flags, item_sep)) - return TRUE; /* For better error reporting: save the first and the second argument. @@ -1711,6 +1710,46 @@ bool agg_item_charsets(DTCollation &coll, const char *fname, } +/* + Collect arguments' character sets together. + We allow to apply automatic character set conversion in some cases. + The conditions when conversion is possible are: + - arguments A and B have different charsets + - A wins according to coercibility rules + (i.e. a column is stronger than a string constant, + an explicit COLLATE clause is stronger than a column) + - character set of A is either superset for character set of B, + or B is a string constant which can be converted into the + character set of A without data loss. + + If all of the above is true, then it's possible to convert + B into the character set of A, and then compare according + to the collation of A. + + For functions with more than two arguments: + + collect(A,B,C) ::= collect(collect(A,B),C) + + Since this function calls THD::change_item_tree() on the passed Item ** + pointers, it is necessary to pass the original Item **'s, not copies. + Otherwise their values will not be properly restored (see BUG#20769). + If the items are not consecutive (eg. args[2] and args[5]), use the + item_sep argument, ie. + + agg_item_charsets(coll, fname, &args[2], 2, flags, 3) + +*/ + +bool agg_item_charsets(DTCollation &coll, const char *fname, + Item **args, uint nargs, uint flags, int item_sep) +{ + if (agg_item_collations(coll, fname, args, nargs, flags, item_sep)) + return TRUE; + + return agg_item_set_converter(coll, fname, args, nargs, flags, item_sep); +} + + void Item_ident_for_show::make_field(Send_field *tmp_field) { tmp_field->table_name= tmp_field->org_table_name= table_name; @@ -2041,6 +2080,12 @@ bool Item_field::val_bool_result() } +bool Item_field::is_null_result() +{ + return (null_value=result_field->is_null()); +} + + bool Item_field::eq(const Item *item, bool binary_cmp) const { Item *real_item= ((Item *) item)->real_item(); @@ -2991,7 +3036,7 @@ bool Item_param::convert_str_value(THD *thd) str_value.set_charset(value.cs_info.final_character_set_of_str_value); /* Here str_value is guaranteed to be in final_character_set_of_str_value */ - max_length= str_value.length(); + max_length= str_value.numchars() * str_value.charset()->mbmaxlen; decimals= 0; /* str_value_ptr is returned from val_str(). It must be not alloced @@ -5629,6 +5674,15 @@ double Item_ref::val_result() } +bool Item_ref::is_null_result() +{ + if (result_field) + return (null_value=result_field->is_null()); + + return is_null(); +} + + longlong Item_ref::val_int_result() { if (result_field) @@ -5734,7 +5788,9 @@ String *Item_ref::val_str(String* tmp) bool Item_ref::is_null() { DBUG_ASSERT(fixed); - return (*ref)->is_null(); + bool tmp=(*ref)->is_null_result(); + null_value=(*ref)->null_value; + return tmp; } @@ -6251,7 +6307,7 @@ bool Item_trigger_field::fix_fields(THD *thd, Item **items) if (check_grant_column(thd, table_grants, triggers->trigger_table->s->db, triggers->trigger_table->s->table_name, field_name, - strlen(field_name), thd->security_ctx)) + (uint) strlen(field_name), thd->security_ctx)) return TRUE; } #endif // NO_EMBEDDED_ACCESS_CHECKS diff --git a/sql/item.h b/sql/item.h index 250bb3f67ef..852b0fcc1ba 100644 --- a/sql/item.h +++ b/sql/item.h @@ -652,6 +652,7 @@ public: virtual my_decimal *val_decimal_result(my_decimal *val) { return val_decimal(val); } virtual bool val_bool_result() { return val_bool(); } + virtual bool is_null_result() { return is_null(); } /* bit map of tables used by item */ virtual table_map used_tables() const { return (table_map) 0L; } @@ -1168,6 +1169,8 @@ bool agg_item_collations(DTCollation &c, const char *name, Item **items, uint nitems, uint flags, int item_sep); bool agg_item_collations_for_comparison(DTCollation &c, const char *name, Item **items, uint nitems, uint flags); +bool agg_item_set_converter(DTCollation &coll, const char *fname, + Item **args, uint nargs, uint flags, int item_sep); bool agg_item_charsets(DTCollation &c, const char *name, Item **items, uint nitems, uint flags, int item_sep); @@ -1301,6 +1304,7 @@ public: String *str_result(String* tmp); my_decimal *val_decimal_result(my_decimal *); bool val_bool_result(); + bool is_null_result(); bool send(Protocol *protocol, String *str_arg); void reset_field(Field *f); bool fix_fields(THD *, Item **); @@ -1942,6 +1946,7 @@ public: String *str_result(String* tmp); my_decimal *val_decimal_result(my_decimal *); bool val_bool_result(); + bool is_null_result(); bool send(Protocol *prot, String *tmp); void make_field(Send_field *field); bool fix_fields(THD *, Item **); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 3b1d18b4252..01d3e9bed52 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -490,7 +490,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols()); return 1; } - comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i)); + if (comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i))) + return 1; } break; } @@ -835,6 +836,16 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, get_value_func= &get_time_value; return 0; } + else if (type == STRING_RESULT && + (*a)->result_type() == STRING_RESULT && + (*b)->result_type() == STRING_RESULT) + { + DTCollation coll; + coll.set((*a)->collation.collation); + if (agg_item_set_converter(coll, owner_arg->func_name(), + b, 1, MY_COLL_CMP_CONV, 1)) + return 1; + } return set_compare_func(owner_arg, type); } diff --git a/sql/item_func.cc b/sql/item_func.cc index 394556140c4..17700d0d23d 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2758,7 +2758,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 @@ -4285,6 +4285,15 @@ my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val) } +bool Item_func_set_user_var::is_null_result() +{ + DBUG_ASSERT(fixed == 1); + check(TRUE); + update(); // Store expression + return is_null(); +} + + void Item_func_set_user_var::print(String *str) { str->append(STRING_WITH_LEN("(@")); @@ -4783,7 +4792,7 @@ Item_func_get_system_var(sys_var *var_arg, enum_var_type var_type_arg, :var(var_arg), var_type(var_type_arg), component(*component_arg) { /* 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); } @@ -4952,7 +4961,10 @@ bool Item_func_match::fix_fields(THD *thd, Item **ref) if (item->type() == Item::REF_ITEM) args[i]= item= *((Item_ref *)item)->ref; if (item->type() != Item::FIELD_ITEM) - key=NO_SUCH_KEY; + { + my_error(ER_WRONG_ARGUMENTS, MYF(0), "AGAINST"); + return TRUE; + } } /* Check that all columns come from the same table. diff --git a/sql/item_func.h b/sql/item_func.h index 89c841abb75..7e15a536cf2 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1302,6 +1302,7 @@ public: longlong val_int_result(); String *str_result(String *str); my_decimal *val_decimal_result(my_decimal *); + bool is_null_result(); bool update_hash(void *ptr, uint length, enum Item_result type, CHARSET_INFO *cs, Derivation dv, bool unsigned_arg); bool send(Protocol *protocol, String *str_arg); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index d1e3f45bba1..7edc1a62307 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -101,13 +101,10 @@ String *Item_func_md5::val_str(String *str) str->set_charset(&my_charset_bin); if (sptr) { - my_MD5_CTX context; unsigned char digest[16]; null_value=0; - my_MD5Init (&context); - my_MD5Update (&context,(unsigned char *) sptr->ptr(), sptr->length()); - my_MD5Final (digest, &context); + MY_MD5_HASH(digest,(unsigned char *) sptr->ptr(), sptr->length()); if (str->alloc(32)) // Ensure that memory is free { null_value=1; @@ -1696,6 +1693,12 @@ Item *Item_func_sysconst::safe_charset_converter(CHARSET_INFO *tocs) Item_string *conv; uint conv_errors; String tmp, cstr, *ostr= val_str(&tmp); + if (null_value) + { + Item *null_item= new Item_null((char *) fully_qualified_func_name()); + null_item->collation.set (tocs); + return null_item; + } cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors); if (conv_errors || !(conv= new Item_static_string_func(fully_qualified_func_name(), @@ -1737,17 +1740,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; @@ -2427,7 +2430,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: @@ -2695,7 +2698,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; } @@ -2707,7 +2710,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_strfunc.h b/sql/item_strfunc.h index 23ac20a4017..9794a092648 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -362,7 +362,7 @@ public: Item_func_encode(Item *a, char *seed_arg): Item_str_func(a), sql_crypt(seed_arg) { - seed.copy(seed_arg, strlen(seed_arg), default_charset_info); + seed.copy(seed_arg, (uint) strlen(seed_arg), default_charset_info); } String *val_str(String *); void fix_length_and_dec(); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index d33d92a5238..57045f52825 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -440,7 +440,8 @@ void Item_sum::make_field(Send_field *tmp_field) void Item_sum::print(String *str) { - Item **pargs= orig_args; + /* orig_args is not filled with valid values until fix_fields() */ + Item **pargs= fixed ? orig_args : args; str->append(func_name()); for (uint i=0 ; i < arg_count ; i++) { diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 38d9d62bd99..22ca8a925db 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -384,7 +384,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; @@ -635,14 +635,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': @@ -651,7 +651,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': @@ -660,13 +660,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")); @@ -689,62 +689,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': @@ -763,7 +763,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': @@ -781,11 +781,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; @@ -795,12 +795,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; @@ -815,7 +815,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; @@ -824,7 +824,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; @@ -875,7 +875,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]; } @@ -1063,7 +1063,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; } @@ -1207,7 +1207,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; } @@ -3222,14 +3222,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/item_timefunc.h b/sql/item_timefunc.h index 161a77f60b4..2c99d6044af 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -398,6 +398,7 @@ public: { return save_time_in_field(field); } + longlong val_int() { return val_int_from_decimal(); } bool result_as_longlong() { return TRUE; } }; diff --git a/sql/lock.cc b/sql/lock.cc index 4927146d96b..3102497576f 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -347,7 +347,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++; @@ -740,7 +740,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((gptr) sql_lock,MYF(0)); DBUG_RETURN(0); diff --git a/sql/log.cc b/sql/log.cc index c411f7c8238..d979dd101e0 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -487,7 +487,7 @@ const char *MYSQL_LOG::generate_name(const char *log_name, { if (!log_name || !log_name[0]) { - strmake(buff, pidfile_name, FN_REFLEN - strlen(suffix) - 1); + strmake(buff, pidfile_name, (uint) (FN_REFLEN - strlen(suffix) - 1)); return (const char *) fn_format(buff, buff, "", suffix, MYF(MY_REPLACE_EXT|MY_REPLACE_DIR)); @@ -728,7 +728,7 @@ bool MYSQL_LOG::open(const char *log_name, file. As every time we write to the index file, we sync it. */ if (my_b_write(&index_file, (byte*) log_file_name, - strlen(log_file_name)) || + (uint) strlen(log_file_name)) || my_b_write(&index_file, (byte*) "\n", 1) || flush_io_cache(&index_file) || my_sync(index_file.file, MYF(MY_WME))) diff --git a/sql/log_event.cc b/sql/log_event.cc index a15a3b3f665..ac29bd8ea63 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -268,7 +268,7 @@ append_query_string(CHARSET_INFO *csinfo, from->ptr(), from->length()); *ptr++='\''; } - to->length(orig_len + ptr - beg); + to->length((uint) (orig_len + ptr - beg)); return 0; } #endif @@ -556,7 +556,7 @@ int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos) protocol->store(log_name, &my_charset_bin); protocol->store((ulonglong) pos); event_type = get_type_str(); - protocol->store(event_type, strlen(event_type), &my_charset_bin); + protocol->store(event_type, (uint) strlen(event_type), &my_charset_bin); protocol->store((uint32) server_id); protocol->store((ulonglong) log_pos); pack_info(protocol); @@ -976,7 +976,7 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info) fputc('#', file); print_timestamp(file); - fprintf(file, " server id %d end_log_pos %s ", server_id, + fprintf(file, " server id %lu end_log_pos %s ", (ulong) server_id, llstr(log_pos,llbuff)); /* mysqlbinlog --hexdump */ @@ -1106,7 +1106,7 @@ void Query_log_event::pack_info(Protocol *protocol) memcpy(pos, query, q_len); pos+= q_len; } - protocol->store(buf, pos-buf, &my_charset_bin); + protocol->store(buf, (uint) (pos - buf), &my_charset_bin); my_free(buf, MYF(MY_ALLOW_ZERO_PTR)); } #endif @@ -1117,6 +1117,11 @@ void Query_log_event::pack_info(Protocol *protocol) static void write_str_with_code_and_len(char **dst, const char *src, int len, uint code) { + /* + only 1 byte to store the length of catalog, so it should not + surpass 255 + */ + DBUG_ASSERT(len <= 255); DBUG_ASSERT(src); *((*dst)++)= code; *((*dst)++)= (uchar) len; @@ -1136,16 +1141,8 @@ static void write_str_with_code_and_len(char **dst, const char *src, bool Query_log_event::write(IO_CACHE* file) { - uchar buf[QUERY_HEADER_LEN+ - 1+4+ // code of flags2 and flags2 - 1+8+ // code of sql_mode and sql_mode - 1+1+FN_REFLEN+ // code of catalog and catalog length and catalog - 1+4+ // code of autoinc and the 2 autoinc variables - 1+6+ // code of charset and charset - 1+1+MAX_TIME_ZONE_NAME_LENGTH+ // code of tz and tz length and tz name - 1+2+ // code of lc_time_names and lc_time_names_number - 1+2 // code of charset_database and charset_database_number - ], *start, *start_of_status; + uchar buf[QUERY_HEADER_LEN + MAX_SIZE_LOG_EVENT_STATUS]; + uchar *start, *start_of_status; ulong event_length; if (!query) @@ -1251,10 +1248,8 @@ bool Query_log_event::write(IO_CACHE* file) { /* In the TZ sys table, column Name is of length 64 so this should be ok */ DBUG_ASSERT(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH); - *start++= Q_TIME_ZONE_CODE; - *start++= time_zone_len; - memcpy(start, time_zone_str, time_zone_len); - start+= time_zone_len; + write_str_with_code_and_len((char **)(&start), + time_zone_str, time_zone_len, Q_TIME_ZONE_CODE); } if (lc_time_names_number) { @@ -1270,7 +1265,17 @@ bool Query_log_event::write(IO_CACHE* file) int2store(start, charset_database_number); start+= 2; } + if (table_map_for_update) + { + *start++= Q_TABLE_MAP_FOR_UPDATE_CODE; + int8store(start, table_map_for_update); + start+= 8; + } /* + NOTE: When adding new status vars, please don't forget to update + the MAX_SIZE_LOG_EVENT_STATUS in log_event.h and update function + code_name in this file. + Here there could be code like if (command-line-option-which-says-"log_this_variable" && inited) { @@ -1348,7 +1353,8 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, auto_increment_increment(thd_arg->variables.auto_increment_increment), auto_increment_offset(thd_arg->variables.auto_increment_offset), lc_time_names_number(thd_arg->variables.lc_time_names->number), - charset_database_number(0) + charset_database_number(0), + table_map_for_update((ulonglong)thd_arg->table_map_for_update) { time_t end_time; @@ -1437,7 +1443,7 @@ get_str_len_and_pointer(const Log_event::Byte **src, if (length > 0) { if (*src + length >= end) - return *src + length - end + 1; // Number of bytes missing + return (int) (*src + length - end + 1); // Number of bytes missing *dst= (char *)*src + 1; // Will be copied later } *len= length; @@ -1471,6 +1477,7 @@ code_name(int code) case Q_CATALOG_NZ_CODE: return "Q_CATALOG_NZ_CODE"; case Q_LC_TIME_NAMES_CODE: return "Q_LC_TIME_NAMES_CODE"; case Q_CHARSET_DATABASE_CODE: return "Q_CHARSET_DATABASE_CODE"; + case Q_TABLE_MAP_FOR_UPDATE_CODE: return "Q_TABLE_MAP_FOR_UPDATE_CODE"; } sprintf(buf, "CODE#%d", code); return buf; @@ -1507,7 +1514,8 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, db(NullS), catalog_len(0), status_vars_len(0), flags2_inited(0), sql_mode_inited(0), charset_inited(0), auto_increment_increment(1), auto_increment_offset(1), - time_zone_len(0), lc_time_names_number(0), charset_database_number(0) + time_zone_len(0), lc_time_names_number(0), charset_database_number(0), + table_map_for_update(0) { ulong data_len; uint32 tmp; @@ -1649,6 +1657,11 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, charset_database_number= uint2korr(pos); pos+= 2; break; + case Q_TABLE_MAP_FOR_UPDATE_CODE: + CHECK_SPACE(pos, end, 8); + table_map_for_update= uint8korr(pos); + pos+= 8; + break; default: /* That's why you must write status vars in growing order of code */ DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\ @@ -1908,7 +1921,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, Thank you. */ thd->catalog= catalog_len ? (char *) catalog : (char *)""; - thd->set_db(new_db, strlen(new_db)); /* allocates a copy of 'db' */ + thd->set_db(new_db, (uint) strlen(new_db)); /* allocates a copy of 'db' */ thd->variables.auto_increment_increment= auto_increment_increment; thd->variables.auto_increment_offset= auto_increment_offset; @@ -2036,6 +2049,8 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, else thd->variables.collation_database= thd->db_charset; + thd->table_map_for_update= (table_map)table_map_for_update; + /* Execute the query (note that we bypass dispatch_command()) */ const char* found_semicolon= NULL; mysql_parse(thd, thd->query, thd->query_length, &found_semicolon); @@ -2771,7 +2786,7 @@ void Load_log_event::pack_info(Protocol *protocol) if (!(buf= my_malloc(get_query_buffer_length(), MYF(MY_WME)))) return; print_query(TRUE, buf, &end, 0, 0); - protocol->store(buf, end-buf, &my_charset_bin); + protocol->store(buf, (uint) (end - buf), &my_charset_bin); my_free(buf, MYF(0)); } #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ @@ -2978,7 +2993,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); @@ -3144,7 +3159,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, bool use_rli_only_for_errors) { const char *new_db= rewrite_db(db); - thd->set_db(new_db, strlen(new_db)); + thd->set_db(new_db, (uint) strlen(new_db)); DBUG_ASSERT(thd->query == 0); thd->query_length= 0; // Should not be needed thd->query_error= 0; @@ -3237,7 +3252,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, print_query(FALSE, load_data_query, &end, (char **)&thd->lex->fname_start, (char **)&thd->lex->fname_end); *end= 0; - thd->query_length= end - load_data_query; + thd->query_length= (uint) (end - load_data_query); thd->query= load_data_query; if (sql_ex.opt_flags & REPLACE_FLAG) @@ -3857,7 +3872,7 @@ void User_var_log_event::pack_info(Protocol* protocol) break; case INT_RESULT: buf= my_malloc(val_offset + 22, MYF(MY_WME)); - event_len= longlong10_to_str(uint8korr(val), buf + val_offset,-10)-buf; + event_len= (uint) (longlong10_to_str(uint8korr(val), buf + val_offset,-10) - buf); break; case DECIMAL_RESULT: { @@ -3883,7 +3898,7 @@ void User_var_log_event::pack_info(Protocol* protocol) char *p= strxmov(buf + val_offset, "_", cs->csname, " ", NullS); p= str_to_hex(p, val, val_len); p= strxmov(p, " COLLATE ", cs->name, NullS); - event_len= p-buf; + event_len= (uint) (p - buf); } break; case ROW_RESULT: @@ -4204,7 +4219,7 @@ void Slave_log_event::pack_info(Protocol *protocol) pos= strmov(pos, master_log); pos= strmov(pos, ",pos="); pos= longlong10_to_str(master_pos, pos, 10); - protocol->store(buf, pos-buf, &my_charset_bin); + protocol->store(buf, (uint) (pos - buf), &my_charset_bin); } #endif /* !MYSQL_CLIENT */ @@ -4222,8 +4237,8 @@ Slave_log_event::Slave_log_event(THD* thd_arg, // TODO: re-write this better without holding both locks at the same time pthread_mutex_lock(&mi->data_lock); pthread_mutex_lock(&rli->data_lock); - master_host_len = strlen(mi->host); - master_log_len = strlen(rli->group_master_log_name); + master_host_len= (uint) strlen(mi->host); + master_log_len= (uint) strlen(rli->group_master_log_name); // on OOM, just do not initialize the structure and print the error if ((mem_pool = (char*)my_malloc(get_data_size() + 1, MYF(MY_WME)))) @@ -4292,7 +4307,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) @@ -4300,7 +4315,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); } @@ -5222,7 +5237,7 @@ void Execute_load_query_log_event::pack_info(Protocol *protocol) } pos= strmov(pos, " ;file_id="); pos= int10_to_str((long) file_id, pos, 10); - protocol->store(buf, pos-buf, &my_charset_bin); + protocol->store(buf, (uint) (pos - buf), &my_charset_bin); my_free(buf, MYF(MY_ALLOW_ZERO_PTR)); } @@ -5265,7 +5280,7 @@ Execute_load_query_log_event::exec_event(struct st_relay_log_info* rli) p= strmake(p, STRING_WITH_LEN(" INTO")); p= strmake(p, query+fn_pos_end, q_len-fn_pos_end); - error= Query_log_event::exec_event(rli, buf, p-buf); + error= Query_log_event::exec_event(rli, buf, (uint) (p - buf)); /* Forging file name for deletion in same buffer */ *fname_end= 0; diff --git a/sql/log_event.h b/sql/log_event.h index 5b065a33dd1..6ccbf8e4d5c 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -204,12 +204,15 @@ struct sql_ex_info packet (i.e. a query) sent from client to master; First, an auxiliary log_event status vars estimation: */ -#define MAX_SIZE_LOG_EVENT_STATUS (4 /* flags2 */ + \ - 8 /* sql mode */ + \ - 1 + 1 + 255 /* catalog */ + \ - 4 /* autoinc */ + \ - 6 /* charset */ + \ - MAX_TIME_ZONE_NAME_LENGTH) +#define MAX_SIZE_LOG_EVENT_STATUS (1 + 4 /* type, flags2 */ + \ + 1 + 8 /* type, sql_mode */ + \ + 1 + 1 + 255 /* type, length, catalog */ + \ + 1 + 4 /* type, auto_increment */ + \ + 1 + 6 /* type, charset */ + \ + 1 + 1 + 255 /* type, length, time_zone */ + \ + 1 + 2 /* type, lc_time_names_number */ + \ + 1 + 2 /* type, charset_database_number */ + \ + 1 + 8 /* type, table_map_for_update */) #define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \ LOG_EVENT_HEADER_LEN + /* write_header */ \ QUERY_HEADER_LEN + /* write_data */ \ @@ -273,6 +276,8 @@ struct sql_ex_info #define Q_LC_TIME_NAMES_CODE 7 #define Q_CHARSET_DATABASE_CODE 8 + +#define Q_TABLE_MAP_FOR_UPDATE_CODE 9 /* Intvar event post-header */ #define I_TYPE_OFFSET 0 @@ -800,6 +805,11 @@ public: const char *time_zone_str; uint lc_time_names_number; /* 0 means en_US */ uint charset_database_number; + /* + map for tables that will be updated for a multi-table update query + statement, for other query statements, this will be zero. + */ + ulonglong table_map_for_update; #ifndef MYSQL_CLIENT diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index c21f7360cc6..2e15883aeb4 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -669,6 +669,8 @@ struct Query_cache_query_flags unsigned int client_long_flag:1; unsigned int client_protocol_41:1; unsigned int more_results_exists:1; + unsigned int in_trans:1; + unsigned int autocommit:1; unsigned int pkt_nr; uint character_set_client_num; uint character_set_results_num; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 2bd2e7320cf..877312a9129 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -186,39 +186,41 @@ int initgroups(const char *,unsigned int); #ifdef HAVE_FP_EXCEPT // Fix type conflict typedef fp_except fp_except_t; #endif +#endif /* __FreeBSD__ && HAVE_IEEEFP_H */ +#ifdef HAVE_SYS_FPU_H +/* for IRIX to use set_fpc_csr() */ +#include <sys/fpu.h> +#endif +inline void setup_fpu() +{ +#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) /* We can't handle floating point exceptions with threads, so disable this on freebsd + Don't fall for overflow, underflow,divide-by-zero or loss of precision */ - -inline void set_proper_floating_point_mode() -{ - /* Don't fall for overflow, underflow,divide-by-zero or loss of precision */ #if defined(__i386__) fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ | FP_X_IMP)); #else - fpsetmask(~(FP_X_INV | FP_X_OFL | FP_X_UFL | FP_X_DZ | - FP_X_IMP)); -#endif -} -#elif defined(__sgi) -/* for IRIX to use set_fpc_csr() */ -#include <sys/fpu.h> + fpsetmask(~(FP_X_INV | FP_X_OFL | FP_X_UFL | FP_X_DZ | + FP_X_IMP)); +#endif /* __i386__ */ +#endif /* __FreeBSD__ && HAVE_IEEEFP_H */ -inline void set_proper_floating_point_mode() -{ +#ifdef HAVE_FESETROUND + /* Set FPU rounding mode to "round-to-nearest" */ + fesetround(FE_TONEAREST); +#endif /* HAVE_FESETROUND */ + +#if defined(__sgi) && defined(HAVE_SYS_FPU_H) /* Enable denormalized DOUBLE values support for IRIX */ - { - union fpc_csr n; - n.fc_word = get_fpc_csr(); - n.fc_struct.flush = 0; - set_fpc_csr(n.fc_word); - } + union fpc_csr n; + n.fc_word = get_fpc_csr(); + n.fc_struct.flush = 0; + set_fpc_csr(n.fc_word); +#endif } -#else -#define set_proper_floating_point_mode() -#endif /* __FreeBSD__ && HAVE_IEEEFP_H */ } /* cplusplus */ @@ -2813,7 +2815,7 @@ static bool init_global_datetime_format(timestamp_type format_type, */ opt_date_time_formats[format_type]= str; } - if (!(*var_ptr= date_time_format_make(format_type, str, strlen(str)))) + if (!(*var_ptr= date_time_format_make(format_type, str, (uint) strlen(str)))) { fprintf(stderr, "Wrong date/time format specifier: %s\n", str); return 1; @@ -3039,7 +3041,7 @@ static int init_common_variables(const char *conf_file_name, int argc, sys_init_slave.value_length= 0; if ((sys_init_slave.value= opt_init_slave)) - sys_init_slave.value_length= strlen(opt_init_slave); + sys_init_slave.value_length= (uint) strlen(opt_init_slave); else sys_init_slave.value=my_strdup("",MYF(0)); sys_init_slave.is_os_charset= TRUE; @@ -3279,7 +3281,7 @@ static int init_server_components() query_cache_init(); query_cache_resize(query_cache_size); randominit(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2); - set_proper_floating_point_mode(); + setup_fpu(); init_thr_lock(); #ifdef HAVE_REPLICATION init_slave_list(); @@ -7342,7 +7344,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case OPT_STORAGE_ENGINE: { if ((enum db_type)((global_system_variables.table_type= - ha_resolve_by_name(argument, strlen(argument)))) == + ha_resolve_by_name(argument, (uint) strlen(argument)))) == DB_TYPE_UNKNOWN) { fprintf(stderr,"Unknown/unsupported table type: %s\n",argument); diff --git a/sql/net_serv.cc b/sql/net_serv.cc index a40764577fd..627a5fae5e3 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -253,7 +253,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); @@ -501,7 +501,7 @@ net_write_buff(NET *net,const char *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 ebebfafb5d8..c3a43776429 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -673,7 +673,7 @@ int SEL_IMERGE::or_sel_tree(PARAM *param, SEL_TREE *tree) if (trees_next == trees_end) { const int realloc_ratio= 2; /* Double size for next round */ - uint old_elements= (trees_end - trees); + uint old_elements= (uint) (trees_end - trees); uint old_size= sizeof(SEL_TREE**) * old_elements; uint new_size= old_size * realloc_ratio; SEL_TREE **new_trees; @@ -2398,7 +2398,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, { SEL_TREE **ptree; TRP_INDEX_MERGE *imerge_trp= NULL; - uint n_child_scans= imerge->trees_next - imerge->trees; + uint n_child_scans= (uint) (imerge->trees_next - imerge->trees); TRP_RANGE **range_scans; TRP_RANGE **cur_child; TRP_RANGE **cpk_scan= NULL; @@ -2997,7 +2997,7 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info, tuple_arg= tuple_arg->next_key_part; tuple_arg->store_min(key_part[tuple_arg->part].store_length, &key_ptr, 0); } - min_range.length= max_range.length= ((char*) key_ptr - (char*) key_val); + min_range.length= max_range.length= (uint) ((char*) key_ptr - (char*) key_val); records= (info->param->table->file-> records_in_range(scan->keynr, &min_range, &max_range)); if (cur_covered) @@ -3297,7 +3297,7 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, intersect_scans_best);); *are_all_covering= intersect->is_covering; - uint best_num= intersect_scans_best - intersect_scans; + uint best_num= (uint) (intersect_scans_best - intersect_scans); ror_intersect_cpy(intersect, intersect_best); /* @@ -3474,7 +3474,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, TRP_ROR_INTERSECT *trp; if (!(trp= new (param->mem_root) TRP_ROR_INTERSECT)) DBUG_RETURN(trp); - uint best_num= (ror_scan_mark - tree->ror_scans); + uint best_num= (uint) (ror_scan_mark - tree->ror_scans); if (!(trp->first_scan= (ROR_SCAN_INFO**)alloc_root(param->mem_root, sizeof(ROR_SCAN_INFO*)* best_num))) @@ -3594,7 +3594,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, "ROR scans");); if (key_to_read) { - idx= key_to_read - tree->keys; + idx= (uint) (key_to_read - tree->keys); if ((read_plan= new (param->mem_root) TRP_RANGE(*key_to_read, idx))) { read_plan->records= best_records; @@ -4755,7 +4755,7 @@ tree_and(PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2) tree1->type= SEL_TREE::IMPOSSIBLE; DBUG_RETURN(tree1); } - result_keys.set_bit(key1 - tree1->keys); + result_keys.set_bit((uint) (key1 - tree1->keys)); #ifdef EXTRA_DEBUG if (*key1 && param->alloced_sel_args < SEL_ARG::MAX_SEL_ARGS) (*key1)->test_use_count(*key1); @@ -4837,7 +4837,7 @@ tree_or(PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2) if (*key1) { result=tree1; // Added to tree1 - result_keys.set_bit(key1 - tree1->keys); + result_keys.set_bit((uint) (key1 - tree1->keys)); #ifdef EXTRA_DEBUG if (param->alloced_sel_args < SEL_ARG::MAX_SEL_ARGS) (*key1)->test_use_count(*key1); @@ -6956,8 +6956,8 @@ int QUICK_RANGE_SELECT::get_next() } } - uint count= min(multi_range_length, ranges.elements - - (cur_range - (QUICK_RANGE**) ranges.buffer)); + uint count= min(multi_range_length, (uint) (ranges.elements - + (cur_range - (QUICK_RANGE**) ranges.buffer))); if (count == 0) { /* Ranges have already been used up before. None is left for read. */ @@ -7047,7 +7047,7 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, byte *cur_prefix) DBUG_RETURN(result); } - uint count= ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer); + uint count= (uint) (ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer)); if (count == 0) { /* Ranges have already been used up before. None is left for read. */ @@ -7102,7 +7102,7 @@ int QUICK_RANGE_SELECT_GEOM::get_next() DBUG_RETURN(result); } - uint count= ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer); + uint count= (uint) (ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer)); if (count == 0) { /* Ranges have already been used up before. None is left for read. */ @@ -7435,18 +7435,18 @@ void QUICK_RANGE_SELECT::add_keys_and_lengths(String *key_names, String *used_lengths) { char buf[64]; - uint length; + size_t length; KEY *key_info= head->key_info + index; key_names->append(key_info->name); length= longlong2str(max_used_key_length, buf, 10) - buf; - used_lengths->append(buf, length); + used_lengths->append(buf, (uint) length); } void QUICK_INDEX_MERGE_SELECT::add_keys_and_lengths(String *key_names, String *used_lengths) { char buf[64]; - uint length; + size_t length; bool first= TRUE; QUICK_RANGE_SELECT *quick; @@ -7464,7 +7464,7 @@ void QUICK_INDEX_MERGE_SELECT::add_keys_and_lengths(String *key_names, KEY *key_info= head->key_info + quick->index; key_names->append(key_info->name); length= longlong2str(quick->max_used_key_length, buf, 10) - buf; - used_lengths->append(buf, length); + used_lengths->append(buf, (uint) length); } if (pk_quick_select) { @@ -7473,7 +7473,7 @@ void QUICK_INDEX_MERGE_SELECT::add_keys_and_lengths(String *key_names, key_names->append(key_info->name); length= longlong2str(pk_quick_select->max_used_key_length, buf, 10) - buf; used_lengths->append(','); - used_lengths->append(buf, length); + used_lengths->append(buf, (uint) length); } } @@ -7481,7 +7481,7 @@ void QUICK_ROR_INTERSECT_SELECT::add_keys_and_lengths(String *key_names, String *used_lengths) { char buf[64]; - uint length; + size_t length; bool first= TRUE; QUICK_RANGE_SELECT *quick; List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects); @@ -7497,7 +7497,7 @@ void QUICK_ROR_INTERSECT_SELECT::add_keys_and_lengths(String *key_names, } key_names->append(key_info->name); length= longlong2str(quick->max_used_key_length, buf, 10) - buf; - used_lengths->append(buf, length); + used_lengths->append(buf, (uint) length); } if (cpk_quick) @@ -7507,7 +7507,7 @@ void QUICK_ROR_INTERSECT_SELECT::add_keys_and_lengths(String *key_names, key_names->append(key_info->name); length= longlong2str(cpk_quick->max_used_key_length, buf, 10) - buf; used_lengths->append(','); - used_lengths->append(buf, length); + used_lengths->append(buf, (uint) length); } } @@ -7775,32 +7775,37 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) */ KEY *cur_index_info= table->key_info; KEY *cur_index_info_end= cur_index_info + table->s->keys; - KEY_PART_INFO *cur_part= NULL; - KEY_PART_INFO *end_part; /* Last part for loops. */ - /* Last index part. */ - KEY_PART_INFO *last_part= NULL; - KEY_PART_INFO *first_non_group_part= NULL; - KEY_PART_INFO *first_non_infix_part= NULL; - uint key_infix_parts= 0; - uint cur_group_key_parts= 0; - uint cur_group_prefix_len= 0; /* Cost-related variables for the best index so far. */ double best_read_cost= DBL_MAX; ha_rows best_records= 0; SEL_ARG *best_index_tree= NULL; ha_rows best_quick_prefix_records= 0; uint best_param_idx= 0; - double cur_read_cost= DBL_MAX; - ha_rows cur_records; + + const uint pk= param->table->s->primary_key; SEL_ARG *cur_index_tree= NULL; ha_rows cur_quick_prefix_records= 0; uint cur_param_idx=MAX_KEY; - key_map cur_used_key_parts; - uint pk= param->table->s->primary_key; for (uint cur_index= 0 ; cur_index_info != cur_index_info_end ; cur_index_info++, cur_index++) { + KEY_PART_INFO *cur_part; + KEY_PART_INFO *end_part; /* Last part for loops. */ + /* Last index part. */ + KEY_PART_INFO *last_part; + KEY_PART_INFO *first_non_group_part; + KEY_PART_INFO *first_non_infix_part; + uint key_infix_parts; + uint cur_group_key_parts= 0; + uint cur_group_prefix_len= 0; + double cur_read_cost; + ha_rows cur_records; + key_map used_key_parts_map; + uint cur_key_infix_len= 0; + byte cur_key_infix[MAX_KEY_LENGTH]; + uint cur_used_key_parts; + /* Check (B1) - if current index is covering. */ if (!table->used_keys.is_set(cur_index)) goto next_index; @@ -7879,7 +7884,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) else if (join->select_distinct) { select_items_it.rewind(); - cur_used_key_parts.clear_all(); + used_key_parts_map.clear_all(); uint max_key_part= 0; while ((item= select_items_it++)) { @@ -7890,13 +7895,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) Check if this attribute was already present in the select list. If it was present, then its corresponding key part was alredy used. */ - if (cur_used_key_parts.is_set(key_part_nr)) + if (used_key_parts_map.is_set(key_part_nr)) continue; if (key_part_nr < 1 || key_part_nr > join->fields_list.elements) goto next_index; cur_part= cur_index_info->key_part + key_part_nr - 1; cur_group_prefix_len+= cur_part->store_length; - cur_used_key_parts.set_bit(key_part_nr); + used_key_parts_map.set_bit(key_part_nr); ++cur_group_key_parts; max_key_part= max(max_key_part,key_part_nr); } @@ -7908,7 +7913,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) */ ulonglong all_parts, cur_parts; all_parts= (1<<max_key_part) - 1; - cur_parts= cur_used_key_parts.to_ulonglong() >> 1; + cur_parts= used_key_parts_map.to_ulonglong() >> 1; if (all_parts != cur_parts) goto next_index; } @@ -7958,7 +7963,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) &dummy); if (!get_constant_key_infix(cur_index_info, index_range_tree, first_non_group_part, min_max_arg_part, - last_part, thd, key_infix, &key_infix_len, + last_part, thd, cur_key_infix, + &cur_key_infix_len, &first_non_infix_part)) goto next_index; } @@ -8010,9 +8016,9 @@ 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= key_infix_len ? + key_infix_parts= cur_key_infix_len ? (uint) (first_non_infix_part - first_non_group_part) : 0; - used_key_parts= cur_group_key_parts + key_infix_parts; + cur_used_key_parts= cur_group_key_parts + key_infix_parts; /* Compute the cost of using this index. */ if (tree) @@ -8024,7 +8030,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) cur_quick_prefix_records= check_quick_select(param, cur_param_idx, cur_index_tree); } - cost_group_min_max(table, cur_index_info, used_key_parts, + cost_group_min_max(table, cur_index_info, cur_used_key_parts, cur_group_key_parts, tree, cur_index_tree, cur_quick_prefix_records, have_min, have_max, &cur_read_cost, &cur_records); @@ -8035,7 +8041,6 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) */ if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost)) { - DBUG_ASSERT(tree != 0 || cur_param_idx == MAX_KEY); index_info= cur_index_info; index= cur_index; best_read_cost= cur_read_cost; @@ -8045,11 +8050,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) best_param_idx= cur_param_idx; group_key_parts= cur_group_key_parts; group_prefix_len= cur_group_prefix_len; + key_infix_len= cur_key_infix_len; + if (key_infix_len) + memcpy (key_infix, cur_key_infix, sizeof (key_infix)); + used_key_parts= cur_used_key_parts; } - next_index: - cur_group_key_parts= 0; - cur_group_prefix_len= 0; + next_index:; } if (!index_info) /* No usable index found. */ DBUG_RETURN(NULL); @@ -8346,7 +8353,7 @@ get_field_keypart(KEY *index, Field *field) for (part= index->key_part, end= part + index->key_parts; part < end; part++) { if (field->eq(part->field)) - return part - index->key_part + 1; + return (uint) (part - index->key_part + 1); } return 0; } @@ -9601,7 +9608,7 @@ void QUICK_GROUP_MIN_MAX_SELECT::add_keys_and_lengths(String *key_names, char buf[64]; uint length; key_names->append(index_info->name); - length= longlong2str(max_used_key_length, buf, 10) - buf; + length= (uint) (longlong2str(max_used_key_length, buf, 10) - buf); used_lengths->append(buf, length); } diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 39db1344588..f8603f06fa0 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -636,12 +636,12 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, key_part_map org_key_part_used= *key_part_used; if (eq_type || between || max_fl == less_fl) { - uint length= (key_ptr-ref->key_buff)+part->store_length; + size_t length= (key_ptr-ref->key_buff)+part->store_length; if (ref->key_length < length) /* Ultimately ref->key_length will contain the length of the search key */ - ref->key_length= length; + ref->key_length= (uint) length; if (!*prefix_len && part+1 == field_part) - *prefix_len= length; + *prefix_len= (uint) length; if (is_field_part && eq_type) *prefix_len= ref->key_length; diff --git a/sql/parse_file.cc b/sql/parse_file.cc index ade0709cf0d..03e0d25b885 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -215,7 +215,7 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, dir->str, file_name->str, (ulong) base)); fn_format(path, file_name->str, dir->str, 0, MY_UNPACK_FILENAME); - path_end= strlen(path); + path_end= (uint) strlen(path); // temporary file name path[path_end]='~'; @@ -249,6 +249,11 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, if (end_io_cache(&file)) goto err_w_file; + if (opt_sync_frm) { + if (my_sync(handler, MYF(MY_WME))) + goto err_w_file; + } + if (my_close(handler, MYF(MY_WME))) { DBUG_RETURN(TRUE); @@ -406,7 +411,7 @@ sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root, sign++; if (*sign != '\n') goto frm_error; - parser->file_type.length= sign - parser->file_type.str; + parser->file_type.length= (uint) (sign - parser->file_type.str); // EOS for file signature just for safety *sign= '\0'; @@ -451,7 +456,7 @@ parse_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str) if (eol >= end) return 0; - str->length= eol - ptr; + str->length= (uint) (eol - ptr); if (!(str->str= alloc_root(mem_root, str->length+1))) return 0; @@ -516,7 +521,7 @@ read_escaped_string(char *ptr, char *eol, LEX_STRING *str) else *write_pos= c; } - str->str[str->length= write_pos-str->str]= '\0'; // just for safety + str->str[str->length= (uint) (write_pos - str->str)]= '\0'; // just for safety return FALSE; } @@ -543,7 +548,7 @@ parse_escaped_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str) char *eol= strchr(ptr, '\n'); if (eol == 0 || eol >= end || - !(str->str= alloc_root(mem_root, (eol - ptr) + 1)) || + !(str->str= alloc_root(mem_root, (uint) ((eol - ptr) + 1))) || read_escaped_string(ptr, eol, str)) return 0; diff --git a/sql/protocol.cc b/sql/protocol.cc index ff58d96f59b..728b9954f6a 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -306,7 +306,7 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message) pos+=2; } if (message) - pos=net_store_data((char*) pos, message, strlen(message)); + pos=net_store_data((char*) pos, message, (uint) strlen(message)); VOID(my_net_write(net,buff,(uint) (pos-buff))); VOID(net_flush(net)); /* We can't anymore send an error to the client */ @@ -616,7 +616,8 @@ bool Protocol::send_fields(List<Item> *list, uint flags) else { /* With conversion */ - uint max_char_len; + ulonglong max_length; + uint32 field_length; int2store(pos, thd_charset->number); /* For TEXT/BLOB columns, field_length describes the maximum data @@ -627,12 +628,22 @@ bool Protocol::send_fields(List<Item> *list, uint flags) char_count * mbmaxlen, where character count is taken from the definition of the column. In other words, the maximum number of characters here is limited by the column definition. + + When one has a LONG TEXT column with a single-byte + character set, and the connection character set is multi-byte, the + client may get fields longer than UINT_MAX32, due to + <character set column> -> <character set connection> conversion. + In that case column max length does not fit into the 4 bytes + reserved for it in the protocol. */ - max_char_len= (field.type >= (int) MYSQL_TYPE_TINY_BLOB && - field.type <= (int) MYSQL_TYPE_BLOB) ? - field.length / item->collation.collation->mbminlen : - field.length / item->collation.collation->mbmaxlen; - int4store(pos+2, max_char_len * thd_charset->mbmaxlen); + max_length= (field.type >= MYSQL_TYPE_TINY_BLOB && + field.type <= MYSQL_TYPE_BLOB) ? + field.length / item->collation.collation->mbminlen : + field.length / item->collation.collation->mbmaxlen; + max_length*= thd_charset->mbmaxlen; + field_length= (max_length > UINT_MAX32) ? + UINT_MAX32 : (uint32) max_length; + int4store(pos + 2, field_length); } pos[6]= field.type; int2store(pos+7,field.flags); @@ -724,8 +735,8 @@ bool Protocol::store(const char *from, CHARSET_INFO *cs) { if (!from) return store_null(); - uint length= strlen(from); - return store(from, length, cs); + size_t length= strlen(from); + return store(from, (uint) length, cs); } diff --git a/sql/set_var.cc b/sql/set_var.cc index 0d9e6b1263e..909496df045 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1941,7 +1941,7 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) pthread_mutex_lock(&LOCK_global_system_variables); char *str= (char*) value_ptr(thd, var_type, base); if (str) - tmp= new Item_string(str, strlen(str), + tmp= new Item_string(str, (uint) strlen(str), charset(thd), DERIVATION_SYSCONST); else { @@ -2093,7 +2093,7 @@ void sys_var_thd_date_time_format::set_default(THD *thd, enum_var_type type) { const char *format; if ((format= opt_date_time_formats[date_time_type])) - res= date_time_format_make(date_time_type, format, strlen(format)); + res= date_time_format_make(date_time_type, format, (uint) strlen(format)); } else { @@ -3180,10 +3180,10 @@ static byte *get_tmpdir(THD *thd) static struct my_option *find_option(struct my_option *opt, const char *name) { - uint length=strlen(name); + size_t length=strlen(name); for (; opt->name; opt++) { - if (!getopt_compare_strings(opt->name, name, length) && + if (!getopt_compare_strings(opt->name, name, (uint) length) && !opt->name[length]) { /* @@ -3224,7 +3224,7 @@ void set_var_init() var < end; var++) { - (*var)->name_length= strlen((*var)->name); + (*var)->name_length= (uint) strlen((*var)->name); (*var)->option_limits= find_option(my_long_options, (*var)->name); my_hash_insert(&system_variable_hash, (byte*) *var); } @@ -3263,7 +3263,7 @@ sys_var *find_sys_var(const char *str, uint length) sys_var *var= (sys_var*) hash_search(&system_variable_hash, (byte*) str, length ? length : - strlen(str)); + (uint) strlen(str)); if (!var) my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str); return var; @@ -3493,7 +3493,7 @@ int set_var_password::check(THD *thd) if (*thd->security_ctx->priv_host != 0) { user->host.str= (char *) thd->security_ctx->priv_host; - user->host.length= strlen(thd->security_ctx->priv_host); + user->host.length= (uint) strlen(thd->security_ctx->priv_host); } else { @@ -3509,7 +3509,7 @@ int set_var_password::check(THD *thd) } /* Returns 1 as the function sends error to client */ return check_change_password(thd, user->host.str, user->user.str, - password, strlen(password)) ? 1 : 0; + password, (uint) strlen(password)) ? 1 : 0; #else return 0; #endif diff --git a/sql/slave.cc b/sql/slave.cc index a50c74e4730..868b11e137f 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1003,7 +1003,7 @@ int db_ok_with_wild_table(const char *db) int len; end= strmov(hash_key, db); *end++= '.'; - len= end - hash_key ; + len= (uint) (end - hash_key); if (wild_do_table_inited && find_wild(&replicate_wild_do_table, hash_key, len)) return 1; @@ -1189,7 +1189,7 @@ void skip_load_data_infile(NET *net) bool net_request_file(NET* net, const char* fname) { DBUG_ENTER("net_request_file"); - DBUG_RETURN(net_write_command(net, 251, fname, strlen(fname), "", 0)); + DBUG_RETURN(net_write_command(net, 251, fname, (uint) strlen(fname), "", 0)); } @@ -1581,7 +1581,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, save_db = thd->db; save_db_length= thd->db_length; DBUG_ASSERT(db != 0); - thd->reset_db((char*)db, strlen(db)); + thd->reset_db((char*)db, (uint) strlen(db)); mysql_parse(thd, thd->query, packet_len, &found_semicolon); // run create table thd->db = save_db; // leave things the way the were before thd->db_length= save_db_length; @@ -2314,11 +2314,11 @@ int register_slave_on_master(MYSQL* mysql) if (!report_host) return 0; - report_host_len= strlen(report_host); + report_host_len= (uint) strlen(report_host); if (report_user) - report_user_len= strlen(report_user); + report_user_len= (uint) strlen(report_user); if (report_password) - report_password_len= strlen(report_password); + report_password_len= (uint) strlen(report_password); /* 30 is a good safety margin */ if (report_host_len + report_user_len + report_password_len + 30 > sizeof(buf)) @@ -3043,7 +3043,7 @@ static int request_table_dump(MYSQL* mysql, const char* db, const char* table) *p++ = table_len; memcpy(p, table, table_len); - if (simple_command(mysql, COM_TABLE_DUMP, buf, p - buf + table_len, 1)) + if (simple_command(mysql, COM_TABLE_DUMP, buf, (uint) (p - buf + table_len), 1)) { sql_print_error("request_table_dump: Error sending the table dump \ command"); diff --git a/sql/sp.cc b/sql/sp.cc index d2a12f2190f..3af51b82521 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -414,7 +414,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, thd->lex= &newlex; newlex.current_select= NULL; - parse_user(definer, strlen(definer), + parse_user(definer, (uint) strlen(definer), definer_user_name.str, &definer_user_name.length, definer_host_name.str, &definer_host_name.length); @@ -929,7 +929,7 @@ sp_drop_db_routines(THD *thd, char *db) if (!(table= open_proc_table_for_update(thd))) goto err; - table->field[MYSQL_PROC_FIELD_DB]->store(db, strlen(db), system_charset_info); + table->field[MYSQL_PROC_FIELD_DB]->store(db, (uint) strlen(db), system_charset_info); key_len= table->key_info->key_part[0].store_length; ret= SP_OK; @@ -1099,8 +1099,8 @@ sp_exist_routines(THD *thd, TABLE_LIST *routines, bool any, bool no_error) sp_name *name; LEX_STRING lex_db; LEX_STRING lex_name; - lex_db.length= strlen(routine->db); - lex_name.length= strlen(routine->table_name); + lex_db.length= (uint) strlen(routine->db); + lex_name.length= (uint) strlen(routine->table_name); lex_db.str= thd->strmake(routine->db, lex_db.length); lex_name.str= thd->strmake(routine->table_name, lex_name.length); name= new sp_name(lex_db, lex_name, true); @@ -1918,7 +1918,7 @@ sp_use_new_db(THD *thd, LEX_STRING new_db, LEX_STRING *old_db, if (thd->db) { - old_db->length= (strmake(old_db->str, thd->db, old_db->length - 1) - + old_db->length= (uint) (strmake(old_db->str, thd->db, old_db->length - 1) - old_db->str); } else diff --git a/sql/sp_head.cc b/sql/sp_head.cc index dd71a8512b4..f2b69ac09fd 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -381,7 +381,7 @@ sp_name::sp_name(THD *thd, char *key, uint key_len) m_qname.length= key_len - 1; if ((m_name.str= strchr(m_qname.str, '.'))) { - m_db.length= m_name.str - key; + m_db.length= (uint) (m_name.str - key); m_db.str= strmake_root(thd->mem_root, key, m_db.length); m_name.str++; m_name.length= m_qname.length - m_db.length - 1; @@ -447,7 +447,7 @@ sp_head::operator new(size_t size) throw() sp_head *sp; init_sql_alloc(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); - sp= (sp_head *) alloc_root(&own_root, size); + sp= (sp_head *) alloc_root(&own_root, (uint) size); if (sp == NULL) DBUG_RETURN(NULL); sp->main_mem_root= own_root; @@ -598,7 +598,7 @@ sp_head::init_strings(THD *thd, LEX *lex) if (m_param_begin && m_param_end) { - m_params.length= m_param_end - m_param_begin; + m_params.length= (uint) (m_param_end - m_param_begin); m_params.str= strmake_root(root, (char *)m_param_begin, m_params.length); } @@ -611,9 +611,9 @@ sp_head::init_strings(THD *thd, LEX *lex) */ endp= skip_rear_comments(thd->charset(), (char*) m_body_begin, (char*) endp); - m_body.length= endp - m_body_begin; + m_body.length= (uint) (endp - m_body_begin); m_body.str= strmake_root(root, m_body_begin, m_body.length); - m_defstr.length= endp - lip->buf; + m_defstr.length= (uint) (endp - lip->buf); m_defstr.str= strmake_root(root, lip->buf, m_defstr.length); DBUG_VOID_RETURN; } @@ -894,6 +894,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++) { @@ -927,6 +929,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) @@ -2650,6 +2654,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; } DBUG_RETURN(res); } @@ -3635,7 +3640,7 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) memcpy(tname+tlen, table->table_name, table->table_name_length); tlen+= table->table_name_length; tname[tlen++]= '\0'; - alen= strlen(table->alias); + alen= (uint) strlen(table->alias); memcpy(tname+tlen, table->alias, alen); tlen+= alen; tname[tlen]= '\0'; @@ -3800,9 +3805,9 @@ sp_add_to_query_tables(THD *thd, LEX *lex, thd->fatal_error(); return NULL; } - table->db_length= strlen(db); + table->db_length= (uint) strlen(db); table->db= thd->strmake(db, table->db_length); - table->table_name_length= strlen(name); + table->table_name_length= (uint) strlen(name); table->table_name= thd->strmake(name, table->table_name_length); table->alias= thd->strdup(name); table->lock_type= locktype; diff --git a/sql/spatial.cc b/sql/spatial.cc index 69d0c15748a..80506f16d0f 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -54,7 +54,7 @@ static Geometry::Class_info **ci_collection_end= Geometry::Class_info::Class_info(const char *name, int type_id, void(*create_func)(void *)): - m_name(name, strlen(name)), m_type_id(type_id), m_create_func(create_func) + m_name(name, (uint) strlen(name)), m_type_id(type_id), m_create_func(create_func) { ci_collection[type_id]= this; } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 22135d376fe..b2d0304f007 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -313,8 +313,8 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) } const char *password= get_field(thd->mem_root, table->field[2]); - uint password_len= password ? strlen(password) : 0; - set_user_salt(&user, password, password_len); + size_t password_len= password ? strlen(password) : 0; + set_user_salt(&user, password, (uint) password_len); if (user.salt_len == 0 && password_len != 0) { switch (password_len) { @@ -1405,7 +1405,7 @@ int check_change_password(THD *thd, const char *host, const char *user, MYF(0)); return(1); } - uint len=strlen(new_password); + size_t len= strlen(new_password); if (len && len != SCRAMBLED_PASSWORD_CHAR_LENGTH && len != SCRAMBLED_PASSWORD_CHAR_LENGTH_323) { @@ -1439,14 +1439,14 @@ bool change_password(THD *thd, const char *host, const char *user, /* Buffer should be extended when password length is extended. */ char buff[512]; ulong query_length; - uint new_password_len= strlen(new_password); + size_t new_password_len= strlen(new_password); bool result= 1; DBUG_ENTER("change_password"); DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'", host,user,new_password)); DBUG_ASSERT(host != 0); // Ensured by parent - if (check_change_password(thd, host, user, new_password, new_password_len)) + if (check_change_password(thd, host, user, new_password, (uint) new_password_len)) DBUG_RETURN(1); bzero((char*) &tables, sizeof(tables)); @@ -1483,12 +1483,12 @@ bool change_password(THD *thd, const char *host, const char *user, goto end; } /* update loaded acl entry: */ - set_user_salt(acl_user, new_password, new_password_len); + set_user_salt(acl_user, new_password, (uint) new_password_len); if (update_user_table(thd, table, acl_user->host.hostname ? acl_user->host.hostname : "", acl_user->user ? acl_user->user : "", - new_password, new_password_len)) + new_password, (uint) new_password_len)) { VOID(pthread_mutex_unlock(&acl_cache->lock)); /* purecov: deadcode */ goto end; @@ -1641,11 +1641,11 @@ bool hostname_requires_resolving(const char *hostname) char cur; if (!hostname) return FALSE; - int namelen= strlen(hostname); - int lhlen= strlen(my_localhost); + size_t namelen= strlen(hostname); + size_t lhlen= strlen(my_localhost); if ((namelen == lhlen) && - !my_strnncoll(system_charset_info, (const uchar *)hostname, namelen, - (const uchar *)my_localhost, strlen(my_localhost))) + !my_strnncoll(system_charset_info, (const uchar *)hostname, (uint) namelen, + (const uchar *)my_localhost, (uint) strlen(my_localhost))) return FALSE; for (; (cur=*hostname); hostname++) { @@ -1873,13 +1873,13 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, table->field[next_field+3]->store("", 0, &my_charset_latin1); if (lex->ssl_cipher) table->field[next_field+1]->store(lex->ssl_cipher, - strlen(lex->ssl_cipher), system_charset_info); + (uint) strlen(lex->ssl_cipher), system_charset_info); if (lex->x509_issuer) table->field[next_field+2]->store(lex->x509_issuer, - strlen(lex->x509_issuer), system_charset_info); + (uint) strlen(lex->x509_issuer), system_charset_info); if (lex->x509_subject) table->field[next_field+3]->store(lex->x509_subject, - strlen(lex->x509_subject), system_charset_info); + (uint) strlen(lex->x509_subject), system_charset_info); break; case SSL_TYPE_NOT_SPECIFIED: break; @@ -3866,6 +3866,11 @@ bool check_grant_all_columns(THD *thd, ulong want_access_arg, Security_context *sctx= thd->security_ctx; ulong want_access= want_access_arg; const char *table_name= NULL; + /* + Flag that gets set if privilege checking has to be performed on column + level. + */ + bool using_column_privileges= FALSE; if (grant_option) { @@ -3909,6 +3914,8 @@ bool check_grant_all_columns(THD *thd, ulong want_access_arg, GRANT_COLUMN *grant_column= column_hash_search(grant_table, field_name, (uint) strlen(field_name)); + if (grant_column) + using_column_privileges= TRUE; if (!grant_column || (~grant_column->rights & want_access)) goto err; } @@ -3924,12 +3931,21 @@ err: char command[128]; get_privilege_desc(command, sizeof(command), want_access); - my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), - command, - sctx->priv_user, - sctx->host_or_ip, - fields->name(), - table_name); + /* + Do not give an error message listing a column name unless the user has + privilege to see all columns. + */ + if (using_column_privileges) + my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), + command, sctx->priv_user, + sctx->host_or_ip, table_name); + else + my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), + command, + sctx->priv_user, + sctx->host_or_ip, + fields->name(), + table_name); return 1; } @@ -4186,10 +4202,10 @@ static void add_user_option(String *grant, ulong value, const char *name) { char buff[22], *p; // just as in int2str grant->append(' '); - grant->append(name, strlen(name)); + grant->append(name, (uint) strlen(name)); grant->append(' '); p=int10_to_str(value, buff, 10); - grant->append(buff,p-buff); + grant->append(buff,(uint) (p - buff)); } } @@ -4327,7 +4343,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) { ssl_options++; global.append(STRING_WITH_LEN("ISSUER \'")); - global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); + global.append(acl_user->x509_issuer,(uint) strlen(acl_user->x509_issuer)); global.append('\''); } if (acl_user->x509_subject) @@ -4335,7 +4351,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (ssl_options++) global.append(' '); global.append(STRING_WITH_LEN("SUBJECT \'")); - global.append(acl_user->x509_subject,strlen(acl_user->x509_subject), + global.append(acl_user->x509_subject,(uint) strlen(acl_user->x509_subject), system_charset_info); global.append('\''); } @@ -4344,7 +4360,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (ssl_options++) global.append(' '); global.append(STRING_WITH_LEN("CIPHER '")); - global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher), + global.append(acl_user->ssl_cipher,(uint) strlen(acl_user->ssl_cipher), system_charset_info); global.append('\''); } @@ -4424,13 +4440,13 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) } } db.append (STRING_WITH_LEN(" ON ")); - append_identifier(thd, &db, acl_db->db, strlen(acl_db->db)); + append_identifier(thd, &db, acl_db->db, (uint) strlen(acl_db->db)); db.append (STRING_WITH_LEN(".* TO '")); db.append(lex_user->user.str, lex_user->user.length, system_charset_info); db.append (STRING_WITH_LEN("'@'")); // host and lex_user->host are equal except for case - db.append(host, strlen(host), system_charset_info); + db.append(host, (uint) strlen(host), system_charset_info); db.append ('\''); if (want_access & GRANT_ACL) db.append(STRING_WITH_LEN(" WITH GRANT OPTION")); @@ -4536,16 +4552,16 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) } global.append(STRING_WITH_LEN(" ON ")); append_identifier(thd, &global, grant_table->db, - strlen(grant_table->db)); + (uint) strlen(grant_table->db)); global.append('.'); append_identifier(thd, &global, grant_table->tname, - strlen(grant_table->tname)); + (uint) strlen(grant_table->tname)); global.append(STRING_WITH_LEN(" TO '")); global.append(lex_user->user.str, lex_user->user.length, system_charset_info); global.append(STRING_WITH_LEN("'@'")); // host and lex_user->host are equal except for case - global.append(host, strlen(host), system_charset_info); + global.append(host, (uint) strlen(host), system_charset_info); global.append('\''); if (table_access & GRANT_ACL) global.append(STRING_WITH_LEN(" WITH GRANT OPTION")); @@ -4642,16 +4658,16 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash, global.append(type,typelen); global.append(' '); append_identifier(thd, &global, grant_proc->db, - strlen(grant_proc->db)); + (uint) strlen(grant_proc->db)); global.append('.'); append_identifier(thd, &global, grant_proc->tname, - strlen(grant_proc->tname)); + (uint) strlen(grant_proc->tname)); global.append(STRING_WITH_LEN(" TO '")); global.append(lex_user->user.str, lex_user->user.length, system_charset_info); global.append(STRING_WITH_LEN("'@'")); // host and lex_user->host are equal except for case - global.append(host, strlen(host), system_charset_info); + global.append(host, (uint) strlen(host), system_charset_info); global.append('\''); if (proc_access & GRANT_ACL) global.append(STRING_WITH_LEN(" WITH GRANT OPTION")); @@ -5769,11 +5785,11 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, { LEX_USER lex_user; lex_user.user.str= grant_proc->user; - lex_user.user.length= strlen(grant_proc->user); + lex_user.user.length= (uint) strlen(grant_proc->user); lex_user.host.str= grant_proc->host.hostname ? grant_proc->host.hostname : (char*)""; lex_user.host.length= grant_proc->host.hostname ? - strlen(grant_proc->host.hostname) : 0; + (uint) strlen(grant_proc->host.hostname) : 0; if (!replace_routine_table(thd,grant_proc,tables[4].table,lex_user, grant_proc->db, grant_proc->tname, is_proc, ~(ulong)0, 1)) @@ -5852,8 +5868,8 @@ int sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, tables->db= (char*)sp_db; tables->table_name= tables->alias= (char*)sp_name; - combo->host.length= strlen(combo->host.str); - combo->user.length= strlen(combo->user.str); + combo->host.length= (uint) strlen(combo->host.str); + combo->user.length= (uint) strlen(combo->user.str); combo->host.str= thd->strmake(combo->host.str,combo->host.length); combo->user.str= thd->strmake(combo->user.str,combo->user.length); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ef3d10c468f..575bc639398 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -780,10 +780,10 @@ void close_temporary_tables(THD *thd) We are going to add 4 ` around the db/table names and possible more due to special characters in the names */ - append_identifier(thd, &s_query, table->s->db, strlen(table->s->db)); + append_identifier(thd, &s_query, table->s->db, (uint) strlen(table->s->db)); s_query.q_append('.'); append_identifier(thd, &s_query, table->s->table_name, - strlen(table->s->table_name)); + (uint) strlen(table->s->table_name)); s_query.q_append(','); next= table->next; close_temporary(table, 1); @@ -3690,7 +3690,7 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, if (field_ptr && *field_ptr) { - *cached_field_index_ptr= field_ptr - table->field; + *cached_field_index_ptr= (uint) (field_ptr - table->field); field= *field_ptr; } else @@ -5479,7 +5479,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Ensure that we have access rights to all fields to be inserted. */ - if (!((table && (table->grant.privilege & SELECT_ACL) || + if (!((table && !tables->view && (table->grant.privilege & SELECT_ACL) || tables->view && (tables->grant.privilege & SELECT_ACL))) && !any_privileges) { @@ -5992,7 +5992,7 @@ my_bool mysql_rm_tmp_tables(void) if (!bcmp(file->name,tmp_file_prefix,tmp_file_prefix_length)) { char *ext= fn_ext(file->name); - uint ext_len= strlen(ext); + size_t ext_len= strlen(ext); uint filePath_len= my_snprintf(filePath, sizeof(filePath), "%s%s", tmpdir, file->name); if (!bcmp(reg_ext, ext, ext_len)) @@ -6264,7 +6264,7 @@ open_new_frm(THD *thd, const char *path, const char *alias, DBUG_ENTER("open_new_frm"); pathstr.str= (char*) path; - pathstr.length= strlen(path); + pathstr.length= (uint) strlen(path); if ((parser= sql_parse_prepare(&pathstr, mem_root, 1))) { diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 577255fbc4a..b618ded8079 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -363,6 +363,43 @@ TYPELIB query_cache_type_typelib= array_elements(query_cache_type_names)-1,"", query_cache_type_names, NULL }; + +/** + Helper function for determine if a SELECT statement has a SQL_NO_CACHE + directive. + + @param sql A pointer to the first white space character after SELECT + + @return + @retval TRUE The character string contains SQL_NO_CACHE + @retval FALSE No directive found. +*/ + +static bool has_no_cache_directive(char *sql) +{ + int i=0; + while (sql[i] == ' ') + ++i; + + if (my_toupper(system_charset_info, sql[i]) == 'S' && + my_toupper(system_charset_info, sql[i+1]) == 'Q' && + my_toupper(system_charset_info, sql[i+2]) == 'L' && + my_toupper(system_charset_info, sql[i+3]) == '_' && + my_toupper(system_charset_info, sql[i+4]) == 'N' && + my_toupper(system_charset_info, sql[i+5]) == 'O' && + my_toupper(system_charset_info, sql[i+6]) == '_' && + my_toupper(system_charset_info, sql[i+7]) == 'C' && + my_toupper(system_charset_info, sql[i+8]) == 'A' && + my_toupper(system_charset_info, sql[i+9]) == 'C' && + my_toupper(system_charset_info, sql[i+10]) == 'H' && + my_toupper(system_charset_info, sql[i+11]) == 'E' && + my_toupper(system_charset_info, sql[i+12]) == ' ') + return TRUE; + + return FALSE; +} + + /***************************************************************************** Query_cache_block_table method(s) *****************************************************************************/ @@ -712,7 +749,12 @@ void query_cache_end_of_result(THD *thd) if (thd->net.query_cache_query == 0) DBUG_VOID_RETURN; - if (thd->killed) + /* + Check if the NET layer raised a unreported error -- my_error() and + as a consequence query_cache_abort() haven't been called. Abort the + cached result as it might be only partially complete. + */ + if (thd->killed || thd->net.report_error) { query_cache_abort(&thd->net); DBUG_VOID_RETURN; @@ -862,6 +904,8 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) CLIENT_PROTOCOL_41); flags.more_results_exists= test(thd->server_status & SERVER_MORE_RESULTS_EXISTS); + flags.in_trans= test(thd->server_status & SERVER_STATUS_IN_TRANS); + flags.autocommit= test(thd->server_status & SERVER_STATUS_AUTOCOMMIT); flags.pkt_nr= net->pkt_nr; flags.character_set_client_num= thd->variables.character_set_client->number; @@ -882,7 +926,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \ CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \ sql mode: 0x%lx, sort len: %lu, conncat len: %lu, div_precision: %lu, \ -def_week_frmt: %lu", +def_week_frmt: %lu, in_trans: %d, autocommit: %d", (int)flags.client_long_flag, (int)flags.client_protocol_41, (int)flags.more_results_exists, @@ -896,7 +940,10 @@ def_week_frmt: %lu", flags.max_sort_length, flags.group_concat_max_len, flags.div_precision_increment, - flags.default_week_format)); + flags.default_week_format, + (int)flags.in_trans, + (int)flags.autocommit)); + /* Make InnoDB to release the adaptive hash index latch before acquiring the query cache mutex. @@ -1088,6 +1135,16 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached")); goto err; } + + if (query_length > 20 && has_no_cache_directive(&sql[i+6])) + { + /* + We do not increase 'refused' statistics here since it will be done + later when the query is parsed. + */ + DBUG_PRINT("qcache", ("The statement has a SQL_NO_CACHE directive")); + goto err; + } } #ifdef __WIN__ @@ -1149,6 +1206,8 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) CLIENT_PROTOCOL_41); flags.more_results_exists= test(thd->server_status & SERVER_MORE_RESULTS_EXISTS); + flags.in_trans= test(thd->server_status & SERVER_STATUS_IN_TRANS); + flags.autocommit= test(thd->server_status & SERVER_STATUS_AUTOCOMMIT); flags.pkt_nr= thd->net.pkt_nr; flags.character_set_client_num= thd->variables.character_set_client->number; flags.character_set_results_num= @@ -1167,7 +1226,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \ CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \ sql mode: 0x%lx, sort len: %lu, conncat len: %lu, div_precision: %lu, \ -def_week_frmt: %lu", +def_week_frmt: %lu, in_trans: %d, autocommit: %d", (int)flags.client_long_flag, (int)flags.client_protocol_41, (int)flags.more_results_exists, @@ -1181,7 +1240,9 @@ def_week_frmt: %lu", flags.max_sort_length, flags.group_concat_max_len, flags.div_precision_increment, - flags.default_week_format)); + flags.default_week_format, + (int)flags.in_trans, + (int)flags.autocommit)); memcpy((void *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)), &flags, QUERY_CACHE_FLAGS_SIZE); query_block = (Query_cache_block *) hash_search(&queries, (byte*) sql, @@ -3124,7 +3185,7 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used, { ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file; MYRG_INFO *file = handler->myrg_info(); - table_count+= (file->end_table - file->open_tables); + table_count+= (uint) (file->end_table - file->open_tables); } } } @@ -3311,7 +3372,7 @@ my_bool Query_cache::move_by_type(byte **border, *pprev = block->pprev, *pnext = block->pnext, *new_block =(Query_cache_block *) *border; - uint tablename_offset = block->table()->table() - block->table()->db(); + size_t tablename_offset= block->table()->table() - block->table()->db(); char *data = (char*) block->data(); byte *key; uint key_length; @@ -3623,7 +3684,7 @@ uint Query_cache::filename_2_table_key (char *key, const char *path, filename= tablename + dirname_length(tablename + 2) + 2; /* Find start of databasename */ for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ; - *db_length= (filename - dbname) - 1; + *db_length= (uint) ((filename - dbname) - 1); DBUG_PRINT("qcache", ("table '%-.*s.%s'", *db_length, dbname, filename)); DBUG_RETURN((uint) (strmov(strmake(key, dbname, *db_length) + 1, @@ -3932,8 +3993,8 @@ my_bool Query_cache::check_integrity(bool locked) } else { - int idx = (((byte*)bin) - ((byte*)bins)) / - sizeof(Query_cache_memory_bin); + int idx = (int) ((((byte*)bin) - ((byte*)bins)) / + sizeof(Query_cache_memory_bin)); if (in_list(bins[idx].free_blocks, block, "free memory")) result = 1; } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9a1c35c7d3d..8a0d84c6735 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -186,7 +186,9 @@ THD::THD() /* statement id */ 0), Open_tables_state(refresh_version), lock_id(&main_lock_id), - user_time(0), in_sub_stmt(0), global_read_lock(0), is_fatal_error(0), + user_time(0), in_sub_stmt(0), + table_map_for_update(0), + global_read_lock(0), is_fatal_error(0), transaction_rollback_request(0), is_fatal_sub_stmt_error(0), rand_used(0), time_zone_used(0), last_insert_id_used(0), last_insert_id_used_bin_log(0), insert_id_used(0), @@ -231,6 +233,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)); @@ -358,6 +361,12 @@ void THD::init(void) if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; options= thd_startup_options; + + if (variables.max_join_size == HA_POS_ERROR) + options |= OPTION_BIG_SELECTS; + else + options &= ~OPTION_BIG_SELECTS; + transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= FALSE; open_options=ha_open_options; update_lock_default= (variables.low_priority_updates ? @@ -408,6 +417,10 @@ void THD::init_for_queries() void THD::change_user(void) { + pthread_mutex_lock(&LOCK_status); + add_to_status(&global_status_var, &status_var); + pthread_mutex_unlock(&LOCK_status); + cleanup(); cleanup_done= 0; init(); @@ -664,6 +677,8 @@ void THD::cleanup_after_query() free_items(); /* Reset where. */ where= THD::DEFAULT_WHERE; + /* reset table map for multi-table update */ + table_map_for_update= 0; } @@ -1060,6 +1075,11 @@ bool select_send::send_data(List<Item> &items) my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); break; } + /* + Reset buffer to its original state, as it may have been altered in + Item::send(). + */ + buffer.set(buff, sizeof(buff), &my_charset_bin); } thd->sent_row_count++; if (!thd->vio_ok()) @@ -1756,7 +1776,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"); } /* @@ -2142,6 +2162,13 @@ void Security_context::skip_grants() } +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 4e8df6700c7..58f7d050d64 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -986,6 +986,7 @@ public: { return (*priv_host ? priv_host : (char *)"%"); } + bool user_matches(Security_context *); }; @@ -1362,6 +1363,13 @@ public: Note: in the parser, stmt_arena == thd, even for PS/SP. */ Query_arena *stmt_arena; + + /* + map for tables that will be updated for a multi-table update query + statement, for other query statements, this will be zero. + */ + table_map table_map_for_update; + /* next_insert_id is set on SET INSERT_ID= #. This is used as the next generated auto_increment value in handler.cc @@ -1557,6 +1565,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_crypt.cc b/sql/sql_crypt.cc index 367b9e38e56..38dfc869b3a 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_db.cc b/sql/sql_db.cc index c3cf7429222..80fea3ef1b1 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -239,7 +239,7 @@ void del_dbopt(const char *path) my_dbopt_t *opt; rw_wrlock(&LOCK_dboptions); if ((opt= (my_dbopt_t *)hash_search(&dboptions, (const byte*) path, - strlen(path)))) + (uint) strlen(path)))) hash_delete(&dboptions, (byte*) opt); rw_unlock(&LOCK_dboptions); } @@ -582,7 +582,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, # database does not exist. */ qinfo.db = db; - qinfo.db_len = strlen(db); + qinfo.db_len = (uint) strlen(db); /* These DDL methods and logging protected with LOCK_mysql_create_db */ mysql_bin_log.write(&qinfo); @@ -653,7 +653,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) default. */ qinfo.db = db; - qinfo.db_len = strlen(db); + qinfo.db_len = (uint) strlen(db); thd->clear_error(); /* These DDL methods and logging protected with LOCK_mysql_create_db */ @@ -777,7 +777,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) default. */ qinfo.db = db; - qinfo.db_len = strlen(db); + qinfo.db_len = (uint) strlen(db); thd->clear_error(); /* These DDL methods and logging protected with LOCK_mysql_create_db */ @@ -797,18 +797,18 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) goto exit; /* not much else we can do */ query_pos= query_data_start= strmov(query,"drop table "); query_end= query + MAX_DROP_TABLE_Q_LEN; - db_len= strlen(db); + db_len= (uint) strlen(db); for (tbl= dropped_tables; tbl; tbl= tbl->next_local) { uint tbl_name_len; /* 3 for the quotes and the comma*/ - tbl_name_len= strlen(tbl->table_name) + 3; + tbl_name_len= (uint) strlen(tbl->table_name) + 3; if (query_pos + tbl_name_len + 1 >= query_end) { /* These DDL methods and logging protected with LOCK_mysql_create_db */ - write_to_binlog(thd, query, query_pos -1 - query, db, db_len); + write_to_binlog(thd, query, (uint) (query_pos - 1 - query), db, db_len); query_pos= query_data_start; } @@ -821,7 +821,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) if (query_pos != query_data_start) { /* These DDL methods and logging protected with LOCK_mysql_create_db */ - write_to_binlog(thd, query, query_pos -1 - query, db, db_len); + write_to_binlog(thd, query, (uint) (query_pos - 1 - query), db, db_len); } } @@ -938,7 +938,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, /* Drop the table nicely */ *extension= 0; // Remove extension TABLE_LIST *table_list=(TABLE_LIST*) - thd->calloc(sizeof(*table_list)+ strlen(db)+strlen(file->name)+2); + thd->calloc((uint) (sizeof(*table_list)+ strlen(db)+strlen(file->name)+2)); if (!table_list) goto err; table_list->db= (char*) (table_list+1); diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 84622398f6f..830d1b7c36f 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -177,7 +177,7 @@ exit: orig_table_list->derived_result= derived_result; orig_table_list->table= table; orig_table_list->table_name= (char*) table->s->table_name; - orig_table_list->table_name_length= strlen((char*)table->s->table_name); + orig_table_list->table_name_length= (uint) strlen((char*)table->s->table_name); table->derived_select_number= first_select->select_number; table->s->tmp_table= NON_TRANSACTIONAL_TMP_TABLE; #ifndef NO_EMBEDDED_ACCESS_CHECKS diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 344a0c00db8..8f825f83df1 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -243,7 +243,7 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show) protocol->store(warning_level_names[err->level], warning_level_length[err->level], 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_handler.cc b/sql/sql_handler.cc index 822f2b2c419..c376f1b3d1d 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -90,7 +90,7 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags); static char *mysql_ha_hash_get_key(TABLE_LIST *tables, uint *key_len_p, my_bool first __attribute__((unused))) { - *key_len_p= strlen(tables->alias) + 1 ; /* include '\0' in comparisons */ + *key_len_p= (uint) strlen(tables->alias) + 1 ; /* include '\0' in comparisons */ return tables->alias; } @@ -151,6 +151,9 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables) } VOID(pthread_mutex_unlock(&LOCK_open)); } + + /* Mark table as closed, ready for re-open if necessary. */ + tables->table= NULL; } /* @@ -168,8 +171,7 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables) 'reopen' is set when a handler table is to be re-opened. In this case, 'tables' is the pointer to the hashed TABLE_LIST object which has been saved on the original open. - 'reopen' is also used to suppress the sending of an 'ok' message or - error messages. + 'reopen' is also used to suppress the sending of an 'ok' message. RETURN FALSE OK @@ -202,11 +204,10 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) else if (! reopen) /* Otherwise we have 'tables' already. */ { if (hash_search(&thd->handler_tables_hash, (byte*) tables->alias, - strlen(tables->alias) + 1)) + (uint) strlen(tables->alias) + 1)) { DBUG_PRINT("info",("duplicate '%s'", tables->alias)); - if (! reopen) - my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias); + my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias); goto err; } } @@ -251,17 +252,16 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) /* There can be only one table in '*tables'. */ if (! (tables->table->file->table_flags() & HA_CAN_SQL_HANDLER)) { - if (! reopen) - my_error(ER_ILLEGAL_HA, MYF(0), tables->alias); + my_error(ER_ILLEGAL_HA, MYF(0), tables->alias); goto err; } if (! reopen) { /* copy the TABLE_LIST struct */ - dblen= strlen(tables->db) + 1; - namelen= strlen(tables->table_name) + 1; - aliaslen= strlen(tables->alias) + 1; + dblen= (uint) strlen(tables->db) + 1; + namelen= (uint) strlen(tables->table_name) + 1; + aliaslen= (uint) strlen(tables->alias) + 1; if (!(my_multi_malloc(MYF(MY_WME), &hash_tables, sizeof(*hash_tables), &db, dblen, @@ -324,7 +324,7 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables) if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, (byte*) tables->alias, - strlen(tables->alias) + 1))) + (uint) strlen(tables->alias) + 1))) { mysql_ha_close_table(thd, hash_tables); hash_delete(&thd->handler_tables_hash, (byte*) hash_tables); @@ -396,7 +396,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, retry: if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, (byte*) tables->alias, - strlen(tables->alias) + 1))) + (uint) strlen(tables->alias) + 1))) { table= hash_tables->table; DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' tab %p", @@ -464,8 +464,7 @@ retry: if (need_reopen) { - mysql_ha_close_table(thd, tables); - hash_tables->table= NULL; + mysql_ha_close_table(thd, hash_tables); /* The lock might have been aborted, we need to manually reset thd->some_tables_deleted because handler's tables are closed @@ -779,7 +778,7 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags) if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, (byte*) table->alias, - strlen(table->alias) + 1))) + (uint) strlen(table->alias) + 1))) { if (! (mode_flags & MYSQL_HA_REOPEN_ON_USAGE)) { diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 6036a687274..e369a72fa9f 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -628,7 +628,7 @@ bool mysqld_help(THD *thd, const char *mask) List<String> topics_list, categories_list, subcategories_list; String name, description, example; int count_topics, count_categories, error; - uint mlen= strlen(mask); + size_t mlen= strlen(mask); size_t i; MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("mysqld_help"); @@ -668,7 +668,7 @@ bool mysqld_help(THD *thd, const char *mask) tables[i].table->file->init_table_handle_for_HANDLER(); if (!(select= - prepare_select_for_name(thd,mask,mlen,tables,tables[0].table, + prepare_select_for_name(thd,mask,(uint) mlen,tables,tables[0].table, used_fields[help_topic_name].field,&error))) goto error; @@ -681,7 +681,7 @@ bool mysqld_help(THD *thd, const char *mask) { int key_id; if (!(select= - prepare_select_for_name(thd,mask,mlen,tables,tables[3].table, + prepare_select_for_name(thd,mask,(uint) mlen,tables,tables[3].table, used_fields[help_keyword_name].field,&error))) goto error; @@ -698,7 +698,7 @@ bool mysqld_help(THD *thd, const char *mask) int16 category_id; Field *cat_cat_id= used_fields[help_category_parent_category_id].field; if (!(select= - prepare_select_for_name(thd,mask,mlen,tables,tables[1].table, + prepare_select_for_name(thd,mask,(uint) mlen,tables,tables[1].table, used_fields[help_category_name].field,&error))) goto error; @@ -759,7 +759,7 @@ bool mysqld_help(THD *thd, const char *mask) send_variant_2_list(mem_root,protocol, &topics_list, "N", 0)) goto error; if (!(select= - prepare_select_for_name(thd,mask,mlen,tables,tables[1].table, + prepare_select_for_name(thd,mask,(uint) mlen,tables,tables[1].table, used_fields[help_category_name].field,&error))) goto error; search_categories(thd, tables[1].table, used_fields, diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3cba300fbc7..9c8aa196908 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1609,10 +1609,13 @@ public: ulong auto_increment_increment; ulong auto_increment_offset; timestamp_auto_set_type timestamp_field_type; + Time_zone *time_zone; uint query_length; delayed_row(enum_duplicates dup_arg, bool ignore_arg, bool log_query_arg) - :record(0), query(0), dup(dup_arg), ignore(ignore_arg), log_query(log_query_arg) {} + :record(0), query(0), dup(dup_arg), ignore(ignore_arg), + log_query(log_query_arg), time_zone(0) + {} ~delayed_row() { x_free(record); @@ -1823,7 +1826,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) { @@ -2066,6 +2069,19 @@ int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic, bool ignore, row->last_insert_id= thd->last_insert_id; 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; + } /* The session variable settings can always be copied. */ row->auto_increment_increment= thd->variables.auto_increment_increment; row->auto_increment_offset= thd->variables.auto_increment_offset; @@ -2519,8 +2535,19 @@ bool Delayed_insert::handle_inserts(void) } if (row->query && row->log_query && using_bin_log) { + 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; + } + Query_log_event qinfo(&thd, row->query, row->query_length, 0, FALSE); mysql_bin_log.write(&qinfo); + + thd.time_zone_used = backup_time_zone_used; + thd.variables.time_zone = backup_time_zone; } if (table->s->blob_fields) free_delayed_insert_blobs(table); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index de2e5867955..d48dacf75d7 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -858,7 +858,7 @@ int MYSQLlex(void *arg, void *yythd) case MY_LEX_HEX_NUMBER: // Found x'hexstring' yyGet(); // Skip ' while (my_isxdigit(cs,(c = yyGet()))) ; - length=(lip->ptr - lip->tok_start); // Length of hexnum+3 + length=(uint) (lip->ptr - lip->tok_start); // Length of hexnum+3 if (!(length & 1) || c != '\'') { return(ABORT_SYM); // Illegal hex constant @@ -872,7 +872,7 @@ int MYSQLlex(void *arg, void *yythd) case MY_LEX_BIN_NUMBER: // Found b'bin-string' yyGet(); // Skip ' while ((c= yyGet()) == '0' || c == '1'); - length= (lip->ptr - lip->tok_start); // Length of bin-num + 3 + length= (uint) (lip->ptr - lip->tok_start); // Length of bin-num + 3 if (c != '\'') return(ABORT_SYM); // Illegal hex constant yyGet(); // get_token makes an unget diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 5477610bb05..5b9f8ea441d 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -526,8 +526,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 cb55be42339..a872585e704 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -250,7 +250,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; @@ -261,7 +261,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1; (void) pthread_mutex_lock(&LOCK_user_conn); if (!(uc = (struct user_conn *) hash_search(&hash_user_connections, - (byte*) temp_user, temp_len))) + (byte*) temp_user, (uint) temp_len))) { /* First connection for user; Create a user connection object */ if (!(uc= ((struct user_conn*) @@ -275,7 +275,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, uc->user=(char*) (uc+1); memcpy(uc->user,temp_user,temp_len+1); uc->host= uc->user + user_len + 1; - uc->len= temp_len; + uc->len= (uint) temp_len; uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0; uc->user_resources= *mqh; uc->intime= thd->thr_create_time; @@ -328,7 +328,7 @@ int check_user(THD *thd, enum enum_server_command command, bool check_count) { DBUG_ENTER("check_user"); - LEX_STRING db_str= { (char *) db, db ? strlen(db) : 0 }; + LEX_STRING db_str= { (char *) db, db ? (uint) strlen(db) : 0 }; #ifdef NO_EMBEDDED_ACCESS_CHECKS thd->main_security_ctx.master_access= GLOBAL_ACLS; // Full rights @@ -1036,7 +1036,7 @@ static int check_connection(THD *thd) char *user= end; char *passwd= strend(user)+1; - uint user_len= passwd - user - 1; + size_t user_len= passwd - user - 1; char *db= passwd; char db_buff[NAME_LEN + 1]; // buffer to store db in utf8 char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8 @@ -1051,10 +1051,10 @@ static int check_connection(THD *thd) *passwd > 127 and become 2**32-127 after casting to uint. */ uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? - (uchar)(*passwd++) : strlen(passwd); + (uchar)(*passwd++) : (uint) strlen(passwd); db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ? db + passwd_len + 1 : 0; - uint db_len= db ? strlen(db) : 0; + size_t db_len= db ? strlen(db) : 0; if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len) { @@ -1067,13 +1067,13 @@ static int check_connection(THD *thd) { db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info, - db, db_len, + db, (uint) db_len, thd->charset(), &dummy_errors)]= 0; db= db_buff; } user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1, - system_charset_info, user, user_len, + system_charset_info, user, (uint) user_len, thd->charset(), &dummy_errors)]= '\0'; user= user_buff; @@ -1789,7 +1789,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, statistic_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB], &LOCK_status); thd->convert_string(&tmp, system_charset_info, - packet, strlen(packet), thd->charset()); + packet, (uint) strlen(packet), thd->charset()); if (!mysql_change_db(thd, &tmp, FALSE)) { mysql_log.write(thd,command,"%s",thd->db); @@ -1852,7 +1852,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, */ char db_buff[NAME_LEN+1]; // buffer to store db in utf8 char *db= passwd; - uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? + size_t passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? (uchar)(*passwd++) : strlen(passwd); db+= passwd_len + 1; #ifndef EMBEDDED_LIBRARY @@ -1866,7 +1866,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* Convert database name to utf8 */ uint dummy_errors; db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, - system_charset_info, db, strlen(db), + system_charset_info, db, (uint) strlen(db), thd->charset(), &dummy_errors)]= 0; db= db_buff; @@ -1885,7 +1885,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* Clear variables that are allocated */ thd->user_connect= 0; - int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE); + int res= check_user(thd, COM_CHANGE_USER, passwd, (uint) passwd_len, db, FALSE); if (res) { @@ -2041,7 +2041,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, table_list.schema_table= schema_table; } - thd->query_length= strlen(packet); // for simplicity: don't optimize + thd->query_length= (uint) strlen(packet); // for simplicity: don't optimize if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1))) break; mysql_log.write(thd,command,"%s %s",table_list.table_name, fields); @@ -2363,8 +2363,9 @@ void log_slow_statement(THD *thd) { thd_proc_info(thd, "logging slow query"); - if ((ulong) (thd->start_time - thd->time_after_lock) > - thd->variables.long_query_time || + if ((thd->start_time > thd->time_after_lock && + (ulong) (thd->start_time - thd->time_after_lock) > + thd->variables.long_query_time) || (thd->server_status & (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) && opt_log_queries_not_using_indexes && @@ -2623,6 +2624,10 @@ mysql_execute_command(THD *thd) TABLE_LIST *all_tables; /* most outer SELECT_LEX_UNIT of query */ SELECT_LEX_UNIT *unit= &lex->unit; +#ifdef HAVE_REPLICATION + /* have table map for update for multi-update statement (BUG#37051) */ + bool have_table_map_for_update= FALSE; +#endif /* Saved variable value */ DBUG_ENTER("mysql_execute_command"); thd->net.no_send_error= 0; @@ -2702,6 +2707,48 @@ mysql_execute_command(THD *thd) // force searching in slave.cc:tables_ok() all_tables->updating= 1; } + + /* + For fix of BUG#37051, the master stores the table map for update + in the Query_log_event, and the value is assigned to + thd->variables.table_map_for_update before executing the update + query. + + If thd->variables.table_map_for_update is set, then we are + replicating from a new master, we can use this value to apply + filter rules without opening all the tables. However If + thd->variables.table_map_for_update is not set, then we are + replicating from an old master, so we just skip this and + continue with the old method. And of course, the bug would still + exist for old masters. + */ + if (lex->sql_command == SQLCOM_UPDATE_MULTI && + thd->table_map_for_update) + { + have_table_map_for_update= TRUE; + table_map table_map_for_update= thd->table_map_for_update; + uint nr= 0; + TABLE_LIST *table; + for (table=all_tables; table; table=table->next_global, nr++) + { + if (table_map_for_update & ((table_map)1 << nr)) + table->updating= TRUE; + else + table->updating= FALSE; + } + + if (all_tables_not_ok(thd, all_tables)) + { + /* we warn the slave SQL thread */ + my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); + if (thd->one_shot_set) + reset_one_shot_variables(thd); + DBUG_RETURN(0); + } + + for (table=all_tables; table; table=table->next_global) + table->updating= TRUE; + } /* Check if statment should be skipped because of slave filtering @@ -3217,6 +3264,42 @@ mysql_execute_command(THD *thd) } if (select_lex->item_list.elements) // With select { + /* + If: + a) we inside an SP and there was NAME_CONST substitution, + b) binlogging is on, + 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() && + !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_result *sel_result; select_lex->options|= SELECT_NO_UNLOCK; @@ -3660,7 +3743,7 @@ end_with_restore_list: #ifdef HAVE_REPLICATION /* Check slave filtering rules */ - if (unlikely(thd->slave_thread)) + if (unlikely(thd->slave_thread && !have_table_map_for_update)) { if (all_tables_not_ok(thd, all_tables)) { @@ -3969,7 +4052,7 @@ end_with_restore_list: #endif case SQLCOM_CHANGE_DB: { - LEX_STRING db_str= { (char *) select_lex->db, strlen(select_lex->db) }; + LEX_STRING db_str= { (char *) select_lex->db, (uint) strlen(select_lex->db) }; if (!mysql_change_db(thd, &db_str, FALSE)) send_ok(thd); @@ -6202,7 +6285,7 @@ void create_select_for_variable(const char *var_name) mysql_init_select(lex); lex->sql_command= SQLCOM_SELECT; tmp.str= (char*) var_name; - tmp.length=strlen(var_name); + tmp.length=(uint) strlen(var_name); bzero((char*) &null_lex_string.str, sizeof(null_lex_string)); /* We set the name of Item to @@session.var_name because that then is used @@ -6211,7 +6294,7 @@ void create_select_for_variable(const char *var_name) if ((var= get_system_var(thd, OPT_SESSION, tmp, null_lex_string))) { end= strxmov(buff, "@@session.", var_name, NullS); - var->set_name(buff, end-buff, system_charset_info); + var->set_name(buff, (uint) (end - buff), system_charset_info); add_item_to_list(thd, var); } DBUG_VOID_RETURN; @@ -7394,8 +7477,26 @@ void 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; @@ -7954,10 +8055,10 @@ void get_default_definer(THD *thd, LEX_USER *definer) const Security_context *sctx= thd->security_ctx; definer->user.str= (char *) sctx->priv_user; - definer->user.length= strlen(definer->user.str); + definer->user.length= (uint) strlen(definer->user.str); definer->host.str= (char *) sctx->priv_host; - definer->host.length= strlen(definer->host.str); + definer->host.length= (uint) strlen(definer->host.str); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 505a3d122b4..c152bde1b92 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -726,13 +726,13 @@ static bool insert_params_withlog(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); } @@ -764,13 +764,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_repl.cc b/sql/sql_repl.cc index 86eb609bdd3..33c2855c20b 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -202,7 +202,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; @@ -1284,8 +1284,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) @@ -1580,7 +1580,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 fd99a6e25f6..f2f2efc9e77 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -78,7 +78,6 @@ static store_key *get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables, KEY_PART_INFO *key_part, char *key_buff, uint maybe_null); -static bool make_simple_join(JOIN *join,TABLE *tmp_table); static void make_outerjoin_info(JOIN *join); static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item); static void make_join_readinfo(JOIN *join, ulonglong options); @@ -100,7 +99,7 @@ static COND* substitute_for_best_equal_field(COND *cond, void *table_join_idx); static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top); -static bool check_interleaving_with_nj(JOIN_TAB *last, JOIN_TAB *next); +static bool check_interleaving_with_nj(JOIN_TAB *next); static void restore_prev_nj_state(JOIN_TAB *last); static void reset_nj_counters(List<TABLE_LIST> *join_list); static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list, @@ -1619,8 +1618,13 @@ JOIN::exec() We have to test for 'conds' here as the WHERE may not be constant even if we don't have any tables for prepared statements or if conds uses something like 'rand()'. + If the HAVING clause is either impossible or always true, then + JOIN::having is set to NULL by optimize_cond. + In this case JOIN::exec must check for JOIN::having_value, in the + same way it checks for JOIN::cond_value. */ if (cond_value != Item::COND_FALSE && + having_value != Item::COND_FALSE && (!conds || conds->val_int()) && (!having || having->val_int())) { @@ -1815,7 +1819,7 @@ JOIN::exec() /* Free first data from old join */ curr_join->join_free(); - if (make_simple_join(curr_join, curr_tmp_table)) + if (curr_join->make_simple_join(this, curr_tmp_table)) DBUG_VOID_RETURN; calc_group_buffer(curr_join, group_list); count_field_types(select_lex, &curr_join->tmp_table_param, @@ -1935,7 +1939,7 @@ JOIN::exec() curr_join->select_distinct=0; } curr_tmp_table->reginfo.lock_type= TL_UNLOCK; - if (make_simple_join(curr_join, curr_tmp_table)) + if (curr_join->make_simple_join(this, curr_tmp_table)) DBUG_VOID_RETURN; calc_group_buffer(curr_join, curr_join->group_list); count_field_types(select_lex, &curr_join->tmp_table_param, @@ -2381,11 +2385,12 @@ typedef struct st_sargable_param */ static bool -make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, +make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, DYNAMIC_ARRAY *keyuse_array) { int error; TABLE *table; + TABLE_LIST *tables= tables_arg; uint i,table_count,const_count,key; table_map found_const_table_map, all_table_map, found_ref, refs; key_map const_ref, eq_part; @@ -2423,10 +2428,10 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, table_vector[i]=s->table=table=tables->table; table->pos_in_table_list= tables; error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); - if(error) + if (error) { - table->file->print_error(error, MYF(0)); - DBUG_RETURN(1); + table->file->print_error(error, MYF(0)); + goto error; } table->quick_keys.clear_all(); table->reginfo.join_tab=s; @@ -2511,7 +2516,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, { join->tables=0; // Don't use join->table my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0)); - DBUG_RETURN(1); + goto error; } s->key_dependent= s->dependent; } @@ -2521,7 +2526,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables, conds, join->cond_equal, ~outer_join, join->select_lex, &sargables)) - DBUG_RETURN(1); + goto error; /* Read tables with 0 or 1 rows (system tables) */ join->const_table_map= 0; @@ -2537,7 +2542,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if ((tmp=join_read_const_table(s, p_pos))) { if (tmp > 0) - DBUG_RETURN(1); // Fatal error + goto error; // Fatal error } else found_const_table_map|= s->table->map; @@ -2609,7 +2614,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if ((tmp= join_read_const_table(s, join->positions+const_count-1))) { if (tmp > 0) - DBUG_RETURN(1); // Fatal error + goto error; // Fatal error } else found_const_table_map|= table->map; @@ -2658,12 +2663,12 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, set_position(join,const_count++,s,start_keyuse); if (create_ref_for_key(join, s, start_keyuse, found_const_table_map)) - DBUG_RETURN(1); + goto error; if ((tmp=join_read_const_table(s, join->positions+const_count-1))) { if (tmp > 0) - DBUG_RETURN(1); // Fatal error + goto error; // Fatal error } else found_const_table_map|= table->map; @@ -2740,7 +2745,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, *s->on_expr_ref ? *s->on_expr_ref : conds, 1, &error); if (!select) - DBUG_RETURN(1); + goto error; records= get_quick_record_count(join->thd, select, s->table, &s->const_keys, join->row_limit); s->quick=select->quick; @@ -2786,7 +2791,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, { optimize_keyuse(join, keyuse_array); if (choose_plan(join, all_table_map & ~join->const_table_map)) - DBUG_RETURN(TRUE); + goto error; } else { @@ -2796,6 +2801,17 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, } /* Generate an execution plan from the found optimal join order. */ DBUG_RETURN(join->thd->killed || get_best_combination(join)); + +error: + /* + Need to clean up join_tab from TABLEs in case of error. + They won't get cleaned up by JOIN::cleanup() because JOIN::join_tab + may not be assigned yet by this function (which is building join_tab). + Dangling TABLE::reginfo.join_tab may cause part_of_refkey to choke. + */ + for (tables= tables_arg; tables; tables= tables->next_leaf) + tables->table->reginfo.join_tab= NULL; + DBUG_RETURN (1); } @@ -4730,6 +4746,18 @@ greedy_search(JOIN *join, */ join->positions[idx]= best_pos; + /* + Update the interleaving state after extending the current partial plan + with a new table. + We are doing this here because best_extension_by_limited_search reverts + the interleaving state to the one of the non-extended partial plan + on exit. + */ + IF_DBUG(bool is_interleave_error= ) + check_interleaving_with_nj (best_table); + /* This has been already checked by best_extension_by_limited_search */ + DBUG_ASSERT(!is_interleave_error); + /* find the position of 'best_table' in 'join->best_ref' */ best_idx= idx; JOIN_TAB *pos= join->best_ref[best_idx]; @@ -4747,7 +4775,7 @@ greedy_search(JOIN *join, --size_remain; ++idx; - DBUG_EXECUTE("opt", print_plan(join, join->tables, + DBUG_EXECUTE("opt", print_plan(join, idx, record_count, read_time, read_time, "extended");); } while (TRUE); @@ -4898,7 +4926,7 @@ best_extension_by_limited_search(JOIN *join, table_map real_table_bit= s->table->map; if ((remaining_tables & real_table_bit) && !(remaining_tables & s->dependent) && - (!idx || !check_interleaving_with_nj(join->positions[idx-1].table, s))) + (!idx || !check_interleaving_with_nj(s))) { double current_record_count, current_read_time; @@ -5043,7 +5071,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, { table_map real_table_bit=s->table->map; if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent) && - (!idx|| !check_interleaving_with_nj(join->positions[idx-1].table, s))) + (!idx|| !check_interleaving_with_nj(s))) { double records, best; best_access_path(join, s, thd, rest_tables, idx, record_count, @@ -5426,48 +5454,42 @@ store_val_in_field(Field *field, Item *item, enum_check_fields check_flag) } -static bool -make_simple_join(JOIN *join,TABLE *tmp_table) +/** + @details Initialize a JOIN as a query execution plan + that accesses a single table via a table scan. + + @param parent contains JOIN_TAB and TABLE object buffers for this join + @param tmp_table temporary table + + @retval FALSE success + @retval TRUE error occurred +*/ +bool +JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table) { - TABLE **tableptr; - JOIN_TAB *join_tab; - DBUG_ENTER("make_simple_join"); + DBUG_ENTER("JOIN::make_simple_join"); /* Reuse TABLE * and JOIN_TAB if already allocated by a previous call to this function through JOIN::exec (may happen for sub-queries). */ - if (!join->table_reexec) - { - if (!(join->table_reexec= (TABLE**) join->thd->alloc(sizeof(TABLE*)))) - DBUG_RETURN(TRUE); /* purecov: inspected */ - if (join->tmp_join) - join->tmp_join->table_reexec= join->table_reexec; - } - if (!join->join_tab_reexec) - { - if (!(join->join_tab_reexec= - (JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB)))) - DBUG_RETURN(TRUE); /* purecov: inspected */ - if (join->tmp_join) - join->tmp_join->join_tab_reexec= join->join_tab_reexec; - } - tableptr= join->table_reexec; - join_tab= join->join_tab_reexec; - - join->join_tab=join_tab; - join->table=tableptr; tableptr[0]=tmp_table; - join->tables=1; - join->const_tables=0; - join->const_table_map=0; - join->tmp_table_param.field_count= join->tmp_table_param.sum_func_count= - join->tmp_table_param.func_count=0; - join->tmp_table_param.copy_field=join->tmp_table_param.copy_field_end=0; - join->first_record=join->sort_and_group=0; - join->send_records=(ha_rows) 0; - join->group=0; - join->row_limit=join->unit->select_limit_cnt; - join->do_send_rows = (join->row_limit) ? 1 : 0; + if (!parent->join_tab_reexec && + !(parent->join_tab_reexec= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)))) + DBUG_RETURN(TRUE); /* purecov: inspected */ + + join_tab= parent->join_tab_reexec; + table= &parent->table_reexec[0]; parent->table_reexec[0]= tmp_table; + tables= 1; + const_tables= 0; + const_table_map= 0; + tmp_table_param.field_count= tmp_table_param.sum_func_count= + tmp_table_param.func_count= 0; + tmp_table_param.copy_field= tmp_table_param.copy_field_end=0; + first_record= sort_and_group=0; + send_records= (ha_rows) 0; + group= 0; + row_limit= unit->select_limit_cnt; + do_send_rows= row_limit ? 1 : 0; join_tab->cache.buff=0; /* No caching */ join_tab->table=tmp_table; @@ -5484,7 +5506,7 @@ make_simple_join(JOIN *join,TABLE *tmp_table) join_tab->ref.key = -1; join_tab->not_used_in_distinct=0; join_tab->read_first_record= join_init_read_record; - join_tab->join=join; + join_tab->join= this; join_tab->ref.key_parts= 0; bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record)); tmp_table->status=0; @@ -7607,7 +7629,7 @@ static int compare_fields_by_table_order(Item_field *field1, if (outer_ref) return cmp; JOIN_TAB **idx= (JOIN_TAB **) table_join_idx; - cmp= idx[field2->field->table->tablenr]-idx[field1->field->table->tablenr]; + cmp= (uint) (idx[field2->field->table->tablenr] - idx[field1->field->table->tablenr]); return cmp < 0 ? -1 : (cmp ? 1 : 0); } @@ -8415,9 +8437,6 @@ static void reset_nj_counters(List<TABLE_LIST> *join_list) SYNOPSIS check_interleaving_with_nj() - join Join being processed - last_tab Last table in current partial join order (this function is - not called for empty partial join orders) next_tab Table we're going to extend the current partial join with DESCRIPTION @@ -8502,10 +8521,10 @@ static void reset_nj_counters(List<TABLE_LIST> *join_list) TRUE Requested join order extension not allowed. */ -static bool check_interleaving_with_nj(JOIN_TAB *last_tab, JOIN_TAB *next_tab) +static bool check_interleaving_with_nj(JOIN_TAB *next_tab) { TABLE_LIST *next_emb= next_tab->table->pos_in_table_list->embedding; - JOIN *join= last_tab->join; + JOIN *join= next_tab->join; if (join->cur_embedding_map & ~next_tab->embedding_map) { @@ -9637,7 +9656,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, table->s->default_values= table->record[1]+alloc_length; } copy_func[0]=0; // End marker - param->func_count= copy_func - param->items_to_copy; + param->func_count= (uint) (copy_func - param->items_to_copy); recinfo=param->start_recinfo; null_flags=(uchar*) table->record[0]; @@ -15210,10 +15229,10 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, item_list.push_back(new Item_int((int32) join->select_lex->select_number)); item_list.push_back(new Item_string(join->select_lex->type, - strlen(join->select_lex->type), cs)); + (uint) strlen(join->select_lex->type), cs)); for (uint i=0 ; i < 7; i++) item_list.push_back(item_null); - item_list.push_back(new Item_string(message,strlen(message),cs)); + item_list.push_back(new Item_string(message,(uint) strlen(message),cs)); if (result->send_data(item_list)) join->error= 1; } @@ -15232,7 +15251,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, item_list.push_back(new Item_null); /* select_type */ item_list.push_back(new Item_string(join->select_lex->type, - strlen(join->select_lex->type), + (uint) strlen(join->select_lex->type), cs)); /* table */ { @@ -15259,7 +15278,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, } /* type */ item_list.push_back(new Item_string(join_type_str[JT_ALL], - strlen(join_type_str[JT_ALL]), + (uint) strlen(join_type_str[JT_ALL]), cs)); /* possible_keys */ item_list.push_back(item_null); @@ -15308,7 +15327,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, join->select_lex->select_number)); /* select_type */ item_list.push_back(new Item_string(join->select_lex->type, - strlen(join->select_lex->type), + (uint) strlen(join->select_lex->type), cs)); if (tab->type == JT_ALL && tab->select && tab->select->quick) { @@ -15333,12 +15352,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, { TABLE_LIST *real_table= table->pos_in_table_list; item_list.push_back(new Item_string(real_table->alias, - strlen(real_table->alias), + (uint) strlen(real_table->alias), cs)); } /* type */ item_list.push_back(new Item_string(join_type_str[tab->type], - strlen(join_type_str[tab->type]), + (uint) strlen(join_type_str[tab->type]), cs)); /* Build "possible_keys" value and add it to item_list */ if (!tab->keys.is_clear_all()) @@ -15351,7 +15370,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, if (tmp1.length()) tmp1.append(','); tmp1.append(table->key_info[j].name, - strlen(table->key_info[j].name), + (uint) strlen(table->key_info[j].name), system_charset_info); } } @@ -15367,17 +15386,17 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, KEY *key_info=table->key_info+ tab->ref.key; register uint length; item_list.push_back(new Item_string(key_info->name, - strlen(key_info->name), + (uint) strlen(key_info->name), system_charset_info)); - length= longlong2str(tab->ref.key_length, keylen_str_buf, 10) - - keylen_str_buf; + length= (uint) (longlong2str(tab->ref.key_length, keylen_str_buf, 10) - + keylen_str_buf); item_list.push_back(new Item_string(keylen_str_buf, length, system_charset_info)); for (store_key **ref=tab->ref.key_copy ; *ref ; ref++) { if (tmp2.length()) tmp2.append(','); - tmp2.append((*ref)->name(), strlen((*ref)->name()), + tmp2.append((*ref)->name(), (uint) strlen((*ref)->name()), system_charset_info); } item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs)); @@ -15387,9 +15406,9 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, KEY *key_info=table->key_info+ tab->index; register uint length; item_list.push_back(new Item_string(key_info->name, - strlen(key_info->name),cs)); - length= longlong2str(key_info->key_length, keylen_str_buf, 10) - - keylen_str_buf; + (uint) strlen(key_info->name),cs)); + length= (uint) (longlong2str(key_info->key_length, keylen_str_buf, 10) - + keylen_str_buf); item_list.push_back(new Item_string(keylen_str_buf, length, system_charset_info)); @@ -15422,7 +15441,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, key_read=1; if (tab->info) - item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs)); + item_list.push_back(new Item_string(tab->info,(uint) strlen(tab->info),cs)); else if (tab->packed_info & TAB_INFO_HAVE_VALUE) { if (tab->packed_info & TAB_INFO_USING_INDEX) @@ -15746,7 +15765,7 @@ void TABLE_LIST::print(THD *thd, String *str) if (schema_table) { append_identifier(thd, str, schema_table_name, - strlen(schema_table_name)); + (uint) strlen(schema_table_name)); cmp_name= schema_table_name; } else @@ -15771,7 +15790,7 @@ void TABLE_LIST::print(THD *thd, String *str) } } - append_identifier(thd, str, t_alias, strlen(t_alias)); + append_identifier(thd, str, t_alias, (uint) strlen(t_alias)); } if (use_index) diff --git a/sql/sql_select.h b/sql/sql_select.h index 8ece01d3286..75a905043d2 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -352,9 +352,12 @@ public: cleared only at the end of the execution of the whole query and not caching allocations that occur in repetition at execution time will result in excessive memory usage. + Note: make_simple_join always creates an execution plan that accesses + a single table, thus it is sufficient to have a one-element array for + table_reexec. */ SORT_FIELD *sortorder; // make_unireg_sortorder() - TABLE **table_reexec; // make_simple_join() + TABLE *table_reexec[1]; // make_simple_join() JOIN_TAB *join_tab_reexec; // make_simple_join() /* end of allocation caching storage */ @@ -384,7 +387,7 @@ public: exec_tmp_table1= 0; exec_tmp_table2= 0; sortorder= 0; - table_reexec= 0; + table_reexec[0]= 0; join_tab_reexec= 0; thd= thd_arg; sum_funcs= sum_funcs2= 0; @@ -476,6 +479,8 @@ public: return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 || select_lex == unit->fake_select_lex)); } +private: + bool make_simple_join(JOIN *join, TABLE *tmp_table); }; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 778f10f2b36..297061207cf 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -106,7 +106,7 @@ static struct show_privileges_st sys_privileges[]= {"Alter", "Tables", "To alter the table"}, {"Alter routine", "Functions,Procedures", "To alter or drop stored functions/procedures"}, {"Create", "Databases,Tables,Indexes", "To create new databases and tables"}, - {"Create routine","Functions,Procedures","To use CREATE FUNCTION/PROCEDURE"}, + {"Create routine","Databases","To use CREATE FUNCTION/PROCEDURE"}, {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"}, {"Create view", "Tables", "To create new views"}, {"Create user", "Server Admin", "To create new users"}, @@ -287,11 +287,18 @@ find_files(THD *thd, List<char> *files, const char *db, #ifndef NO_EMBEDDED_ACCESS_CHECKS uint col_access=thd->col_access; #endif + uint wild_length= 0; TABLE_LIST table_list; DBUG_ENTER("find_files"); - if (wild && !wild[0]) - wild=0; + if (wild) + { + if (!wild[0]) + wild= 0; + else + wild_length= strlen(wild); + } + bzero((char*) &table_list,sizeof(table_list)); @@ -340,8 +347,11 @@ find_files(THD *thd, List<char> *files, const char *db, { if (lower_case_table_names) { - if (wild_case_compare(files_charset_info, file->name, wild)) - continue; + if (my_wildcmp(files_charset_info, + file->name, file->name + strlen(file->name), + wild, wild + wild_length, + wild_prefix, wild_one,wild_many)) + continue; } else if (wild_compare(file->name,wild,0)) continue; @@ -352,9 +362,9 @@ find_files(THD *thd, List<char> *files, const char *db, if (db && !(col_access & TABLE_ACLS)) { table_list.db= (char*) db; - table_list.db_length= strlen(db); + table_list.db_length= (uint) strlen(db); table_list.table_name= file->name; - table_list.table_name_length= strlen(file->name); + table_list.table_name_length= (uint) strlen(file->name); table_list.grant.privilege=col_access; if (check_grant(thd, TABLE_ACLS, &table_list, 1, 1, 1)) continue; @@ -520,12 +530,12 @@ bool mysqld_show_create_db(THD *thd, char *dbname, DBUG_RETURN(TRUE); protocol->prepare_for_resend(); - protocol->store(dbname, strlen(dbname), system_charset_info); + protocol->store(dbname, (uint) strlen(dbname), system_charset_info); buffer.length(0); buffer.append(STRING_WITH_LEN("CREATE DATABASE ")); if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS) buffer.append(STRING_WITH_LEN("/*!32312 IF NOT EXISTS*/ ")); - append_identifier(thd, &buffer, dbname, strlen(dbname)); + append_identifier(thd, &buffer, dbname, (uint) strlen(dbname)); if (create.default_table_charset) { @@ -897,7 +907,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) else alias= (lower_case_table_names == 2 ? table->alias : share->table_name); - append_identifier(thd, packet, alias, strlen(alias)); + append_identifier(thd, packet, alias, (uint) strlen(alias)); packet->append(STRING_WITH_LEN(" (\n")); for (ptr=table->field ; (field= *ptr); ptr++) @@ -908,7 +918,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) packet->append(STRING_WITH_LEN(",\n")); packet->append(STRING_WITH_LEN(" ")); - append_identifier(thd,packet,field->field_name, strlen(field->field_name)); + append_identifier(thd,packet,field->field_name, (uint) strlen(field->field_name)); packet->append(' '); // check for surprises from the previous call to Field::sql_type() if (type.ptr() != tmp) @@ -995,7 +1005,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) packet->append(STRING_WITH_LEN("KEY ")); if (!found_primary) - append_identifier(thd, packet, key_info->name, strlen(key_info->name)); + append_identifier(thd, packet, key_info->name, (uint) strlen(key_info->name)); if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) && !limited_mysql_mode && !foreign_db_mode) @@ -1022,7 +1032,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) if (key_part->field) append_identifier(thd,packet,key_part->field->field_name, - strlen(key_part->field->field_name)); + (uint) strlen(key_part->field->field_name)); if (key_part->field && (key_part->length != table->field[key_part->fieldnr-1]->key_length() && @@ -1046,7 +1056,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) if ((for_str= file->get_foreign_key_create_info())) { - packet->append(for_str, strlen(for_str)); + packet->append(for_str, (uint) strlen(for_str)); file->free_foreign_key_create_info(for_str); } @@ -1222,21 +1232,25 @@ void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user, static int view_store_create_info(THD *thd, TABLE_LIST *table, String *buff) { + my_bool compact_view_name= TRUE; my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL | MODE_ORACLE | MODE_MSSQL | MODE_DB2 | MODE_MAXDB | MODE_ANSI)) != 0; - /* - Compact output format for view can be used - - if user has db of this view as current db - - if this view only references table inside it's own db - */ + if (!thd->db || strcmp(thd->db, table->view_db.str)) - table->compact_view_format= FALSE; + /* + print compact view name if the view belongs to the current database + */ + compact_view_name= table->compact_view_format= FALSE; else { + /* + Compact output format for view body can be used + if this view only references table inside it's own db + */ TABLE_LIST *tbl; table->compact_view_format= TRUE; for (tbl= thd->lex->query_tables; @@ -1257,7 +1271,7 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff) view_store_options(thd, table, buff); } buff->append(STRING_WITH_LEN("VIEW ")); - if (!table->compact_view_format) + if (!compact_view_name) { append_identifier(thd, buff, table->view_db.str, table->view_db.length); buff->append('.'); @@ -1324,7 +1338,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) field_list.push_back(field=new Item_empty_string("db",NAME_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, FIELD_TYPE_LONG)); + field_list.push_back(field= new Item_return_int("Time",7, FIELD_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)); @@ -1425,7 +1440,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) else protocol->store(command_name[thd_info->command], 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); @@ -1451,7 +1466,7 @@ static bool show_status_array(THD *thd, const char *wild, char buff[1024], *prefix_end; /* the variable name should not be longer then 80 characters */ char name_buffer[80]; - int len; + size_t len; LEX_STRING null_lex_str; CHARSET_INFO *charset= system_charset_info; DBUG_ENTER("show_status_array"); @@ -1460,11 +1475,11 @@ static bool show_status_array(THD *thd, const char *wild, null_lex_str.length= 0; prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1); - len=name_buffer + sizeof(name_buffer) - prefix_end; + len= name_buffer + sizeof(name_buffer) - prefix_end; for (; variables->name; variables++) { - strnmov(prefix_end, variables->name, len); + strnmov(prefix_end, variables->name, (uint) len); name_buffer[sizeof(name_buffer)-1]=0; /* Safety */ SHOW_TYPE show_type=variables->type; if (show_type == SHOW_VARS) @@ -1783,7 +1798,7 @@ static bool show_status_array(THD *thd, const char *wild, const char *p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i); if (p == NULL) break; - to= strnmov(to, p, buff_end-to-1); + to= strnmov(to, p, (uint) (buff_end-to-1)); *to++= ':'; } if (to != buff) @@ -1812,7 +1827,7 @@ static bool show_status_array(THD *thd, const char *wild, break; } restore_record(table, s->default_values); - table->field[0]->store(name_buffer, strlen(name_buffer), + table->field[0]->store(name_buffer, (uint) strlen(name_buffer), system_charset_info); table->field[1]->store(pos, (uint32) (end - pos), charset); if (schema_table_store_record(thd, table)) @@ -1931,9 +1946,9 @@ int make_table_list(THD *thd, SELECT_LEX *sel, Table_ident *table_ident; LEX_STRING ident_db, ident_table; ident_db.str= db; - ident_db.length= strlen(db); + ident_db.length= (uint) strlen(db); ident_table.str= table; - ident_table.length= strlen(table); + ident_table.length= (uint) strlen(table); table_ident= new Table_ident(thd, ident_db, ident_table, 1); sel->init_query(); if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ, @@ -1963,12 +1978,12 @@ bool uses_only_table_name_fields(Item *item, TABLE_LIST *table) const char *field_name1= schema_table->idx_field1 >= 0 ? field_info[schema_table->idx_field1].field_name : ""; const char *field_name2= schema_table->idx_field2 >= 0 ? field_info[schema_table->idx_field2].field_name : ""; if (table->table != item_field->field->table || - (cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1), + (cs->coll->strnncollsp(cs, (uchar *) field_name1, (uint) strlen(field_name1), (uchar *) item_field->field_name, - strlen(item_field->field_name), 0) && - cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2), + (uint) strlen(item_field->field_name), 0) && + cs->coll->strnncollsp(cs, (uchar *) field_name2, (uint) strlen(field_name2), (uchar *) item_field->field_name, - strlen(item_field->field_name), 0))) + (uint) strlen(item_field->field_name), 0))) return 0; } else if (item->type() == Item::REF_ITEM) @@ -2299,9 +2314,9 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) { restore_record(table, s->default_values); table->field[schema_table->idx_field1]-> - store(base_name, strlen(base_name), system_charset_info); + store(base_name, (uint) strlen(base_name), system_charset_info); table->field[schema_table->idx_field2]-> - store(file_name, strlen(file_name),system_charset_info); + store(file_name, (uint) strlen(file_name),system_charset_info); if (!partial_cond || partial_cond->val_int()) { if (schema_table_idx == SCH_TABLE_NAMES) @@ -2409,9 +2424,9 @@ bool store_schema_shemata(THD* thd, TABLE *table, const char *db_name, CHARSET_INFO *cs) { restore_record(table, s->default_values); - table->field[1]->store(db_name, strlen(db_name), system_charset_info); - table->field[2]->store(cs->csname, strlen(cs->csname), system_charset_info); - table->field[3]->store(cs->name, strlen(cs->name), system_charset_info); + table->field[1]->store(db_name, (uint) strlen(db_name), system_charset_info); + table->field[2]->store(cs->csname, (uint) strlen(cs->csname), system_charset_info); + table->field[3]->store(cs->name, (uint) strlen(cs->name), system_charset_info); return schema_table_store_record(thd, table); } @@ -2477,8 +2492,8 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, DBUG_ENTER("get_schema_tables_record"); restore_record(table, s->default_values); - table->field[1]->store(base_name, strlen(base_name), cs); - table->field[2]->store(file_name, strlen(file_name), cs); + table->field[1]->store(base_name, (uint) strlen(base_name), cs); + table->field[2]->store(file_name, (uint) strlen(file_name), cs); if (res) { /* @@ -2491,7 +2506,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs); else table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs); - table->field[20]->store(error, strlen(error), cs); + table->field[20]->store(error, (uint) strlen(error), cs); thd->clear_error(); } else if (tables->view) @@ -2521,7 +2536,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, table->field[i]->set_notnull(); } tmp_buff= file->table_type(); - table->field[4]->store(tmp_buff, strlen(tmp_buff), cs); + table->field[4]->store(tmp_buff, (uint) strlen(tmp_buff), cs); table->field[5]->store((longlong) share->frm_version, TRUE); enum row_type row_type = file->get_row_type(); switch (row_type) { @@ -2548,7 +2563,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, tmp_buff= "Compact"; break; } - table->field[6]->store(tmp_buff, strlen(tmp_buff), cs); + table->field[6]->store(tmp_buff, (uint) strlen(tmp_buff), cs); if (!tables->schema_table) { table->field[7]->store((longlong) file->records, TRUE); @@ -2590,7 +2605,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, } tmp_buff= (share->table_charset ? share->table_charset->name : "default"); - table->field[17]->store(tmp_buff, strlen(tmp_buff), cs); + table->field[17]->store(tmp_buff, (uint) strlen(tmp_buff), cs); if (file->table_flags() & (ulong) HA_HAS_CHECKSUM) { table->field[18]->store((longlong) file->checksum(), TRUE); @@ -2646,7 +2661,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, table->field[20]->store(comment, (comment == share->comment.str ? share->comment.length : - strlen(comment)), cs); + (uint) strlen(comment)), cs); if (comment != share->comment.str) my_free(comment, MYF(0)); } @@ -2692,8 +2707,8 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, count= 0; file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); restore_record(show_table, s->default_values); - base_name_length= strlen(base_name); - file_name_length= strlen(file_name); + base_name_length= (uint) strlen(base_name); + file_name_length= (uint) strlen(file_name); for (ptr=show_table->field; (field= *ptr) ; ptr++) { @@ -2738,13 +2753,13 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, #endif table->field[1]->store(base_name, base_name_length, cs); table->field[2]->store(file_name, file_name_length, cs); - table->field[3]->store(field->field_name, strlen(field->field_name), + table->field[3]->store(field->field_name, (uint) strlen(field->field_name), cs); table->field[4]->store((longlong) count, TRUE); field->sql_type(type); table->field[14]->store(type.ptr(), type.length(), cs); tmp_buff= strchr(type.ptr(), '('); - table->field[7]->store(type.ptr(), + table->field[7]->store(type.ptr(), (uint) (tmp_buff ? tmp_buff - type.ptr() : type.length()), cs); @@ -2756,7 +2771,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, pos=(byte*) ((flags & NOT_NULL_FLAG) ? "NO" : "YES"); table->field[6]->store((const char*) pos, - strlen((const char*) pos), cs); + (uint) strlen((const char*) pos), cs); is_blob= (field->type() == FIELD_TYPE_BLOB); if (field->has_charset() || is_blob || field->real_type() == MYSQL_TYPE_VARCHAR || // For varbinary type @@ -2824,18 +2839,18 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, { pos=(byte*) field->charset()->csname; table->field[12]->store((const char*) pos, - strlen((const char*) pos), cs); + (uint) strlen((const char*) pos), cs); table->field[12]->set_notnull(); pos=(byte*) field->charset()->name; table->field[13]->store((const char*) pos, - strlen((const char*) pos), cs); + (uint) strlen((const char*) pos), cs); table->field[13]->set_notnull(); } pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" : (field->flags & UNIQUE_KEY_FLAG) ? "UNI" : (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":""); table->field[15]->store((const char*) pos, - strlen((const char*) pos), cs); + (uint) strlen((const char*) pos), cs); end= tmp; if (field->unireg_check == Field::NEXT_NUMBER) @@ -2868,10 +2883,10 @@ int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond) { const char *comment; restore_record(table, s->default_values); - table->field[0]->store(tmp_cs->csname, strlen(tmp_cs->csname), scs); - table->field[1]->store(tmp_cs->name, strlen(tmp_cs->name), scs); + table->field[0]->store(tmp_cs->csname, (uint) strlen(tmp_cs->csname), scs); + table->field[1]->store(tmp_cs->name, (uint) strlen(tmp_cs->name), scs); comment= tmp_cs->comment ? tmp_cs->comment : ""; - table->field[2]->store(comment, strlen(comment), scs); + table->field[2]->store(comment, (uint) strlen(comment), scs); table->field[3]->store((longlong) tmp_cs->mbmaxlen, TRUE); if (schema_table_store_record(thd, table)) return 1; @@ -2905,13 +2920,13 @@ int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond) { const char *tmp_buff; restore_record(table, s->default_values); - table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs); - table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs); + table->field[0]->store(tmp_cl->name, (uint) strlen(tmp_cl->name), scs); + table->field[1]->store(tmp_cl->csname , (uint) strlen(tmp_cl->csname), scs); table->field[2]->store((longlong) tmp_cl->number, TRUE); tmp_buff= (tmp_cl->state & MY_CS_PRIMARY) ? "Yes" : ""; - table->field[3]->store(tmp_buff, strlen(tmp_buff), scs); + table->field[3]->store(tmp_buff, (uint) strlen(tmp_buff), scs); tmp_buff= (tmp_cl->state & MY_CS_COMPILED)? "Yes" : ""; - table->field[4]->store(tmp_buff, strlen(tmp_buff), scs); + table->field[4]->store(tmp_buff, (uint) strlen(tmp_buff), scs); table->field[5]->store((longlong) tmp_cl->strxfrm_multiply, TRUE); if (schema_table_store_record(thd, table)) return 1; @@ -2941,8 +2956,8 @@ int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond) !my_charset_same(tmp_cs,tmp_cl)) continue; restore_record(table, s->default_values); - table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs); - table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs); + table->field[0]->store(tmp_cl->name, (uint) strlen(tmp_cl->name), scs); + table->field[1]->store(tmp_cl->csname , (uint) strlen(tmp_cl->csname), scs); if (schema_table_store_record(thd, table)) return 1; } @@ -3113,16 +3128,16 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) { restore_record(table, s->default_values); - table->field[1]->store(base_name, strlen(base_name), cs); - table->field[2]->store(file_name, strlen(file_name), cs); + table->field[1]->store(base_name, (uint) strlen(base_name), cs); + table->field[2]->store(file_name, (uint) strlen(file_name), cs); table->field[3]->store((longlong) ((key_info->flags & HA_NOSAME) ? 0 : 1), TRUE); - table->field[4]->store(base_name, strlen(base_name), cs); - table->field[5]->store(key_info->name, strlen(key_info->name), cs); + table->field[4]->store(base_name, (uint) strlen(base_name), cs); + table->field[5]->store(key_info->name, (uint) strlen(key_info->name), cs); table->field[6]->store((longlong) (j+1), TRUE); str=(key_part->field ? key_part->field->field_name : "?unknown field?"); - table->field[7]->store(str, strlen(str), cs); + table->field[7]->store(str, (uint) strlen(str), cs); if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER) { table->field[8]->store(((key_part->key_part_flag & @@ -3149,9 +3164,9 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, } uint flags= key_part->field ? key_part->field->flags : 0; const char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES"); - table->field[12]->store(pos, strlen(pos), cs); + table->field[12]->store(pos, (uint) strlen(pos), cs); pos= show_table->file->index_type(i); - table->field[13]->store(pos, strlen(pos), cs); + table->field[13]->store(pos, (uint) strlen(pos), cs); if (!show_table->s->keys_in_use.is_set(i)) table->field[14]->store(STRING_WITH_LEN("disabled"), cs); else @@ -3267,7 +3282,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, table->field[5]->store(STRING_WITH_LEN("YES"), cs); else table->field[5]->store(STRING_WITH_LEN("NO"), cs); - definer_len= (strxmov(definer, tables->definer.user.str, "@", + definer_len= (uint) (strxmov(definer, tables->definer.user.str, "@", tables->definer.host.str, NullS) - definer); table->field[6]->store(definer, definer_len, cs); if (tables->view_suid) @@ -3292,10 +3307,10 @@ bool store_constraints(THD *thd, TABLE *table, const char *db, { CHARSET_INFO *cs= system_charset_info; restore_record(table, s->default_values); - table->field[1]->store(db, strlen(db), cs); + table->field[1]->store(db, (uint) strlen(db), cs); table->field[2]->store(key_name, key_len, cs); - table->field[3]->store(db, strlen(db), cs); - table->field[4]->store(tname, strlen(tname), cs); + table->field[3]->store(db, (uint) strlen(db), cs); + table->field[4]->store(tname, (uint) strlen(tname), cs); table->field[5]->store(con_type, con_len, cs); return schema_table_store_record(thd, table); } @@ -3332,14 +3347,14 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, if (i == primary_key && !strcmp(key_info->name, primary_key_name)) { if (store_constraints(thd, table, base_name, file_name, key_info->name, - strlen(key_info->name), + (uint) strlen(key_info->name), STRING_WITH_LEN("PRIMARY KEY"))) DBUG_RETURN(1); } else if (key_info->flags & HA_NOSAME) { if (store_constraints(thd, table, base_name, file_name, key_info->name, - strlen(key_info->name), + (uint) strlen(key_info->name), STRING_WITH_LEN("UNIQUE"))) DBUG_RETURN(1); } @@ -3352,7 +3367,7 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, { if (store_constraints(thd, table, base_name, file_name, f_key_info->forein_id->str, - strlen(f_key_info->forein_id->str), + (uint) strlen(f_key_info->forein_id->str), "FOREIGN KEY", 11)) DBUG_RETURN(1); } @@ -3374,12 +3389,12 @@ static bool store_trigger(THD *thd, TABLE *table, const char *db, ulong sql_mode_len; restore_record(table, s->default_values); - table->field[1]->store(db, strlen(db), cs); + table->field[1]->store(db, (uint) strlen(db), cs); table->field[2]->store(trigger_name->str, trigger_name->length, cs); table->field[3]->store(trg_event_type_names[event].str, trg_event_type_names[event].length, cs); - table->field[5]->store(db, strlen(db), cs); - table->field[6]->store(tname, strlen(tname), cs); + table->field[5]->store(db, (uint) strlen(db), cs); + table->field[6]->store(tname, (uint) strlen(tname), cs); table->field[9]->store(trigger_stmt->str, trigger_stmt->length, cs); table->field[10]->store(STRING_WITH_LEN("ROW"), cs); table->field[11]->store(trg_action_time_type_names[timing].str, @@ -3463,10 +3478,10 @@ void store_key_column_usage(TABLE *table, const char*db, const char *tname, const char *con_type, uint con_len, longlong idx) { CHARSET_INFO *cs= system_charset_info; - table->field[1]->store(db, strlen(db), cs); + table->field[1]->store(db, (uint) strlen(db), cs); table->field[2]->store(key_name, key_len, cs); - table->field[4]->store(db, strlen(db), cs); - table->field[5]->store(tname, strlen(tname), cs); + table->field[4]->store(db, (uint) strlen(db), cs); + table->field[5]->store(tname, (uint) strlen(tname), cs); table->field[6]->store(con_type, con_len, cs); table->field[7]->store((longlong) idx, TRUE); } @@ -3510,9 +3525,9 @@ static int get_schema_key_column_usage_record(THD *thd, restore_record(table, s->default_values); store_key_column_usage(table, base_name, file_name, key_info->name, - strlen(key_info->name), + (uint) strlen(key_info->name), key_part->field->field_name, - strlen(key_part->field->field_name), + (uint) strlen(key_part->field->field_name), (longlong) f_idx); if (schema_table_store_record(thd, table)) DBUG_RETURN(1); @@ -3576,8 +3591,8 @@ int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond) for (; open_list ; open_list=open_list->next) { restore_record(table, s->default_values); - table->field[0]->store(open_list->db, strlen(open_list->db), cs); - table->field[1]->store(open_list->table, strlen(open_list->table), cs); + table->field[0]->store(open_list->db, (uint) strlen(open_list->db), cs); + table->field[1]->store(open_list->table, (uint) strlen(open_list->table), cs); table->field[2]->store((longlong) open_list->in_use, TRUE); table->field[3]->store((longlong) open_list->locked, TRUE); if (schema_table_store_record(thd, table)) @@ -3733,7 +3748,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) DBUG_RETURN(0); } item->set_name(fields_info->field_name, - strlen(fields_info->field_name), cs); + (uint) strlen(fields_info->field_name), cs); break; } field_list.push_back(item); @@ -3786,7 +3801,7 @@ int make_old_format(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; @@ -3855,7 +3870,7 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) field= new Item_field(context, NullS, NullS, field_info->field_name); if (add_item_to_list(thd, field)) return 1; - field->set_name(field_info->old_name, strlen(field_info->old_name), + field->set_name(field_info->old_name, (uint) strlen(field_info->old_name), system_charset_info); } return 0; @@ -3881,7 +3896,7 @@ int make_columns_old_format(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; @@ -3906,7 +3921,7 @@ int make_character_sets_old_format(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; @@ -3931,7 +3946,7 @@ int make_proc_old_format(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; @@ -3977,7 +3992,7 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) table_list->schema_table_name, table_list->alias); table_list->table_name= (char*) table->s->table_name; - table_list->table_name_length= strlen(table->s->table_name); + table_list->table_name_length= (uint) strlen(table->s->table_name); table_list->table= table; table->next= thd->derived_tables; thd->derived_tables= table; @@ -4053,7 +4068,7 @@ int make_schema_select(THD *thd, SELECT_LEX *sel, make_lex_string(thd, &db, INFORMATION_SCHEMA_NAME.str, INFORMATION_SCHEMA_NAME.length, 0); make_lex_string(thd, &table, schema_table->table_name, - strlen(schema_table->table_name), 0); + (uint) strlen(schema_table->table_name), 0); if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */ !sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0), 0, 0, TL_READ, (List<String> *) 0, diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 75e47dd0c8e..e536fc10d51 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -71,25 +71,22 @@ bool String::realloc(uint32 alloc_length) char *new_ptr; if (alloced) { - if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME)))) - { - Ptr=new_ptr; - Alloced_length=len; - } - else - return TRUE; // Signal error + if (!(new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME)))) + return TRUE; // Signal error } else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME)))) { + if (str_length > len - 1) + str_length= 0; if (str_length) // Avoid bugs in memcpy on AIX memcpy(new_ptr,Ptr,str_length); new_ptr[str_length]=0; - Ptr=new_ptr; - Alloced_length=len; alloced=1; } else return TRUE; // Signal error + Ptr= new_ptr; + Alloced_length= len; } Ptr[alloc_length]=0; // This make other funcs shorter return FALSE; @@ -125,7 +122,7 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs) str_charset=cs; if (decimals >= NOT_FIXED_DEC) { - uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME + uint32 len= my_sprintf(buff,(buff, "%.15g",num));// Enough for a DATETIME return copy(buff, len, &my_charset_latin1, cs, &dummy_errors); } #ifdef HAVE_FCONVERT @@ -468,7 +465,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)); } @@ -677,7 +674,7 @@ void String::qs_append(const char *str, uint32 len) void String::qs_append(double d) { char *buff = Ptr + str_length; - str_length+= my_sprintf(buff, (buff, "%.14g", d)); + str_length+= my_sprintf(buff, (buff, "%.15g", d)); } void String::qs_append(double *d) @@ -1003,7 +1000,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 b57cd859f0f..79aa0b04335 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -66,8 +66,8 @@ static void set_tmp_file_path(char *buf, size_t bufsize, THD *thd); uint build_table_path(char *buff, size_t bufflen, const char *db, const char *table, const char *ext) { - strxnmov(buff, bufflen-1, mysql_data_home, "/", db, "/", table, ext, - NullS); + strxnmov(buff, (uint) (bufflen - 1), mysql_data_home, "/", db, "/", table, + ext, NullS); return unpack_filename(buff,buff); } @@ -2314,7 +2314,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM)); - result_code= HA_ADMIN_CORRUPT; + if (thd->net.last_errno == ER_NO_SUCH_TABLE) + /* A missing table is just issued as a failed command */ + result_code= HA_ADMIN_FAILED; + else + /* Default failure code is corrupt table */ + result_code= HA_ADMIN_CORRUPT; goto send_result; } @@ -2537,7 +2542,7 @@ send_result_message: case HA_ADMIN_WRONG_CHECKSUM: { protocol->store(STRING_WITH_LEN("note"), system_charset_info); - protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)), + protocol->store(ER(ER_VIEW_CHECKSUM), (uint) strlen(ER(ER_VIEW_CHECKSUM)), system_charset_info); break; } @@ -4443,7 +4448,7 @@ static bool check_engine(THD *thd, const char *table_name, static void set_tmp_file_path(char *buf, size_t bufsize, THD *thd) { - char *p= strnmov(buf, mysql_tmpdir, bufsize); + char *p= strnmov(buf, mysql_tmpdir, (uint) bufsize); my_snprintf(p, bufsize - (p - buf), "%s%lx_%lx_%x%s", tmp_file_prefix, current_pid, thd->thread_id, thd->tmp_table++, reg_ext); diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index d3b5289cd68..930e3601699 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -459,12 +459,12 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, strxnmov(dir_buff, FN_REFLEN, mysql_data_home, "/", tables->db, "/", NullS); dir.length= unpack_filename(dir_buff, dir_buff); dir.str= dir_buff; - file.length= strxnmov(file_buff, FN_REFLEN, tables->table_name, - triggers_file_ext, NullS) - file_buff; + file.length= (uint) (strxnmov(file_buff, FN_REFLEN, tables->table_name, + triggers_file_ext, NullS) - file_buff); file.str= file_buff; - trigname_file.length= strxnmov(trigname_buff, FN_REFLEN, + trigname_file.length= (uint) (strxnmov(trigname_buff, FN_REFLEN, lex->spname->m_name.str, - trigname_file_ext, NullS) - trigname_buff; + trigname_file_ext, NullS) - trigname_buff); trigname_file.str= trigname_buff; strxnmov(trigname_path, FN_REFLEN, dir_buff, trigname_buff, NullS); @@ -524,8 +524,8 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, definer_host= lex->definer->host; trg_definer->str= trg_definer_holder; - trg_definer->length= strxmov(trg_definer->str, definer_user.str, "@", - definer_host.str, NullS) - trg_definer->str; + trg_definer->length= (uint) (strxmov(trg_definer->str, definer_user.str, "@", + definer_host.str, NullS) - trg_definer->str); } else { @@ -559,9 +559,9 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, } stmt_query->append(thd->lex->stmt_definition_begin, - (char *) thd->lex->sphead->m_body_begin - + (uint) ((char *) thd->lex->sphead->m_body_begin - thd->lex->stmt_definition_begin + - thd->lex->sphead->m_body.length); + thd->lex->sphead->m_body.length)); trg_def->str= stmt_query->c_ptr(); trg_def->length= stmt_query->length(); @@ -651,8 +651,8 @@ static bool save_trigger_file(Table_triggers_list *triggers, const char *db, strxnmov(dir_buff, FN_REFLEN, mysql_data_home, "/", db, "/", NullS); dir.length= unpack_filename(dir_buff, dir_buff); dir.str= dir_buff; - file.length= strxnmov(file_buff, FN_REFLEN, table_name, triggers_file_ext, - NullS) - file_buff; + file.length= (uint) (strxnmov(file_buff, FN_REFLEN, table_name, triggers_file_ext, + NullS) - file_buff); file.str= file_buff; return sql_create_definition_file(&dir, &file, &triggers_file_type, @@ -960,7 +960,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, save_db.str= thd->db; save_db.length= thd->db_length; - thd->reset_db((char*) db, strlen(db)); + thd->reset_db((char*) db, (uint) strlen(db)); while ((trg_create_str= it++)) { trg_sql_mode= itm++; @@ -1153,8 +1153,8 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event, } else { - definer->length= strxmov(definer->str, body->m_definer_user.str, "@", - body->m_definer_host.str, NullS) - definer->str; + definer->length= (uint) (strxmov(definer->str, body->m_definer_user.str, "@", + body->m_definer_host.str, NullS) - definer->str); } DBUG_RETURN(0); @@ -1350,7 +1350,7 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd, /* Construct CREATE TRIGGER statement with new table name. */ buff.length(0); - before_on_len= on_table_name->str - def->str; + before_on_len= (uint) (on_table_name->str - def->str); buff.append(def->str, before_on_len); buff.append(STRING_WITH_LEN("ON ")); append_identifier(thd, &buff, new_table_name->str, new_table_name->length); @@ -1420,8 +1420,8 @@ Table_triggers_list::change_table_name_in_trignames(const char *db_name, while ((trigger= it_name++) != stopper) { - trigname_file.length= strxnmov(trigname_buff, FN_REFLEN, trigger->str, - trigname_file_ext, NullS) - trigname_buff; + trigname_file.length= (uint) (strxnmov(trigname_buff, FN_REFLEN, trigger->str, + trigname_file_ext, NullS) - trigname_buff); trigname_file.str= trigname_buff; trigname.trigger_table= *new_table_name; @@ -1482,8 +1482,8 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db, } if (table.triggers) { - LEX_STRING_WITH_INIT old_table_name(old_table, strlen(old_table)); - LEX_STRING_WITH_INIT new_table_name(new_table, strlen(new_table)); + LEX_STRING_WITH_INIT old_table_name(old_table, (uint) strlen(old_table)); + LEX_STRING_WITH_INIT new_table_name(new_table, (uint) strlen(new_table)); /* Since triggers should be in the same schema as their subject tables moving table with them between two schemas raises too many questions. diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 6520c1a661e..f1b16a627ac 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -182,7 +182,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_update.cc b/sql/sql_update.cc index ad7cb87514d..195a2beed88 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -775,7 +775,7 @@ reopen_tables: DBUG_RETURN(TRUE); } - tables_for_update= get_table_map(fields); + thd->table_map_for_update= tables_for_update= get_table_map(fields); /* Setup timestamp handling and locking mode diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 1a758f2aecc..bef3bc65e51 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -775,11 +775,11 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, } view->source.str= thd->query + thd->lex->create_view_select_start; - view->source.length= (char *)skip_rear_comments(thd->charset(), + view->source.length= (uint) ((char *)skip_rear_comments(thd->charset(), (char *)view->source.str, (char *)thd->query + thd->query_length) - - view->source.str; + view->source.str); view->file_version= 1; view->calc_md5(md5); if (!(view->md5.str= thd->memdup(md5, 32))) @@ -831,10 +831,10 @@ loop_out: mysql_data_home, view->db); unpack_filename(dir_buff, dir_buff); dir.str= dir_buff; - dir.length= strlen(dir_buff); + dir.length= (uint) strlen(dir_buff); file.str= file_buff; - file.length= (strxnmov(file_buff, FN_REFLEN, view->table_name, reg_ext, + file.length= (uint) (strxnmov(file_buff, FN_REFLEN, view->table_name, reg_ext, NullS) - file_buff); /* init timestamp */ if (!view->timestamp.str) @@ -848,7 +848,7 @@ loop_out: path.str= path_buff; fn_format(path_buff, file.str, dir.str, 0, MY_UNPACK_FILENAME); - path.length= strlen(path_buff); + path.length= (uint) strlen(path_buff); if (!access(path.str, F_OK)) { @@ -1828,7 +1828,7 @@ mysql_rename_view(THD *thd, (void) unpack_filename(view_path, view_path); pathstr.str= (char *)view_path; - pathstr.length= strlen(view_path); + pathstr.length= (uint) strlen(view_path); if ((parser= sql_parse_prepare(&pathstr, thd->mem_root, 1)) && is_equal(&view_type, parser->type())) @@ -1860,10 +1860,10 @@ mysql_rename_view(THD *thd, (void) unpack_filename(dir_buff, dir_buff); pathstr.str= (char*)dir_buff; - pathstr.length= strlen(dir_buff); + pathstr.length= (uint) strlen(dir_buff); file.str= file_buff; - file.length= (strxnmov(file_buff, FN_REFLEN, new_name, reg_ext, NullS) + file.length= (uint) (strxnmov(file_buff, FN_REFLEN, new_name, reg_ext, NullS) - file_buff); if (sql_create_definition_file(&pathstr, &file, view_file_type, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b08650ac4f7..04caaa7ad20 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7525,6 +7525,11 @@ drop: THD *thd= YYTHD; LEX *lex= thd->lex; sp_name *spname; + if ($4.str && check_db_name($4.str)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), $4.str); + MYSQL_YYABORT; + } if (lex->sphead) { my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"); diff --git a/sql/table.cc b/sql/table.cc index 3abd2c24c94..c559b4bb7fd 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -471,7 +471,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, for (count= 0; count < interval->count; count++) { char *val= (char*) interval->type_names[count]; - interval->type_lengths[count]= strlen(val); + interval->type_lengths[count]= (uint) strlen(val); } interval->type_lengths[count]= 0; } @@ -916,7 +916,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, the correct null_bytes can now be set, since bitfields have been taken into account */ - share->null_bytes= (null_pos - (uchar*) outparam->null_flags + + share->null_bytes= (uint) (null_pos - (uchar*) outparam->null_flags + (null_bit_pos + 7) / 8); share->last_null_bit_pos= null_bit_pos; @@ -1792,11 +1792,8 @@ void st_table::reset_item_list(List<Item> *item_list) const void TABLE_LIST::calc_md5(char *buffer) { - my_MD5_CTX context; uchar digest[16]; - my_MD5Init(&context); - my_MD5Update(&context,(uchar *) query.str, query.length); - my_MD5Final(digest, &context); + MY_MD5_HASH(digest, (uchar *) query.str, query.length); sprintf((char *) buffer, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", digest[0], digest[1], digest[2], digest[3], @@ -3000,8 +2997,8 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_ /* The field belongs to a merge view or information schema table. */ Field_translator *translated_field= view_field_it.field_translator(); nj_col= new Natural_join_column(translated_field, table_ref); - field_count= table_ref->field_translation_end - - table_ref->field_translation; + field_count= (uint) (table_ref->field_translation_end - + table_ref->field_translation); } else { diff --git a/sql/tztime.cc b/sql/tztime.cc index d3d952e3c1e..d73a1ca0111 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1871,6 +1871,12 @@ 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"); @@ -1914,7 +1920,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; } @@ -1943,8 +1950,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(); @@ -1981,18 +1988,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 " @@ -2005,9 +2012,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], (byte*)table->field[0]->ptr, 4); @@ -2040,14 +2047,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: " @@ -2055,9 +2062,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", @@ -2082,6 +2089,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= alloc_root(&tz_storage, @@ -2112,15 +2147,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 4ca6133da03..db48984eed8 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 7c197d2a2e9..a0d1beaf0f9 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -131,7 +131,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 + diff --git a/sql/unireg.cc b/sql/unireg.cc index f20d3e8cc6b..d658365abd0 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -63,8 +63,8 @@ static bool make_empty_rec(THD *thd, int file, enum db_type table_type, db_file Handler to use. May be zero, in which case we use create_info->db_type RETURN - 0 ok - 1 error + false ok + true error */ bool mysql_create_frm(THD *thd, my_string file_name, @@ -119,7 +119,7 @@ bool mysql_create_frm(THD *thd, my_string file_name, /* Calculate extra data segment length */ str_db_type.str= (char *) ha_get_storage_engine(create_info->db_type); - str_db_type.length= strlen(str_db_type.str); + str_db_type.length= (uint) strlen(str_db_type.str); create_info->extra_size= (2 + str_db_type.length + 2 + create_info->connect_string.length); |