diff options
Diffstat (limited to 'sql/item.h')
-rw-r--r-- | sql/item.h | 582 |
1 files changed, 480 insertions, 102 deletions
diff --git a/sql/item.h b/sql/item.h index 33296b619db..ed50605ef7b 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1,5 +1,9 @@ +#ifndef SQL_ITEM_INCLUDED +#define SQL_ITEM_INCLUDED + /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2013, Monty Program Ab. + Copyright (c) 2009, 2013 Monty Program Ab. + 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 the Free Software Foundation; version 2 of the License. @@ -18,11 +22,18 @@ #pragma interface /* gcc class implementation */ #endif +#include "sql_priv.h" /* STRING_BUFFER_USUAL_SIZE */ +#include "unireg.h" +#include "sql_const.h" /* RAND_TABLE_BIT, MAX_FIELD_NAME */ +#include "unireg.h" // REQUIRED: for other includes +#include "thr_malloc.h" /* sql_calloc */ +#include "field.h" /* Derivation */ + C_MODE_START #include <ma_dyncol.h> C_MODE_END -inline +static inline bool trace_unsupported_func(const char *where, const char *processor_name) { char buff[64]; @@ -33,17 +44,18 @@ bool trace_unsupported_func(const char *where, const char *processor_name) DBUG_RETURN(TRUE); } -inline +static inline bool trace_unsupported_by_check_vcol_func_processor(const char *where) { return trace_unsupported_func(where, "check_vcol_func_processor"); } - class Protocol; struct TABLE_LIST; void item_init(void); /* Init item functions */ class Item_field; +class user_var_entry; + static inline uint32 char_to_byte_length_safe(uint32 char_length_arg, uint32 mbmaxlen_arg) @@ -63,6 +75,8 @@ char_to_byte_length_safe(uint32 char_length_arg, uint32 mbmaxlen_arg) (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 @@ -71,9 +85,11 @@ char_to_byte_length_safe(uint32 char_length_arg, uint32 mbmaxlen_arg) #define MY_COLL_ALLOW_SUPERSET_CONV 1 #define MY_COLL_ALLOW_COERCIBLE_CONV 2 -#define MY_COLL_ALLOW_CONV 3 #define MY_COLL_DISALLOW_NONE 4 -#define MY_COLL_CMP_CONV 7 +#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) class DTCollation { public: @@ -118,6 +134,12 @@ public: 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; @@ -132,6 +154,7 @@ public: { switch(derivation) { + case DERIVATION_NUMERIC: return "NUMERIC"; case DERIVATION_IGNORABLE: return "IGNORABLE"; case DERIVATION_COERCIBLE: return "COERCIBLE"; case DERIVATION_IMPLICIT: return "IMPLICIT"; @@ -309,6 +332,8 @@ struct Name_resolution_context: Sql_alloc */ TABLE_LIST *last_name_resolution_table; + /* Cache first_name_resolution_table in setup_natural_join_row_types */ + TABLE_LIST *natural_join_first_table; /* SELECT_LEX item belong to, in case of merged VIEW it can differ from SELECT_LEX where item was created, so we can't use table_list/field_list @@ -496,6 +521,11 @@ public: TRUE if error has occured. */ virtual bool set_value(THD *thd, sp_rcontext *ctx, Item **it)= 0; + + virtual void set_out_param_info(Send_field *info) {} + + virtual const Send_field *get_out_param_info() const + { return NULL; } }; @@ -589,6 +619,10 @@ public: @see Query_arena::free_list */ Item *next; + /* + The maximum value length in characters multiplied by collation->mbmaxlen. + Almost always it's the maximum value length in bytes. + */ uint32 max_length; /* TODO: convert name and name_length fields into LEX_STRING to keep them in @@ -641,7 +675,7 @@ public: void init_make_field(Send_field *tmp_field,enum enum_field_types type); virtual void cleanup(); virtual void make_field(Send_field *field); - Field *make_string_field(TABLE *table); + virtual Field *make_string_field(TABLE *table); virtual bool fix_fields(THD *, Item **); /* Fix after some tables has been pulled out. Basically re-calculate all @@ -793,6 +827,77 @@ public: If value is not null null_value flag will be reset to FALSE. */ virtual String *val_str(String *str)=0; + + /* + Returns string representation of this item in ASCII format. + + SYNOPSIS + val_str_ascii() + str - similar to val_str(); + + NOTE + This method is introduced for performance optimization purposes. + + 1. val_str() result of some Items in string context + depends on @@character_set_results. + @@character_set_results can be set to a "real multibyte" character + set like UCS2, UTF16, UTF32. (We'll use only UTF32 in the examples + below for convenience.) + + So the default string result of such functions + in these circumstances is real multi-byte character set, like UTF32. + + For example, all numbers in string context + return result in @@character_set_results: + + SELECT CONCAT(20010101); -> UTF32 + + We do sprintf() first (to get ASCII representation) + and then convert to UTF32; + + So these kind "data sources" can use ASCII representation + internally, but return multi-byte data only because + @@character_set_results wants so. + Therefore, conversion from ASCII to UTF32 is applied internally. + + + 2. Some other functions need in fact ASCII input. + + For example, + inet_aton(), GeometryFromText(), Convert_TZ(), GET_FORMAT(). + + Similar, fields of certain type, like DATE, TIME, + when you insert string data into them, expect in fact ASCII input. + If they get non-ASCII input, for example UTF32, they + convert input from UTF32 to ASCII, and then use ASCII + representation to do further processing. + + + 3. Now imagine we pass result of a data source of the first type + to a data destination of the second type. + + What happens: + a. data source converts data from ASCII to UTF32, because + @@character_set_results wants so and passes the result to + data destination. + b. data destination gets UTF32 string. + c. data destination converts UTF32 string to ASCII, + because it needs ASCII representation to be able to handle data + correctly. + + As a result we get two steps of unnecessary conversion: + From ASCII to UTF32, then from UTF32 to ASCII. + + A better way to handle these situations is to pass ASCII + representation directly from the source to the destination. + + This is why val_str_ascii() introduced. + + RETURN + Similar to val_str() + */ + virtual String *val_str_ascii(String *str); + /* Returns the val_str() value converted to the given character set. */ @@ -990,11 +1095,11 @@ public: /* Called for items that really have to be split */ void split_sum_func2(THD *thd, Item **ref_pointer_array, List<Item> &fields, Item **ref, bool skip_registered); - virtual bool get_date(MYSQL_TIME *ltime,uint fuzzydate); + virtual bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); bool get_time(MYSQL_TIME *ltime) { return get_date(ltime, TIME_TIME_ONLY); } bool get_seconds(ulonglong *sec, ulong *sec_part); - virtual bool get_date_result(MYSQL_TIME *ltime,uint fuzzydate) + virtual bool get_date_result(MYSQL_TIME *ltime, ulonglong fuzzydate) { return get_date(ltime,fuzzydate); } /* The method allows to determine nullness of a complex expression @@ -1042,6 +1147,16 @@ public: static CHARSET_INFO *default_charset(); virtual CHARSET_INFO *compare_collation() { return NULL; } + /* + For backward compatibility, to make numeric + data types return "binary" charset in client-side metadata. + */ + virtual CHARSET_INFO *charset_for_protocol(void) const + { + return result_type() == STRING_RESULT ? collation.collation : + &my_charset_bin; + }; + virtual bool walk(Item_processor processor, bool walk_subquery, uchar *arg) { return (this->*processor)(arg); @@ -1079,6 +1194,15 @@ public: (*traverser)(this, arg); } + /* + This is used to get the most recent version of any function in + an item tree. The version is the version where a MySQL function + was introduced in. So any function which is added should use + this function and set the int_arg to maximum of the input data + and their own version info. + */ + virtual bool intro_version(uchar *int_arg) { return 0; } + virtual bool remove_dependence_processor(uchar * arg) { return 0; } virtual bool remove_fixed(uchar * arg) { fixed= 0; return 0; } virtual bool cleanup_processor(uchar *arg); @@ -1124,6 +1248,10 @@ public: is passed as uchar *arg. */ virtual bool register_field_in_bitmap(uchar *arg) { return 0; } + + bool cache_const_expr_analyzer(uchar **arg); + Item* cache_const_expr_transformer(uchar *arg); + /* Check if a partition function is allowed SYNOPSIS @@ -1317,22 +1445,33 @@ public: { return 0; } + /** + Check whether this and the given item has compatible comparison context. + Used by the equality propagation. See Item_field::equal_fields_propagator. - /* + @return + TRUE if the context is the same + FALSE otherwise. + */ + inline bool has_compatible_context(Item *item) const + { + return cmp_context == IMPOSSIBLE_RESULT || item->cmp_context == cmp_context; + } + /** Test whether an expression is expensive to compute. Used during optimization to avoid computing expensive expressions during this phase. Also used to force temp tables when sorting on expensive functions. - TODO: + @todo Normally we should have a method: cost Item::execution_cost(), where 'cost' is either 'double' or some structure of various cost parameters. - NOTE - This function is now used to prevent evaluation of materialized IN - subquery predicates before it is allowed. grep for - DontEvaluateMaterializedSubqueryTooEarly to see the uses. + @note + This function is now used to prevent evaluation of expensive subquery + predicates during the optimization phase. It also prevents evaluation + of predicates that are not computable at this moment. */ virtual bool is_expensive() { @@ -1344,13 +1483,31 @@ public: { return Field::GEOM_GEOMETRY; }; 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) + { + max_length= char_to_byte_length_safe(max_char_length_arg, cs->mbmaxlen); + collation.collation= cs; + } void fix_char_length(uint32 max_char_length_arg) { max_length= char_to_byte_length_safe(max_char_length_arg, collation.collation->mbmaxlen); } + /* + Return TRUE if the item points to a column of an outer-joined table. + */ + virtual bool is_outer_field() const { DBUG_ASSERT(fixed); return FALSE; } + + /** + Checks if this item or any of its decendents contains a subquery. + */ + virtual bool has_subquery() const { return with_subselect; } + Item* set_expr_cache(THD *thd); - virtual Item *get_cached_item() { return NULL; } virtual Item_equal *get_item_equal() { return NULL; } virtual void set_item_equal(Item_equal *item_eq) {}; @@ -1384,11 +1541,6 @@ public: virtual void get_cache_parameters(List<Item> ¶meters) { }; virtual void mark_as_condition_AND_part(TABLE_LIST *embedding) {}; - - /** - Checks if this item or any of its decendents contains a subquery. - */ - virtual bool has_subquery() const { return with_subselect; } }; @@ -1424,10 +1576,8 @@ public: Field_enumerator() {} /* Remove gcc warning */ }; - class sp_head; - class Item_basic_constant :public Item { table_map used_table_map; @@ -1543,6 +1693,13 @@ class Item_splocal :public Item_sp_variable, Item_result m_result_type; enum_field_types m_field_type; public: + /* + If this variable is a parameter in LIMIT clause. + Used only during NAME_CONST substitution, to not append + NAME_CONST to the resulting query and thus not break + the slave. + */ + bool limit_clause_param; /* Position of this reference to SP variable in the statement (the statement itself is in sp_instr_stmt::m_query). @@ -1728,12 +1885,44 @@ bool agg_item_set_converter(DTCollation &coll, const char *fname, Item **args, uint nargs, uint flags, int item_sep); bool agg_item_charsets(DTCollation &c, const char *name, Item **items, uint nitems, uint flags, int item_sep); +inline bool +agg_item_charsets_for_string_result(DTCollation &c, const char *name, + 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_item_charsets(c, name, items, nitems, flags, item_sep); +} +inline bool +agg_item_charsets_for_comparison(DTCollation &c, const char *name, + 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_item_charsets(c, name, items, nitems, flags, item_sep); +} +inline bool +agg_item_charsets_for_string_result_with_comparison(DTCollation &c, + const char *name, + 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_item_charsets(c, name, items, nitems, flags, item_sep); +} class Item_num: public Item_basic_constant { public: - Item_num() {} /* Remove gcc warning */ + Item_num() { collation.set_numeric(); } /* Remove gcc warning */ virtual Item_num *neg()= 0; Item *safe_charset_converter(CHARSET_INFO *tocs); bool check_partition_func_processor(uchar *int_arg) { return FALSE;} @@ -1829,6 +2018,8 @@ public: 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(Send_field *tmp_field); + CHARSET_INFO *charset_for_protocol(void) const + { return field->charset_for_protocol(); } }; @@ -1907,8 +2098,8 @@ public: longlong val_int_endpoint(bool left_endp, bool *incl_endp); Field *get_tmp_table_field() { return result_field; } Field *tmp_table_field(TABLE *t_arg) { return result_field; } - bool get_date(MYSQL_TIME *ltime,uint fuzzydate); - bool get_date_result(MYSQL_TIME *ltime,uint fuzzydate); + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool get_date_result(MYSQL_TIME *ltime,ulonglong fuzzydate); bool is_null() { return field->is_null(); } void update_null_value(); void update_table_bitmaps() @@ -1958,11 +2149,18 @@ public: int fix_outer_field(THD *thd, Field **field, Item **reference); virtual Item *update_value_transformer(uchar *select_arg); virtual void print(String *str, enum_query_type query_type); + bool is_outer_field() const + { + DBUG_ASSERT(fixed); + return field->table->pos_in_table_list->outer_join; + } Field::geometry_type get_geometry_type() const { 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; @@ -2023,7 +2221,8 @@ public: /* Item represents one placeholder ('?') of prepared statement */ -class Item_param :public Item +class Item_param :public Item, + private Settable_routine_parameter { char cnvbuf[MAX_FIELD_WIDTH]; String cnvstr; @@ -2104,13 +2303,14 @@ public: longlong val_int(); my_decimal *val_decimal(my_decimal*); String *val_str(String*); - bool get_date(MYSQL_TIME *tm, uint fuzzydate); + bool get_date(MYSQL_TIME *tm, ulonglong fuzzydate); int save_in_field(Field *field, bool no_conversions); void set_null(); void set_int(longlong i, uint32 max_length_arg); void set_double(double i); void set_decimal(const char *str, ulong length); + void set_decimal(const my_decimal *dv); bool set_str(const char *str, ulong length); bool set_longdata(const char *str, ulong length); void set_time(MYSQL_TIME *tm, timestamp_type type, uint32 max_length_arg); @@ -2161,6 +2361,24 @@ public: bool limit_clause_param; void set_param_type_and_swap_value(Item_param *from); +private: + virtual inline Settable_routine_parameter * + get_settable_routine_parameter() + { + return this; + } + + virtual bool set_value(THD *thd, sp_rcontext *ctx, Item **it); + + virtual void set_out_param_info(Send_field *info); + +public: + virtual const Send_field *get_out_param_info() const; + + virtual void make_field(Send_field *field); + +private: + Send_field *m_out_param_info; }; @@ -2481,7 +2699,7 @@ double_from_string_with_check(CHARSET_INFO *cs, const char *cptr, class Item_static_string_func :public Item_string { const char *func_name; - public: +public: Item_static_string_func(const char *name_par, const char *str, uint length, CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) @@ -2543,7 +2761,7 @@ public: /** Item_empty_string -- is a utility class to put an item into List<Item> - which is then used in protocol.send_fields() when sending SHOW output to + which is then used in protocol.send_result_set_metadata() when sending SHOW output to the client. */ @@ -2571,36 +2789,112 @@ public: }; -class Item_hex_string: public Item_basic_constant +/** + Item_hex_constant -- a common class for hex literals: X'HHHH' and 0xHHHH +*/ +class Item_hex_constant: public Item_basic_constant { +private: + void hex_string_init(const char *str, uint str_length); public: - Item_hex_string(); - Item_hex_string(const char *str,uint str_length); + Item_hex_constant() + { + hex_string_init("", 0); + } + Item_hex_constant(const char *str, uint str_length) + { + hex_string_init(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; } + virtual Item *safe_charset_converter(CHARSET_INFO *tocs); + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} + bool check_vcol_func_processor(uchar *arg) { return FALSE;} + bool basic_const_item() const { return 1; } + bool eq(const Item *item, bool binary_cmp) const; + String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; } +}; + + +/** + Item_hex_hybrid -- is a class implementing 0xHHHH literals, e.g.: + SELECT 0x3132; + They can behave as numbers and as strings depending on context. +*/ +class Item_hex_hybrid: public Item_hex_constant +{ +public: + Item_hex_hybrid(): Item_hex_constant() {} + Item_hex_hybrid(const char *str, uint str_length): + Item_hex_constant(str, str_length) {} double val_real() { DBUG_ASSERT(fixed == 1); - return (double) (ulonglong) Item_hex_string::val_int(); + return (double) (ulonglong) Item_hex_hybrid::val_int(); } longlong val_int(); - bool basic_const_item() const { return 1; } - String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; } - my_decimal *val_decimal(my_decimal *); + my_decimal *val_decimal(my_decimal *decimal_value) + { + // following assert is redundant, because fixed=1 assigned in constructor + DBUG_ASSERT(fixed == 1); + ulonglong value= (ulonglong) Item_hex_hybrid::val_int(); + int2my_decimal(E_DEC_FATAL_ERROR, value, TRUE, decimal_value); + return decimal_value; + } int save_in_field(Field *field, bool no_conversions); - enum Item_result result_type () const { return STRING_RESULT; } enum Item_result cast_to_int_type() const { return INT_RESULT; } - enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } - virtual void print(String *str, enum_query_type query_type); - bool eq(const Item *item, bool binary_cmp) const; - virtual Item *safe_charset_converter(CHARSET_INFO *tocs); - bool check_partition_func_processor(uchar *int_arg) {return FALSE;} - bool check_vcol_func_processor(uchar *arg) { return FALSE;} -private: - void hex_string_init(const char *str, uint str_length); + void print(String *str, enum_query_type query_type); +}; + + +/** + Item_hex_string -- is a class implementing X'HHHH' literals, e.g.: + SELECT X'3132'; + Unlike Item_hex_hybrid, X'HHHH' literals behave as strings in all contexts. + X'HHHH' are also used in replication of string constants in case of + "dangerous" charsets (sjis, cp932, big5, gbk) who can have backslash (0x5C) + as the second byte of a multi-byte character, so using '\' escaping for + these charsets is not desirable. +*/ +class Item_hex_string: public Item_hex_constant +{ +public: + Item_hex_string(): Item_hex_constant() {} + Item_hex_string(const char *str, uint str_length): + Item_hex_constant(str, str_length) {} + longlong val_int() + { + DBUG_ASSERT(fixed == 1); + return longlong_from_string_with_check(str_value.charset(), + str_value.ptr(), + str_value.ptr()+ + str_value.length()); + } + double val_real() + { + DBUG_ASSERT(fixed == 1); + return double_from_string_with_check(str_value.charset(), + str_value.ptr(), + str_value.ptr() + + str_value.length()); + } + my_decimal *val_decimal(my_decimal *decimal_value) + { + return val_decimal_from_string(decimal_value); + } + int save_in_field(Field *field, bool no_conversions) + { + field->set_notnull(); + 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); }; -class Item_bin_string: public Item_hex_string +class Item_bin_string: public Item_hex_hybrid { public: Item_bin_string(const char *str,uint str_length); @@ -2701,7 +2995,7 @@ public: bool val_bool(); String *val_str(String* tmp); bool is_null(); - bool get_date(MYSQL_TIME *ltime,uint fuzzydate); + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); double val_result(); longlong val_int_result(); String *str_result(String* tmp); @@ -2797,6 +3091,13 @@ public: { return trace_unsupported_by_check_vcol_func_processor("ref"); } + bool basic_const_item() const { return ref && (*ref)->basic_const_item(); } + bool is_outer_field() const + { + DBUG_ASSERT(fixed); + DBUG_ASSERT(ref); + return (*ref)->is_outer_field(); + } /** Checks if the item tree that ref points to contains a subquery. @@ -2838,7 +3139,7 @@ public: my_decimal *val_decimal(my_decimal *); bool val_bool(); bool is_null(); - bool get_date(MYSQL_TIME *ltime,uint fuzzydate); + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); virtual Ref_Type ref_type() { return DIRECT_REF; } }; @@ -2876,9 +3177,8 @@ public: }; -class Expression_cache; class Item_cache; - +class Expression_cache; /** The objects of this class can store its values in an expression cache. @@ -2927,13 +3227,8 @@ public: my_decimal *val_decimal(my_decimal *); bool val_bool(); bool is_null(); - bool get_date(MYSQL_TIME *ltime, uint fuzzydate); - bool send(Protocol *protocol, String *buffer) - { - if (result_field) - return protocol->store(result_field); - return Item::send(protocol, buffer); - } + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); + bool send(Protocol *protocol, String *buffer); void save_org_in_field(Field *field) { save_val(field); @@ -3121,7 +3416,7 @@ public: else return Item_direct_ref::is_null(); } - bool get_date(MYSQL_TIME *ltime, uint fuzzydate) + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) { if (check_null_ref()) { @@ -3130,12 +3425,7 @@ public: } return Item_direct_ref::get_date(ltime, fuzzydate); } - bool send(Protocol *protocol, String *buffer) - { - if (check_null_ref()) - return protocol->store_null(); - return Item_direct_ref::send(protocol, buffer); - } + bool send(Protocol *protocol, String *buffer); void save_org_in_field(Field *field) { if (check_null_ref()) @@ -3212,7 +3502,6 @@ public: return (*ref)->const_item() ? 0 : OUTER_REF_TABLE_BIT; } table_map not_null_tables() const { return 0; } - virtual Ref_Type ref_type() { return OUTER_REF; } bool check_inner_refs_processor(uchar * arg); }; @@ -3246,7 +3535,7 @@ public: String* val_str(String* s); my_decimal *val_decimal(my_decimal *); bool val_bool(); - bool get_date(MYSQL_TIME *ltime, uint fuzzydate); + bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); virtual void print(String *str, enum_query_type query_type); table_map used_tables() const; }; @@ -3289,6 +3578,7 @@ public: #include "item_timefunc.h" #include "item_subselect.h" #include "item_xmlfunc.h" +#include "item_create.h" #endif /** @@ -3346,6 +3636,8 @@ protected: cached_field_type= item->field_type(); cached_result_type= item->result_type(); unsigned_flag= item->unsigned_flag; + fixed= item->fixed; + collation.set(item->collation); } public: @@ -3647,6 +3939,7 @@ public: return arg->walk(processor, walk_subquery, args) || (this->*processor)(args); } + bool check_partition_func_processor(uchar *int_arg) {return TRUE;} bool check_vcol_func_processor(uchar *arg) { return trace_unsupported_by_check_vcol_func_processor("values"); @@ -3654,18 +3947,6 @@ public: }; -/* - We need this two enums here instead of sql_lex.h because - at least one of them is used by Item_trigger_field interface. - - Time when trigger is invoked (i.e. before or after row actually - inserted/updated/deleted). -*/ -enum trg_action_time_type -{ - TRG_ACTION_BEFORE= 0, TRG_ACTION_AFTER= 1, TRG_ACTION_MAX -}; - class Table_triggers_list; /* @@ -3757,7 +4038,7 @@ private: /** @todo Implement the is_null() method for this class. Currently calling is_null() - on any Item_cache object resolves to Item::is_null(), which reutns FALSE + on any Item_cache object resolves to Item::is_null(), which returns FALSE for any value. */ @@ -3783,7 +4064,8 @@ protected: bool value_cached; public: Item_cache(): - example(0), used_table_map(0), cached_field(0), cached_field_type(MYSQL_TYPE_STRING), + example(0), used_table_map(0), cached_field(0), + cached_field_type(MYSQL_TYPE_STRING), value_cached(0) { fixed= 1; @@ -3791,7 +4073,8 @@ public: null_value= 1; } Item_cache(enum_field_types field_type_arg): - example(0), used_table_map(0), cached_field(0), cached_field_type(field_type_arg), + example(0), used_table_map(0), cached_field(0), + cached_field_type(field_type_arg), value_cached(0) { fixed= 1; @@ -3832,20 +4115,24 @@ public: { return trace_unsupported_by_check_vcol_func_processor("cache"); } - - /** - If this item caches a field value, return pointer to underlying field. - - @return Pointer to field, or NULL if this is not a cache for a field value. - */ - Field* field() { return cached_field; } + /** + Check if saved item has a non-NULL value. + Will cache value of saved item if not already done. + @return TRUE if cached value is non-NULL. + */ + bool has_value() + { + return (value_cached || cache_value()) && !null_value; + } virtual void store(Item *item); virtual bool cache_value()= 0; + bool basic_const_item() const + { return test(example && example->basic_const_item());} + virtual void clear() { null_value= TRUE; value_cached= FALSE; } bool is_null() { return null_value; } virtual bool is_expensive() { - DBUG_ASSERT(example); if (value_cached) return false; return example->is_expensive(); @@ -3858,6 +4145,12 @@ public: return example->is_expensive_processor(arg); } virtual void set_null(); + bool walk(Item_processor processor, bool walk_subquery, uchar *arg) + { + if (example && example->walk(processor, walk_subquery, arg)) + return TRUE; + return (this->*processor)(arg); + } }; @@ -3884,21 +4177,16 @@ public: class Item_cache_temporal: public Item_cache_int { public: - Item_cache_temporal(enum_field_types field_type_arg): - Item_cache_int(field_type_arg) - { - if (mysql_type_to_time_type(cached_field_type) == MYSQL_TIMESTAMP_ERROR) - cached_field_type= MYSQL_TYPE_DATETIME; - } - + Item_cache_temporal(enum_field_types field_type_arg); String* val_str(String *str); my_decimal *val_decimal(my_decimal *); longlong val_int(); longlong val_temporal_packed(); double val_real(); bool cache_value(); - bool get_date(MYSQL_TIME *ltime, uint fuzzydate); + 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 @@ -3913,6 +4201,7 @@ public: } }; + class Item_cache_real: public Item_cache { double value; @@ -3953,12 +4242,13 @@ class Item_cache_str: public Item_cache public: Item_cache_str(const Item *item) : - Item_cache(), value(0), + Item_cache(item->field_type()), value(0), is_varbinary(item->type() == FIELD_ITEM && - ((const Item_field *) item)->field->type() == - MYSQL_TYPE_VARCHAR && + cached_field_type == MYSQL_TYPE_VARCHAR && !((const Item_field *) item)->field->has_charset()) - {} + { + collation.set(const_cast<DTCollation&>(item->collation)); + } double val_real(); longlong val_int(); String* val_str(String *); @@ -4088,3 +4378,91 @@ extern Cached_item *new_Cached_item(THD *thd, Item *item, extern Item_result item_cmp_type(Item_result a,Item_result b); extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item); extern int stored_field_cmp_to_item(THD *thd, Field *field, Item *item); + +extern const String my_null_string; + +/** + Interface for Item iterator +*/ + +class Item_iterator +{ +public: + /** + Shall set this iterator to the position before the first item + + @note + This method also may perform some other initialization actions like + allocation of certain resources. + */ + virtual void open()= 0; + /** + Shall return the next Item (or NULL if there is no next item) and + move pointer to position after it. + */ + virtual Item *next()= 0; + /** + Shall force iterator to free resources (if it holds them) + + @note + One should not use the iterator without open() call after close() + */ + virtual void close()= 0; + + virtual ~Item_iterator() {} +}; + + +/** + Item iterator over List_iterator_fast for Item references +*/ + +class Item_iterator_ref_list: public Item_iterator +{ + List_iterator<Item*> list; +public: + Item_iterator_ref_list(List_iterator<Item*> &arg_list): + list(arg_list) {} + void open() { list.rewind(); } + Item *next() { return *(list++); } + void close() {} +}; + + +/** + Item iterator over List_iterator_fast for Items +*/ + +class Item_iterator_list: public Item_iterator +{ + List_iterator<Item> list; +public: + Item_iterator_list(List_iterator<Item> &arg_list): + list(arg_list) {} + void open() { list.rewind(); } + Item *next() { return (list++); } + void close() {} +}; + + +/** + Item iterator over Item interface for rows +*/ + +class Item_iterator_row: public Item_iterator +{ + Item *base_item; + uint current; +public: + Item_iterator_row(Item *base) : base_item(base), current(0) {} + void open() { current= 0; } + Item *next() + { + if (current >= base_item->cols()) + return NULL; + return base_item->element_index(current++); + } + void close() {} +}; + +#endif /* SQL_ITEM_INCLUDED */ |