summaryrefslogtreecommitdiff
path: root/sql/item.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item.cc')
-rw-r--r--sql/item.cc233
1 files changed, 156 insertions, 77 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 26c75ccfd40..570af9fe5b7 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -105,7 +105,7 @@ void
Hybrid_type_traits_decimal::fix_length_and_dec(Item *item, Item *arg) const
{
item->decimals= arg->decimals;
- item->max_length= min(arg->max_length + DECIMAL_LONGLONG_DIGITS,
+ item->max_length= MY_MIN(arg->max_length + DECIMAL_LONGLONG_DIGITS,
DECIMAL_MAX_STR_LENGTH);
}
@@ -297,8 +297,9 @@ String *Item::val_string_from_decimal(String *str)
String *Item::val_string_from_date(String *str)
{
MYSQL_TIME ltime;
- if (get_date(&ltime,
- field_type() == MYSQL_TYPE_TIME ? TIME_TIME_ONLY : 0) ||
+ if (get_date(&ltime, field_type() == MYSQL_TYPE_TIME
+ ? TIME_TIME_ONLY
+ : sql_mode_for_dates(current_thd)) ||
str->alloc(MAX_DATE_STRING_REP_LENGTH))
{
null_value= 1;
@@ -342,7 +343,7 @@ my_decimal *Item::val_decimal_from_string(my_decimal *decimal_value)
decimal_value) & E_DEC_BAD_NUM)
{
ErrConvString err(res);
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), "DECIMAL",
err.ptr());
@@ -355,7 +356,7 @@ my_decimal *Item::val_decimal_from_date(my_decimal *decimal_value)
{
DBUG_ASSERT(fixed == 1);
MYSQL_TIME ltime;
- if (get_date(&ltime, 0))
+ if (get_date(&ltime, sql_mode_for_dates(current_thd)))
{
my_decimal_set_zero(decimal_value);
null_value= 1; // set NULL, stop processing
@@ -378,6 +379,27 @@ my_decimal *Item::val_decimal_from_time(my_decimal *decimal_value)
}
+longlong Item::val_int_from_date()
+{
+ DBUG_ASSERT(fixed == 1);
+ MYSQL_TIME ltime;
+ if (get_date(&ltime, 0))
+ return 0;
+ longlong v= TIME_to_ulonglong(&ltime);
+ return ltime.neg ? -v : v;
+}
+
+
+double Item::val_real_from_date()
+{
+ DBUG_ASSERT(fixed == 1);
+ MYSQL_TIME ltime;
+ if (get_date(&ltime, 0))
+ return 0;
+ return TIME_to_double(&ltime);
+}
+
+
double Item::val_real_from_decimal()
{
/* Note that fix_fields may not be called for Item_avg_field items */
@@ -414,9 +436,7 @@ int Item::save_time_in_field(Field *field)
int Item::save_date_in_field(Field *field)
{
MYSQL_TIME ltime;
- if (get_date(&ltime, (current_thd->variables.sql_mode &
- (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
- MODE_INVALID_DATES))))
+ if (get_date(&ltime, sql_mode_for_dates(current_thd)))
return set_field_to_null_with_conversions(field, 0);
field->set_notnull();
return field->store_time_dec(&ltime, decimals);
@@ -531,28 +551,12 @@ uint Item::decimal_precision() const
uint prec=
my_decimal_length_to_precision(max_char_length(), decimals,
unsigned_flag);
- return min(prec, DECIMAL_MAX_PRECISION);
+ return MY_MIN(prec, DECIMAL_MAX_PRECISION);
}
- return min(max_char_length(), DECIMAL_MAX_PRECISION);
+ return MY_MIN(max_char_length(), DECIMAL_MAX_PRECISION);
}
-#if MARIADB_VERSION_ID < 1000000
-static uint ms_to_precision(uint ms)
-{
- uint cut, precision;
- for (cut= 10, precision= 6 ; precision > 0 ; cut*= 10, precision--)
- {
- if (ms % cut)
- return precision;
- }
- return 0;
-}
-#else
-#error Change the code to use MYSQL_TIME_STATUS::precision instead.
-#endif
-
-
uint Item::temporal_precision(enum_field_types type)
{
if (const_item() && result_type() == STRING_RESULT &&
@@ -560,18 +564,18 @@ uint Item::temporal_precision(enum_field_types type)
{
MYSQL_TIME ltime;
String buf, *tmp;
- int was_cut;
+ MYSQL_TIME_STATUS status;
DBUG_ASSERT(fixed);
if ((tmp= val_str(&buf)) &&
(type == MYSQL_TYPE_TIME ?
str_to_time(tmp->charset(), tmp->ptr(), tmp->length(),
- &ltime, TIME_TIME_ONLY, &was_cut) :
+ &ltime, TIME_TIME_ONLY, &status) :
str_to_datetime(tmp->charset(), tmp->ptr(), tmp->length(),
- &ltime, TIME_FUZZY_DATES, &was_cut)) >
+ &ltime, TIME_FUZZY_DATES, &status)) >
MYSQL_TIMESTAMP_ERROR)
- return min(ms_to_precision(ltime.second_part), TIME_SECOND_PART_DIGITS);
+ return MY_MIN(status.precision, TIME_SECOND_PART_DIGITS);
}
- return min(decimals, TIME_SECOND_PART_DIGITS);
+ return MY_MIN(decimals, TIME_SECOND_PART_DIGITS);
}
@@ -689,9 +693,12 @@ Item_result Item::cmp_type() const
case MYSQL_TYPE_GEOMETRY:
return STRING_RESULT;
case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_TIMESTAMP2:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_TIME2:
case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_DATETIME2:
case MYSQL_TYPE_NEWDATE:
return TIME_RESULT;
};
@@ -1020,14 +1027,14 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
{
char buff[SAFE_NAME_LEN];
strmake(buff, str_start,
- min(sizeof(buff)-1, length + (int) (str-str_start)));
+ MY_MIN(sizeof(buff)-1, length + (int) (str-str_start)));
if (length == 0)
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_NAME_BECOMES_EMPTY, ER(ER_NAME_BECOMES_EMPTY),
buff);
else
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_REMOVED_SPACES, ER(ER_REMOVED_SPACES),
buff);
}
@@ -1041,7 +1048,7 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
name_length= res_length;
}
else
- name= sql_strmake(str, (name_length= min(length,MAX_ALIAS_NAME)));
+ name= sql_strmake(str, (name_length= MY_MIN(length,MAX_ALIAS_NAME)));
}
@@ -1170,11 +1177,26 @@ Item *Item_static_float_func::safe_charset_converter(CHARSET_INFO *tocs)
Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
{
+ return charset_converter(tocs, true);
+}
+
+
+/**
+ Convert a string item into the requested character set.
+
+ @param tocs Character set to to convert the string to.
+ @param lossless Whether data loss is acceptable.
+
+ @return A new item representing the converted string.
+*/
+Item *Item_string::charset_converter(CHARSET_INFO *tocs, bool lossless)
+{
Item_string *conv;
uint conv_errors;
char *ptr;
String tmp, cstr, *ostr= val_str(&tmp);
cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
+ conv_errors= lossless && conv_errors;
if (conv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(),
cstr.charset(),
collation.derivation)))
@@ -1195,7 +1217,6 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
return conv;
}
-
Item *Item_param::safe_charset_converter(CHARSET_INFO *tocs)
{
if (const_item())
@@ -1307,7 +1328,7 @@ bool Item::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
String tmp(buff,sizeof(buff), &my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
str_to_datetime_with_warn(res->charset(), res->ptr(), res->length(),
- ltime, fuzzydate) <= MYSQL_TIMESTAMP_ERROR)
+ ltime, fuzzydate))
goto err;
break;
}
@@ -3013,7 +3034,7 @@ double_from_string_with_check(CHARSET_INFO *cs, const char *cptr,
We can use err.ptr() here as ErrConvString is guranteed to put an
end \0 here.
*/
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), "DOUBLE",
err.ptr());
@@ -3050,7 +3071,7 @@ longlong_from_string_with_check(CHARSET_INFO *cs, const char *cptr,
(end != end_of_num && !check_if_only_end_space(cs, end_of_num, end))))
{
ErrConvString err(cptr, end - cptr, cs);
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
err.ptr());
@@ -3256,14 +3277,10 @@ void Item_param::set_time(MYSQL_TIME *tm, timestamp_type time_type,
value.time= *tm;
value.time.time_type= time_type;
- if (value.time.year > 9999 || value.time.month > 12 ||
- value.time.day > 31 ||
- (time_type != MYSQL_TIMESTAMP_TIME && value.time.hour > 23) ||
- value.time.minute > 59 || value.time.second > 59 ||
- value.time.second_part > TIME_MAX_SECOND_PART)
+ if (check_datetime_range(&value.time))
{
ErrConvTime str(&value.time);
- make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN,
&str, time_type, 0);
set_zero_time(&value.time, MYSQL_TIMESTAMP_ERROR);
}
@@ -3522,7 +3539,7 @@ double Item_param::val_real()
This works for example when user says SELECT ?+0.0 and supplies
time value for the placeholder.
*/
- return ulonglong2double(TIME_to_ulonglong(&value.time));
+ return TIME_to_double(&value.time);
case NULL_VALUE:
return 0.0;
default:
@@ -3580,9 +3597,7 @@ my_decimal *Item_param::val_decimal(my_decimal *dec)
return dec;
case TIME_VALUE:
{
- longlong i= (longlong) TIME_to_ulonglong(&value.time);
- int2my_decimal(E_DEC_FATAL_ERROR, i, 0, dec);
- return dec;
+ return TIME_to_my_decimal(&value.time, dec);
}
case NULL_VALUE:
return 0;
@@ -4344,7 +4359,7 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
return TRUE;
if (thd->lex->describe & DESCRIBE_EXTENDED)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_WARN_FIELD_RESOLVED, ER(ER_WARN_FIELD_RESOLVED),
db_name, (db_name[0] ? "." : ""),
table_name, (table_name [0] ? "." : ""),
@@ -4592,7 +4607,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
!((*group_by_ref)->eq(*select_ref, 0)))
{
ambiguous_fields= TRUE;
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR,
ER(ER_NON_UNIQ_ERROR), ref->full_name(),
current_thd->where);
@@ -5565,8 +5580,7 @@ String *Item::check_well_formed_result(String *str, bool send_error)
cs->csname, hexbuf);
return 0;
}
- if ((thd->variables.sql_mode &
- (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
+ if (thd->is_strict_mode())
{
null_value= 1;
str= 0;
@@ -5575,7 +5589,7 @@ String *Item::check_well_formed_result(String *str, bool send_error)
{
str->length(wlen);
}
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_INVALID_CHARACTER_STRING,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_INVALID_CHARACTER_STRING,
ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf);
}
return str;
@@ -5711,29 +5725,23 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length)
field= new Field_double((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
name, decimals, 0, unsigned_flag);
break;
- case MYSQL_TYPE_NULL:
- field= new Field_null((uchar*) 0, max_length, Field::NONE,
- name, &my_charset_bin);
- break;
case MYSQL_TYPE_INT24:
field= new Field_medium((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
name, 0, unsigned_flag);
break;
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_DATE:
- field= new Field_newdate(0, null_ptr, 0, Field::NONE, name, &my_charset_bin);
+ field= new Field_newdate(0, null_ptr, 0, Field::NONE, name);
break;
case MYSQL_TYPE_TIME:
- field= new_Field_time(0, null_ptr, 0, Field::NONE, name,
- decimals, &my_charset_bin);
+ field= new_Field_time(0, null_ptr, 0, Field::NONE, name, decimals);
break;
case MYSQL_TYPE_TIMESTAMP:
field= new_Field_timestamp(0, null_ptr, 0,
- Field::NONE, name, 0, decimals, &my_charset_bin);
+ Field::NONE, name, 0, decimals);
break;
case MYSQL_TYPE_DATETIME:
- field= new_Field_datetime(0, null_ptr, 0, Field::NONE, name,
- decimals, &my_charset_bin);
+ field= new_Field_datetime(0, null_ptr, 0, Field::NONE, name, decimals);
break;
case MYSQL_TYPE_YEAR:
field= new Field_year((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
@@ -5747,6 +5755,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length)
/* This case should never be chosen */
DBUG_ASSERT(0);
/* If something goes awfully wrong, it's better to get a string than die */
+ case MYSQL_TYPE_NULL:
case MYSQL_TYPE_STRING:
if (fixed_length && !too_big_for_varchar())
{
@@ -6200,7 +6209,7 @@ longlong Item_hex_hybrid::val_int()
// following assert is redundant, because fixed=1 assigned in constructor
DBUG_ASSERT(fixed == 1);
char *end=(char*) str_value.ptr()+str_value.length(),
- *ptr=end-min(str_value.length(),sizeof(longlong));
+ *ptr=end-MY_MIN(str_value.length(),sizeof(longlong));
ulonglong value=0;
for (; ptr != end ; ptr++)
@@ -6236,7 +6245,7 @@ int Item_hex_hybrid::save_in_field(Field *field, bool no_conversions)
warn:
if (!field->store((longlong) nr, TRUE))
- field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE,
+ field->set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE,
1);
return 1;
}
@@ -6244,7 +6253,7 @@ warn:
void Item_hex_hybrid::print(String *str, enum_query_type query_type)
{
- uint32 len= min(str_value.length(), sizeof(longlong));
+ uint32 len= MY_MIN(str_value.length(), sizeof(longlong));
const char *ptr= str_value.ptr() + str_value.length() - len;
str->append("0x");
str->append_hex(ptr, len);
@@ -6329,6 +6338,76 @@ Item_bin_string::Item_bin_string(const char *str, uint str_length)
}
+bool Item_temporal_literal::eq(const Item *item, bool binary_cmp) const
+{
+ return
+ item->basic_const_item() && type() == item->type() &&
+ field_type() == ((Item_temporal_literal *) item)->field_type() &&
+ !my_time_compare(&cached_time,
+ &((Item_temporal_literal *) item)->cached_time);
+}
+
+
+void Item_date_literal::print(String *str, enum_query_type query_type)
+{
+ str->append("DATE'");
+ char buf[MAX_DATE_STRING_REP_LENGTH];
+ my_date_to_str(&cached_time, buf);
+ str->append(buf);
+ str->append('\'');
+}
+
+
+bool Item_date_literal::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
+{
+ DBUG_ASSERT(fixed);
+ *ltime= cached_time;
+ return (null_value= check_date_with_warn(ltime, fuzzy_date,
+ MYSQL_TIMESTAMP_ERROR));
+}
+
+
+void Item_datetime_literal::print(String *str, enum_query_type query_type)
+{
+ str->append("TIMESTAMP'");
+ char buf[MAX_DATE_STRING_REP_LENGTH];
+ my_datetime_to_str(&cached_time, buf, decimals);
+ str->append(buf);
+ str->append('\'');
+}
+
+
+bool Item_datetime_literal::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
+{
+ DBUG_ASSERT(fixed);
+ *ltime= cached_time;
+ return (null_value= check_date_with_warn(ltime, fuzzy_date,
+ MYSQL_TIMESTAMP_ERROR));
+}
+
+
+void Item_time_literal::print(String *str, enum_query_type query_type)
+{
+ str->append("TIME'");
+ char buf[MAX_DATE_STRING_REP_LENGTH];
+ my_time_to_str(&cached_time, buf, decimals);
+ str->append(buf);
+ str->append('\'');
+}
+
+
+bool Item_time_literal::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
+{
+ DBUG_ASSERT(fixed);
+ *ltime= cached_time;
+ if (fuzzy_date & TIME_TIME_ONLY)
+ return (null_value= false);
+ return (null_value= check_date_with_warn(ltime, fuzzy_date,
+ MYSQL_TIMESTAMP_ERROR));
+}
+
+
+
/**
Pack data in buffer for sending.
*/
@@ -6430,7 +6509,7 @@ bool Item::send(Protocol *protocol, String *buffer)
case MYSQL_TYPE_TIMESTAMP:
{
MYSQL_TIME tm;
- get_date(&tm, sql_mode_for_dates());
+ get_date(&tm, sql_mode_for_dates(current_thd));
if (!null_value)
{
if (f_type == MYSQL_TYPE_DATE)
@@ -8179,7 +8258,7 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
{
TABLE_LIST *view= cached_table->top_table();
push_warning_printf(field_arg->table->in_use,
- MYSQL_ERROR::WARN_LEVEL_WARN,
+ Sql_condition::WARN_LEVEL_WARN,
ER_NO_DEFAULT_FOR_VIEW_FIELD,
ER(ER_NO_DEFAULT_FOR_VIEW_FIELD),
view->view_db.str,
@@ -8188,7 +8267,7 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
else
{
push_warning_printf(field_arg->table->in_use,
- MYSQL_ERROR::WARN_LEVEL_WARN,
+ Sql_condition::WARN_LEVEL_WARN,
ER_NO_DEFAULT_FOR_FIELD,
ER(ER_NO_DEFAULT_FOR_FIELD),
field_arg->field_name);
@@ -9340,14 +9419,14 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
/* fix variable decimals which always is NOT_FIXED_DEC */
if (Field::result_merge_type(fld_type) == INT_RESULT)
item_decimals= 0;
- decimals= max(decimals, item_decimals);
+ decimals= MY_MAX(decimals, item_decimals);
}
if (Field::result_merge_type(fld_type) == DECIMAL_RESULT)
{
- decimals= min(max(decimals, item->decimals), DECIMAL_MAX_SCALE);
+ decimals= MY_MIN(MY_MAX(decimals, item->decimals), DECIMAL_MAX_SCALE);
int item_int_part= item->decimal_int_part();
- int item_prec = max(prev_decimal_int_part, item_int_part) + decimals;
- int precision= min(item_prec, DECIMAL_MAX_PRECISION);
+ int item_prec = MY_MAX(prev_decimal_int_part, item_int_part) + decimals;
+ int precision= MY_MIN(item_prec, DECIMAL_MAX_PRECISION);
unsigned_flag&= item->unsigned_flag;
max_length= my_decimal_precision_to_length_no_truncation(precision,
decimals,
@@ -9378,7 +9457,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
*/
if (collation.collation != &my_charset_bin)
{
- max_length= max(old_max_chars * collation.collation->mbmaxlen,
+ max_length= MY_MAX(old_max_chars * collation.collation->mbmaxlen,
display_length(item) /
item->collation.collation->mbmaxlen *
collation.collation->mbmaxlen);
@@ -9400,7 +9479,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
{
int delta1= max_length_orig - decimals_orig;
int delta2= item->max_length - item->decimals;
- max_length= max(delta1, delta2) + decimals;
+ max_length= MY_MAX(delta1, delta2) + decimals;
if (fld_type == MYSQL_TYPE_FLOAT && max_length > FLT_DIG + 2)
{
max_length= MAX_FLOAT_STR_LENGTH;
@@ -9418,7 +9497,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
break;
}
default:
- max_length= max(max_length, display_length(item));
+ max_length= MY_MAX(max_length, display_length(item));
};
maybe_null|= item->maybe_null;
get_full_info(item);