diff options
author | Aleksey Midenkov <midenok@gmail.com> | 2017-12-11 15:43:41 +0300 |
---|---|---|
committer | Aleksey Midenkov <midenok@gmail.com> | 2017-12-11 15:43:41 +0300 |
commit | 79dd77e6aebc861b82e4895941224bbbad441650 (patch) | |
tree | 8c22b54de7964a89358415b5380c2bc734f162a1 /sql/item.h | |
parent | b7cd18289639b30fafc7f623c1187e442608727c (diff) | |
parent | 8f581e8bf1d400be08995b1cf8c11e3b0f7ae283 (diff) | |
download | mariadb-git-79dd77e6aebc861b82e4895941224bbbad441650.tar.gz |
System Versioning 1.0 pre3
Merge branch '10.3' into trunk
Diffstat (limited to 'sql/item.h')
-rw-r--r-- | sql/item.h | 256 |
1 files changed, 209 insertions, 47 deletions
diff --git a/sql/item.h b/sql/item.h index b81af3db4de..d178d9f97d6 100644 --- a/sql/item.h +++ b/sql/item.h @@ -411,6 +411,8 @@ public: virtual const Send_field *get_out_param_info() const { return NULL; } + + virtual Item_param *get_item_param() { return 0; } }; @@ -720,9 +722,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); /* @@ -1898,9 +1897,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); @@ -1978,6 +1978,21 @@ inline Item* get_item_copy (THD *thd, T* item) } +/* + 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; @@ -2200,7 +2215,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 @@ -2209,13 +2225,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) {} /* @@ -3097,12 +3113,27 @@ 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 { /* @@ -3148,9 +3179,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; @@ -3163,7 +3193,6 @@ class Item_param :public Item_basic_value, void fix_temporal(uint32 max_length_arg, uint decimals_arg); -public: struct CONVERSION_INFO { /* @@ -3205,31 +3234,71 @@ 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; - /* - 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; - const Type_handler *type_handler() const { return Type_handler_hybrid_field_type::type_handler(); } @@ -3248,10 +3317,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); @@ -3262,20 +3343,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); @@ -3301,7 +3426,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 @@ -3342,6 +3468,8 @@ private: public: virtual const Send_field *get_out_param_info() const; + Item_param *get_item_param() { return this; } + virtual void make_field(THD *thd, Send_field *field); private: @@ -3562,7 +3690,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; } @@ -4279,7 +4407,8 @@ 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 { protected: bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems, @@ -4362,6 +4491,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)) @@ -4391,6 +4521,35 @@ public: Item* build_clone(THD *thd); }; +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); + 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 { @@ -4576,9 +4735,9 @@ public: /** 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) { return get_item_copy<Item_ref>(thd, this); } @@ -4701,7 +4860,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 */ @@ -4728,6 +4888,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); @@ -5773,6 +5934,7 @@ public: } virtual void store(Item *item); + virtual Item *get_item() { return example; } virtual bool cache_value()= 0; bool basic_const_item() const { return MY_TEST(example && example->basic_const_item()); } |