diff options
Diffstat (limited to 'sql/item_strfunc.cc')
-rw-r--r-- | sql/item_strfunc.cc | 539 |
1 files changed, 308 insertions, 231 deletions
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index f5a8a649ac2..5bdd3e10069 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2009, 2019, MariaDB Corporation + Copyright (c) 2009, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,7 +31,7 @@ #pragma implementation // gcc: Class implementation #endif -#include <my_global.h> // HAVE_* +#include "mariadb.h" // HAVE_* #include "sql_priv.h" /* @@ -58,6 +58,27 @@ C_MODE_END size_t username_char_length= 80; + +class Repeat_count +{ + ulonglong m_count; +public: + Repeat_count(Item *item) + :m_count(0) + { + Longlong_hybrid nr= item->to_longlong_hybrid(); + if (!item->null_value && !nr.neg()) + { + // Assume that the maximum length of a String is < INT_MAX32 + m_count= (ulonglong) nr.value(); + if (m_count > (ulonglong) INT_MAX32) + m_count= (ulonglong) INT_MAX32; + } + } + ulonglong count() const { return m_count; } +}; + + /* For the Items which have only val_str_ascii() method and don't have their own "native" val_str(), @@ -463,7 +484,7 @@ String *Item_func_from_base64::val_str(String *str) THD *thd= current_thd; push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_BAD_BASE64_DATA, ER_THD(thd, ER_BAD_BASE64_DATA), - end_ptr - res->ptr()); + (int) (end_ptr - res->ptr())); goto err; } @@ -533,14 +554,14 @@ String *Item_func_decode_histogram::val_str(String *str) DBUG_ASSERT(0); } /* show delta with previous value */ - int size= my_snprintf(numbuf, sizeof(numbuf), + size_t size= my_snprintf(numbuf, sizeof(numbuf), representation_by_type[type], val - prev); str->append(numbuf, size); str->append(","); prev= val; } /* show delta with max */ - int size= my_snprintf(numbuf, sizeof(numbuf), + size_t size= my_snprintf(numbuf, sizeof(numbuf), representation_by_type[type], 1.0 - prev); str->append(numbuf, size); @@ -607,23 +628,45 @@ String *Item_func_concat::val_str(String *str) for (uint i= 1 ; i < arg_count ; i++) { - uint concat_len; - if (!(res= args[i]->val_str(&tmp_value))) + if (!(res= args[i]->val_str(&tmp_value)) || + append_value(thd, str, res)) goto null; - if (res->length() == 0) + } + + str->set_charset(collation.collation); + return str; + +null: + null_value= true; + return 0; +} + + +String *Item_func_concat_operator_oracle::val_str(String *str) +{ + DBUG_ASSERT(fixed == 1); + THD *thd= current_thd; + String *res= NULL; + uint i; + + null_value=0; + // Search first non null argument + for (i= 0; i < arg_count; i++) + { + if ((res= args[i]->val_str(str))) + break; + } + if (!res) + goto null; + + if (res != str) + str->copy(res->ptr(), res->length(), res->charset()); + + for (i++ ; i < arg_count ; i++) + { + if (!(res= args[i]->val_str(&tmp_value)) || res->length() == 0) continue; - if ((concat_len= str->length() + res->length()) > - thd->variables.max_allowed_packet) - { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_WARN_ALLOWED_PACKET_OVERFLOWED, - ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(), - thd->variables.max_allowed_packet); - goto null; - } - DBUG_ASSERT(!res->uses_buffer_owned_by(str)); - DBUG_ASSERT(!str->uses_buffer_owned_by(res)); - if (realloc_result(str, concat_len) || str->append(*res)) + if (append_value(thd, str, res)) goto null; } @@ -631,11 +674,29 @@ String *Item_func_concat::val_str(String *str) return str; null: - null_value=1; + null_value= true; return 0; } +bool Item_func_concat::append_value(THD *thd, String *res, const String *app) +{ + uint concat_len; + if ((concat_len= res->length() + app->length()) > + thd->variables.max_allowed_packet) + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_WARN_ALLOWED_PACKET_OVERFLOWED, + ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(), + thd->variables.max_allowed_packet); + return true; + } + DBUG_ASSERT(!res->uses_buffer_owned_by(app)); + DBUG_ASSERT(!app->uses_buffer_owned_by(res)); + return realloc_result(res, concat_len) || res->append(*app); +} + + bool Item_func_concat::fix_length_and_dec() { ulonglong char_length= 0; @@ -1072,7 +1133,8 @@ String *Item_func_reverse::val_str(String *str) bool Item_func_reverse::fix_length_and_dec() { - agg_arg_charsets_for_string_result(collation, args, 1); + if (agg_arg_charsets_for_string_result(collation, args, 1)) + return TRUE; DBUG_ASSERT(collation.collation != NULL); fix_char_length(args[0]->max_char_length()); return FALSE; @@ -1087,7 +1149,8 @@ bool Item_func_reverse::fix_length_and_dec() Fix that this works with binary strings when using USE_MB */ -String *Item_func_replace::val_str(String *str) +String *Item_func_replace::val_str_internal(String *str, + String *empty_string_for_null) { DBUG_ASSERT(fixed == 1); String *res,*res2,*res3; @@ -1107,8 +1170,11 @@ String *Item_func_replace::val_str(String *str) goto null; res2=args[1]->val_str(&tmp_value); if (args[1]->null_value) - goto null; - + { + if (!empty_string_for_null) + goto null; + res2= empty_string_for_null; + } res->set_charset(collation.collation); #ifdef USE_MB @@ -1126,7 +1192,11 @@ String *Item_func_replace::val_str(String *str) return res; #endif if (!(res3=args[2]->val_str(&tmp_value2))) - goto null; + { + if (!empty_string_for_null) + goto null; + res3= empty_string_for_null; + } from_length= res2->length(); to_length= res3->length(); @@ -1209,6 +1279,9 @@ redo: } while ((offset=res->strstr(*res2,(uint) offset)) >= 0); } + if (empty_string_for_null && !res->length()) + goto null; + return res; null: @@ -1518,7 +1591,7 @@ String *Item_str_conv::val_str(String *str) { DBUG_ASSERT(fixed == 1); String *res; - uint alloced_length, len; + size_t alloced_length, len; if ((null_value= (!(res= args[0]->val_str(&tmp_value)) || str->alloc((alloced_length= res->length() * multiply))))) @@ -1583,13 +1656,10 @@ String *Item_func_left::val_str(String *str) void Item_str_func::left_right_max_length() { uint32 char_length= args[0]->max_char_length(); - if (args[1]->const_item()) + if (args[1]->const_item() && !args[1]->is_expensive()) { - int length= (int) args[1]->val_int(); - if (args[1]->null_value || length <= 0) - char_length=0; - else - set_if_smaller(char_length, (uint) length); + Repeat_count tmp(args[1]); + set_if_smaller(char_length, (uint) tmp.count()); } fix_char_length(char_length); } @@ -1646,7 +1716,7 @@ String *Item_func_substr::val_str(String *str) DBUG_ASSERT(fixed == 1); String *res = args[0]->val_str(str); /* must be longlong to avoid truncation */ - longlong start= args[1]->val_int(); + longlong start= get_position(); /* Assumes that the maximum length of a String is < INT_MAX32. */ /* Limit so that code sees out-of-bound value properly. */ longlong length= arg_count == 3 ? args[2]->val_int() : INT_MAX32; @@ -1697,7 +1767,7 @@ bool Item_func_substr::fix_length_and_dec() DBUG_ASSERT(collation.collation != NULL); if (args[1]->const_item()) { - int32 start= (int32) args[1]->val_int(); + int32 start= (int32) get_position(); if (args[1]->null_value) max_length= 0; else if (start < 0) @@ -2093,6 +2163,7 @@ void Item_func_trim::print(String *str, enum_query_type query_type) return; } str->append(Item_func_trim::func_name()); + str->append(func_name_ext()); str->append('('); str->append(mode_name()); str->append(' '); @@ -2201,9 +2272,8 @@ char *Item_func_password::alloc(THD *thd, const char *password, String *Item_func_encrypt::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res =args[0]->val_str(str); - #ifdef HAVE_CRYPT + String *res =args[0]->val_str(str); char salt[3],*salt_ptr; if ((null_value=args[0]->null_value)) return 0; @@ -2309,18 +2379,37 @@ String *Item_func_database::val_str(String *str) { DBUG_ASSERT(fixed == 1); THD *thd= current_thd; - if (thd->db == NULL) + if (thd->db.str == NULL) { null_value= 1; return 0; } else - str->copy(thd->db, thd->db_length, system_charset_info); + str->copy(thd->db.str, thd->db.length, system_charset_info); null_value= 0; return str; } +String *Item_func_sqlerrm::val_str(String *str) +{ + DBUG_ASSERT(fixed); + DBUG_ASSERT(!null_value); + Diagnostics_area::Sql_condition_iterator it= + current_thd->get_stmt_da()->sql_conditions(); + const Sql_condition *err; + if ((err= it++)) + { + str->copy(err->get_message_text(), err->get_message_octet_length(), + system_charset_info); + return str; + } + str->copy(STRING_WITH_LEN("normal, successful completion"), + system_charset_info); + return str; +} + + /** @note USER() is replicated correctly if binlog_format=ROW or (as of BUG#28086) binlog_format=MIXED, but is incorrectly replicated to '' @@ -2414,7 +2503,8 @@ bool Item_func_current_role::fix_fields(THD *thd, Item **ref) bool Item_func_soundex::fix_length_and_dec() { uint32 char_length= args[0]->max_char_length(); - agg_arg_charsets_for_string_result(collation, args, 1); + if (agg_arg_charsets_for_string_result(collation, args, 1)) + return TRUE; DBUG_ASSERT(collation.collation != NULL); set_if_bigger(char_length, 4); fix_char_length(char_length); @@ -2576,24 +2666,6 @@ String *Item_func_soundex::val_str(String *str) const int FORMAT_MAX_DECIMALS= 30; -MY_LOCALE *Item_func_format::get_locale(Item *item) -{ - DBUG_ASSERT(arg_count == 3); - String tmp, *locale_name= args[2]->val_str_ascii(&tmp); - MY_LOCALE *lc; - if (!locale_name || - !(lc= my_locale_by_name(locale_name->c_ptr_safe()))) - { - THD *thd= current_thd; - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_UNKNOWN_LOCALE, - ER_THD(thd, ER_UNKNOWN_LOCALE), - locale_name ? locale_name->c_ptr_safe() : "NULL"); - lc= &my_locale_en_US; - } - return lc; -} - bool Item_func_format::fix_length_and_dec() { uint32 char_length= args[0]->max_char_length(); @@ -2601,7 +2673,7 @@ bool Item_func_format::fix_length_and_dec() collation.set(default_charset()); fix_char_length(char_length + max_sep_count + decimals); if (arg_count == 3) - locale= args[2]->basic_const_item() ? get_locale(args[2]) : NULL; + locale= args[2]->basic_const_item() ? args[2]->locale_from_val_str() : NULL; else locale= &my_locale_en_US; /* Two arguments */ return FALSE; @@ -2621,7 +2693,7 @@ String *Item_func_format::val_str_ascii(String *str) int dec; /* Number of characters used to represent the decimals, including '.' */ uint32 dec_length; - MY_LOCALE *lc; + const MY_LOCALE *lc; DBUG_ASSERT(fixed == 1); dec= (int) args[1]->val_int(); @@ -2631,7 +2703,7 @@ String *Item_func_format::val_str_ascii(String *str) return NULL; } - lc= locale ? locale : get_locale(args[2]); + lc= locale ? locale : args[2]->locale_from_val_str(); dec= set_zone(dec, 0, FORMAT_MAX_DECIMALS); dec_length= dec ? dec+1 : 0; @@ -2854,7 +2926,7 @@ void Item_func_char::print(String *str, enum_query_type query_type) print_args(str, 0, query_type); if (collation.collation != &my_charset_bin) { - str->append(C_STRING_WITH_LEN(" using ")); + str->append(STRING_WITH_LEN(" using ")); str->append(collation.collation->csname); } str->append(')'); @@ -2870,29 +2942,51 @@ String *Item_func_char::val_str(String *str) { int32 num=(int32) args[i]->val_int(); if (!args[i]->null_value) - { - char tmp[4]; - if (num & 0xFF000000L) - { - mi_int4store(tmp, num); - str->append(tmp, 4, &my_charset_bin); - } - else if (num & 0xFF0000L) - { - mi_int3store(tmp, num); - str->append(tmp, 3, &my_charset_bin); - } - else if (num & 0xFF00L) - { - mi_int2store(tmp, num); - str->append(tmp, 2, &my_charset_bin); - } - else - { - tmp[0]= (char) num; - str->append(tmp, 1, &my_charset_bin); - } - } + append_char(str, num); + } + str->realloc(str->length()); // Add end 0 (for Purify) + return check_well_formed_result(str); +} + + +void Item_func_char::append_char(String *str, int32 num) +{ + char tmp[4]; + if (num & 0xFF000000L) + { + mi_int4store(tmp, num); + str->append(tmp, 4, &my_charset_bin); + } + else if (num & 0xFF0000L) + { + mi_int3store(tmp, num); + str->append(tmp, 3, &my_charset_bin); + } + else if (num & 0xFF00L) + { + mi_int2store(tmp, num); + str->append(tmp, 2, &my_charset_bin); + } + else + { + tmp[0]= (char) num; + str->append(tmp, 1, &my_charset_bin); + } +} + + +String *Item_func_chr::val_str(String *str) +{ + DBUG_ASSERT(fixed == 1); + str->length(0); + str->set_charset(collation.collation); + int32 num=(int32) args[0]->val_int(); + if (!args[0]->null_value) + append_char(str, num); + else + { + null_value= 1; + return 0; } str->realloc(str->length()); // Add end 0 (for Purify) return check_well_formed_result(str); @@ -2926,27 +3020,16 @@ bool Item_func_repeat::fix_length_and_dec() if (agg_arg_charsets_for_string_result(collation, args, 1)) return TRUE; DBUG_ASSERT(collation.collation != NULL); - if (args[1]->const_item()) + if (args[1]->const_item() && !args[1]->is_expensive()) { - /* must be longlong to avoid truncation */ - longlong count= args[1]->val_int(); - - /* Assumes that the maximum length of a String is < INT_MAX32. */ - /* Set here so that rest of code sees out-of-bound value as such. */ - if (args[1]->null_value) - count= 0; - else if (count > INT_MAX32) - count= INT_MAX32; - - ulonglong char_length= (ulonglong) args[0]->max_char_length() * count; + Repeat_count tmp(args[1]); + ulonglong char_length= (ulonglong) args[0]->max_char_length() * tmp.count(); fix_char_length_ulonglong(char_length); + return false; } - else - { - max_length= MAX_BLOB_WIDTH; - maybe_null= 1; - } - return FALSE; + max_length= MAX_BLOB_WIDTH; + maybe_null= true; + return false; } /** @@ -3011,26 +3094,14 @@ err: bool Item_func_space::fix_length_and_dec() { collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); - if (args[0]->const_item()) + if (args[0]->const_item() && !args[0]->is_expensive()) { - /* must be longlong to avoid truncation */ - longlong count= args[0]->val_int(); - if (args[0]->null_value) - goto end; - /* - Assumes that the maximum length of a String is < INT_MAX32. - Set here so that rest of code sees out-of-bound value as such. - */ - if (count > INT_MAX32) - count= INT_MAX32; - fix_char_length_ulonglong(count); - return FALSE; + fix_char_length_ulonglong(Repeat_count(args[0]).count()); + return false; } - -end: max_length= MAX_BLOB_WIDTH; - maybe_null= 1; - return FALSE; + maybe_null= true; + return false; } @@ -3123,31 +3194,33 @@ err: bool Item_func_pad::fix_length_and_dec() { - String *str; - if (!args[2]->basic_const_item() || !(str= args[2]->val_str(&pad_str)) || !str->length()) - maybe_null= true; - - // Handle character set for args[0] and args[2]. - if (agg_arg_charsets_for_string_result(collation, &args[0], 2, 2)) - return TRUE; - if (args[1]->const_item()) + if (arg_count == 3) { - ulonglong char_length= (ulonglong) args[1]->val_int(); - DBUG_ASSERT(collation.collation->mbmaxlen > 0); - /* Assumes that the maximum length of a String is < INT_MAX32. */ - /* Set here so that rest of code sees out-of-bound value as such. */ - if (args[1]->null_value) - char_length= 0; - else if (char_length > INT_MAX32) - char_length= INT_MAX32; - fix_char_length_ulonglong(char_length); + String *str; + if (!args[2]->basic_const_item() || !(str= args[2]->val_str(&pad_str)) || !str->length()) + maybe_null= true; + // Handle character set for args[0] and args[2]. + if (agg_arg_charsets_for_string_result(collation, &args[0], 2, 2)) + return TRUE; } else { - max_length= MAX_BLOB_WIDTH; - maybe_null= 1; + if (agg_arg_charsets_for_string_result(collation, &args[0], 1, 1)) + return TRUE; + pad_str.set_charset(collation.collation); + pad_str.length(0); + pad_str.append(" ", 1); } - return FALSE; + + DBUG_ASSERT(collation.collation->mbmaxlen > 0); + if (args[1]->const_item() && !args[1]->is_expensive()) + { + fix_char_length_ulonglong(Repeat_count(args[1]).count()); + return false; + } + max_length= MAX_BLOB_WIDTH; + maybe_null= true; + return false; } @@ -3193,12 +3266,17 @@ String *Item_func_rpad::val_str(String *str) longlong count= args[1]->val_int(); longlong byte_count; String *res= args[0]->val_str(str); - String *rpad= args[2]->val_str(&pad_str); + String *rpad= arg_count == 2 ? &pad_str : args[2]->val_str(&pad_str); if (!res || args[1]->null_value || !rpad || ((count < 0) && !args[1]->unsigned_flag)) goto err; + null_value=0; + + if (count == 0) + return make_empty_result(); + /* Assumes that the maximum length of a String is < INT_MAX32. */ /* Set here so that rest of code sees out-of-bound value as such. */ if ((ulonglong) count > INT_MAX32) @@ -3222,7 +3300,6 @@ String *Item_func_rpad::val_str(String *str) res->length(res->charpos((int) count)); // Shorten result if longer return (res); } - pad_char_length= rpad->numchars(); byte_count= count * collation.collation->mbmaxlen; { @@ -3236,8 +3313,15 @@ String *Item_func_rpad::val_str(String *str) goto err; } } - if (args[2]->null_value || !pad_char_length) - goto err; + + if (arg_count == 3) + { + if (args[2]->null_value || !(pad_char_length= rpad->numchars())) + goto err; + } + else + pad_char_length= 1; // Implicit space + res_byte_length= res->length(); /* Must be done before alloc_buffer */ if (!(res= alloc_buffer(res,str,&tmp_value, (ulong) byte_count))) goto err; @@ -3274,12 +3358,17 @@ String *Item_func_lpad::val_str(String *str) longlong count= args[1]->val_int(); longlong byte_count; String *res= args[0]->val_str(&tmp_value); - String *pad= args[2]->val_str(&pad_str); + String *pad= arg_count == 2 ? &pad_str : args[2]->val_str(&pad_str); if (!res || args[1]->null_value || !pad || ((count < 0) && !args[1]->unsigned_flag)) goto err; + null_value=0; + + if (count == 0) + return make_empty_result(); + /* Assumes that the maximum length of a String is < INT_MAX32. */ /* Set here so that rest of code sees out-of-bound value as such. */ if ((ulonglong) count > INT_MAX32) @@ -3307,7 +3396,6 @@ String *Item_func_lpad::val_str(String *str) return res; } - pad_char_length= pad->numchars(); byte_count= count * collation.collation->mbmaxlen; { @@ -3322,9 +3410,16 @@ String *Item_func_lpad::val_str(String *str) } } - if (args[2]->null_value || !pad_char_length || - str->alloc((uint32) byte_count)) + if (str->alloc((uint32) byte_count)) goto err; + + if (arg_count == 3) + { + if (args[2]->null_value || !(pad_char_length= pad->numchars())) + goto err; + } + else + pad_char_length= 1; // Implicit space str->length(0); str->set_charset(collation.collation); @@ -3440,27 +3535,13 @@ String *Item_func_set_collation::val_str(String *str) bool Item_func_set_collation::fix_length_and_dec() { - CHARSET_INFO *set_collation; - const char *colname; - String tmp, *str= args[1]->val_str(&tmp); - colname= str->c_ptr(); - if (colname == binary_keyword) - set_collation= get_charset_by_csname(args[0]->collation.collation->csname, - MY_CS_BINSORT,MYF(0)); - else - { - if (!(set_collation= mysqld_collation_get_by_name(colname))) - return TRUE; - } - - if (!set_collation || - !my_charset_same(args[0]->collation.collation,set_collation)) + if (!my_charset_same(args[0]->collation.collation, m_set_collation)) { my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), - colname, args[0]->collation.collation->csname); + m_set_collation->name, args[0]->collation.collation->csname); return TRUE; } - collation.set(set_collation, DERIVATION_EXPLICIT, + collation.set(m_set_collation, DERIVATION_EXPLICIT, args[0]->collation.repertoire); max_length= args[0]->max_length; return FALSE; @@ -3469,22 +3550,8 @@ bool Item_func_set_collation::fix_length_and_dec() bool Item_func_set_collation::eq(const Item *item, bool binary_cmp) const { - /* Assume we don't have rtti */ - if (this == item) - return 1; - if (item->type() != FUNC_ITEM) - return 0; - Item_func *item_func=(Item_func*) item; - if (arg_count != item_func->argument_count() || - functype() != item_func->functype()) - return 0; - Item_func_set_collation *item_func_sc=(Item_func_set_collation*) item; - if (collation.collation != item_func_sc->collation.collation) - return 0; - for (uint i=0; i < arg_count ; i++) - if (!args[i]->eq(item_func_sc->args[i], binary_cmp)) - return 0; - return 1; + return Item_func::eq(item, binary_cmp) && + collation.collation == item->collation.collation; } @@ -3492,9 +3559,7 @@ void Item_func_set_collation::print(String *str, enum_query_type query_type) { args[0]->print_parenthesised(str, query_type, precedence()); str->append(STRING_WITH_LEN(" collate ")); - DBUG_ASSERT(args[1]->basic_const_item() && - args[1]->type() == Item::STRING_ITEM); - ((Item_string *)args[1])->print_value(str); + str->append(m_set_collation->name); } String *Item_func_charset::val_str(String *str) @@ -3534,10 +3599,10 @@ bool Item_func_weight_string::fix_length_and_dec() */ if (!(max_length= result_length)) { - uint char_length; + size_t char_length; char_length= ((cs->state & MY_CS_STRNXFRM_BAD_NWEIGHTS) || !nweights) ? args[0]->max_char_length() : nweights * cs->levels_for_order; - max_length= cs->coll->strnxfrmlen(cs, char_length * cs->mbmaxlen); + max_length= (uint32)cs->coll->strnxfrmlen(cs, char_length * cs->mbmaxlen); } maybe_null= 1; return FALSE; @@ -3549,7 +3614,7 @@ String *Item_func_weight_string::val_str(String *str) { String *res; CHARSET_INFO *cs= args[0]->collation.collation; - uint tmp_length, frm_length; + size_t tmp_length, frm_length; DBUG_ASSERT(fixed == 1); if (args[0]->result_type() != STRING_RESULT || @@ -3563,7 +3628,7 @@ String *Item_func_weight_string::val_str(String *str) */ if (!(tmp_length= result_length)) { - uint char_length; + size_t char_length; if (cs->state & MY_CS_STRNXFRM_BAD_NWEIGHTS) { /* @@ -3609,7 +3674,7 @@ String *Item_func_weight_string::val_str(String *str) frm_length= cs->coll->strnxfrm(cs, (uchar *) str->ptr(), tmp_length, - nweights ? nweights : tmp_length, + nweights ? nweights : (uint)tmp_length, (const uchar *) res->ptr(), res->length(), flags); DBUG_ASSERT(frm_length <= tmp_length); @@ -3639,53 +3704,41 @@ void Item_func_weight_string::print(String *str, enum_query_type query_type) } -String *Item_func_hex::val_str_ascii(String *str) +String *Item_func_hex::val_str_ascii_from_val_real(String *str) { - String *res; - DBUG_ASSERT(fixed == 1); - if (args[0]->result_type() != STRING_RESULT) - { - ulonglong dec; - char ans[65],*ptr; - /* Return hex of unsigned longlong value */ - if (args[0]->result_type() == REAL_RESULT || - args[0]->result_type() == DECIMAL_RESULT) - { - double val= args[0]->val_real(); - if ((val <= (double) LONGLONG_MIN) || - (val >= (double) (ulonglong) ULONGLONG_MAX)) - dec= ~(longlong) 0; - else - dec= (ulonglong) (val + (val > 0 ? 0.5 : -0.5)); - } - else - dec= (ulonglong) args[0]->val_int(); + ulonglong dec; + double val= args[0]->val_real(); + if ((null_value= args[0]->null_value)) + return 0; + if ((val <= (double) LONGLONG_MIN) || + (val >= (double) (ulonglong) ULONGLONG_MAX)) + dec= ~(longlong) 0; + else + dec= (ulonglong) (val + (val > 0 ? 0.5 : -0.5)); + return str->set_hex(dec) ? make_empty_result() : str; +} - if ((null_value= args[0]->null_value)) - return 0; - - if (!(ptr= longlong2str(dec, ans, 16)) || - str->copy(ans,(uint32) (ptr - ans), - &my_charset_numeric)) - return make_empty_result(); // End of memory - return str; - } - /* Convert given string to a hex string, character by character */ - res= args[0]->val_str(&tmp_value); - if (!res || str->alloc(res->length()*2+1)) - { - null_value=1; - return 0; - } - null_value=0; - str->length(res->length()*2); - str->set_charset(&my_charset_latin1); +String *Item_func_hex::val_str_ascii_from_val_str(String *str) +{ + DBUG_ASSERT(&tmp_value != str); + String *res= args[0]->val_str(&tmp_value); + DBUG_ASSERT(res != str); + if ((null_value= (res == NULL))) + return NULL; + return str->set_hex(res->ptr(), res->length()) ? make_empty_result() : str; +} - octet2hex((char*) str->ptr(), res->ptr(), res->length()); - return str; + +String *Item_func_hex::val_str_ascii_from_val_int(String *str) +{ + ulonglong dec= (ulonglong) args[0]->val_int(); + if ((null_value= args[0]->null_value)) + return 0; + return str->set_hex(dec) ? make_empty_result() : str; } + /** Convert given hex string to a binary string. */ String *Item_func_unhex::val_str(String *str) @@ -4444,6 +4497,9 @@ bool Item_func_dyncol_create::prepare_arguments(THD *thd, bool force_names_arg) case MYSQL_TYPE_GEOMETRY: type= DYN_COL_STRING; break; + case MYSQL_TYPE_VARCHAR_COMPRESSED: + case MYSQL_TYPE_BLOB_COMPRESSED: + DBUG_ASSERT(0); } } if (type == DYN_COL_STRING && @@ -4963,7 +5019,7 @@ longlong Item_dyncol_get::val_int() char *end= val.x.string.value.str + val.x.string.value.length, *org_end= end; num= my_strtoll10(val.x.string.value.str, &end, &error); - if (end != org_end || error > 0) + if (unlikely(end != org_end || error > 0)) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_BAD_DATA, @@ -5249,3 +5305,24 @@ null: my_free(names); return NULL; } + +Item_temptable_rowid::Item_temptable_rowid(TABLE *table_arg) + : Item_str_func(table_arg->in_use), table(table_arg) +{ + max_length= table->file->ref_length; +} + +bool Item_temptable_rowid::fix_length_and_dec() +{ + used_tables_cache= table->map; + const_item_cache= false; + return FALSE; +} + +String *Item_temptable_rowid::val_str(String *str) +{ + if (!((null_value= table->null_row))) + table->file->position(table->record[0]); + str_value.set((char*)(table->file->ref), max_length, &my_charset_bin); + return &str_value; +} |