summaryrefslogtreecommitdiff
path: root/sql/item_strfunc.cc
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2017-07-05 19:08:55 +0200
committerSergei Golubchik <serg@mariadb.org>2017-07-05 19:08:55 +0200
commitf6633bf058802ad7da8196d01fd19d75c53f7274 (patch)
treeb7ba9832aae2a3d0c72d2bf3d89cf2a5f13a44f6 /sql/item_strfunc.cc
parentfc5932a1b733b331be20c3f1b45c61c798227dba (diff)
parente555540ab6b9c3e0d4fdd00af093b115a9401d0a (diff)
downloadmariadb-git-f6633bf058802ad7da8196d01fd19d75c53f7274.tar.gz
Merge branch '10.1' into 10.2
Diffstat (limited to 'sql/item_strfunc.cc')
-rw-r--r--sql/item_strfunc.cc230
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 :