diff options
Diffstat (limited to 'sql/item_func.h')
-rw-r--r-- | sql/item_func.h | 566 |
1 files changed, 465 insertions, 101 deletions
diff --git a/sql/item_func.h b/sql/item_func.h index 754b1cd1eb2..b368e5872fe 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -35,12 +35,11 @@ extern "C" /* Bug in BSDI include file */ #include <cmath> -class Item_func :public Item_func_or_sum +class Item_func :public Item_func_or_sum, + protected With_sum_func_cache { void sync_with_sum_func_and_with_field(List<Item> &list); protected: - String *val_str_from_val_str_ascii(String *str, String *str2); - virtual bool check_arguments() const { return check_argument_types_scalar(0, arg_count); @@ -56,6 +55,7 @@ protected: bool check_argument_types_can_return_text(uint start, uint end) const; bool check_argument_types_can_return_date(uint start, uint end) const; bool check_argument_types_can_return_time(uint start, uint end) const; + void print_cast_temporal(String *str, enum_query_type query_type); public: table_map not_null_tables_cache; @@ -80,49 +80,56 @@ public: CASE_SEARCHED_FUNC, // Used by ColumnStore/Spider CASE_SIMPLE_FUNC // Used by ColumnStore/spider }; + static scalar_comparison_op functype_to_scalar_comparison_op(Functype type) + { + switch (type) { + case EQ_FUNC: return SCALAR_CMP_EQ; + case EQUAL_FUNC: return SCALAR_CMP_EQUAL; + case LT_FUNC: return SCALAR_CMP_LT; + case LE_FUNC: return SCALAR_CMP_LE; + case GE_FUNC: return SCALAR_CMP_GE; + case GT_FUNC: return SCALAR_CMP_GT; + default: break; + } + DBUG_ASSERT(0); + return SCALAR_CMP_EQ; + } enum Type type() const { return FUNC_ITEM; } virtual enum Functype functype() const { return UNKNOWN_FUNC; } Item_func(THD *thd): Item_func_or_sum(thd) { - with_sum_func= 0; with_field= 0; with_param= 0; } - Item_func(THD *thd, Item *a): Item_func_or_sum(thd, a) + Item_func(THD *thd, Item *a) + :Item_func_or_sum(thd, a), With_sum_func_cache(a) { - with_sum_func= a->with_sum_func; with_param= a->with_param; with_field= a->with_field; } - Item_func(THD *thd, Item *a, Item *b): - Item_func_or_sum(thd, a, b) + Item_func(THD *thd, Item *a, Item *b) + :Item_func_or_sum(thd, a, b), With_sum_func_cache(a, b) { - with_sum_func= a->with_sum_func || b->with_sum_func; with_param= a->with_param || b->with_param; with_field= a->with_field || b->with_field; } - Item_func(THD *thd, Item *a, Item *b, Item *c): - Item_func_or_sum(thd, a, b, c) + Item_func(THD *thd, Item *a, Item *b, Item *c) + :Item_func_or_sum(thd, a, b, c), With_sum_func_cache(a, b, c) { - with_sum_func= a->with_sum_func || b->with_sum_func || c->with_sum_func; with_field= a->with_field || b->with_field || c->with_field; with_param= a->with_param || b->with_param || c->with_param; } - Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d): - Item_func_or_sum(thd, a, b, c, d) + Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d) + :Item_func_or_sum(thd, a, b, c, d), With_sum_func_cache(a, b, c, d) { - with_sum_func= a->with_sum_func || b->with_sum_func || - c->with_sum_func || d->with_sum_func; with_field= a->with_field || b->with_field || c->with_field || d->with_field; with_param= a->with_param || b->with_param || c->with_param || d->with_param; } - Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e): - Item_func_or_sum(thd, a, b, c, d, e) + Item_func(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e) + :Item_func_or_sum(thd, a, b, c, d, e), With_sum_func_cache(a, b, c, d, e) { - with_sum_func= a->with_sum_func || b->with_sum_func || - c->with_sum_func || d->with_sum_func || e->with_sum_func; with_field= a->with_field || b->with_field || c->with_field || d->with_field || e->with_field; with_param= a->with_param || b->with_param || @@ -134,11 +141,10 @@ public: set_arguments(thd, list); } // Constructor used for Item_cond_and/or (see Item comment) - Item_func(THD *thd, Item_func *item): - Item_func_or_sum(thd, item), + Item_func(THD *thd, Item_func *item) + :Item_func_or_sum(thd, item), With_sum_func_cache(item), not_null_tables_cache(item->not_null_tables_cache) - { - } + { } bool fix_fields(THD *, Item **ref); void cleanup() { @@ -174,16 +180,12 @@ public: virtual void print(String *str, enum_query_type query_type); void print_op(String *str, enum_query_type query_type); void print_args(String *str, uint from, enum_query_type query_type); - inline bool get_arg0_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) - { - DBUG_ASSERT(!(fuzzy_date & TIME_TIME_ONLY)); - Datetime dt(current_thd, args[0], fuzzy_date); - return (null_value= dt.copy_to_mysql_time(ltime)); - } bool is_null() { update_null_value(); return null_value; } + String *val_str_from_val_str_ascii(String *str, String *str2); + void signal_divide_by_null(); friend class udf_handler; Field *create_field_for_create_select(TABLE *table) @@ -325,6 +327,11 @@ public: return this; } + bool has_rand_bit() + { + return used_tables() & RAND_TABLE_BIT; + } + bool excl_dep_on_table(table_map tab_map) { if (used_tables() & OUTER_REF_TABLE_BIT) @@ -335,9 +342,16 @@ public: bool excl_dep_on_grouping_fields(st_select_lex *sel) { + if (has_rand_bit() || with_subquery()) + return false; return Item_args::excl_dep_on_grouping_fields(sel); } + bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred) + { + return Item_args::excl_dep_on_in_subq_left_part(subq_pred); + } + /* We assume the result of any function that has a TIMESTAMP argument to be timezone-dependent, since a TIMESTAMP value in both numeric and string @@ -380,6 +394,12 @@ public: - or replaced to an Item_int_with_ref */ bool setup_args_and_comparator(THD *thd, Arg_comparator *cmp); + + bool with_sum_func() const { return m_with_sum_func; } + With_sum_func_cache* get_with_sum_func_cache() { return this; } + Item_func *get_item_func() { return this; } + bool is_simplified_cond_processor(void *arg) + { return const_item() && !val_int(); } }; @@ -400,8 +420,8 @@ public: DBUG_ASSERT(fixed == 1); return Converter_double_to_longlong(val_real(), unsigned_flag).result(); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_real(ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { return get_date_from_real(thd, ltime, fuzzydate); } const Type_handler *type_handler() const { return &type_handler_double; } bool fix_length_and_dec() { @@ -438,6 +458,230 @@ public: { Type_geometry_attributes::set_geometry_type(type); } + void fix_length_and_dec_long_or_longlong(uint char_length, bool unsigned_arg) + { + collation.set_numeric(); + unsigned_flag= unsigned_arg; + max_length= char_length; +#if MARIADB_VERSION_ID < 100500 + set_handler(Type_handler::type_handler_long_or_longlong(char_length)); +#else + set_handler(Type_handler::type_handler_long_or_longlong(char_length, + unsigned_arg)); +#endif + } + void fix_length_and_dec_ulong_or_ulonglong_by_nbits(uint nbits) + { + uint digits= Type_handler_bit::Bit_decimal_notation_int_digits_by_nbits(nbits); + collation.set_numeric(); + unsigned_flag= true; + max_length= digits; + if (nbits > 32) + set_handler(&type_handler_longlong); + else + set_handler(&type_handler_long); + } +}; + + +class Item_handled_func: public Item_func +{ +public: + class Handler + { + public: + virtual ~Handler() { } + virtual String *val_str(Item_handled_func *, String *) const= 0; + virtual String *val_str_ascii(Item_handled_func *, String *) const= 0; + virtual double val_real(Item_handled_func *) const= 0; + virtual longlong val_int(Item_handled_func *) const= 0; + virtual my_decimal *val_decimal(Item_handled_func *, my_decimal *) const= 0; + virtual bool get_date(THD *thd, Item_handled_func *, MYSQL_TIME *, date_mode_t fuzzydate) const= 0; + virtual bool val_native(THD *thd, Item_handled_func *, Native *to) const + { + DBUG_ASSERT(0); + to->length(0); + return true; + } + virtual const Type_handler *return_type_handler() const= 0; + virtual bool fix_length_and_dec(Item_handled_func *) const= 0; + }; + + /** + Abstract class for functions returning TIME, DATE, DATETIME or string values, + whose data type depends on parameters and is set at fix_fields time. + */ + class Handler_temporal: public Handler + { + public: + String *val_str(Item_handled_func *item, String *to) const + { + StringBuffer<MAX_FIELD_WIDTH> ascii_buf; + return item->val_str_from_val_str_ascii(to, &ascii_buf); + } + }; + + /** + Abstract class for functions returning strings, + which are generated from get_date() results, + when get_date() can return different MYSQL_TIMESTAMP_XXX per row. + */ + class Handler_temporal_string: public Handler_temporal + { + public: + const Type_handler *return_type_handler() const + { + return &type_handler_string; + } + double val_real(Item_handled_func *item) const + { + return Temporal_hybrid(item).to_double(); + } + longlong val_int(Item_handled_func *item) const + { + return Temporal_hybrid(item).to_longlong(); + } + my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const + { + return Temporal_hybrid(item).to_decimal(to); + } + String *val_str_ascii(Item_handled_func *item, String *to) const + { + return Temporal_hybrid(item).to_string(to, item->decimals); + } + }; + + + class Handler_date: public Handler_temporal + { + public: + const Type_handler *return_type_handler() const + { + return &type_handler_newdate; + } + bool fix_length_and_dec(Item_handled_func *item) const + { + item->fix_attributes_date(); + return false; + } + double val_real(Item_handled_func *item) const + { + return Date(item).to_double(); + } + longlong val_int(Item_handled_func *item) const + { + return Date(item).to_longlong(); + } + my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const + { + return Date(item).to_decimal(to); + } + String *val_str_ascii(Item_handled_func *item, String *to) const + { + return Date(item).to_string(to); + } + }; + + + class Handler_time: public Handler_temporal + { + public: + const Type_handler *return_type_handler() const + { + return &type_handler_time2; + } + double val_real(Item_handled_func *item) const + { + return Time(item).to_double(); + } + longlong val_int(Item_handled_func *item) const + { + return Time(item).to_longlong(); + } + my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const + { + return Time(item).to_decimal(to); + } + String *val_str_ascii(Item_handled_func *item, String *to) const + { + return Time(item).to_string(to, item->decimals); + } + bool val_native(THD *thd, Item_handled_func *item, Native *to) const + { + return Time(thd, item).to_native(to, item->decimals); + } + }; + + + class Handler_datetime: public Handler_temporal + { + public: + const Type_handler *return_type_handler() const + { + return &type_handler_datetime2; + } + double val_real(Item_handled_func *item) const + { + return Datetime(item).to_double(); + } + longlong val_int(Item_handled_func *item) const + { + return Datetime(item).to_longlong(); + } + my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const + { + return Datetime(item).to_decimal(to); + } + String *val_str_ascii(Item_handled_func *item, String *to) const + { + return Datetime(item).to_string(to, item->decimals); + } + }; + + +protected: + const Handler *m_func_handler; +public: + Item_handled_func(THD *thd, Item *a) + :Item_func(thd, a), m_func_handler(NULL) { } + Item_handled_func(THD *thd, Item *a, Item *b) + :Item_func(thd, a, b), m_func_handler(NULL) { } + void set_func_handler(const Handler *handler) + { + m_func_handler= handler; + } + const Type_handler *type_handler() const + { + return m_func_handler->return_type_handler(); + } + String *val_str(String *to) + { + return m_func_handler->val_str(this, to); + } + String *val_str_ascii(String *to) + { + return m_func_handler->val_str_ascii(this, to); + } + double val_real() + { + return m_func_handler->val_real(this); + } + longlong val_int() + { + return m_func_handler->val_int(this); + } + my_decimal *val_decimal(my_decimal *to) + { + return m_func_handler->val_decimal(this, to); + } + bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) + { + return m_func_handler->get_date(thd, this, to, fuzzydate); + } + bool val_native(THD *thd, Native *to) + { + return m_func_handler->val_native(thd, this, to); + } }; @@ -463,15 +707,15 @@ class Item_func_hybrid_field_type: public Item_hybrid_func Helper methods to make sure that the result of decimal_op(), str_op() and date_op() is properly synched with null_value. */ - bool date_op_with_null_check(MYSQL_TIME *ltime) + bool date_op_with_null_check(THD *thd, MYSQL_TIME *ltime) { - bool rc= date_op(ltime, 0); + bool rc= date_op(thd, ltime, date_mode_t(0)); DBUG_ASSERT(!rc ^ null_value); return rc; } - bool time_op_with_null_check(MYSQL_TIME *ltime) + bool time_op_with_null_check(THD *thd, MYSQL_TIME *ltime) { - bool rc= time_op(ltime); + bool rc= time_op(thd, ltime); DBUG_ASSERT(!rc ^ null_value); DBUG_ASSERT(rc || ltime->time_type == MYSQL_TIMESTAMP_TIME); return rc; @@ -482,17 +726,6 @@ class Item_func_hybrid_field_type: public Item_hybrid_func DBUG_ASSERT((res != NULL) ^ null_value); return res; } - my_decimal *decimal_op_with_null_check(my_decimal *decimal_buffer) - { - my_decimal *res= decimal_op(decimal_buffer); - DBUG_ASSERT((res != NULL) ^ null_value); - return res; - } - bool make_zero_mysql_time(MYSQL_TIME *ltime, ulonglong fuzzydate) - { - bzero(ltime, sizeof(*ltime)); - return null_value|= !(fuzzydate & TIME_FUZZY_DATES); - } public: // Value methods that involve no conversion @@ -500,10 +733,6 @@ public: { return str_op_with_null_check(&str_value); } - my_decimal *val_decimal_from_decimal_op(my_decimal *dec) - { - return decimal_op_with_null_check(dec); - } longlong val_int_from_int_op() { return int_op(); @@ -514,7 +743,6 @@ public: } // Value methods that involve conversion - String *val_str_from_decimal_op(String *str); String *val_str_from_real_op(String *str); String *val_str_from_int_op(String *str); String *val_str_from_date_op(String *str); @@ -528,21 +756,14 @@ public: longlong val_int_from_str_op(); longlong val_int_from_real_op(); - longlong val_int_from_decimal_op(); longlong val_int_from_date_op(); longlong val_int_from_time_op(); double val_real_from_str_op(); - double val_real_from_decimal_op(); double val_real_from_date_op(); double val_real_from_time_op(); double val_real_from_int_op(); - bool get_date_from_str_op(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool get_date_from_real_op(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool get_date_from_decimal_op(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool get_date_from_int_op(MYSQL_TIME *ltime, ulonglong fuzzydate); - public: Item_func_hybrid_field_type(THD *thd): Item_hybrid_func(thd) @@ -586,11 +807,17 @@ public: DBUG_ASSERT(null_value == (res == NULL)); return res; } - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date) + bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode) { DBUG_ASSERT(fixed); return Item_func_hybrid_field_type::type_handler()-> - Item_func_hybrid_field_type_get_date(this, res, fuzzy_date); + Item_func_hybrid_field_type_get_date_with_warn(thd, this, to, mode); + } + + bool val_native(THD *thd, Native *to) + { + DBUG_ASSERT(fixed); + return native_op(thd, to); } /** @@ -600,6 +827,20 @@ public: @return The result of the operation. */ virtual longlong int_op()= 0; + Longlong_null to_longlong_null_op() + { + longlong nr= int_op(); + /* + C++ does not guarantee the order of parameter evaluation, + so to make sure "null_value" is passed to the constructor + after the int_op() call, int_op() is caled on a separate line. + */ + return Longlong_null(nr, null_value); + } + Longlong_hybrid_null to_longlong_hybrid_null_op() + { + return Longlong_hybrid_null(to_longlong_null_op(), unsigned_flag); + } /** @brief Performs the operation that this functions implements when the @@ -608,6 +849,12 @@ public: @return The result of the operation. */ virtual double real_op()= 0; + Double_null to_double_null_op() + { + // val_real() must be caleed on a separate line. See to_longlong_null() + double nr= real_op(); + return Double_null(nr, null_value); + } /** @brief Performs the operation that this functions implements when the @@ -634,15 +881,16 @@ public: field type is DATETIME or DATE. @return The result of the operation. */ - virtual bool date_op(MYSQL_TIME *res, ulonglong fuzzy_date)= 0; + virtual bool date_op(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate)= 0; /** @brief Performs the operation that this functions implements when field type is TIME. @return The result of the operation. */ - virtual bool time_op(MYSQL_TIME *res)= 0; + virtual bool time_op(THD *thd, MYSQL_TIME *res)= 0; + virtual bool native_op(THD *thd, Native *native)= 0; }; @@ -700,12 +948,17 @@ public: Item_func_hybrid_field_type(thd, list) { } String *str_op(String *str) { DBUG_ASSERT(0); return 0; } - bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { DBUG_ASSERT(0); return true; } - bool time_op(MYSQL_TIME *ltime) + bool time_op(THD *thd, MYSQL_TIME *ltime) + { + DBUG_ASSERT(0); + return true; + } + bool native_op(THD *thd, Native *to) { DBUG_ASSERT(0); return true; @@ -791,8 +1044,8 @@ public: { collation.set_numeric(); } double val_real(); String *val_str(String*str); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_int(ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { return get_date_from_int(thd, ltime, fuzzydate); } const Type_handler *type_handler() const= 0; bool fix_length_and_dec() { return FALSE; } }; @@ -812,6 +1065,19 @@ public: }; +class Item_func_hash: public Item_int_func +{ +public: + Item_func_hash(THD *thd, List<Item> &item): Item_int_func(thd, item) + {} + longlong val_int(); + bool fix_length_and_dec(); + const Type_handler *type_handler() const { return &type_handler_long; } + Item *get_copy(THD *thd) + { return get_item_copy<Item_func_hash>(thd, this); } + const char *func_name() const { return "<hash>"; } +}; + class Item_longlong_func: public Item_int_func { public: @@ -982,12 +1248,15 @@ public: fix_char_length(my_decimal_precision_to_length_no_truncation(len, dec, unsigned_flag)); } - String *val_str(String *str); - double val_real(); - longlong val_int(); + String *val_str(String *str) { return VDec(this).to_string(str); } + double val_real() { return VDec(this).to_double(); } + longlong val_int() { return VDec(this).to_longlong(unsigned_flag); } my_decimal *val_decimal(my_decimal*); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_decimal(ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode) + { + return decimal_to_datetime_with_warn(thd, VDec(this).ptr(), to, mode, + NULL, NULL); + } const Type_handler *type_handler() const { return &type_handler_newdecimal; } void fix_length_and_dec_generic() {} bool fix_length_and_dec() @@ -1434,13 +1703,33 @@ public: }; -class Item_func_int_val :public Item_func_num1 +class Item_func_int_val :public Item_func_hybrid_field_type { public: - Item_func_int_val(THD *thd, Item *a): Item_func_num1(thd, a) {} + Item_func_int_val(THD *thd, Item *a): Item_func_hybrid_field_type(thd, a) {} + bool check_partition_func_processor(void *int_arg) { return FALSE; } + bool check_vcol_func_processor(void *arg) { return FALSE; } + virtual decimal_round_mode round_mode() const= 0; void fix_length_and_dec_double(); void fix_length_and_dec_int_or_decimal(); + void fix_length_and_dec_time() + { + fix_attributes_time(0); + set_handler(&type_handler_time2); + } + void fix_length_and_dec_datetime() + { + fix_attributes_datetime(0); + set_handler(&type_handler_datetime2); + maybe_null= true; // E.g. CEILING(TIMESTAMP'0000-01-01 23:59:59.9') + } bool fix_length_and_dec(); + String *str_op(String *str) { DBUG_ASSERT(0); return 0; } + bool native_op(THD *thd, Native *to) + { + DBUG_ASSERT(0); + return true; + } }; @@ -1449,9 +1738,12 @@ class Item_func_ceiling :public Item_func_int_val public: Item_func_ceiling(THD *thd, Item *a): Item_func_int_val(thd, a) {} const char *func_name() const { return "ceiling"; } + decimal_round_mode round_mode() const { return CEILING; } longlong int_op(); double real_op(); my_decimal *decimal_op(my_decimal *); + bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool time_op(THD *thd, MYSQL_TIME *ltime); Item *get_copy(THD *thd) { return get_item_copy<Item_func_ceiling>(thd, this); } }; @@ -1462,33 +1754,59 @@ class Item_func_floor :public Item_func_int_val public: Item_func_floor(THD *thd, Item *a): Item_func_int_val(thd, a) {} const char *func_name() const { return "floor"; } + decimal_round_mode round_mode() const { return FLOOR; } longlong int_op(); double real_op(); my_decimal *decimal_op(my_decimal *); + bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool time_op(THD *thd, MYSQL_TIME *ltime); Item *get_copy(THD *thd) { return get_item_copy<Item_func_floor>(thd, this); } }; /* This handles round and truncate */ -class Item_func_round :public Item_func_numhybrid +class Item_func_round :public Item_func_hybrid_field_type { bool truncate; void fix_length_and_dec_decimal(uint decimals_to_set); void fix_length_and_dec_double(uint decimals_to_set); + bool test_if_length_can_increase(); public: Item_func_round(THD *thd, Item *a, Item *b, bool trunc_arg) - :Item_func_numhybrid(thd, a, b), truncate(trunc_arg) {} + :Item_func_hybrid_field_type(thd, a, b), truncate(trunc_arg) {} const char *func_name() const { return truncate ? "truncate" : "round"; } double real_op(); longlong int_op(); my_decimal *decimal_op(my_decimal *); + bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool time_op(THD *thd, MYSQL_TIME *ltime); + bool native_op(THD *thd, Native *to) + { + DBUG_ASSERT(0); + return true; + } + String *str_op(String *str) + { + DBUG_ASSERT(0); + return NULL; + } void fix_arg_decimal(); - void fix_arg_int(); + void fix_arg_int(const Type_handler *preferred, + const Type_std_attributes *preferred_attributes, + bool use_decimal_on_length_increase); + void fix_arg_hex_hybrid(); void fix_arg_double(); + void fix_arg_time(); + void fix_arg_datetime(); + void fix_arg_temporal(const Type_handler *h, uint int_part_length); bool fix_length_and_dec() { - return args[0]->type_handler()->Item_func_round_fix_length_and_dec(this); + /* + We don't want to translate ENUM/SET to CHAR here. + So let's real_type_handler(), not type_handler(). + */ + return args[0]->real_type_handler()->Item_func_round_fix_length_and_dec(this); } Item *get_copy(THD *thd) { return get_item_copy<Item_func_round>(thd, this); } @@ -1585,8 +1903,8 @@ public: double val_real_native(); longlong val_int_native(); my_decimal *val_decimal_native(my_decimal *); - bool get_date_native(MYSQL_TIME *res, ulonglong fuzzydate); - bool get_time_native(MYSQL_TIME *res); + bool get_date_native(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate); + bool get_time_native(THD *thd, MYSQL_TIME *res); double val_real() { @@ -1612,12 +1930,13 @@ public: return Item_func_min_max::type_handler()-> Item_func_min_max_val_decimal(this, dec); } - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date) + bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate) { DBUG_ASSERT(fixed); return Item_func_min_max::type_handler()-> - Item_func_min_max_get_date(this, res, fuzzy_date); + Item_func_min_max_get_date(thd, this, res, fuzzydate); } + bool val_native(THD *thd, Native *to); void aggregate_attributes_real(Item **items, uint nitems) { /* @@ -1681,10 +2000,12 @@ public: double val_real() { return val_real_from_item(args[0]); } longlong val_int() { return val_int_from_item(args[0]); } String *val_str(String *str) { return val_str_from_item(args[0], str); } + bool val_native(THD *thd, Native *to) + { return val_native_from_item(thd, args[0], to); } my_decimal *val_decimal(my_decimal *dec) { return val_decimal_from_item(args[0], dec); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return get_date_from_item(args[0], ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { return get_date_from_item(thd, args[0], ltime, fuzzydate); } const char *func_name() const { return "rollup_const"; } bool const_item() const { return 0; } const Type_handler *type_handler() const { return args[0]->type_handler(); } @@ -2051,6 +2372,18 @@ protected: udf_handler udf; bool is_expensive_processor(void *arg) { return TRUE; } + class VDec_udf: public Dec_ptr_and_buffer + { + public: + VDec_udf(Item_udf_func *func, udf_handler *udf) + { + my_bool tmp_null_value; + m_ptr= udf->val_decimal(&tmp_null_value, &m_buffer); + DBUG_ASSERT(is_null() == (tmp_null_value != 0)); + func->null_value= is_null(); + } + }; + public: Item_udf_func(THD *thd, udf_func *udf_arg): Item_func(thd), udf(udf_arg) {} @@ -2128,10 +2461,12 @@ public: { return mark_unsupported_function(func_name(), "()", arg, VCOL_NON_DETERMINISTIC); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return type_handler()->Item_get_date(this, ltime, fuzzydate); + return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } + bool excl_dep_on_grouping_fields(st_select_lex *sel) + { return false; } }; @@ -2191,10 +2526,19 @@ public: Item_udf_func(thd, udf_arg) {} Item_func_udf_decimal(THD *thd, udf_func *udf_arg, List<Item> &list): Item_udf_func(thd, udf_arg, list) {} - longlong val_int(); - double val_real(); + longlong val_int() + { + return VDec_udf(this, &udf).to_longlong(unsigned_flag); + } + double val_real() + { + return VDec_udf(this, &udf).to_double(); + } my_decimal *val_decimal(my_decimal *); - String *val_str(String *str); + String *val_str(String *str) + { + return VDec_udf(this, &udf).to_string_round(str, decimals); + } const Type_handler *type_handler() const { return &type_handler_newdecimal; } bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; } Item *get_copy(THD *thd) @@ -2425,13 +2769,15 @@ public: Item_func_user_var(THD *thd, Item_func_user_var *item) :Item_hybrid_func(thd, item), m_var_entry(item->m_var_entry), name(item->name) { } - Field *create_tmp_field(bool group, TABLE *table) - { return create_table_field_from_handler(table); } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param); Field *create_field_for_create_select(TABLE *table) { return create_table_field_from_handler(table); } bool check_vcol_func_processor(void *arg); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) - { return type_handler()->Item_get_date(this, ltime, fuzzydate); } + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) + { + return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); + } }; @@ -2559,14 +2905,14 @@ public: in List<Item> and desire to place this code somewhere near other functions working with user variables. */ -class Item_user_var_as_out_param :public Item, +class Item_user_var_as_out_param :public Item_fixed_hybrid, public Load_data_outvar { LEX_CSTRING org_name; user_var_entry *entry; public: Item_user_var_as_out_param(THD *thd, const LEX_CSTRING *a) - :Item(thd) + :Item_fixed_hybrid(thd) { DBUG_ASSERT(a->length < UINT_MAX32); org_name= *a; @@ -2601,12 +2947,18 @@ public: { return 0; } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + DBUG_ASSERT(0); + return NULL; + } /* We should return something different from FIELD_ITEM here */ - enum Type type() const { return STRING_ITEM;} + enum Type type() const { return CONST_ITEM;} double val_real(); longlong val_int(); String *val_str(String *str); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); my_decimal *val_decimal(my_decimal *decimal_buffer); /* fix_fields() binds variable name with its entry structure */ bool fix_fields(THD *thd, Item **ref); @@ -2653,9 +3005,9 @@ public: String* val_str(String*); my_decimal *val_decimal(my_decimal *dec_buf) { return val_decimal_from_real(dec_buf); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { - return type_handler()->Item_get_date(this, ltime, fuzzydate); + return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate); } /* TODO: fix to support views */ const char *func_name() const { return "get_system_var"; } @@ -2914,6 +3266,8 @@ public: const Type_handler *type_handler() const; + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param); Field *create_field_for_create_select(TABLE *table) { return result_type() != STRING_RESULT ? @@ -2943,7 +3297,7 @@ public: return sp_result_field->val_decimal(dec_buf); } - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) { if (execute()) return true; @@ -2969,6 +3323,13 @@ public: return str; } + bool val_native(THD *thd, Native *to) + { + if (execute()) + return true; + return null_value= sp_result_field->val_native(to); + } + void update_null_value() { execute(); @@ -3003,6 +3364,8 @@ public: not_null_tables_cache= 0; return 0; } + bool excl_dep_on_grouping_fields(st_select_lex *sel) + { return false; } }; @@ -3097,7 +3460,8 @@ public: longlong val_int(); String *val_str(String *); my_decimal *val_decimal(my_decimal *); - bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate); + bool val_native(THD *thd, Native *); bool fix_length_and_dec(); const char *func_name() const { return "last_value"; } const Type_handler *type_handler() const { return last_value->type_handler(); } |