diff options
Diffstat (limited to 'sql/item_func.cc')
-rw-r--r-- | sql/item_func.cc | 212 |
1 files changed, 116 insertions, 96 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc index 1f1523e738a..63a3937a12e 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -151,15 +151,81 @@ void Item_func::sync_with_sum_func_and_with_field(List<Item> &list) } -bool Item_func::check_allowed_arg_cols(uint n) +bool Item_func::check_argument_types_like_args0() const { - if (allowed_arg_cols) - return args[n]->check_cols(allowed_arg_cols); + uint cols; + if (arg_count == 0) + return false; + cols= args[0]->cols(); + for (uint i= 1; i < arg_count; i++) + { + if (args[i]->check_cols(cols)) + return true; + } + return false; +} + + +bool Item_func::check_argument_types_or_binary(const Type_handler *handler, + uint start, uint end) const +{ + for (uint i= start; i < end ; i++) + { + DBUG_ASSERT(i < arg_count); + if (args[i]->check_type_or_binary(func_name(), handler)) + return true; + } + return false; +} - /* we have to fetch allowed_arg_cols from first argument */ - DBUG_ASSERT(n == 0); // it is first argument - allowed_arg_cols= args[n]->cols(); - DBUG_ASSERT(allowed_arg_cols); // Can't be 0 any more + +bool Item_func::check_argument_types_traditional_scalar(uint start, + uint end) const +{ + for (uint i= start; i < end ; i++) + { + DBUG_ASSERT(i < arg_count); + if (args[i]->check_type_traditional_scalar(func_name())) + return true; + } + return false; +} + + +bool Item_func::check_argument_types_can_return_int(uint start, + uint end) const +{ + for (uint i= start; i < end ; i++) + { + DBUG_ASSERT(i < arg_count); + if (args[i]->check_type_can_return_int(func_name())) + return true; + } + return false; +} + + +bool Item_func::check_argument_types_can_return_real(uint start, + uint end) const +{ + for (uint i= start; i < end ; i++) + { + DBUG_ASSERT(i < arg_count); + if (args[i]->check_type_can_return_real(func_name())) + return true; + } + return false; +} + + +bool Item_func::check_argument_types_scalar(uint start, uint end) const +{ + for (uint i= start; i < end; i++) + { + DBUG_ASSERT(i < arg_count); + if (args[i]->check_type_scalar(func_name())) + return true; + } return false; } @@ -236,9 +302,6 @@ Item_func::fix_fields(THD *thd, Item **ref) return TRUE; /* purecov: inspected */ item= *arg; - if (check_allowed_arg_cols(arg - args)) - return true; - if (item->maybe_null) maybe_null=1; @@ -249,6 +312,8 @@ Item_func::fix_fields(THD *thd, Item **ref) with_subselect|= item->has_subquery(); } } + if (check_arguments()) + return true; fix_length_and_dec(); if (thd->is_error()) // An error inside fix_length_and_dec occurred return TRUE; @@ -632,7 +697,7 @@ String *Item_int_func::val_str(String *str) void Item_func_connection_id::fix_length_and_dec() { - Item_int_func::fix_length_and_dec(); + Item_long_func::fix_length_and_dec(); max_length= 10; } @@ -879,41 +944,6 @@ void Item_func_signed::print(String *str, enum_query_type query_type) } -longlong Item::val_int_from_str(int *error) -{ - char buff[MAX_FIELD_WIDTH]; - String tmp(buff,sizeof(buff), &my_charset_bin), *res; - - /* - For a string result, we must first get the string and then convert it - to a longlong - */ - - if (!(res= val_str(&tmp))) - { - *error= 0; - return 0; - } - Converter_strtoll10_with_warn cnv(NULL, Warn_filter_all(), - res->charset(), res->ptr(), res->length()); - *error= cnv.error(); - return cnv.result(); -} - - -longlong Item::val_int_signed_typecast() -{ - if (cast_to_int_type_handler()->cmp_type() != STRING_RESULT) - return val_int(); - - int error; - longlong value= val_int_from_str(&error); - if (!null_value && value < 0 && error == 0) - push_note_converted_to_negative_complement(current_thd); - return value; -} - - void Item_func_unsigned::print(String *str, enum_query_type query_type) { str->append(STRING_WITH_LEN("cast(")); @@ -923,34 +953,6 @@ void Item_func_unsigned::print(String *str, enum_query_type query_type) } -longlong Item::val_int_unsigned_typecast() -{ - if (cast_to_int_type_handler()->cmp_type() == DECIMAL_RESULT) - { - longlong value; - my_decimal tmp, *dec= val_decimal(&tmp); - if (!null_value) - my_decimal2int(E_DEC_FATAL_ERROR, dec, 1, &value); - else - value= 0; - return value; - } - else if (cast_to_int_type_handler()->cmp_type() != STRING_RESULT) - { - longlong value= val_int(); - if (!null_value && unsigned_flag == 0 && value < 0) - push_note_converted_to_positive_complement(current_thd); - return value; - } - - int error; - longlong value= val_int_from_str(&error); - if (!null_value && error < 0) - push_note_converted_to_positive_complement(current_thd); - return value; -} - - String *Item_decimal_typecast::val_str(String *str) { my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf); @@ -1804,8 +1806,8 @@ my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value) void Item_func_neg::fix_length_and_dec_int() { - set_handler(&type_handler_longlong); max_length= args[0]->max_length + 1; + set_handler(type_handler_long_or_longlong()); /* If this is in integer context keep the context as integer if possible @@ -1898,9 +1900,9 @@ my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value) void Item_func_abs::fix_length_and_dec_int() { - set_handler(&type_handler_longlong); max_length= args[0]->max_length; unsigned_flag= args[0]->unsigned_flag; + set_handler(type_handler_long_or_longlong()); } @@ -2181,7 +2183,7 @@ void Item_func_int_val::fix_length_and_dec_int_or_decimal() else { unsigned_flag= args[0]->unsigned_flag; - set_handler(&type_handler_longlong); + set_handler(type_handler_long_or_longlong()); } } @@ -2372,9 +2374,9 @@ void Item_func_round::fix_arg_int() int length_can_increase= MY_TEST(!truncate && val1_is_negative); max_length= args[0]->max_length + length_can_increase; // Here we can keep INT_RESULT - set_handler(&type_handler_longlong); unsigned_flag= args[0]->unsigned_flag; decimals= 0; + set_handler(type_handler_long_or_longlong()); } else fix_length_and_dec_decimal(decimals_to_set); @@ -2773,6 +2775,14 @@ my_decimal *Item_func_min_max::val_decimal_native(my_decimal *dec) } +longlong Item_func_bit_length::val_int() +{ + DBUG_ASSERT(fixed == 1); + String *res= args[0]->val_str(&value); + return (null_value= !res) ? 0 : (longlong) res->length() * 8; +} + + longlong Item_func_octet_length::val_int() { DBUG_ASSERT(fixed == 1); @@ -2809,13 +2819,6 @@ longlong Item_func_coercibility::val_int() } -void Item_func_locate::fix_length_and_dec() -{ - max_length= MY_INT32_NUM_DECIMAL_DIGITS; - agg_arg_charsets_for_comparison(cmp_collation, args, 2); -} - - longlong Item_func_locate::val_int() { DBUG_ASSERT(fixed == 1); @@ -4414,8 +4417,27 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref) m_var_entry->set_charset(args[0]->collation.derivation == DERIVATION_NUMERIC ? default_charset() : args[0]->collation.collation); collation.set(m_var_entry->charset(), DERIVATION_IMPLICIT); - set_handler_by_result_type(args[0]->result_type(), - max_length, collation.collation); + switch (args[0]->result_type()) { + case STRING_RESULT: + case TIME_RESULT: + set_handler(type_handler_long_blob. + type_handler_adjusted_to_max_octet_length(max_length, + collation.collation)); + break; + case REAL_RESULT: + set_handler(&type_handler_double); + break; + case INT_RESULT: + set_handler(Type_handler::type_handler_long_or_longlong(max_char_length())); + break; + case DECIMAL_RESULT: + set_handler(&type_handler_newdecimal); + break; + case ROW_RESULT: + DBUG_ASSERT(0); + set_handler(&type_handler_row); + break; + } if (thd->lex->current_select) { /* @@ -5321,7 +5343,6 @@ void Item_func_get_user_var::fix_length_and_dec() break; case STRING_RESULT: max_length= MAX_BLOB_WIDTH - 1; - set_handler(&type_handler_medium_blob); break; case DECIMAL_RESULT: fix_char_length(DECIMAL_MAX_STR_LENGTH); @@ -5406,15 +5427,14 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref) } -void Item_user_var_as_out_param::load_data_set_null_value(CHARSET_INFO* cs) +void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs) { ::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs, 0 /* unsigned_arg */); } -void Item_user_var_as_out_param::load_data_set_value(const char *str, - uint length, - CHARSET_INFO* cs) +void Item_user_var_as_out_param::set_value(const char *str, uint length, + CHARSET_INFO* cs) { ::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs, 0 /* unsigned_arg */); @@ -5449,7 +5469,7 @@ my_decimal* Item_user_var_as_out_param::val_decimal(my_decimal *decimal_buffer) } -void Item_user_var_as_out_param::load_data_print(THD *thd, String *str) +void Item_user_var_as_out_param::print_for_load(THD *thd, String *str) { str->append('@'); append_identifier(thd, str, name.str, name.length); @@ -6688,14 +6708,14 @@ void Item_func_last_value::fix_length_and_dec() } -void Item_func_cursor_int_attr::print(String *str, enum_query_type query_type) +void Cursor_ref::print_func(String *str, const char *func_name) { append_identifier(current_thd, str, m_cursor_name.str, m_cursor_name.length); - str->append(func_name()); + str->append(func_name); } -sp_cursor *Item_func_cursor_int_attr::get_open_cursor_or_error() +sp_cursor *Cursor_ref::get_open_cursor_or_error() { THD *thd= current_thd; sp_cursor *c= thd->spcont->get_cursor(m_cursor_offset); |