diff options
Diffstat (limited to 'sql/item_timefunc.cc')
-rw-r--r-- | sql/item_timefunc.cc | 150 |
1 files changed, 124 insertions, 26 deletions
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 7ef138b7f9a..1f86741e706 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -157,7 +157,7 @@ static bool extract_date_time(THD *thd, DATE_TIME_FORMAT *format, for (; ptr != end && val != val_end; ptr++) { /* Skip pre-space between each argument */ - if ((val+= cs->cset->scan(cs, val, val_end, MY_SEQ_SPACES)) >= val_end) + if ((val+= cs->scan(val, val_end, MY_SEQ_SPACES)) >= val_end) break; if (*ptr == '%' && ptr+1 != end) @@ -259,13 +259,9 @@ static bool extract_date_time(THD *thd, DATE_TIME_FORMAT *format, case 'p': if (val_len < 2 || ! usa_time) goto err; - if (!my_strnncoll(&my_charset_latin1, - (const uchar *) val, 2, - (const uchar *) "PM", 2)) + if (!my_charset_latin1.strnncoll(val, 2, "PM", 2)) daypart= 12; - else if (my_strnncoll(&my_charset_latin1, - (const uchar *) val, 2, - (const uchar *) "AM", 2)) + else if (my_charset_latin1.strnncoll(val, 2, "AM", 2)) goto err; val+= 2; break; @@ -478,7 +474,7 @@ err: Create a formatted date/time value in a string. */ -static bool make_date_time(const LEX_CSTRING &format, MYSQL_TIME *l_time, +static bool make_date_time(const String *format, const MYSQL_TIME *l_time, timestamp_type type, const MY_LOCALE *locale, String *str) { @@ -493,7 +489,7 @@ static bool make_date_time(const LEX_CSTRING &format, MYSQL_TIME *l_time, if (l_time->neg) str->append('-'); - end= (ptr= format.str) + format.length; + end= (ptr= format->ptr()) + format->length(); for (; ptr != end ; ptr++) { if (*ptr != '%' || ptr+1 == end) @@ -1000,7 +996,7 @@ String* Item_func_monthname::val_str(String* str) return (String *) 0; month_name= locale->month_names->type_names[d.get_mysql_time()->month - 1]; - str->copy(month_name, (uint) strlen(month_name), &my_charset_utf8_bin, + str->copy(month_name, (uint) strlen(month_name), &my_charset_utf8mb3_bin, collation.collation, &err); return str; } @@ -1146,7 +1142,7 @@ String* Item_func_dayname::val_str(String* str) return (String*) 0; day_name= locale->day_names->type_names[dt.weekday(false)]; - str->copy(day_name, (uint) strlen(day_name), &my_charset_utf8_bin, + str->copy(day_name, (uint) strlen(day_name), &my_charset_utf8mb3_bin, collation.collation, &err); return str; } @@ -1228,7 +1224,7 @@ bool Item_func_unix_timestamp::get_timestamp_value(my_time_t *seconds, { if ((null_value= field->is_null())) return 1; - *seconds= ((Field_timestamp*)field)->get_timestamp(second_part); + *seconds= field->get_timestamp(second_part); return 0; } } @@ -1284,7 +1280,7 @@ longlong Item_func_unix_timestamp::val_int_endpoint(bool left_endp, bool *incl_e DBUG_ASSERT(arg_count == 1 && args[0]->type() == Item::FIELD_ITEM && args[0]->field_type() == MYSQL_TYPE_TIMESTAMP); - Field_timestamp *field=(Field_timestamp *)(((Item_field*)args[0])->field); + Field *field= ((Item_field*)args[0])->field; /* Leave the incl_endp intact */ ulong unused; my_time_t ts= field->get_timestamp(&unused); @@ -1658,7 +1654,7 @@ int Item_func_now_local::save_in_field(Field *field, bool no_conversions) ulong sec_part= decimals ? thd->query_start_sec_part() : 0; sec_part-= my_time_fraction_remainder(sec_part, decimals); field->set_notnull(); - ((Field_timestamp*)field)->store_TIME(ts, sec_part); + field->store_timestamp(ts, sec_part); return 0; } else @@ -1760,7 +1756,7 @@ bool Item_func_date_format::fix_length_and_dec() decimals=0; CHARSET_INFO *cs= thd->variables.collation_connection; - uint32 repertoire= arg1->collation.repertoire; + my_repertoire_t repertoire= arg1->collation.repertoire; if (!thd->variables.lc_time_names->is_ascii) repertoire|= MY_REPERTOIRE_EXTENDED; collation.set(cs, arg1->collation.derivation, repertoire); @@ -1895,6 +1891,7 @@ String *Item_func_date_format::val_str(String *str) DBUG_ASSERT(fixed == 1); date_conv_mode_t mode= is_time_format ? TIME_TIME_ONLY : TIME_CONV_NONE; THD *thd= current_thd; + if ((null_value= args[0]->get_date(thd, &l_time, Temporal::Options(mode, thd)))) return 0; @@ -1919,7 +1916,7 @@ String *Item_func_date_format::val_str(String *str) /* Create the result string */ str->set_charset(collation.collation); - if (!make_date_time(format->lex_cstring(), &l_time, + if (!make_date_time(format, &l_time, is_time_format ? MYSQL_TIMESTAMP_TIME : MYSQL_TIMESTAMP_DATE, lc, str)) @@ -1936,7 +1933,10 @@ bool Item_func_from_unixtime::fix_length_and_dec() THD *thd= current_thd; thd->time_zone_used= 1; tz= thd->variables.time_zone; - fix_attributes_datetime_not_fixed_dec(args[0]->decimals); + Type_std_attributes::set( + Type_temporal_attributes_not_fixed_dec(MAX_DATETIME_WIDTH, + args[0]->decimals, false), + DTCollation_numeric()); maybe_null= true; return FALSE; } @@ -2017,7 +2017,7 @@ bool Item_date_add_interval::fix_length_and_dec() { enum_field_types arg0_field_type; - if (!args[0]->type_handler()->is_traditional_type()) + if (!args[0]->type_handler()->is_traditional_scalar_type()) { my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0), args[0]->type_handler()->name().ptr(), @@ -2124,6 +2124,21 @@ void Item_extract::print(String *str, enum_query_type query_type) str->append(')'); } + +bool Item_extract::check_arguments() const +{ + if (!args[0]->type_handler()->can_return_extract_source(int_type)) + { + char tmp[64]; + my_snprintf(tmp, sizeof(tmp), "extract(%s)", interval_names[int_type]); + my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0), + args[0]->type_handler()->name().ptr(), tmp); + return true; + } + return false; +} + + bool Item_extract::fix_length_and_dec() { maybe_null=1; // If wrong date @@ -2339,7 +2354,7 @@ uint Item_char_typecast::adjusted_length_with_warn(uint length) } -String *Item_char_typecast::val_str(String *str) +String *Item_char_typecast::val_str_generic(String *str) { DBUG_ASSERT(fixed == 1); String *res; @@ -2395,11 +2410,75 @@ end: } +String *Item_char_typecast::val_str_binary_from_native(String *str) +{ + DBUG_ASSERT(fixed == 1); + DBUG_ASSERT(cast_cs == &my_charset_bin); + NativeBuffer<STRING_BUFFER_USUAL_SIZE> native; + + if (args[0]->val_native(current_thd, &native)) + { + null_value= 1; + return 0; + } + + if (has_explicit_length()) + { + cast_length= adjusted_length_with_warn(cast_length); + if (cast_length > native.length()) + { + // add trailing 0x00s + DBUG_ASSERT(cast_length <= current_thd->variables.max_allowed_packet); + str->alloc(cast_length); + str->copy(native.ptr(), native.length(), &my_charset_bin); + bzero((char*) str->end(), cast_length - str->length()); + str->length(cast_length); + } + else + str->copy(native.ptr(), cast_length, &my_charset_bin); + } + else + str->copy(native.ptr(), native.length(), &my_charset_bin); + + return ((null_value= (str->length() > + adjusted_length_with_warn(str->length())))) ? 0 : str; +} + + +class Item_char_typecast_func_handler: public Item_handled_func::Handler_str +{ +public: + const Type_handler *return_type_handler(const Item_handled_func *item) const + { + return Type_handler::string_type_handler(item->max_length); + } + const Type_handler * + type_handler_for_create_select(const Item_handled_func *item) const + { + return return_type_handler(item)->type_handler_for_tmp_table(item); + } + + bool fix_length_and_dec(Item_handled_func *item) const + { + return false; + } + String *val_str(Item_handled_func *item, String *to) const + { + DBUG_ASSERT(dynamic_cast<const Item_char_typecast*>(item)); + return static_cast<Item_char_typecast*>(item)->val_str_generic(to); + } +}; + + +static Item_char_typecast_func_handler item_char_typecast_func_handler; + + void Item_char_typecast::fix_length_and_dec_numeric() { fix_length_and_dec_internal(from_cs= cast_cs->mbminlen == 1 ? cast_cs : &my_charset_latin1); + set_func_handler(&item_char_typecast_func_handler); } @@ -2408,6 +2487,24 @@ void Item_char_typecast::fix_length_and_dec_generic() fix_length_and_dec_internal(from_cs= args[0]->dynamic_result() ? 0 : args[0]->collation.collation); + set_func_handler(&item_char_typecast_func_handler); +} + + +void Item_char_typecast::fix_length_and_dec_str() +{ + fix_length_and_dec_generic(); + m_suppress_warning_to_error_escalation= true; + set_func_handler(&item_char_typecast_func_handler); +} + + +void +Item_char_typecast::fix_length_and_dec_native_to_binary(uint32 octet_length) +{ + collation.set(&my_charset_bin, DERIVATION_IMPLICIT); + max_length= has_explicit_length() ? (uint32) cast_length : octet_length; + maybe_null|= current_thd->is_strict_mode(); } @@ -2451,6 +2548,8 @@ void Item_char_typecast::fix_length_and_dec_internal(CHARSET_INFO *from_cs) (cast_cs == &my_charset_bin ? 1 : args[0]->collation.collation->mbmaxlen)); max_length= char_length * cast_cs->mbmaxlen; + // Add NULL-ability in strict mode. See Item_str_func::fix_fields() + maybe_null= maybe_null || current_thd->is_strict_mode(); } @@ -2537,8 +2636,8 @@ bool Item_func_add_time::fix_length_and_dec() { enum_field_types arg0_field_type; - if (!args[0]->type_handler()->is_traditional_type() || - !args[1]->type_handler()->is_traditional_type()) + if (!args[0]->type_handler()->is_traditional_scalar_type() || + !args[1]->type_handler()->is_traditional_scalar_type()) { my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0), args[0]->type_handler()->name().ptr(), @@ -2843,9 +2942,8 @@ String *Item_func_get_format::val_str_ascii(String *str) uint format_name_len; format_name_len= (uint) strlen(format_name); if (val_len == format_name_len && - !my_strnncoll(&my_charset_latin1, - (const uchar *) val->ptr(), val_len, - (const uchar *) format_name, val_len)) + !my_charset_latin1.strnncoll(val->ptr(), val_len, + format_name, val_len)) { const char *format_str= get_date_time_format_str(format, type); str->set(format_str, (uint) strlen(format_str), &my_charset_numeric); @@ -2947,8 +3045,8 @@ get_date_time_result_type(const char *format, uint length) bool Item_func_str_to_date::fix_length_and_dec() { - if (!args[0]->type_handler()->is_traditional_type() || - !args[1]->type_handler()->is_traditional_type()) + if (!args[0]->type_handler()->is_traditional_scalar_type() || + !args[1]->type_handler()->is_traditional_scalar_type()) { my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0), args[0]->type_handler()->name().ptr(), |