summaryrefslogtreecommitdiff
path: root/sql/item_strfunc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item_strfunc.cc')
-rw-r--r--sql/item_strfunc.cc539
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;
+}