diff options
Diffstat (limited to 'sql/item.h')
-rw-r--r-- | sql/item.h | 2290 |
1 files changed, 1388 insertions, 902 deletions
diff --git a/sql/item.h b/sql/item.h index 4d861623836..a40f0ab082e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2,7 +2,7 @@ #define SQL_ITEM_INCLUDED /* 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 @@ -57,12 +57,46 @@ struct st_value C_MODE_END + +class Value: public st_value +{ +public: + bool is_null() const { return m_type == DYN_COL_NULL; } + bool is_longlong() const + { + return m_type == DYN_COL_UINT || m_type == DYN_COL_INT; + } + bool is_double() const { return m_type == DYN_COL_DOUBLE; } + bool is_temporal() const { return m_type == DYN_COL_DATETIME; } + bool is_string() const { return m_type == DYN_COL_STRING; } + bool is_decimal() const { return m_type == DYN_COL_DECIMAL; } +}; + + +template<size_t buffer_size> +class ValueBuffer: public Value +{ + char buffer[buffer_size]; + void reset_buffer() + { + m_string.set(buffer, buffer_size, &my_charset_bin); + } +public: + ValueBuffer() + { + reset_buffer(); + } +}; + + #ifdef DBUG_OFF static inline const char *dbug_print_item(Item *item) { return NULL; } #else const char *dbug_print_item(Item *item); #endif +class Virtual_tmp_table; +class sp_head; class Protocol; struct TABLE_LIST; void item_init(void); /* Init item functions */ @@ -100,15 +134,6 @@ enum precedence { HIGHEST_PRECEDENCE }; -typedef Bounds_checked_array<Item*> Ref_ptr_array; - -static inline uint32 -char_to_byte_length_safe(size_t char_length_arg, uint32 mbmaxlen_arg) -{ - ulonglong tmp= ((ulonglong) char_length_arg) * mbmaxlen_arg; - return tmp > UINT_MAX32 ? UINT_MAX32 : static_cast<uint32>(tmp); -} - bool mark_unsupported_function(const char *where, void *store, uint result); /* convenience helper for mark_unsupported_function() above */ @@ -119,125 +144,13 @@ bool mark_unsupported_function(const char *w1, const char *w2, #define SPLIT_SUM_SKIP_REGISTERED 1 /* Skip registered funcs */ #define SPLIT_SUM_SELECT 2 /* SELECT item; Split all parts */ -/* - "Declared Type Collation" - A combination of collation and its derivation. - - Flags for collation aggregation modes: - MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset - MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value - (i.e. constant). - MY_COLL_ALLOW_CONV - allow any kind of conversion - (combination of the above two) - MY_COLL_ALLOW_NUMERIC_CONV - if all items were numbers, convert to - @@character_set_connection - MY_COLL_DISALLOW_NONE - don't allow return DERIVATION_NONE - (e.g. when aggregating for comparison) - MY_COLL_CMP_CONV - combination of MY_COLL_ALLOW_CONV - and MY_COLL_DISALLOW_NONE -*/ - -#define MY_COLL_ALLOW_SUPERSET_CONV 1 -#define MY_COLL_ALLOW_COERCIBLE_CONV 2 -#define MY_COLL_DISALLOW_NONE 4 -#define MY_COLL_ALLOW_NUMERIC_CONV 8 - -#define MY_COLL_ALLOW_CONV (MY_COLL_ALLOW_SUPERSET_CONV | MY_COLL_ALLOW_COERCIBLE_CONV) -#define MY_COLL_CMP_CONV (MY_COLL_ALLOW_CONV | MY_COLL_DISALLOW_NONE) #define NO_EXTRACTION_FL (1 << 6) #define FULL_EXTRACTION_FL (1 << 7) #define SUBSTITUTION_FL (1 << 8) #define EXTRACTION_MASK (NO_EXTRACTION_FL | FULL_EXTRACTION_FL) -class DTCollation { -public: - CHARSET_INFO *collation; - enum Derivation derivation; - uint repertoire; - - void set_repertoire_from_charset(CHARSET_INFO *cs) - { - repertoire= cs->state & MY_CS_PUREASCII ? - MY_REPERTOIRE_ASCII : MY_REPERTOIRE_UNICODE30; - } - DTCollation() - { - collation= &my_charset_bin; - derivation= DERIVATION_NONE; - repertoire= MY_REPERTOIRE_UNICODE30; - } - DTCollation(CHARSET_INFO *collation_arg, Derivation derivation_arg) - { - collation= collation_arg; - derivation= derivation_arg; - set_repertoire_from_charset(collation_arg); - } - DTCollation(CHARSET_INFO *collation_arg, - Derivation derivation_arg, - uint repertoire_arg) - :collation(collation_arg), - derivation(derivation_arg), - repertoire(repertoire_arg) - { } - void set(const DTCollation &dt) - { - collation= dt.collation; - derivation= dt.derivation; - repertoire= dt.repertoire; - } - void set(CHARSET_INFO *collation_arg, Derivation derivation_arg) - { - collation= collation_arg; - derivation= derivation_arg; - set_repertoire_from_charset(collation_arg); - } - void set(CHARSET_INFO *collation_arg, - Derivation derivation_arg, - uint repertoire_arg) - { - collation= collation_arg; - derivation= derivation_arg; - repertoire= repertoire_arg; - } - void set_numeric() - { - collation= &my_charset_numeric; - derivation= DERIVATION_NUMERIC; - repertoire= MY_REPERTOIRE_NUMERIC; - } - void set(CHARSET_INFO *collation_arg) - { - collation= collation_arg; - set_repertoire_from_charset(collation_arg); - } - void set(Derivation derivation_arg) - { derivation= derivation_arg; } - bool aggregate(const DTCollation &dt, uint flags= 0); - bool set(DTCollation &dt1, DTCollation &dt2, uint flags= 0) - { set(dt1); return aggregate(dt2, flags); } - const char *derivation_name() const - { - switch(derivation) - { - case DERIVATION_NUMERIC: return "NUMERIC"; - case DERIVATION_IGNORABLE: return "IGNORABLE"; - case DERIVATION_COERCIBLE: return "COERCIBLE"; - case DERIVATION_IMPLICIT: return "IMPLICIT"; - case DERIVATION_SYSCONST: return "SYSCONST"; - case DERIVATION_EXPLICIT: return "EXPLICIT"; - case DERIVATION_NONE: return "NONE"; - default: return "UNKNOWN"; - } - } - int sortcmp(const String *s, const String *t) const - { - return collation->coll->strnncollsp(collation, - (uchar *) s->ptr(), s->length(), - (uchar *) t->ptr(), t->length()); - } -}; - +extern const char *item_empty_name; void dummy_error_processor(THD *thd, void *data); @@ -395,6 +308,28 @@ public: } }; +class Name_resolution_context_backup +{ + Name_resolution_context &ctx; + TABLE_LIST &table_list; + table_map save_map; + Name_resolution_context_state ctx_state; + +public: + Name_resolution_context_backup(Name_resolution_context &_ctx, TABLE_LIST &_table_list) + : ctx(_ctx), table_list(_table_list), save_map(_table_list.map) + { + ctx_state.save_state(&ctx, &table_list); + ctx.table_list= &table_list; + ctx.first_name_resolution_table= &table_list; + } + ~Name_resolution_context_backup() + { + ctx_state.restore_state(&ctx, &table_list); + table_list.map= save_map; + } +}; + /* This enum is used to report information about monotonicity of function @@ -435,6 +370,65 @@ typedef enum monotonicity_info class sp_rcontext; +/** + A helper class to collect different behavior of various kinds of SP variables: + - local SP variables and SP parameters + - PACKAGE BODY routine variables + - (there will be more kinds in the future) +*/ + +class Sp_rcontext_handler +{ +public: + virtual ~Sp_rcontext_handler() {} + /** + A prefix used for SP variable names in queries: + - EXPLAIN EXTENDED + - SHOW PROCEDURE CODE + Local variables and SP parameters have empty prefixes. + Package body variables are marked with a special prefix. + This improves readability of the output of these queries, + especially when a local variable or a parameter has the same + name with a package body variable. + */ + virtual const LEX_CSTRING *get_name_prefix() const= 0; + /** + At execution time THD->spcont points to the run-time context (sp_rcontext) + of the currently executed routine. + Local variables store their data in the sp_rcontext pointed by thd->spcont. + Package body variables store data in separate sp_rcontext that belongs + to the package. + This method provides access to the proper sp_rcontext structure, + depending on the SP variable kind. + */ + virtual sp_rcontext *get_rcontext(sp_rcontext *ctx) const= 0; +}; + + +class Sp_rcontext_handler_local: public Sp_rcontext_handler +{ +public: + const LEX_CSTRING *get_name_prefix() const; + sp_rcontext *get_rcontext(sp_rcontext *ctx) const; +}; + + +class Sp_rcontext_handler_package_body: public Sp_rcontext_handler +{ +public: + const LEX_CSTRING *get_name_prefix() const; + sp_rcontext *get_rcontext(sp_rcontext *ctx) const; +}; + + +extern MYSQL_PLUGIN_IMPORT + Sp_rcontext_handler_local sp_rcontext_handler_local; + + +extern MYSQL_PLUGIN_IMPORT + Sp_rcontext_handler_package_body sp_rcontext_handler_package_body; + + class Item_equal; @@ -483,8 +477,35 @@ public: virtual const Send_field *get_out_param_info() const { return NULL; } + + virtual Item_param *get_item_param() { return 0; } +}; + + +/* + A helper class to calculate offset and length of a query fragment + - outside of SP + - inside an SP + - inside a compound block +*/ +class Query_fragment +{ + uint m_pos; + uint m_length; + void set(size_t pos, size_t length) + { + DBUG_ASSERT(pos < UINT_MAX32); + DBUG_ASSERT(length < UINT_MAX32); + m_pos= (uint) pos; + m_length= (uint) length; + } +public: + Query_fragment(THD *thd, sp_head *sphead, const char *start, const char *end); + uint pos() const { return m_pos; } + uint length() const { return m_length; } }; + /** This is used for items in the query that needs to be rewritten before binlogging @@ -499,11 +520,11 @@ class Rewritable_query_parameter Value of 0 means that this object doesn't have to be replaced (for example SP variables in control statements) */ - uint pos_in_query; + my_ptrdiff_t pos_in_query; /* Byte length of parameter name in the statement. This is not - Item::name_length because name_length contains byte length of UTF8-encoded + Item::name.length because name.length contains byte length of UTF8-encoded name, but the query string is in the client charset. */ uint len_in_query; @@ -585,6 +606,8 @@ struct find_selective_predicates_list_processor_data List<st_cond_statistic> list; }; +class MY_LOCALE; + class Item_equal; class COND_EQUAL; @@ -606,50 +629,8 @@ public: String_copier_for_item(THD *thd): m_thd(thd) { } }; - -/** - A class to store type attributes for the standard data types. - Does not include attributes for the extended data types - such as ENUM, SET, GEOMETRY. -*/ -class Type_std_attributes -{ -public: - DTCollation collation; - uint decimals; - /* - The maximum value length in characters multiplied by collation->mbmaxlen. - Almost always it's the maximum value length in bytes. - */ - uint32 max_length; - bool unsigned_flag; - Type_std_attributes() - :collation(&my_charset_bin, DERIVATION_COERCIBLE), - decimals(0), max_length(0), unsigned_flag(false) - { } - Type_std_attributes(const Type_std_attributes *other) - :collation(other->collation), - decimals(other->decimals), - max_length(other->max_length), - unsigned_flag(other->unsigned_flag) - { } - void set(const Type_std_attributes *other) - { - *this= *other; - } - void set(const Field *field) - { - decimals= field->decimals(); - max_length= field->field_length; - collation.set(field->charset()); - unsigned_flag= MY_TEST(field->flags & UNSIGNED_FLAG); - } -}; - - class Item: public Value_source, - public Type_std_attributes, - public Type_handler + public Type_all_attributes { /** The index in the JOIN::join_tab array of the JOIN_TAB this Item is attached @@ -701,11 +682,36 @@ protected: SEL_TREE *get_mm_tree_for_const(RANGE_OPT_PARAM *param); - virtual Field *make_string_field(TABLE *table); - Field *tmp_table_field_from_field_type(TABLE *table, - bool fixed_length, - bool set_blob_packlength); - Field *create_tmp_field(bool group, TABLE *table, uint convert_int_length); + /** + Create a field based on the exact data type handler. + */ + Field *create_table_field_from_handler(TABLE *table) + { + const Type_handler *h= type_handler(); + return h->make_and_init_table_field(&name, Record_addr(maybe_null), + *this, table); + } + /** + Create a field based on field_type of argument. + This is used to create a field for + - IFNULL(x,something) + - time functions + - prepared statement placeholders + - SP variables with data type references: DECLARE a TYPE OF t1.a; + @retval NULL error + @retval !NULL on success + */ + Field *tmp_table_field_from_field_type(TABLE *table) + { + const Type_handler *h= type_handler()->type_handler_for_tmp_table(this); + return h->make_and_init_table_field(&name, Record_addr(maybe_null), + *this, table); + } + Field *create_tmp_field_int(TABLE *table, uint convert_int_length); + + void push_note_converted_to_negative_complement(THD *thd); + void push_note_converted_to_positive_complement(THD *thd); + /* Helper methods, to get an Item value from another Item */ double val_real_from_item(Item *item) { @@ -752,8 +758,6 @@ protected: */ bool make_zero_date(MYSQL_TIME *ltime, ulonglong fuzzydate); - void push_note_converted_to_negative_complement(THD *thd); - void push_note_converted_to_positive_complement(THD *thd); public: /* Cache val_str() into the own buffer, e.g. to evaluate constant @@ -761,9 +765,11 @@ public: */ String *val_str() { return val_str(&str_value); } - char * name; /* Name from select */ + const MY_LOCALE *locale_from_val_str(); + + LEX_CSTRING name; /* Name of item */ /* Original item name (if it was renamed)*/ - char * orig_name; + const char *orig_name; /** Intrusive list pointer for free list. If not null, points to the next Item on some Query_arena's free list. For instance, stored procedures @@ -772,12 +778,6 @@ public: @see Query_arena::free_list */ Item *next; - /* - TODO: convert name and name_length fields into LEX_STRING to keep them in - sync (see bug #11829681/60295 etc). Then also remove some strlen(name) - calls. - */ - uint name_length; /* Length of name */ int marker; bool maybe_null; /* If item may be null */ bool in_rollup; /* If used in GROUP BY list @@ -793,9 +793,6 @@ public: bool fixed; /* If item fixed with fix_fields */ bool is_autogenerated_name; /* indicate was name of this Item autogenerated or set by user */ - bool with_subselect; /* If this item is a subselect or some - of its arguments is or contains a - subselect */ // alloc & destruct is done as start of select on THD::mem_root Item(THD *thd); /* @@ -810,18 +807,33 @@ public: virtual ~Item() { #ifdef EXTRA_DEBUG - name=0; + name.str= 0; + name.length= 0; #endif } /*lint -e1509 */ - void set_name(THD *thd, const char *str, uint length, CHARSET_INFO *cs); + void set_name(THD *thd, const char *str, size_t length, CHARSET_INFO *cs); void set_name_no_truncate(THD *thd, const char *str, uint length, CHARSET_INFO *cs); - void set_name_for_rollback(THD *thd, const char *str, uint length, - CHARSET_INFO *cs); - void rename(char *new_name); - void init_make_field(Send_field *tmp_field,enum enum_field_types type); + void init_make_send_field(Send_field *tmp_field,enum enum_field_types type); virtual void cleanup(); - virtual void make_field(THD *thd, Send_field *field); + virtual void make_send_field(THD *thd, Send_field *field); + + bool fix_fields_if_needed(THD *thd, Item **ref) + { + return fixed ? false : fix_fields(thd, ref); + } + bool fix_fields_if_needed_for_scalar(THD *thd, Item **ref) + { + return fix_fields_if_needed(thd, ref) || check_cols(1); + } + bool fix_fields_if_needed_for_bool(THD *thd, Item **ref) + { + return fix_fields_if_needed_for_scalar(thd, ref); + } + bool fix_fields_if_needed_for_order_by(THD *thd, Item **ref) + { + return fix_fields_if_needed_for_scalar(thd, ref); + } virtual bool fix_fields(THD *, Item **); /* Fix after some tables has been pulled out. Basically re-calculate all @@ -844,54 +856,9 @@ public: */ virtual inline void quick_fix_field() { fixed= 1; } - bool store(struct st_value *value, ulonglong fuzzydate) + bool save_in_value(struct st_value *value) { - switch (cmp_type()) { - case INT_RESULT: - { - value->m_type= unsigned_flag ? DYN_COL_UINT : DYN_COL_INT; - value->value.m_longlong= val_int(); - break; - } - case REAL_RESULT: - { - value->m_type= DYN_COL_DOUBLE; - value->value.m_double= val_real(); - break; - } - case DECIMAL_RESULT: - { - value->m_type= DYN_COL_DECIMAL; - my_decimal *dec= val_decimal(&value->m_decimal); - if (dec != &value->m_decimal && !null_value) - my_decimal2decimal(dec, &value->m_decimal); - break; - } - case STRING_RESULT: - { - value->m_type= DYN_COL_STRING; - String *str= val_str(&value->m_string); - if (str != &value->m_string && !null_value) - value->m_string.set(str->ptr(), str->length(), str->charset()); - break; - } - case TIME_RESULT: - { - value->m_type= DYN_COL_DATETIME; - get_date(&value->value.m_time, fuzzydate); - break; - } - case ROW_RESULT: - DBUG_ASSERT(false); - null_value= true; - break; - } - if (null_value) - { - value->m_type= DYN_COL_NULL; - return true; - } - return false; + return type_handler()->Item_save_in_value(this, value); } /* Function returns 1 on overflow and -1 on fatal errors */ @@ -906,42 +873,84 @@ public: { return NULL; } virtual int save_safe_in_field(Field *field) { return save_in_field(field, 1); } - virtual bool send(Protocol *protocol, String *str); + virtual bool send(Protocol *protocol, st_value *buffer) + { + return type_handler()->Item_send(this, protocol, buffer); + } virtual bool eq(const Item *, bool binary_cmp) const; - const Type_handler *type_handler() const + enum_field_types field_type() const { - return get_handler_by_field_type(field_type()); + return type_handler()->field_type(); } - Field *make_num_distinct_aggregator_field(MEM_ROOT *mem_root, - const Item *item) const + virtual const Type_handler *type_handler() const= 0; + const Type_handler *type_handler_for_comparison() const { - return type_handler()->make_num_distinct_aggregator_field(mem_root, this); + return type_handler()->type_handler_for_comparison(); } - Field *make_conversion_table_field(TABLE *table, - uint metadata, const Field *target) const + virtual const Type_handler *real_type_handler() const { - DBUG_ASSERT(0); // Should not be called in Item context - return NULL; + return type_handler(); + } + virtual const Type_handler *cast_to_int_type_handler() const + { + return type_handler(); + } + virtual const Type_handler *type_handler_for_system_time() const + { + return real_type_handler(); } /* result_type() of an item specifies how the value should be returned */ - Item_result result_type() const { return type_handler()->result_type(); } + Item_result result_type() const + { + return type_handler()->result_type(); + } /* ... while cmp_type() specifies how it should be compared */ - Item_result cmp_type() const { return type_handler()->cmp_type(); } - void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, - Sort_param *param) const + Item_result cmp_type() const + { + return type_handler()->cmp_type(); + } + const Type_handler *string_type_handler() const + { + return Type_handler::string_type_handler(max_length); + } + /* + Calculate the maximum length of an expression. + This method is used in data type aggregation for UNION, e.g.: + SELECT 'b' UNION SELECT COALESCE(double_10_3_field) FROM t1; + + The result is usually equal to max_length, except for some numeric types. + In case of the INT, FLOAT, DOUBLE data types Item::max_length and + Item::decimals are ignored, so the returned value depends only on the + data type itself. E.g. for an expression of the DOUBLE(10,3) data type, + the result is always 53 (length 10 and precision 3 do not matter). + + max_length is ignored for these numeric data types because the length limit + means only "expected maximum length", it is not a hard limit, so it does + not impose any data truncation. E.g. a column of the type INT(4) can + normally store big values up to 2147483647 without truncation. When we're + aggregating such column for UNION it's important to create a long enough + result column, not to lose any data. + + For detailed behaviour of various data types see implementations of + the corresponding Type_handler_xxx::max_display_length(). + + Note, Item_field::max_display_length() overrides this to get + max_display_length() from the underlying field. + */ + virtual uint32 max_display_length() const { - type_handler()->make_sort_key(to, item, sort_field, param); + return type_handler()->max_display_length(this); } - void sortlength(THD *thd, - const Type_std_attributes *item, - SORT_FIELD_ATTR *attr) const + TYPELIB *get_typelib() const { return NULL; } + void set_maybe_null(bool maybe_null_arg) { maybe_null= maybe_null_arg; } + void set_typelib(TYPELIB *typelib) { - type_handler()->sortlength(thd, item, attr); + // Non-field Items (e.g. hybrid functions) never have ENUM/SET types yet. + DBUG_ASSERT(0); } - virtual Item_result cast_to_int_type() const { return cmp_type(); } - enum_field_types string_field_type() const + Item_cache* get_cache(THD *thd) const { - return Type_handler::string_type_handler(max_length)->field_type(); + return type_handler()->Item_get_cache(thd, this); } virtual enum Type type() const =0; /* @@ -1019,29 +1028,47 @@ public: If value is not null null_value flag will be reset to FALSE. */ virtual longlong val_int()=0; + Longlong_hybrid to_longlong_hybrid() + { + return Longlong_hybrid(val_int(), unsigned_flag); + } /** Get a value for CAST(x AS SIGNED). Too large positive unsigned integer values are converted to negative complements. Values of non-integer data types are adjusted to the SIGNED range. */ - virtual longlong val_int_signed_typecast(); + virtual longlong val_int_signed_typecast() + { + return cast_to_int_type_handler()->Item_val_int_signed_typecast(this); + } + longlong val_int_signed_typecast_from_str(); /** Get a value for CAST(x AS UNSIGNED). Negative signed integer values are converted to positive complements. Values of non-integer data types are adjusted to the UNSIGNED range. */ - virtual longlong val_int_unsigned_typecast(); - Longlong_hybrid to_longlong_hybrid() + virtual longlong val_int_unsigned_typecast() { - return Longlong_hybrid(val_int(), unsigned_flag); + return cast_to_int_type_handler()->Item_val_int_unsigned_typecast(this); } + longlong val_int_unsigned_typecast_from_decimal(); + longlong val_int_unsigned_typecast_from_int(); + longlong val_int_unsigned_typecast_from_str(); + + /** + Get a value for CAST(x AS UNSIGNED). + Huge positive unsigned values are converted to negative complements. + */ + longlong val_int_signed_typecast_from_int(); + /* This is just a shortcut to avoid the cast. You should still use unsigned_flag to check the sign of the item. */ inline ulonglong val_uint() { return (ulonglong) val_int(); } + /* Return string representation of this item object. @@ -1142,7 +1169,13 @@ public: Similar to val_str() */ virtual String *val_str_ascii(String *str); - + + /* + Returns the result of val_str_ascii(), translating NULLs back + to empty strings (if MODE_EMPTY_STRING_IS_NULL is set). + */ + String *val_str_ascii_revert_empty_string_is_null(THD *thd, String *str); + /* Returns the val_str() value converted to the given character set. */ @@ -1175,7 +1208,10 @@ public: FALSE value is false or NULL TRUE value is true (not equal to 0) */ - virtual bool val_bool(); + virtual bool val_bool() + { + return type_handler()->Item_val_bool(this); + } virtual String *val_nodeset(String*) { return 0; } bool eval_const_cond() @@ -1247,16 +1283,21 @@ public: // Check NULL value for a TIME, DATE or DATETIME expression bool is_null_from_temporal(); - int save_time_in_field(Field *field); - int save_date_in_field(Field *field); + int save_time_in_field(Field *field, bool no_conversions); + int save_date_in_field(Field *field, bool no_conversions); + int save_str_in_field(Field *field, bool no_conversions); + int save_real_in_field(Field *field, bool no_conversions); + int save_int_in_field(Field *field, bool no_conversions); + int save_decimal_in_field(Field *field, bool no_conversions); + int save_str_value_in_field(Field *field, String *result); virtual Field *get_tmp_table_field() { return 0; } virtual Field *create_field_for_create_select(TABLE *table); virtual Field *create_field_for_schema(THD *thd, TABLE *table); - virtual const char *full_name() const { return name ? name : "???"; } + virtual const char *full_name() const { return name.str ? name.str : "???"; } const char *field_name_or_null() - { return real_item()->type() == Item::FIELD_ITEM ? name : NULL; } + { return real_item()->type() == Item::FIELD_ITEM ? name.str : NULL; } const TABLE_SHARE *field_table_or_null(); /* @@ -1310,12 +1351,15 @@ public: virtual bool vcol_assignment_allowed_value() const { return false; } /* cloning of constant items (0 if it is not const) */ virtual Item *clone_item(THD *thd) { return 0; } - virtual Item* build_clone(THD *thd, MEM_ROOT *mem_root) { return get_copy(thd, mem_root); } + virtual Item* build_clone(THD *thd) { return get_copy(thd); } virtual cond_result eq_cmp_result() const { return COND_OK; } inline uint float_length(uint decimals_par) const { return decimals < FLOATING_POINT_DECIMALS ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;} /* Returns total number of decimal digits */ - virtual uint decimal_precision() const; + virtual uint decimal_precision() const + { + return type_handler()->Item_decimal_precision(this); + } /* Returns the number of integer part digits only */ inline int decimal_int_part() const { return my_decimal_int_part(decimal_precision(), decimals); } @@ -1326,10 +1370,7 @@ public: */ uint decimal_scale() const { - return decimals < NOT_FIXED_DEC ? decimals : - is_temporal_type_with_time(field_type()) ? - TIME_SECOND_PART_DIGITS : - MY_MIN(max_length, DECIMAL_MAX_SCALE); + return type_handler()->Item_decimal_scale(this); } /* Returns how many digits a divisor adds into a division result. @@ -1350,15 +1391,25 @@ public: */ uint divisor_precision_increment() const { - return decimals < NOT_FIXED_DEC ? decimals : - is_temporal_type_with_time(field_type()) ? - TIME_SECOND_PART_DIGITS : - decimals; + return type_handler()->Item_divisor_precision_increment(this); } /** TIME or DATETIME precision of the item: 0..6 */ - uint temporal_precision(enum_field_types type); + uint time_precision() + { + return const_item() ? type_handler()->Item_time_precision(this) : + MY_MIN(decimals, TIME_SECOND_PART_DIGITS); + } + uint datetime_precision() + { + return const_item() ? type_handler()->Item_datetime_precision(this) : + MY_MIN(decimals, TIME_SECOND_PART_DIGITS); + } + virtual longlong val_int_min() const + { + return LONGLONG_MIN; + } /* Returns true if this is constant (during query execution, i.e. its value will not change until next fix_fields) and its value is known. @@ -1404,6 +1455,16 @@ public: LOWEST_PRECEDENCE); } virtual void print(String *str, enum_query_type query_type); + + class Print: public String + { + public: + Print(Item *item, enum_query_type type) + { + item->print(this, type); + } + }; + void print_item_w_name(String *str, enum_query_type query_type); void print_value(String *str); @@ -1450,27 +1511,23 @@ public: void split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, Item **ref, uint flags); - virtual bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + virtual bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)= 0; + bool get_date_from_int(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date_from_year(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date_from_real(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date_from_decimal(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date_from_string(MYSQL_TIME *ltime, ulonglong fuzzydate); bool get_time(MYSQL_TIME *ltime) - { return get_date(ltime, TIME_TIME_ONLY | TIME_INVALID_DATES); } - // Get date with automatic TIME->DATETIME conversion - bool convert_time_to_datetime(THD *thd, MYSQL_TIME *ltime, ulonglong fuzzydate) - { - MYSQL_TIME tmp; - if (time_to_datetime_with_warn(thd, ltime, &tmp, fuzzydate)) - return null_value= true; - *ltime= tmp; - return false; - } - bool get_date_with_conversion(MYSQL_TIME *ltime, ulonglong fuzzydate); + { return get_date(ltime, Time::flags_for_get_date()); } /* - Get time with automatic DATE/DATETIME to TIME conversion. + Get time with automatic DATE/DATETIME to TIME conversion, + by subtracting CURRENT_DATE. - Performes a reverse operation to get_date_with_conversion(). + Performce a reverse operation to CAST(time AS DATETIME) Suppose: - we have a set of items (typically with the native MYSQL_TYPE_TIME type) whose item->get_date() return TIME1 value, and - - item->get_date_with_conversion() for the same Items return DATETIME1, + - CAST(AS DATETIME) for the same Items return DATETIME1, after applying time-to-datetime conversion to TIME1. then all items (typically of the native MYSQL_TYPE_{DATE|DATETIME} types) @@ -1499,52 +1556,30 @@ public: // Get a DATE or DATETIME value in numeric packed format for comparison virtual longlong val_datetime_packed() { - MYSQL_TIME ltime; - uint fuzzydate= TIME_FUZZY_DATES | TIME_INVALID_DATES; - return get_date_with_conversion(<ime, fuzzydate) ? 0 : pack_time(<ime); + ulonglong fuzzydate= TIME_FUZZY_DATES | TIME_INVALID_DATES; + Datetime dt(current_thd, this, fuzzydate); + return dt.is_valid_datetime() ? pack_time(dt.get_mysql_time()) : 0; } // Get a TIME value in numeric packed format for comparison virtual longlong val_time_packed() { - MYSQL_TIME ltime; - uint fuzzydate= TIME_FUZZY_DATES | TIME_INVALID_DATES | TIME_TIME_ONLY; - return get_date(<ime, fuzzydate) ? 0 : pack_time(<ime); + Time tm(this, Time::comparison_flags_for_get_date()); + return tm.is_valid_time() ? pack_time(tm.get_mysql_time()) : 0; } longlong val_datetime_packed_result(); longlong val_time_packed_result() { MYSQL_TIME ltime; - uint fuzzydate= TIME_TIME_ONLY | TIME_INVALID_DATES | TIME_FUZZY_DATES; + ulonglong fuzzydate= Time::comparison_flags_for_get_date(); return get_date_result(<ime, fuzzydate) ? 0 : pack_time(<ime); } + // Get a temporal value in packed DATE/DATETIME or TIME format longlong val_temporal_packed(enum_field_types f_type) { return f_type == MYSQL_TYPE_TIME ? val_time_packed() : val_datetime_packed(); } - enum_field_types field_type_for_temporal_comparison(const Item *other) const - { - if (cmp_type() == TIME_RESULT) - { - if (other->cmp_type() == TIME_RESULT) - return Field::field_type_merge(field_type(), other->field_type()); - else - return field_type(); - } - else - { - if (other->cmp_type() == TIME_RESULT) - return other->field_type(); - DBUG_ASSERT(0); // Two non-temporal data types, we should not get to here - return MYSQL_TYPE_DATETIME; - } - } - // Get a temporal value to compare to another Item - longlong val_temporal_packed(const Item *other) - { - return val_temporal_packed(field_type_for_temporal_comparison(other)); - } bool get_seconds(ulonglong *sec, ulong *sec_part); virtual bool get_date_result(MYSQL_TIME *ltime, ulonglong fuzzydate) { return get_date(ltime,fuzzydate); } @@ -1624,17 +1659,16 @@ public: virtual Item *copy_andor_structure(THD *thd) { return this; } virtual Item *real_item() { return this; } virtual Item *get_tmp_table_item(THD *thd) { return copy_or_same(thd); } + virtual Item *make_odbc_literal(THD *thd, const LEX_CSTRING *typestr) + { + return this; + } static CHARSET_INFO *default_charset(); - /* - For backward compatibility, to make numeric - data types return "binary" charset in client-side metadata. - */ - virtual CHARSET_INFO *charset_for_protocol(void) const + CHARSET_INFO *charset_for_protocol(void) const { - return cmp_type() == STRING_RESULT ? collation.collation : - &my_charset_bin; + return type_handler()->charset_for_protocol(this); }; virtual bool walk(Item_processor processor, bool walk_subquery, void *arg) @@ -1813,9 +1847,10 @@ public: */ virtual bool check_valid_arguments_processor(void *arg) { return 0; } virtual bool update_vcol_processor(void *arg) { return 0; } + virtual bool set_fields_as_dependent_processor(void *arg) { return 0; } /*============== End of Item processor list ======================*/ - virtual Item *get_copy(THD *thd, MEM_ROOT *mem_root)=0; + virtual Item *get_copy(THD *thd)=0; bool cache_const_expr_analyzer(uchar **arg); Item* cache_const_expr_transformer(THD *thd, uchar *arg); @@ -1857,22 +1892,34 @@ public: virtual Item **this_item_addr(THD *thd, Item **addr_arg) { return addr_arg; } // Row emulation - virtual uint cols() { return 1; } + virtual uint cols() const { return 1; } virtual Item* element_index(uint i) { return this; } virtual Item** addr(uint i) { return 0; } virtual bool check_cols(uint c); + bool check_type_traditional_scalar(const char *opname) const; + bool check_type_scalar(const char *opname) const; + bool check_type_or_binary(const char *opname, const Type_handler *handler) const; + bool check_type_general_purpose_string(const char *opname) const; + bool check_type_can_return_int(const char *opname) const; + bool check_type_can_return_decimal(const char *opname) const; + bool check_type_can_return_real(const char *opname) const; + bool check_type_can_return_str(const char *opname) const; + bool check_type_can_return_text(const char *opname) const; + bool check_type_can_return_date(const char *opname) const; + bool check_type_can_return_time(const char *opname) const; // It is not row => null inside is impossible virtual bool null_inside() { return 0; } // used in row subselects to get value of elements virtual void bring_value() {} + const Type_handler *type_handler_long_or_longlong() const + { + return Type_handler::type_handler_long_or_longlong(max_char_length()); + } + virtual Field *create_tmp_field(bool group, TABLE *table) { - /* - Values with MY_INT32_NUM_DECIMAL_DIGITS digits may or may not fit into - Field_long : make them Field_longlong. - */ - return create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS - 2); + return tmp_table_field_from_field_type(table); } virtual Item_field *field_for_view_update() { return 0; } @@ -1889,6 +1936,8 @@ public: virtual Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg) { return this; } + virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg) + { return this; } virtual bool expr_cache_is_needed(THD *) { return FALSE; } virtual Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs); bool needs_charset_converter(uint32 length, CHARSET_INFO *tocs) const @@ -1961,7 +2010,7 @@ public: Load_data_outvar *dst= get_load_data_outvar(); if (dst) return dst; - my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), name); + my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), name.str); return NULL; } @@ -1989,10 +2038,14 @@ public: } virtual Field::geometry_type get_geometry_type() const { return Field::GEOM_GEOMETRY; }; + uint uint_geometry_type() const + { return get_geometry_type(); } + void set_geometry_type(uint type) + { + DBUG_ASSERT(0); + } String *check_well_formed_result(String *str, bool send_error= 0); bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs); - uint32 max_char_length() const - { return max_length / collation.collation->mbmaxlen; } bool too_big_for_varchar() const { return max_char_length() > CONVERT_IF_BIGGER_TO_BLOB; } void fix_length_and_charset(uint32 max_char_length_arg, CHARSET_INFO *cs) @@ -2011,9 +2064,10 @@ public: virtual bool is_outer_field() const { DBUG_ASSERT(fixed); return FALSE; } /** - Checks if this item or any of its decendents contains a subquery. + Checks if this item or any of its decendents contains a subquery. This is a + replacement of the former Item::has_subquery() and Item::with_subselect. */ - virtual bool has_subquery() const { return with_subselect; } + virtual bool with_subquery() const { DBUG_ASSERT(fixed); return false; } Item* set_expr_cache(THD *thd); @@ -2079,16 +2133,83 @@ public: } }; +MEM_ROOT *get_thd_memroot(THD *thd); template <class T> -inline Item* get_item_copy (THD *thd, MEM_ROOT *mem_root, T* item) +inline Item* get_item_copy (THD *thd, T* item) { - Item *copy= new (mem_root) T(*item); - copy->register_in(thd); + Item *copy= new (get_thd_memroot(thd)) T(*item); + if (likely(copy)) + copy->register_in(thd); return copy; } +/* + This class is a replacement for the former member Item::with_subselect. + Determines if the descendant Item is a subselect or some of + its arguments is or contains a subselect. +*/ +class With_subquery_cache +{ +protected: + bool m_with_subquery; +public: + With_subquery_cache(): m_with_subquery(false) { } + void join(const Item *item) { m_with_subquery|= item->with_subquery(); } +}; + + +class Type_geometry_attributes +{ + uint m_geometry_type; + static const uint m_geometry_type_unknown= Field::GEOM_GEOMETRYCOLLECTION + 1; + void copy(const Type_handler *handler, const Type_all_attributes *gattr) + { + // Ignore implicit NULLs + m_geometry_type= handler == &type_handler_geometry ? + gattr->uint_geometry_type() : + m_geometry_type_unknown; + } +public: + Type_geometry_attributes() + :m_geometry_type(m_geometry_type_unknown) + { } + Type_geometry_attributes(const Type_handler *handler, + const Type_all_attributes *gattr) + :m_geometry_type(m_geometry_type_unknown) + { + copy(handler, gattr); + } + void join(const Item *item) + { + // Ignore implicit NULLs + if (m_geometry_type == m_geometry_type_unknown) + copy(item->type_handler(), item); + else if (item->type_handler() == &type_handler_geometry) + { + m_geometry_type= + Field_geom::geometry_type_merge((Field_geom::geometry_type) + m_geometry_type, + (Field_geom::geometry_type) + item->uint_geometry_type()); + } + } + Field::geometry_type get_geometry_type() const + { + return m_geometry_type == m_geometry_type_unknown ? + Field::GEOM_GEOMETRY : + (Field::geometry_type) m_geometry_type; + } + void set_geometry_type(uint type) + { + DBUG_ASSERT(type <= m_geometry_type_unknown); + m_geometry_type= type; + } +}; + + + /** Compare two Items for List<Item>::add_unique() */ @@ -2096,6 +2217,115 @@ inline Item* get_item_copy (THD *thd, MEM_ROOT *mem_root, T* item) bool cmp_items(Item *a, Item *b); +/** + Array of items, e.g. function or aggerate function arguments. +*/ +class Item_args +{ +protected: + Item **args, *tmp_arg[2]; + uint arg_count; + void set_arguments(THD *thd, List<Item> &list); + bool walk_args(Item_processor processor, bool walk_subquery, void *arg) + { + for (uint i= 0; i < arg_count; i++) + { + if (args[i]->walk(processor, walk_subquery, arg)) + return true; + } + return false; + } + bool transform_args(THD *thd, Item_transformer transformer, uchar *arg); + void propagate_equal_fields(THD *, const Item::Context &, COND_EQUAL *); + bool excl_dep_on_table(table_map tab_map) + { + for (uint i= 0; i < arg_count; i++) + { + if (args[i]->const_item()) + continue; + if (!args[i]->excl_dep_on_table(tab_map)) + return false; + } + return true; + } + bool excl_dep_on_grouping_fields(st_select_lex *sel) + { + for (uint i= 0; i < arg_count; i++) + { + if (args[i]->const_item()) + continue; + if (!args[i]->excl_dep_on_grouping_fields(sel)) + return false; + } + return true; + } + bool eq(const Item_args *other, bool binary_cmp) const + { + for (uint i= 0; i < arg_count ; i++) + { + if (!args[i]->eq(other->args[i], binary_cmp)) + return false; + } + return true; + } +public: + Item_args(void) + :args(NULL), arg_count(0) + { } + Item_args(Item *a) + :args(tmp_arg), arg_count(1) + { + args[0]= a; + } + Item_args(Item *a, Item *b) + :args(tmp_arg), arg_count(2) + { + args[0]= a; args[1]= b; + } + Item_args(THD *thd, Item *a, Item *b, Item *c) + { + arg_count= 0; + if (likely((args= (Item**) thd_alloc(thd, sizeof(Item*) * 3)))) + { + arg_count= 3; + args[0]= a; args[1]= b; args[2]= c; + } + } + Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d) + { + arg_count= 0; + if (likely((args= (Item**) thd_alloc(thd, sizeof(Item*) * 4)))) + { + arg_count= 4; + args[0]= a; args[1]= b; args[2]= c; args[3]= d; + } + } + Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e) + { + arg_count= 5; + if (likely((args= (Item**) thd_alloc(thd, sizeof(Item*) * 5)))) + { + arg_count= 5; + args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e; + } + } + Item_args(THD *thd, List<Item> &list) + { + set_arguments(thd, list); + } + Item_args(THD *thd, const Item_args *other); + bool alloc_arguments(THD *thd, uint count); + void add_argument(Item *item) + { + args[arg_count++]= item; + } + inline Item **arguments() const { return args; } + inline uint argument_count() const { return arg_count; } + inline void remove_arguments() { arg_count=0; } + Sql_mode_dependency value_depends_on_sql_mode_bit_or() const; +}; + + /* Class to be used to enumerate all field references in an item tree. This includes references to outside but not fields of the tables within a @@ -2121,7 +2351,6 @@ public: Field_enumerator() {} /* Remove gcc warning */ }; -class sp_head; class Item_string; @@ -2163,7 +2392,8 @@ protected: uint repertoire() const { return MY_STRING_METADATA::repertoire; } size_t char_length() const { return MY_STRING_METADATA::char_length; } }; - void fix_charset_and_length_from_str_value(Derivation dv, Metadata metadata) + void fix_charset_and_length(CHARSET_INFO *cs, + Derivation dv, Metadata metadata) { /* We have to have a different max_length than 'length' here to @@ -2172,13 +2402,13 @@ protected: number of chars for a string of this type because we in Create_field:: divide the max_length with mbmaxlen). */ - collation.set(str_value.charset(), dv, metadata.repertoire()); + collation.set(cs, dv, metadata.repertoire()); fix_char_length(metadata.char_length()); decimals= NOT_FIXED_DEC; } - void fix_charset_and_length_from_str_value(Derivation dv) + void fix_charset_and_length_from_str_value(const String &str, Derivation dv) { - fix_charset_and_length_from_str_value(dv, Metadata(&str_value)); + fix_charset_and_length(str.charset(), dv, Metadata(&str)); } Item_basic_value(THD *thd): Item(thd) {} /* @@ -2221,6 +2451,12 @@ public: void set_used_tables(table_map map) { used_table_map= map; } table_map used_tables() const { return used_table_map; } bool check_vcol_func_processor(void *arg) { return FALSE;} + virtual Item_basic_constant *make_string_literal_concat(THD *thd, + const LEX_CSTRING *) + { + DBUG_ASSERT(0); + return this; + } /* to prevent drop fixed flag (no need parent cleanup call) */ void cleanup() { @@ -2230,7 +2466,10 @@ public: done again between subsequent executions of a prepared statement. */ if (orig_name) - name= orig_name; + { + name.str= orig_name; + name.length= strlen(orig_name); + } } }; @@ -2251,37 +2490,39 @@ protected: */ THD *m_thd; + bool fix_fields_from_item(THD *thd, Item **, const Item *); public: - LEX_STRING m_name; + LEX_CSTRING m_name; public: -#ifndef DBUG_OFF +#ifdef DBUG_ASSERT_EXISTS /* Routine to which this Item_splocal belongs. Used for checking if correct runtime context is used for variable handling. */ - sp_head *m_sp; + const sp_head *m_sp; #endif public: - Item_sp_variable(THD *thd, char *sp_var_name_str, uint sp_var_name_length); + Item_sp_variable(THD *thd, const LEX_CSTRING *sp_var_name); public: - bool fix_fields(THD *thd, Item **); + bool fix_fields(THD *thd, Item **)= 0; double val_real(); longlong val_int(); String *val_str(String *sp); my_decimal *val_decimal(my_decimal *decimal_value); + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); bool is_null(); public: - inline void make_field(THD *thd, Send_field *field); + void make_send_field(THD *thd, Send_field *field); inline bool const_item() const; inline int save_in_field(Field *field, bool no_conversions); - inline bool send(Protocol *protocol, String *str); + inline bool send(Protocol *protocol, st_value *buffer); bool check_vcol_func_processor(void *arg) { return mark_unsupported_function(m_name.str, arg, VCOL_IMPOSSIBLE); @@ -2292,17 +2533,6 @@ public: Item_sp_variable inline implementation. *****************************************************************************/ -inline void Item_sp_variable::make_field(THD *thd, Send_field *field) -{ - Item *it= this_item(); - - if (name) - it->set_name(thd, name, (uint) strlen(name), system_charset_info); - else - it->set_name(thd, m_name.str, (uint) m_name.length, system_charset_info); - it->make_field(thd, field); -} - inline bool Item_sp_variable::const_item() const { return TRUE; @@ -2313,9 +2543,9 @@ inline int Item_sp_variable::save_in_field(Field *field, bool no_conversions) return this_item()->save_in_field(field, no_conversions); } -inline bool Item_sp_variable::send(Protocol *protocol, String *str) +inline bool Item_sp_variable::send(Protocol *protocol, st_value *buffer) { - return this_item()->send(protocol, str); + return this_item()->send(protocol, buffer); } @@ -2329,14 +2559,25 @@ class Item_splocal :public Item_sp_variable, public Rewritable_query_parameter, public Type_handler_hybrid_field_type { +protected: + const Sp_rcontext_handler *m_rcontext_handler; + uint m_var_idx; Type m_type; + + bool append_value_for_log(THD *thd, String *str); + + sp_rcontext *get_rcontext(sp_rcontext *local_ctx) const; + Item_field *get_variable(sp_rcontext *ctx) const; + public: - Item_splocal(THD *thd, const LEX_STRING &sp_var_name, uint sp_var_idx, - enum_field_types sp_var_type, + Item_splocal(THD *thd, const Sp_rcontext_handler *rh, + const LEX_CSTRING *sp_var_name, uint sp_var_idx, + const Type_handler *handler, uint pos_in_q= 0, uint len_in_q= 0); + bool fix_fields(THD *, Item **); Item *this_item(); const Item *this_item() const; Item **this_item_addr(THD *thd, Item **); @@ -2344,17 +2585,17 @@ public: virtual void print(String *str, enum_query_type query_type); public: - inline const LEX_STRING *my_name() const; + inline const LEX_CSTRING *my_name() const; inline uint get_var_idx() const; inline enum Type type() const; - enum_field_types field_type() const - { return Type_handler_hybrid_field_type::field_type(); } - enum Item_result result_type () const - { return Type_handler_hybrid_field_type::result_type(); } - enum Item_result cmp_type () const - { return Type_handler_hybrid_field_type::cmp_type(); } + const Type_handler *type_handler() const + { return Type_handler_hybrid_field_type::type_handler(); } + uint cols() const { return this_item()->cols(); } + Item* element_index(uint i) { return this_item()->element_index(i); } + Item** addr(uint i) { return this_item()->addr(i); } + bool check_cols(uint c); private: bool set_value(THD *thd, sp_rcontext *ctx, Item **it); @@ -2370,14 +2611,97 @@ public: bool append_for_log(THD *thd, String *str); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; } + Item *get_copy(THD *thd) { return 0; } + + /* + Override the inherited create_field_for_create_select(), + because we want to preserve the exact data type for: + DECLARE a1 INT; + DECLARE a2 TYPE OF t1.a2; + CREATE TABLE t1 AS SELECT a1, a2; + The inherited implementation would create a column + based on result_type(), which is less exact. + */ + Field *create_field_for_create_select(TABLE *table) + { return create_table_field_from_handler(table); } +}; + + +/** + An Item_splocal variant whose data type becomes known only at + sp_rcontext creation time, e.g. "DECLARE var1 t1.col1%TYPE". +*/ +class Item_splocal_with_delayed_data_type: public Item_splocal +{ +public: + Item_splocal_with_delayed_data_type(THD *thd, + const Sp_rcontext_handler *rh, + const LEX_CSTRING *sp_var_name, + uint sp_var_idx, + uint pos_in_q, uint len_in_q) + :Item_splocal(thd, rh, sp_var_name, sp_var_idx, &type_handler_null, + pos_in_q, len_in_q) + { } +}; + + +/** + SP variables that are fields of a ROW. + DELCARE r ROW(a INT,b INT); + SELECT r.a; -- This is handled by Item_splocal_row_field +*/ +class Item_splocal_row_field :public Item_splocal +{ +protected: + LEX_CSTRING m_field_name; + uint m_field_idx; + bool set_value(THD *thd, sp_rcontext *ctx, Item **it); +public: + Item_splocal_row_field(THD *thd, + const Sp_rcontext_handler *rh, + const LEX_CSTRING *sp_var_name, + const LEX_CSTRING *sp_field_name, + uint sp_var_idx, uint sp_field_idx, + const Type_handler *handler, + uint pos_in_q= 0, uint len_in_q= 0) + :Item_splocal(thd, rh, sp_var_name, sp_var_idx, handler, pos_in_q, len_in_q), + m_field_name(*sp_field_name), + m_field_idx(sp_field_idx) + { } + bool fix_fields(THD *thd, Item **); + Item *this_item(); + const Item *this_item() const; + Item **this_item_addr(THD *thd, Item **); + bool append_for_log(THD *thd, String *str); + void print(String *str, enum_query_type query_type); }; + +class Item_splocal_row_field_by_name :public Item_splocal_row_field +{ + bool set_value(THD *thd, sp_rcontext *ctx, Item **it); +public: + Item_splocal_row_field_by_name(THD *thd, + const Sp_rcontext_handler *rh, + const LEX_CSTRING *sp_var_name, + const LEX_CSTRING *sp_field_name, + uint sp_var_idx, + const Type_handler *handler, + uint pos_in_q= 0, uint len_in_q= 0) + :Item_splocal_row_field(thd, rh, sp_var_name, sp_field_name, + sp_var_idx, 0 /* field index will be set later */, + handler, pos_in_q, len_in_q) + { } + bool fix_fields(THD *thd, Item **it); + void print(String *str, enum_query_type query_type); +}; + + /***************************************************************************** Item_splocal inline implementation. *****************************************************************************/ -inline const LEX_STRING *Item_splocal::my_name() const +inline const LEX_CSTRING *Item_splocal::my_name() const { return &m_name; } @@ -2402,13 +2726,13 @@ public: Item_case_expr(THD *thd, uint case_expr_id); public: + bool fix_fields(THD *thd, Item **); Item *this_item(); const Item *this_item() const; Item **this_item_addr(THD *thd, Item **); inline enum Type type() const; - inline Item_result result_type() const; - enum_field_types field_type() const { return this_item()->field_type(); } + const Type_handler *type_handler() const { return this_item()->type_handler(); } public: /* @@ -2417,7 +2741,7 @@ public: purposes. */ virtual void print(String *str, enum_query_type query_type); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; } + Item *get_copy(THD *thd) { return 0; } private: uint m_case_expr_id; @@ -2432,12 +2756,6 @@ inline enum Item::Type Item_case_expr::type() const return this_item()->type(); } -inline Item_result Item_case_expr::result_type() const -{ - return this_item()->result_type(); -} - - /* NAME_CONST(given_name, const_value). This 'function' has all properties of the supplied const_value (which is @@ -2467,17 +2785,13 @@ public: longlong val_int(); String *val_str(String *sp); my_decimal *val_decimal(my_decimal *); + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); bool is_null(); virtual void print(String *str, enum_query_type query_type); - enum_field_types field_type() const - { - return value_item->field_type(); - } - - Item_result result_type() const + const Type_handler *type_handler() const { - return value_item->result_type(); + return value_item->type_handler(); } bool const_item() const @@ -2490,16 +2804,16 @@ public: return value_item->save_in_field(field, no_conversions); } - bool send(Protocol *protocol, String *str) + bool send(Protocol *protocol, st_value *buffer) { - return value_item->send(protocol, str); + return value_item->send(protocol, buffer); } bool check_vcol_func_processor(void *arg) { return mark_unsupported_function("name_const()", arg, VCOL_IMPOSSIBLE); } - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_name_const>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_name_const>(thd, this); } }; class Item_num: public Item_basic_constant @@ -2508,6 +2822,10 @@ public: Item_num(THD *thd): Item_basic_constant(thd) { collation.set_numeric(); } Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs); bool check_partition_func_processor(void *int_arg) { return FALSE;} + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { + return type_handler()->Item_get_date(this, ltime, fuzzydate); + } }; #define NO_CACHED_FIELD_INDEX ((uint)(-1)) @@ -2554,13 +2872,13 @@ protected: */ const char *orig_db_name; const char *orig_table_name; - const char *orig_field_name; + LEX_CSTRING orig_field_name; public: Name_resolution_context *context; const char *db_name; const char *table_name; - const char *field_name; + LEX_CSTRING field_name; bool alias_name_used; /* true if item was resolved against alias */ /* Cached value of index for this field in table->field array, used by prep. @@ -2590,9 +2908,9 @@ public: bool can_be_depended; Item_ident(THD *thd, Name_resolution_context *context_arg, const char *db_name_arg, const char *table_name_arg, - const char *field_name_arg); + const LEX_CSTRING *field_name_arg); Item_ident(THD *thd, Item_ident *item); - Item_ident(THD *thd, TABLE_LIST *view_arg, const char *field_name_arg); + Item_ident(THD *thd, TABLE_LIST *view_arg, const LEX_CSTRING *field_name_arg); const char *full_name() const; void cleanup(); st_select_lex *get_depended_from() const; @@ -2621,19 +2939,26 @@ public: Item_ident_for_show(THD *thd, Field *par_field, const char *db_arg, const char *table_name_arg): Item(thd), field(par_field), db_name(db_arg), table_name(table_name_arg) - {} - + { + Type_std_attributes::set(par_field->type_std_attributes()); + } enum Type type() const { return FIELD_ITEM; } double val_real() { return field->val_real(); } longlong val_int() { return field->val_int(); } String *val_str(String *str) { return field->val_str(str); } my_decimal *val_decimal(my_decimal *dec) { return field->val_decimal(dec); } - void make_field(THD *thd, Send_field *tmp_field); - CHARSET_INFO *charset_for_protocol(void) const - { return field->charset_for_protocol(); } - enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } - Item* get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_ident_for_show>(thd, mem_root, this); } + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { + return field->get_date(ltime, fuzzydate); + } + void make_send_field(THD *thd, Send_field *tmp_field); + const Type_handler *type_handler() const + { + const Type_handler *handler= field->type_handler(); + return handler->type_handler_for_item_field(); + } + Item* get_copy(THD *thd) + { return get_item_copy<Item_ident_for_show>(thd, this); } }; @@ -2654,7 +2979,7 @@ public: bool any_privileges; Item_field(THD *thd, Name_resolution_context *context_arg, const char *db_arg,const char *table_name_arg, - const char *field_name_arg); + const LEX_CSTRING *field_name_arg); /* Constructor needed to process subselect with temporary tables (see Item) */ @@ -2684,7 +3009,7 @@ public: my_decimal *val_decimal_result(my_decimal *); bool val_bool_result(); bool is_null_result(); - bool send(Protocol *protocol, String *str_arg); + bool send(Protocol *protocol, st_value *buffer); Load_data_outvar *get_load_data_outvar() { return this; @@ -2712,24 +3037,28 @@ public: void reset_field(Field *f); bool fix_fields(THD *, Item **); void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge); - void make_field(THD *thd, Send_field *tmp_field); + void make_send_field(THD *thd, Send_field *tmp_field); int save_in_field(Field *field,bool no_conversions); void save_org_in_field(Field *field, fast_field_copier optimizer_data); fast_field_copier setup_fast_field_copier(Field *field); table_map used_tables() const; table_map all_used_tables() const; - enum Item_result result_type () const + const Type_handler *type_handler() const { - return field->result_type(); + const Type_handler *handler= field->type_handler(); + return handler->type_handler_for_item_field(); } - Item_result cast_to_int_type() const + const Type_handler *cast_to_int_type_handler() const { - return field->cmp_type(); + return field->type_handler()->cast_to_int_type_handler(); } - enum_field_types field_type() const + const Type_handler *real_type_handler() const { - return field->type(); + if (field->is_created_from_null_item) + return &type_handler_null; + return field->type_handler(); } + TYPELIB *get_typelib() const { return field->get_typelib(); } enum_monotonicity_info get_monotonicity_info() const { return MONOTONIC_STRICT_INCREASING; @@ -2785,8 +3114,7 @@ public: cond_equal_ref); } bool is_result_field() { return false; } - void set_result_field(Field *field_arg) {} - void save_in_result_field(bool no_conversions) { } + void save_in_result_field(bool no_conversions); Item *get_tmp_table_item(THD *thd); bool collect_item_field_processor(void * arg); bool add_field_to_set_processor(void * arg); @@ -2809,9 +3137,18 @@ public: if (field && (field->unireg_check == Field::NEXT_NUMBER)) { // Auto increment fields are unsupported - return mark_unsupported_function(field_name, arg, VCOL_FIELD_REF | VCOL_AUTO_INC); + return mark_unsupported_function(field_name.str, arg, VCOL_FIELD_REF | VCOL_AUTO_INC); + } + return mark_unsupported_function(field_name.str, arg, VCOL_FIELD_REF); + } + bool set_fields_as_dependent_processor(void *arg) + { + if (!(used_tables() & OUTER_REF_TABLE_BIT)) + { + depended_from= (st_select_lex *) arg; + item_equal= NULL; } - return mark_unsupported_function(field_name, arg, VCOL_FIELD_REF); + return 0; } void cleanup(); Item_equal *get_item_equal() { return item_equal; } @@ -2819,7 +3156,7 @@ public: Item_equal *find_item_equal(COND_EQUAL *cond_equal); Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *); Item *replace_equal_field(THD *thd, uchar *arg); - inline uint32 max_disp_length() { return field->max_display_length(); } + uint32 max_display_length() const { return field->max_display_length(); } Item_field *field_for_view_update() { return this; } int fix_outer_field(THD *thd, Field **field, Item **reference); virtual Item *update_value_transformer(THD *thd, uchar *select_arg); @@ -2834,8 +3171,8 @@ public: bool cleanup_excluding_const_fields_processor(void *arg) { return field && const_item() ? 0 : cleanup_processor(arg); } - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_field>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_field>(thd, this); } bool is_outer_field() const { DBUG_ASSERT(fixed); @@ -2846,14 +3183,43 @@ public: DBUG_ASSERT(field_type() == MYSQL_TYPE_GEOMETRY); return field->get_geometry_type(); } - CHARSET_INFO *charset_for_protocol(void) const - { return field->charset_for_protocol(); } friend class Item_default_value; friend class Item_insert_value; friend class st_select_lex_unit; }; +/** + Item_field for the ROW data type +*/ +class Item_field_row: public Item_field, + public Item_args +{ +public: + Item_field_row(THD *thd, Field *field) + :Item_field(thd, field), + Item_args() + { } + Item *get_copy(THD *thd) + { return get_item_copy<Item_field_row>(thd, this); } + + const Type_handler *type_handler() const { return &type_handler_row; } + uint cols() const { return arg_count; } + Item* element_index(uint i) { return arg_count ? args[i] : this; } + Item** addr(uint i) { return arg_count ? args + i : NULL; } + bool check_cols(uint c) + { + if (cols() != c) + { + my_error(ER_OPERAND_COLUMNS, MYF(0), c); + return true; + } + return false; + } + bool row_create_items(THD *thd, List<Spvar_definition> *list); +}; + + /* @brief Item_temptable_field is the same as Item_field, except that print() @@ -2897,12 +3263,13 @@ public: class Item_null :public Item_basic_constant { public: - Item_null(THD *thd, char *name_par=0, CHARSET_INFO *cs= &my_charset_bin): + Item_null(THD *thd, const char *name_par=0, CHARSET_INFO *cs= &my_charset_bin): Item_basic_constant(thd) { maybe_null= null_value= TRUE; max_length= 0; - name= name_par ? name_par : (char*) "NULL"; + name.str= name_par ? name_par : "NULL"; + name.length= strlen(name.str); fixed= 1; collation.set(cs, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII); } @@ -2918,9 +3285,8 @@ public: longlong val_time_packed(); int save_in_field(Field *field, bool no_conversions); int save_safe_in_field(Field *field); - bool send(Protocol *protocol, String *str); - enum Item_result result_type () const { return STRING_RESULT; } - enum_field_types field_type() const { return MYSQL_TYPE_NULL; } + bool send(Protocol *protocol, st_value *buffer); + const Type_handler *type_handler() const { return &type_handler_null; } bool basic_const_item() const { return 1; } Item *clone_item(THD *thd); bool is_null() { return 1; } @@ -2932,8 +3298,10 @@ public: Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs); bool check_partition_func_processor(void *int_arg) {return FALSE;} - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_null>(thd, mem_root, this); } + Item_basic_constant *make_string_literal_concat(THD *thd, + const LEX_CSTRING *); + Item *get_copy(THD *thd) + { return get_item_copy<Item_null>(thd, this); } }; class Item_null_result :public Item_null @@ -2942,21 +3310,10 @@ public: Field *result_field; Item_null_result(THD *thd): Item_null(thd), result_field(0) {} bool is_result_field() { return result_field != 0; } -#if MARIADB_VERSION_ID < 100300 enum_field_types field_type() const { return result_field->type(); } - CHARSET_INFO *charset_for_protocol(void) const - { - return collation.collation; - } -#else - const Type_handler *type_handler() const - { - return result_field->type_handler(); - } -#endif void save_in_result_field(bool no_conversions) { save_in_field(result_field, no_conversions); @@ -2978,12 +3335,28 @@ public: For example in case of 'SELECT ?' you'll get MYSQL_TYPE_STRING both in result set and placeholders metadata, no matter what type you will supply for this placeholder in mysql_stmt_execute. + + Item_param has two Type_handler pointers, + which can point to different handlers: + + 1. In the Type_handler_hybrid_field_type member + It's initialized in: + - Item_param::setup_conversion(), for client-server PS protocol, + according to the bind type. + - Item_param::set_from_item(), for EXECUTE and EXECUTE IMMEDIATE, + according to the actual parameter data type. + + 2. In the "value" member. + It's initialized in: + - Item_param::set_param_func(), for client-server PS protocol. + - Item_param::set_from_item(), for EXECUTE and EXECUTE IMMEDIATE. */ class Item_param :public Item_basic_value, private Settable_routine_parameter, public Rewritable_query_parameter, - public Type_handler_hybrid_field_type + private Type_handler_hybrid_field_type, + public Type_geometry_attributes { /* NO_VALUE is a special value meaning that the parameter has not been @@ -3028,9 +3401,8 @@ class Item_param :public Item_basic_value, */ enum enum_item_param_state { - NO_VALUE, NULL_VALUE, INT_VALUE, REAL_VALUE, - STRING_VALUE, TIME_VALUE, LONG_DATA_VALUE, - DECIMAL_VALUE, DEFAULT_VALUE, IGNORE_VALUE + NO_VALUE, NULL_VALUE, SHORT_DATA_VALUE, LONG_DATA_VALUE, + DEFAULT_VALUE, IGNORE_VALUE } state; enum Type item_type; @@ -3043,7 +3415,6 @@ class Item_param :public Item_basic_value, void fix_temporal(uint32 max_length_arg, uint decimals_arg); -public: struct CONVERSION_INFO { /* @@ -3085,11 +3456,74 @@ public: } }; + bool m_empty_string_is_null; + + class PValue_simple + { + public: + union + { + longlong integer; + double real; + CONVERSION_INFO cs_info; + MYSQL_TIME time; + }; + void swap(PValue_simple &other) + { + swap_variables(PValue_simple, *this, other); + } + }; + + class PValue: public Type_handler_hybrid_field_type, + public PValue_simple, + public Value_source + { + public: + PValue(): Type_handler_hybrid_field_type(&type_handler_null) {} + my_decimal m_decimal; + String m_string; + /* + A buffer for string and long data values. Historically all allocated + values returned from val_str() were treated as eligible to + modification. I. e. in some cases Item_func_concat can append it's + second argument to return value of the first one. Because of that we + can't return the original buffer holding string data from val_str(), + and have to have one buffer for data and another just pointing to + the data. This is the latter one and it's returned from val_str(). + Can not be declared inside the union as it's not a POD type. + */ + String m_string_ptr; + + void swap(PValue &other) + { + Type_handler_hybrid_field_type::swap(other); + PValue_simple::swap(other); + m_decimal.swap(other.m_decimal); + m_string.swap(other.m_string); + m_string_ptr.swap(other.m_string_ptr); + } + double val_real() const; + longlong val_int(const Type_std_attributes *attr) const; + my_decimal *val_decimal(my_decimal *dec, const Type_std_attributes *attr); + String *val_str(String *str, const Type_std_attributes *attr); + }; + + PValue value; + + const String *value_query_val_str(THD *thd, String* str) const; + bool value_eq(const Item *item, bool binary_cmp) const; + Item *value_clone_item(THD *thd); + bool can_return_value() const; + +public: /* Used for bulk protocol only. */ enum enum_indicator_type indicator; + const Type_handler *type_handler() const + { return Type_handler_hybrid_field_type::type_handler(); } + bool vcol_assignment_allowed_value() const { switch (state) { @@ -3098,45 +3532,21 @@ public: case IGNORE_VALUE: return true; case NO_VALUE: - case INT_VALUE: - case REAL_VALUE: - case STRING_VALUE: - case TIME_VALUE: + case SHORT_DATA_VALUE: case LONG_DATA_VALUE: - case DECIMAL_VALUE: break; } return false; } - /* - A buffer for string and long data values. Historically all allocated - values returned from val_str() were treated as eligible to - modification. I. e. in some cases Item_func_concat can append it's - second argument to return value of the first one. Because of that we - can't return the original buffer holding string data from val_str(), - and have to have one buffer for data and another just pointing to - the data. This is the latter one and it's returned from val_str(). - Can not be declared inside the union as it's not a POD type. - */ - String str_value_ptr; - my_decimal decimal_value; - union - { - longlong integer; - double real; - CONVERSION_INFO cs_info; - MYSQL_TIME time; - } value; + Field::geometry_type get_geometry_type() const + { return Type_geometry_attributes::get_geometry_type(); }; - enum_field_types field_type() const - { return Type_handler_hybrid_field_type::field_type(); } - enum Item_result result_type () const - { return Type_handler_hybrid_field_type::result_type(); } - enum Item_result cmp_type () const - { return Type_handler_hybrid_field_type::cmp_type(); } + void set_geometry_type(uint type) + { Type_geometry_attributes::set_geometry_type(type); } - Item_param(THD *thd, uint pos_in_query_arg); + Item_param(THD *thd, const LEX_CSTRING *name_arg, + uint pos_in_query_arg, uint len_in_query_arg); enum Type type() const { @@ -3144,10 +3554,22 @@ public: return item_type; } - double val_real(); - longlong val_int(); - my_decimal *val_decimal(my_decimal*); - String *val_str(String*); + double val_real() + { + return can_return_value() ? value.val_real() : 0e0; + } + longlong val_int() + { + return can_return_value() ? value.val_int(this) : 0; + } + my_decimal *val_decimal(my_decimal *dec) + { + return can_return_value() ? value.val_decimal(dec, this) : NULL; + } + String *val_str(String *str) + { + return can_return_value() ? value.val_str(str, this) : NULL; + } bool get_date(MYSQL_TIME *tm, ulonglong fuzzydate); int save_in_field(Field *field, bool no_conversions); @@ -3158,20 +3580,64 @@ public: void set_double(double i); void set_decimal(const char *str, ulong length); void set_decimal(const my_decimal *dv, bool unsigned_arg); - bool set_str(const char *str, ulong length); + bool set_str(const char *str, ulong length, + CHARSET_INFO *fromcs, CHARSET_INFO *tocs); bool set_longdata(const char *str, ulong length); void set_time(MYSQL_TIME *tm, timestamp_type type, uint32 max_length_arg); void set_time(const MYSQL_TIME *tm, uint32 max_length_arg, uint decimals_arg); bool set_from_item(THD *thd, Item *item); void reset(); + + void set_param_tiny(uchar **pos, ulong len); + void set_param_short(uchar **pos, ulong len); + void set_param_int32(uchar **pos, ulong len); + void set_param_int64(uchar **pos, ulong len); + void set_param_float(uchar **pos, ulong len); + void set_param_double(uchar **pos, ulong len); + void set_param_decimal(uchar **pos, ulong len); + void set_param_time(uchar **pos, ulong len); + void set_param_datetime(uchar **pos, ulong len); + void set_param_date(uchar **pos, ulong len); + void set_param_str(uchar **pos, ulong len); + + void setup_conversion(THD *thd, uchar param_type); + void setup_conversion_blob(THD *thd); + void setup_conversion_string(THD *thd, CHARSET_INFO *fromcs); + /* Assign placeholder value from bind data. Note, that 'len' has different semantics in embedded library (as we don't need to check that packet is not broken there). See sql_prepare.cc for details. */ - void (*set_param_func)(Item_param *param, uchar **pos, ulong len); + void set_param_func(uchar **pos, ulong len) + { + /* + To avoid Item_param::set_xxx() asserting on data type mismatch, + we set the value type handler here: + - It can not be initialized yet after Item_param::setup_conversion(). + - Also, for LIMIT clause parameters, the value type handler might have + changed from the real type handler to type_handler_longlong. + So here we'll restore it. + */ + const Type_handler *h= Item_param::type_handler(); + value.set_handler(h); + h->Item_param_set_param_func(this, pos, len); + } + bool set_value(THD *thd, const Type_all_attributes *attr, + const st_value *val, const Type_handler *h) + { + value.set_handler(h); // See comments in set_param_func() + return h->Item_param_set_from_value(thd, this, attr, val); + } + + bool set_limit_clause_param(longlong nr) + { + value.set_handler(&type_handler_longlong); + set_int(nr, MY_INT64_NUM_DECIMAL_DIGITS); + return !unsigned_flag && value.integer < 0; + } const String *query_val_str(THD *thd, String *str) const; bool convert_str_value(THD *thd); @@ -3197,7 +3663,8 @@ public: } bool has_int_value() const { - return state == INT_VALUE; + return state == SHORT_DATA_VALUE && + value.type_handler()->cmp_type() == INT_RESULT; } /* This method is used to make a copy of a basic constant item when @@ -3226,7 +3693,7 @@ public: bool append_for_log(THD *thd, String *str); bool check_vcol_func_processor(void *int_arg) {return FALSE;} - Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; } + Item *get_copy(THD *thd) { return 0; } bool add_as_clone(THD *thd); void sync_clones(); @@ -3242,7 +3709,9 @@ private: public: virtual const Send_field *get_out_param_info() const; - virtual void make_field(THD *thd, Send_field *field); + Item_param *get_item_param() { return this; } + + virtual void make_send_field(THD *thd, Send_field *field); private: Send_field *m_out_param_info; @@ -3260,23 +3729,40 @@ class Item_int :public Item_num { public: longlong value; - Item_int(THD *thd, int32 i,uint length= MY_INT32_NUM_DECIMAL_DIGITS): + Item_int(THD *thd, int32 i,size_t length= MY_INT32_NUM_DECIMAL_DIGITS): Item_num(thd), value((longlong) i) - { max_length=length; fixed= 1; } - Item_int(THD *thd, longlong i,uint length= MY_INT64_NUM_DECIMAL_DIGITS): + { max_length=(uint32)length; fixed= 1; } + Item_int(THD *thd, longlong i,size_t length= MY_INT64_NUM_DECIMAL_DIGITS): Item_num(thd), value(i) - { max_length=length; fixed= 1; } - Item_int(THD *thd, ulonglong i, uint length= MY_INT64_NUM_DECIMAL_DIGITS): + { max_length=(uint32)length; fixed= 1; } + Item_int(THD *thd, ulonglong i, size_t length= MY_INT64_NUM_DECIMAL_DIGITS): Item_num(thd), value((longlong)i) - { max_length=length; fixed= 1; unsigned_flag= 1; } - Item_int(THD *thd, const char *str_arg,longlong i,uint length): + { max_length=(uint32)length; fixed= 1; unsigned_flag= 1; } + Item_int(THD *thd, const char *str_arg,longlong i,size_t length): Item_num(thd), value(i) - { max_length=length; name=(char*) str_arg; fixed= 1; } - Item_int(THD *thd, const char *str_arg, uint length=64); + { + max_length=(uint32)length; + name.str= str_arg; name.length= safe_strlen(name.str); + fixed= 1; + } + Item_int(THD *thd, const char *str_arg,longlong i,size_t length, bool flag): + Item_num(thd), value(i) + { + max_length=(uint32)length; + name.str= str_arg; name.length= safe_strlen(name.str); + fixed= 1; + unsigned_flag= flag; + } + Item_int(THD *thd, const char *str_arg, size_t length=64); enum Type type() const { return INT_ITEM; } - enum Item_result result_type () const { return INT_RESULT; } - enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } + const Type_handler *type_handler() const + { return type_handler_long_or_longlong(); } + Field *create_tmp_field(bool group, TABLE *table) + { return tmp_table_field_from_field_type(table); } + Field *create_field_for_create_select(TABLE *table) + { return tmp_table_field_from_field_type(table); } longlong val_int() { DBUG_ASSERT(fixed == 1); return value; } + longlong val_int_min() const { DBUG_ASSERT(fixed == 1); return value; } double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; } my_decimal *val_decimal(my_decimal *); String *val_str(String*); @@ -3289,8 +3775,8 @@ public: { return (uint) (max_length - MY_TEST(value < 0)); } bool eq(const Item *item, bool binary_cmp) const { return int_eq(value, item); } - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_int>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_int>(thd, this); } }; @@ -3312,7 +3798,7 @@ public: class Item_uint :public Item_int { public: - Item_uint(THD *thd, const char *str_arg, uint length); + Item_uint(THD *thd, const char *str_arg, size_t length); Item_uint(THD *thd, ulonglong i): Item_int(thd, i, 10) {} Item_uint(THD *thd, const char *str_arg, longlong i, uint length); double val_real() @@ -3322,8 +3808,8 @@ public: virtual void print(String *str, enum_query_type query_type); Item *neg(THD *thd); uint decimal_precision() const { return max_length; } - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_uint>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_uint>(thd, this); } }; @@ -3336,7 +3822,12 @@ public: int save_in_field(Field *field, bool no_conversions); longlong val_int(); double val_real() { return (double)val_int(); } - void set(longlong packed); + void set(longlong packed, enum_mysql_timestamp_type ts_type); + bool get_date(MYSQL_TIME *to, ulonglong fuzzydate) + { + *to= ltime; + return false; + } }; @@ -3346,7 +3837,7 @@ class Item_decimal :public Item_num protected: my_decimal decimal_value; public: - Item_decimal(THD *thd, const char *str_arg, uint length, + Item_decimal(THD *thd, const char *str_arg, size_t length, CHARSET_INFO *charset); Item_decimal(THD *thd, const char *str, const my_decimal *val_arg, uint decimal_par, uint length); @@ -3356,8 +3847,7 @@ public: Item_decimal(THD *thd, const uchar *bin, int precision, int scale); enum Type type() const { return DECIMAL_ITEM; } - enum Item_result result_type () const { return DECIMAL_RESULT; } - enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; } + const Type_handler *type_handler() const { return &type_handler_newdecimal; } longlong val_int(); double val_real(); String *val_str(String*); @@ -3370,23 +3860,24 @@ public: uint decimal_precision() const { return decimal_value.precision(); } bool eq(const Item *, bool binary_cmp) const; void set_decimal_value(my_decimal *value_par); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_decimal>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_decimal>(thd, this); } }; class Item_float :public Item_num { - char *presentation; + const char *presentation; public: double value; - Item_float(THD *thd, const char *str_arg, uint length); + Item_float(THD *thd, const char *str_arg, size_t length); Item_float(THD *thd, const char *str, double val_arg, uint decimal_par, uint length): Item_num(thd), value(val_arg) { - presentation= name=(char*) str; + presentation= name.str= str; + name.length= safe_strlen(str); decimals=(uint8) decimal_par; - max_length=length; + max_length= length; fixed= 1; } Item_float(THD *thd, double value_par, uint decimal_par): @@ -3397,7 +3888,7 @@ public: } int save_in_field(Field *field, bool no_conversions); enum Type type() const { return REAL_ITEM; } - enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } + const Type_handler *type_handler() const { return &type_handler_double; } double val_real() { DBUG_ASSERT(fixed == 1); return value; } longlong val_int() { @@ -3420,8 +3911,8 @@ public: virtual void print(String *str, enum_query_type query_type); bool eq(const Item *item, bool binary_cmp) const { return real_eq(value, item); } - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_float>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_float>(thd, this); } }; @@ -3451,7 +3942,7 @@ class Item_string :public Item_basic_constant protected: void fix_from_value(Derivation dv, const Metadata metadata) { - fix_charset_and_length_from_str_value(dv, metadata); + fix_charset_and_length(str_value.charset(), dv, metadata); // it is constant => can be used without fix_fields (and frequently used) fixed= 1; } @@ -3490,7 +3981,7 @@ public: str_value.set_or_copy_aligned(str, length, cs); fix_and_set_name_from_value(thd, dv, Metadata(&str_value, repertoire)); } - Item_string(THD *thd, const char *str, uint length, + Item_string(THD *thd, const char *str, size_t length, CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE): Item_basic_constant(thd) { @@ -3506,21 +3997,21 @@ public: fix_and_set_name_from_value(thd, dv, Metadata(&str_value, repertoire)); } // Constructors with an externally provided item name - Item_string(THD *thd, const char *name_par, const char *str, uint length, + Item_string(THD *thd, const char *name_par, const char *str, size_t length, CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE): Item_basic_constant(thd) { str_value.set_or_copy_aligned(str, length, cs); fix_from_value(dv, Metadata(&str_value)); - set_name(thd, name_par, 0, system_charset_info); + set_name(thd, name_par,safe_strlen(name_par), system_charset_info); } - Item_string(THD *thd, const char *name_par, const char *str, uint length, + Item_string(THD *thd, const char *name_par, const char *str, size_t length, CHARSET_INFO *cs, Derivation dv, uint repertoire): Item_basic_constant(thd) { str_value.set_or_copy_aligned(str, length, cs); fix_from_value(dv, Metadata(&str_value, repertoire)); - set_name(thd, name_par, 0, system_charset_info); + set_name(thd, name_par, safe_strlen(name_par), system_charset_info); } void print_value(String *to) const { @@ -3535,9 +4026,12 @@ public: return (String*) &str_value; } my_decimal *val_decimal(my_decimal *); + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { + return get_date_from_string(ltime, fuzzydate); + } int save_in_field(Field *field, bool no_conversions); - enum Item_result result_type () const { return STRING_RESULT; } - enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } + const Type_handler *type_handler() const { return &type_handler_varchar; } bool basic_const_item() const { return 1; } bool eq(const Item *item, bool binary_cmp) const { @@ -3548,7 +4042,7 @@ public: { return const_charset_converter(thd, tocs, true); } - inline void append(char *str, uint length) + inline void append(const char *str, uint length) { str_value.append(str, length); max_length= str_value.numchars() * collation.collation->mbmaxlen; @@ -3583,7 +4077,7 @@ public: String *check_well_formed_result(bool send_error) { return Item::check_well_formed_result(&str_value, send_error); } - enum_field_types odbc_temporal_literal_type(const LEX_STRING *type_str) const + enum_field_types odbc_temporal_literal_type(const LEX_CSTRING *type_str) const { /* If string is a reasonably short pure ASCII string literal, @@ -3611,9 +4105,12 @@ public: } return MYSQL_TYPE_STRING; // Not a temporal literal } - - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_string>(thd, mem_root, this); } + Item_basic_constant *make_string_literal_concat(THD *thd, + const LEX_CSTRING *); + Item *make_odbc_literal(THD *thd, const LEX_CSTRING *typestr); + + Item *get_copy(THD *thd) + { return get_item_copy<Item_string>(thd, this); } }; @@ -3656,7 +4153,7 @@ public: DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII) { } Item_string_ascii(THD *thd, const char *str): - Item_string(thd, str, (uint)strlen(str), &my_charset_latin1, + Item_string(thd, str, (uint) strlen(str), &my_charset_latin1, DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII) { } }; @@ -3718,11 +4215,14 @@ class Item_return_date_time :public Item_partition_func_safe_string enum_field_types date_time_field_type; public: Item_return_date_time(THD *thd, const char *name_arg, uint length_arg, - enum_field_types field_type_arg): + enum_field_types field_type_arg, uint dec_arg= 0): Item_partition_func_safe_string(thd, name_arg, length_arg, &my_charset_bin), date_time_field_type(field_type_arg) - { decimals= 0; } - enum_field_types field_type() const { return date_time_field_type; } + { decimals= dec_arg; } + const Type_handler *type_handler() const + { + return Type_handler::get_handler_by_field_type(date_time_field_type); + } }; @@ -3730,12 +4230,22 @@ class Item_blob :public Item_partition_func_safe_string { public: Item_blob(THD *thd, const char *name_arg, uint length): - Item_partition_func_safe_string(thd, name_arg, (uint) strlen(name_arg), &my_charset_bin) + Item_partition_func_safe_string(thd, name_arg, (uint) safe_strlen(name_arg), + &my_charset_bin) { max_length= length; } enum Type type() const { return TYPE_HOLDER; } - enum_field_types field_type() const { return MYSQL_TYPE_BLOB; } + const Type_handler *type_handler() const + { + return Type_handler::blob_type_handler(max_length); + } + const Type_handler *real_type_handler() const + { + // Should not be called, Item_blob is used for SHOW purposes only. + DBUG_ASSERT(0); + return &type_handler_varchar; + } Field *create_field_for_schema(THD *thd, TABLE *table) - { return tmp_table_field_from_field_type(table, false, true); } + { return tmp_table_field_from_field_type(table); } }; @@ -3752,8 +4262,12 @@ public: CHARSET_INFO *cs= NULL): Item_partition_func_safe_string(thd, "", 0, cs ? cs : &my_charset_utf8_general_ci) - { name=(char*) header; max_length= length * collation.collation->mbmaxlen; } - void make_field(THD *thd, Send_field *field); + { + name.str= header; + name.length= strlen(name.str); + max_length= length * collation.collation->mbmaxlen; + } + void make_send_field(THD *thd, Send_field *field); }; @@ -3767,7 +4281,10 @@ public: { unsigned_flag=1; } - enum_field_types field_type() const { return int_field_type; } + const Type_handler *type_handler() const + { + return Type_handler::get_handler_by_field_type(int_field_type); + } }; @@ -3777,20 +4294,19 @@ public: class Item_hex_constant: public Item_basic_constant { private: - void hex_string_init(THD *thd, const char *str, uint str_length); + void hex_string_init(THD *thd, const char *str, size_t str_length); public: Item_hex_constant(THD *thd): Item_basic_constant(thd) { hex_string_init(thd, "", 0); } - Item_hex_constant(THD *thd, const char *str, uint str_length): + Item_hex_constant(THD *thd, const char *str, size_t str_length): Item_basic_constant(thd) { hex_string_init(thd, str, str_length); } enum Type type() const { return VARBIN_ITEM; } - enum Item_result result_type () const { return STRING_RESULT; } - enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } + const Type_handler *type_handler() const { return &type_handler_varchar; } virtual Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) { return const_charset_converter(thd, tocs, true); @@ -3800,10 +4316,14 @@ public: bool eq(const Item *item, bool binary_cmp) const { return item->basic_const_item() && item->type() == type() && - item->cast_to_int_type() == cast_to_int_type() && + item->cast_to_int_type_handler() == cast_to_int_type_handler() && str_value.bin_eq(&((Item_hex_constant*)item)->str_value); } String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; } + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { + return type_handler()->Item_get_date(this, ltime, fuzzydate); + } }; @@ -3816,8 +4336,9 @@ class Item_hex_hybrid: public Item_hex_constant { public: Item_hex_hybrid(THD *thd): Item_hex_constant(thd) {} - Item_hex_hybrid(THD *thd, const char *str, uint str_length): + Item_hex_hybrid(THD *thd, const char *str, size_t str_length): Item_hex_constant(thd, str, str_length) {} + uint decimal_precision() const; double val_real() { DBUG_ASSERT(fixed == 1); @@ -3833,7 +4354,7 @@ public: { // following assert is redundant, because fixed=1 assigned in constructor DBUG_ASSERT(fixed == 1); - ulonglong value= (ulonglong) Item_hex_hybrid::val_int(); + longlong value= Item_hex_hybrid::val_int(); int2my_decimal(E_DEC_FATAL_ERROR, value, TRUE, decimal_value); return decimal_value; } @@ -3842,10 +4363,17 @@ public: field->set_notnull(); return field->store_hex_hybrid(str_value.ptr(), str_value.length()); } - enum Item_result cast_to_int_type() const { return INT_RESULT; } + const Type_handler *cast_to_int_type_handler() const + { + return &type_handler_longlong; + } + const Type_handler *type_handler_for_system_time() const + { + return &type_handler_longlong; + } void print(String *str, enum_query_type query_type); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_hex_hybrid>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_hex_hybrid>(thd, this); } }; @@ -3862,7 +4390,7 @@ class Item_hex_string: public Item_hex_constant { public: Item_hex_string(THD *thd): Item_hex_constant(thd) {} - Item_hex_string(THD *thd, const char *str, uint str_length): + Item_hex_string(THD *thd, const char *str, size_t str_length): Item_hex_constant(thd, str, str_length) {} longlong val_int() { @@ -3884,17 +4412,16 @@ public: return field->store(str_value.ptr(), str_value.length(), collation.collation); } - enum Item_result cast_to_int_type() const { return STRING_RESULT; } void print(String *str, enum_query_type query_type); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_hex_string>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_hex_string>(thd, this); } }; class Item_bin_string: public Item_hex_hybrid { public: - Item_bin_string(THD *thd, const char *str,uint str_length); + Item_bin_string(THD *thd, const char *str, size_t str_length); }; @@ -3907,13 +4434,14 @@ public: Constructor for Item_date_literal. @param ltime DATE value. */ - Item_temporal_literal(THD *thd, MYSQL_TIME *ltime): Item_basic_constant(thd) + Item_temporal_literal(THD *thd, const MYSQL_TIME *ltime) + :Item_basic_constant(thd) { collation.set(&my_charset_numeric, DERIVATION_NUMERIC, MY_REPERTOIRE_ASCII); decimals= 0; cached_time= *ltime; } - Item_temporal_literal(THD *thd, MYSQL_TIME *ltime, uint dec_arg): + Item_temporal_literal(THD *thd, const MYSQL_TIME *ltime, uint dec_arg): Item_basic_constant(thd) { collation.set(&my_charset_numeric, DERIVATION_NUMERIC, MY_REPERTOIRE_ASCII); @@ -3924,8 +4452,6 @@ public: bool const_item() const { return true; } enum Type type() const { return DATE_ITEM; } bool eq(const Item *item, bool binary_cmp) const; - enum Item_result result_type () const { return STRING_RESULT; } - Item_result cmp_type() const { return TIME_RESULT; } bool check_partition_func_processor(void *int_arg) {return FALSE;} @@ -3941,7 +4467,7 @@ public: my_decimal *val_decimal(my_decimal *decimal_value) { return val_decimal_from_date(decimal_value); } int save_in_field(Field *field, bool no_conversions) - { return save_date_in_field(field); } + { return save_date_in_field(field, no_conversions); } }; @@ -3951,7 +4477,7 @@ public: class Item_date_literal: public Item_temporal_literal { public: - Item_date_literal(THD *thd, MYSQL_TIME *ltime) + Item_date_literal(THD *thd, const MYSQL_TIME *ltime) :Item_temporal_literal(thd, ltime) { max_length= MAX_DATE_WIDTH; @@ -3965,12 +4491,12 @@ public: */ maybe_null= !ltime->month || !ltime->day; } - enum_field_types field_type() const { return MYSQL_TYPE_DATE; } + const Type_handler *type_handler() const { return &type_handler_newdate; } void print(String *str, enum_query_type query_type); Item *clone_item(THD *thd); bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_date_literal>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_date_literal>(thd, this); } }; @@ -3980,18 +4506,18 @@ public: class Item_time_literal: public Item_temporal_literal { public: - Item_time_literal(THD *thd, MYSQL_TIME *ltime, uint dec_arg): + Item_time_literal(THD *thd, const MYSQL_TIME *ltime, uint dec_arg): Item_temporal_literal(thd, ltime, dec_arg) { max_length= MIN_TIME_WIDTH + (decimals ? decimals + 1 : 0); fixed= 1; } - enum_field_types field_type() const { return MYSQL_TYPE_TIME; } + const Type_handler *type_handler() const { return &type_handler_time2; } void print(String *str, enum_query_type query_type); Item *clone_item(THD *thd); bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_time_literal>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_time_literal>(thd, this); } }; @@ -4001,7 +4527,7 @@ public: class Item_datetime_literal: public Item_temporal_literal { public: - Item_datetime_literal(THD *thd, MYSQL_TIME *ltime, uint dec_arg): + Item_datetime_literal(THD *thd, const MYSQL_TIME *ltime, uint dec_arg): Item_temporal_literal(thd, ltime, dec_arg) { max_length= MAX_DATETIME_WIDTH + (decimals ? decimals + 1 : 0); @@ -4009,12 +4535,12 @@ public: // See the comment on maybe_null in Item_date_literal maybe_null= !ltime->month || !ltime->day; } - enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } + const Type_handler *type_handler() const { return &type_handler_datetime2; } void print(String *str, enum_query_type query_type); Item *clone_item(THD *thd); bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_datetime_literal>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_datetime_literal>(thd, this); } }; @@ -4047,7 +4573,7 @@ class Item_date_literal_for_invalid_dates: public Item_date_literal in sql_mode=TRADITIONAL. */ public: - Item_date_literal_for_invalid_dates(THD *thd, MYSQL_TIME *ltime) + Item_date_literal_for_invalid_dates(THD *thd, const MYSQL_TIME *ltime) :Item_date_literal(thd, ltime) { } bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) { @@ -4065,7 +4591,7 @@ class Item_datetime_literal_for_invalid_dates: public Item_datetime_literal { public: Item_datetime_literal_for_invalid_dates(THD *thd, - MYSQL_TIME *ltime, uint dec_arg) + const MYSQL_TIME *ltime, uint dec_arg) :Item_datetime_literal(thd, ltime, dec_arg) { } bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) { @@ -4075,101 +4601,6 @@ public: }; -/** - Array of items, e.g. function or aggerate function arguments. -*/ -class Item_args -{ -protected: - Item **args, *tmp_arg[2]; - uint arg_count; - void set_arguments(THD *thd, List<Item> &list); - bool walk_args(Item_processor processor, bool walk_subquery, void *arg) - { - for (uint i= 0; i < arg_count; i++) - { - if (args[i]->walk(processor, walk_subquery, arg)) - return true; - } - return false; - } - bool transform_args(THD *thd, Item_transformer transformer, uchar *arg); - void propagate_equal_fields(THD *, const Item::Context &, COND_EQUAL *); - bool excl_dep_on_table(table_map tab_map) - { - for (uint i= 0; i < arg_count; i++) - { - if (args[i]->const_item()) - continue; - if (!args[i]->excl_dep_on_table(tab_map)) - return false; - } - return true; - } - bool excl_dep_on_grouping_fields(st_select_lex *sel) - { - for (uint i= 0; i < arg_count; i++) - { - if (args[i]->const_item()) - continue; - if (!args[i]->excl_dep_on_grouping_fields(sel)) - return false; - } - return true; - } -public: - Item_args(void) - :args(NULL), arg_count(0) - { } - Item_args(Item *a) - :args(tmp_arg), arg_count(1) - { - args[0]= a; - } - Item_args(Item *a, Item *b) - :args(tmp_arg), arg_count(2) - { - args[0]= a; args[1]= b; - } - Item_args(THD *thd, Item *a, Item *b, Item *c) - { - arg_count= 0; - if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 3))) - { - arg_count= 3; - args[0]= a; args[1]= b; args[2]= c; - } - } - Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d) - { - arg_count= 0; - if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 4))) - { - arg_count= 4; - args[0]= a; args[1]= b; args[2]= c; args[3]= d; - } - } - Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e) - { - arg_count= 5; - if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 5))) - { - arg_count= 5; - args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e; - } - } - Item_args(THD *thd, List<Item> &list) - { - set_arguments(thd, list); - } - Item_args(THD *thd, const Item_args *other); - inline Item **arguments() const { return args; } - inline uint argument_count() const { return arg_count; } - inline void remove_arguments() { arg_count=0; } - Sql_mode_dependency value_depends_on_sql_mode_bit_or() const; -}; - - class Used_tables_and_const_cache { public: @@ -4237,82 +4668,34 @@ public: */ class Item_func_or_sum: public Item_result_field, public Item_args, - public Used_tables_and_const_cache + public Used_tables_and_const_cache, + public With_subquery_cache { - bool agg_item_collations(DTCollation &c, const char *name, - Item **items, uint nitems, - uint flags, int item_sep); - bool agg_item_set_converter(const DTCollation &coll, const char *fname, - Item **args, uint nargs, - uint flags, int item_sep); protected: - /* - Collect arguments' character sets together. - We allow to apply automatic character set conversion in some cases. - The conditions when conversion is possible are: - - arguments A and B have different charsets - - A wins according to coercibility rules - (i.e. a column is stronger than a string constant, - an explicit COLLATE clause is stronger than a column) - - character set of A is either superset for character set of B, - or B is a string constant which can be converted into the - character set of A without data loss. - - If all of the above is true, then it's possible to convert - B into the character set of A, and then compare according - to the collation of A. - - For functions with more than two arguments: - - collect(A,B,C) ::= collect(collect(A,B),C) - - Since this function calls THD::change_item_tree() on the passed Item ** - pointers, it is necessary to pass the original Item **'s, not copies. - Otherwise their values will not be properly restored (see BUG#20769). - If the items are not consecutive (eg. args[2] and args[5]), use the - item_sep argument, ie. - - agg_item_charsets(coll, fname, &args[2], 2, flags, 3) - */ bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems, uint flags, int item_sep) { - if (agg_item_collations(c, func_name(), items, nitems, flags, item_sep)) - return true; - - return agg_item_set_converter(c, func_name(), items, nitems, - flags, item_sep); + return Type_std_attributes::agg_arg_charsets(c, func_name(), + items, nitems, + flags, item_sep); } - /* - Aggregate arguments for string result, e.g: CONCAT(a,b) - - convert to @@character_set_connection if all arguments are numbers - - allow DERIVATION_NONE - */ bool agg_arg_charsets_for_string_result(DTCollation &c, Item **items, uint nitems, int item_sep= 1) { - uint flags= MY_COLL_ALLOW_SUPERSET_CONV | - MY_COLL_ALLOW_COERCIBLE_CONV | - MY_COLL_ALLOW_NUMERIC_CONV; - return agg_arg_charsets(c, items, nitems, flags, item_sep); + return Type_std_attributes:: + agg_arg_charsets_for_string_result(c, func_name(), + items, nitems, item_sep); } - /* - Aggregate arguments for string result, when some comparison - is involved internally, e.g: REPLACE(a,b,c) - - convert to @@character_set_connection if all arguments are numbers - - disallow DERIVATION_NONE - */ bool agg_arg_charsets_for_string_result_with_comparison(DTCollation &c, Item **items, uint nitems, int item_sep= 1) { - uint flags= MY_COLL_ALLOW_SUPERSET_CONV | - MY_COLL_ALLOW_COERCIBLE_CONV | - MY_COLL_ALLOW_NUMERIC_CONV | - MY_COLL_DISALLOW_NONE; - return agg_arg_charsets(c, items, nitems, flags, item_sep); + return Type_std_attributes:: + agg_arg_charsets_for_string_result_with_comparison(c, func_name(), + items, nitems, + item_sep); } /* @@ -4324,13 +4707,10 @@ protected: Item **items, uint nitems, int item_sep= 1) { - uint flags= MY_COLL_ALLOW_SUPERSET_CONV | - MY_COLL_ALLOW_COERCIBLE_CONV | - MY_COLL_DISALLOW_NONE; - return agg_arg_charsets(c, items, nitems, flags, item_sep); + return Type_std_attributes:: + agg_arg_charsets_for_comparison(c, func_name(), items, nitems, item_sep); } - public: // This method is used by Arg_comparator bool agg_arg_charsets_for_comparison(CHARSET_INFO **cs, Item **a, Item **b) @@ -4372,6 +4752,7 @@ public: Used_tables_and_const_cache(item) { } Item_func_or_sum(THD *thd, List<Item> &list): Item_result_field(thd), Item_args(thd, list) { } + bool with_subquery() const { DBUG_ASSERT(fixed); return m_with_subquery; } bool walk(Item_processor processor, bool walk_subquery, void *arg) { if (walk_args(processor, walk_subquery, arg)) @@ -4398,13 +4779,43 @@ public: virtual bool fix_length_and_dec()= 0; bool const_item() const { return const_item_cache; } table_map used_tables() const { return used_tables_cache; } - Item* build_clone(THD *thd, MEM_ROOT *mem_root); + Item* build_clone(THD *thd); Sql_mode_dependency value_depends_on_sql_mode() const { return Item_args::value_depends_on_sql_mode_bit_or().soft_to_hard(); } }; +class sp_head; +class sp_name; +struct st_sp_security_context; + +class Item_sp +{ +public: + Name_resolution_context *context; + sp_name *m_name; + sp_head *m_sp; + TABLE *dummy_table; + uchar result_buf[64]; + sp_rcontext *func_ctx; + MEM_ROOT sp_mem_root; + Query_arena *sp_query_arena; + + /* + The result field of the stored function. + */ + Field *sp_result_field; + Item_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name_arg); + Item_sp(THD *thd, Item_sp *item); + const char *func_name(THD *thd) const; + void cleanup(); + bool sp_check_access(THD *thd); + bool execute(THD *thd, bool *null_value, Item **args, uint arg_count); + bool execute_impl(THD *thd, Item **args, uint arg_count); + bool init_result_field(THD *thd, uint max_length, uint maybe_null, + bool *null_value, LEX_CSTRING *name); +}; class Item_ref :public Item_ident { @@ -4417,7 +4828,7 @@ public: bool reference_trough_name; Item_ref(THD *thd, Name_resolution_context *context_arg, const char *db_arg, const char *table_name_arg, - const char *field_name_arg): + const LEX_CSTRING *field_name_arg): Item_ident(thd, context_arg, db_arg, table_name_arg, field_name_arg), set_properties_only(0), ref(0), reference_trough_name(1) {} /* @@ -4435,10 +4846,10 @@ public: with Bar, and if we have a more broader set of problems like this. */ Item_ref(THD *thd, Name_resolution_context *context_arg, Item **item, - const char *table_name_arg, const char *field_name_arg, + const char *table_name_arg, const LEX_CSTRING *field_name_arg, bool alias_name_used_arg= FALSE); Item_ref(THD *thd, TABLE_LIST *view_arg, Item **item, - const char *field_name_arg, bool alias_name_used_arg= FALSE); + const LEX_CSTRING *field_name_arg, bool alias_name_used_arg= FALSE); /* Constructor need to process subselect with temporary tables (see Item) */ Item_ref(THD *thd, Item_ref *item) @@ -4468,22 +4879,17 @@ public: my_decimal *val_decimal_result(my_decimal *); bool val_bool_result(); bool is_null_result(); - bool send(Protocol *prot, String *tmp); - void make_field(THD *thd, Send_field *field); + bool send(Protocol *prot, st_value *buffer); + void make_send_field(THD *thd, Send_field *field); bool fix_fields(THD *, Item **); void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge); int save_in_field(Field *field, bool no_conversions); void save_org_in_field(Field *field, fast_field_copier optimizer_data); fast_field_copier setup_fast_field_copier(Field *field) { return (*ref)->setup_fast_field_copier(field); } -#if MARIADB_VERSION_ID < 100300 - CHARSET_INFO *charset_for_protocol(void) const - { - return (*ref)->charset_for_protocol(); - } -#endif - enum Item_result result_type () const { return (*ref)->result_type(); } - enum_field_types field_type() const { return (*ref)->field_type(); } + const Type_handler *type_handler() const { return (*ref)->type_handler(); } + const Type_handler *real_type_handler() const + { return (*ref)->real_type_handler(); } Field *get_tmp_table_field() { return result_field ? result_field : (*ref)->get_tmp_table_field(); } Item *get_tmp_table_item(THD *thd); @@ -4521,6 +4927,11 @@ public: { return ref ? (*ref)->real_item() : this; } + TYPELIB *get_typelib() const + { + return ref ? (*ref)->get_typelib() : NULL; + } + bool walk(Item_processor processor, bool walk_subquery, void *arg) { if (ref && *ref) @@ -4553,7 +4964,7 @@ public: virtual Ref_Type ref_type() { return REF; } // Row emulation: forwarding of ROW-related calls to ref - uint cols() + uint cols() const { return ref && result_type() == ROW_RESULT ? (*ref)->cols() : 1; } @@ -4591,17 +5002,17 @@ public: return (*ref)->is_outer_field(); } - Item* build_clone(THD *thd, MEM_ROOT *mem_root); + Item* build_clone(THD *thd); /** Checks if the item tree that ref points to contains a subquery. */ - virtual bool has_subquery() const - { - return (*ref)->has_subquery(); + virtual bool with_subquery() const + { + return (*ref)->with_subquery(); } - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_ref>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_ref>(thd, this); } bool excl_dep_on_table(table_map tab_map) { table_map used= used_tables(); @@ -4639,7 +5050,7 @@ class Item_direct_ref :public Item_ref public: Item_direct_ref(THD *thd, Name_resolution_context *context_arg, Item **item, const char *table_name_arg, - const char *field_name_arg, + const LEX_CSTRING *field_name_arg, bool alias_name_used_arg= FALSE): Item_ref(thd, context_arg, item, table_name_arg, field_name_arg, alias_name_used_arg) @@ -4647,7 +5058,7 @@ public: /* Constructor need to process subselect with temporary tables (see Item) */ Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {} Item_direct_ref(THD *thd, TABLE_LIST *view_arg, Item **item, - const char *field_name_arg, + const LEX_CSTRING *field_name_arg, bool alias_name_used_arg= FALSE): Item_ref(thd, view_arg, item, field_name_arg, alias_name_used_arg) @@ -4655,8 +5066,7 @@ public: bool fix_fields(THD *thd, Item **it) { - if ((!(*ref)->fixed && (*ref)->fix_fields(thd, ref)) || - (*ref)->check_cols(1)) + if ((*ref)->fix_fields_if_needed_for_scalar(thd, ref)) return TRUE; return Item_ref::fix_fields(thd, it); } @@ -4669,8 +5079,8 @@ public: bool is_null(); bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); virtual Ref_Type ref_type() { return DIRECT_REF; } - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_direct_ref>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_direct_ref>(thd, this); } }; @@ -4685,7 +5095,7 @@ class Item_direct_ref_to_ident :public Item_direct_ref public: Item_direct_ref_to_ident(THD *thd, Item_ident *item): Item_direct_ref(thd, item->context, (Item**)&item, item->table_name, - item->field_name, FALSE) + &item->field_name, FALSE) { ident= item; ref= (Item**)&ident; @@ -4694,8 +5104,7 @@ public: bool fix_fields(THD *thd, Item **it) { DBUG_ASSERT(ident->type() == FIELD_ITEM || ident->type() == REF_ITEM); - if ((!ident->fixed && ident->fix_fields(thd, ref)) || - ident->check_cols(1)) + if (ident->fix_fields_if_needed_for_scalar(thd, ref)) return TRUE; set_properties(); return FALSE; @@ -4715,7 +5124,8 @@ class Expression_cache_tracker; The objects of this class can store its values in an expression cache. */ -class Item_cache_wrapper :public Item_result_field +class Item_cache_wrapper :public Item_result_field, + public With_subquery_cache { private: /* Pointer on the cached expression */ @@ -4742,6 +5152,7 @@ public: enum Type type() const { return EXPR_CACHE_ITEM; } enum Type real_type() const { return orig_item->type(); } + bool with_subquery() const { DBUG_ASSERT(fixed); return m_with_subquery; } bool set_cache(THD *thd); Expression_cache_tracker* init_tracker(MEM_ROOT *mem_root); @@ -4760,7 +5171,7 @@ public: bool val_bool(); bool is_null(); bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); - bool send(Protocol *protocol, String *buffer); + bool send(Protocol *protocol, st_value *buffer); void save_org_in_field(Field *field, fast_field_copier data __attribute__ ((__unused__))) { @@ -4776,8 +5187,8 @@ public: virtual void print(String *str, enum_query_type query_type); virtual const char *full_name() const { return orig_item->full_name(); } - virtual void make_field(THD *thd, Send_field *field) - { orig_item->make_field(thd, field); } + virtual void make_send_field(THD *thd, Send_field *field) + { orig_item->make_send_field(thd, field); } bool eq(const Item *item, bool binary_cmp) const { Item *it= ((Item *) item)->real_item(); @@ -4788,8 +5199,7 @@ public: orig_item->fix_after_pullout(new_parent, &orig_item, merge); } int save_in_field(Field *to, bool no_conversions); - enum Item_result result_type () const { return orig_item->result_type(); } - enum_field_types field_type() const { return orig_item->field_type(); } + const Type_handler *type_handler() const { return orig_item->type_handler(); } table_map used_tables() const { return orig_item->used_tables(); } void update_used_tables() { @@ -4808,7 +5218,7 @@ public: { return orig_item->field_for_view_update(); } /* Row emulation: forwarding of ROW-related calls to orig_item */ - uint cols() + uint cols() const { return result_type() == ROW_RESULT ? orig_item->cols() : 1; } Item* element_index(uint i) { return result_type() == ROW_RESULT ? orig_item->element_index(i) : this; } @@ -4834,9 +5244,9 @@ public: { return mark_unsupported_function("cache", arg, VCOL_IMPOSSIBLE); } - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_cache_wrapper>(thd, mem_root, this); } - Item *build_clone(THD *thd, MEM_ROOT *mem_root) { return 0; } + Item *get_copy(THD *thd) + { return get_item_copy<Item_cache_wrapper>(thd, this); } + Item *build_clone(THD *thd) { return 0; } }; @@ -4874,7 +5284,7 @@ public: Item_direct_view_ref(THD *thd, Name_resolution_context *context_arg, Item **item, const char *table_name_arg, - const char *field_name_arg, + LEX_CSTRING *field_name_arg, TABLE_LIST *view_arg): Item_direct_ref(thd, context_arg, item, table_name_arg, field_name_arg), item_equal(0), view(view_arg), @@ -4982,7 +5392,7 @@ public: } return Item_direct_ref::get_date(ltime, fuzzydate); } - bool send(Protocol *protocol, String *buffer); + bool send(Protocol *protocol, st_value *buffer); void save_org_in_field(Field *field, fast_field_copier data __attribute__ ((__unused__))) { @@ -5014,8 +5424,8 @@ public: my_decimal *val_decimal_result(my_decimal *val); bool val_bool_result(); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_direct_view_ref>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_direct_view_ref>(thd, this); } }; @@ -5045,7 +5455,7 @@ public: Item_outer_ref(THD *thd, Name_resolution_context *context_arg, Item_field *outer_field_arg): Item_direct_ref(thd, context_arg, 0, outer_field_arg->table_name, - outer_field_arg->field_name), + &outer_field_arg->field_name), outer_ref(outer_field_arg), in_sum_func(0), found_in_select_list(0), found_in_group_by(0) { @@ -5054,7 +5464,7 @@ public: fixed= 0; /* reset flag set in set_properties() */ } Item_outer_ref(THD *thd, Name_resolution_context *context_arg, Item **item, - const char *table_name_arg, const char *field_name_arg, + const char *table_name_arg, LEX_CSTRING *field_name_arg, bool alias_name_used_arg): Item_direct_ref(thd, context_arg, item, table_name_arg, field_name_arg, alias_name_used_arg), @@ -5095,7 +5505,8 @@ protected: public: Item_ref_null_helper(THD *thd, Name_resolution_context *context_arg, Item_in_subselect* master, Item **item, - const char *table_name_arg, const char *field_name_arg): + const char *table_name_arg, + const LEX_CSTRING *field_name_arg): Item_ref(thd, context_arg, item, table_name_arg, field_name_arg), owner(master) {} void save_val(Field *to); @@ -5107,8 +5518,8 @@ public: bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); virtual void print(String *str, enum_query_type query_type); table_map used_tables() const; - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_ref_null_helper>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_ref_null_helper>(thd, this); } }; /* @@ -5151,6 +5562,7 @@ public: #include "item_xmlfunc.h" #include "item_jsonfunc.h" #include "item_create.h" +#include "item_vers.h" #endif /** @@ -5198,8 +5610,8 @@ protected: item= i; null_value=maybe_null=item->maybe_null; Type_std_attributes::set(item); - name=item->name; - set_handler_by_field_type(item->field_type()); + name= item->name; + set_handler(item->type_handler()); fixed= item->fixed; } @@ -5218,14 +5630,11 @@ public: /** All of the subclasses should have the same type tag */ enum Type type() const { return COPY_STR_ITEM; } - enum_field_types field_type() const - { return Type_handler_hybrid_field_type::field_type(); } - enum Item_result result_type () const - { return Type_handler_hybrid_field_type::result_type(); } - enum Item_result cmp_type () const - { return Type_handler_hybrid_field_type::cmp_type(); } + const Type_handler *type_handler() const + { return Type_handler_hybrid_field_type::type_handler(); } - void make_field(THD *thd, Send_field *field) { item->make_field(thd, field); } + void make_send_field(THD *thd, Send_field *field) + { item->make_send_field(thd, field); } table_map used_tables() const { return (table_map) 1L; } bool const_item() const { return 0; } bool is_null() { return null_value; } @@ -5265,10 +5674,12 @@ public: my_decimal *val_decimal(my_decimal *); double val_real(); longlong val_int(); + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { return get_date_from_string(ltime, fuzzydate); } void copy(); int save_in_field(Field *field, bool no_conversions); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_copy_string>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_copy_string>(thd, this); } }; @@ -5388,16 +5799,16 @@ public: Field *cached_field; Item_default_value(THD *thd, Name_resolution_context *context_arg) :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL, - (const char *)NULL), - arg(NULL), cached_field(NULL) {} + &null_clex_str), + arg(NULL), cached_field(NULL) {} Item_default_value(THD *thd, Name_resolution_context *context_arg, Item *a) :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL, - (const char *)NULL), - arg(a), cached_field(NULL) {} + &null_clex_str), + arg(a), cached_field(NULL) {} Item_default_value(THD *thd, Name_resolution_context *context_arg, Field *a) :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL, - (const char *)NULL), - arg(NULL),cached_field(NULL) {} + &null_clex_str), + arg(NULL), cached_field(NULL) {} enum Type type() const { return DEFAULT_VALUE_ITEM; } bool vcol_assignment_allowed_value() const { return arg == NULL; } bool eq(const Item *item, bool binary_cmp) const; @@ -5409,7 +5820,7 @@ public: longlong val_int(); my_decimal *val_decimal(my_decimal *decimal_value); bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate); - bool send(Protocol *protocol, String *buffer); + bool send(Protocol *protocol, st_value *buffer); int save_in_field(Field *field_arg, bool no_conversions); bool save_in_param(THD *thd, Item_param *param) { @@ -5466,7 +5877,7 @@ public: longlong val_int(); my_decimal *val_decimal(my_decimal *decimal_value); bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate); - bool send(Protocol *protocol, String *buffer); + bool send(Protocol *protocol, st_value *buffer); }; @@ -5486,7 +5897,7 @@ public: Item *arg; Item_insert_value(THD *thd, Name_resolution_context *context_arg, Item *a) :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL, - (const char *)NULL), + &null_clex_str), arg(a) {} bool eq(const Item *item, bool binary_cmp) const; bool fix_fields(THD *, Item **); @@ -5513,7 +5924,7 @@ public: bool update_vcol_processor(void *arg) { return 0; } bool check_vcol_func_processor(void *arg) { - return mark_unsupported_function("values()", arg, VCOL_IMPOSSIBLE); + return mark_unsupported_function("value()", arg, VCOL_IMPOSSIBLE); } }; @@ -5547,7 +5958,7 @@ public: Item_trigger_field(THD *thd, Name_resolution_context *context_arg, row_version_type row_ver_arg, - const char *field_name_arg, + const LEX_CSTRING *field_name_arg, ulong priv, const bool ro) :Item_field(thd, context_arg, (const char *)NULL, (const char *)NULL, field_name_arg), @@ -5633,7 +6044,7 @@ protected: public: Item_cache(THD *thd): Item_basic_constant(thd), - Type_handler_hybrid_field_type(MYSQL_TYPE_STRING), + Type_handler_hybrid_field_type(&type_handler_string), example(0), cached_field(0), value_cached(0) { @@ -5642,9 +6053,9 @@ public: null_value= 1; } protected: - Item_cache(THD *thd, enum_field_types field_type_arg): + Item_cache(THD *thd, const Type_handler *handler): Item_basic_constant(thd), - Type_handler_hybrid_field_type(field_type_arg), + Type_handler_hybrid_field_type(handler), example(0), cached_field(0), value_cached(0) { @@ -5665,24 +6076,9 @@ public: }; enum Type type() const { return CACHE_ITEM; } - enum_field_types field_type() const - { return Type_handler_hybrid_field_type::field_type(); } - enum Item_result result_type () const - { return Type_handler_hybrid_field_type::result_type(); } - enum Item_result cmp_type () const - { return Type_handler_hybrid_field_type::cmp_type(); } + const Type_handler *type_handler() const + { return Type_handler_hybrid_field_type::type_handler(); } - static Item_cache* get_cache(THD *thd, const Item* item, - const Item_result type, const enum_field_types f_type); - static Item_cache* get_cache(THD *thd, const Item* item, - const Item_result type) - { - return get_cache(thd, item, type, item->field_type()); - } - static Item_cache* get_cache(THD *thd, const Item *item) - { - return get_cache(thd, item, item->cmp_type()); - } virtual void keep_array() {} virtual void print(String *str, enum_query_type query_type); bool eq_def(const Field *field) @@ -5725,6 +6121,7 @@ public: } virtual void store(Item *item); + virtual Item *get_item() { return example; } virtual bool cache_value()= 0; bool basic_const_item() const { return example && example->basic_const_item(); } @@ -5773,28 +6170,39 @@ class Item_cache_int: public Item_cache protected: longlong value; public: - Item_cache_int(THD *thd): Item_cache(thd, MYSQL_TYPE_LONGLONG), + Item_cache_int(THD *thd): Item_cache(thd, &type_handler_longlong), value(0) {} - Item_cache_int(THD *thd, enum_field_types field_type_arg): - Item_cache(thd, field_type_arg), value(0) {} + Item_cache_int(THD *thd, const Type_handler *handler): + Item_cache(thd, handler), value(0) {} double val_real(); longlong val_int(); String* val_str(String *str); my_decimal *val_decimal(my_decimal *); - enum Item_result result_type() const { return INT_RESULT; } + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { return get_date_from_int(ltime, fuzzydate); } bool cache_value(); int save_in_field(Field *field, bool no_conversions); Item *convert_to_basic_const_item(THD *thd); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_cache_int>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_cache_int>(thd, this); } +}; + + +class Item_cache_year: public Item_cache_int +{ +public: + Item_cache_year(THD *thd): Item_cache_int(thd, &type_handler_year) { } + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { return get_date_from_year(ltime, fuzzydate); } }; class Item_cache_temporal: public Item_cache_int { +protected: + Item_cache_temporal(THD *thd, const Type_handler *handler); public: - Item_cache_temporal(THD *thd, enum_field_types field_type_arg); String* val_str(String *str); my_decimal *val_decimal(my_decimal *); longlong val_int(); @@ -5804,7 +6212,6 @@ public: bool cache_value(); bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); int save_in_field(Field *field, bool no_conversions); - Item_result cmp_type() const { return TIME_RESULT; } void store_packed(longlong val_arg, Item *example); /* Having a clone_item method tells optimizer that this object @@ -5813,27 +6220,84 @@ public: */ Item *clone_item(THD *thd); Item *convert_to_basic_const_item(THD *thd); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_cache_temporal>(thd, mem_root, this); } + virtual Item *make_literal(THD *) =0; +}; + + +class Item_cache_time: public Item_cache_temporal +{ +public: + Item_cache_time(THD *thd) + :Item_cache_temporal(thd, &type_handler_time2) { } + bool cache_value(); + Item *get_copy(THD *thd) + { return get_item_copy<Item_cache_time>(thd, this); } + Item *make_literal(THD *); +}; + + +class Item_cache_datetime: public Item_cache_temporal +{ +public: + Item_cache_datetime(THD *thd) + :Item_cache_temporal(thd, &type_handler_datetime2) { } + Item *get_copy(THD *thd) + { return get_item_copy<Item_cache_datetime>(thd, this); } + Item *make_literal(THD *); +}; + + +class Item_cache_date: public Item_cache_temporal +{ +public: + Item_cache_date(THD *thd) + :Item_cache_temporal(thd, &type_handler_newdate) { } + Item *get_copy(THD *thd) + { return get_item_copy<Item_cache_date>(thd, this); } + Item *make_literal(THD *); }; class Item_cache_real: public Item_cache { +protected: double value; public: - Item_cache_real(THD *thd): Item_cache(thd, MYSQL_TYPE_DOUBLE), - value(0) {} - + Item_cache_real(THD *thd, const Type_handler *h) + :Item_cache(thd, h), + value(0) + {} double val_real(); longlong val_int(); - String* val_str(String *str); my_decimal *val_decimal(my_decimal *); - enum Item_result result_type() const { return REAL_RESULT; } + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { return get_date_from_real(ltime, fuzzydate); } bool cache_value(); Item *convert_to_basic_const_item(THD *thd); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_cache_real>(thd, mem_root, this); } +}; + + +class Item_cache_double: public Item_cache_real +{ +public: + Item_cache_double(THD *thd) + :Item_cache_real(thd, &type_handler_double) + { } + String* val_str(String *str); + Item *get_copy(THD *thd) + { return get_item_copy<Item_cache_double>(thd, this); } +}; + + +class Item_cache_float: public Item_cache_real +{ +public: + Item_cache_float(THD *thd) + :Item_cache_real(thd, &type_handler_float) + { } + String* val_str(String *str); + Item *get_copy(THD *thd) + { return get_item_copy<Item_cache_float>(thd, this); } }; @@ -5842,17 +6306,18 @@ class Item_cache_decimal: public Item_cache protected: my_decimal decimal_value; public: - Item_cache_decimal(THD *thd): Item_cache(thd, MYSQL_TYPE_NEWDECIMAL) {} + Item_cache_decimal(THD *thd): Item_cache(thd, &type_handler_newdecimal) {} double val_real(); longlong val_int(); String* val_str(String *str); my_decimal *val_decimal(my_decimal *); - enum Item_result result_type() const { return DECIMAL_RESULT; } + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { return get_date_from_decimal(ltime, fuzzydate); } bool cache_value(); Item *convert_to_basic_const_item(THD *thd); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_cache_decimal>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_cache_decimal>(thd, this); } }; @@ -5864,7 +6329,7 @@ class Item_cache_str: public Item_cache public: Item_cache_str(THD *thd, const Item *item): - Item_cache(thd, item->field_type()), value(0), + Item_cache(thd, item->type_handler()), value(0), is_varbinary(item->type() == FIELD_ITEM && Item_cache_str::field_type() == MYSQL_TYPE_VARCHAR && !((const Item_field *) item)->field->has_charset()) @@ -5875,13 +6340,14 @@ public: longlong val_int(); String* val_str(String *); my_decimal *val_decimal(my_decimal *); - enum Item_result result_type() const { return STRING_RESULT; } + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { return get_date_from_string(ltime, fuzzydate); } CHARSET_INFO *charset() const { return value->charset(); }; int save_in_field(Field *field, bool no_conversions); bool cache_value(); Item *convert_to_basic_const_item(THD *thd); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_cache_str>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_cache_str>(thd, this); } }; @@ -5905,8 +6371,8 @@ public: */ return Item::safe_charset_converter(thd, tocs); } - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_cache_str_for_nullif>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_cache_str_for_nullif>(thd, this); } }; @@ -5932,9 +6398,9 @@ public: bool setup(THD *thd, Item *item); void store(Item *item); void illegal_method_call(const char *); - void make_field(THD *thd, Send_field *) + void make_send_field(THD *thd, Send_field *) { - illegal_method_call((const char*)"make_field"); + illegal_method_call((const char*)"make_send_field"); }; double val_real() { @@ -5956,10 +6422,13 @@ public: illegal_method_call((const char*)"val_decimal"); return 0; }; + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) + { + illegal_method_call((const char*)"val_decimal"); + return true; + } - enum Item_result result_type() const { return ROW_RESULT; } - - uint cols() { return item_count; } + uint cols() const { return item_count; } Item *element_index(uint i) { return values[i]; } Item **addr(uint i) { return (Item **) (values + i); } bool check_cols(uint c); @@ -5978,8 +6447,8 @@ public: } bool cache_value(); virtual void set_null(); - Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_cache_row>(thd, mem_root, this); } + Item *get_copy(THD *thd) + { return get_item_copy<Item_cache_row>(thd, this); } }; @@ -5991,51 +6460,68 @@ public: single SP/PS execution. */ class Item_type_holder: public Item, - public Type_handler_hybrid_real_field_type + public Type_handler_hybrid_field_type, + public Type_geometry_attributes { protected: TYPELIB *enum_set_typelib; - Field::geometry_type geometry_type; - - void get_full_info(Item *item); - - /* It is used to count decimal precision in join_types */ - int prev_decimal_int_part; public: - Item_type_holder(THD*, Item*); + Item_type_holder(THD *thd, Item *item) + :Item(thd, item), + Type_handler_hybrid_field_type(item->real_type_handler()), + enum_set_typelib(0) + { + DBUG_ASSERT(item->fixed); + maybe_null= item->maybe_null; + } + Item_type_holder(THD *thd, + Item *item, + const Type_handler *handler, + const Type_all_attributes *attr, + bool maybe_null_arg) + :Item(thd), + Type_handler_hybrid_field_type(handler), + Type_geometry_attributes(handler, attr), + enum_set_typelib(attr->get_typelib()) + { + name= item->name; + Type_std_attributes::set(*attr); + maybe_null= maybe_null_arg; + } - enum_field_types field_type() const - { return Type_handler_hybrid_real_field_type::field_type(); } - enum_field_types real_field_type() const - { return Type_handler_hybrid_real_field_type::real_field_type(); } - enum Item_result result_type () const + const Type_handler *type_handler() const { - /* - In 10.1 Item_type_holder::result_type() returned - Field::result_merge_type(field_type()), which returned STRING_RESULT - for the BIT data type. In 10.2 it returns INT_RESULT, similar - to what Field_bit::result_type() does. This should not be - important because Item_type_holder is a limited purpose Item - and its result_type() should not be called from outside of - Item_type_holder. It's called only internally from decimal_int_part() - from join_types(), to calculate "decimals" of the result data type. - As soon as we get BIT as one of the joined types, the result field - type cannot be numeric: it's either BIT, or VARBINARY. - */ - return Type_handler_hybrid_real_field_type::result_type(); + return Type_handler_hybrid_field_type::type_handler()-> + type_handler_for_item_field(); + } + const Type_handler *real_type_handler() const + { + return Type_handler_hybrid_field_type::type_handler(); } enum Type type() const { return TYPE_HOLDER; } + TYPELIB *get_typelib() const { return enum_set_typelib; } double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal *); String *val_str(String*); - bool join_types(THD *thd, Item *); - Field *make_field_by_type(TABLE *table); - static uint32 display_length(Item *item); - static enum_field_types get_real_type(Item *); - Field::geometry_type get_geometry_type() const { return geometry_type; }; - Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; } + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + Field *create_tmp_field(bool group, TABLE *table) + { + return Item_type_holder::real_type_handler()-> + make_and_init_table_field(&name, Record_addr(maybe_null), + *this, table); + } + Field::geometry_type get_geometry_type() const + { + return Type_geometry_attributes::get_geometry_type(); + } + void set_geometry_type(uint type) + { + Type_geometry_attributes::set_geometry_type(type); + } + Item* get_copy(THD *thd) { return 0; } + }; |