diff options
author | Sergei Golubchik <serg@mariadb.org> | 2017-07-05 19:08:55 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2017-07-05 19:08:55 +0200 |
commit | f6633bf058802ad7da8196d01fd19d75c53f7274 (patch) | |
tree | b7ba9832aae2a3d0c72d2bf3d89cf2a5f13a44f6 /sql/item_strfunc.cc | |
parent | fc5932a1b733b331be20c3f1b45c61c798227dba (diff) | |
parent | e555540ab6b9c3e0d4fdd00af093b115a9401d0a (diff) | |
download | mariadb-git-f6633bf058802ad7da8196d01fd19d75c53f7274.tar.gz |
Merge branch '10.1' into 10.2
Diffstat (limited to 'sql/item_strfunc.cc')
-rw-r--r-- | sql/item_strfunc.cc | 230 |
1 files changed, 130 insertions, 100 deletions
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index e91cf64fd04..3c2b2374f1e 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -66,8 +66,14 @@ size_t username_char_length= 80; Conversion happens only in case of "tricky" Item character set (e.g. UCS2). Normally conversion does not happen, and val_str_ascii() is immediately returned instead. + + No matter if conversion is needed or not needed, + the result is always returned in "str" (see MDEV-10306 why). + + @param [OUT] str - Store the result here + @param [IN] ascii_buffer - Use this temporary buffer to call val_str_ascii() */ -String *Item_func::val_str_from_val_str_ascii(String *str, String *str2) +String *Item_func::val_str_from_val_str_ascii(String *str, String *ascii_buffer) { DBUG_ASSERT(fixed == 1); @@ -79,19 +85,19 @@ String *Item_func::val_str_from_val_str_ascii(String *str, String *str2) return res; } - DBUG_ASSERT(str != str2); + DBUG_ASSERT(str != ascii_buffer); uint errors; - String *res= val_str_ascii(str); + String *res= val_str_ascii(ascii_buffer); if (!res) return 0; - if ((null_value= str2->copy(res->ptr(), res->length(), - &my_charset_latin1, collation.collation, - &errors))) + if ((null_value= str->copy(res->ptr(), res->length(), + &my_charset_latin1, collation.collation, + &errors))) return 0; - return str2; + return str; } @@ -307,11 +313,11 @@ void Item_aes_crypt::create_key(String *user_key, uchar *real_key) } -String *Item_aes_crypt::val_str(String *str) +String *Item_aes_crypt::val_str(String *str2) { DBUG_ASSERT(fixed == 1); StringBuffer<80> user_key_buf; - String *sptr= args[0]->val_str(str); + String *sptr= args[0]->val_str(&str_value); String *user_key= args[1]->val_str(&user_key_buf); uint32 aes_length; @@ -320,17 +326,17 @@ String *Item_aes_crypt::val_str(String *str) null_value=0; aes_length=my_aes_get_size(MY_AES_ECB, sptr->length()); - if (!str_value.alloc(aes_length)) // Ensure that memory is free + if (!str2->alloc(aes_length)) // Ensure that memory is free { uchar rkey[AES_KEY_LENGTH / 8]; create_key(user_key, rkey); if (!my_aes_crypt(MY_AES_ECB, what, (uchar*)sptr->ptr(), sptr->length(), - (uchar*)str_value.ptr(), &aes_length, + (uchar*)str2->ptr(), &aes_length, rkey, AES_KEY_LENGTH / 8, 0, 0)) { - str_value.length((uint) aes_length); - return &str_value; + str2->length((uint) aes_length); + return str2; } } } @@ -345,6 +351,7 @@ void Item_func_aes_encrypt::fix_length_and_dec() } + void Item_func_aes_decrypt::fix_length_and_dec() { max_length=args[0]->max_length; @@ -373,7 +380,7 @@ void Item_func_to_base64::fix_length_and_dec() String *Item_func_to_base64::val_str_ascii(String *str) { - String *res= args[0]->val_str(str); + String *res= args[0]->val_str(&tmp_value); bool too_long= false; int length; if (!res || @@ -381,7 +388,7 @@ String *Item_func_to_base64::val_str_ascii(String *str) (too_long= ((uint) (length= my_base64_needed_encoded_length((int) res->length())) > current_thd->variables.max_allowed_packet)) || - tmp_value.alloc((uint) length)) + str->alloc((uint) length)) { null_value= 1; // NULL input, too long input, or OOM. if (too_long) @@ -395,11 +402,11 @@ String *Item_func_to_base64::val_str_ascii(String *str) } return 0; } - my_base64_encode(res->ptr(), (int) res->length(), (char*) tmp_value.ptr()); + my_base64_encode(res->ptr(), (int) res->length(), (char*) str->ptr()); DBUG_ASSERT(length > 0); - tmp_value.length((uint) length - 1); // Without trailing '\0' + str->length((uint) length - 1); // Without trailing '\0' null_value= 0; - return &tmp_value; + return str; } @@ -420,7 +427,7 @@ void Item_func_from_base64::fix_length_and_dec() String *Item_func_from_base64::val_str(String *str) { - String *res= args[0]->val_str_ascii(str); + String *res= args[0]->val_str_ascii(&tmp_value); int length; const char *end_ptr; @@ -440,11 +447,11 @@ String *Item_func_from_base64::val_str(String *str) goto err; } - if (tmp_value.alloc((uint) length)) + if (str->alloc((uint) length)) goto err; if ((length= my_base64_decode(res->ptr(), (int) res->length(), - (char *) tmp_value.ptr(), &end_ptr, 0)) < 0 || + (char *) str->ptr(), &end_ptr, 0)) < 0 || end_ptr < res->ptr() + res->length()) { THD *thd= current_thd; @@ -454,9 +461,9 @@ String *Item_func_from_base64::val_str(String *str) goto err; } - tmp_value.length((uint) length); + str->length((uint) length); null_value= 0; - return &tmp_value; + return str; err: null_value= 1; // NULL input, too long input, OOM, or badly formed input return 0; @@ -712,7 +719,7 @@ String *Item_func_des_encrypt::val_str(String *str) struct st_des_keyschedule keyschedule; const char *append_str="********"; uint key_number, res_length, tail; - String *res= args[0]->val_str(str); + String *res= args[0]->val_str(&tmp_value); if ((null_value= args[0]->null_value)) return 0; // ENCRYPT(NULL) == NULL @@ -736,7 +743,7 @@ String *Item_func_des_encrypt::val_str(String *str) } else { - String *keystr=args[1]->val_str(&tmp_value); + String *keystr= args[1]->val_str(str); if (!keystr) goto error; key_number=127; // User key string @@ -768,23 +775,23 @@ String *Item_func_des_encrypt::val_str(String *str) tmp_arg.length(0); tmp_arg.append(res->ptr(), res->length()); code= ER_OUT_OF_RESOURCES; - if (tmp_arg.append(append_str, tail) || tmp_value.alloc(res_length+1)) + if (tmp_arg.append(append_str, tail) || str->alloc(res_length+1)) goto error; tmp_arg[res_length-1]=tail; // save extra length - tmp_value.realloc(res_length+1); - tmp_value.length(res_length+1); - tmp_value.set_charset(&my_charset_bin); - tmp_value[0]=(char) (128 | key_number); + str->realloc(res_length+1); + str->length(res_length+1); + str->set_charset(&my_charset_bin); + (*str)[0]=(char) (128 | key_number); // Real encryption bzero((char*) &ivec,sizeof(ivec)); DES_ede3_cbc_encrypt((const uchar*) (tmp_arg.ptr()), - (uchar*) (tmp_value.ptr()+1), + (uchar*) (str->ptr()+1), res_length, &keyschedule.ks1, &keyschedule.ks2, &keyschedule.ks3, &ivec, TRUE); - return &tmp_value; + return str; error: THD *thd= current_thd; @@ -810,7 +817,7 @@ String *Item_func_des_decrypt::val_str(String *str) DES_cblock ivec; struct st_des_keyblock keyblock; struct st_des_keyschedule keyschedule; - String *res= args[0]->val_str(str); + String *res= args[0]->val_str(&tmp_value); uint length,tail; if ((null_value= args[0]->null_value)) @@ -834,7 +841,7 @@ String *Item_func_des_decrypt::val_str(String *str) else { // We make good 24-byte (168 bit) key from given plaintext key with MD5 - String *keystr=args[1]->val_str(&tmp_value); + String *keystr= args[1]->val_str(str); if (!keystr) goto error; @@ -849,23 +856,23 @@ String *Item_func_des_decrypt::val_str(String *str) DES_set_key_unchecked(&keyblock.key3,&keyschedule.ks3); } code= ER_OUT_OF_RESOURCES; - if (tmp_value.alloc(length-1)) + if (str->alloc(length-1)) goto error; bzero((char*) &ivec,sizeof(ivec)); DES_ede3_cbc_encrypt((const uchar*) res->ptr()+1, - (uchar*) (tmp_value.ptr()), + (uchar*) (str->ptr()), length-1, &keyschedule.ks1, &keyschedule.ks2, &keyschedule.ks3, &ivec, FALSE); /* Restore old length of key */ - if ((tail=(uint) (uchar) tmp_value[length-2]) > 8) + if ((tail=(uint) (uchar) (*str)[length-2]) > 8) goto wrong_key; // Wrong key - tmp_value.length(length-1-tail); - tmp_value.set_charset(&my_charset_bin); - return &tmp_value; + str->length(length-1-tail); + str->set_charset(&my_charset_bin); + return str; error: { @@ -1063,25 +1070,26 @@ void Item_func_concat_ws::fix_length_and_dec() String *Item_func_reverse::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res = args[0]->val_str(str); - char *ptr, *end, *tmp; + String *res= args[0]->val_str(&tmp_value); + const char *ptr, *end; + char *tmp; if ((null_value=args[0]->null_value)) return 0; /* An empty string is a special case as the string pointer may be null */ if (!res->length()) return make_empty_result(); - if (tmp_value.alloced_length() < res->length() && - tmp_value.realloc(res->length())) + if (str->alloced_length() < res->length() && + str->realloc(res->length())) { null_value= 1; return 0; } - tmp_value.length(res->length()); - tmp_value.set_charset(res->charset()); - ptr= (char *) res->ptr(); - end= ptr + res->length(); - tmp= (char *) tmp_value.ptr() + tmp_value.length(); + str->length(res->length()); + str->set_charset(res->charset()); + ptr= res->ptr(); + end= res->end(); + tmp= (char *) str->end(); #ifdef USE_MB if (use_mb(res->charset())) { @@ -1091,7 +1099,7 @@ String *Item_func_reverse::val_str(String *str) if ((l= my_ismbchar(res->charset(),ptr,end))) { tmp-= l; - DBUG_ASSERT(tmp >= tmp_value.ptr()); + DBUG_ASSERT(tmp >= str->ptr()); memcpy(tmp,ptr,l); ptr+= l; } @@ -1105,7 +1113,7 @@ String *Item_func_reverse::val_str(String *str) while (ptr < end) *--tmp= *ptr++; } - return &tmp_value; + return str; } @@ -2285,6 +2293,7 @@ String *Item_func_database::val_str(String *str) } else str->copy(thd->db, thd->db_length, system_charset_info); + null_value= 0; return str; } @@ -2319,6 +2328,28 @@ bool Item_func_user::init(const char *user, const char *host) } +Item *Item_func_sysconst::safe_charset_converter(THD *thd, CHARSET_INFO *tocs) +{ + /* + During view or prepared statement creation, the item should not + make use of const_charset_converter as it would imply substitution + with constant items which is not correct. Functions can have different + values during view creation and view execution based on context. + + Return the identical item during view creation and prepare. + */ + if (thd->lex->is_ps_or_view_context_analysis()) + return this; + return const_charset_converter(thd, tocs, true, fully_qualified_func_name()); +} + +bool Item_func_sysconst::const_item() const +{ + if (current_thd->lex->is_ps_or_view_context_analysis()) + return false; + return true; +} + bool Item_func_user::fix_fields(THD *thd, Item **ref) { return (Item_func_sysconst::fix_fields(thd, ref) || @@ -2344,15 +2375,13 @@ bool Item_func_current_role::fix_fields(THD *thd, Item **ref) Security_context *ctx= context && context->security_ctx ? context->security_ctx : thd->security_ctx; - if (ctx->priv_role[0]) { if (str_value.copy(ctx->priv_role, strlen(ctx->priv_role), system_charset_info)) return 1; - - null_value= maybe_null= 0; str_value.mark_as_const(); + null_value= maybe_null= 0; return 0; } null_value= maybe_null= 1; @@ -2366,7 +2395,6 @@ void Item_func_soundex::fix_length_and_dec() DBUG_ASSERT(collation.collation != NULL); set_if_bigger(char_length, 4); fix_char_length(char_length); - tmp_value.set_charset(collation.collation); } @@ -2411,7 +2439,7 @@ static bool my_uni_isalpha(int wc) String *Item_func_soundex::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res =args[0]->val_str(str); + String *res= args[0]->val_str(&tmp_value); char last_ch,ch; CHARSET_INFO *cs= collation.collation; my_wc_t wc; @@ -2421,10 +2449,11 @@ String *Item_func_soundex::val_str(String *str) if ((null_value= args[0]->null_value)) return 0; /* purecov: inspected */ - if (tmp_value.alloc(MY_MAX(res->length(), 4 * cs->mbminlen))) - return str; /* purecov: inspected */ - char *to= (char *) tmp_value.ptr(); - char *to_end= to + tmp_value.alloced_length(); + if (str->alloc(MY_MAX(res->length(), 4 * cs->mbminlen))) + return &tmp_value; /* purecov: inspected */ + str->set_charset(collation.collation); + char *to= (char *) str->ptr(); + char *to_end= to + str->alloced_length(); char *from= (char *) res->ptr(), *end= from + res->length(); for ( ; ; ) /* Skip pre-space */ @@ -2509,8 +2538,8 @@ String *Item_func_soundex::val_str(String *str) to+= nbytes; } - tmp_value.length((uint) (to-tmp_value.ptr())); - return &tmp_value; + str->length((uint) (to - str->ptr())); + return str; } @@ -3332,13 +3361,13 @@ String *Item_func_conv_charset::val_str(String *str) DBUG_ASSERT(fixed == 1); if (use_cached_value) return null_value ? 0 : &str_value; - String *arg= args[0]->val_str(str); + String *arg= args[0]->val_str(&tmp_value); String_copier_for_item copier(current_thd); return ((null_value= args[0]->null_value || - copier.copy_with_warn(collation.collation, &tmp_value, + copier.copy_with_warn(collation.collation, str, arg->charset(), arg->ptr(), arg->length(), arg->length()))) ? - 0 : &tmp_value; + 0 : str; } void Item_func_conv_charset::fix_length_and_dec() @@ -3479,7 +3508,7 @@ String *Item_func_weight_string::val_str(String *str) DBUG_ASSERT(fixed == 1); if (args[0]->result_type() != STRING_RESULT || - !(res= args[0]->val_str(str))) + !(res= args[0]->val_str(&tmp_value))) goto nl; /* @@ -3529,19 +3558,20 @@ String *Item_func_weight_string::val_str(String *str) goto nl; } } - if (tmp_value.alloc(tmp_length)) + + if (str->alloc(tmp_length)) goto nl; frm_length= cs->coll->strnxfrm(cs, - (uchar *) tmp_value.ptr(), tmp_length, + (uchar *) str->ptr(), tmp_length, nweights ? nweights : tmp_length, (const uchar *) res->ptr(), res->length(), flags); DBUG_ASSERT(frm_length <= tmp_length); - tmp_value.length(frm_length); + str->length(frm_length); null_value= 0; - return &tmp_value; + return str; nl: null_value= 1; @@ -3597,18 +3627,18 @@ String *Item_func_hex::val_str_ascii(String *str) } /* Convert given string to a hex string, character by character */ - res= args[0]->val_str(str); - if (!res || tmp_value.alloc(res->length()*2+1)) + res= args[0]->val_str(&tmp_value); + if (!res || str->alloc(res->length()*2+1)) { null_value=1; return 0; } null_value=0; - tmp_value.length(res->length()*2); - tmp_value.set_charset(&my_charset_latin1); + str->length(res->length()*2); + str->set_charset(&my_charset_latin1); - octet2hex((char*) tmp_value.ptr(), res->ptr(), res->length()); - return &tmp_value; + octet2hex((char*) str->ptr(), res->ptr(), res->length()); + return str; } /** Convert given hex string to a binary string. */ @@ -3621,8 +3651,8 @@ String *Item_func_unhex::val_str(String *str) uint length; DBUG_ASSERT(fixed == 1); - res= args[0]->val_str(str); - if (!res || tmp_value.alloc(length= (1+res->length())/2)) + res= args[0]->val_str(&tmp_value); + if (!res || str->alloc(length= (1+res->length())/2)) { null_value=1; return 0; @@ -3630,8 +3660,8 @@ String *Item_func_unhex::val_str(String *str) from= res->ptr(); null_value= 0; - tmp_value.length(length); - to= (char*) tmp_value.ptr(); + str->length(length); + to= (char*) str->ptr(); if (res->length() % 2) { int hex_char; @@ -3649,7 +3679,7 @@ String *Item_func_unhex::val_str(String *str) if ((null_value= (hex_char == -1))) return 0; } - return &tmp_value; + return str; } @@ -3900,7 +3930,7 @@ String *Item_func_quote::val_str(String *str) ulong max_allowed_packet= current_thd->variables.max_allowed_packet; char *from, *to, *end, *start; - String *arg= args[0]->val_str(str); + String *arg= args[0]->val_str(&tmp_value); uint arg_length, new_length; if (!arg) // Null argument { @@ -3927,7 +3957,7 @@ String *Item_func_quote::val_str(String *str) set_if_smaller(new_length, max_allowed_packet); } - if (tmp_value.alloc(new_length)) + if (str->alloc(new_length)) goto null; if (collation.collation->mbmaxlen > 1) @@ -3935,7 +3965,7 @@ String *Item_func_quote::val_str(String *str) CHARSET_INFO *cs= collation.collation; int mblen; uchar *to_end; - to= (char*) tmp_value.ptr(); + to= (char*) str->ptr(); to_end= (uchar*) to + new_length; /* Put leading quote */ @@ -3972,14 +4002,14 @@ String *Item_func_quote::val_str(String *str) if ((mblen= cs->cset->wc_mb(cs, '\'', (uchar *) to, to_end)) <= 0) goto toolong; to+= mblen; - new_length= to - tmp_value.ptr(); + new_length= to - str->ptr(); goto ret; } /* We replace characters from the end to the beginning */ - to= (char*) tmp_value.ptr() + new_length - 1; + to= (char*) str->ptr() + new_length - 1; *to--= '\''; for (start= (char*) arg->ptr(),end= start + arg_length; end-- != start; to--) { @@ -4009,10 +4039,10 @@ String *Item_func_quote::val_str(String *str) *to= '\''; ret: - tmp_value.length(new_length); - tmp_value.set_charset(collation.collation); + str->length(new_length); + str->set_charset(collation.collation); null_value= 0; - return &tmp_value; + return str; toolong: push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN, @@ -4086,7 +4116,7 @@ String *Item_func_compress::val_str(String *str) char *tmp, *last_char; DBUG_ASSERT(fixed == 1); - if (!(res= args[0]->val_str(str))) + if (!(res= args[0]->val_str(&tmp_value))) { null_value= 1; return 0; @@ -4107,13 +4137,13 @@ String *Item_func_compress::val_str(String *str) // Check new_size overflow: new_size <= res->length() if (((uint32) (new_size+5) <= res->length()) || - buffer.realloc((uint32) new_size + 4 + 1)) + str->realloc((uint32) new_size + 4 + 1)) { null_value= 1; return 0; } - body= ((Byte*)buffer.ptr()) + 4; + body= ((Byte*)str->ptr()) + 4; // As far as we have checked res->is_empty() we can use ptr() if ((err= my_compress_buffer(body, &new_size, (const uchar *)res->ptr(), @@ -4127,7 +4157,7 @@ String *Item_func_compress::val_str(String *str) return 0; } - tmp= (char*)buffer.ptr(); // int4store is a macro; avoid side effects + tmp= (char*) str->ptr(); // int4store is a macro; avoid side effects int4store(tmp, res->length() & 0x3FFFFFFF); /* This is to ensure that things works for CHAR fields, which trim ' ': */ @@ -4138,15 +4168,15 @@ String *Item_func_compress::val_str(String *str) new_size++; } - buffer.length((uint32)new_size + 4); - return &buffer; + str->length((uint32)new_size + 4); + return str; } String *Item_func_uncompress::val_str(String *str) { DBUG_ASSERT(fixed == 1); - String *res= args[0]->val_str(str); + String *res= args[0]->val_str(&tmp_value); ulong new_size; int err; uint code; @@ -4179,14 +4209,14 @@ String *Item_func_uncompress::val_str(String *str) max_allowed_packet)); goto err; } - if (buffer.realloc((uint32)new_size)) + if (str->realloc((uint32)new_size)) goto err; - if ((err= uncompress((Byte*)buffer.ptr(), &new_size, + if ((err= uncompress((Byte*)str->ptr(), &new_size, ((const Bytef*)res->ptr())+4,res->length()-4)) == Z_OK) { - buffer.length((uint32) new_size); - return &buffer; + str->length((uint32) new_size); + return str; } code= ((err == Z_BUF_ERROR) ? ER_ZLIB_Z_BUF_ERROR : |