diff options
Diffstat (limited to 'sql/item.h')
-rw-r--r-- | sql/item.h | 454 |
1 files changed, 414 insertions, 40 deletions
diff --git a/sql/item.h b/sql/item.h index 8e8199ecac8..4c5475fb080 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1,5 +1,5 @@ -#ifndef ITEM_INCLUDED -#define ITEM_INCLUDED +#ifndef SQL_ITEM_INCLUDED +#define SQL_ITEM_INCLUDED /* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved. @@ -28,6 +28,23 @@ #include "thr_malloc.h" /* sql_calloc */ #include "field.h" /* Derivation */ +static inline +bool trace_unsupported_func(const char *where, const char *processor_name) +{ + char buff[64]; + sprintf(buff, "%s::%s", where, processor_name); + DBUG_ENTER(buff); + sprintf(buff, "%s returns TRUE: unsupported function", processor_name); + DBUG_PRINT("info", ("%s", buff)); + DBUG_RETURN(TRUE); +} + +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 */ @@ -522,12 +539,15 @@ public: SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER, PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM, XPATH_NODESET, XPATH_NODESET_CMP, - VIEW_FIXER_ITEM}; + VIEW_FIXER_ITEM, EXPR_CACHE_ITEM}; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; enum traverse_order { POSTFIX, PREFIX }; + /* Cache of the result of is_expensive(). */ + int8 is_expensive_cache; + /* Reuse size, only used by SP local variable assignment, otherwize 0 */ uint rsize; @@ -551,17 +571,17 @@ public: uint name_length; /* Length of name */ int8 marker; uint8 decimals; - my_bool maybe_null; /* If item may be null */ - my_bool null_value; /* if item is null */ - my_bool unsigned_flag; - my_bool with_sum_func; - my_bool fixed; /* If item fixed with fix_fields */ - my_bool is_autogenerated_name; /* indicate was name of this Item + bool maybe_null; /* If item may be null */ + bool null_value; /* if item is null */ + bool unsigned_flag; + bool with_sum_func; + bool fixed; /* If item fixed with fix_fields */ + bool is_autogenerated_name; /* indicate was name of this Item autogenerated or set by user */ - DTCollation collation; - my_bool with_subselect; /* If this item is a subselect or some + bool with_subselect; /* If this item is a subselect or some of its arguments is or contains a subselect */ + DTCollation collation; Item_result cmp_context; /* Comparison context */ // alloc & destruct is done as start of select using sql_alloc Item(); @@ -588,6 +608,12 @@ public: Field *make_string_field(TABLE *table); virtual bool fix_fields(THD *, Item **); /* + Fix after some tables has been pulled out. Basically re-calculate all + attributes that are dependent on the tables. + */ + virtual void fix_after_pullout(st_select_lex *new_parent, Item **ref) {}; + + /* should be used in case where we are sure that we do not need complete fix_fields() procedure. */ @@ -814,6 +840,17 @@ public: */ virtual bool val_bool(); virtual String *val_nodeset(String*) { return 0; } + + /* + save_val() is method of val_* family which stores value in the given + field. + */ + virtual void save_val(Field *to) { save_org_in_field(to); } + /* + save_result() is method of val*result() family which stores value in + the given field. + */ + virtual void save_result(Field *to) { save_val(to); } /* Helper functions, see item_sum.cc */ String *val_string_from_real(String *str); String *val_string_from_int(String *str); @@ -849,7 +886,11 @@ public: virtual bool val_bool_result() { return val_bool(); } virtual bool is_null_result() { return is_null(); } - /* bit map of tables used by item */ + /* + Bitmap of tables used by item + (note: if you need to check dependencies on individual columns, check out + class Field_enumerator) + */ virtual table_map used_tables() const { return (table_map) 0L; } /* Return table map of tables that can't be NULL tables (tables that are @@ -952,6 +993,7 @@ public: set value of aggregate function in case of no rows for grouping were found */ virtual void no_rows_in_result() {} + virtual void restore_to_before_no_rows_in_result() {} virtual Item *copy_or_same(THD *thd) { return this; } virtual Item *copy_andor_structure(THD *thd) { return this; } virtual Item *real_item() { return this; } @@ -1020,15 +1062,37 @@ public: virtual bool remove_fixed(uchar * arg) { fixed= 0; return 0; } virtual bool cleanup_processor(uchar *arg); virtual bool collect_item_field_processor(uchar * arg) { return 0; } + virtual bool add_field_to_set_processor(uchar * arg) { return 0; } virtual bool find_item_in_field_list_processor(uchar *arg) { return 0; } virtual bool change_context_processor(uchar *context) { return 0; } virtual bool reset_query_id_processor(uchar *query_id_arg) { return 0; } virtual bool is_expensive_processor(uchar *arg) { return 0; } - virtual bool find_item_processor(uchar *arg) { return this == (void *) arg; } virtual bool register_field_in_read_map(uchar *arg) { return 0; } - virtual bool cache_const_expr_analyzer(uchar **arg); virtual Item* cache_const_expr_transformer(uchar *arg); + virtual bool enumerate_field_refs_processor(uchar *arg) { return 0; } + virtual bool mark_as_eliminated_processor(uchar *arg) { return 0; } + + /* To call bool function for all arguments */ + struct bool_func_call_args + { + Item *original_func_item; + void (Item::*bool_function)(); + }; + bool call_bool_func_processor(uchar *org_item) + { + bool_func_call_args *info= (bool_func_call_args*) org_item; + /* Avoid recursion, as walk also calls for original item */ + if (info->original_func_item != this) + (this->*(info->bool_function))(); + return FALSE; + } + /* + The next function differs from the previous one that a bitmap to be updated + is passed as uchar *arg. + */ + virtual bool register_field_in_bitmap(uchar *arg) { return 0; } + /* Check if a partition function is allowed SYNOPSIS @@ -1081,11 +1145,43 @@ public: fields. */ virtual bool check_partition_func_processor(uchar *bool_arg) { return TRUE;} + /* + @brief + Processor used to mark virtual columns used in partitioning expression + + @param + arg always ignored + + @retval + FALSE always + */ + virtual bool vcol_in_partition_func_processor(uchar *arg) + { + return FALSE; + } + virtual bool subst_argument_checker(uchar **arg) - { + { if (*arg) - *arg= NULL; - return TRUE; + *arg= NULL; + return TRUE; + } + /* + @brief + Processor used to check acceptability of an item in the defining + expression for a virtual column + + @param + arg always ignored + + @retval + FALSE the item is accepted in the definition of a virtual column + @retval + TRUE otherwise + */ + virtual bool check_vcol_func_processor(uchar *arg) + { + return trace_unsupported_by_check_vcol_func_processor(full_name()); } virtual Item *equal_fields_propagator(uchar * arg) { return this; } @@ -1118,6 +1214,8 @@ public: return FALSE; } + virtual bool check_inner_refs_processor(uchar *arg) { return FALSE; } + /* For SP local variable returns pointer to Item representing its current value and pointer to current Item otherwise. @@ -1146,6 +1244,8 @@ public: virtual Item *neg_transformer(THD *thd) { return NULL; } virtual Item *update_value_transformer(uchar *select_arg) { return this; } + virtual Item *expr_cache_insert_transformer(uchar *thd_arg) { return this; } + virtual bool expr_cache_is_needed(THD *) { return FALSE; } virtual Item *safe_charset_converter(CHARSET_INFO *tocs); void delete_self() { @@ -1205,6 +1305,28 @@ public: return is_datetime() || cmp_context == STRING_RESULT; return FALSE; } + /* + 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: + 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. + */ + virtual bool is_expensive() + { + if (is_expensive_cache < 0) + is_expensive_cache= walk(&Item::is_expensive_processor, 0, (uchar*)0); + return test(is_expensive_cache); + } virtual Field::geometry_type get_geometry_type() const { return Field::GEOM_GEOMETRY; }; String *check_well_formed_result(String *str, bool send_error= 0); @@ -1242,11 +1364,36 @@ public: 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; } + Item* set_expr_cache(THD *thd, List<Item*> &depends_on); + virtual Item *get_cached_item() { return NULL; } }; +/* + 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 + subquery. + Suggested usage: -class sp_head; + class My_enumerator : public Field_enumerator + { + virtual void visit_field() { ... your actions ...} + } + + My_enumerator enumerator; + item->walk(Item::enumerate_field_refs_processor, ...,(uchar*)&enumerator); + + This is similar to Visitor pattern. +*/ + +class Field_enumerator +{ +public: + virtual void visit_field(Item_field *field)= 0; + virtual ~Field_enumerator() {}; /* purecov: inspected */ + Field_enumerator() {} /* Remove gcc warning */ +}; +class sp_head; class Item_basic_constant :public Item { @@ -1541,6 +1688,10 @@ public: { return value_item->send(protocol, str); } + bool check_vcol_func_processor(uchar *arg) + { + return trace_unsupported_by_check_vcol_func_processor("name_const"); + } }; bool agg_item_collations(DTCollation &c, const char *name, @@ -1578,6 +1729,7 @@ public: virtual Item_num *neg()= 0; 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;} }; #define NO_CACHED_FIELD_INDEX ((uint)(-1)) @@ -1615,6 +1767,19 @@ public: */ TABLE_LIST *cached_table; st_select_lex *depended_from; + /* + Some Items resolved in another select should not be marked as dependency + of the subquery where they are. During normal name resolution, we check + this. Stored procedures and prepared statements first try to resolve an + ident item using a cached table reference and field position from the + previous query execution (cached_table/cached_field_index). If the + tables were not changed, the ident matches the table/field, and we have + faster resolution of the ident without looking through all tables and + fields in the query. But in this case, we can not check all conditions + about this ident item dependency, so we should cache the condition in + this variable. + */ + bool can_be_depended; Item_ident(Name_resolution_context *context_arg, const char *db_name_arg, const char *table_name_arg, const char *field_name_arg); @@ -1697,6 +1862,7 @@ public: longlong val_int(); my_decimal *val_decimal(my_decimal *); String *val_str(String*); + void save_result(Field *to); double val_result(); longlong val_int_result(); String *str_result(String* tmp); @@ -1706,6 +1872,7 @@ public: bool send(Protocol *protocol, String *str_arg); void reset_field(Field *f); bool fix_fields(THD *, Item **); + void fix_after_pullout(st_select_lex *new_parent, Item **ref); void make_field(Send_field *tmp_field); int save_in_field(Field *field,bool no_conversions); void save_org_in_field(Field *field); @@ -1736,9 +1903,14 @@ public: void update_null_value(); Item *get_tmp_table_item(THD *thd); bool collect_item_field_processor(uchar * arg); + bool add_field_to_set_processor(uchar * arg); bool find_item_in_field_list_processor(uchar *arg); bool register_field_in_read_map(uchar *arg); + bool register_field_in_bitmap(uchar *arg); bool check_partition_func_processor(uchar *int_arg) {return FALSE;} + bool vcol_in_partition_func_processor(uchar *bool_arg); + bool check_vcol_func_processor(uchar *arg) { return FALSE;} + bool enumerate_field_refs_processor(uchar *arg); void cleanup(); bool result_as_longlong() { @@ -1805,6 +1977,7 @@ public: 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;} }; class Item_null_result :public Item_null @@ -1818,7 +1991,11 @@ public: save_in_field(result_field, no_conversions); } 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(full_name()); + } +}; /* Item represents one placeholder ('?') of prepared statement */ @@ -2015,6 +2192,7 @@ public: { return (uint)(max_length - test(value < 0)); } bool eq(const Item *, bool binary_cmp) const; bool check_partition_func_processor(uchar *bool_arg) { return FALSE;} + bool check_vcol_func_processor(uchar *arg) { return FALSE;} }; @@ -2032,7 +2210,6 @@ public: virtual void print(String *str, enum_query_type query_type); Item_num *neg (); uint decimal_precision() const { return max_length; } - bool check_partition_func_processor(uchar *bool_arg) { return FALSE;} }; @@ -2074,6 +2251,7 @@ public: bool eq(const Item *, bool binary_cmp) const; void set_decimal_value(my_decimal *value_par); bool check_partition_func_processor(uchar *bool_arg) { return FALSE;} + bool check_vcol_func_processor(uchar *arg) { return FALSE;} }; @@ -2231,6 +2409,7 @@ public: } virtual void print(String *str, enum_query_type query_type); bool check_partition_func_processor(uchar *int_arg) {return FALSE;} + bool check_vcol_func_processor(uchar *arg) { return FALSE;} /** Return TRUE if character-set-introducer was explicitly specified in the @@ -2284,7 +2463,7 @@ double_from_string_with_check (CHARSET_INFO *cs, const char *cptr, char *end); 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) @@ -2298,6 +2477,10 @@ public: } 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(func_name); + } }; @@ -2305,10 +2488,14 @@ public: class Item_partition_func_safe_string: public Item_string { public: - Item_partition_func_safe_string(const char *name, uint length, + Item_partition_func_safe_string(const char *name_arg, uint length, CHARSET_INFO *cs= NULL): - Item_string(name, length, cs) + Item_string(name_arg, length, cs) {} + bool check_vcol_func_processor(uchar *arg) + { + return trace_unsupported_by_check_vcol_func_processor("safe_string"); + } }; @@ -2327,8 +2514,8 @@ public: class Item_blob :public Item_partition_func_safe_string { public: - Item_blob(const char *name, uint length) : - Item_partition_func_safe_string(name, length, &my_charset_bin) + Item_blob(const char *name_arg, uint length) : + Item_partition_func_safe_string(name_arg, length, &my_charset_bin) { max_length= length; } enum Type type() const { return TYPE_HOLDER; } enum_field_types field_type() const { return MYSQL_TYPE_BLOB; } @@ -2356,8 +2543,8 @@ class Item_return_int :public Item_int enum_field_types int_field_type; public: Item_return_int(const char *name_arg, uint length, - enum_field_types field_type_arg, longlong value= 0) - :Item_int(name_arg, value, length), int_field_type(field_type_arg) + enum_field_types field_type_arg, longlong value_arg= 0) + :Item_int(name_arg, value_arg, length), int_field_type(field_type_arg) { unsigned_flag=1; } @@ -2388,6 +2575,7 @@ public: 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); }; @@ -2420,6 +2608,7 @@ public: save_in_field(result_field, no_conversions); } void cleanup(); + bool check_vcol_func_processor(uchar *arg) { return FALSE;} /* This method is used for debug purposes to print the name of an item to the debug log. The second use of this method is as @@ -2482,6 +2671,8 @@ public: Item *it= ((Item *) item)->real_item(); return ref && (*ref)->eq(it, binary_cmp); } + void save_val(Field *to); + void save_result(Field *to); double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal *); @@ -2498,6 +2689,7 @@ public: bool send(Protocol *prot, String *tmp); void make_field(Send_field *field); bool fix_fields(THD *, Item **); + void fix_after_pullout(st_select_lex *new_parent, Item **ref); int save_in_field(Field *field, bool no_conversions); void save_org_in_field(Field *field); enum Item_result result_type () const { return (*ref)->result_type(); } @@ -2514,6 +2706,10 @@ public: if (!depended_from) (*ref)->update_used_tables(); } + bool const_item() const + { + return (*ref)->const_item(); + } table_map not_null_tables() const { return (*ref)->not_null_tables(); } void set_result_field(Field *field) { result_field= field; } bool is_result_field() { return 1; } @@ -2526,9 +2722,22 @@ public: return ref ? (*ref)->real_item() : this; } bool walk(Item_processor processor, bool walk_subquery, uchar *arg) + { + if (ref && *ref) + return (*ref)->walk(processor, walk_subquery, arg) || + (this->*processor)(arg); + else + return FALSE; + } + bool enumerate_field_refs_processor(uchar *arg) + { return (*ref)->enumerate_field_refs_processor(arg); } + void no_rows_in_result() + { + (*ref)->no_rows_in_result(); + } + void restore_to_before_no_rows_in_result() { - return (*ref)->walk(processor, walk_subquery, arg) || - (this->*processor)(arg); + (*ref)->restore_to_before_no_rows_in_result(); } virtual void print(String *str, enum_query_type query_type); bool result_as_longlong() @@ -2567,6 +2776,10 @@ public: if (ref && result_type() == ROW_RESULT) (*ref)->bring_value(); } + bool check_vcol_func_processor(uchar *arg) + { + return trace_unsupported_by_check_vcol_func_processor("ref"); + } bool get_time(MYSQL_TIME *ltime) { DBUG_ASSERT(fixed); @@ -2579,7 +2792,6 @@ public: DBUG_ASSERT(ref); return (*ref)->is_outer_field(); } - }; @@ -2606,6 +2818,7 @@ public: alias_name_used_arg) {} + void save_val(Field *to); double val_real(); longlong val_int(); String *val_str(String* tmp); @@ -2616,6 +2829,131 @@ public: virtual Ref_Type ref_type() { return DIRECT_REF; } }; +class Expression_cache; +class Item_cache; + + +/** + The objects of this class can store its values in an expression cache. +*/ + +class Item_cache_wrapper :public Item_result_field +{ +private: + /* Pointer on the cached expression */ + Item *orig_item; + Expression_cache *expr_cache; + /* + In order to put the expression into the expression cache and return + value of val_*() method, we will need to get the expression value twice + (probably in different types). In order to avoid making two + (potentially costly) orig_item->val_*() calls, we store expression value + in this Item_cache object. + */ + Item_cache *expr_value; + + Item *check_cache(); + inline void cache(); + +public: + Item_cache_wrapper(Item *item_arg); + ~Item_cache_wrapper(); + + const char *func_name() const { return "<expr_cache>"; } + enum Type type() const { return EXPR_CACHE_ITEM; } + virtual Item *get_cached_item() { return orig_item; } + + bool set_cache(THD *thd, List<Item*> &depends_on); + + bool fix_fields(THD *thd, Item **it); + void fix_length_and_dec() {} + void cleanup(); + + /* Methods of getting value which should be cached in the cache */ + void save_val(Field *to); + double val_real(); + longlong val_int(); + String *val_str(String* tmp); + my_decimal *val_decimal(my_decimal *); + bool val_bool(); + bool is_null(); + bool get_date(MYSQL_TIME *ltime, uint fuzzydate); + bool get_time(MYSQL_TIME *ltime); + bool send(Protocol *protocol, String *buffer) + { + if (result_field) + return protocol->store(result_field); + return Item::send(protocol, buffer); + } + void save_org_in_field(Field *field) + { + save_val(field); + } + void save_in_result_field(bool no_conversions) + { + save_val(result_field); + } + Item* get_tmp_table_item(THD *thd_arg); + + /* Following methods make this item transparent as much as possible */ + + 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(Send_field *field) { orig_item->make_field(field); } + bool eq(const Item *item, bool binary_cmp) const + { + Item *it= ((Item *) item)->real_item(); + return orig_item->eq(it, binary_cmp); + } + void fix_after_pullout(st_select_lex *new_parent, Item **refptr) + { + orig_item->fix_after_pullout(new_parent, &orig_item); + } + 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(); } + table_map used_tables() const { return orig_item->used_tables(); } + void update_used_tables() { orig_item->update_used_tables(); } + bool const_item() const { return orig_item->const_item(); } + table_map not_null_tables() const { return orig_item->not_null_tables(); } + bool walk(Item_processor processor, bool walk_subquery, uchar *arg) + { + return orig_item->walk(processor, walk_subquery, arg) || + (this->*processor)(arg); + } + bool enumerate_field_refs_processor(uchar *arg) + { return orig_item->enumerate_field_refs_processor(arg); } + bool result_as_longlong() { return orig_item->result_as_longlong(); } + Item_field *filed_for_view_update() + { return orig_item->filed_for_view_update(); } + + /* Row emulation: forwarding of ROW-related calls to orig_item */ + uint cols() + { 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; } + Item** addr(uint i) + { return result_type() == ROW_RESULT ? orig_item->addr(i) : 0; } + bool check_cols(uint c) + { + return (result_type() == ROW_RESULT ? + orig_item->check_cols(c) : + Item::check_cols(c)); + } + bool null_inside() + { return result_type() == ROW_RESULT ? orig_item->null_inside() : 0; } + void bring_value() + { + if (result_type() == ROW_RESULT) + orig_item->bring_value(); + } + bool check_vcol_func_processor(uchar *arg) + { + return trace_unsupported_by_check_vcol_func_processor("cache"); + } +}; + + /* Class for view fields, the same as Item_direct_ref, but call fix_fields of reference if it is not called yet @@ -2669,12 +3007,13 @@ public: of the outer select. */ bool found_in_select_list; + bool found_in_group_by; Item_outer_ref(Name_resolution_context *context_arg, Item_field *outer_field_arg) :Item_direct_ref(context_arg, 0, outer_field_arg->table_name, outer_field_arg->field_name), outer_ref(outer_field_arg), in_sum_func(0), - found_in_select_list(0) + found_in_select_list(0), found_in_group_by(0) { ref= &outer_ref; set_properties(); @@ -2685,18 +3024,21 @@ public: bool alias_name_used_arg) :Item_direct_ref(context_arg, item, table_name_arg, field_name_arg, alias_name_used_arg), - outer_ref(0), in_sum_func(0), found_in_select_list(1) + outer_ref(0), in_sum_func(0), found_in_select_list(1), found_in_group_by(0) {} void save_in_result_field(bool no_conversions) { outer_ref->save_org_in_field(result_field); } bool fix_fields(THD *, Item **); + void fix_after_pullout(st_select_lex *new_parent, Item **ref); table_map used_tables() const { 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); }; @@ -2722,6 +3064,7 @@ public: const char *table_name_arg, const char *field_name_arg) :Item_ref(context_arg, item, table_name_arg, field_name_arg), owner(master) {} + void save_val(Field *to); double val_real(); longlong val_int(); String* val_str(String* s); @@ -2753,7 +3096,7 @@ class Item_int_with_ref :public Item_int { Item *ref; public: - Item_int_with_ref(longlong i, Item *ref_arg, my_bool unsigned_arg) : + Item_int_with_ref(longlong i, Item *ref_arg, bool unsigned_arg) : Item_int(i), ref(ref_arg) { unsigned_flag= unsigned_arg; @@ -2868,6 +3211,10 @@ public: table_map used_tables() const { return (table_map) 1L; } bool const_item() const { return 0; } bool is_null() { return null_value; } + bool check_vcol_func_processor(uchar *arg) + { + return trace_unsupported_by_check_vcol_func_processor("copy"); + } /* Override the methods below as pure virtual to make sure all the @@ -2983,10 +3330,21 @@ public: }; +/* + Cached_item_XXX objects are not exactly caches. They do the following: + + Each Cached_item_XXX object has + - its source item + - saved value of the source item + - cmp() method that compares the saved value with the current value of the + source item, and if they were not equal saves item's value into the saved + value. +*/ + class Cached_item :public Sql_alloc { public: - my_bool null_value; + bool null_value; Cached_item() :null_value(0) {} virtual bool cmp(void)=0; virtual ~Cached_item(); /*line -e1509 */ @@ -3039,9 +3397,10 @@ class Cached_item_field :public Cached_item uint length; public: - Cached_item_field(Item_field *item) + Cached_item_field(Field *arg_field) : field(arg_field) { - field= item->field; + field= arg_field; + /* TODO: take the memory allocation below out of the constructor. */ buff= (uchar*) sql_calloc(length=field->pack_length()); } bool cmp(void); @@ -3111,6 +3470,10 @@ public: return arg->walk(processor, walk_subquery, args) || (this->*processor)(args); } + bool check_vcol_func_processor(uchar *arg) + { + return trace_unsupported_by_check_vcol_func_processor("values"); + } }; @@ -3195,6 +3558,10 @@ private: BEFORE INSERT of BEFORE UPDATE trigger. */ bool read_only; + virtual bool check_vcol_func_processor(uchar *arg) + { + return trace_unsupported_by_check_vcol_func_processor("trigger"); + } }; @@ -3225,7 +3592,8 @@ public: cached_field_type(MYSQL_TYPE_STRING), value_cached(0) { - fixed= 1; + fixed= 1; + maybe_null= 1; null_value= 1; } Item_cache(enum_field_types field_type_arg): @@ -3234,6 +3602,7 @@ public: value_cached(0) { fixed= 1; + maybe_null= 1; null_value= 1; } @@ -3266,6 +3635,10 @@ public: { return this == item; } + bool check_vcol_func_processor(uchar *arg) + { + return trace_unsupported_by_check_vcol_func_processor("cache"); + } /** Check if saved item has a non-NULL value. Will cache value of saved item if not already done. @@ -3300,7 +3673,7 @@ public: Item_cache(field_type_arg), value(0) {} virtual void store(Item *item){ Item_cache::store(item); } - void store(Item *item, longlong val_arg); + void store_longlong(Item *item, longlong val_arg); double val_real(); longlong val_int(); String* val_str(String *str); @@ -3515,11 +3888,12 @@ void mark_select_range_as_dependent(THD *thd, Field *found_field, Item *found_item, Item_ident *resolved_item); -extern Cached_item *new_Cached_item(THD *thd, Item *item); +extern Cached_item *new_Cached_item(THD *thd, Item *item, + bool pass_through_ref); 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; -#endif /* ITEM_INCLUDED */ +#endif /* SQL_ITEM_INCLUDED */ |